diff options
Diffstat (limited to 'drivers')
558 files changed, 25859 insertions, 17063 deletions
diff --git a/drivers/accel/ivpu/Makefile b/drivers/accel/ivpu/Makefile index 95ff7ad16338..ebd682a42eb1 100644 --- a/drivers/accel/ivpu/Makefile +++ b/drivers/accel/ivpu/Makefile @@ -1,19 +1,22 @@ # SPDX-License-Identifier: GPL-2.0-only -# Copyright (C) 2023 Intel Corporation +# Copyright (C) 2023-2024 Intel Corporation intel_vpu-y := \ ivpu_drv.o \ ivpu_fw.o \ ivpu_fw_log.o \ ivpu_gem.o \ - ivpu_hw_37xx.o \ - ivpu_hw_40xx.o \ + ivpu_hw.o \ + ivpu_hw_btrs.o \ + ivpu_hw_ip.o \ ivpu_ipc.o \ ivpu_job.o \ ivpu_jsm_msg.o \ ivpu_mmu.o \ ivpu_mmu_context.o \ - ivpu_pm.o + ivpu_ms.o \ + ivpu_pm.o \ + ivpu_sysfs.o intel_vpu-$(CONFIG_DEBUG_FS) += ivpu_debugfs.o diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c index e07e447d08d1..6f86f8df30db 100644 --- a/drivers/accel/ivpu/ivpu_debugfs.c +++ b/drivers/accel/ivpu/ivpu_debugfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include <linux/debugfs.h> @@ -145,6 +145,30 @@ static const struct file_operations dvfs_mode_fops = { .write = dvfs_mode_fops_write, }; +static ssize_t +fw_dyndbg_fops_write(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) +{ + struct ivpu_device *vdev = file->private_data; + char buffer[VPU_DYNDBG_CMD_MAX_LEN] = {}; + int ret; + + if (size >= VPU_DYNDBG_CMD_MAX_LEN) + return -EINVAL; + + ret = strncpy_from_user(buffer, user_buf, size); + if (ret < 0) + return ret; + + ivpu_jsm_dyndbg_control(vdev, buffer, size); + return size; +} + +static const struct file_operations fw_dyndbg_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = fw_dyndbg_fops_write, +}; + static int fw_log_show(struct seq_file *s, void *v) { struct ivpu_device *vdev = s->private; @@ -335,6 +359,61 @@ static const struct file_operations ivpu_reset_engine_fops = { .write = ivpu_reset_engine_fn, }; +static ssize_t +ivpu_resume_engine_fn(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) +{ + struct ivpu_device *vdev = file->private_data; + + if (!size) + return -EINVAL; + + if (ivpu_jsm_hws_resume_engine(vdev, DRM_IVPU_ENGINE_COMPUTE)) + return -ENODEV; + if (ivpu_jsm_hws_resume_engine(vdev, DRM_IVPU_ENGINE_COPY)) + return -ENODEV; + + return size; +} + +static const struct file_operations ivpu_resume_engine_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = ivpu_resume_engine_fn, +}; + +static int dct_active_get(void *data, u64 *active_percent) +{ + struct ivpu_device *vdev = data; + + *active_percent = vdev->pm->dct_active_percent; + + return 0; +} + +static int dct_active_set(void *data, u64 active_percent) +{ + struct ivpu_device *vdev = data; + int ret; + + if (active_percent > 100) + return -EINVAL; + + ret = ivpu_rpm_get(vdev); + if (ret) + return ret; + + if (active_percent) + ret = ivpu_pm_dct_enable(vdev, active_percent); + else + ret = ivpu_pm_dct_disable(vdev); + + ivpu_rpm_put(vdev); + + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(ivpu_dct_fops, dct_active_get, dct_active_set, "%llu\n"); + void ivpu_debugfs_init(struct ivpu_device *vdev) { struct dentry *debugfs_root = vdev->drm.debugfs_root; @@ -347,6 +426,8 @@ void ivpu_debugfs_init(struct ivpu_device *vdev) debugfs_create_file("dvfs_mode", 0200, debugfs_root, vdev, &dvfs_mode_fops); + debugfs_create_file("fw_dyndbg", 0200, debugfs_root, vdev, + &fw_dyndbg_fops); debugfs_create_file("fw_log", 0644, debugfs_root, vdev, &fw_log_fops); debugfs_create_file("fw_trace_destination_mask", 0200, debugfs_root, vdev, @@ -358,8 +439,12 @@ void ivpu_debugfs_init(struct ivpu_device *vdev) debugfs_create_file("reset_engine", 0200, debugfs_root, vdev, &ivpu_reset_engine_fops); + debugfs_create_file("resume_engine", 0200, debugfs_root, vdev, + &ivpu_resume_engine_fops); - if (ivpu_hw_gen(vdev) >= IVPU_HW_40XX) + if (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_40XX) { debugfs_create_file("fw_profiling_freq_drive", 0200, debugfs_root, vdev, &fw_profiling_freq_fops); + debugfs_create_file("dct", 0644, debugfs_root, vdev, &ivpu_dct_fops); + } } diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 51d3f1a55d02..c91400ecf926 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -26,7 +26,9 @@ #include "ivpu_jsm_msg.h" #include "ivpu_mmu.h" #include "ivpu_mmu_context.h" +#include "ivpu_ms.h" #include "ivpu_pm.h" +#include "ivpu_sysfs.h" #ifndef DRIVER_VERSION_STR #define DRIVER_VERSION_STR __stringify(DRM_IVPU_DRIVER_MAJOR) "." \ @@ -51,10 +53,18 @@ u8 ivpu_pll_max_ratio = U8_MAX; module_param_named(pll_max_ratio, ivpu_pll_max_ratio, byte, 0644); MODULE_PARM_DESC(pll_max_ratio, "Maximum PLL ratio used to set NPU frequency"); +int ivpu_sched_mode; +module_param_named(sched_mode, ivpu_sched_mode, int, 0444); +MODULE_PARM_DESC(sched_mode, "Scheduler mode: 0 - Default scheduler, 1 - Force HW scheduler"); + bool ivpu_disable_mmu_cont_pages; -module_param_named(disable_mmu_cont_pages, ivpu_disable_mmu_cont_pages, bool, 0644); +module_param_named(disable_mmu_cont_pages, ivpu_disable_mmu_cont_pages, bool, 0444); MODULE_PARM_DESC(disable_mmu_cont_pages, "Disable MMU contiguous pages optimization"); +bool ivpu_force_snoop; +module_param_named(force_snoop, ivpu_force_snoop, bool, 0444); +MODULE_PARM_DESC(force_snoop, "Force snooping for NPU host memory access"); + struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv) { struct ivpu_device *vdev = file_priv->vdev; @@ -74,7 +84,6 @@ static void file_priv_unbind(struct ivpu_device *vdev, struct ivpu_file_priv *fi ivpu_dbg(vdev, FILE, "file_priv unbind: ctx %u\n", file_priv->ctx.id); ivpu_cmdq_release_all_locked(file_priv); - ivpu_jsm_context_release(vdev, file_priv->ctx.id); ivpu_bo_unbind_all_bos_from_context(vdev, &file_priv->ctx); ivpu_mmu_user_context_fini(vdev, &file_priv->ctx); file_priv->bound = false; @@ -97,6 +106,7 @@ static void file_priv_release(struct kref *ref) mutex_unlock(&vdev->context_list_lock); pm_runtime_put_autosuspend(vdev->drm.dev); + mutex_destroy(&file_priv->ms_lock); mutex_destroy(&file_priv->lock); kfree(file_priv); } @@ -119,7 +129,7 @@ static int ivpu_get_capabilities(struct ivpu_device *vdev, struct drm_ivpu_param { switch (args->index) { case DRM_IVPU_CAP_METRIC_STREAMER: - args->value = 0; + args->value = 1; break; case DRM_IVPU_CAP_DMA_MEMORY_RANGE: args->value = 1; @@ -228,10 +238,13 @@ static int ivpu_open(struct drm_device *dev, struct drm_file *file) goto err_dev_exit; } + INIT_LIST_HEAD(&file_priv->ms_instance_list); + file_priv->vdev = vdev; file_priv->bound = true; kref_init(&file_priv->ref); mutex_init(&file_priv->lock); + mutex_init(&file_priv->ms_lock); mutex_lock(&vdev->context_list_lock); @@ -260,6 +273,7 @@ err_xa_erase: xa_erase_irq(&vdev->context_xa, ctx_id); err_unlock: mutex_unlock(&vdev->context_list_lock); + mutex_destroy(&file_priv->ms_lock); mutex_destroy(&file_priv->lock); kfree(file_priv); err_dev_exit: @@ -275,6 +289,7 @@ static void ivpu_postclose(struct drm_device *dev, struct drm_file *file) ivpu_dbg(vdev, FILE, "file_priv close: ctx %u process %s pid %d\n", file_priv->ctx.id, current->comm, task_pid_nr(current)); + ivpu_ms_cleanup(file_priv); ivpu_file_priv_put(&file_priv); } @@ -285,6 +300,10 @@ static const struct drm_ioctl_desc ivpu_drm_ioctls[] = { DRM_IOCTL_DEF_DRV(IVPU_BO_INFO, ivpu_bo_info_ioctl, 0), DRM_IOCTL_DEF_DRV(IVPU_SUBMIT, ivpu_submit_ioctl, 0), DRM_IOCTL_DEF_DRV(IVPU_BO_WAIT, ivpu_bo_wait_ioctl, 0), + DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_START, ivpu_ms_start_ioctl, 0), + DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_GET_DATA, ivpu_ms_get_data_ioctl, 0), + DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_STOP, ivpu_ms_stop_ioctl, 0), + DRM_IOCTL_DEF_DRV(IVPU_METRIC_STREAMER_GET_INFO, ivpu_ms_get_info_ioctl, 0), }; static int ivpu_wait_for_ready(struct ivpu_device *vdev) @@ -301,7 +320,7 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev) timeout = jiffies + msecs_to_jiffies(vdev->timeout.boot); while (1) { - ivpu_ipc_irq_handler(vdev, NULL); + ivpu_ipc_irq_handler(vdev); ret = ivpu_ipc_receive(vdev, &cons, &ipc_hdr, NULL, 0); if (ret != -ETIMEDOUT || time_after_eq(jiffies, timeout)) break; @@ -323,6 +342,21 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev) return ret; } +static int ivpu_hw_sched_init(struct ivpu_device *vdev) +{ + int ret = 0; + + if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) { + ret = ivpu_jsm_hws_setup_priority_bands(vdev); + if (ret) { + ivpu_err(vdev, "Failed to enable hw scheduler: %d", ret); + return ret; + } + } + + return ret; +} + /** * ivpu_boot() - Start VPU firmware * @vdev: VPU device @@ -356,6 +390,15 @@ int ivpu_boot(struct ivpu_device *vdev) enable_irq(vdev->irq); ivpu_hw_irq_enable(vdev); ivpu_ipc_enable(vdev); + + if (ivpu_fw_is_cold_boot(vdev)) { + ret = ivpu_pm_dct_init(vdev); + if (ret) + return ret; + + return ivpu_hw_sched_init(vdev); + } + return 0; } @@ -408,11 +451,52 @@ static const struct drm_driver driver = { .minor = DRM_IVPU_DRIVER_MINOR, }; +static void ivpu_context_abort_invalid(struct ivpu_device *vdev) +{ + struct ivpu_file_priv *file_priv; + unsigned long ctx_id; + + mutex_lock(&vdev->context_list_lock); + + xa_for_each(&vdev->context_xa, ctx_id, file_priv) { + if (!file_priv->has_mmu_faults || file_priv->aborted) + continue; + + mutex_lock(&file_priv->lock); + ivpu_context_abort_locked(file_priv); + file_priv->aborted = true; + mutex_unlock(&file_priv->lock); + } + + mutex_unlock(&vdev->context_list_lock); +} + static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg) { struct ivpu_device *vdev = arg; + u8 irq_src; + + if (kfifo_is_empty(&vdev->hw->irq.fifo)) + return IRQ_NONE; - return ivpu_ipc_irq_thread_handler(vdev); + while (kfifo_get(&vdev->hw->irq.fifo, &irq_src)) { + switch (irq_src) { + case IVPU_HW_IRQ_SRC_IPC: + ivpu_ipc_irq_thread_handler(vdev); + break; + case IVPU_HW_IRQ_SRC_MMU_EVTQ: + ivpu_context_abort_invalid(vdev); + break; + case IVPU_HW_IRQ_SRC_DCT: + ivpu_pm_dct_irq_thread_handler(vdev); + break; + default: + ivpu_err_ratelimited(vdev, "Unknown IRQ source: %u\n", irq_src); + break; + } + } + + return IRQ_HANDLED; } static int ivpu_irq_init(struct ivpu_device *vdev) @@ -426,9 +510,11 @@ static int ivpu_irq_init(struct ivpu_device *vdev) return ret; } + ivpu_irq_handlers_init(vdev); + vdev->irq = pci_irq_vector(pdev, 0); - ret = devm_request_threaded_irq(vdev->drm.dev, vdev->irq, vdev->hw->ops->irq_handler, + ret = devm_request_threaded_irq(vdev->drm.dev, vdev->irq, ivpu_hw_irq_handler, ivpu_irq_thread_handler, IRQF_NO_AUTOEN, DRIVER_NAME, vdev); if (ret) ivpu_err(vdev, "Failed to request an IRQ %d\n", ret); @@ -505,13 +591,10 @@ static int ivpu_dev_init(struct ivpu_device *vdev) if (!vdev->pm) return -ENOMEM; - if (ivpu_hw_gen(vdev) >= IVPU_HW_40XX) { - vdev->hw->ops = &ivpu_hw_40xx_ops; + if (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_40XX) vdev->hw->dma_bits = 48; - } else { - vdev->hw->ops = &ivpu_hw_37xx_ops; + else vdev->hw->dma_bits = 38; - } vdev->platform = IVPU_PLATFORM_INVALID; vdev->context_xa_limit.min = IVPU_USER_CONTEXT_MIN_SSID; @@ -540,7 +623,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev) goto err_xa_destroy; /* Init basic HW info based on buttress registers which are accessible before power up */ - ret = ivpu_hw_info_init(vdev); + ret = ivpu_hw_init(vdev); if (ret) goto err_xa_destroy; @@ -612,13 +695,14 @@ static void ivpu_bo_unbind_all_user_contexts(struct ivpu_device *vdev) static void ivpu_dev_fini(struct ivpu_device *vdev) { + ivpu_jobs_abort_all(vdev); + ivpu_pm_cancel_recovery(vdev); ivpu_pm_disable(vdev); ivpu_prepare_for_reset(vdev); ivpu_shutdown(vdev); - ivpu_jobs_abort_all(vdev); + ivpu_ms_cleanup_all(vdev); ivpu_job_done_consumer_fini(vdev); - ivpu_pm_cancel_recovery(vdev); ivpu_bo_unbind_all_user_contexts(vdev); ivpu_ipc_fini(vdev); @@ -658,6 +742,7 @@ static int ivpu_probe(struct pci_dev *pdev, const struct pci_device_id *id) return ret; ivpu_debugfs_init(vdev); + ivpu_sysfs_init(vdev); ret = drm_dev_register(&vdev->drm, 0); if (ret) { diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index bb4374d0eaec..63f13b697eed 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -27,8 +27,15 @@ #define PCI_DEVICE_ID_ARL 0xad1d #define PCI_DEVICE_ID_LNL 0x643e -#define IVPU_HW_37XX 37 -#define IVPU_HW_40XX 40 +#define IVPU_HW_IP_37XX 37 +#define IVPU_HW_IP_40XX 40 +#define IVPU_HW_IP_50XX 50 +#define IVPU_HW_IP_60XX 60 + +#define IVPU_HW_IP_REV_LNL_B0 4 + +#define IVPU_HW_BTRS_MTL 1 +#define IVPU_HW_BTRS_LNL 2 #define IVPU_GLOBAL_CONTEXT_MMU_SSID 0 /* SSID 1 is used by the VPU to represent reserved context */ @@ -39,7 +46,11 @@ #define IVPU_MIN_DB 1 #define IVPU_MAX_DB 255 -#define IVPU_NUM_ENGINES 2 +#define IVPU_NUM_ENGINES 2 +#define IVPU_NUM_PRIORITIES 4 +#define IVPU_NUM_CMDQS_PER_CTX (IVPU_NUM_ENGINES * IVPU_NUM_PRIORITIES) + +#define IVPU_CMDQ_INDEX(engine, priority) ((engine) * IVPU_NUM_PRIORITIES + (priority)) #define IVPU_PLATFORM_SILICON 0 #define IVPU_PLATFORM_SIMICS 2 @@ -93,6 +104,7 @@ struct ivpu_wa_table { bool interrupt_clear_with_0; bool disable_clock_relinquish; bool disable_d0i3_msg; + bool wp0_during_power_up; }; struct ivpu_hw_info; @@ -131,11 +143,13 @@ struct ivpu_device { atomic64_t unique_id_counter; + ktime_t busy_start_ts; + ktime_t busy_time; + struct { int boot; int jsm; int tdr; - int reschedule_suspend; int autosuspend; int d0i3_entry_msg; } timeout; @@ -149,22 +163,31 @@ struct ivpu_file_priv { struct kref ref; struct ivpu_device *vdev; struct mutex lock; /* Protects cmdq */ - struct ivpu_cmdq *cmdq[IVPU_NUM_ENGINES]; + struct ivpu_cmdq *cmdq[IVPU_NUM_CMDQS_PER_CTX]; struct ivpu_mmu_context ctx; + struct mutex ms_lock; /* Protects ms_instance_list, ms_info_bo */ + struct list_head ms_instance_list; + struct ivpu_bo *ms_info_bo; bool has_mmu_faults; bool bound; + bool aborted; }; extern int ivpu_dbg_mask; extern u8 ivpu_pll_min_ratio; extern u8 ivpu_pll_max_ratio; +extern int ivpu_sched_mode; extern bool ivpu_disable_mmu_cont_pages; +extern bool ivpu_force_snoop; #define IVPU_TEST_MODE_FW_TEST BIT(0) #define IVPU_TEST_MODE_NULL_HW BIT(1) #define IVPU_TEST_MODE_NULL_SUBMISSION BIT(2) #define IVPU_TEST_MODE_D0I3_MSG_DISABLE BIT(4) #define IVPU_TEST_MODE_D0I3_MSG_ENABLE BIT(5) +#define IVPU_TEST_MODE_PREEMPTION_DISABLE BIT(6) +#define IVPU_TEST_MODE_HWS_EXTRA_EVENTS BIT(7) +#define IVPU_TEST_MODE_DISABLE_TIMEOUTS BIT(8) extern int ivpu_test_mode; struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv); @@ -184,16 +207,32 @@ static inline u16 ivpu_device_id(struct ivpu_device *vdev) return to_pci_dev(vdev->drm.dev)->device; } -static inline int ivpu_hw_gen(struct ivpu_device *vdev) +static inline int ivpu_hw_ip_gen(struct ivpu_device *vdev) { switch (ivpu_device_id(vdev)) { case PCI_DEVICE_ID_MTL: case PCI_DEVICE_ID_ARL: - return IVPU_HW_37XX; + return IVPU_HW_IP_37XX; case PCI_DEVICE_ID_LNL: - return IVPU_HW_40XX; + return IVPU_HW_IP_40XX; default: - ivpu_err(vdev, "Unknown NPU device\n"); + dump_stack(); + ivpu_err(vdev, "Unknown NPU IP generation\n"); + return 0; + } +} + +static inline int ivpu_hw_btrs_gen(struct ivpu_device *vdev) +{ + switch (ivpu_device_id(vdev)) { + case PCI_DEVICE_ID_MTL: + case PCI_DEVICE_ID_ARL: + return IVPU_HW_BTRS_MTL; + case PCI_DEVICE_ID_LNL: + return IVPU_HW_BTRS_LNL; + default: + dump_stack(); + ivpu_err(vdev, "Unknown buttress generation\n"); return 0; } } @@ -231,4 +270,9 @@ static inline bool ivpu_is_fpga(struct ivpu_device *vdev) return ivpu_get_platform(vdev) == IVPU_PLATFORM_FPGA; } +static inline bool ivpu_is_force_snoop_enabled(struct ivpu_device *vdev) +{ + return ivpu_force_snoop; +} + #endif /* __IVPU_DRV_H__ */ diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 1457300828bf..de3d66116375 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include <linux/firmware.h> @@ -44,6 +44,8 @@ #define IVPU_FW_CHECK_API_VER_LT(vdev, fw_hdr, name, major, minor) \ ivpu_fw_check_api_ver_lt(vdev, fw_hdr, #name, VPU_##name##_API_VER_INDEX, major, minor) +#define IVPU_FOCUS_PRESENT_TIMER_MS 1000 + static char *ivpu_firmware; module_param_named_unsafe(firmware, ivpu_firmware, charp, 0644); MODULE_PARM_DESC(firmware, "NPU firmware binary in /lib/firmware/.."); @@ -52,10 +54,10 @@ static struct { int gen; const char *name; } fw_names[] = { - { IVPU_HW_37XX, "vpu_37xx.bin" }, - { IVPU_HW_37XX, "intel/vpu/vpu_37xx_v0.0.bin" }, - { IVPU_HW_40XX, "vpu_40xx.bin" }, - { IVPU_HW_40XX, "intel/vpu/vpu_40xx_v0.0.bin" }, + { IVPU_HW_IP_37XX, "vpu_37xx.bin" }, + { IVPU_HW_IP_37XX, "intel/vpu/vpu_37xx_v0.0.bin" }, + { IVPU_HW_IP_40XX, "vpu_40xx.bin" }, + { IVPU_HW_IP_40XX, "intel/vpu/vpu_40xx_v0.0.bin" }, }; static int ivpu_fw_request(struct ivpu_device *vdev) @@ -71,7 +73,7 @@ static int ivpu_fw_request(struct ivpu_device *vdev) } for (i = 0; i < ARRAY_SIZE(fw_names); i++) { - if (fw_names[i].gen != ivpu_hw_gen(vdev)) + if (fw_names[i].gen != ivpu_hw_ip_gen(vdev)) continue; ret = firmware_request_nowarn(&vdev->fw->file, fw_names[i].name, vdev->drm.dev); @@ -121,6 +123,14 @@ ivpu_fw_check_api_ver_lt(struct ivpu_device *vdev, const struct vpu_firmware_hea return false; } +static bool is_within_range(u64 addr, size_t size, u64 range_start, size_t range_size) +{ + if (addr < range_start || addr + size > range_start + range_size) + return false; + + return true; +} + static int ivpu_fw_parse(struct ivpu_device *vdev) { struct ivpu_fw_info *fw = vdev->fw; @@ -200,10 +210,27 @@ static int ivpu_fw_parse(struct ivpu_device *vdev) fw->dvfs_mode = 0; + fw->primary_preempt_buf_size = fw_hdr->preemption_buffer_1_size; + fw->secondary_preempt_buf_size = fw_hdr->preemption_buffer_2_size; + + if (fw_hdr->ro_section_start_address && !is_within_range(fw_hdr->ro_section_start_address, + fw_hdr->ro_section_size, + fw_hdr->image_load_address, + fw_hdr->image_size)) { + ivpu_err(vdev, "Invalid read-only section: start address 0x%llx, size %u\n", + fw_hdr->ro_section_start_address, fw_hdr->ro_section_size); + return -EINVAL; + } + + fw->read_only_addr = fw_hdr->ro_section_start_address; + fw->read_only_size = fw_hdr->ro_section_size; + ivpu_dbg(vdev, FW_BOOT, "Size: file %lu image %u runtime %u shavenn %u\n", fw->file->size, fw->image_size, fw->runtime_size, fw->shave_nn_size); ivpu_dbg(vdev, FW_BOOT, "Address: runtime 0x%llx, load 0x%llx, entry point 0x%llx\n", fw->runtime_addr, image_load_addr, fw->entry_point); + ivpu_dbg(vdev, FW_BOOT, "Read-only section: address 0x%llx, size %u\n", + fw->read_only_addr, fw->read_only_size); return 0; } @@ -241,7 +268,7 @@ static int ivpu_fw_update_global_range(struct ivpu_device *vdev) return -EINVAL; } - ivpu_hw_init_range(&vdev->hw->ranges.global, start, size); + ivpu_hw_range_init(&vdev->hw->ranges.global, start, size); return 0; } @@ -265,6 +292,13 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) return -ENOMEM; } + ret = ivpu_mmu_context_set_pages_ro(vdev, &vdev->gctx, fw->read_only_addr, + fw->read_only_size); + if (ret) { + ivpu_err(vdev, "Failed to set firmware image read-only\n"); + goto err_free_fw_mem; + } + fw->mem_log_crit = ivpu_bo_create_global(vdev, IVPU_FW_CRITICAL_BUFFER_SIZE, DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE); if (!fw->mem_log_crit) { @@ -464,6 +498,8 @@ static void ivpu_fw_boot_params_print(struct ivpu_device *vdev, struct vpu_boot_ boot_params->punit_telemetry_sram_size); ivpu_dbg(vdev, FW_BOOT, "boot_params.vpu_telemetry_enable = 0x%x\n", boot_params->vpu_telemetry_enable); + ivpu_dbg(vdev, FW_BOOT, "boot_params.vpu_scheduling_mode = 0x%x\n", + boot_params->vpu_scheduling_mode); ivpu_dbg(vdev, FW_BOOT, "boot_params.dvfs_mode = %u\n", boot_params->dvfs_mode); ivpu_dbg(vdev, FW_BOOT, "boot_params.d0i3_delayed_entry = %d\n", @@ -504,7 +540,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params boot_params->magic = VPU_BOOT_PARAMS_MAGIC; boot_params->vpu_id = to_pci_dev(vdev->drm.dev)->bus->number; - boot_params->frequency = ivpu_hw_reg_pll_freq_get(vdev); + boot_params->frequency = ivpu_hw_pll_freq_get(vdev); /* * This param is a debug firmware feature. It switches default clock @@ -561,9 +597,12 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params boot_params->verbose_tracing_buff_addr = vdev->fw->mem_log_verb->vpu_addr; boot_params->verbose_tracing_buff_size = ivpu_bo_size(vdev->fw->mem_log_verb); - boot_params->punit_telemetry_sram_base = ivpu_hw_reg_telemetry_offset_get(vdev); - boot_params->punit_telemetry_sram_size = ivpu_hw_reg_telemetry_size_get(vdev); - boot_params->vpu_telemetry_enable = ivpu_hw_reg_telemetry_enable_get(vdev); + boot_params->punit_telemetry_sram_base = ivpu_hw_telemetry_offset_get(vdev); + boot_params->punit_telemetry_sram_size = ivpu_hw_telemetry_size_get(vdev); + boot_params->vpu_telemetry_enable = ivpu_hw_telemetry_enable_get(vdev); + boot_params->vpu_scheduling_mode = vdev->hw->sched_mode; + if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) + boot_params->vpu_focus_present_timer_ms = IVPU_FOCUS_PRESENT_TIMER_MS; boot_params->dvfs_mode = vdev->fw->dvfs_mode; if (!IVPU_WA(disable_d0i3_msg)) boot_params->d0i3_delayed_entry = 1; diff --git a/drivers/accel/ivpu/ivpu_fw.h b/drivers/accel/ivpu/ivpu_fw.h index 66b60fa161b5..40d9d17be3f5 100644 --- a/drivers/accel/ivpu/ivpu_fw.h +++ b/drivers/accel/ivpu/ivpu_fw.h @@ -28,6 +28,10 @@ struct ivpu_fw_info { u32 trace_destination_mask; u64 trace_hw_component_mask; u32 dvfs_mode; + u32 primary_preempt_buf_size; + u32 secondary_preempt_buf_size; + u64 read_only_addr; + u32 read_only_size; }; int ivpu_fw_init(struct ivpu_device *vdev); diff --git a/drivers/accel/ivpu/ivpu_gem.h b/drivers/accel/ivpu/ivpu_gem.h index fb7117c13eec..d975000abd78 100644 --- a/drivers/accel/ivpu/ivpu_gem.h +++ b/drivers/accel/ivpu/ivpu_gem.h @@ -60,14 +60,17 @@ static inline u32 ivpu_bo_cache_mode(struct ivpu_bo *bo) return bo->flags & DRM_IVPU_BO_CACHE_MASK; } -static inline bool ivpu_bo_is_snooped(struct ivpu_bo *bo) +static inline struct ivpu_device *ivpu_bo_to_vdev(struct ivpu_bo *bo) { - return ivpu_bo_cache_mode(bo) == DRM_IVPU_BO_CACHED; + return to_ivpu_device(bo->base.base.dev); } -static inline struct ivpu_device *ivpu_bo_to_vdev(struct ivpu_bo *bo) +static inline bool ivpu_bo_is_snooped(struct ivpu_bo *bo) { - return to_ivpu_device(bo->base.base.dev); + if (ivpu_is_force_snoop_enabled(ivpu_bo_to_vdev(bo))) + return true; + + return ivpu_bo_cache_mode(bo) == DRM_IVPU_BO_CACHED; } static inline void *ivpu_to_cpu_addr(struct ivpu_bo *bo, u32 vpu_addr) diff --git a/drivers/accel/ivpu/ivpu_hw.c b/drivers/accel/ivpu/ivpu_hw.c new file mode 100644 index 000000000000..27f0fe4d54e0 --- /dev/null +++ b/drivers/accel/ivpu/ivpu_hw.c @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020 - 2024 Intel Corporation + */ + +#include "ivpu_drv.h" +#include "ivpu_hw.h" +#include "ivpu_hw_btrs.h" +#include "ivpu_hw_ip.h" + +#include <linux/dmi.h> + +static char *platform_to_str(u32 platform) +{ + switch (platform) { + case IVPU_PLATFORM_SILICON: + return "SILICON"; + case IVPU_PLATFORM_SIMICS: + return "SIMICS"; + case IVPU_PLATFORM_FPGA: + return "FPGA"; + default: + return "Invalid platform"; + } +} + +static const struct dmi_system_id dmi_platform_simulation[] = { + { + .ident = "Intel Simics", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "lnlrvp"), + DMI_MATCH(DMI_BOARD_VERSION, "1.0"), + DMI_MATCH(DMI_BOARD_SERIAL, "123456789"), + }, + }, + { + .ident = "Intel Simics", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "Simics"), + }, + }, + { } +}; + +static void platform_init(struct ivpu_device *vdev) +{ + if (dmi_check_system(dmi_platform_simulation)) + vdev->platform = IVPU_PLATFORM_SIMICS; + else + vdev->platform = IVPU_PLATFORM_SILICON; + + ivpu_dbg(vdev, MISC, "Platform type: %s (%d)\n", + platform_to_str(vdev->platform), vdev->platform); +} + +static void wa_init(struct ivpu_device *vdev) +{ + vdev->wa.punit_disabled = ivpu_is_fpga(vdev); + vdev->wa.clear_runtime_mem = false; + + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + vdev->wa.interrupt_clear_with_0 = ivpu_hw_btrs_irqs_clear_with_0_mtl(vdev); + + if (ivpu_device_id(vdev) == PCI_DEVICE_ID_LNL && + ivpu_revision(vdev) < IVPU_HW_IP_REV_LNL_B0) + vdev->wa.disable_clock_relinquish = true; + + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + vdev->wa.wp0_during_power_up = true; + + IVPU_PRINT_WA(punit_disabled); + IVPU_PRINT_WA(clear_runtime_mem); + IVPU_PRINT_WA(interrupt_clear_with_0); + IVPU_PRINT_WA(disable_clock_relinquish); + IVPU_PRINT_WA(wp0_during_power_up); +} + +static void timeouts_init(struct ivpu_device *vdev) +{ + if (ivpu_test_mode & IVPU_TEST_MODE_DISABLE_TIMEOUTS) { + vdev->timeout.boot = -1; + vdev->timeout.jsm = -1; + vdev->timeout.tdr = -1; + vdev->timeout.autosuspend = -1; + vdev->timeout.d0i3_entry_msg = -1; + } else if (ivpu_is_fpga(vdev)) { + vdev->timeout.boot = 100000; + vdev->timeout.jsm = 50000; + vdev->timeout.tdr = 2000000; + vdev->timeout.autosuspend = -1; + vdev->timeout.d0i3_entry_msg = 500; + } else if (ivpu_is_simics(vdev)) { + vdev->timeout.boot = 50; + vdev->timeout.jsm = 500; + vdev->timeout.tdr = 10000; + vdev->timeout.autosuspend = -1; + vdev->timeout.d0i3_entry_msg = 100; + } else { + vdev->timeout.boot = 1000; + vdev->timeout.jsm = 500; + vdev->timeout.tdr = 2000; + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + vdev->timeout.autosuspend = 10; + else + vdev->timeout.autosuspend = 100; + vdev->timeout.d0i3_entry_msg = 5; + } +} + +static void memory_ranges_init(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) { + ivpu_hw_range_init(&vdev->hw->ranges.global, 0x80000000, SZ_512M); + ivpu_hw_range_init(&vdev->hw->ranges.user, 0xc0000000, 255 * SZ_1M); + ivpu_hw_range_init(&vdev->hw->ranges.shave, 0x180000000, SZ_2G); + ivpu_hw_range_init(&vdev->hw->ranges.dma, 0x200000000, SZ_8G); + } else { + ivpu_hw_range_init(&vdev->hw->ranges.global, 0x80000000, SZ_512M); + ivpu_hw_range_init(&vdev->hw->ranges.user, 0x80000000, SZ_256M); + ivpu_hw_range_init(&vdev->hw->ranges.shave, 0x80000000 + SZ_256M, SZ_2G - SZ_256M); + ivpu_hw_range_init(&vdev->hw->ranges.dma, 0x200000000, SZ_8G); + } +} + +static int wp_enable(struct ivpu_device *vdev) +{ + return ivpu_hw_btrs_wp_drive(vdev, true); +} + +static int wp_disable(struct ivpu_device *vdev) +{ + return ivpu_hw_btrs_wp_drive(vdev, false); +} + +int ivpu_hw_power_up(struct ivpu_device *vdev) +{ + int ret; + + if (IVPU_WA(wp0_during_power_up)) { + /* WP requests may fail when powering down, so issue WP 0 here */ + ret = wp_disable(vdev); + if (ret) + ivpu_warn(vdev, "Failed to disable workpoint: %d\n", ret); + } + + ret = ivpu_hw_btrs_d0i3_disable(vdev); + if (ret) + ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret); + + ret = wp_enable(vdev); + if (ret) { + ivpu_err(vdev, "Failed to enable workpoint: %d\n", ret); + return ret; + } + + if (ivpu_hw_btrs_gen(vdev) >= IVPU_HW_BTRS_LNL) { + if (IVPU_WA(disable_clock_relinquish)) + ivpu_hw_btrs_clock_relinquish_disable_lnl(vdev); + ivpu_hw_btrs_profiling_freq_reg_set_lnl(vdev); + ivpu_hw_btrs_ats_print_lnl(vdev); + } + + ret = ivpu_hw_ip_host_ss_configure(vdev); + if (ret) { + ivpu_err(vdev, "Failed to configure host SS: %d\n", ret); + return ret; + } + + ivpu_hw_ip_idle_gen_disable(vdev); + + ret = ivpu_hw_btrs_wait_for_clock_res_own_ack(vdev); + if (ret) { + ivpu_err(vdev, "Timed out waiting for clock resource own ACK\n"); + return ret; + } + + ret = ivpu_hw_ip_pwr_domain_enable(vdev); + if (ret) { + ivpu_err(vdev, "Failed to enable power domain: %d\n", ret); + return ret; + } + + ret = ivpu_hw_ip_host_ss_axi_enable(vdev); + if (ret) { + ivpu_err(vdev, "Failed to enable AXI: %d\n", ret); + return ret; + } + + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_LNL) + ivpu_hw_btrs_set_port_arbitration_weights_lnl(vdev); + + ret = ivpu_hw_ip_top_noc_enable(vdev); + if (ret) + ivpu_err(vdev, "Failed to enable TOP NOC: %d\n", ret); + + return ret; +} + +static void save_d0i3_entry_timestamp(struct ivpu_device *vdev) +{ + vdev->hw->d0i3_entry_host_ts = ktime_get_boottime(); + vdev->hw->d0i3_entry_vpu_ts = ivpu_hw_ip_read_perf_timer_counter(vdev); +} + +int ivpu_hw_reset(struct ivpu_device *vdev) +{ + int ret = 0; + + if (ivpu_hw_btrs_ip_reset(vdev)) { + ivpu_err(vdev, "Failed to reset NPU IP\n"); + ret = -EIO; + } + + if (wp_disable(vdev)) { + ivpu_err(vdev, "Failed to disable workpoint\n"); + ret = -EIO; + } + + return ret; +} + +int ivpu_hw_power_down(struct ivpu_device *vdev) +{ + int ret = 0; + + save_d0i3_entry_timestamp(vdev); + + if (!ivpu_hw_is_idle(vdev)) + ivpu_warn(vdev, "NPU not idle during power down\n"); + + if (ivpu_hw_reset(vdev)) { + ivpu_err(vdev, "Failed to reset NPU\n"); + ret = -EIO; + } + + if (ivpu_hw_btrs_d0i3_enable(vdev)) { + ivpu_err(vdev, "Failed to enter D0I3\n"); + ret = -EIO; + } + + return ret; +} + +int ivpu_hw_init(struct ivpu_device *vdev) +{ + ivpu_hw_btrs_info_init(vdev); + ivpu_hw_btrs_freq_ratios_init(vdev); + memory_ranges_init(vdev); + platform_init(vdev); + wa_init(vdev); + timeouts_init(vdev); + + return 0; +} + +int ivpu_hw_boot_fw(struct ivpu_device *vdev) +{ + int ret; + + ivpu_hw_ip_snoop_disable(vdev); + ivpu_hw_ip_tbu_mmu_enable(vdev); + ret = ivpu_hw_ip_soc_cpu_boot(vdev); + if (ret) + ivpu_err(vdev, "Failed to boot SOC CPU: %d\n", ret); + + return ret; +} + +void ivpu_hw_profiling_freq_drive(struct ivpu_device *vdev, bool enable) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) { + vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT; + return; + } + + if (enable) + vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_HIGH; + else + vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT; +} + +void ivpu_irq_handlers_init(struct ivpu_device *vdev) +{ + INIT_KFIFO(vdev->hw->irq.fifo); + + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + vdev->hw->irq.ip_irq_handler = ivpu_hw_ip_irq_handler_37xx; + else + vdev->hw->irq.ip_irq_handler = ivpu_hw_ip_irq_handler_40xx; + + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + vdev->hw->irq.btrs_irq_handler = ivpu_hw_btrs_irq_handler_mtl; + else + vdev->hw->irq.btrs_irq_handler = ivpu_hw_btrs_irq_handler_lnl; +} + +void ivpu_hw_irq_enable(struct ivpu_device *vdev) +{ + kfifo_reset(&vdev->hw->irq.fifo); + ivpu_hw_ip_irq_enable(vdev); + ivpu_hw_btrs_irq_enable(vdev); +} + +void ivpu_hw_irq_disable(struct ivpu_device *vdev) +{ + ivpu_hw_btrs_irq_disable(vdev); + ivpu_hw_ip_irq_disable(vdev); +} + +irqreturn_t ivpu_hw_irq_handler(int irq, void *ptr) +{ + struct ivpu_device *vdev = ptr; + bool ip_handled, btrs_handled; + + ivpu_hw_btrs_global_int_disable(vdev); + + btrs_handled = ivpu_hw_btrs_irq_handler(vdev, irq); + if (!ivpu_hw_is_idle((vdev)) || !btrs_handled) + ip_handled = ivpu_hw_ip_irq_handler(vdev, irq); + else + ip_handled = false; + + /* Re-enable global interrupts to re-trigger MSI for pending interrupts */ + ivpu_hw_btrs_global_int_enable(vdev); + + if (!kfifo_is_empty(&vdev->hw->irq.fifo)) + return IRQ_WAKE_THREAD; + if (ip_handled || btrs_handled) + return IRQ_HANDLED; + return IRQ_NONE; +} diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h index 094c659d2800..1c0c98e3afb8 100644 --- a/drivers/accel/ivpu/ivpu_hw.h +++ b/drivers/accel/ivpu/ivpu_hw.h @@ -1,39 +1,22 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #ifndef __IVPU_HW_H__ #define __IVPU_HW_H__ +#include <linux/kfifo.h> + #include "ivpu_drv.h" +#include "ivpu_hw_btrs.h" +#include "ivpu_hw_ip.h" -struct ivpu_hw_ops { - int (*info_init)(struct ivpu_device *vdev); - int (*power_up)(struct ivpu_device *vdev); - int (*boot_fw)(struct ivpu_device *vdev); - int (*power_down)(struct ivpu_device *vdev); - int (*reset)(struct ivpu_device *vdev); - bool (*is_idle)(struct ivpu_device *vdev); - int (*wait_for_idle)(struct ivpu_device *vdev); - void (*wdt_disable)(struct ivpu_device *vdev); - void (*diagnose_failure)(struct ivpu_device *vdev); - u32 (*profiling_freq_get)(struct ivpu_device *vdev); - void (*profiling_freq_drive)(struct ivpu_device *vdev, bool enable); - u32 (*reg_pll_freq_get)(struct ivpu_device *vdev); - u32 (*ratio_to_freq)(struct ivpu_device *vdev, u32 ratio); - u32 (*reg_telemetry_offset_get)(struct ivpu_device *vdev); - u32 (*reg_telemetry_size_get)(struct ivpu_device *vdev); - u32 (*reg_telemetry_enable_get)(struct ivpu_device *vdev); - void (*reg_db_set)(struct ivpu_device *vdev, u32 db_id); - u32 (*reg_ipc_rx_addr_get)(struct ivpu_device *vdev); - u32 (*reg_ipc_rx_count_get)(struct ivpu_device *vdev); - void (*reg_ipc_tx_set)(struct ivpu_device *vdev, u32 vpu_addr); - void (*irq_clear)(struct ivpu_device *vdev); - void (*irq_enable)(struct ivpu_device *vdev); - void (*irq_disable)(struct ivpu_device *vdev); - irqreturn_t (*irq_handler)(int irq, void *ptr); -}; +#define IVPU_HW_IRQ_FIFO_LENGTH 1024 + +#define IVPU_HW_IRQ_SRC_IPC 1 +#define IVPU_HW_IRQ_SRC_MMU_EVTQ 2 +#define IVPU_HW_IRQ_SRC_DCT 3 struct ivpu_addr_range { resource_size_t start; @@ -41,7 +24,11 @@ struct ivpu_addr_range { }; struct ivpu_hw_info { - const struct ivpu_hw_ops *ops; + struct { + bool (*btrs_irq_handler)(struct ivpu_device *vdev, int irq); + bool (*ip_irq_handler)(struct ivpu_device *vdev, int irq); + DECLARE_KFIFO(fifo, u8, IVPU_HW_IRQ_FIFO_LENGTH); + } irq; struct { struct ivpu_addr_range global; struct ivpu_addr_range user; @@ -59,6 +46,7 @@ struct ivpu_hw_info { u32 profiling_freq; } pll; u32 tile_fuse; + u32 sched_mode; u32 sku; u16 config; int dma_bits; @@ -66,140 +54,107 @@ struct ivpu_hw_info { u64 d0i3_entry_vpu_ts; }; -extern const struct ivpu_hw_ops ivpu_hw_37xx_ops; -extern const struct ivpu_hw_ops ivpu_hw_40xx_ops; - -static inline int ivpu_hw_info_init(struct ivpu_device *vdev) -{ - return vdev->hw->ops->info_init(vdev); -}; - -static inline int ivpu_hw_power_up(struct ivpu_device *vdev) -{ - ivpu_dbg(vdev, PM, "HW power up\n"); +int ivpu_hw_init(struct ivpu_device *vdev); +int ivpu_hw_power_up(struct ivpu_device *vdev); +int ivpu_hw_power_down(struct ivpu_device *vdev); +int ivpu_hw_reset(struct ivpu_device *vdev); +int ivpu_hw_boot_fw(struct ivpu_device *vdev); +void ivpu_hw_profiling_freq_drive(struct ivpu_device *vdev, bool enable); +void ivpu_irq_handlers_init(struct ivpu_device *vdev); +void ivpu_hw_irq_enable(struct ivpu_device *vdev); +void ivpu_hw_irq_disable(struct ivpu_device *vdev); +irqreturn_t ivpu_hw_irq_handler(int irq, void *ptr); - return vdev->hw->ops->power_up(vdev); -}; - -static inline int ivpu_hw_boot_fw(struct ivpu_device *vdev) -{ - return vdev->hw->ops->boot_fw(vdev); -}; - -static inline bool ivpu_hw_is_idle(struct ivpu_device *vdev) -{ - return vdev->hw->ops->is_idle(vdev); -}; - -static inline int ivpu_hw_wait_for_idle(struct ivpu_device *vdev) +static inline u32 ivpu_hw_btrs_irq_handler(struct ivpu_device *vdev, int irq) { - return vdev->hw->ops->wait_for_idle(vdev); -}; - -static inline int ivpu_hw_power_down(struct ivpu_device *vdev) -{ - ivpu_dbg(vdev, PM, "HW power down\n"); - - return vdev->hw->ops->power_down(vdev); -}; - -static inline int ivpu_hw_reset(struct ivpu_device *vdev) -{ - ivpu_dbg(vdev, PM, "HW reset\n"); - - return vdev->hw->ops->reset(vdev); -}; - -static inline void ivpu_hw_wdt_disable(struct ivpu_device *vdev) -{ - vdev->hw->ops->wdt_disable(vdev); -}; + return vdev->hw->irq.btrs_irq_handler(vdev, irq); +} -static inline u32 ivpu_hw_profiling_freq_get(struct ivpu_device *vdev) +static inline u32 ivpu_hw_ip_irq_handler(struct ivpu_device *vdev, int irq) { - return vdev->hw->ops->profiling_freq_get(vdev); -}; + return vdev->hw->irq.ip_irq_handler(vdev, irq); +} -static inline void ivpu_hw_profiling_freq_drive(struct ivpu_device *vdev, bool enable) +static inline void ivpu_hw_range_init(struct ivpu_addr_range *range, u64 start, u64 size) { - return vdev->hw->ops->profiling_freq_drive(vdev, enable); -}; + range->start = start; + range->end = start + size; +} -/* Register indirect accesses */ -static inline u32 ivpu_hw_reg_pll_freq_get(struct ivpu_device *vdev) +static inline u64 ivpu_hw_range_size(const struct ivpu_addr_range *range) { - return vdev->hw->ops->reg_pll_freq_get(vdev); -}; + return range->end - range->start; +} static inline u32 ivpu_hw_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) { - return vdev->hw->ops->ratio_to_freq(vdev, ratio); + return ivpu_hw_btrs_ratio_to_freq(vdev, ratio); } -static inline u32 ivpu_hw_reg_telemetry_offset_get(struct ivpu_device *vdev) +static inline void ivpu_hw_irq_clear(struct ivpu_device *vdev) { - return vdev->hw->ops->reg_telemetry_offset_get(vdev); -}; + ivpu_hw_ip_irq_clear(vdev); +} -static inline u32 ivpu_hw_reg_telemetry_size_get(struct ivpu_device *vdev) +static inline u32 ivpu_hw_pll_freq_get(struct ivpu_device *vdev) { - return vdev->hw->ops->reg_telemetry_size_get(vdev); -}; + return ivpu_hw_btrs_pll_freq_get(vdev); +} -static inline u32 ivpu_hw_reg_telemetry_enable_get(struct ivpu_device *vdev) +static inline u32 ivpu_hw_profiling_freq_get(struct ivpu_device *vdev) { - return vdev->hw->ops->reg_telemetry_enable_get(vdev); -}; + return vdev->hw->pll.profiling_freq; +} -static inline void ivpu_hw_reg_db_set(struct ivpu_device *vdev, u32 db_id) +static inline void ivpu_hw_diagnose_failure(struct ivpu_device *vdev) { - vdev->hw->ops->reg_db_set(vdev, db_id); -}; + ivpu_hw_ip_diagnose_failure(vdev); + ivpu_hw_btrs_diagnose_failure(vdev); +} -static inline u32 ivpu_hw_reg_ipc_rx_addr_get(struct ivpu_device *vdev) +static inline u32 ivpu_hw_telemetry_offset_get(struct ivpu_device *vdev) { - return vdev->hw->ops->reg_ipc_rx_addr_get(vdev); -}; + return ivpu_hw_btrs_telemetry_offset_get(vdev); +} -static inline u32 ivpu_hw_reg_ipc_rx_count_get(struct ivpu_device *vdev) +static inline u32 ivpu_hw_telemetry_size_get(struct ivpu_device *vdev) { - return vdev->hw->ops->reg_ipc_rx_count_get(vdev); -}; + return ivpu_hw_btrs_telemetry_size_get(vdev); +} -static inline void ivpu_hw_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr) +static inline u32 ivpu_hw_telemetry_enable_get(struct ivpu_device *vdev) { - vdev->hw->ops->reg_ipc_tx_set(vdev, vpu_addr); -}; + return ivpu_hw_btrs_telemetry_enable_get(vdev); +} -static inline void ivpu_hw_irq_clear(struct ivpu_device *vdev) +static inline bool ivpu_hw_is_idle(struct ivpu_device *vdev) { - vdev->hw->ops->irq_clear(vdev); -}; + return ivpu_hw_btrs_is_idle(vdev); +} -static inline void ivpu_hw_irq_enable(struct ivpu_device *vdev) +static inline int ivpu_hw_wait_for_idle(struct ivpu_device *vdev) { - vdev->hw->ops->irq_enable(vdev); -}; + return ivpu_hw_btrs_wait_for_idle(vdev); +} -static inline void ivpu_hw_irq_disable(struct ivpu_device *vdev) +static inline void ivpu_hw_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr) { - vdev->hw->ops->irq_disable(vdev); -}; + ivpu_hw_ip_ipc_tx_set(vdev, vpu_addr); +} -static inline void ivpu_hw_init_range(struct ivpu_addr_range *range, u64 start, u64 size) +static inline void ivpu_hw_db_set(struct ivpu_device *vdev, u32 db_id) { - range->start = start; - range->end = start + size; + ivpu_hw_ip_db_set(vdev, db_id); } -static inline u64 ivpu_hw_range_size(const struct ivpu_addr_range *range) +static inline u32 ivpu_hw_ipc_rx_addr_get(struct ivpu_device *vdev) { - return range->end - range->start; + return ivpu_hw_ip_ipc_rx_addr_get(vdev); } -static inline void ivpu_hw_diagnose_failure(struct ivpu_device *vdev) +static inline u32 ivpu_hw_ipc_rx_count_get(struct ivpu_device *vdev) { - vdev->hw->ops->diagnose_failure(vdev); + return ivpu_hw_ip_ipc_rx_count_get(vdev); } #endif /* __IVPU_HW_H__ */ diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c deleted file mode 100644 index bd25e2d9fb0f..000000000000 --- a/drivers/accel/ivpu/ivpu_hw_37xx.c +++ /dev/null @@ -1,1065 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020-2024 Intel Corporation - */ - -#include "ivpu_drv.h" -#include "ivpu_fw.h" -#include "ivpu_hw_37xx_reg.h" -#include "ivpu_hw_reg_io.h" -#include "ivpu_hw.h" -#include "ivpu_ipc.h" -#include "ivpu_mmu.h" -#include "ivpu_pm.h" - -#define TILE_FUSE_ENABLE_BOTH 0x0 -#define TILE_SKU_BOTH 0x3630 - -/* Work point configuration values */ -#define CONFIG_1_TILE 0x01 -#define CONFIG_2_TILE 0x02 -#define PLL_RATIO_5_3 0x01 -#define PLL_RATIO_4_3 0x02 -#define WP_CONFIG(tile, ratio) (((tile) << 8) | (ratio)) -#define WP_CONFIG_1_TILE_5_3_RATIO WP_CONFIG(CONFIG_1_TILE, PLL_RATIO_5_3) -#define WP_CONFIG_1_TILE_4_3_RATIO WP_CONFIG(CONFIG_1_TILE, PLL_RATIO_4_3) -#define WP_CONFIG_2_TILE_5_3_RATIO WP_CONFIG(CONFIG_2_TILE, PLL_RATIO_5_3) -#define WP_CONFIG_2_TILE_4_3_RATIO WP_CONFIG(CONFIG_2_TILE, PLL_RATIO_4_3) -#define WP_CONFIG_0_TILE_PLL_OFF WP_CONFIG(0, 0) - -#define PLL_REF_CLK_FREQ (50 * 1000000) -#define PLL_SIMULATION_FREQ (10 * 1000000) -#define PLL_PROF_CLK_FREQ (38400 * 1000) -#define PLL_DEFAULT_EPP_VALUE 0x80 - -#define TIM_SAFE_ENABLE 0xf1d0dead -#define TIM_WATCHDOG_RESET_VALUE 0xffffffff - -#define TIMEOUT_US (150 * USEC_PER_MSEC) -#define PWR_ISLAND_STATUS_TIMEOUT_US (5 * USEC_PER_MSEC) -#define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC) -#define IDLE_TIMEOUT_US (5 * USEC_PER_MSEC) - -#define ICB_0_IRQ_MASK ((REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT)) | \ - (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT)) | \ - (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT)) | \ - (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT)) | \ - (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT)) | \ - (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT)) | \ - (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT))) - -#define ICB_1_IRQ_MASK ((REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_2_INT)) | \ - (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_3_INT)) | \ - (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_4_INT))) - -#define ICB_0_1_IRQ_MASK ((((u64)ICB_1_IRQ_MASK) << 32) | ICB_0_IRQ_MASK) - -#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \ - (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR))) - -#define BUTTRESS_ALL_IRQ_MASK (BUTTRESS_IRQ_MASK | \ - (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE))) - -#define BUTTRESS_IRQ_ENABLE_MASK ((u32)~BUTTRESS_IRQ_MASK) -#define BUTTRESS_IRQ_DISABLE_MASK ((u32)-1) - -#define ITF_FIREWALL_VIOLATION_MASK ((REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_ROM_CMX)) | \ - (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_DBG)) | \ - (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_CTRL)) | \ - (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, DEC400)) | \ - (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_NCE)) | \ - (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \ - (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX))) - -static void ivpu_hw_wa_init(struct ivpu_device *vdev) -{ - vdev->wa.punit_disabled = false; - vdev->wa.clear_runtime_mem = false; - - REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, BUTTRESS_ALL_IRQ_MASK); - if (REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) == BUTTRESS_ALL_IRQ_MASK) { - /* Writing 1s does not clear the interrupt status register */ - vdev->wa.interrupt_clear_with_0 = true; - REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, 0x0); - } - - IVPU_PRINT_WA(punit_disabled); - IVPU_PRINT_WA(clear_runtime_mem); - IVPU_PRINT_WA(interrupt_clear_with_0); -} - -static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) -{ - vdev->timeout.boot = 1000; - vdev->timeout.jsm = 500; - vdev->timeout.tdr = 2000; - vdev->timeout.reschedule_suspend = 10; - vdev->timeout.autosuspend = 10; - vdev->timeout.d0i3_entry_msg = 5; -} - -static int ivpu_pll_wait_for_cmd_send(struct ivpu_device *vdev) -{ - return REGB_POLL_FLD(VPU_37XX_BUTTRESS_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US); -} - -/* Send KMD initiated workpoint change */ -static int ivpu_pll_cmd_send(struct ivpu_device *vdev, u16 min_ratio, u16 max_ratio, - u16 target_ratio, u16 config) -{ - int ret; - u32 val; - - ret = ivpu_pll_wait_for_cmd_send(vdev); - if (ret) { - ivpu_err(vdev, "Failed to sync before WP request: %d\n", ret); - return ret; - } - - val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0); - val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0, MIN_RATIO, min_ratio, val); - val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0, MAX_RATIO, max_ratio, val); - REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0, val); - - val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1); - val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1, TARGET_RATIO, target_ratio, val); - val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1, EPP, PLL_DEFAULT_EPP_VALUE, val); - REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1, val); - - val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2); - val = REG_SET_FLD_NUM(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2, CONFIG, config, val); - REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2, val); - - val = REGB_RD32(VPU_37XX_BUTTRESS_WP_REQ_CMD); - val = REG_SET_FLD(VPU_37XX_BUTTRESS_WP_REQ_CMD, SEND, val); - REGB_WR32(VPU_37XX_BUTTRESS_WP_REQ_CMD, val); - - ret = ivpu_pll_wait_for_cmd_send(vdev); - if (ret) - ivpu_err(vdev, "Failed to sync after WP request: %d\n", ret); - - return ret; -} - -static int ivpu_pll_wait_for_lock(struct ivpu_device *vdev, bool enable) -{ - u32 exp_val = enable ? 0x1 : 0x0; - - if (IVPU_WA(punit_disabled)) - return 0; - - return REGB_POLL_FLD(VPU_37XX_BUTTRESS_PLL_STATUS, LOCK, exp_val, PLL_TIMEOUT_US); -} - -static int ivpu_pll_wait_for_status_ready(struct ivpu_device *vdev) -{ - if (IVPU_WA(punit_disabled)) - return 0; - - return REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, READY, 1, PLL_TIMEOUT_US); -} - -static void ivpu_pll_init_frequency_ratios(struct ivpu_device *vdev) -{ - struct ivpu_hw_info *hw = vdev->hw; - u8 fuse_min_ratio, fuse_max_ratio, fuse_pn_ratio; - u32 fmin_fuse, fmax_fuse; - - fmin_fuse = REGB_RD32(VPU_37XX_BUTTRESS_FMIN_FUSE); - fuse_min_ratio = REG_GET_FLD(VPU_37XX_BUTTRESS_FMIN_FUSE, MIN_RATIO, fmin_fuse); - fuse_pn_ratio = REG_GET_FLD(VPU_37XX_BUTTRESS_FMIN_FUSE, PN_RATIO, fmin_fuse); - - fmax_fuse = REGB_RD32(VPU_37XX_BUTTRESS_FMAX_FUSE); - fuse_max_ratio = REG_GET_FLD(VPU_37XX_BUTTRESS_FMAX_FUSE, MAX_RATIO, fmax_fuse); - - hw->pll.min_ratio = clamp_t(u8, ivpu_pll_min_ratio, fuse_min_ratio, fuse_max_ratio); - hw->pll.max_ratio = clamp_t(u8, ivpu_pll_max_ratio, hw->pll.min_ratio, fuse_max_ratio); - hw->pll.pn_ratio = clamp_t(u8, fuse_pn_ratio, hw->pll.min_ratio, hw->pll.max_ratio); -} - -static int ivpu_hw_37xx_wait_for_vpuip_bar(struct ivpu_device *vdev) -{ - return REGV_POLL_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, AON, 0, 100); -} - -static int ivpu_pll_drive(struct ivpu_device *vdev, bool enable) -{ - struct ivpu_hw_info *hw = vdev->hw; - u16 target_ratio; - u16 config; - int ret; - - if (IVPU_WA(punit_disabled)) { - ivpu_dbg(vdev, PM, "Skipping PLL request\n"); - return 0; - } - - if (enable) { - target_ratio = hw->pll.pn_ratio; - config = hw->config; - } else { - target_ratio = 0; - config = 0; - } - - ivpu_dbg(vdev, PM, "PLL workpoint request: config 0x%04x pll ratio 0x%x\n", - config, target_ratio); - - ret = ivpu_pll_cmd_send(vdev, hw->pll.min_ratio, hw->pll.max_ratio, target_ratio, config); - if (ret) { - ivpu_err(vdev, "Failed to send PLL workpoint request: %d\n", ret); - return ret; - } - - ret = ivpu_pll_wait_for_lock(vdev, enable); - if (ret) { - ivpu_err(vdev, "Timed out waiting for PLL lock\n"); - return ret; - } - - if (enable) { - ret = ivpu_pll_wait_for_status_ready(vdev); - if (ret) { - ivpu_err(vdev, "Timed out waiting for PLL ready status\n"); - return ret; - } - - ret = ivpu_hw_37xx_wait_for_vpuip_bar(vdev); - if (ret) { - ivpu_err(vdev, "Timed out waiting for NPU IP bar\n"); - return ret; - } - } - - return 0; -} - -static int ivpu_pll_enable(struct ivpu_device *vdev) -{ - return ivpu_pll_drive(vdev, true); -} - -static int ivpu_pll_disable(struct ivpu_device *vdev) -{ - return ivpu_pll_drive(vdev, false); -} - -static void ivpu_boot_host_ss_rst_clr_assert(struct ivpu_device *vdev) -{ - u32 val = 0; - - val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, TOP_NOC, val); - val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, DSS_MAS, val); - val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, MSS_MAS, val); - - REGV_WR32(VPU_37XX_HOST_SS_CPR_RST_CLR, val); -} - -static void ivpu_boot_host_ss_rst_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_SS_CPR_RST_SET); - - if (enable) { - val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, TOP_NOC, val); - val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, DSS_MAS, val); - val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, MSS_MAS, val); - } else { - val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, TOP_NOC, val); - val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, DSS_MAS, val); - val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, MSS_MAS, val); - } - - REGV_WR32(VPU_37XX_HOST_SS_CPR_RST_SET, val); -} - -static void ivpu_boot_host_ss_clk_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_SS_CPR_CLK_SET); - - if (enable) { - val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, TOP_NOC, val); - val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, DSS_MAS, val); - val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, MSS_MAS, val); - } else { - val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, TOP_NOC, val); - val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, DSS_MAS, val); - val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, MSS_MAS, val); - } - - REGV_WR32(VPU_37XX_HOST_SS_CPR_CLK_SET, val); -} - -static int ivpu_boot_noc_qreqn_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QREQN); - - if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QACCEPTN); - - if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QACCEPTN, TOP_SOCMMIO, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QDENY); - - if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QDENY, TOP_SOCMMIO, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN); - - if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QACCEPTN); - - if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QDENY); - - if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_host_ss_configure(struct ivpu_device *vdev) -{ - ivpu_boot_host_ss_rst_clr_assert(vdev); - - return ivpu_boot_noc_qreqn_check(vdev, 0x0); -} - -static void ivpu_boot_vpu_idle_gen_disable(struct ivpu_device *vdev) -{ - REGV_WR32(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN, 0x0); -} - -static int ivpu_boot_host_ss_axi_drive(struct ivpu_device *vdev, bool enable) -{ - int ret; - u32 val; - - val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QREQN); - if (enable) - val = REG_SET_FLD(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); - else - val = REG_CLR_FLD(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); - REGV_WR32(VPU_37XX_HOST_SS_NOC_QREQN, val); - - ret = ivpu_boot_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); - if (ret) { - ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); - return ret; - } - - ret = ivpu_boot_noc_qdeny_check(vdev, 0x0); - if (ret) - ivpu_err(vdev, "Failed qdeny check: %d\n", ret); - - return ret; -} - -static int ivpu_boot_host_ss_axi_enable(struct ivpu_device *vdev) -{ - return ivpu_boot_host_ss_axi_drive(vdev, true); -} - -static int ivpu_boot_host_ss_top_noc_drive(struct ivpu_device *vdev, bool enable) -{ - int ret; - u32 val; - - val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN); - if (enable) { - val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val); - val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); - } else { - val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val); - val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); - } - REGV_WR32(VPU_37XX_TOP_NOC_QREQN, val); - - ret = ivpu_boot_top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); - if (ret) { - ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); - return ret; - } - - ret = ivpu_boot_top_noc_qdeny_check(vdev, 0x0); - if (ret) - ivpu_err(vdev, "Failed qdeny check: %d\n", ret); - - return ret; -} - -static int ivpu_boot_host_ss_top_noc_enable(struct ivpu_device *vdev) -{ - return ivpu_boot_host_ss_top_noc_drive(vdev, true); -} - -static void ivpu_boot_pwr_island_trickle_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0); - - if (enable) - val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val); - else - val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val); - - REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, val); -} - -static void ivpu_boot_pwr_island_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0); - - if (enable) - val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val); - else - val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val); - - REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, val); -} - -static int ivpu_boot_wait_for_pwr_island_status(struct ivpu_device *vdev, u32 exp_val) -{ - return REGV_POLL_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_STATUS0, MSS_CPU, - exp_val, PWR_ISLAND_STATUS_TIMEOUT_US); -} - -static void ivpu_boot_pwr_island_isolation_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0); - - if (enable) - val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val); - else - val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val); - - REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, val); -} - -static void ivpu_boot_dpu_active_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_DPU_ACTIVE); - - if (enable) - val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val); - else - val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val); - - REGV_WR32(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, val); -} - -static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev) -{ - int ret; - - ivpu_boot_pwr_island_trickle_drive(vdev, true); - ivpu_boot_pwr_island_drive(vdev, true); - - ret = ivpu_boot_wait_for_pwr_island_status(vdev, 0x1); - if (ret) { - ivpu_err(vdev, "Timed out waiting for power island status\n"); - return ret; - } - - ret = ivpu_boot_top_noc_qrenqn_check(vdev, 0x0); - if (ret) { - ivpu_err(vdev, "Failed qrenqn check %d\n", ret); - return ret; - } - - ivpu_boot_host_ss_clk_drive(vdev, true); - ivpu_boot_pwr_island_isolation_drive(vdev, false); - ivpu_boot_host_ss_rst_drive(vdev, true); - ivpu_boot_dpu_active_drive(vdev, true); - - return ret; -} - -static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES); - - val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, NOSNOOP_OVERRIDE_EN, val); - val = REG_CLR_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val); - val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val); - - REGV_WR32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, val); -} - -static void ivpu_boot_tbu_mmu_enable(struct ivpu_device *vdev) -{ - u32 val = REGV_RD32(VPU_37XX_HOST_IF_TBU_MMUSSIDV); - - val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val); - val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val); - val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val); - val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val); - - REGV_WR32(VPU_37XX_HOST_IF_TBU_MMUSSIDV, val); -} - -static void ivpu_boot_soc_cpu_boot(struct ivpu_device *vdev) -{ - u32 val; - - val = REGV_RD32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC); - val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val); - - val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val); - REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); - - val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); - REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); - - val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); - REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); - - val = vdev->fw->entry_point >> 9; - REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val); - - val = REG_SET_FLD(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, DONE, val); - REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val); - - ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n", - vdev->fw->entry_point == vdev->fw->cold_boot_entry_point ? "cold boot" : "resume"); -} - -static int ivpu_boot_d0i3_drive(struct ivpu_device *vdev, bool enable) -{ - int ret; - u32 val; - - ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); - if (ret) { - ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret); - return ret; - } - - val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL); - if (enable) - val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, I3, val); - else - val = REG_CLR_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, I3, val); - REGB_WR32(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, val); - - ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); - if (ret) - ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret); - - return ret; -} - -static int ivpu_hw_37xx_info_init(struct ivpu_device *vdev) -{ - struct ivpu_hw_info *hw = vdev->hw; - - hw->tile_fuse = TILE_FUSE_ENABLE_BOTH; - hw->sku = TILE_SKU_BOTH; - hw->config = WP_CONFIG_2_TILE_4_3_RATIO; - - ivpu_pll_init_frequency_ratios(vdev); - - ivpu_hw_init_range(&hw->ranges.global, 0x80000000, SZ_512M); - ivpu_hw_init_range(&hw->ranges.user, 0xc0000000, 255 * SZ_1M); - ivpu_hw_init_range(&hw->ranges.shave, 0x180000000, SZ_2G); - ivpu_hw_init_range(&hw->ranges.dma, 0x200000000, SZ_8G); - - vdev->platform = IVPU_PLATFORM_SILICON; - ivpu_hw_wa_init(vdev); - ivpu_hw_timeouts_init(vdev); - - return 0; -} - -static int ivpu_hw_37xx_ip_reset(struct ivpu_device *vdev) -{ - int ret; - u32 val; - - if (IVPU_WA(punit_disabled)) - return 0; - - ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US); - if (ret) { - ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n"); - return ret; - } - - val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_IP_RESET); - val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, val); - REGB_WR32(VPU_37XX_BUTTRESS_VPU_IP_RESET, val); - - ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US); - if (ret) - ivpu_err(vdev, "Timed out waiting for RESET completion\n"); - - return ret; -} - -static int ivpu_hw_37xx_reset(struct ivpu_device *vdev) -{ - int ret = 0; - - if (ivpu_hw_37xx_ip_reset(vdev)) { - ivpu_err(vdev, "Failed to reset NPU\n"); - ret = -EIO; - } - - if (ivpu_pll_disable(vdev)) { - ivpu_err(vdev, "Failed to disable PLL\n"); - ret = -EIO; - } - - return ret; -} - -static int ivpu_hw_37xx_d0i3_enable(struct ivpu_device *vdev) -{ - int ret; - - ret = ivpu_boot_d0i3_drive(vdev, true); - if (ret) - ivpu_err(vdev, "Failed to enable D0i3: %d\n", ret); - - udelay(5); /* VPU requires 5 us to complete the transition */ - - return ret; -} - -static int ivpu_hw_37xx_d0i3_disable(struct ivpu_device *vdev) -{ - int ret; - - ret = ivpu_boot_d0i3_drive(vdev, false); - if (ret) - ivpu_err(vdev, "Failed to disable D0i3: %d\n", ret); - - return ret; -} - -static int ivpu_hw_37xx_power_up(struct ivpu_device *vdev) -{ - int ret; - - /* PLL requests may fail when powering down, so issue WP 0 here */ - ret = ivpu_pll_disable(vdev); - if (ret) - ivpu_warn(vdev, "Failed to disable PLL: %d\n", ret); - - ret = ivpu_hw_37xx_d0i3_disable(vdev); - if (ret) - ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret); - - ret = ivpu_pll_enable(vdev); - if (ret) { - ivpu_err(vdev, "Failed to enable PLL: %d\n", ret); - return ret; - } - - ret = ivpu_boot_host_ss_configure(vdev); - if (ret) { - ivpu_err(vdev, "Failed to configure host SS: %d\n", ret); - return ret; - } - - /* - * The control circuitry for vpu_idle indication logic powers up active. - * To ensure unnecessary low power mode signal from LRT during bring up, - * KMD disables the circuitry prior to bringing up the Main Power island. - */ - ivpu_boot_vpu_idle_gen_disable(vdev); - - ret = ivpu_boot_pwr_domain_enable(vdev); - if (ret) { - ivpu_err(vdev, "Failed to enable power domain: %d\n", ret); - return ret; - } - - ret = ivpu_boot_host_ss_axi_enable(vdev); - if (ret) { - ivpu_err(vdev, "Failed to enable AXI: %d\n", ret); - return ret; - } - - ret = ivpu_boot_host_ss_top_noc_enable(vdev); - if (ret) - ivpu_err(vdev, "Failed to enable TOP NOC: %d\n", ret); - - return ret; -} - -static int ivpu_hw_37xx_boot_fw(struct ivpu_device *vdev) -{ - ivpu_boot_no_snoop_enable(vdev); - ivpu_boot_tbu_mmu_enable(vdev); - ivpu_boot_soc_cpu_boot(vdev); - - return 0; -} - -static bool ivpu_hw_37xx_is_idle(struct ivpu_device *vdev) -{ - u32 val; - - if (IVPU_WA(punit_disabled)) - return true; - - val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_STATUS); - return REG_TEST_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, READY, val) && - REG_TEST_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, IDLE, val); -} - -static int ivpu_hw_37xx_wait_for_idle(struct ivpu_device *vdev) -{ - return REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US); -} - -static void ivpu_hw_37xx_save_d0i3_entry_timestamp(struct ivpu_device *vdev) -{ - vdev->hw->d0i3_entry_host_ts = ktime_get_boottime(); - vdev->hw->d0i3_entry_vpu_ts = REGV_RD64(VPU_37XX_CPU_SS_TIM_PERF_FREE_CNT); -} - -static int ivpu_hw_37xx_power_down(struct ivpu_device *vdev) -{ - int ret = 0; - - ivpu_hw_37xx_save_d0i3_entry_timestamp(vdev); - - if (!ivpu_hw_37xx_is_idle(vdev)) - ivpu_warn(vdev, "NPU not idle during power down\n"); - - if (ivpu_hw_37xx_reset(vdev)) { - ivpu_err(vdev, "Failed to reset NPU\n"); - ret = -EIO; - } - - if (ivpu_hw_37xx_d0i3_enable(vdev)) { - ivpu_err(vdev, "Failed to enter D0I3\n"); - ret = -EIO; - } - - return ret; -} - -static void ivpu_hw_37xx_wdt_disable(struct ivpu_device *vdev) -{ - u32 val; - - /* Enable writing and set non-zero WDT value */ - REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); - REGV_WR32(VPU_37XX_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE); - - /* Enable writing and disable watchdog timer */ - REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); - REGV_WR32(VPU_37XX_CPU_SS_TIM_WDOG_EN, 0); - - /* Now clear the timeout interrupt */ - val = REGV_RD32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG); - val = REG_CLR_FLD(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val); - REGV_WR32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, val); -} - -static u32 ivpu_hw_37xx_profiling_freq_get(struct ivpu_device *vdev) -{ - return PLL_PROF_CLK_FREQ; -} - -static void ivpu_hw_37xx_profiling_freq_drive(struct ivpu_device *vdev, bool enable) -{ - /* Profiling freq - is a debug feature. Unavailable on VPU 37XX. */ -} - -static u32 ivpu_hw_37xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) -{ - u32 pll_clock = PLL_REF_CLK_FREQ * ratio; - u32 cpu_clock; - - if ((vdev->hw->config & 0xff) == PLL_RATIO_4_3) - cpu_clock = pll_clock * 2 / 4; - else - cpu_clock = pll_clock * 2 / 5; - - return cpu_clock; -} - -/* Register indirect accesses */ -static u32 ivpu_hw_37xx_reg_pll_freq_get(struct ivpu_device *vdev) -{ - u32 pll_curr_ratio; - - pll_curr_ratio = REGB_RD32(VPU_37XX_BUTTRESS_CURRENT_PLL); - pll_curr_ratio &= VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK; - - if (!ivpu_is_silicon(vdev)) - return PLL_SIMULATION_FREQ; - - return ivpu_hw_37xx_ratio_to_freq(vdev, pll_curr_ratio); -} - -static u32 ivpu_hw_37xx_reg_telemetry_offset_get(struct ivpu_device *vdev) -{ - return REGB_RD32(VPU_37XX_BUTTRESS_VPU_TELEMETRY_OFFSET); -} - -static u32 ivpu_hw_37xx_reg_telemetry_size_get(struct ivpu_device *vdev) -{ - return REGB_RD32(VPU_37XX_BUTTRESS_VPU_TELEMETRY_SIZE); -} - -static u32 ivpu_hw_37xx_reg_telemetry_enable_get(struct ivpu_device *vdev) -{ - return REGB_RD32(VPU_37XX_BUTTRESS_VPU_TELEMETRY_ENABLE); -} - -static void ivpu_hw_37xx_reg_db_set(struct ivpu_device *vdev, u32 db_id) -{ - u32 reg_stride = VPU_37XX_CPU_SS_DOORBELL_1 - VPU_37XX_CPU_SS_DOORBELL_0; - u32 val = REG_FLD(VPU_37XX_CPU_SS_DOORBELL_0, SET); - - REGV_WR32I(VPU_37XX_CPU_SS_DOORBELL_0, reg_stride, db_id, val); -} - -static u32 ivpu_hw_37xx_reg_ipc_rx_addr_get(struct ivpu_device *vdev) -{ - return REGV_RD32(VPU_37XX_HOST_SS_TIM_IPC_FIFO_ATM); -} - -static u32 ivpu_hw_37xx_reg_ipc_rx_count_get(struct ivpu_device *vdev) -{ - u32 count = REGV_RD32_SILENT(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT); - - return REG_GET_FLD(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count); -} - -static void ivpu_hw_37xx_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr) -{ - REGV_WR32(VPU_37XX_CPU_SS_TIM_IPC_FIFO, vpu_addr); -} - -static void ivpu_hw_37xx_irq_clear(struct ivpu_device *vdev) -{ - REGV_WR64(VPU_37XX_HOST_SS_ICB_CLEAR_0, ICB_0_1_IRQ_MASK); -} - -static void ivpu_hw_37xx_irq_enable(struct ivpu_device *vdev) -{ - REGV_WR32(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, ITF_FIREWALL_VIOLATION_MASK); - REGV_WR64(VPU_37XX_HOST_SS_ICB_ENABLE_0, ICB_0_1_IRQ_MASK); - REGB_WR32(VPU_37XX_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_ENABLE_MASK); - REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x0); -} - -static void ivpu_hw_37xx_irq_disable(struct ivpu_device *vdev) -{ - REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x1); - REGB_WR32(VPU_37XX_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_DISABLE_MASK); - REGV_WR64(VPU_37XX_HOST_SS_ICB_ENABLE_0, 0x0ull); - REGV_WR32(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, 0x0); -} - -static void ivpu_hw_37xx_irq_wdt_nce_handler(struct ivpu_device *vdev) -{ - ivpu_pm_trigger_recovery(vdev, "WDT NCE IRQ"); -} - -static void ivpu_hw_37xx_irq_wdt_mss_handler(struct ivpu_device *vdev) -{ - ivpu_hw_wdt_disable(vdev); - ivpu_pm_trigger_recovery(vdev, "WDT MSS IRQ"); -} - -static void ivpu_hw_37xx_irq_noc_firewall_handler(struct ivpu_device *vdev) -{ - ivpu_pm_trigger_recovery(vdev, "NOC Firewall IRQ"); -} - -/* Handler for IRQs from VPU core (irqV) */ -static bool ivpu_hw_37xx_irqv_handler(struct ivpu_device *vdev, int irq, bool *wake_thread) -{ - u32 status = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK; - - if (!status) - return false; - - REGV_WR32(VPU_37XX_HOST_SS_ICB_CLEAR_0, status); - - if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT, status)) - ivpu_mmu_irq_evtq_handler(vdev); - - if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status)) - ivpu_ipc_irq_handler(vdev, wake_thread); - - if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status)) - ivpu_dbg(vdev, IRQ, "MMU sync complete\n"); - - if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT, status)) - ivpu_mmu_irq_gerr_handler(vdev); - - if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, status)) - ivpu_hw_37xx_irq_wdt_mss_handler(vdev); - - if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, status)) - ivpu_hw_37xx_irq_wdt_nce_handler(vdev); - - if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, status)) - ivpu_hw_37xx_irq_noc_firewall_handler(vdev); - - return true; -} - -/* Handler for IRQs from Buttress core (irqB) */ -static bool ivpu_hw_37xx_irqb_handler(struct ivpu_device *vdev, int irq) -{ - u32 status = REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK; - bool schedule_recovery = false; - - if (!status) - return false; - - if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE, status)) - ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", - REGB_RD32(VPU_37XX_BUTTRESS_CURRENT_PLL)); - - if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR, status)) { - ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_37XX_BUTTRESS_ATS_ERR_LOG_0)); - REGB_WR32(VPU_37XX_BUTTRESS_ATS_ERR_CLEAR, 0x1); - schedule_recovery = true; - } - - if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR, status)) { - u32 ufi_log = REGB_RD32(VPU_37XX_BUTTRESS_UFI_ERR_LOG); - - ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx", - ufi_log, REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, OPCODE, ufi_log), - REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, AXI_ID, ufi_log), - REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, CQ_ID, ufi_log)); - REGB_WR32(VPU_37XX_BUTTRESS_UFI_ERR_CLEAR, 0x1); - schedule_recovery = true; - } - - /* This must be done after interrupts are cleared at the source. */ - if (IVPU_WA(interrupt_clear_with_0)) - /* - * Writing 1 triggers an interrupt, so we can't perform read update write. - * Clear local interrupt status by writing 0 to all bits. - */ - REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, 0x0); - else - REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, status); - - if (schedule_recovery) - ivpu_pm_trigger_recovery(vdev, "Buttress IRQ"); - - return true; -} - -static irqreturn_t ivpu_hw_37xx_irq_handler(int irq, void *ptr) -{ - struct ivpu_device *vdev = ptr; - bool irqv_handled, irqb_handled, wake_thread = false; - - REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x1); - - irqv_handled = ivpu_hw_37xx_irqv_handler(vdev, irq, &wake_thread); - irqb_handled = ivpu_hw_37xx_irqb_handler(vdev, irq); - - /* Re-enable global interrupts to re-trigger MSI for pending interrupts */ - REGB_WR32(VPU_37XX_BUTTRESS_GLOBAL_INT_MASK, 0x0); - - if (wake_thread) - return IRQ_WAKE_THREAD; - if (irqv_handled || irqb_handled) - return IRQ_HANDLED; - return IRQ_NONE; -} - -static void ivpu_hw_37xx_diagnose_failure(struct ivpu_device *vdev) -{ - u32 irqv = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK; - u32 irqb = REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK; - - if (ivpu_hw_37xx_reg_ipc_rx_count_get(vdev)) - ivpu_err(vdev, "IPC FIFO queue not empty, missed IPC IRQ"); - - if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, irqv)) - ivpu_err(vdev, "WDT MSS timeout detected\n"); - - if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, irqv)) - ivpu_err(vdev, "WDT NCE timeout detected\n"); - - if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, irqv)) - ivpu_err(vdev, "NOC Firewall irq detected\n"); - - if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR, irqb)) - ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_37XX_BUTTRESS_ATS_ERR_LOG_0)); - - if (REG_TEST_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR, irqb)) { - u32 ufi_log = REGB_RD32(VPU_37XX_BUTTRESS_UFI_ERR_LOG); - - ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx", - ufi_log, REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, OPCODE, ufi_log), - REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, AXI_ID, ufi_log), - REG_GET_FLD(VPU_37XX_BUTTRESS_UFI_ERR_LOG, CQ_ID, ufi_log)); - } -} - -const struct ivpu_hw_ops ivpu_hw_37xx_ops = { - .info_init = ivpu_hw_37xx_info_init, - .power_up = ivpu_hw_37xx_power_up, - .is_idle = ivpu_hw_37xx_is_idle, - .wait_for_idle = ivpu_hw_37xx_wait_for_idle, - .power_down = ivpu_hw_37xx_power_down, - .reset = ivpu_hw_37xx_reset, - .boot_fw = ivpu_hw_37xx_boot_fw, - .wdt_disable = ivpu_hw_37xx_wdt_disable, - .diagnose_failure = ivpu_hw_37xx_diagnose_failure, - .profiling_freq_get = ivpu_hw_37xx_profiling_freq_get, - .profiling_freq_drive = ivpu_hw_37xx_profiling_freq_drive, - .reg_pll_freq_get = ivpu_hw_37xx_reg_pll_freq_get, - .ratio_to_freq = ivpu_hw_37xx_ratio_to_freq, - .reg_telemetry_offset_get = ivpu_hw_37xx_reg_telemetry_offset_get, - .reg_telemetry_size_get = ivpu_hw_37xx_reg_telemetry_size_get, - .reg_telemetry_enable_get = ivpu_hw_37xx_reg_telemetry_enable_get, - .reg_db_set = ivpu_hw_37xx_reg_db_set, - .reg_ipc_rx_addr_get = ivpu_hw_37xx_reg_ipc_rx_addr_get, - .reg_ipc_rx_count_get = ivpu_hw_37xx_reg_ipc_rx_count_get, - .reg_ipc_tx_set = ivpu_hw_37xx_reg_ipc_tx_set, - .irq_clear = ivpu_hw_37xx_irq_clear, - .irq_enable = ivpu_hw_37xx_irq_enable, - .irq_disable = ivpu_hw_37xx_irq_disable, - .irq_handler = ivpu_hw_37xx_irq_handler, -}; diff --git a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h index f6fec1919202..cf5e2f01049c 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h +++ b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h @@ -8,78 +8,6 @@ #include <linux/bits.h> -#define VPU_37XX_BUTTRESS_INTERRUPT_TYPE 0x00000000u - -#define VPU_37XX_BUTTRESS_INTERRUPT_STAT 0x00000004u -#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0) -#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1) -#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_UFI_ERR_MASK BIT_MASK(2) - -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0 0x00000008u -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16) - -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1 0x0000000cu -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16) - -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2 0x00000010u -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0) - -#define VPU_37XX_BUTTRESS_WP_REQ_CMD 0x00000014u -#define VPU_37XX_BUTTRESS_WP_REQ_CMD_SEND_MASK BIT_MASK(0) - -#define VPU_37XX_BUTTRESS_WP_DOWNLOAD 0x00000018u -#define VPU_37XX_BUTTRESS_WP_DOWNLOAD_TARGET_RATIO_MASK GENMASK(15, 0) - -#define VPU_37XX_BUTTRESS_CURRENT_PLL 0x0000001cu -#define VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK GENMASK(15, 0) - -#define VPU_37XX_BUTTRESS_PLL_ENABLE 0x00000020u - -#define VPU_37XX_BUTTRESS_FMIN_FUSE 0x00000024u -#define VPU_37XX_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0) -#define VPU_37XX_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8) - -#define VPU_37XX_BUTTRESS_FMAX_FUSE 0x00000028u -#define VPU_37XX_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0) - -#define VPU_37XX_BUTTRESS_TILE_FUSE 0x0000002cu -#define VPU_37XX_BUTTRESS_TILE_FUSE_VALID_MASK BIT_MASK(0) -#define VPU_37XX_BUTTRESS_TILE_FUSE_SKU_MASK GENMASK(3, 2) - -#define VPU_37XX_BUTTRESS_LOCAL_INT_MASK 0x00000030u -#define VPU_37XX_BUTTRESS_GLOBAL_INT_MASK 0x00000034u - -#define VPU_37XX_BUTTRESS_PLL_STATUS 0x00000040u -#define VPU_37XX_BUTTRESS_PLL_STATUS_LOCK_MASK BIT_MASK(1) - -#define VPU_37XX_BUTTRESS_VPU_STATUS 0x00000044u -#define VPU_37XX_BUTTRESS_VPU_STATUS_READY_MASK BIT_MASK(0) -#define VPU_37XX_BUTTRESS_VPU_STATUS_IDLE_MASK BIT_MASK(1) - -#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL 0x00000060u -#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0) -#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_I3_MASK BIT_MASK(2) - -#define VPU_37XX_BUTTRESS_VPU_IP_RESET 0x00000050u -#define VPU_37XX_BUTTRESS_VPU_IP_RESET_TRIGGER_MASK BIT_MASK(0) - -#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_OFFSET 0x00000080u -#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_SIZE 0x00000084u -#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_ENABLE 0x00000088u - -#define VPU_37XX_BUTTRESS_ATS_ERR_LOG_0 0x000000a0u -#define VPU_37XX_BUTTRESS_ATS_ERR_LOG_1 0x000000a4u -#define VPU_37XX_BUTTRESS_ATS_ERR_CLEAR 0x000000a8u - -#define VPU_37XX_BUTTRESS_UFI_ERR_LOG 0x000000b0u -#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_CQ_ID_MASK GENMASK(11, 0) -#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_AXI_ID_MASK GENMASK(19, 12) -#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_OPCODE_MASK GENMASK(24, 20) - -#define VPU_37XX_BUTTRESS_UFI_ERR_CLEAR 0x000000b4u - #define VPU_37XX_HOST_SS_CPR_CLK_SET 0x00000084u #define VPU_37XX_HOST_SS_CPR_CLK_SET_TOP_NOC_MASK BIT_MASK(1) #define VPU_37XX_HOST_SS_CPR_CLK_SET_DSS_MAS_MASK BIT_MASK(10) diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c deleted file mode 100644 index b0b88d4c8926..000000000000 --- a/drivers/accel/ivpu/ivpu_hw_40xx.c +++ /dev/null @@ -1,1250 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020-2023 Intel Corporation - */ - -#include "ivpu_drv.h" -#include "ivpu_fw.h" -#include "ivpu_hw.h" -#include "ivpu_hw_40xx_reg.h" -#include "ivpu_hw_reg_io.h" -#include "ivpu_ipc.h" -#include "ivpu_mmu.h" -#include "ivpu_pm.h" - -#include <linux/dmi.h> - -#define TILE_MAX_NUM 6 -#define TILE_MAX_MASK 0x3f - -#define LNL_HW_ID 0x4040 - -#define SKU_TILE_SHIFT 0u -#define SKU_TILE_MASK 0x0000ffffu -#define SKU_HW_ID_SHIFT 16u -#define SKU_HW_ID_MASK 0xffff0000u - -#define PLL_CONFIG_DEFAULT 0x0 -#define PLL_CDYN_DEFAULT 0x80 -#define PLL_EPP_DEFAULT 0x80 -#define PLL_REF_CLK_FREQ (50 * 1000000) -#define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ) - -#define PLL_PROFILING_FREQ_DEFAULT 38400000 -#define PLL_PROFILING_FREQ_HIGH 400000000 - -#define TIM_SAFE_ENABLE 0xf1d0dead -#define TIM_WATCHDOG_RESET_VALUE 0xffffffff - -#define TIMEOUT_US (150 * USEC_PER_MSEC) -#define PWR_ISLAND_STATUS_TIMEOUT_US (5 * USEC_PER_MSEC) -#define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC) -#define IDLE_TIMEOUT_US (5 * USEC_PER_MSEC) - -#define WEIGHTS_DEFAULT 0xf711f711u -#define WEIGHTS_ATS_DEFAULT 0x0000f711u - -#define ICB_0_IRQ_MASK ((REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT)) | \ - (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT)) | \ - (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT)) | \ - (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT)) | \ - (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT)) | \ - (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT)) | \ - (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT))) - -#define ICB_1_IRQ_MASK ((REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_2_INT)) | \ - (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_3_INT)) | \ - (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_4_INT))) - -#define ICB_0_1_IRQ_MASK ((((u64)ICB_1_IRQ_MASK) << 32) | ICB_0_IRQ_MASK) - -#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \ - (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI0_ERR)) | \ - (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI1_ERR)) | \ - (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR0_ERR)) | \ - (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR1_ERR)) | \ - (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, SURV_ERR))) - -#define BUTTRESS_IRQ_ENABLE_MASK ((u32)~BUTTRESS_IRQ_MASK) -#define BUTTRESS_IRQ_DISABLE_MASK ((u32)-1) - -#define ITF_FIREWALL_VIOLATION_MASK ((REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_ROM_CMX)) | \ - (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_DBG)) | \ - (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_CTRL)) | \ - (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, DEC400)) | \ - (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_NCE)) | \ - (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \ - (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX))) - -static char *ivpu_platform_to_str(u32 platform) -{ - switch (platform) { - case IVPU_PLATFORM_SILICON: - return "SILICON"; - case IVPU_PLATFORM_SIMICS: - return "SIMICS"; - case IVPU_PLATFORM_FPGA: - return "FPGA"; - default: - return "Invalid platform"; - } -} - -static const struct dmi_system_id ivpu_dmi_platform_simulation[] = { - { - .ident = "Intel Simics", - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "lnlrvp"), - DMI_MATCH(DMI_BOARD_VERSION, "1.0"), - DMI_MATCH(DMI_BOARD_SERIAL, "123456789"), - }, - }, - { - .ident = "Intel Simics", - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "Simics"), - }, - }, - { } -}; - -static void ivpu_hw_read_platform(struct ivpu_device *vdev) -{ - if (dmi_check_system(ivpu_dmi_platform_simulation)) - vdev->platform = IVPU_PLATFORM_SIMICS; - else - vdev->platform = IVPU_PLATFORM_SILICON; - - ivpu_dbg(vdev, MISC, "Platform type: %s (%d)\n", - ivpu_platform_to_str(vdev->platform), vdev->platform); -} - -static void ivpu_hw_wa_init(struct ivpu_device *vdev) -{ - vdev->wa.punit_disabled = ivpu_is_fpga(vdev); - vdev->wa.clear_runtime_mem = false; - - if (ivpu_hw_gen(vdev) == IVPU_HW_40XX) - vdev->wa.disable_clock_relinquish = true; - - IVPU_PRINT_WA(punit_disabled); - IVPU_PRINT_WA(clear_runtime_mem); - IVPU_PRINT_WA(disable_clock_relinquish); -} - -static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) -{ - if (ivpu_is_fpga(vdev)) { - vdev->timeout.boot = 100000; - vdev->timeout.jsm = 50000; - vdev->timeout.tdr = 2000000; - vdev->timeout.reschedule_suspend = 1000; - vdev->timeout.autosuspend = -1; - vdev->timeout.d0i3_entry_msg = 500; - } else if (ivpu_is_simics(vdev)) { - vdev->timeout.boot = 50; - vdev->timeout.jsm = 500; - vdev->timeout.tdr = 10000; - vdev->timeout.reschedule_suspend = 10; - vdev->timeout.autosuspend = -1; - vdev->timeout.d0i3_entry_msg = 100; - } else { - vdev->timeout.boot = 1000; - vdev->timeout.jsm = 500; - vdev->timeout.tdr = 2000; - vdev->timeout.reschedule_suspend = 10; - vdev->timeout.autosuspend = 10; - vdev->timeout.d0i3_entry_msg = 5; - } -} - -static int ivpu_pll_wait_for_cmd_send(struct ivpu_device *vdev) -{ - return REGB_POLL_FLD(VPU_40XX_BUTTRESS_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US); -} - -static int ivpu_pll_cmd_send(struct ivpu_device *vdev, u16 min_ratio, u16 max_ratio, - u16 target_ratio, u16 epp, u16 config, u16 cdyn) -{ - int ret; - u32 val; - - ret = ivpu_pll_wait_for_cmd_send(vdev); - if (ret) { - ivpu_err(vdev, "Failed to sync before WP request: %d\n", ret); - return ret; - } - - val = REGB_RD32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0); - val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0, MIN_RATIO, min_ratio, val); - val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0, MAX_RATIO, max_ratio, val); - REGB_WR32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0, val); - - val = REGB_RD32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1); - val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1, TARGET_RATIO, target_ratio, val); - val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1, EPP, epp, val); - REGB_WR32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1, val); - - val = REGB_RD32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2); - val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2, CONFIG, config, val); - val = REG_SET_FLD_NUM(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2, CDYN, cdyn, val); - REGB_WR32(VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2, val); - - val = REGB_RD32(VPU_40XX_BUTTRESS_WP_REQ_CMD); - val = REG_SET_FLD(VPU_40XX_BUTTRESS_WP_REQ_CMD, SEND, val); - REGB_WR32(VPU_40XX_BUTTRESS_WP_REQ_CMD, val); - - ret = ivpu_pll_wait_for_cmd_send(vdev); - if (ret) - ivpu_err(vdev, "Failed to sync after WP request: %d\n", ret); - - return ret; -} - -static int ivpu_pll_wait_for_status_ready(struct ivpu_device *vdev) -{ - return REGB_POLL_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, READY, 1, PLL_TIMEOUT_US); -} - -static int ivpu_wait_for_clock_own_resource_ack(struct ivpu_device *vdev) -{ - if (ivpu_is_simics(vdev)) - return 0; - - return REGB_POLL_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, CLOCK_RESOURCE_OWN_ACK, 1, TIMEOUT_US); -} - -static void ivpu_pll_init_frequency_ratios(struct ivpu_device *vdev) -{ - struct ivpu_hw_info *hw = vdev->hw; - u8 fuse_min_ratio, fuse_pn_ratio, fuse_max_ratio; - u32 fmin_fuse, fmax_fuse; - - fmin_fuse = REGB_RD32(VPU_40XX_BUTTRESS_FMIN_FUSE); - fuse_min_ratio = REG_GET_FLD(VPU_40XX_BUTTRESS_FMIN_FUSE, MIN_RATIO, fmin_fuse); - fuse_pn_ratio = REG_GET_FLD(VPU_40XX_BUTTRESS_FMIN_FUSE, PN_RATIO, fmin_fuse); - - fmax_fuse = REGB_RD32(VPU_40XX_BUTTRESS_FMAX_FUSE); - fuse_max_ratio = REG_GET_FLD(VPU_40XX_BUTTRESS_FMAX_FUSE, MAX_RATIO, fmax_fuse); - - hw->pll.min_ratio = clamp_t(u8, ivpu_pll_min_ratio, fuse_min_ratio, fuse_max_ratio); - hw->pll.max_ratio = clamp_t(u8, ivpu_pll_max_ratio, hw->pll.min_ratio, fuse_max_ratio); - hw->pll.pn_ratio = clamp_t(u8, fuse_pn_ratio, hw->pll.min_ratio, hw->pll.max_ratio); -} - -static int ivpu_pll_drive(struct ivpu_device *vdev, bool enable) -{ - u16 config = enable ? PLL_CONFIG_DEFAULT : 0; - u16 cdyn = enable ? PLL_CDYN_DEFAULT : 0; - u16 epp = enable ? PLL_EPP_DEFAULT : 0; - struct ivpu_hw_info *hw = vdev->hw; - u16 target_ratio = hw->pll.pn_ratio; - int ret; - - ivpu_dbg(vdev, PM, "PLL workpoint request: %u Hz, epp: 0x%x, config: 0x%x, cdyn: 0x%x\n", - PLL_RATIO_TO_FREQ(target_ratio), epp, config, cdyn); - - ret = ivpu_pll_cmd_send(vdev, hw->pll.min_ratio, hw->pll.max_ratio, - target_ratio, epp, config, cdyn); - if (ret) { - ivpu_err(vdev, "Failed to send PLL workpoint request: %d\n", ret); - return ret; - } - - if (enable) { - ret = ivpu_pll_wait_for_status_ready(vdev); - if (ret) { - ivpu_err(vdev, "Timed out waiting for PLL ready status\n"); - return ret; - } - } - - return 0; -} - -static int ivpu_pll_enable(struct ivpu_device *vdev) -{ - return ivpu_pll_drive(vdev, true); -} - -static int ivpu_pll_disable(struct ivpu_device *vdev) -{ - return ivpu_pll_drive(vdev, false); -} - -static void ivpu_boot_host_ss_rst_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_SS_CPR_RST_EN); - - if (enable) { - val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, TOP_NOC, val); - val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, DSS_MAS, val); - val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, CSS_MAS, val); - } else { - val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, TOP_NOC, val); - val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, DSS_MAS, val); - val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, CSS_MAS, val); - } - - REGV_WR32(VPU_40XX_HOST_SS_CPR_RST_EN, val); -} - -static void ivpu_boot_host_ss_clk_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_SS_CPR_CLK_EN); - - if (enable) { - val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, TOP_NOC, val); - val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, DSS_MAS, val); - val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, CSS_MAS, val); - } else { - val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, TOP_NOC, val); - val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, DSS_MAS, val); - val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, CSS_MAS, val); - } - - REGV_WR32(VPU_40XX_HOST_SS_CPR_CLK_EN, val); -} - -static int ivpu_boot_noc_qreqn_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QREQN); - - if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QACCEPTN); - - if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QACCEPTN, TOP_SOCMMIO, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QDENY); - - if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QDENY, TOP_SOCMMIO, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QREQN); - - if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QACCEPTN); - - if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QDENY); - - if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val)) - return -EIO; - - return 0; -} - -static void ivpu_boot_idle_gen_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_IDLE_GEN); - - if (enable) - val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_IDLE_GEN, EN, val); - else - val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_IDLE_GEN, EN, val); - - REGV_WR32(VPU_40XX_HOST_SS_AON_IDLE_GEN, val); -} - -static int ivpu_boot_host_ss_check(struct ivpu_device *vdev) -{ - int ret; - - ret = ivpu_boot_noc_qreqn_check(vdev, 0x0); - if (ret) { - ivpu_err(vdev, "Failed qreqn check: %d\n", ret); - return ret; - } - - ret = ivpu_boot_noc_qacceptn_check(vdev, 0x0); - if (ret) { - ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); - return ret; - } - - ret = ivpu_boot_noc_qdeny_check(vdev, 0x0); - if (ret) - ivpu_err(vdev, "Failed qdeny check %d\n", ret); - - return ret; -} - -static int ivpu_boot_host_ss_axi_drive(struct ivpu_device *vdev, bool enable) -{ - int ret; - u32 val; - - val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QREQN); - if (enable) - val = REG_SET_FLD(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); - else - val = REG_CLR_FLD(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); - REGV_WR32(VPU_40XX_HOST_SS_NOC_QREQN, val); - - ret = ivpu_boot_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); - if (ret) { - ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); - return ret; - } - - ret = ivpu_boot_noc_qdeny_check(vdev, 0x0); - if (ret) { - ivpu_err(vdev, "Failed qdeny check: %d\n", ret); - return ret; - } - - if (enable) { - REGB_WR32(VPU_40XX_BUTTRESS_PORT_ARBITRATION_WEIGHTS, WEIGHTS_DEFAULT); - REGB_WR32(VPU_40XX_BUTTRESS_PORT_ARBITRATION_WEIGHTS_ATS, WEIGHTS_ATS_DEFAULT); - } - - return ret; -} - -static int ivpu_boot_host_ss_axi_enable(struct ivpu_device *vdev) -{ - return ivpu_boot_host_ss_axi_drive(vdev, true); -} - -static int ivpu_boot_host_ss_top_noc_drive(struct ivpu_device *vdev, bool enable) -{ - int ret; - u32 val; - - val = REGV_RD32(VPU_40XX_TOP_NOC_QREQN); - if (enable) { - val = REG_SET_FLD(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, val); - val = REG_SET_FLD(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); - } else { - val = REG_CLR_FLD(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, val); - val = REG_CLR_FLD(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); - } - REGV_WR32(VPU_40XX_TOP_NOC_QREQN, val); - - ret = ivpu_boot_top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); - if (ret) { - ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); - return ret; - } - - ret = ivpu_boot_top_noc_qdeny_check(vdev, 0x0); - if (ret) - ivpu_err(vdev, "Failed qdeny check: %d\n", ret); - - return ret; -} - -static int ivpu_boot_host_ss_top_noc_enable(struct ivpu_device *vdev) -{ - return ivpu_boot_host_ss_top_noc_drive(vdev, true); -} - -static void ivpu_boot_pwr_island_trickle_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0); - - if (enable) - val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, CSS_CPU, val); - else - val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, CSS_CPU, val); - - REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, val); - - if (enable) - ndelay(500); -} - -static void ivpu_boot_pwr_island_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0); - - if (enable) - val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, CSS_CPU, val); - else - val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, CSS_CPU, val); - - REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, val); - - if (!enable) - ndelay(500); -} - -static int ivpu_boot_wait_for_pwr_island_status(struct ivpu_device *vdev, u32 exp_val) -{ - if (ivpu_is_fpga(vdev)) - return 0; - - return REGV_POLL_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_STATUS0, CSS_CPU, - exp_val, PWR_ISLAND_STATUS_TIMEOUT_US); -} - -static void ivpu_boot_pwr_island_isolation_drive(struct ivpu_device *vdev, bool enable) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0); - - if (enable) - val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, CSS_CPU, val); - else - val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, CSS_CPU, val); - - REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, val); -} - -static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES); - - val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, SNOOP_OVERRIDE_EN, val); - val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AW_SNOOP_OVERRIDE, val); - val = REG_CLR_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AR_SNOOP_OVERRIDE, val); - - REGV_WR32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, val); -} - -static void ivpu_boot_tbu_mmu_enable(struct ivpu_device *vdev) -{ - u32 val = REGV_RD32(VPU_40XX_HOST_IF_TBU_MMUSSIDV); - - val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val); - val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val); - val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU1_AWMMUSSIDV, val); - val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU1_ARMMUSSIDV, val); - val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val); - val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val); - - REGV_WR32(VPU_40XX_HOST_IF_TBU_MMUSSIDV, val); -} - -static int ivpu_boot_cpu_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QACCEPTN); - - if (!REG_TEST_FLD_NUM(VPU_40XX_CPU_SS_CPR_NOC_QACCEPTN, TOP_MMIO, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_cpu_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) -{ - u32 val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QDENY); - - if (!REG_TEST_FLD_NUM(VPU_40XX_CPU_SS_CPR_NOC_QDENY, TOP_MMIO, exp_val, val)) - return -EIO; - - return 0; -} - -static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev) -{ - int ret; - - ret = ivpu_wait_for_clock_own_resource_ack(vdev); - if (ret) { - ivpu_err(vdev, "Timed out waiting for clock own resource ACK\n"); - return ret; - } - - ivpu_boot_pwr_island_trickle_drive(vdev, true); - ivpu_boot_pwr_island_drive(vdev, true); - - ret = ivpu_boot_wait_for_pwr_island_status(vdev, 0x1); - if (ret) { - ivpu_err(vdev, "Timed out waiting for power island status\n"); - return ret; - } - - ret = ivpu_boot_top_noc_qrenqn_check(vdev, 0x0); - if (ret) { - ivpu_err(vdev, "Failed qrenqn check %d\n", ret); - return ret; - } - - ivpu_boot_host_ss_clk_drive(vdev, true); - ivpu_boot_host_ss_rst_drive(vdev, true); - ivpu_boot_pwr_island_isolation_drive(vdev, false); - - return ret; -} - -static int ivpu_boot_soc_cpu_drive(struct ivpu_device *vdev, bool enable) -{ - int ret; - u32 val; - - val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QREQN); - if (enable) - val = REG_SET_FLD(VPU_40XX_CPU_SS_CPR_NOC_QREQN, TOP_MMIO, val); - else - val = REG_CLR_FLD(VPU_40XX_CPU_SS_CPR_NOC_QREQN, TOP_MMIO, val); - REGV_WR32(VPU_40XX_CPU_SS_CPR_NOC_QREQN, val); - - ret = ivpu_boot_cpu_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); - if (ret) { - ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); - return ret; - } - - ret = ivpu_boot_cpu_noc_qdeny_check(vdev, 0x0); - if (ret) - ivpu_err(vdev, "Failed qdeny check: %d\n", ret); - - return ret; -} - -static int ivpu_boot_soc_cpu_enable(struct ivpu_device *vdev) -{ - return ivpu_boot_soc_cpu_drive(vdev, true); -} - -static int ivpu_boot_soc_cpu_boot(struct ivpu_device *vdev) -{ - int ret; - u32 val; - u64 val64; - - ret = ivpu_boot_soc_cpu_enable(vdev); - if (ret) { - ivpu_err(vdev, "Failed to enable SOC CPU: %d\n", ret); - return ret; - } - - val64 = vdev->fw->entry_point; - val64 <<= ffs(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO_IMAGE_LOCATION_MASK) - 1; - REGV_WR64(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val64); - - val = REGV_RD32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO); - val = REG_SET_FLD(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, DONE, val); - REGV_WR32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val); - - ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n", - ivpu_fw_is_cold_boot(vdev) ? "cold boot" : "resume"); - - return 0; -} - -static int ivpu_boot_d0i3_drive(struct ivpu_device *vdev, bool enable) -{ - int ret; - u32 val; - - ret = REGB_POLL_FLD(VPU_40XX_BUTTRESS_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); - if (ret) { - ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret); - return ret; - } - - val = REGB_RD32(VPU_40XX_BUTTRESS_D0I3_CONTROL); - if (enable) - val = REG_SET_FLD(VPU_40XX_BUTTRESS_D0I3_CONTROL, I3, val); - else - val = REG_CLR_FLD(VPU_40XX_BUTTRESS_D0I3_CONTROL, I3, val); - REGB_WR32(VPU_40XX_BUTTRESS_D0I3_CONTROL, val); - - ret = REGB_POLL_FLD(VPU_40XX_BUTTRESS_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); - if (ret) { - ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret); - return ret; - } - - return 0; -} - -static bool ivpu_tile_disable_check(u32 config) -{ - /* Allowed values: 0 or one bit from range 0-5 (6 tiles) */ - if (config == 0) - return true; - - if (config > BIT(TILE_MAX_NUM - 1)) - return false; - - if ((config & (config - 1)) == 0) - return true; - - return false; -} - -static int ivpu_hw_40xx_info_init(struct ivpu_device *vdev) -{ - struct ivpu_hw_info *hw = vdev->hw; - u32 tile_disable; - u32 fuse; - - fuse = REGB_RD32(VPU_40XX_BUTTRESS_TILE_FUSE); - if (!REG_TEST_FLD(VPU_40XX_BUTTRESS_TILE_FUSE, VALID, fuse)) { - ivpu_err(vdev, "Fuse: invalid (0x%x)\n", fuse); - return -EIO; - } - - tile_disable = REG_GET_FLD(VPU_40XX_BUTTRESS_TILE_FUSE, CONFIG, fuse); - if (!ivpu_tile_disable_check(tile_disable)) { - ivpu_err(vdev, "Fuse: Invalid tile disable config (0x%x)\n", tile_disable); - return -EIO; - } - - if (tile_disable) - ivpu_dbg(vdev, MISC, "Fuse: %d tiles enabled. Tile number %d disabled\n", - TILE_MAX_NUM - 1, ffs(tile_disable) - 1); - else - ivpu_dbg(vdev, MISC, "Fuse: All %d tiles enabled\n", TILE_MAX_NUM); - - hw->tile_fuse = tile_disable; - hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT; - - ivpu_pll_init_frequency_ratios(vdev); - - ivpu_hw_init_range(&vdev->hw->ranges.global, 0x80000000, SZ_512M); - ivpu_hw_init_range(&vdev->hw->ranges.user, 0x80000000, SZ_256M); - ivpu_hw_init_range(&vdev->hw->ranges.shave, 0x80000000 + SZ_256M, SZ_2G - SZ_256M); - ivpu_hw_init_range(&vdev->hw->ranges.dma, 0x200000000, SZ_8G); - - ivpu_hw_read_platform(vdev); - ivpu_hw_wa_init(vdev); - ivpu_hw_timeouts_init(vdev); - - return 0; -} - -static int ivpu_hw_40xx_ip_reset(struct ivpu_device *vdev) -{ - int ret; - u32 val; - - ret = REGB_POLL_FLD(VPU_40XX_BUTTRESS_IP_RESET, TRIGGER, 0, TIMEOUT_US); - if (ret) { - ivpu_err(vdev, "Wait for *_TRIGGER timed out\n"); - return ret; - } - - val = REGB_RD32(VPU_40XX_BUTTRESS_IP_RESET); - val = REG_SET_FLD(VPU_40XX_BUTTRESS_IP_RESET, TRIGGER, val); - REGB_WR32(VPU_40XX_BUTTRESS_IP_RESET, val); - - ret = REGB_POLL_FLD(VPU_40XX_BUTTRESS_IP_RESET, TRIGGER, 0, TIMEOUT_US); - if (ret) - ivpu_err(vdev, "Timed out waiting for RESET completion\n"); - - return ret; -} - -static int ivpu_hw_40xx_reset(struct ivpu_device *vdev) -{ - int ret = 0; - - if (ivpu_hw_40xx_ip_reset(vdev)) { - ivpu_err(vdev, "Failed to reset NPU IP\n"); - ret = -EIO; - } - - if (ivpu_pll_disable(vdev)) { - ivpu_err(vdev, "Failed to disable PLL\n"); - ret = -EIO; - } - - return ret; -} - -static int ivpu_hw_40xx_d0i3_enable(struct ivpu_device *vdev) -{ - int ret; - - if (IVPU_WA(punit_disabled)) - return 0; - - ret = ivpu_boot_d0i3_drive(vdev, true); - if (ret) - ivpu_err(vdev, "Failed to enable D0i3: %d\n", ret); - - udelay(5); /* VPU requires 5 us to complete the transition */ - - return ret; -} - -static int ivpu_hw_40xx_d0i3_disable(struct ivpu_device *vdev) -{ - int ret; - - if (IVPU_WA(punit_disabled)) - return 0; - - ret = ivpu_boot_d0i3_drive(vdev, false); - if (ret) - ivpu_err(vdev, "Failed to disable D0i3: %d\n", ret); - - return ret; -} - -static void ivpu_hw_40xx_profiling_freq_reg_set(struct ivpu_device *vdev) -{ - u32 val = REGB_RD32(VPU_40XX_BUTTRESS_VPU_STATUS); - - if (vdev->hw->pll.profiling_freq == PLL_PROFILING_FREQ_DEFAULT) - val = REG_CLR_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, PERF_CLK, val); - else - val = REG_SET_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, PERF_CLK, val); - - REGB_WR32(VPU_40XX_BUTTRESS_VPU_STATUS, val); -} - -static void ivpu_hw_40xx_ats_print(struct ivpu_device *vdev) -{ - ivpu_dbg(vdev, MISC, "Buttress ATS: %s\n", - REGB_RD32(VPU_40XX_BUTTRESS_HM_ATS) ? "Enable" : "Disable"); -} - -static void ivpu_hw_40xx_clock_relinquish_disable(struct ivpu_device *vdev) -{ - u32 val = REGB_RD32(VPU_40XX_BUTTRESS_VPU_STATUS); - - val = REG_SET_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, DISABLE_CLK_RELINQUISH, val); - REGB_WR32(VPU_40XX_BUTTRESS_VPU_STATUS, val); -} - -static int ivpu_hw_40xx_power_up(struct ivpu_device *vdev) -{ - int ret; - - ret = ivpu_hw_40xx_d0i3_disable(vdev); - if (ret) - ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret); - - ret = ivpu_pll_enable(vdev); - if (ret) { - ivpu_err(vdev, "Failed to enable PLL: %d\n", ret); - return ret; - } - - if (IVPU_WA(disable_clock_relinquish)) - ivpu_hw_40xx_clock_relinquish_disable(vdev); - ivpu_hw_40xx_profiling_freq_reg_set(vdev); - ivpu_hw_40xx_ats_print(vdev); - - ret = ivpu_boot_host_ss_check(vdev); - if (ret) { - ivpu_err(vdev, "Failed to configure host SS: %d\n", ret); - return ret; - } - - ivpu_boot_idle_gen_drive(vdev, false); - - ret = ivpu_boot_pwr_domain_enable(vdev); - if (ret) { - ivpu_err(vdev, "Failed to enable power domain: %d\n", ret); - return ret; - } - - ret = ivpu_boot_host_ss_axi_enable(vdev); - if (ret) { - ivpu_err(vdev, "Failed to enable AXI: %d\n", ret); - return ret; - } - - ret = ivpu_boot_host_ss_top_noc_enable(vdev); - if (ret) - ivpu_err(vdev, "Failed to enable TOP NOC: %d\n", ret); - - return ret; -} - -static int ivpu_hw_40xx_boot_fw(struct ivpu_device *vdev) -{ - int ret; - - ivpu_boot_no_snoop_enable(vdev); - ivpu_boot_tbu_mmu_enable(vdev); - - ret = ivpu_boot_soc_cpu_boot(vdev); - if (ret) - ivpu_err(vdev, "Failed to boot SOC CPU: %d\n", ret); - - return ret; -} - -static bool ivpu_hw_40xx_is_idle(struct ivpu_device *vdev) -{ - u32 val; - - if (IVPU_WA(punit_disabled)) - return true; - - val = REGB_RD32(VPU_40XX_BUTTRESS_VPU_STATUS); - return REG_TEST_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, READY, val) && - REG_TEST_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, IDLE, val); -} - -static int ivpu_hw_40xx_wait_for_idle(struct ivpu_device *vdev) -{ - return REGB_POLL_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US); -} - -static void ivpu_hw_40xx_save_d0i3_entry_timestamp(struct ivpu_device *vdev) -{ - vdev->hw->d0i3_entry_host_ts = ktime_get_boottime(); - vdev->hw->d0i3_entry_vpu_ts = REGV_RD64(VPU_40XX_CPU_SS_TIM_PERF_EXT_FREE_CNT); -} - -static int ivpu_hw_40xx_power_down(struct ivpu_device *vdev) -{ - int ret = 0; - - ivpu_hw_40xx_save_d0i3_entry_timestamp(vdev); - - if (!ivpu_hw_40xx_is_idle(vdev) && ivpu_hw_40xx_ip_reset(vdev)) - ivpu_warn(vdev, "Failed to reset the NPU\n"); - - if (ivpu_pll_disable(vdev)) { - ivpu_err(vdev, "Failed to disable PLL\n"); - ret = -EIO; - } - - if (ivpu_hw_40xx_d0i3_enable(vdev)) { - ivpu_err(vdev, "Failed to enter D0I3\n"); - ret = -EIO; - } - - return ret; -} - -static void ivpu_hw_40xx_wdt_disable(struct ivpu_device *vdev) -{ - u32 val; - - REGV_WR32(VPU_40XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); - REGV_WR32(VPU_40XX_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE); - - REGV_WR32(VPU_40XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); - REGV_WR32(VPU_40XX_CPU_SS_TIM_WDOG_EN, 0); - - val = REGV_RD32(VPU_40XX_CPU_SS_TIM_GEN_CONFIG); - val = REG_CLR_FLD(VPU_40XX_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val); - REGV_WR32(VPU_40XX_CPU_SS_TIM_GEN_CONFIG, val); -} - -static u32 ivpu_hw_40xx_profiling_freq_get(struct ivpu_device *vdev) -{ - return vdev->hw->pll.profiling_freq; -} - -static void ivpu_hw_40xx_profiling_freq_drive(struct ivpu_device *vdev, bool enable) -{ - if (enable) - vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_HIGH; - else - vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT; -} - -/* Register indirect accesses */ -static u32 ivpu_hw_40xx_reg_pll_freq_get(struct ivpu_device *vdev) -{ - u32 pll_curr_ratio; - - pll_curr_ratio = REGB_RD32(VPU_40XX_BUTTRESS_PLL_FREQ); - pll_curr_ratio &= VPU_40XX_BUTTRESS_PLL_FREQ_RATIO_MASK; - - return PLL_RATIO_TO_FREQ(pll_curr_ratio); -} - -static u32 ivpu_hw_40xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) -{ - return PLL_RATIO_TO_FREQ(ratio); -} - -static u32 ivpu_hw_40xx_reg_telemetry_offset_get(struct ivpu_device *vdev) -{ - return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_OFFSET); -} - -static u32 ivpu_hw_40xx_reg_telemetry_size_get(struct ivpu_device *vdev) -{ - return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_SIZE); -} - -static u32 ivpu_hw_40xx_reg_telemetry_enable_get(struct ivpu_device *vdev) -{ - return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_ENABLE); -} - -static void ivpu_hw_40xx_reg_db_set(struct ivpu_device *vdev, u32 db_id) -{ - u32 reg_stride = VPU_40XX_CPU_SS_DOORBELL_1 - VPU_40XX_CPU_SS_DOORBELL_0; - u32 val = REG_FLD(VPU_40XX_CPU_SS_DOORBELL_0, SET); - - REGV_WR32I(VPU_40XX_CPU_SS_DOORBELL_0, reg_stride, db_id, val); -} - -static u32 ivpu_hw_40xx_reg_ipc_rx_addr_get(struct ivpu_device *vdev) -{ - return REGV_RD32(VPU_40XX_HOST_SS_TIM_IPC_FIFO_ATM); -} - -static u32 ivpu_hw_40xx_reg_ipc_rx_count_get(struct ivpu_device *vdev) -{ - u32 count = REGV_RD32_SILENT(VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT); - - return REG_GET_FLD(VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count); -} - -static void ivpu_hw_40xx_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr) -{ - REGV_WR32(VPU_40XX_CPU_SS_TIM_IPC_FIFO, vpu_addr); -} - -static void ivpu_hw_40xx_irq_clear(struct ivpu_device *vdev) -{ - REGV_WR64(VPU_40XX_HOST_SS_ICB_CLEAR_0, ICB_0_1_IRQ_MASK); -} - -static void ivpu_hw_40xx_irq_enable(struct ivpu_device *vdev) -{ - REGV_WR32(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, ITF_FIREWALL_VIOLATION_MASK); - REGV_WR64(VPU_40XX_HOST_SS_ICB_ENABLE_0, ICB_0_1_IRQ_MASK); - REGB_WR32(VPU_40XX_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_ENABLE_MASK); - REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x0); -} - -static void ivpu_hw_40xx_irq_disable(struct ivpu_device *vdev) -{ - REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x1); - REGB_WR32(VPU_40XX_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_DISABLE_MASK); - REGV_WR64(VPU_40XX_HOST_SS_ICB_ENABLE_0, 0x0ull); - REGV_WR32(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, 0x0ul); -} - -static void ivpu_hw_40xx_irq_wdt_nce_handler(struct ivpu_device *vdev) -{ - /* TODO: For LNN hang consider engine reset instead of full recovery */ - ivpu_pm_trigger_recovery(vdev, "WDT NCE IRQ"); -} - -static void ivpu_hw_40xx_irq_wdt_mss_handler(struct ivpu_device *vdev) -{ - ivpu_hw_wdt_disable(vdev); - ivpu_pm_trigger_recovery(vdev, "WDT MSS IRQ"); -} - -static void ivpu_hw_40xx_irq_noc_firewall_handler(struct ivpu_device *vdev) -{ - ivpu_pm_trigger_recovery(vdev, "NOC Firewall IRQ"); -} - -/* Handler for IRQs from VPU core (irqV) */ -static bool ivpu_hw_40xx_irqv_handler(struct ivpu_device *vdev, int irq, bool *wake_thread) -{ - u32 status = REGV_RD32(VPU_40XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK; - - if (!status) - return false; - - REGV_WR32(VPU_40XX_HOST_SS_ICB_CLEAR_0, status); - - if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT, status)) - ivpu_mmu_irq_evtq_handler(vdev); - - if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status)) - ivpu_ipc_irq_handler(vdev, wake_thread); - - if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status)) - ivpu_dbg(vdev, IRQ, "MMU sync complete\n"); - - if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT, status)) - ivpu_mmu_irq_gerr_handler(vdev); - - if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, status)) - ivpu_hw_40xx_irq_wdt_mss_handler(vdev); - - if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, status)) - ivpu_hw_40xx_irq_wdt_nce_handler(vdev); - - if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, status)) - ivpu_hw_40xx_irq_noc_firewall_handler(vdev); - - return true; -} - -/* Handler for IRQs from Buttress core (irqB) */ -static bool ivpu_hw_40xx_irqb_handler(struct ivpu_device *vdev, int irq) -{ - bool schedule_recovery = false; - u32 status = REGB_RD32(VPU_40XX_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK; - - if (!status) - return false; - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE, status)) - ivpu_dbg(vdev, IRQ, "FREQ_CHANGE"); - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR, status)) { - ivpu_err(vdev, "ATS_ERR LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n", - REGB_RD32(VPU_40XX_BUTTRESS_ATS_ERR_LOG1), - REGB_RD32(VPU_40XX_BUTTRESS_ATS_ERR_LOG2)); - REGB_WR32(VPU_40XX_BUTTRESS_ATS_ERR_CLEAR, 0x1); - schedule_recovery = true; - } - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI0_ERR, status)) { - ivpu_err(vdev, "CFI0_ERR 0x%08x", REGB_RD32(VPU_40XX_BUTTRESS_CFI0_ERR_LOG)); - REGB_WR32(VPU_40XX_BUTTRESS_CFI0_ERR_CLEAR, 0x1); - schedule_recovery = true; - } - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI1_ERR, status)) { - ivpu_err(vdev, "CFI1_ERR 0x%08x", REGB_RD32(VPU_40XX_BUTTRESS_CFI1_ERR_LOG)); - REGB_WR32(VPU_40XX_BUTTRESS_CFI1_ERR_CLEAR, 0x1); - schedule_recovery = true; - } - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR0_ERR, status)) { - ivpu_err(vdev, "IMR_ERR_CFI0 LOW: 0x%08x HIGH: 0x%08x", - REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI0_LOW), - REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI0_HIGH)); - REGB_WR32(VPU_40XX_BUTTRESS_IMR_ERR_CFI0_CLEAR, 0x1); - schedule_recovery = true; - } - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR1_ERR, status)) { - ivpu_err(vdev, "IMR_ERR_CFI1 LOW: 0x%08x HIGH: 0x%08x", - REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI1_LOW), - REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI1_HIGH)); - REGB_WR32(VPU_40XX_BUTTRESS_IMR_ERR_CFI1_CLEAR, 0x1); - schedule_recovery = true; - } - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, SURV_ERR, status)) { - ivpu_err(vdev, "Survivability error detected\n"); - schedule_recovery = true; - } - - /* This must be done after interrupts are cleared at the source. */ - REGB_WR32(VPU_40XX_BUTTRESS_INTERRUPT_STAT, status); - - if (schedule_recovery) - ivpu_pm_trigger_recovery(vdev, "Buttress IRQ"); - - return true; -} - -static irqreturn_t ivpu_hw_40xx_irq_handler(int irq, void *ptr) -{ - bool irqv_handled, irqb_handled, wake_thread = false; - struct ivpu_device *vdev = ptr; - - REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x1); - - irqv_handled = ivpu_hw_40xx_irqv_handler(vdev, irq, &wake_thread); - irqb_handled = ivpu_hw_40xx_irqb_handler(vdev, irq); - - /* Re-enable global interrupts to re-trigger MSI for pending interrupts */ - REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x0); - - if (wake_thread) - return IRQ_WAKE_THREAD; - if (irqv_handled || irqb_handled) - return IRQ_HANDLED; - return IRQ_NONE; -} - -static void ivpu_hw_40xx_diagnose_failure(struct ivpu_device *vdev) -{ - u32 irqv = REGV_RD32(VPU_40XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK; - u32 irqb = REGB_RD32(VPU_40XX_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK; - - if (ivpu_hw_40xx_reg_ipc_rx_count_get(vdev)) - ivpu_err(vdev, "IPC FIFO queue not empty, missed IPC IRQ"); - - if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, irqv)) - ivpu_err(vdev, "WDT MSS timeout detected\n"); - - if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, irqv)) - ivpu_err(vdev, "WDT NCE timeout detected\n"); - - if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, irqv)) - ivpu_err(vdev, "NOC Firewall irq detected\n"); - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR, irqb)) { - ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n", - REGB_RD32(VPU_40XX_BUTTRESS_ATS_ERR_LOG1), - REGB_RD32(VPU_40XX_BUTTRESS_ATS_ERR_LOG2)); - } - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI0_ERR, irqb)) - ivpu_err(vdev, "CFI0_ERR_LOG 0x%08x\n", REGB_RD32(VPU_40XX_BUTTRESS_CFI0_ERR_LOG)); - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI1_ERR, irqb)) - ivpu_err(vdev, "CFI1_ERR_LOG 0x%08x\n", REGB_RD32(VPU_40XX_BUTTRESS_CFI1_ERR_LOG)); - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR0_ERR, irqb)) - ivpu_err(vdev, "IMR_ERR_CFI0 LOW: 0x%08x HIGH: 0x%08x\n", - REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI0_LOW), - REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI0_HIGH)); - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR1_ERR, irqb)) - ivpu_err(vdev, "IMR_ERR_CFI1 LOW: 0x%08x HIGH: 0x%08x\n", - REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI1_LOW), - REGB_RD32(VPU_40XX_BUTTRESS_IMR_ERR_CFI1_HIGH)); - - if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, SURV_ERR, irqb)) - ivpu_err(vdev, "Survivability error detected\n"); -} - -const struct ivpu_hw_ops ivpu_hw_40xx_ops = { - .info_init = ivpu_hw_40xx_info_init, - .power_up = ivpu_hw_40xx_power_up, - .is_idle = ivpu_hw_40xx_is_idle, - .wait_for_idle = ivpu_hw_40xx_wait_for_idle, - .power_down = ivpu_hw_40xx_power_down, - .reset = ivpu_hw_40xx_reset, - .boot_fw = ivpu_hw_40xx_boot_fw, - .wdt_disable = ivpu_hw_40xx_wdt_disable, - .diagnose_failure = ivpu_hw_40xx_diagnose_failure, - .profiling_freq_get = ivpu_hw_40xx_profiling_freq_get, - .profiling_freq_drive = ivpu_hw_40xx_profiling_freq_drive, - .reg_pll_freq_get = ivpu_hw_40xx_reg_pll_freq_get, - .ratio_to_freq = ivpu_hw_40xx_ratio_to_freq, - .reg_telemetry_offset_get = ivpu_hw_40xx_reg_telemetry_offset_get, - .reg_telemetry_size_get = ivpu_hw_40xx_reg_telemetry_size_get, - .reg_telemetry_enable_get = ivpu_hw_40xx_reg_telemetry_enable_get, - .reg_db_set = ivpu_hw_40xx_reg_db_set, - .reg_ipc_rx_addr_get = ivpu_hw_40xx_reg_ipc_rx_addr_get, - .reg_ipc_rx_count_get = ivpu_hw_40xx_reg_ipc_rx_count_get, - .reg_ipc_tx_set = ivpu_hw_40xx_reg_ipc_tx_set, - .irq_clear = ivpu_hw_40xx_irq_clear, - .irq_enable = ivpu_hw_40xx_irq_enable, - .irq_disable = ivpu_hw_40xx_irq_disable, - .irq_handler = ivpu_hw_40xx_irq_handler, -}; diff --git a/drivers/accel/ivpu/ivpu_hw_40xx_reg.h b/drivers/accel/ivpu/ivpu_hw_40xx_reg.h index ff4a5d4f5821..d0b795b344c7 100644 --- a/drivers/accel/ivpu/ivpu_hw_40xx_reg.h +++ b/drivers/accel/ivpu/ivpu_hw_40xx_reg.h @@ -8,91 +8,6 @@ #include <linux/bits.h> -#define VPU_40XX_BUTTRESS_INTERRUPT_STAT 0x00000000u -#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0) -#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1) -#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_CFI0_ERR_MASK BIT_MASK(2) -#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_CFI1_ERR_MASK BIT_MASK(3) -#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_IMR0_ERR_MASK BIT_MASK(4) -#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_IMR1_ERR_MASK BIT_MASK(5) -#define VPU_40XX_BUTTRESS_INTERRUPT_STAT_SURV_ERR_MASK BIT_MASK(6) - -#define VPU_40XX_BUTTRESS_LOCAL_INT_MASK 0x00000004u -#define VPU_40XX_BUTTRESS_GLOBAL_INT_MASK 0x00000008u - -#define VPU_40XX_BUTTRESS_HM_ATS 0x0000000cu - -#define VPU_40XX_BUTTRESS_ATS_ERR_LOG1 0x00000010u -#define VPU_40XX_BUTTRESS_ATS_ERR_LOG2 0x00000014u -#define VPU_40XX_BUTTRESS_ATS_ERR_CLEAR 0x00000018u - -#define VPU_40XX_BUTTRESS_CFI0_ERR_LOG 0x0000001cu -#define VPU_40XX_BUTTRESS_CFI0_ERR_CLEAR 0x00000020u - -#define VPU_40XX_BUTTRESS_PORT_ARBITRATION_WEIGHTS_ATS 0x00000024u - -#define VPU_40XX_BUTTRESS_CFI1_ERR_LOG 0x00000040u -#define VPU_40XX_BUTTRESS_CFI1_ERR_CLEAR 0x00000044u - -#define VPU_40XX_BUTTRESS_IMR_ERR_CFI0_LOW 0x00000048u -#define VPU_40XX_BUTTRESS_IMR_ERR_CFI0_HIGH 0x0000004cu -#define VPU_40XX_BUTTRESS_IMR_ERR_CFI0_CLEAR 0x00000050u - -#define VPU_40XX_BUTTRESS_PORT_ARBITRATION_WEIGHTS 0x00000054u - -#define VPU_40XX_BUTTRESS_IMR_ERR_CFI1_LOW 0x00000058u -#define VPU_40XX_BUTTRESS_IMR_ERR_CFI1_HIGH 0x0000005cu -#define VPU_40XX_BUTTRESS_IMR_ERR_CFI1_CLEAR 0x00000060u - -#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0 0x00000130u -#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0) -#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16) - -#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1 0x00000134u -#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0) -#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16) - -#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2 0x00000138u -#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0) -#define VPU_40XX_BUTTRESS_WP_REQ_PAYLOAD2_CDYN_MASK GENMASK(31, 16) - -#define VPU_40XX_BUTTRESS_WP_REQ_CMD 0x0000013cu -#define VPU_40XX_BUTTRESS_WP_REQ_CMD_SEND_MASK BIT_MASK(0) - -#define VPU_40XX_BUTTRESS_PLL_FREQ 0x00000148u -#define VPU_40XX_BUTTRESS_PLL_FREQ_RATIO_MASK GENMASK(15, 0) - -#define VPU_40XX_BUTTRESS_TILE_FUSE 0x00000150u -#define VPU_40XX_BUTTRESS_TILE_FUSE_VALID_MASK BIT_MASK(0) -#define VPU_40XX_BUTTRESS_TILE_FUSE_CONFIG_MASK GENMASK(6, 1) - -#define VPU_40XX_BUTTRESS_VPU_STATUS 0x00000154u -#define VPU_40XX_BUTTRESS_VPU_STATUS_READY_MASK BIT_MASK(0) -#define VPU_40XX_BUTTRESS_VPU_STATUS_IDLE_MASK BIT_MASK(1) -#define VPU_40XX_BUTTRESS_VPU_STATUS_DUP_IDLE_MASK BIT_MASK(2) -#define VPU_40XX_BUTTRESS_VPU_STATUS_CLOCK_RESOURCE_OWN_ACK_MASK BIT_MASK(6) -#define VPU_40XX_BUTTRESS_VPU_STATUS_POWER_RESOURCE_OWN_ACK_MASK BIT_MASK(7) -#define VPU_40XX_BUTTRESS_VPU_STATUS_PERF_CLK_MASK BIT_MASK(11) -#define VPU_40XX_BUTTRESS_VPU_STATUS_DISABLE_CLK_RELINQUISH_MASK BIT_MASK(12) - -#define VPU_40XX_BUTTRESS_IP_RESET 0x00000160u -#define VPU_40XX_BUTTRESS_IP_RESET_TRIGGER_MASK BIT_MASK(0) - -#define VPU_40XX_BUTTRESS_D0I3_CONTROL 0x00000164u -#define VPU_40XX_BUTTRESS_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0) -#define VPU_40XX_BUTTRESS_D0I3_CONTROL_I3_MASK BIT_MASK(2) - -#define VPU_40XX_BUTTRESS_VPU_TELEMETRY_OFFSET 0x00000168u -#define VPU_40XX_BUTTRESS_VPU_TELEMETRY_SIZE 0x0000016cu -#define VPU_40XX_BUTTRESS_VPU_TELEMETRY_ENABLE 0x00000170u - -#define VPU_40XX_BUTTRESS_FMIN_FUSE 0x00000174u -#define VPU_40XX_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0) -#define VPU_40XX_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8) - -#define VPU_40XX_BUTTRESS_FMAX_FUSE 0x00000178u -#define VPU_40XX_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0) - #define VPU_40XX_HOST_SS_CPR_CLK_EN 0x00000080u #define VPU_40XX_HOST_SS_CPR_CLK_EN_TOP_NOC_MASK BIT_MASK(1) #define VPU_40XX_HOST_SS_CPR_CLK_EN_DSS_MAS_MASK BIT_MASK(10) @@ -198,6 +113,12 @@ #define VPU_40XX_HOST_SS_AON_PWR_ISLAND_STATUS0 0x0003002cu #define VPU_40XX_HOST_SS_AON_PWR_ISLAND_STATUS0_CSS_CPU_MASK BIT_MASK(3) +#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_EN_POST_DLY 0x00030068u +#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_EN_POST_DLY_POST_DLY_MASK GENMASK(7, 0) + +#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY 0x0003006cu +#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY_STATUS_DLY_MASK GENMASK(7, 0) + #define VPU_40XX_HOST_SS_AON_IDLE_GEN 0x00030200u #define VPU_40XX_HOST_SS_AON_IDLE_GEN_EN_MASK BIT_MASK(0) #define VPU_40XX_HOST_SS_AON_IDLE_GEN_HW_PG_EN_MASK BIT_MASK(1) @@ -205,6 +126,9 @@ #define VPU_40XX_HOST_SS_AON_DPU_ACTIVE 0x00030204u #define VPU_40XX_HOST_SS_AON_DPU_ACTIVE_DPU_ACTIVE_MASK BIT_MASK(0) +#define VPU_50XX_HOST_SS_AON_FABRIC_REQ_OVERRIDE 0x00030210u +#define VPU_50XX_HOST_SS_AON_FABRIC_REQ_OVERRIDE_REQ_OVERRIDE_MASK BIT_MASK(0) + #define VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO 0x00040040u #define VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO_DONE_MASK BIT_MASK(0) #define VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO_IOSF_RS_ID_MASK GENMASK(2, 1) diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.c b/drivers/accel/ivpu/ivpu_hw_btrs.c new file mode 100644 index 000000000000..745e5248803d --- /dev/null +++ b/drivers/accel/ivpu/ivpu_hw_btrs.c @@ -0,0 +1,905 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020-2024 Intel Corporation + */ + +#include "ivpu_drv.h" +#include "ivpu_hw.h" +#include "ivpu_hw_btrs.h" +#include "ivpu_hw_btrs_lnl_reg.h" +#include "ivpu_hw_btrs_mtl_reg.h" +#include "ivpu_hw_reg_io.h" +#include "ivpu_pm.h" + +#define BTRS_MTL_IRQ_MASK ((REG_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR)) | \ + (REG_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, UFI_ERR))) + +#define BTRS_LNL_IRQ_MASK ((REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR)) | \ + (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI0_ERR)) | \ + (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI1_ERR)) | \ + (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR0_ERR)) | \ + (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR1_ERR)) | \ + (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR))) + +#define BTRS_MTL_ALL_IRQ_MASK (BTRS_MTL_IRQ_MASK | (REG_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, \ + FREQ_CHANGE))) + +#define BTRS_IRQ_DISABLE_MASK ((u32)-1) + +#define BTRS_LNL_ALL_IRQ_MASK ((u32)-1) + +#define BTRS_MTL_WP_CONFIG_1_TILE_5_3_RATIO WP_CONFIG(MTL_CONFIG_1_TILE, MTL_PLL_RATIO_5_3) +#define BTRS_MTL_WP_CONFIG_1_TILE_4_3_RATIO WP_CONFIG(MTL_CONFIG_1_TILE, MTL_PLL_RATIO_4_3) +#define BTRS_MTL_WP_CONFIG_2_TILE_5_3_RATIO WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_5_3) +#define BTRS_MTL_WP_CONFIG_2_TILE_4_3_RATIO WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_4_3) +#define BTRS_MTL_WP_CONFIG_0_TILE_PLL_OFF WP_CONFIG(0, 0) + +#define PLL_CDYN_DEFAULT 0x80 +#define PLL_EPP_DEFAULT 0x80 +#define PLL_CONFIG_DEFAULT 0x0 +#define PLL_SIMULATION_FREQ 10000000 +#define PLL_REF_CLK_FREQ 50000000 +#define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC) +#define IDLE_TIMEOUT_US (5 * USEC_PER_MSEC) +#define TIMEOUT_US (150 * USEC_PER_MSEC) + +/* Work point configuration values */ +#define WP_CONFIG(tile, ratio) (((tile) << 8) | (ratio)) +#define MTL_CONFIG_1_TILE 0x01 +#define MTL_CONFIG_2_TILE 0x02 +#define MTL_PLL_RATIO_5_3 0x01 +#define MTL_PLL_RATIO_4_3 0x02 +#define BTRS_MTL_TILE_FUSE_ENABLE_BOTH 0x0 +#define BTRS_MTL_TILE_SKU_BOTH 0x3630 + +#define BTRS_LNL_TILE_MAX_NUM 6 +#define BTRS_LNL_TILE_MAX_MASK 0x3f + +#define WEIGHTS_DEFAULT 0xf711f711u +#define WEIGHTS_ATS_DEFAULT 0x0000f711u + +#define DCT_REQ 0x2 +#define DCT_ENABLE 0x1 +#define DCT_DISABLE 0x0 + +int ivpu_hw_btrs_irqs_clear_with_0_mtl(struct ivpu_device *vdev) +{ + REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, BTRS_MTL_ALL_IRQ_MASK); + if (REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) == BTRS_MTL_ALL_IRQ_MASK) { + /* Writing 1s does not clear the interrupt status register */ + REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, 0x0); + return true; + } + + return false; +} + +static void freq_ratios_init_mtl(struct ivpu_device *vdev) +{ + struct ivpu_hw_info *hw = vdev->hw; + u32 fmin_fuse, fmax_fuse; + + fmin_fuse = REGB_RD32(VPU_HW_BTRS_MTL_FMIN_FUSE); + hw->pll.min_ratio = REG_GET_FLD(VPU_HW_BTRS_MTL_FMIN_FUSE, MIN_RATIO, fmin_fuse); + hw->pll.pn_ratio = REG_GET_FLD(VPU_HW_BTRS_MTL_FMIN_FUSE, PN_RATIO, fmin_fuse); + + fmax_fuse = REGB_RD32(VPU_HW_BTRS_MTL_FMAX_FUSE); + hw->pll.max_ratio = REG_GET_FLD(VPU_HW_BTRS_MTL_FMAX_FUSE, MAX_RATIO, fmax_fuse); +} + +static void freq_ratios_init_lnl(struct ivpu_device *vdev) +{ + struct ivpu_hw_info *hw = vdev->hw; + u32 fmin_fuse, fmax_fuse; + + fmin_fuse = REGB_RD32(VPU_HW_BTRS_LNL_FMIN_FUSE); + hw->pll.min_ratio = REG_GET_FLD(VPU_HW_BTRS_LNL_FMIN_FUSE, MIN_RATIO, fmin_fuse); + hw->pll.pn_ratio = REG_GET_FLD(VPU_HW_BTRS_LNL_FMIN_FUSE, PN_RATIO, fmin_fuse); + + fmax_fuse = REGB_RD32(VPU_HW_BTRS_LNL_FMAX_FUSE); + hw->pll.max_ratio = REG_GET_FLD(VPU_HW_BTRS_LNL_FMAX_FUSE, MAX_RATIO, fmax_fuse); +} + +void ivpu_hw_btrs_freq_ratios_init(struct ivpu_device *vdev) +{ + struct ivpu_hw_info *hw = vdev->hw; + + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + freq_ratios_init_mtl(vdev); + else + freq_ratios_init_lnl(vdev); + + hw->pll.min_ratio = clamp_t(u8, ivpu_pll_min_ratio, hw->pll.min_ratio, hw->pll.max_ratio); + hw->pll.max_ratio = clamp_t(u8, ivpu_pll_max_ratio, hw->pll.min_ratio, hw->pll.max_ratio); + hw->pll.pn_ratio = clamp_t(u8, hw->pll.pn_ratio, hw->pll.min_ratio, hw->pll.max_ratio); +} + +static bool tile_disable_check(u32 config) +{ + /* Allowed values: 0 or one bit from range 0-5 (6 tiles) */ + if (config == 0) + return true; + + if (config > BIT(BTRS_LNL_TILE_MAX_NUM - 1)) + return false; + + if ((config & (config - 1)) == 0) + return true; + + return false; +} + +static int read_tile_config_fuse(struct ivpu_device *vdev, u32 *tile_fuse_config) +{ + u32 fuse; + u32 config; + + fuse = REGB_RD32(VPU_HW_BTRS_LNL_TILE_FUSE); + if (!REG_TEST_FLD(VPU_HW_BTRS_LNL_TILE_FUSE, VALID, fuse)) { + ivpu_err(vdev, "Fuse: invalid (0x%x)\n", fuse); + return -EIO; + } + + config = REG_GET_FLD(VPU_HW_BTRS_LNL_TILE_FUSE, CONFIG, fuse); + if (!tile_disable_check(config)) { + ivpu_err(vdev, "Fuse: Invalid tile disable config (0x%x)\n", config); + return -EIO; + } + + if (config) + ivpu_dbg(vdev, MISC, "Fuse: %d tiles enabled. Tile number %d disabled\n", + BTRS_LNL_TILE_MAX_NUM - 1, ffs(config) - 1); + else + ivpu_dbg(vdev, MISC, "Fuse: All %d tiles enabled\n", BTRS_LNL_TILE_MAX_NUM); + + *tile_fuse_config = config; + return 0; +} + +static int info_init_mtl(struct ivpu_device *vdev) +{ + struct ivpu_hw_info *hw = vdev->hw; + + hw->tile_fuse = BTRS_MTL_TILE_FUSE_ENABLE_BOTH; + hw->sku = BTRS_MTL_TILE_SKU_BOTH; + hw->config = BTRS_MTL_WP_CONFIG_2_TILE_4_3_RATIO; + hw->sched_mode = ivpu_sched_mode; + + return 0; +} + +static int info_init_lnl(struct ivpu_device *vdev) +{ + struct ivpu_hw_info *hw = vdev->hw; + u32 tile_fuse_config; + int ret; + + ret = read_tile_config_fuse(vdev, &tile_fuse_config); + if (ret) + return ret; + + hw->sched_mode = ivpu_sched_mode; + hw->tile_fuse = tile_fuse_config; + hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT; + + return 0; +} + +int ivpu_hw_btrs_info_init(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return info_init_mtl(vdev); + else + return info_init_lnl(vdev); +} + +static int wp_request_sync(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return REGB_POLL_FLD(VPU_HW_BTRS_MTL_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US); + else + return REGB_POLL_FLD(VPU_HW_BTRS_LNL_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US); +} + +static int wait_for_status_ready(struct ivpu_device *vdev, bool enable) +{ + u32 exp_val = enable ? 0x1 : 0x0; + + if (IVPU_WA(punit_disabled)) + return 0; + + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, READY, exp_val, PLL_TIMEOUT_US); + else + return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, READY, exp_val, PLL_TIMEOUT_US); +} + +struct wp_request { + u16 min; + u16 max; + u16 target; + u16 cfg; + u16 epp; + u16 cdyn; +}; + +static void wp_request_mtl(struct ivpu_device *vdev, struct wp_request *wp) +{ + u32 val; + + val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0, MIN_RATIO, wp->min, val); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0, MAX_RATIO, wp->max, val); + REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0, val); + + val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1, TARGET_RATIO, wp->target, val); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1, EPP, PLL_EPP_DEFAULT, val); + REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1, val); + + val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2, CONFIG, wp->cfg, val); + REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2, val); + + val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_CMD); + val = REG_SET_FLD(VPU_HW_BTRS_MTL_WP_REQ_CMD, SEND, val); + REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_CMD, val); +} + +static void wp_request_lnl(struct ivpu_device *vdev, struct wp_request *wp) +{ + u32 val; + + val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0, MIN_RATIO, wp->min, val); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0, MAX_RATIO, wp->max, val); + REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0, val); + + val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1, TARGET_RATIO, wp->target, val); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1, EPP, wp->epp, val); + REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1, val); + + val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2, CONFIG, wp->cfg, val); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2, CDYN, wp->cdyn, val); + REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2, val); + + val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_CMD); + val = REG_SET_FLD(VPU_HW_BTRS_LNL_WP_REQ_CMD, SEND, val); + REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_CMD, val); +} + +static void wp_request(struct ivpu_device *vdev, struct wp_request *wp) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + wp_request_mtl(vdev, wp); + else + wp_request_lnl(vdev, wp); +} + +static int wp_request_send(struct ivpu_device *vdev, struct wp_request *wp) +{ + int ret; + + ret = wp_request_sync(vdev); + if (ret) { + ivpu_err(vdev, "Failed to sync before workpoint request: %d\n", ret); + return ret; + } + + wp_request(vdev, wp); + + ret = wp_request_sync(vdev); + if (ret) + ivpu_err(vdev, "Failed to sync after workpoint request: %d\n", ret); + + return ret; +} + +static void prepare_wp_request(struct ivpu_device *vdev, struct wp_request *wp, bool enable) +{ + struct ivpu_hw_info *hw = vdev->hw; + + wp->min = hw->pll.min_ratio; + wp->max = hw->pll.max_ratio; + + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) { + wp->target = enable ? hw->pll.pn_ratio : 0; + wp->cfg = enable ? hw->config : 0; + wp->cdyn = 0; + wp->epp = 0; + } else { + wp->target = hw->pll.pn_ratio; + wp->cfg = enable ? PLL_CONFIG_DEFAULT : 0; + wp->cdyn = enable ? PLL_CDYN_DEFAULT : 0; + wp->epp = enable ? PLL_EPP_DEFAULT : 0; + } + + /* Simics cannot start without at least one tile */ + if (enable && ivpu_is_simics(vdev)) + wp->cfg = 1; +} + +static int wait_for_pll_lock(struct ivpu_device *vdev, bool enable) +{ + u32 exp_val = enable ? 0x1 : 0x0; + + if (ivpu_hw_btrs_gen(vdev) != IVPU_HW_BTRS_MTL) + return 0; + + if (IVPU_WA(punit_disabled)) + return 0; + + return REGB_POLL_FLD(VPU_HW_BTRS_MTL_PLL_STATUS, LOCK, exp_val, PLL_TIMEOUT_US); +} + +int ivpu_hw_btrs_wp_drive(struct ivpu_device *vdev, bool enable) +{ + struct wp_request wp; + int ret; + + if (IVPU_WA(punit_disabled)) { + ivpu_dbg(vdev, PM, "Skipping workpoint request\n"); + return 0; + } + + prepare_wp_request(vdev, &wp, enable); + + ivpu_dbg(vdev, PM, "PLL workpoint request: %u Hz, config: 0x%x, epp: 0x%x, cdyn: 0x%x\n", + PLL_RATIO_TO_FREQ(wp.target), wp.cfg, wp.epp, wp.cdyn); + + ret = wp_request_send(vdev, &wp); + if (ret) { + ivpu_err(vdev, "Failed to send workpoint request: %d\n", ret); + return ret; + } + + ret = wait_for_pll_lock(vdev, enable); + if (ret) { + ivpu_err(vdev, "Timed out waiting for PLL lock\n"); + return ret; + } + + ret = wait_for_status_ready(vdev, enable); + if (ret) { + ivpu_err(vdev, "Timed out waiting for NPU ready status\n"); + return ret; + } + + return 0; +} + +static int d0i3_drive_mtl(struct ivpu_device *vdev, bool enable) +{ + int ret; + u32 val; + + ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); + if (ret) { + ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret); + return ret; + } + + val = REGB_RD32(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL); + if (enable) + val = REG_SET_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, I3, val); + else + val = REG_CLR_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, I3, val); + REGB_WR32(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, val); + + ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); + if (ret) + ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret); + + return ret; +} + +static int d0i3_drive_lnl(struct ivpu_device *vdev, bool enable) +{ + int ret; + u32 val; + + ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); + if (ret) { + ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret); + return ret; + } + + val = REGB_RD32(VPU_HW_BTRS_LNL_D0I3_CONTROL); + if (enable) + val = REG_SET_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, I3, val); + else + val = REG_CLR_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, I3, val); + REGB_WR32(VPU_HW_BTRS_LNL_D0I3_CONTROL, val); + + ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); + if (ret) { + ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret); + return ret; + } + + return 0; +} + +static int d0i3_drive(struct ivpu_device *vdev, bool enable) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return d0i3_drive_mtl(vdev, enable); + else + return d0i3_drive_lnl(vdev, enable); +} + +int ivpu_hw_btrs_d0i3_enable(struct ivpu_device *vdev) +{ + int ret; + + if (IVPU_WA(punit_disabled)) + return 0; + + ret = d0i3_drive(vdev, true); + if (ret) + ivpu_err(vdev, "Failed to enable D0i3: %d\n", ret); + + udelay(5); /* VPU requires 5 us to complete the transition */ + + return ret; +} + +int ivpu_hw_btrs_d0i3_disable(struct ivpu_device *vdev) +{ + int ret; + + if (IVPU_WA(punit_disabled)) + return 0; + + ret = d0i3_drive(vdev, false); + if (ret) + ivpu_err(vdev, "Failed to disable D0i3: %d\n", ret); + + return ret; +} + +int ivpu_hw_btrs_wait_for_clock_res_own_ack(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return 0; + + if (ivpu_is_simics(vdev)) + return 0; + + return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, CLOCK_RESOURCE_OWN_ACK, 1, TIMEOUT_US); +} + +void ivpu_hw_btrs_set_port_arbitration_weights_lnl(struct ivpu_device *vdev) +{ + REGB_WR32(VPU_HW_BTRS_LNL_PORT_ARBITRATION_WEIGHTS, WEIGHTS_DEFAULT); + REGB_WR32(VPU_HW_BTRS_LNL_PORT_ARBITRATION_WEIGHTS_ATS, WEIGHTS_ATS_DEFAULT); +} + +static int ip_reset_mtl(struct ivpu_device *vdev) +{ + int ret; + u32 val; + + ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US); + if (ret) { + ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n"); + return ret; + } + + val = REGB_RD32(VPU_HW_BTRS_MTL_VPU_IP_RESET); + val = REG_SET_FLD(VPU_HW_BTRS_MTL_VPU_IP_RESET, TRIGGER, val); + REGB_WR32(VPU_HW_BTRS_MTL_VPU_IP_RESET, val); + + ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US); + if (ret) + ivpu_err(vdev, "Timed out waiting for RESET completion\n"); + + return ret; +} + +static int ip_reset_lnl(struct ivpu_device *vdev) +{ + int ret; + u32 val; + + ivpu_hw_btrs_clock_relinquish_disable_lnl(vdev); + + ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, 0, TIMEOUT_US); + if (ret) { + ivpu_err(vdev, "Wait for *_TRIGGER timed out\n"); + return ret; + } + + val = REGB_RD32(VPU_HW_BTRS_LNL_IP_RESET); + val = REG_SET_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, val); + REGB_WR32(VPU_HW_BTRS_LNL_IP_RESET, val); + + ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, 0, TIMEOUT_US); + if (ret) + ivpu_err(vdev, "Timed out waiting for RESET completion\n"); + + return ret; +} + +int ivpu_hw_btrs_ip_reset(struct ivpu_device *vdev) +{ + if (IVPU_WA(punit_disabled)) + return 0; + + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return ip_reset_mtl(vdev); + else + return ip_reset_lnl(vdev); +} + +void ivpu_hw_btrs_profiling_freq_reg_set_lnl(struct ivpu_device *vdev) +{ + u32 val = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS); + + if (vdev->hw->pll.profiling_freq == PLL_PROFILING_FREQ_DEFAULT) + val = REG_CLR_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, PERF_CLK, val); + else + val = REG_SET_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, PERF_CLK, val); + + REGB_WR32(VPU_HW_BTRS_LNL_VPU_STATUS, val); +} + +void ivpu_hw_btrs_ats_print_lnl(struct ivpu_device *vdev) +{ + ivpu_dbg(vdev, MISC, "Buttress ATS: %s\n", + REGB_RD32(VPU_HW_BTRS_LNL_HM_ATS) ? "Enable" : "Disable"); +} + +void ivpu_hw_btrs_clock_relinquish_disable_lnl(struct ivpu_device *vdev) +{ + u32 val = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS); + + val = REG_SET_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, DISABLE_CLK_RELINQUISH, val); + REGB_WR32(VPU_HW_BTRS_LNL_VPU_STATUS, val); +} + +bool ivpu_hw_btrs_is_idle(struct ivpu_device *vdev) +{ + u32 val; + + if (IVPU_WA(punit_disabled)) + return true; + + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) { + val = REGB_RD32(VPU_HW_BTRS_MTL_VPU_STATUS); + + return REG_TEST_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, READY, val) && + REG_TEST_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, IDLE, val); + } else { + val = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS); + + return REG_TEST_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, READY, val) && + REG_TEST_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, IDLE, val); + } +} + +int ivpu_hw_btrs_wait_for_idle(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US); + else + return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US); +} + +/* Handler for IRQs from Buttress core (irqB) */ +bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq) +{ + u32 status = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_MTL_IRQ_MASK; + bool schedule_recovery = false; + + if (!status) + return false; + + if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, FREQ_CHANGE, status)) + ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", + REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL)); + + if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR, status)) { + ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_HW_BTRS_MTL_ATS_ERR_LOG_0)); + REGB_WR32(VPU_HW_BTRS_MTL_ATS_ERR_CLEAR, 0x1); + schedule_recovery = true; + } + + if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, UFI_ERR, status)) { + u32 ufi_log = REGB_RD32(VPU_HW_BTRS_MTL_UFI_ERR_LOG); + + ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx", + ufi_log, REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, OPCODE, ufi_log), + REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, AXI_ID, ufi_log), + REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, CQ_ID, ufi_log)); + REGB_WR32(VPU_HW_BTRS_MTL_UFI_ERR_CLEAR, 0x1); + schedule_recovery = true; + } + + /* This must be done after interrupts are cleared at the source. */ + if (IVPU_WA(interrupt_clear_with_0)) + /* + * Writing 1 triggers an interrupt, so we can't perform read update write. + * Clear local interrupt status by writing 0 to all bits. + */ + REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, 0x0); + else + REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, status); + + if (schedule_recovery) + ivpu_pm_trigger_recovery(vdev, "Buttress IRQ"); + + return true; +} + +/* Handler for IRQs from Buttress core (irqB) */ +bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq) +{ + u32 status = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK; + bool schedule_recovery = false; + + if (!status) + return false; + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, status)) { + ivpu_dbg(vdev, IRQ, "Survivability IRQ\n"); + if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_DCT)) + ivpu_err_ratelimited(vdev, "IRQ FIFO full\n"); + } + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, FREQ_CHANGE, status)) + ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ)); + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, status)) { + ivpu_err(vdev, "ATS_ERR LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n", + REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG1), + REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG2)); + REGB_WR32(VPU_HW_BTRS_LNL_ATS_ERR_CLEAR, 0x1); + schedule_recovery = true; + } + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI0_ERR, status)) { + ivpu_err(vdev, "CFI0_ERR 0x%08x", REGB_RD32(VPU_HW_BTRS_LNL_CFI0_ERR_LOG)); + REGB_WR32(VPU_HW_BTRS_LNL_CFI0_ERR_CLEAR, 0x1); + schedule_recovery = true; + } + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI1_ERR, status)) { + ivpu_err(vdev, "CFI1_ERR 0x%08x", REGB_RD32(VPU_HW_BTRS_LNL_CFI1_ERR_LOG)); + REGB_WR32(VPU_HW_BTRS_LNL_CFI1_ERR_CLEAR, 0x1); + schedule_recovery = true; + } + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR0_ERR, status)) { + ivpu_err(vdev, "IMR_ERR_CFI0 LOW: 0x%08x HIGH: 0x%08x", + REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_LOW), + REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_HIGH)); + REGB_WR32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_CLEAR, 0x1); + schedule_recovery = true; + } + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR1_ERR, status)) { + ivpu_err(vdev, "IMR_ERR_CFI1 LOW: 0x%08x HIGH: 0x%08x", + REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_LOW), + REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_HIGH)); + REGB_WR32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_CLEAR, 0x1); + schedule_recovery = true; + } + + /* This must be done after interrupts are cleared at the source. */ + REGB_WR32(VPU_HW_BTRS_LNL_INTERRUPT_STAT, status); + + if (schedule_recovery) + ivpu_pm_trigger_recovery(vdev, "Buttress IRQ"); + + return true; +} + +int ivpu_hw_btrs_dct_get_request(struct ivpu_device *vdev, bool *enable) +{ + u32 val = REGB_RD32(VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW); + u32 cmd = REG_GET_FLD(VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW, CMD, val); + u32 param1 = REG_GET_FLD(VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW, PARAM1, val); + + if (cmd != DCT_REQ) { + ivpu_err_ratelimited(vdev, "Unsupported PCODE command: 0x%x\n", cmd); + return -EBADR; + } + + switch (param1) { + case DCT_ENABLE: + *enable = true; + return 0; + case DCT_DISABLE: + *enable = false; + return 0; + default: + ivpu_err_ratelimited(vdev, "Invalid PARAM1 value: %u\n", param1); + return -EINVAL; + } +} + +void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 active_percent) +{ + u32 val = 0; + u32 cmd = enable ? DCT_ENABLE : DCT_DISABLE; + + val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, CMD, DCT_REQ, val); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, PARAM1, cmd, val); + val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, PARAM2, active_percent, val); + + REGB_WR32(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, val); +} + +static u32 pll_ratio_to_freq_mtl(u32 ratio, u32 config) +{ + u32 pll_clock = PLL_REF_CLK_FREQ * ratio; + u32 cpu_clock; + + if ((config & 0xff) == MTL_PLL_RATIO_4_3) + cpu_clock = pll_clock * 2 / 4; + else + cpu_clock = pll_clock * 2 / 5; + + return cpu_clock; +} + +u32 ivpu_hw_btrs_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) +{ + struct ivpu_hw_info *hw = vdev->hw; + + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return pll_ratio_to_freq_mtl(ratio, hw->config); + else + return PLL_RATIO_TO_FREQ(ratio); +} + +static u32 pll_freq_get_mtl(struct ivpu_device *vdev) +{ + u32 pll_curr_ratio; + + pll_curr_ratio = REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL); + pll_curr_ratio &= VPU_HW_BTRS_MTL_CURRENT_PLL_RATIO_MASK; + + if (!ivpu_is_silicon(vdev)) + return PLL_SIMULATION_FREQ; + + return pll_ratio_to_freq_mtl(pll_curr_ratio, vdev->hw->config); +} + +static u32 pll_freq_get_lnl(struct ivpu_device *vdev) +{ + u32 pll_curr_ratio; + + pll_curr_ratio = REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ); + pll_curr_ratio &= VPU_HW_BTRS_LNL_PLL_FREQ_RATIO_MASK; + + return PLL_RATIO_TO_FREQ(pll_curr_ratio); +} + +u32 ivpu_hw_btrs_pll_freq_get(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return pll_freq_get_mtl(vdev); + else + return pll_freq_get_lnl(vdev); +} + +u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return REGB_RD32(VPU_HW_BTRS_MTL_VPU_TELEMETRY_OFFSET); + else + return REGB_RD32(VPU_HW_BTRS_LNL_VPU_TELEMETRY_OFFSET); +} + +u32 ivpu_hw_btrs_telemetry_size_get(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return REGB_RD32(VPU_HW_BTRS_MTL_VPU_TELEMETRY_SIZE); + else + return REGB_RD32(VPU_HW_BTRS_LNL_VPU_TELEMETRY_SIZE); +} + +u32 ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return REGB_RD32(VPU_HW_BTRS_MTL_VPU_TELEMETRY_ENABLE); + else + return REGB_RD32(VPU_HW_BTRS_LNL_VPU_TELEMETRY_ENABLE); +} + +void ivpu_hw_btrs_global_int_disable(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x1); + else + REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x1); +} + +void ivpu_hw_btrs_global_int_enable(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x0); + else + REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x0); +} + +void ivpu_hw_btrs_irq_enable(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) { + REGB_WR32(VPU_HW_BTRS_MTL_LOCAL_INT_MASK, (u32)(~BTRS_MTL_IRQ_MASK)); + REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x0); + } else { + REGB_WR32(VPU_HW_BTRS_LNL_LOCAL_INT_MASK, (u32)(~BTRS_LNL_IRQ_MASK)); + REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x0); + } +} + +void ivpu_hw_btrs_irq_disable(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) { + REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x1); + REGB_WR32(VPU_HW_BTRS_MTL_LOCAL_INT_MASK, BTRS_IRQ_DISABLE_MASK); + } else { + REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x1); + REGB_WR32(VPU_HW_BTRS_LNL_LOCAL_INT_MASK, BTRS_IRQ_DISABLE_MASK); + } +} + +static void diagnose_failure_mtl(struct ivpu_device *vdev) +{ + u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_MTL_IRQ_MASK; + + if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR, reg)) + ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_HW_BTRS_MTL_ATS_ERR_LOG_0)); + + if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, UFI_ERR, reg)) { + u32 log = REGB_RD32(VPU_HW_BTRS_MTL_UFI_ERR_LOG); + + ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx", + log, REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, OPCODE, log), + REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, AXI_ID, log), + REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, CQ_ID, log)); + } +} + +static void diagnose_failure_lnl(struct ivpu_device *vdev) +{ + u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK; + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, reg)) { + ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n", + REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG1), + REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG2)); + } + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI0_ERR, reg)) + ivpu_err(vdev, "CFI0_ERR_LOG 0x%08x\n", REGB_RD32(VPU_HW_BTRS_LNL_CFI0_ERR_LOG)); + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI1_ERR, reg)) + ivpu_err(vdev, "CFI1_ERR_LOG 0x%08x\n", REGB_RD32(VPU_HW_BTRS_LNL_CFI1_ERR_LOG)); + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR0_ERR, reg)) + ivpu_err(vdev, "IMR_ERR_CFI0 LOW: 0x%08x HIGH: 0x%08x\n", + REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_LOW), + REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_HIGH)); + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR1_ERR, reg)) + ivpu_err(vdev, "IMR_ERR_CFI1 LOW: 0x%08x HIGH: 0x%08x\n", + REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_LOW), + REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_HIGH)); + + if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, reg)) + ivpu_err(vdev, "Survivability IRQ\n"); +} + +void ivpu_hw_btrs_diagnose_failure(struct ivpu_device *vdev) +{ + if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) + return diagnose_failure_mtl(vdev); + else + return diagnose_failure_lnl(vdev); +} diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.h b/drivers/accel/ivpu/ivpu_hw_btrs.h new file mode 100644 index 000000000000..04f14f50fed6 --- /dev/null +++ b/drivers/accel/ivpu/ivpu_hw_btrs.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2020-2024 Intel Corporation + */ + +#ifndef __IVPU_HW_BTRS_H__ +#define __IVPU_HW_BTRS_H__ + +#include "ivpu_drv.h" +#include "ivpu_hw_37xx_reg.h" +#include "ivpu_hw_40xx_reg.h" +#include "ivpu_hw_reg_io.h" + +#define PLL_PROFILING_FREQ_DEFAULT 38400000 +#define PLL_PROFILING_FREQ_HIGH 400000000 +#define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ) + +#define DCT_DEFAULT_ACTIVE_PERCENT 15u +#define DCT_PERIOD_US 35300u + +int ivpu_hw_btrs_info_init(struct ivpu_device *vdev); +void ivpu_hw_btrs_freq_ratios_init(struct ivpu_device *vdev); +int ivpu_hw_btrs_irqs_clear_with_0_mtl(struct ivpu_device *vdev); +int ivpu_hw_btrs_wp_drive(struct ivpu_device *vdev, bool enable); +int ivpu_hw_btrs_wait_for_clock_res_own_ack(struct ivpu_device *vdev); +int ivpu_hw_btrs_d0i3_enable(struct ivpu_device *vdev); +int ivpu_hw_btrs_d0i3_disable(struct ivpu_device *vdev); +void ivpu_hw_btrs_set_port_arbitration_weights_lnl(struct ivpu_device *vdev); +bool ivpu_hw_btrs_is_idle(struct ivpu_device *vdev); +int ivpu_hw_btrs_wait_for_idle(struct ivpu_device *vdev); +int ivpu_hw_btrs_ip_reset(struct ivpu_device *vdev); +void ivpu_hw_btrs_profiling_freq_reg_set_lnl(struct ivpu_device *vdev); +void ivpu_hw_btrs_ats_print_lnl(struct ivpu_device *vdev); +void ivpu_hw_btrs_clock_relinquish_disable_lnl(struct ivpu_device *vdev); +bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq); +bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq); +int ivpu_hw_btrs_dct_get_request(struct ivpu_device *vdev, bool *enable); +void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 dct_percent); +u32 ivpu_hw_btrs_pll_freq_get(struct ivpu_device *vdev); +u32 ivpu_hw_btrs_ratio_to_freq(struct ivpu_device *vdev, u32 ratio); +u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev); +u32 ivpu_hw_btrs_telemetry_size_get(struct ivpu_device *vdev); +u32 ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device *vdev); +void ivpu_hw_btrs_global_int_enable(struct ivpu_device *vdev); +void ivpu_hw_btrs_global_int_disable(struct ivpu_device *vdev); +void ivpu_hw_btrs_irq_enable(struct ivpu_device *vdev); +void ivpu_hw_btrs_irq_disable(struct ivpu_device *vdev); +void ivpu_hw_btrs_diagnose_failure(struct ivpu_device *vdev); + +#endif /* __IVPU_HW_BTRS_H__ */ diff --git a/drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h b/drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h new file mode 100644 index 000000000000..fc51f3098f97 --- /dev/null +++ b/drivers/accel/ivpu/ivpu_hw_btrs_lnl_reg.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2020-2024 Intel Corporation + */ + +#ifndef __IVPU_HW_BTRS_LNL_REG_H__ +#define __IVPU_HW_BTRS_LNL_REG_H__ + +#include <linux/bits.h> + +#define VPU_HW_BTRS_LNL_INTERRUPT_STAT 0x00000000u +#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0) +#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1) +#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_CFI0_ERR_MASK BIT_MASK(2) +#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_CFI1_ERR_MASK BIT_MASK(3) +#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_IMR0_ERR_MASK BIT_MASK(4) +#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_IMR1_ERR_MASK BIT_MASK(5) +#define VPU_HW_BTRS_LNL_INTERRUPT_STAT_SURV_ERR_MASK BIT_MASK(6) + +#define VPU_HW_BTRS_LNL_LOCAL_INT_MASK 0x00000004u +#define VPU_HW_BTRS_LNL_GLOBAL_INT_MASK 0x00000008u + +#define VPU_HW_BTRS_LNL_HM_ATS 0x0000000cu + +#define VPU_HW_BTRS_LNL_ATS_ERR_LOG1 0x00000010u +#define VPU_HW_BTRS_LNL_ATS_ERR_LOG2 0x00000014u +#define VPU_HW_BTRS_LNL_ATS_ERR_CLEAR 0x00000018u + +#define VPU_HW_BTRS_LNL_CFI0_ERR_LOG 0x0000001cu +#define VPU_HW_BTRS_LNL_CFI0_ERR_CLEAR 0x00000020u + +#define VPU_HW_BTRS_LNL_PORT_ARBITRATION_WEIGHTS_ATS 0x00000024u + +#define VPU_HW_BTRS_LNL_CFI1_ERR_LOG 0x00000040u +#define VPU_HW_BTRS_LNL_CFI1_ERR_CLEAR 0x00000044u + +#define VPU_HW_BTRS_LNL_IMR_ERR_CFI0_LOW 0x00000048u +#define VPU_HW_BTRS_LNL_IMR_ERR_CFI0_HIGH 0x0000004cu +#define VPU_HW_BTRS_LNL_IMR_ERR_CFI0_CLEAR 0x00000050u + +#define VPU_HW_BTRS_LNL_PORT_ARBITRATION_WEIGHTS 0x00000054u + +#define VPU_HW_BTRS_LNL_IMR_ERR_CFI1_LOW 0x00000058u +#define VPU_HW_BTRS_LNL_IMR_ERR_CFI1_HIGH 0x0000005cu +#define VPU_HW_BTRS_LNL_IMR_ERR_CFI1_CLEAR 0x00000060u + +#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS 0x00000070u +#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS_CMD_MASK GENMASK(7, 0) +#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS_PARAM1_MASK GENMASK(15, 8) +#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS_PARAM2_MASK GENMASK(23, 16) +#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS_PARAM3_MASK GENMASK(31, 24) + +#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW 0x00000074u +#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW_CMD_MASK GENMASK(7, 0) +#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW_PARAM1_MASK GENMASK(15, 8) +#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW_PARAM2_MASK GENMASK(23, 16) +#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW_PARAM3_MASK GENMASK(31, 24) + +#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0 0x00000130u +#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0) +#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16) + +#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1 0x00000134u +#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0) +#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16) + +#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2 0x00000138u +#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0) +#define VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2_CDYN_MASK GENMASK(31, 16) + +#define VPU_HW_BTRS_LNL_WP_REQ_CMD 0x0000013cu +#define VPU_HW_BTRS_LNL_WP_REQ_CMD_SEND_MASK BIT_MASK(0) + +#define VPU_HW_BTRS_LNL_PLL_FREQ 0x00000148u +#define VPU_HW_BTRS_LNL_PLL_FREQ_RATIO_MASK GENMASK(15, 0) + +#define VPU_HW_BTRS_LNL_TILE_FUSE 0x00000150u +#define VPU_HW_BTRS_LNL_TILE_FUSE_VALID_MASK BIT_MASK(0) +#define VPU_HW_BTRS_LNL_TILE_FUSE_CONFIG_MASK GENMASK(6, 1) + +#define VPU_HW_BTRS_LNL_VPU_STATUS 0x00000154u +#define VPU_HW_BTRS_LNL_VPU_STATUS_READY_MASK BIT_MASK(0) +#define VPU_HW_BTRS_LNL_VPU_STATUS_IDLE_MASK BIT_MASK(1) +#define VPU_HW_BTRS_LNL_VPU_STATUS_DUP_IDLE_MASK BIT_MASK(2) +#define VPU_HW_BTRS_LNL_VPU_STATUS_CLOCK_RESOURCE_OWN_ACK_MASK BIT_MASK(6) +#define VPU_HW_BTRS_LNL_VPU_STATUS_POWER_RESOURCE_OWN_ACK_MASK BIT_MASK(7) +#define VPU_HW_BTRS_LNL_VPU_STATUS_PERF_CLK_MASK BIT_MASK(11) +#define VPU_HW_BTRS_LNL_VPU_STATUS_DISABLE_CLK_RELINQUISH_MASK BIT_MASK(12) + +#define VPU_HW_BTRS_LNL_IP_RESET 0x00000160u +#define VPU_HW_BTRS_LNL_IP_RESET_TRIGGER_MASK BIT_MASK(0) + +#define VPU_HW_BTRS_LNL_D0I3_CONTROL 0x00000164u +#define VPU_HW_BTRS_LNL_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0) +#define VPU_HW_BTRS_LNL_D0I3_CONTROL_I3_MASK BIT_MASK(2) + +#define VPU_HW_BTRS_LNL_VPU_TELEMETRY_OFFSET 0x00000168u +#define VPU_HW_BTRS_LNL_VPU_TELEMETRY_SIZE 0x0000016cu +#define VPU_HW_BTRS_LNL_VPU_TELEMETRY_ENABLE 0x00000170u + +#define VPU_HW_BTRS_LNL_FMIN_FUSE 0x00000174u +#define VPU_HW_BTRS_LNL_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0) +#define VPU_HW_BTRS_LNL_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8) + +#define VPU_HW_BTRS_LNL_FMAX_FUSE 0x00000178u +#define VPU_HW_BTRS_LNL_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0) + +#endif /* __IVPU_HW_BTRS_LNL_REG_H__ */ diff --git a/drivers/accel/ivpu/ivpu_hw_btrs_mtl_reg.h b/drivers/accel/ivpu/ivpu_hw_btrs_mtl_reg.h new file mode 100644 index 000000000000..e93d539e066f --- /dev/null +++ b/drivers/accel/ivpu/ivpu_hw_btrs_mtl_reg.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2020-2023 Intel Corporation + */ + +#ifndef __IVPU_HW_BTRS_MTL_REG_H__ +#define __IVPU_HW_BTRS_MTL_REG_H__ + +#include <linux/bits.h> + +#define VPU_HW_BTRS_MTL_INTERRUPT_TYPE 0x00000000u + +#define VPU_HW_BTRS_MTL_INTERRUPT_STAT 0x00000004u +#define VPU_HW_BTRS_MTL_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0) +#define VPU_HW_BTRS_MTL_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1) +#define VPU_HW_BTRS_MTL_INTERRUPT_STAT_UFI_ERR_MASK BIT_MASK(2) + +#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0 0x00000008u +#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0) +#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16) + +#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1 0x0000000cu +#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0) +#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16) + +#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2 0x00000010u +#define VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0) + +#define VPU_HW_BTRS_MTL_WP_REQ_CMD 0x00000014u +#define VPU_HW_BTRS_MTL_WP_REQ_CMD_SEND_MASK BIT_MASK(0) + +#define VPU_HW_BTRS_MTL_WP_DOWNLOAD 0x00000018u +#define VPU_HW_BTRS_MTL_WP_DOWNLOAD_TARGET_RATIO_MASK GENMASK(15, 0) + +#define VPU_HW_BTRS_MTL_CURRENT_PLL 0x0000001cu +#define VPU_HW_BTRS_MTL_CURRENT_PLL_RATIO_MASK GENMASK(15, 0) + +#define VPU_HW_BTRS_MTL_PLL_ENABLE 0x00000020u + +#define VPU_HW_BTRS_MTL_FMIN_FUSE 0x00000024u +#define VPU_HW_BTRS_MTL_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0) +#define VPU_HW_BTRS_MTL_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8) + +#define VPU_HW_BTRS_MTL_FMAX_FUSE 0x00000028u +#define VPU_HW_BTRS_MTL_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0) + +#define VPU_HW_BTRS_MTL_TILE_FUSE 0x0000002cu +#define VPU_HW_BTRS_MTL_TILE_FUSE_VALID_MASK BIT_MASK(0) +#define VPU_HW_BTRS_MTL_TILE_FUSE_SKU_MASK GENMASK(3, 2) + +#define VPU_HW_BTRS_MTL_LOCAL_INT_MASK 0x00000030u +#define VPU_HW_BTRS_MTL_GLOBAL_INT_MASK 0x00000034u + +#define VPU_HW_BTRS_MTL_PLL_STATUS 0x00000040u +#define VPU_HW_BTRS_MTL_PLL_STATUS_LOCK_MASK BIT_MASK(1) + +#define VPU_HW_BTRS_MTL_VPU_STATUS 0x00000044u +#define VPU_HW_BTRS_MTL_VPU_STATUS_READY_MASK BIT_MASK(0) +#define VPU_HW_BTRS_MTL_VPU_STATUS_IDLE_MASK BIT_MASK(1) + +#define VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL 0x00000060u +#define VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0) +#define VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL_I3_MASK BIT_MASK(2) + +#define VPU_HW_BTRS_MTL_VPU_IP_RESET 0x00000050u +#define VPU_HW_BTRS_MTL_VPU_IP_RESET_TRIGGER_MASK BIT_MASK(0) + +#define VPU_HW_BTRS_MTL_VPU_TELEMETRY_OFFSET 0x00000080u +#define VPU_HW_BTRS_MTL_VPU_TELEMETRY_SIZE 0x00000084u +#define VPU_HW_BTRS_MTL_VPU_TELEMETRY_ENABLE 0x00000088u + +#define VPU_HW_BTRS_MTL_ATS_ERR_LOG_0 0x000000a0u +#define VPU_HW_BTRS_MTL_ATS_ERR_LOG_1 0x000000a4u +#define VPU_HW_BTRS_MTL_ATS_ERR_CLEAR 0x000000a8u + +#define VPU_HW_BTRS_MTL_UFI_ERR_LOG 0x000000b0u +#define VPU_HW_BTRS_MTL_UFI_ERR_LOG_CQ_ID_MASK GENMASK(11, 0) +#define VPU_HW_BTRS_MTL_UFI_ERR_LOG_AXI_ID_MASK GENMASK(19, 12) +#define VPU_HW_BTRS_MTL_UFI_ERR_LOG_OPCODE_MASK GENMASK(24, 20) + +#define VPU_HW_BTRS_MTL_UFI_ERR_CLEAR 0x000000b4u + +#endif /* __IVPU_HW_BTRS_MTL_REG_H__ */ diff --git a/drivers/accel/ivpu/ivpu_hw_ip.c b/drivers/accel/ivpu/ivpu_hw_ip.c new file mode 100644 index 000000000000..dfd2f4a5b526 --- /dev/null +++ b/drivers/accel/ivpu/ivpu_hw_ip.c @@ -0,0 +1,1174 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020-2024 Intel Corporation + */ + +#include "ivpu_drv.h" +#include "ivpu_fw.h" +#include "ivpu_hw.h" +#include "ivpu_hw_37xx_reg.h" +#include "ivpu_hw_40xx_reg.h" +#include "ivpu_hw_ip.h" +#include "ivpu_hw_reg_io.h" +#include "ivpu_mmu.h" +#include "ivpu_pm.h" + +#define PWR_ISLAND_EN_POST_DLY_FREQ_DEFAULT 0 +#define PWR_ISLAND_EN_POST_DLY_FREQ_HIGH 18 +#define PWR_ISLAND_STATUS_DLY_FREQ_DEFAULT 3 +#define PWR_ISLAND_STATUS_DLY_FREQ_HIGH 46 +#define PWR_ISLAND_STATUS_TIMEOUT_US (5 * USEC_PER_MSEC) + +#define TIM_SAFE_ENABLE 0xf1d0dead +#define TIM_WATCHDOG_RESET_VALUE 0xffffffff + +#define ICB_0_IRQ_MASK_37XX ((REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT)) | \ + (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT)) | \ + (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT)) | \ + (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT)) | \ + (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT)) | \ + (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT)) | \ + (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT))) + +#define ICB_1_IRQ_MASK_37XX ((REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_2_INT)) | \ + (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_3_INT)) | \ + (REG_FLD(VPU_37XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_4_INT))) + +#define ICB_0_1_IRQ_MASK_37XX ((((u64)ICB_1_IRQ_MASK_37XX) << 32) | ICB_0_IRQ_MASK_37XX) + +#define ICB_0_IRQ_MASK_40XX ((REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT)) | \ + (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT)) | \ + (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT)) | \ + (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT)) | \ + (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT)) | \ + (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT)) | \ + (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT))) + +#define ICB_1_IRQ_MASK_40XX ((REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_2_INT)) | \ + (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_3_INT)) | \ + (REG_FLD(VPU_40XX_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_4_INT))) + +#define ICB_0_1_IRQ_MASK_40XX ((((u64)ICB_1_IRQ_MASK_40XX) << 32) | ICB_0_IRQ_MASK_40XX) + +#define ITF_FIREWALL_VIOLATION_MASK_37XX ((REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_ROM_CMX)) | \ + (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_DBG)) | \ + (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, CSS_CTRL)) | \ + (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, DEC400)) | \ + (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_NCE)) | \ + (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \ + (REG_FLD(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX))) + +#define ITF_FIREWALL_VIOLATION_MASK_40XX ((REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_ROM_CMX)) | \ + (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_DBG)) | \ + (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, CSS_CTRL)) | \ + (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, DEC400)) | \ + (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_NCE)) | \ + (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \ + (REG_FLD(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX))) + +static int wait_for_ip_bar(struct ivpu_device *vdev) +{ + return REGV_POLL_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, AON, 0, 100); +} + +static void host_ss_rst_clr(struct ivpu_device *vdev) +{ + u32 val = 0; + + val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, TOP_NOC, val); + val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, DSS_MAS, val); + val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_CLR, MSS_MAS, val); + + REGV_WR32(VPU_37XX_HOST_SS_CPR_RST_CLR, val); +} + +static int host_ss_noc_qreqn_check_37xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QREQN); + + if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, exp_val, val)) + return -EIO; + + return 0; +} + +static int host_ss_noc_qreqn_check_40xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QREQN); + + if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, exp_val, val)) + return -EIO; + + return 0; +} + +static int host_ss_noc_qreqn_check(struct ivpu_device *vdev, u32 exp_val) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return host_ss_noc_qreqn_check_37xx(vdev, exp_val); + else + return host_ss_noc_qreqn_check_40xx(vdev, exp_val); +} + +static int host_ss_noc_qacceptn_check_37xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QACCEPTN); + + if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QACCEPTN, TOP_SOCMMIO, exp_val, val)) + return -EIO; + + return 0; +} + +static int host_ss_noc_qacceptn_check_40xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QACCEPTN); + + if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QACCEPTN, TOP_SOCMMIO, exp_val, val)) + return -EIO; + + return 0; +} + +static int host_ss_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return host_ss_noc_qacceptn_check_37xx(vdev, exp_val); + else + return host_ss_noc_qacceptn_check_40xx(vdev, exp_val); +} + +static int host_ss_noc_qdeny_check_37xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QDENY); + + if (!REG_TEST_FLD_NUM(VPU_37XX_HOST_SS_NOC_QDENY, TOP_SOCMMIO, exp_val, val)) + return -EIO; + + return 0; +} + +static int host_ss_noc_qdeny_check_40xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QDENY); + + if (!REG_TEST_FLD_NUM(VPU_40XX_HOST_SS_NOC_QDENY, TOP_SOCMMIO, exp_val, val)) + return -EIO; + + return 0; +} + +static int host_ss_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return host_ss_noc_qdeny_check_37xx(vdev, exp_val); + else + return host_ss_noc_qdeny_check_40xx(vdev, exp_val); +} + +static int top_noc_qrenqn_check_37xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN); + + if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val)) + return -EIO; + + return 0; +} + +static int top_noc_qrenqn_check_40xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QREQN); + + if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val)) + return -EIO; + + return 0; +} + +static int top_noc_qreqn_check(struct ivpu_device *vdev, u32 exp_val) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return top_noc_qrenqn_check_37xx(vdev, exp_val); + else + return top_noc_qrenqn_check_40xx(vdev, exp_val); +} + +int ivpu_hw_ip_host_ss_configure(struct ivpu_device *vdev) +{ + int ret; + + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) { + ret = wait_for_ip_bar(vdev); + if (ret) { + ivpu_err(vdev, "Timed out waiting for NPU IP bar\n"); + return ret; + } + host_ss_rst_clr(vdev); + } + + ret = host_ss_noc_qreqn_check(vdev, 0x0); + if (ret) { + ivpu_err(vdev, "Failed qreqn check: %d\n", ret); + return ret; + } + + ret = host_ss_noc_qacceptn_check(vdev, 0x0); + if (ret) { + ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); + return ret; + } + + ret = host_ss_noc_qdeny_check(vdev, 0x0); + if (ret) + ivpu_err(vdev, "Failed qdeny check %d\n", ret); + + return ret; +} + +static void idle_gen_drive_37xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN); + + if (enable) + val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN, EN, val); + else + val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN, EN, val); + + REGV_WR32(VPU_37XX_HOST_SS_AON_VPU_IDLE_GEN, val); +} + +static void idle_gen_drive_40xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_IDLE_GEN); + + if (enable) + val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_IDLE_GEN, EN, val); + else + val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_IDLE_GEN, EN, val); + + REGV_WR32(VPU_40XX_HOST_SS_AON_IDLE_GEN, val); +} + +void ivpu_hw_ip_idle_gen_enable(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + idle_gen_drive_37xx(vdev, true); + else + idle_gen_drive_40xx(vdev, true); +} + +void ivpu_hw_ip_idle_gen_disable(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + idle_gen_drive_37xx(vdev, false); + else + idle_gen_drive_40xx(vdev, false); +} + +static void pwr_island_delay_set_50xx(struct ivpu_device *vdev) +{ + u32 val, post, status; + + if (vdev->hw->pll.profiling_freq == PLL_PROFILING_FREQ_DEFAULT) { + post = PWR_ISLAND_EN_POST_DLY_FREQ_DEFAULT; + status = PWR_ISLAND_STATUS_DLY_FREQ_DEFAULT; + } else { + post = PWR_ISLAND_EN_POST_DLY_FREQ_HIGH; + status = PWR_ISLAND_STATUS_DLY_FREQ_HIGH; + } + + val = REGV_RD32(VPU_50XX_HOST_SS_AON_PWR_ISLAND_EN_POST_DLY); + val = REG_SET_FLD_NUM(VPU_50XX_HOST_SS_AON_PWR_ISLAND_EN_POST_DLY, POST_DLY, post, val); + REGV_WR32(VPU_50XX_HOST_SS_AON_PWR_ISLAND_EN_POST_DLY, val); + + val = REGV_RD32(VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY); + val = REG_SET_FLD_NUM(VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY, STATUS_DLY, status, val); + REGV_WR32(VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY, val); +} + +static void pwr_island_trickle_drive_37xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0); + + if (enable) + val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val); + else + val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val); + + REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, val); +} + +static void pwr_island_trickle_drive_40xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0); + + if (enable) + val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, CSS_CPU, val); + else + val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, CSS_CPU, val); + + REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, val); + + if (enable) + ndelay(500); +} + +static void pwr_island_drive_37xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0); + + if (enable) + val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, CSS_CPU, val); + else + val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, CSS_CPU, val); + + REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISLAND_EN0, val); + + if (!enable) + ndelay(500); +} + +static void pwr_island_drive_40xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0); + + if (enable) + val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val); + else + val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val); + + REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0, val); +} + +static void pwr_island_enable(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) { + pwr_island_trickle_drive_37xx(vdev, true); + pwr_island_drive_37xx(vdev, true); + } else { + pwr_island_trickle_drive_40xx(vdev, true); + pwr_island_drive_40xx(vdev, true); + } +} + +static int wait_for_pwr_island_status(struct ivpu_device *vdev, u32 exp_val) +{ + if (IVPU_WA(punit_disabled)) + return 0; + + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return REGV_POLL_FLD(VPU_37XX_HOST_SS_AON_PWR_ISLAND_STATUS0, MSS_CPU, exp_val, + PWR_ISLAND_STATUS_TIMEOUT_US); + else + return REGV_POLL_FLD(VPU_40XX_HOST_SS_AON_PWR_ISLAND_STATUS0, CSS_CPU, exp_val, + PWR_ISLAND_STATUS_TIMEOUT_US); +} + +static void pwr_island_isolation_drive_37xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0); + + if (enable) + val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val); + else + val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val); + + REGV_WR32(VPU_37XX_HOST_SS_AON_PWR_ISO_EN0, val); +} + +static void pwr_island_isolation_drive_40xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0); + + if (enable) + val = REG_SET_FLD(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, CSS_CPU, val); + else + val = REG_CLR_FLD(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, CSS_CPU, val); + + REGV_WR32(VPU_40XX_HOST_SS_AON_PWR_ISO_EN0, val); +} + +static void pwr_island_isolation_drive(struct ivpu_device *vdev, bool enable) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + pwr_island_isolation_drive_37xx(vdev, enable); + else + pwr_island_isolation_drive_40xx(vdev, enable); +} + +static void pwr_island_isolation_disable(struct ivpu_device *vdev) +{ + pwr_island_isolation_drive(vdev, false); +} + +static void host_ss_clk_drive_37xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_CPR_CLK_SET); + + if (enable) { + val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, TOP_NOC, val); + val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, DSS_MAS, val); + val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, MSS_MAS, val); + } else { + val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, TOP_NOC, val); + val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, DSS_MAS, val); + val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_CLK_SET, MSS_MAS, val); + } + + REGV_WR32(VPU_37XX_HOST_SS_CPR_CLK_SET, val); +} + +static void host_ss_clk_drive_40xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_SS_CPR_CLK_EN); + + if (enable) { + val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, TOP_NOC, val); + val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, DSS_MAS, val); + val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, CSS_MAS, val); + } else { + val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, TOP_NOC, val); + val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, DSS_MAS, val); + val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_CLK_EN, CSS_MAS, val); + } + + REGV_WR32(VPU_40XX_HOST_SS_CPR_CLK_EN, val); +} + +static void host_ss_clk_drive(struct ivpu_device *vdev, bool enable) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + host_ss_clk_drive_37xx(vdev, enable); + else + host_ss_clk_drive_40xx(vdev, enable); +} + +static void host_ss_clk_enable(struct ivpu_device *vdev) +{ + host_ss_clk_drive(vdev, true); +} + +static void host_ss_rst_drive_37xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_CPR_RST_SET); + + if (enable) { + val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, TOP_NOC, val); + val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, DSS_MAS, val); + val = REG_SET_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, MSS_MAS, val); + } else { + val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, TOP_NOC, val); + val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, DSS_MAS, val); + val = REG_CLR_FLD(VPU_37XX_HOST_SS_CPR_RST_SET, MSS_MAS, val); + } + + REGV_WR32(VPU_37XX_HOST_SS_CPR_RST_SET, val); +} + +static void host_ss_rst_drive_40xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_SS_CPR_RST_EN); + + if (enable) { + val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, TOP_NOC, val); + val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, DSS_MAS, val); + val = REG_SET_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, CSS_MAS, val); + } else { + val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, TOP_NOC, val); + val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, DSS_MAS, val); + val = REG_CLR_FLD(VPU_40XX_HOST_SS_CPR_RST_EN, CSS_MAS, val); + } + + REGV_WR32(VPU_40XX_HOST_SS_CPR_RST_EN, val); +} + +static void host_ss_rst_drive(struct ivpu_device *vdev, bool enable) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + host_ss_rst_drive_37xx(vdev, enable); + else + host_ss_rst_drive_40xx(vdev, enable); +} + +static void host_ss_rst_enable(struct ivpu_device *vdev) +{ + host_ss_rst_drive(vdev, true); +} + +static void host_ss_noc_qreqn_top_socmmio_drive_37xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_NOC_QREQN); + + if (enable) + val = REG_SET_FLD(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); + else + val = REG_CLR_FLD(VPU_37XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); + REGV_WR32(VPU_37XX_HOST_SS_NOC_QREQN, val); +} + +static void host_ss_noc_qreqn_top_socmmio_drive_40xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_SS_NOC_QREQN); + + if (enable) + val = REG_SET_FLD(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); + else + val = REG_CLR_FLD(VPU_40XX_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); + REGV_WR32(VPU_40XX_HOST_SS_NOC_QREQN, val); +} + +static void host_ss_noc_qreqn_top_socmmio_drive(struct ivpu_device *vdev, bool enable) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + host_ss_noc_qreqn_top_socmmio_drive_37xx(vdev, enable); + else + host_ss_noc_qreqn_top_socmmio_drive_40xx(vdev, enable); +} + +static int host_ss_axi_drive(struct ivpu_device *vdev, bool enable) +{ + int ret; + + host_ss_noc_qreqn_top_socmmio_drive(vdev, enable); + + ret = host_ss_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); + if (ret) { + ivpu_err(vdev, "Failed HOST SS NOC QACCEPTN check: %d\n", ret); + return ret; + } + + ret = host_ss_noc_qdeny_check(vdev, 0x0); + if (ret) + ivpu_err(vdev, "Failed HOST SS NOC QDENY check: %d\n", ret); + + return ret; +} + +static void top_noc_qreqn_drive_40xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QREQN); + + if (enable) { + val = REG_SET_FLD(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, val); + val = REG_SET_FLD(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); + } else { + val = REG_CLR_FLD(VPU_40XX_TOP_NOC_QREQN, CPU_CTRL, val); + val = REG_CLR_FLD(VPU_40XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); + } + + REGV_WR32(VPU_40XX_TOP_NOC_QREQN, val); +} + +static void top_noc_qreqn_drive_37xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN); + + if (enable) { + val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val); + val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); + } else { + val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val); + val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); + } + + REGV_WR32(VPU_37XX_TOP_NOC_QREQN, val); +} + +static void top_noc_qreqn_drive(struct ivpu_device *vdev, bool enable) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + top_noc_qreqn_drive_37xx(vdev, enable); + else + top_noc_qreqn_drive_40xx(vdev, enable); +} + +int ivpu_hw_ip_host_ss_axi_enable(struct ivpu_device *vdev) +{ + return host_ss_axi_drive(vdev, true); +} + +static int top_noc_qacceptn_check_37xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QACCEPTN); + + if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val)) + return -EIO; + + return 0; +} + +static int top_noc_qacceptn_check_40xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QACCEPTN); + + if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val)) + return -EIO; + + return 0; +} + +static int top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return top_noc_qacceptn_check_37xx(vdev, exp_val); + else + return top_noc_qacceptn_check_40xx(vdev, exp_val); +} + +static int top_noc_qdeny_check_37xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QDENY); + + if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val)) + return -EIO; + + return 0; +} + +static int top_noc_qdeny_check_40xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_40XX_TOP_NOC_QDENY); + + if (!REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_40XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val)) + return -EIO; + + return 0; +} + +static int top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return top_noc_qdeny_check_37xx(vdev, exp_val); + else + return top_noc_qdeny_check_40xx(vdev, exp_val); +} + +static int top_noc_drive(struct ivpu_device *vdev, bool enable) +{ + int ret; + + top_noc_qreqn_drive(vdev, enable); + + ret = top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); + if (ret) { + ivpu_err(vdev, "Failed TOP NOC QACCEPTN check: %d\n", ret); + return ret; + } + + ret = top_noc_qdeny_check(vdev, 0x0); + if (ret) + ivpu_err(vdev, "Failed TOP NOC QDENY check: %d\n", ret); + + return ret; +} + +int ivpu_hw_ip_top_noc_enable(struct ivpu_device *vdev) +{ + return top_noc_drive(vdev, true); +} + +static void dpu_active_drive_37xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_SS_AON_DPU_ACTIVE); + + if (enable) + val = REG_SET_FLD(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val); + else + val = REG_CLR_FLD(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val); + + REGV_WR32(VPU_37XX_HOST_SS_AON_DPU_ACTIVE, val); +} + +int ivpu_hw_ip_pwr_domain_enable(struct ivpu_device *vdev) +{ + int ret; + + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_50XX) + pwr_island_delay_set_50xx(vdev); + + pwr_island_enable(vdev); + + ret = wait_for_pwr_island_status(vdev, 0x1); + if (ret) { + ivpu_err(vdev, "Timed out waiting for power island status\n"); + return ret; + } + + ret = top_noc_qreqn_check(vdev, 0x0); + if (ret) { + ivpu_err(vdev, "Failed TOP NOC QREQN check %d\n", ret); + return ret; + } + + host_ss_clk_enable(vdev); + pwr_island_isolation_disable(vdev); + host_ss_rst_enable(vdev); + + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + dpu_active_drive_37xx(vdev, true); + + return ret; +} + +u64 ivpu_hw_ip_read_perf_timer_counter(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return REGV_RD64(VPU_37XX_CPU_SS_TIM_PERF_FREE_CNT); + else + return REGV_RD64(VPU_40XX_CPU_SS_TIM_PERF_EXT_FREE_CNT); +} + +static void ivpu_hw_ip_snoop_disable_37xx(struct ivpu_device *vdev) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES); + + val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, NOSNOOP_OVERRIDE_EN, val); + val = REG_CLR_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val); + + if (ivpu_is_force_snoop_enabled(vdev)) + val = REG_CLR_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val); + else + val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val); + + REGV_WR32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, val); +} + +static void ivpu_hw_ip_snoop_disable_40xx(struct ivpu_device *vdev) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES); + + val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, SNOOP_OVERRIDE_EN, val); + val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AW_SNOOP_OVERRIDE, val); + + if (ivpu_is_force_snoop_enabled(vdev)) + val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AR_SNOOP_OVERRIDE, val); + else + val = REG_CLR_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AR_SNOOP_OVERRIDE, val); + + REGV_WR32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, val); +} + +void ivpu_hw_ip_snoop_disable(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return ivpu_hw_ip_snoop_disable_37xx(vdev); + else + return ivpu_hw_ip_snoop_disable_40xx(vdev); +} + +static void ivpu_hw_ip_tbu_mmu_enable_37xx(struct ivpu_device *vdev) +{ + u32 val = REGV_RD32(VPU_37XX_HOST_IF_TBU_MMUSSIDV); + + val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val); + val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val); + val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val); + val = REG_SET_FLD(VPU_37XX_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val); + + REGV_WR32(VPU_37XX_HOST_IF_TBU_MMUSSIDV, val); +} + +static void ivpu_hw_ip_tbu_mmu_enable_40xx(struct ivpu_device *vdev) +{ + u32 val = REGV_RD32(VPU_40XX_HOST_IF_TBU_MMUSSIDV); + + val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val); + val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val); + val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU1_AWMMUSSIDV, val); + val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU1_ARMMUSSIDV, val); + val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val); + val = REG_SET_FLD(VPU_40XX_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val); + + REGV_WR32(VPU_40XX_HOST_IF_TBU_MMUSSIDV, val); +} + +void ivpu_hw_ip_tbu_mmu_enable(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return ivpu_hw_ip_tbu_mmu_enable_37xx(vdev); + else + return ivpu_hw_ip_tbu_mmu_enable_40xx(vdev); +} + +static int soc_cpu_boot_37xx(struct ivpu_device *vdev) +{ + u32 val; + + val = REGV_RD32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC); + val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val); + + val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val); + REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); + + val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); + REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); + + val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); + REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); + + val = vdev->fw->entry_point >> 9; + REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val); + + val = REG_SET_FLD(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, DONE, val); + REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val); + + ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n", + vdev->fw->entry_point == vdev->fw->cold_boot_entry_point ? "cold boot" : "resume"); + + return 0; +} + +static int cpu_noc_qacceptn_check_40xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QACCEPTN); + + if (!REG_TEST_FLD_NUM(VPU_40XX_CPU_SS_CPR_NOC_QACCEPTN, TOP_MMIO, exp_val, val)) + return -EIO; + + return 0; +} + +static int cpu_noc_qdeny_check_40xx(struct ivpu_device *vdev, u32 exp_val) +{ + u32 val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QDENY); + + if (!REG_TEST_FLD_NUM(VPU_40XX_CPU_SS_CPR_NOC_QDENY, TOP_MMIO, exp_val, val)) + return -EIO; + + return 0; +} + +static void cpu_noc_top_mmio_drive_40xx(struct ivpu_device *vdev, bool enable) +{ + u32 val = REGV_RD32(VPU_40XX_CPU_SS_CPR_NOC_QREQN); + + if (enable) + val = REG_SET_FLD(VPU_40XX_CPU_SS_CPR_NOC_QREQN, TOP_MMIO, val); + else + val = REG_CLR_FLD(VPU_40XX_CPU_SS_CPR_NOC_QREQN, TOP_MMIO, val); + REGV_WR32(VPU_40XX_CPU_SS_CPR_NOC_QREQN, val); +} + +static int soc_cpu_drive_40xx(struct ivpu_device *vdev, bool enable) +{ + int ret; + + cpu_noc_top_mmio_drive_40xx(vdev, enable); + + ret = cpu_noc_qacceptn_check_40xx(vdev, enable ? 0x1 : 0x0); + if (ret) { + ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); + return ret; + } + + ret = cpu_noc_qdeny_check_40xx(vdev, 0x0); + if (ret) + ivpu_err(vdev, "Failed qdeny check: %d\n", ret); + + return ret; +} + +static int soc_cpu_enable(struct ivpu_device *vdev) +{ + return soc_cpu_drive_40xx(vdev, true); +} + +static int soc_cpu_boot_40xx(struct ivpu_device *vdev) +{ + int ret; + u32 val; + u64 val64; + + ret = soc_cpu_enable(vdev); + if (ret) { + ivpu_err(vdev, "Failed to enable SOC CPU: %d\n", ret); + return ret; + } + + val64 = vdev->fw->entry_point; + val64 <<= ffs(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO_IMAGE_LOCATION_MASK) - 1; + REGV_WR64(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val64); + + val = REGV_RD32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO); + val = REG_SET_FLD(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, DONE, val); + REGV_WR32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val); + + ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n", + ivpu_fw_is_cold_boot(vdev) ? "cold boot" : "resume"); + + return 0; +} + +int ivpu_hw_ip_soc_cpu_boot(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return soc_cpu_boot_37xx(vdev); + else + return soc_cpu_boot_40xx(vdev); +} + +static void wdt_disable_37xx(struct ivpu_device *vdev) +{ + u32 val; + + /* Enable writing and set non-zero WDT value */ + REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); + REGV_WR32(VPU_37XX_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE); + + /* Enable writing and disable watchdog timer */ + REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); + REGV_WR32(VPU_37XX_CPU_SS_TIM_WDOG_EN, 0); + + /* Now clear the timeout interrupt */ + val = REGV_RD32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG); + val = REG_CLR_FLD(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val); + REGV_WR32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, val); +} + +static void wdt_disable_40xx(struct ivpu_device *vdev) +{ + u32 val; + + REGV_WR32(VPU_40XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); + REGV_WR32(VPU_40XX_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE); + + REGV_WR32(VPU_40XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); + REGV_WR32(VPU_40XX_CPU_SS_TIM_WDOG_EN, 0); + + val = REGV_RD32(VPU_40XX_CPU_SS_TIM_GEN_CONFIG); + val = REG_CLR_FLD(VPU_40XX_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val); + REGV_WR32(VPU_40XX_CPU_SS_TIM_GEN_CONFIG, val); +} + +void ivpu_hw_ip_wdt_disable(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return wdt_disable_37xx(vdev); + else + return wdt_disable_40xx(vdev); +} + +static u32 ipc_rx_count_get_37xx(struct ivpu_device *vdev) +{ + u32 count = REGV_RD32_SILENT(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT); + + return REG_GET_FLD(VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count); +} + +static u32 ipc_rx_count_get_40xx(struct ivpu_device *vdev) +{ + u32 count = REGV_RD32_SILENT(VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT); + + return REG_GET_FLD(VPU_40XX_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count); +} + +u32 ivpu_hw_ip_ipc_rx_count_get(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return ipc_rx_count_get_37xx(vdev); + else + return ipc_rx_count_get_40xx(vdev); +} + +void ivpu_hw_ip_irq_enable(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) { + REGV_WR32(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, ITF_FIREWALL_VIOLATION_MASK_37XX); + REGV_WR64(VPU_37XX_HOST_SS_ICB_ENABLE_0, ICB_0_1_IRQ_MASK_37XX); + } else { + REGV_WR32(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, ITF_FIREWALL_VIOLATION_MASK_40XX); + REGV_WR64(VPU_40XX_HOST_SS_ICB_ENABLE_0, ICB_0_1_IRQ_MASK_40XX); + } +} + +void ivpu_hw_ip_irq_disable(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) { + REGV_WR64(VPU_37XX_HOST_SS_ICB_ENABLE_0, 0x0ull); + REGV_WR32(VPU_37XX_HOST_SS_FW_SOC_IRQ_EN, 0x0); + } else { + REGV_WR64(VPU_40XX_HOST_SS_ICB_ENABLE_0, 0x0ull); + REGV_WR32(VPU_40XX_HOST_SS_FW_SOC_IRQ_EN, 0x0ul); + } +} + +static void diagnose_failure_37xx(struct ivpu_device *vdev) +{ + u32 reg = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_37XX; + + if (ipc_rx_count_get_37xx(vdev)) + ivpu_err(vdev, "IPC FIFO queue not empty, missed IPC IRQ"); + + if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, reg)) + ivpu_err(vdev, "WDT MSS timeout detected\n"); + + if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, reg)) + ivpu_err(vdev, "WDT NCE timeout detected\n"); + + if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, reg)) + ivpu_err(vdev, "NOC Firewall irq detected\n"); +} + +static void diagnose_failure_40xx(struct ivpu_device *vdev) +{ + u32 reg = REGV_RD32(VPU_40XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_40XX; + + if (ipc_rx_count_get_40xx(vdev)) + ivpu_err(vdev, "IPC FIFO queue not empty, missed IPC IRQ"); + + if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, reg)) + ivpu_err(vdev, "WDT MSS timeout detected\n"); + + if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, reg)) + ivpu_err(vdev, "WDT NCE timeout detected\n"); + + if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, reg)) + ivpu_err(vdev, "NOC Firewall irq detected\n"); +} + +void ivpu_hw_ip_diagnose_failure(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + diagnose_failure_37xx(vdev); + else + diagnose_failure_40xx(vdev); +} + +void ivpu_hw_ip_irq_clear(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + REGV_WR64(VPU_37XX_HOST_SS_ICB_CLEAR_0, ICB_0_1_IRQ_MASK_37XX); + else + REGV_WR64(VPU_40XX_HOST_SS_ICB_CLEAR_0, ICB_0_1_IRQ_MASK_40XX); +} + +static void irq_wdt_nce_handler(struct ivpu_device *vdev) +{ + ivpu_pm_trigger_recovery(vdev, "WDT NCE IRQ"); +} + +static void irq_wdt_mss_handler(struct ivpu_device *vdev) +{ + ivpu_hw_ip_wdt_disable(vdev); + ivpu_pm_trigger_recovery(vdev, "WDT MSS IRQ"); +} + +static void irq_noc_firewall_handler(struct ivpu_device *vdev) +{ + ivpu_pm_trigger_recovery(vdev, "NOC Firewall IRQ"); +} + +/* Handler for IRQs from NPU core */ +bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq) +{ + u32 status = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_37XX; + + if (!status) + return false; + + REGV_WR32(VPU_37XX_HOST_SS_ICB_CLEAR_0, status); + + if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT, status)) + ivpu_mmu_irq_evtq_handler(vdev); + + if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status)) + ivpu_ipc_irq_handler(vdev); + + if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status)) + ivpu_dbg(vdev, IRQ, "MMU sync complete\n"); + + if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT, status)) + ivpu_mmu_irq_gerr_handler(vdev); + + if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, status)) + irq_wdt_mss_handler(vdev); + + if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, status)) + irq_wdt_nce_handler(vdev); + + if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, status)) + irq_noc_firewall_handler(vdev); + + return true; +} + +/* Handler for IRQs from NPU core */ +bool ivpu_hw_ip_irq_handler_40xx(struct ivpu_device *vdev, int irq) +{ + u32 status = REGV_RD32(VPU_40XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_40XX; + + if (!status) + return false; + + REGV_WR32(VPU_40XX_HOST_SS_ICB_CLEAR_0, status); + + if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT, status)) + ivpu_mmu_irq_evtq_handler(vdev); + + if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status)) + ivpu_ipc_irq_handler(vdev); + + if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status)) + ivpu_dbg(vdev, IRQ, "MMU sync complete\n"); + + if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT, status)) + ivpu_mmu_irq_gerr_handler(vdev); + + if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, status)) + irq_wdt_mss_handler(vdev); + + if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, status)) + irq_wdt_nce_handler(vdev); + + if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, status)) + irq_noc_firewall_handler(vdev); + + return true; +} + +static void db_set_37xx(struct ivpu_device *vdev, u32 db_id) +{ + u32 reg_stride = VPU_37XX_CPU_SS_DOORBELL_1 - VPU_37XX_CPU_SS_DOORBELL_0; + u32 val = REG_FLD(VPU_37XX_CPU_SS_DOORBELL_0, SET); + + REGV_WR32I(VPU_37XX_CPU_SS_DOORBELL_0, reg_stride, db_id, val); +} + +static void db_set_40xx(struct ivpu_device *vdev, u32 db_id) +{ + u32 reg_stride = VPU_40XX_CPU_SS_DOORBELL_1 - VPU_40XX_CPU_SS_DOORBELL_0; + u32 val = REG_FLD(VPU_40XX_CPU_SS_DOORBELL_0, SET); + + REGV_WR32I(VPU_40XX_CPU_SS_DOORBELL_0, reg_stride, db_id, val); +} + +void ivpu_hw_ip_db_set(struct ivpu_device *vdev, u32 db_id) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + db_set_37xx(vdev, db_id); + else + db_set_40xx(vdev, db_id); +} + +u32 ivpu_hw_ip_ipc_rx_addr_get(struct ivpu_device *vdev) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + return REGV_RD32(VPU_37XX_HOST_SS_TIM_IPC_FIFO_ATM); + else + return REGV_RD32(VPU_40XX_HOST_SS_TIM_IPC_FIFO_ATM); +} + +void ivpu_hw_ip_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr) +{ + if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) + REGV_WR32(VPU_37XX_CPU_SS_TIM_IPC_FIFO, vpu_addr); + else + REGV_WR32(VPU_40XX_CPU_SS_TIM_IPC_FIFO, vpu_addr); +} diff --git a/drivers/accel/ivpu/ivpu_hw_ip.h b/drivers/accel/ivpu/ivpu_hw_ip.h new file mode 100644 index 000000000000..5b1b391aa577 --- /dev/null +++ b/drivers/accel/ivpu/ivpu_hw_ip.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2020-2024 Intel Corporation + */ + +#ifndef __IVPU_HW_IP_H__ +#define __IVPU_HW_IP_H__ + +#include "ivpu_drv.h" + +int ivpu_hw_ip_host_ss_configure(struct ivpu_device *vdev); +void ivpu_hw_ip_idle_gen_enable(struct ivpu_device *vdev); +void ivpu_hw_ip_idle_gen_disable(struct ivpu_device *vdev); +int ivpu_hw_ip_pwr_domain_enable(struct ivpu_device *vdev); +int ivpu_hw_ip_host_ss_axi_enable(struct ivpu_device *vdev); +int ivpu_hw_ip_top_noc_enable(struct ivpu_device *vdev); +u64 ivpu_hw_ip_read_perf_timer_counter(struct ivpu_device *vdev); +void ivpu_hw_ip_snoop_disable(struct ivpu_device *vdev); +void ivpu_hw_ip_tbu_mmu_enable(struct ivpu_device *vdev); +int ivpu_hw_ip_soc_cpu_boot(struct ivpu_device *vdev); +void ivpu_hw_ip_wdt_disable(struct ivpu_device *vdev); +void ivpu_hw_ip_diagnose_failure(struct ivpu_device *vdev); +u32 ivpu_hw_ip_ipc_rx_count_get(struct ivpu_device *vdev); +void ivpu_hw_ip_irq_clear(struct ivpu_device *vdev); +bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq); +bool ivpu_hw_ip_irq_handler_40xx(struct ivpu_device *vdev, int irq); +void ivpu_hw_ip_db_set(struct ivpu_device *vdev, u32 db_id); +u32 ivpu_hw_ip_ipc_rx_addr_get(struct ivpu_device *vdev); +void ivpu_hw_ip_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr); +void ivpu_hw_ip_irq_enable(struct ivpu_device *vdev); +void ivpu_hw_ip_irq_disable(struct ivpu_device *vdev); +void ivpu_hw_ip_diagnose_failure(struct ivpu_device *vdev); +void ivpu_hw_ip_fabric_req_override_enable_50xx(struct ivpu_device *vdev); +void ivpu_hw_ip_fabric_req_override_disable_50xx(struct ivpu_device *vdev); + +#endif /* __IVPU_HW_IP_H__ */ diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c index 56ff067f63e2..78b32a823241 100644 --- a/drivers/accel/ivpu/ivpu_ipc.c +++ b/drivers/accel/ivpu/ivpu_ipc.c @@ -129,7 +129,7 @@ static void ivpu_ipc_tx_release(struct ivpu_device *vdev, u32 vpu_addr) static void ivpu_ipc_tx(struct ivpu_device *vdev, u32 vpu_addr) { - ivpu_hw_reg_ipc_tx_set(vdev, vpu_addr); + ivpu_hw_ipc_tx_set(vdev, vpu_addr); } static void @@ -210,8 +210,7 @@ void ivpu_ipc_consumer_del(struct ivpu_device *vdev, struct ivpu_ipc_consumer *c ivpu_ipc_tx_release(vdev, cons->tx_vpu_addr); } -static int -ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, struct vpu_jsm_msg *req) +int ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, struct vpu_jsm_msg *req) { struct ivpu_ipc_info *ipc = vdev->ipc; int ret; @@ -378,7 +377,7 @@ ivpu_ipc_match_consumer(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons return false; } -void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread) +void ivpu_ipc_irq_handler(struct ivpu_device *vdev) { struct ivpu_ipc_info *ipc = vdev->ipc; struct ivpu_ipc_consumer *cons; @@ -392,8 +391,8 @@ void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread) * Driver needs to purge all messages from IPC FIFO to clear IPC interrupt. * Without purge IPC FIFO to 0 next IPC interrupts won't be generated. */ - while (ivpu_hw_reg_ipc_rx_count_get(vdev)) { - vpu_addr = ivpu_hw_reg_ipc_rx_addr_get(vdev); + while (ivpu_hw_ipc_rx_count_get(vdev)) { + vpu_addr = ivpu_hw_ipc_rx_addr_get(vdev); if (vpu_addr == REG_IO_ERROR) { ivpu_err_ratelimited(vdev, "Failed to read IPC rx addr register\n"); return; @@ -442,11 +441,12 @@ void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread) } } - if (wake_thread) - *wake_thread = !list_empty(&ipc->cb_msg_list); + if (!list_empty(&ipc->cb_msg_list)) + if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_IPC)) + ivpu_err_ratelimited(vdev, "IRQ FIFO full\n"); } -irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev) +void ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev) { struct ivpu_ipc_info *ipc = vdev->ipc; struct ivpu_ipc_rx_msg *rx_msg, *r; @@ -462,8 +462,6 @@ irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev) rx_msg->callback(vdev, rx_msg->ipc_hdr, rx_msg->jsm_msg); ivpu_ipc_rx_msg_del(vdev, rx_msg); } - - return IRQ_HANDLED; } int ivpu_ipc_init(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_ipc.h b/drivers/accel/ivpu/ivpu_ipc.h index 40ca3cc4e61f..4fe38141045e 100644 --- a/drivers/accel/ivpu/ivpu_ipc.h +++ b/drivers/accel/ivpu/ivpu_ipc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #ifndef __IVPU_IPC_H__ @@ -89,13 +89,15 @@ void ivpu_ipc_enable(struct ivpu_device *vdev); void ivpu_ipc_disable(struct ivpu_device *vdev); void ivpu_ipc_reset(struct ivpu_device *vdev); -void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread); -irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev); +void ivpu_ipc_irq_handler(struct ivpu_device *vdev); +void ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev); void ivpu_ipc_consumer_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, u32 channel, ivpu_ipc_rx_callback_t callback); void ivpu_ipc_consumer_del(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons); +int ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, + struct vpu_jsm_msg *req); int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, struct ivpu_ipc_hdr *ipc_buf, struct vpu_jsm_msg *jsm_msg, unsigned long timeout_ms); diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index a49bc9105ed0..be2e2bf0f43f 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include <drm/drm_file.h> @@ -12,11 +12,13 @@ #include <uapi/drm/ivpu_accel.h> #include "ivpu_drv.h" +#include "ivpu_fw.h" #include "ivpu_hw.h" #include "ivpu_ipc.h" #include "ivpu_job.h" #include "ivpu_jsm_msg.h" #include "ivpu_pm.h" +#include "vpu_boot_api.h" #define CMD_BUF_IDX 0 #define JOB_ID_JOB_MASK GENMASK(7, 0) @@ -25,14 +27,60 @@ static void ivpu_cmdq_ring_db(struct ivpu_device *vdev, struct ivpu_cmdq *cmdq) { - ivpu_hw_reg_db_set(vdev, cmdq->db_id); + ivpu_hw_db_set(vdev, cmdq->db_id); } -static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv, u16 engine) +static int ivpu_preemption_buffers_create(struct ivpu_device *vdev, + struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) +{ + u64 primary_size = ALIGN(vdev->fw->primary_preempt_buf_size, PAGE_SIZE); + u64 secondary_size = ALIGN(vdev->fw->secondary_preempt_buf_size, PAGE_SIZE); + struct ivpu_addr_range range; + + if (vdev->hw->sched_mode != VPU_SCHEDULING_MODE_HW) + return 0; + + range.start = vdev->hw->ranges.user.end - (primary_size * IVPU_NUM_CMDQS_PER_CTX); + range.end = vdev->hw->ranges.user.end; + cmdq->primary_preempt_buf = ivpu_bo_create(vdev, &file_priv->ctx, &range, primary_size, + DRM_IVPU_BO_WC); + if (!cmdq->primary_preempt_buf) { + ivpu_err(vdev, "Failed to create primary preemption buffer\n"); + return -ENOMEM; + } + + range.start = vdev->hw->ranges.shave.end - (secondary_size * IVPU_NUM_CMDQS_PER_CTX); + range.end = vdev->hw->ranges.shave.end; + cmdq->secondary_preempt_buf = ivpu_bo_create(vdev, &file_priv->ctx, &range, secondary_size, + DRM_IVPU_BO_WC); + if (!cmdq->secondary_preempt_buf) { + ivpu_err(vdev, "Failed to create secondary preemption buffer\n"); + goto err_free_primary; + } + + return 0; + +err_free_primary: + ivpu_bo_free(cmdq->primary_preempt_buf); + return -ENOMEM; +} + +static void ivpu_preemption_buffers_free(struct ivpu_device *vdev, + struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) +{ + if (vdev->hw->sched_mode != VPU_SCHEDULING_MODE_HW) + return; + + drm_WARN_ON(&vdev->drm, !cmdq->primary_preempt_buf); + drm_WARN_ON(&vdev->drm, !cmdq->secondary_preempt_buf); + ivpu_bo_free(cmdq->primary_preempt_buf); + ivpu_bo_free(cmdq->secondary_preempt_buf); +} + +static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv) { struct xa_limit db_xa_limit = {.max = IVPU_MAX_DB, .min = IVPU_MIN_DB}; struct ivpu_device *vdev = file_priv->vdev; - struct vpu_job_queue_header *jobq_header; struct ivpu_cmdq *cmdq; int ret; @@ -50,18 +98,14 @@ static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv, u16 e if (!cmdq->mem) goto err_erase_xa; - cmdq->entry_count = (u32)((ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header)) / - sizeof(struct vpu_job_queue_entry)); - - cmdq->jobq = (struct vpu_job_queue *)ivpu_bo_vaddr(cmdq->mem); - jobq_header = &cmdq->jobq->header; - jobq_header->engine_idx = engine; - jobq_header->head = 0; - jobq_header->tail = 0; - wmb(); /* Flush WC buffer for jobq->header */ + ret = ivpu_preemption_buffers_create(vdev, file_priv, cmdq); + if (ret) + goto err_free_cmdq_mem; return cmdq; +err_free_cmdq_mem: + ivpu_bo_free(cmdq->mem); err_erase_xa: xa_erase(&vdev->db_xa, cmdq->db_id); err_free_cmdq: @@ -74,92 +118,183 @@ static void ivpu_cmdq_free(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *c if (!cmdq) return; + ivpu_preemption_buffers_free(file_priv->vdev, file_priv, cmdq); ivpu_bo_free(cmdq->mem); xa_erase(&file_priv->vdev->db_xa, cmdq->db_id); kfree(cmdq); } -static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u16 engine) +static int ivpu_hws_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u16 engine, + u8 priority) { struct ivpu_device *vdev = file_priv->vdev; - struct ivpu_cmdq *cmdq = file_priv->cmdq[engine]; + int ret; + + ret = ivpu_jsm_hws_create_cmdq(vdev, file_priv->ctx.id, file_priv->ctx.id, cmdq->db_id, + task_pid_nr(current), engine, + cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); + if (ret) + return ret; + + ret = ivpu_jsm_hws_set_context_sched_properties(vdev, file_priv->ctx.id, cmdq->db_id, + priority); + if (ret) + return ret; + + return 0; +} + +static int ivpu_register_db(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) +{ + struct ivpu_device *vdev = file_priv->vdev; + int ret; + + if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) + ret = ivpu_jsm_hws_register_db(vdev, file_priv->ctx.id, cmdq->db_id, cmdq->db_id, + cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); + else + ret = ivpu_jsm_register_db(vdev, file_priv->ctx.id, cmdq->db_id, + cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); + + if (!ret) + ivpu_dbg(vdev, JOB, "DB %d registered to ctx %d\n", cmdq->db_id, file_priv->ctx.id); + + return ret; +} + +static int +ivpu_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u16 engine, u8 priority) +{ + struct ivpu_device *vdev = file_priv->vdev; + struct vpu_job_queue_header *jobq_header; + int ret; + + lockdep_assert_held(&file_priv->lock); + + if (cmdq->db_registered) + return 0; + + cmdq->entry_count = (u32)((ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header)) / + sizeof(struct vpu_job_queue_entry)); + + cmdq->jobq = (struct vpu_job_queue *)ivpu_bo_vaddr(cmdq->mem); + jobq_header = &cmdq->jobq->header; + jobq_header->engine_idx = engine; + jobq_header->head = 0; + jobq_header->tail = 0; + wmb(); /* Flush WC buffer for jobq->header */ + + if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) { + ret = ivpu_hws_cmdq_init(file_priv, cmdq, engine, priority); + if (ret) + return ret; + } + + ret = ivpu_register_db(file_priv, cmdq); + if (ret) + return ret; + + cmdq->db_registered = true; + + return 0; +} + +static int ivpu_cmdq_fini(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) +{ + struct ivpu_device *vdev = file_priv->vdev; + int ret; + + lockdep_assert_held(&file_priv->lock); + + if (!cmdq->db_registered) + return 0; + + cmdq->db_registered = false; + + if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) { + ret = ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->db_id); + if (!ret) + ivpu_dbg(vdev, JOB, "Command queue %d destroyed\n", cmdq->db_id); + } + + ret = ivpu_jsm_unregister_db(vdev, cmdq->db_id); + if (!ret) + ivpu_dbg(vdev, JOB, "DB %d unregistered\n", cmdq->db_id); + + return 0; +} + +static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u16 engine, + u8 priority) +{ + int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority); + struct ivpu_cmdq *cmdq = file_priv->cmdq[cmdq_idx]; int ret; lockdep_assert_held(&file_priv->lock); if (!cmdq) { - cmdq = ivpu_cmdq_alloc(file_priv, engine); + cmdq = ivpu_cmdq_alloc(file_priv); if (!cmdq) return NULL; - file_priv->cmdq[engine] = cmdq; + file_priv->cmdq[cmdq_idx] = cmdq; } - if (cmdq->db_registered) - return cmdq; - - ret = ivpu_jsm_register_db(vdev, file_priv->ctx.id, cmdq->db_id, - cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); + ret = ivpu_cmdq_init(file_priv, cmdq, engine, priority); if (ret) return NULL; - cmdq->db_registered = true; - return cmdq; } -static void ivpu_cmdq_release_locked(struct ivpu_file_priv *file_priv, u16 engine) +static void ivpu_cmdq_release_locked(struct ivpu_file_priv *file_priv, u16 engine, u8 priority) { - struct ivpu_cmdq *cmdq = file_priv->cmdq[engine]; + int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority); + struct ivpu_cmdq *cmdq = file_priv->cmdq[cmdq_idx]; lockdep_assert_held(&file_priv->lock); if (cmdq) { - file_priv->cmdq[engine] = NULL; - if (cmdq->db_registered) - ivpu_jsm_unregister_db(file_priv->vdev, cmdq->db_id); - + file_priv->cmdq[cmdq_idx] = NULL; + ivpu_cmdq_fini(file_priv, cmdq); ivpu_cmdq_free(file_priv, cmdq); } } void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv) { - int i; + u16 engine; + u8 priority; lockdep_assert_held(&file_priv->lock); - for (i = 0; i < IVPU_NUM_ENGINES; i++) - ivpu_cmdq_release_locked(file_priv, i); + for (engine = 0; engine < IVPU_NUM_ENGINES; engine++) + for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) + ivpu_cmdq_release_locked(file_priv, engine, priority); } /* - * Mark the doorbell as unregistered and reset job queue pointers. + * Mark the doorbell as unregistered * This function needs to be called when the VPU hardware is restarted * and FW loses job queue state. The next time job queue is used it * will be registered again. */ -static void ivpu_cmdq_reset_locked(struct ivpu_file_priv *file_priv, u16 engine) -{ - struct ivpu_cmdq *cmdq = file_priv->cmdq[engine]; - - lockdep_assert_held(&file_priv->lock); - - if (cmdq) { - cmdq->db_registered = false; - cmdq->jobq->header.head = 0; - cmdq->jobq->header.tail = 0; - wmb(); /* Flush WC buffer for jobq header */ - } -} - -static void ivpu_cmdq_reset_all(struct ivpu_file_priv *file_priv) +static void ivpu_cmdq_reset(struct ivpu_file_priv *file_priv) { - int i; + u16 engine; + u8 priority; mutex_lock(&file_priv->lock); - for (i = 0; i < IVPU_NUM_ENGINES; i++) - ivpu_cmdq_reset_locked(file_priv, i); + for (engine = 0; engine < IVPU_NUM_ENGINES; engine++) { + for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) { + int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority); + struct ivpu_cmdq *cmdq = file_priv->cmdq[cmdq_idx]; + + if (cmdq) + cmdq->db_registered = false; + } + } mutex_unlock(&file_priv->lock); } @@ -172,10 +307,36 @@ void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev) mutex_lock(&vdev->context_list_lock); xa_for_each(&vdev->context_xa, ctx_id, file_priv) - ivpu_cmdq_reset_all(file_priv); + ivpu_cmdq_reset(file_priv); mutex_unlock(&vdev->context_list_lock); +} + +static void ivpu_cmdq_fini_all(struct ivpu_file_priv *file_priv) +{ + u16 engine; + u8 priority; + + for (engine = 0; engine < IVPU_NUM_ENGINES; engine++) { + for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) { + int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority); + + if (file_priv->cmdq[cmdq_idx]) + ivpu_cmdq_fini(file_priv, file_priv->cmdq[cmdq_idx]); + } + } +} +void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv) +{ + struct ivpu_device *vdev = file_priv->vdev; + + lockdep_assert_held(&file_priv->lock); + + ivpu_cmdq_fini_all(file_priv); + + if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_OS) + ivpu_jsm_context_release(vdev, file_priv->ctx.id); } static int ivpu_cmdq_push_job(struct ivpu_cmdq *cmdq, struct ivpu_job *job) @@ -199,6 +360,15 @@ static int ivpu_cmdq_push_job(struct ivpu_cmdq *cmdq, struct ivpu_job *job) entry->flags = 0; if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_SUBMISSION)) entry->flags = VPU_JOB_FLAGS_NULL_SUBMISSION_MASK; + + if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW && + (unlikely(!(ivpu_test_mode & IVPU_TEST_MODE_PREEMPTION_DISABLE)))) { + entry->primary_preempt_buf_addr = cmdq->primary_preempt_buf->vpu_addr; + entry->primary_preempt_buf_size = ivpu_bo_size(cmdq->primary_preempt_buf); + entry->secondary_preempt_buf_addr = cmdq->secondary_preempt_buf->vpu_addr; + entry->secondary_preempt_buf_size = ivpu_bo_size(cmdq->secondary_preempt_buf); + } + wmb(); /* Ensure that tail is updated after filling entry */ header->tail = next_entry; wmb(); /* Flush WC buffer for jobq header */ @@ -295,11 +465,28 @@ err_free_job: return NULL; } +static struct ivpu_job *ivpu_job_remove_from_submitted_jobs(struct ivpu_device *vdev, u32 job_id) +{ + struct ivpu_job *job; + + xa_lock(&vdev->submitted_jobs_xa); + job = __xa_erase(&vdev->submitted_jobs_xa, job_id); + + if (xa_empty(&vdev->submitted_jobs_xa) && job) { + vdev->busy_time = ktime_add(ktime_sub(ktime_get(), vdev->busy_start_ts), + vdev->busy_time); + } + + xa_unlock(&vdev->submitted_jobs_xa); + + return job; +} + static int ivpu_job_signal_and_destroy(struct ivpu_device *vdev, u32 job_id, u32 job_status) { struct ivpu_job *job; - job = xa_erase(&vdev->submitted_jobs_xa, job_id); + job = ivpu_job_remove_from_submitted_jobs(vdev, job_id); if (!job) return -ENOENT; @@ -328,12 +515,13 @@ void ivpu_jobs_abort_all(struct ivpu_device *vdev) ivpu_job_signal_and_destroy(vdev, id, DRM_IVPU_JOB_STATUS_ABORTED); } -static int ivpu_job_submit(struct ivpu_job *job) +static int ivpu_job_submit(struct ivpu_job *job, u8 priority) { struct ivpu_file_priv *file_priv = job->file_priv; struct ivpu_device *vdev = job->vdev; struct xa_limit job_id_range; struct ivpu_cmdq *cmdq; + bool is_first_job; int ret; ret = ivpu_rpm_get(vdev); @@ -342,10 +530,10 @@ static int ivpu_job_submit(struct ivpu_job *job) mutex_lock(&file_priv->lock); - cmdq = ivpu_cmdq_acquire(job->file_priv, job->engine_idx); + cmdq = ivpu_cmdq_acquire(job->file_priv, job->engine_idx, priority); if (!cmdq) { - ivpu_warn_ratelimited(vdev, "Failed get job queue, ctx %d engine %d\n", - file_priv->ctx.id, job->engine_idx); + ivpu_warn_ratelimited(vdev, "Failed to get job queue, ctx %d engine %d prio %d\n", + file_priv->ctx.id, job->engine_idx, priority); ret = -EINVAL; goto err_unlock_file_priv; } @@ -354,6 +542,7 @@ static int ivpu_job_submit(struct ivpu_job *job) job_id_range.max = job_id_range.min | JOB_ID_JOB_MASK; xa_lock(&vdev->submitted_jobs_xa); + is_first_job = xa_empty(&vdev->submitted_jobs_xa); ret = __xa_alloc(&vdev->submitted_jobs_xa, &job->job_id, job, job_id_range, GFP_KERNEL); if (ret) { ivpu_dbg(vdev, JOB, "Too many active jobs in ctx %d\n", @@ -373,10 +562,12 @@ static int ivpu_job_submit(struct ivpu_job *job) wmb(); /* Flush WC buffer for jobq header */ } else { ivpu_cmdq_ring_db(vdev, cmdq); + if (is_first_job) + vdev->busy_start_ts = ktime_get(); } - ivpu_dbg(vdev, JOB, "Job submitted: id %3u ctx %2d engine %d addr 0x%llx next %d\n", - job->job_id, file_priv->ctx.id, job->engine_idx, + ivpu_dbg(vdev, JOB, "Job submitted: id %3u ctx %2d engine %d prio %d addr 0x%llx next %d\n", + job->job_id, file_priv->ctx.id, job->engine_idx, priority, job->cmd_buf_vpu_addr, cmdq->jobq->header.tail); xa_unlock(&vdev->submitted_jobs_xa); @@ -464,6 +655,14 @@ unlock_reservations: return ret; } +static inline u8 ivpu_job_to_hws_priority(struct ivpu_file_priv *file_priv, u8 priority) +{ + if (priority == DRM_IVPU_JOB_PRIORITY_DEFAULT) + return DRM_IVPU_JOB_PRIORITY_NORMAL; + + return priority - 1; +} + int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct ivpu_file_priv *file_priv = file->driver_priv; @@ -472,6 +671,7 @@ int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file) struct ivpu_job *job; u32 *buf_handles; int idx, ret; + u8 priority; if (params->engine > DRM_IVPU_ENGINE_COPY) return -EINVAL; @@ -525,8 +725,10 @@ int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file) goto err_destroy_job; } + priority = ivpu_job_to_hws_priority(file_priv, params->priority); + down_read(&vdev->pm->reset_lock); - ret = ivpu_job_submit(job); + ret = ivpu_job_submit(job, priority); up_read(&vdev->pm->reset_lock); if (ret) goto err_signal_fence; diff --git a/drivers/accel/ivpu/ivpu_job.h b/drivers/accel/ivpu/ivpu_job.h index ca4984071cc7..6accb94028c7 100644 --- a/drivers/accel/ivpu/ivpu_job.h +++ b/drivers/accel/ivpu/ivpu_job.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #ifndef __IVPU_JOB_H__ @@ -24,6 +24,8 @@ struct ivpu_file_priv; */ struct ivpu_cmdq { struct vpu_job_queue *jobq; + struct ivpu_bo *primary_preempt_buf; + struct ivpu_bo *secondary_preempt_buf; struct ivpu_bo *mem; u32 entry_count; u32 db_id; @@ -55,6 +57,8 @@ struct ivpu_job { int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv); + void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv); void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev); diff --git a/drivers/accel/ivpu/ivpu_jsm_msg.c b/drivers/accel/ivpu/ivpu_jsm_msg.c index 8cea0dd731b9..46ef16c3c069 100644 --- a/drivers/accel/ivpu/ivpu_jsm_msg.c +++ b/drivers/accel/ivpu/ivpu_jsm_msg.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include "ivpu_drv.h" @@ -103,14 +103,10 @@ int ivpu_jsm_register_db(struct ivpu_device *vdev, u32 ctx_id, u32 db_id, ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_REGISTER_DB_DONE, &resp, VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); - if (ret) { - ivpu_err_ratelimited(vdev, "Failed to register doorbell %d: %d\n", db_id, ret); - return ret; - } - - ivpu_dbg(vdev, JSM, "Doorbell %d registered to context %d\n", db_id, ctx_id); + if (ret) + ivpu_err_ratelimited(vdev, "Failed to register doorbell %u: %d\n", db_id, ret); - return 0; + return ret; } int ivpu_jsm_unregister_db(struct ivpu_device *vdev, u32 db_id) @@ -123,14 +119,10 @@ int ivpu_jsm_unregister_db(struct ivpu_device *vdev, u32 db_id) ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_UNREGISTER_DB_DONE, &resp, VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); - if (ret) { - ivpu_warn_ratelimited(vdev, "Failed to unregister doorbell %d: %d\n", db_id, ret); - return ret; - } - - ivpu_dbg(vdev, JSM, "Doorbell %d unregistered\n", db_id); + if (ret) + ivpu_warn_ratelimited(vdev, "Failed to unregister doorbell %u: %d\n", db_id, ret); - return 0; + return ret; } int ivpu_jsm_get_heartbeat(struct ivpu_device *vdev, u32 engine, u64 *heartbeat) @@ -255,11 +247,16 @@ int ivpu_jsm_context_release(struct ivpu_device *vdev, u32 host_ssid) { struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_SSID_RELEASE }; struct vpu_jsm_msg resp; + int ret; req.payload.ssid_release.host_ssid = host_ssid; - return ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_SSID_RELEASE_DONE, &resp, - VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_SSID_RELEASE_DONE, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) + ivpu_warn_ratelimited(vdev, "Failed to release context: %d\n", ret); + + return ret; } int ivpu_jsm_pwr_d0i3_enter(struct ivpu_device *vdev) @@ -281,3 +278,283 @@ int ivpu_jsm_pwr_d0i3_enter(struct ivpu_device *vdev) return ivpu_hw_wait_for_idle(vdev); } + +int ivpu_jsm_hws_create_cmdq(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_group, u32 cmdq_id, + u32 pid, u32 engine, u64 cmdq_base, u32 cmdq_size) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_CREATE_CMD_QUEUE }; + struct vpu_jsm_msg resp; + int ret; + + req.payload.hws_create_cmdq.host_ssid = ctx_id; + req.payload.hws_create_cmdq.process_id = pid; + req.payload.hws_create_cmdq.engine_idx = engine; + req.payload.hws_create_cmdq.cmdq_group = cmdq_group; + req.payload.hws_create_cmdq.cmdq_id = cmdq_id; + req.payload.hws_create_cmdq.cmdq_base = cmdq_base; + req.payload.hws_create_cmdq.cmdq_size = cmdq_size; + + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_CREATE_CMD_QUEUE_RSP, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) + ivpu_warn_ratelimited(vdev, "Failed to create command queue: %d\n", ret); + + return ret; +} + +int ivpu_jsm_hws_destroy_cmdq(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_DESTROY_CMD_QUEUE }; + struct vpu_jsm_msg resp; + int ret; + + req.payload.hws_destroy_cmdq.host_ssid = ctx_id; + req.payload.hws_destroy_cmdq.cmdq_id = cmdq_id; + + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_DESTROY_CMD_QUEUE_RSP, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) + ivpu_warn_ratelimited(vdev, "Failed to destroy command queue: %d\n", ret); + + return ret; +} + +int ivpu_jsm_hws_register_db(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id, u32 db_id, + u64 cmdq_base, u32 cmdq_size) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_HWS_REGISTER_DB }; + struct vpu_jsm_msg resp; + int ret = 0; + + req.payload.hws_register_db.db_id = db_id; + req.payload.hws_register_db.host_ssid = ctx_id; + req.payload.hws_register_db.cmdq_id = cmdq_id; + req.payload.hws_register_db.cmdq_base = cmdq_base; + req.payload.hws_register_db.cmdq_size = cmdq_size; + + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_REGISTER_DB_DONE, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) + ivpu_err_ratelimited(vdev, "Failed to register doorbell %u: %d\n", db_id, ret); + + return ret; +} + +int ivpu_jsm_hws_resume_engine(struct ivpu_device *vdev, u32 engine) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_HWS_ENGINE_RESUME }; + struct vpu_jsm_msg resp; + int ret; + + if (engine >= VPU_ENGINE_NB) + return -EINVAL; + + req.payload.hws_resume_engine.engine_idx = engine; + + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_HWS_RESUME_ENGINE_DONE, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) + ivpu_err_ratelimited(vdev, "Failed to resume engine %d: %d\n", engine, ret); + + return ret; +} + +int ivpu_jsm_hws_set_context_sched_properties(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id, + u32 priority) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_SET_CONTEXT_SCHED_PROPERTIES }; + struct vpu_jsm_msg resp; + int ret; + + req.payload.hws_set_context_sched_properties.host_ssid = ctx_id; + req.payload.hws_set_context_sched_properties.cmdq_id = cmdq_id; + req.payload.hws_set_context_sched_properties.priority_band = priority; + req.payload.hws_set_context_sched_properties.realtime_priority_level = 0; + req.payload.hws_set_context_sched_properties.in_process_priority = 0; + req.payload.hws_set_context_sched_properties.context_quantum = 20000; + req.payload.hws_set_context_sched_properties.grace_period_same_priority = 10000; + req.payload.hws_set_context_sched_properties.grace_period_lower_priority = 0; + + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_SET_CONTEXT_SCHED_PROPERTIES_RSP, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) + ivpu_warn_ratelimited(vdev, "Failed to set context sched properties: %d\n", ret); + + return ret; +} + +int ivpu_jsm_hws_set_scheduling_log(struct ivpu_device *vdev, u32 engine_idx, u32 host_ssid, + u64 vpu_log_buffer_va) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_HWS_SET_SCHEDULING_LOG }; + struct vpu_jsm_msg resp; + int ret; + + req.payload.hws_set_scheduling_log.engine_idx = engine_idx; + req.payload.hws_set_scheduling_log.host_ssid = host_ssid; + req.payload.hws_set_scheduling_log.vpu_log_buffer_va = vpu_log_buffer_va; + req.payload.hws_set_scheduling_log.notify_index = 0; + req.payload.hws_set_scheduling_log.enable_extra_events = + ivpu_test_mode & IVPU_TEST_MODE_HWS_EXTRA_EVENTS; + + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_HWS_SET_SCHEDULING_LOG_RSP, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) + ivpu_warn_ratelimited(vdev, "Failed to set scheduling log: %d\n", ret); + + return ret; +} + +int ivpu_jsm_hws_setup_priority_bands(struct ivpu_device *vdev) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_SET_PRIORITY_BAND_SETUP }; + struct vpu_jsm_msg resp; + int ret; + + /* Idle */ + req.payload.hws_priority_band_setup.grace_period[0] = 0; + req.payload.hws_priority_band_setup.process_grace_period[0] = 50000; + req.payload.hws_priority_band_setup.process_quantum[0] = 160000; + /* Normal */ + req.payload.hws_priority_band_setup.grace_period[1] = 50000; + req.payload.hws_priority_band_setup.process_grace_period[1] = 50000; + req.payload.hws_priority_band_setup.process_quantum[1] = 300000; + /* Focus */ + req.payload.hws_priority_band_setup.grace_period[2] = 50000; + req.payload.hws_priority_band_setup.process_grace_period[2] = 50000; + req.payload.hws_priority_band_setup.process_quantum[2] = 200000; + /* Realtime */ + req.payload.hws_priority_band_setup.grace_period[3] = 0; + req.payload.hws_priority_band_setup.process_grace_period[3] = 50000; + req.payload.hws_priority_band_setup.process_quantum[3] = 200000; + + req.payload.hws_priority_band_setup.normal_band_percentage = 10; + + ret = ivpu_ipc_send_receive_active(vdev, &req, VPU_JSM_MSG_SET_PRIORITY_BAND_SETUP_RSP, + &resp, VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) + ivpu_warn_ratelimited(vdev, "Failed to set priority bands: %d\n", ret); + + return ret; +} + +int ivpu_jsm_metric_streamer_start(struct ivpu_device *vdev, u64 metric_group_mask, + u64 sampling_rate, u64 buffer_addr, u64 buffer_size) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_METRIC_STREAMER_START }; + struct vpu_jsm_msg resp; + int ret; + + req.payload.metric_streamer_start.metric_group_mask = metric_group_mask; + req.payload.metric_streamer_start.sampling_rate = sampling_rate; + req.payload.metric_streamer_start.buffer_addr = buffer_addr; + req.payload.metric_streamer_start.buffer_size = buffer_size; + + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_METRIC_STREAMER_START_DONE, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) { + ivpu_warn_ratelimited(vdev, "Failed to start metric streamer: ret %d\n", ret); + return ret; + } + + return ret; +} + +int ivpu_jsm_metric_streamer_stop(struct ivpu_device *vdev, u64 metric_group_mask) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_METRIC_STREAMER_STOP }; + struct vpu_jsm_msg resp; + int ret; + + req.payload.metric_streamer_stop.metric_group_mask = metric_group_mask; + + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_METRIC_STREAMER_STOP_DONE, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) + ivpu_warn_ratelimited(vdev, "Failed to stop metric streamer: ret %d\n", ret); + + return ret; +} + +int ivpu_jsm_metric_streamer_update(struct ivpu_device *vdev, u64 metric_group_mask, + u64 buffer_addr, u64 buffer_size, u64 *bytes_written) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_METRIC_STREAMER_UPDATE }; + struct vpu_jsm_msg resp; + int ret; + + req.payload.metric_streamer_update.metric_group_mask = metric_group_mask; + req.payload.metric_streamer_update.buffer_addr = buffer_addr; + req.payload.metric_streamer_update.buffer_size = buffer_size; + + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_METRIC_STREAMER_UPDATE_DONE, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) { + ivpu_warn_ratelimited(vdev, "Failed to update metric streamer: ret %d\n", ret); + return ret; + } + + if (buffer_size && resp.payload.metric_streamer_done.bytes_written > buffer_size) { + ivpu_warn_ratelimited(vdev, "MS buffer overflow: bytes_written %#llx > buffer_size %#llx\n", + resp.payload.metric_streamer_done.bytes_written, buffer_size); + return -EOVERFLOW; + } + + *bytes_written = resp.payload.metric_streamer_done.bytes_written; + + return ret; +} + +int ivpu_jsm_metric_streamer_info(struct ivpu_device *vdev, u64 metric_group_mask, u64 buffer_addr, + u64 buffer_size, u32 *sample_size, u64 *info_size) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_METRIC_STREAMER_INFO }; + struct vpu_jsm_msg resp; + int ret; + + req.payload.metric_streamer_start.metric_group_mask = metric_group_mask; + req.payload.metric_streamer_start.buffer_addr = buffer_addr; + req.payload.metric_streamer_start.buffer_size = buffer_size; + + ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_METRIC_STREAMER_INFO_DONE, &resp, + VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm); + if (ret) { + ivpu_warn_ratelimited(vdev, "Failed to get metric streamer info: ret %d\n", ret); + return ret; + } + + if (!resp.payload.metric_streamer_done.sample_size) { + ivpu_warn_ratelimited(vdev, "Invalid sample size\n"); + return -EBADMSG; + } + + if (sample_size) + *sample_size = resp.payload.metric_streamer_done.sample_size; + if (info_size) + *info_size = resp.payload.metric_streamer_done.bytes_written; + + return ret; +} + +int ivpu_jsm_dct_enable(struct ivpu_device *vdev, u32 active_us, u32 inactive_us) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_DCT_ENABLE }; + struct vpu_jsm_msg resp; + + req.payload.pwr_dct_control.dct_active_us = active_us; + req.payload.pwr_dct_control.dct_inactive_us = inactive_us; + + return ivpu_ipc_send_receive_active(vdev, &req, VPU_JSM_MSG_DCT_ENABLE_DONE, + &resp, VPU_IPC_CHAN_ASYNC_CMD, + vdev->timeout.jsm); +} + +int ivpu_jsm_dct_disable(struct ivpu_device *vdev) +{ + struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_DCT_DISABLE }; + struct vpu_jsm_msg resp; + + return ivpu_ipc_send_receive_active(vdev, &req, VPU_JSM_MSG_DCT_DISABLE_DONE, + &resp, VPU_IPC_CHAN_ASYNC_CMD, + vdev->timeout.jsm); +} diff --git a/drivers/accel/ivpu/ivpu_jsm_msg.h b/drivers/accel/ivpu/ivpu_jsm_msg.h index ae75e5dbcc41..e4e42c0ff6e6 100644 --- a/drivers/accel/ivpu/ivpu_jsm_msg.h +++ b/drivers/accel/ivpu/ivpu_jsm_msg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #ifndef __IVPU_JSM_MSG_H__ @@ -23,4 +23,24 @@ int ivpu_jsm_trace_set_config(struct ivpu_device *vdev, u32 trace_level, u32 tra u64 trace_hw_component_mask); int ivpu_jsm_context_release(struct ivpu_device *vdev, u32 host_ssid); int ivpu_jsm_pwr_d0i3_enter(struct ivpu_device *vdev); +int ivpu_jsm_hws_create_cmdq(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_group, u32 cmdq_id, + u32 pid, u32 engine, u64 cmdq_base, u32 cmdq_size); +int ivpu_jsm_hws_destroy_cmdq(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id); +int ivpu_jsm_hws_register_db(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id, u32 db_id, + u64 cmdq_base, u32 cmdq_size); +int ivpu_jsm_hws_resume_engine(struct ivpu_device *vdev, u32 engine); +int ivpu_jsm_hws_set_context_sched_properties(struct ivpu_device *vdev, u32 ctx_id, u32 cmdq_id, + u32 priority); +int ivpu_jsm_hws_set_scheduling_log(struct ivpu_device *vdev, u32 engine_idx, u32 host_ssid, + u64 vpu_log_buffer_va); +int ivpu_jsm_hws_setup_priority_bands(struct ivpu_device *vdev); +int ivpu_jsm_metric_streamer_start(struct ivpu_device *vdev, u64 metric_group_mask, + u64 sampling_rate, u64 buffer_addr, u64 buffer_size); +int ivpu_jsm_metric_streamer_stop(struct ivpu_device *vdev, u64 metric_group_mask); +int ivpu_jsm_metric_streamer_update(struct ivpu_device *vdev, u64 metric_group_mask, + u64 buffer_addr, u64 buffer_size, u64 *bytes_written); +int ivpu_jsm_metric_streamer_info(struct ivpu_device *vdev, u64 metric_group_mask, u64 buffer_addr, + u64 buffer_size, u32 *sample_size, u64 *info_size); +int ivpu_jsm_dct_enable(struct ivpu_device *vdev, u32 active_us, u32 inactive_us); +int ivpu_jsm_dct_disable(struct ivpu_device *vdev); #endif diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c index 2e46b322c450..c078e214b221 100644 --- a/drivers/accel/ivpu/ivpu_mmu.c +++ b/drivers/accel/ivpu/ivpu_mmu.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include <linux/circ_buf.h> @@ -519,7 +519,8 @@ static int ivpu_mmu_cmdq_sync(struct ivpu_device *vdev) if (ret) return ret; - clflush_cache_range(q->base, IVPU_MMU_CMDQ_SIZE); + if (!ivpu_is_force_snoop_enabled(vdev)) + clflush_cache_range(q->base, IVPU_MMU_CMDQ_SIZE); REGV_WR32(IVPU_MMU_REG_CMDQ_PROD, q->prod); ret = ivpu_mmu_cmdq_wait_for_cons(vdev); @@ -567,7 +568,8 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev) int ret; memset(mmu->cmdq.base, 0, IVPU_MMU_CMDQ_SIZE); - clflush_cache_range(mmu->cmdq.base, IVPU_MMU_CMDQ_SIZE); + if (!ivpu_is_force_snoop_enabled(vdev)) + clflush_cache_range(mmu->cmdq.base, IVPU_MMU_CMDQ_SIZE); mmu->cmdq.prod = 0; mmu->cmdq.cons = 0; @@ -661,7 +663,8 @@ static void ivpu_mmu_strtab_link_cd(struct ivpu_device *vdev, u32 sid) WRITE_ONCE(entry[1], str[1]); WRITE_ONCE(entry[0], str[0]); - clflush_cache_range(entry, IVPU_MMU_STRTAB_ENT_SIZE); + if (!ivpu_is_force_snoop_enabled(vdev)) + clflush_cache_range(entry, IVPU_MMU_STRTAB_ENT_SIZE); ivpu_dbg(vdev, MMU, "STRTAB write entry (SSID=%u): 0x%llx, 0x%llx\n", sid, str[0], str[1]); } @@ -735,7 +738,8 @@ static int ivpu_mmu_cd_add(struct ivpu_device *vdev, u32 ssid, u64 cd_dma) WRITE_ONCE(entry[3], cd[3]); WRITE_ONCE(entry[0], cd[0]); - clflush_cache_range(entry, IVPU_MMU_CDTAB_ENT_SIZE); + if (!ivpu_is_force_snoop_enabled(vdev)) + clflush_cache_range(entry, IVPU_MMU_CDTAB_ENT_SIZE); ivpu_dbg(vdev, MMU, "CDTAB %s entry (SSID=%u, dma=%pad): 0x%llx, 0x%llx, 0x%llx, 0x%llx\n", cd_dma ? "write" : "clear", ssid, &cd_dma, cd[0], cd[1], cd[2], cd[3]); @@ -874,8 +878,9 @@ static void ivpu_mmu_dump_event(struct ivpu_device *vdev, u32 *event) u64 in_addr = ((u64)event[5]) << 32 | event[4]; u32 sid = event[1]; - ivpu_err(vdev, "MMU EVTQ: 0x%x (%s) SSID: %d SID: %d, e[2] %08x, e[3] %08x, in addr: 0x%llx, fetch addr: 0x%llx\n", - op, ivpu_mmu_event_to_str(op), ssid, sid, event[2], event[3], in_addr, fetch_addr); + ivpu_err_ratelimited(vdev, "MMU EVTQ: 0x%x (%s) SSID: %d SID: %d, e[2] %08x, e[3] %08x, in addr: 0x%llx, fetch addr: 0x%llx\n", + op, ivpu_mmu_event_to_str(op), ssid, sid, + event[2], event[3], in_addr, fetch_addr); } static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev) @@ -911,6 +916,9 @@ void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev) ivpu_mmu_user_context_mark_invalid(vdev, ssid); REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons); } + + if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_MMU_EVTQ)) + ivpu_err_ratelimited(vdev, "IRQ FIFO full\n"); } void ivpu_mmu_evtq_dump(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/ivpu/ivpu_mmu_context.c index 128aef8e5a19..bbe652a7019d 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.c +++ b/drivers/accel/ivpu/ivpu_mmu_context.c @@ -24,6 +24,7 @@ #define IVPU_MMU_ENTRY_FLAG_CONT BIT(52) #define IVPU_MMU_ENTRY_FLAG_NG BIT(11) #define IVPU_MMU_ENTRY_FLAG_AF BIT(10) +#define IVPU_MMU_ENTRY_FLAG_RO BIT(7) #define IVPU_MMU_ENTRY_FLAG_USER BIT(6) #define IVPU_MMU_ENTRY_FLAG_LLC_COHERENT BIT(2) #define IVPU_MMU_ENTRY_FLAG_TYPE_PAGE BIT(1) @@ -319,6 +320,91 @@ ivpu_mmu_context_map_pages(struct ivpu_device *vdev, struct ivpu_mmu_context *ct return 0; } +static void ivpu_mmu_context_set_page_ro(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, + u64 vpu_addr) +{ + int pgd_idx = FIELD_GET(IVPU_MMU_PGD_INDEX_MASK, vpu_addr); + int pud_idx = FIELD_GET(IVPU_MMU_PUD_INDEX_MASK, vpu_addr); + int pmd_idx = FIELD_GET(IVPU_MMU_PMD_INDEX_MASK, vpu_addr); + int pte_idx = FIELD_GET(IVPU_MMU_PTE_INDEX_MASK, vpu_addr); + + ctx->pgtable.pte_ptrs[pgd_idx][pud_idx][pmd_idx][pte_idx] |= IVPU_MMU_ENTRY_FLAG_RO; +} + +static void ivpu_mmu_context_split_page(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, + u64 vpu_addr) +{ + int pgd_idx = FIELD_GET(IVPU_MMU_PGD_INDEX_MASK, vpu_addr); + int pud_idx = FIELD_GET(IVPU_MMU_PUD_INDEX_MASK, vpu_addr); + int pmd_idx = FIELD_GET(IVPU_MMU_PMD_INDEX_MASK, vpu_addr); + int pte_idx = FIELD_GET(IVPU_MMU_PTE_INDEX_MASK, vpu_addr); + + ctx->pgtable.pte_ptrs[pgd_idx][pud_idx][pmd_idx][pte_idx] &= ~IVPU_MMU_ENTRY_FLAG_CONT; +} + +static void ivpu_mmu_context_split_64k_page(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, + u64 vpu_addr) +{ + u64 start = ALIGN_DOWN(vpu_addr, IVPU_MMU_CONT_PAGES_SIZE); + u64 end = ALIGN(vpu_addr, IVPU_MMU_CONT_PAGES_SIZE); + u64 offset = 0; + + ivpu_dbg(vdev, MMU_MAP, "Split 64K page ctx: %u vpu_addr: 0x%llx\n", ctx->id, vpu_addr); + + while (start + offset < end) { + ivpu_mmu_context_split_page(vdev, ctx, start + offset); + offset += IVPU_MMU_PAGE_SIZE; + } +} + +int +ivpu_mmu_context_set_pages_ro(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u64 vpu_addr, + size_t size) +{ + u64 end = vpu_addr + size; + size_t size_left = size; + int ret; + + if (size == 0) + return 0; + + if (drm_WARN_ON(&vdev->drm, !IS_ALIGNED(vpu_addr | size, IVPU_MMU_PAGE_SIZE))) + return -EINVAL; + + mutex_lock(&ctx->lock); + + ivpu_dbg(vdev, MMU_MAP, "Set read-only pages ctx: %u vpu_addr: 0x%llx size: %lu\n", + ctx->id, vpu_addr, size); + + if (!ivpu_disable_mmu_cont_pages) { + /* Split 64K contiguous page at the beginning if needed */ + if (!IS_ALIGNED(vpu_addr, IVPU_MMU_CONT_PAGES_SIZE)) + ivpu_mmu_context_split_64k_page(vdev, ctx, vpu_addr); + + /* Split 64K contiguous page at the end if needed */ + if (!IS_ALIGNED(vpu_addr + size, IVPU_MMU_CONT_PAGES_SIZE)) + ivpu_mmu_context_split_64k_page(vdev, ctx, vpu_addr + size); + } + + while (size_left) { + if (vpu_addr < end) + ivpu_mmu_context_set_page_ro(vdev, ctx, vpu_addr); + + vpu_addr += IVPU_MMU_PAGE_SIZE; + size_left -= IVPU_MMU_PAGE_SIZE; + } + + /* Ensure page table modifications are flushed from wc buffers to memory */ + wmb(); + + mutex_unlock(&ctx->lock); + ret = ivpu_mmu_invalidate_tlb(vdev, ctx->id); + if (ret) + ivpu_err(vdev, "Failed to invalidate TLB for ctx %u: %d\n", ctx->id, ret); + + return 0; +} + static void ivpu_mmu_context_unmap_pages(struct ivpu_mmu_context *ctx, u64 vpu_addr, size_t size) { while (size) { diff --git a/drivers/accel/ivpu/ivpu_mmu_context.h b/drivers/accel/ivpu/ivpu_mmu_context.h index 535db3a1fc74..7f9aaf3d10c2 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.h +++ b/drivers/accel/ivpu/ivpu_mmu_context.h @@ -46,5 +46,7 @@ int ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context * u64 vpu_addr, struct sg_table *sgt, bool llc_coherent); void ivpu_mmu_context_unmap_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u64 vpu_addr, struct sg_table *sgt); +int ivpu_mmu_context_set_pages_ro(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, + u64 vpu_addr, size_t size); #endif /* __IVPU_MMU_CONTEXT_H__ */ diff --git a/drivers/accel/ivpu/ivpu_ms.c b/drivers/accel/ivpu/ivpu_ms.c new file mode 100644 index 000000000000..2f9d37f5c208 --- /dev/null +++ b/drivers/accel/ivpu/ivpu_ms.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (C) 2020-2024 Intel Corporation + */ + +#include <drm/drm_file.h> + +#include "ivpu_drv.h" +#include "ivpu_gem.h" +#include "ivpu_jsm_msg.h" +#include "ivpu_ms.h" +#include "ivpu_pm.h" + +#define MS_INFO_BUFFER_SIZE SZ_16K +#define MS_NUM_BUFFERS 2 +#define MS_READ_PERIOD_MULTIPLIER 2 +#define MS_MIN_SAMPLE_PERIOD_NS 1000000 + +static struct ivpu_ms_instance * +get_instance_by_mask(struct ivpu_file_priv *file_priv, u64 metric_mask) +{ + struct ivpu_ms_instance *ms; + + lockdep_assert_held(&file_priv->ms_lock); + + list_for_each_entry(ms, &file_priv->ms_instance_list, ms_instance_node) + if (ms->mask == metric_mask) + return ms; + + return NULL; +} + +int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct ivpu_file_priv *file_priv = file->driver_priv; + struct drm_ivpu_metric_streamer_start *args = data; + struct ivpu_device *vdev = file_priv->vdev; + struct ivpu_ms_instance *ms; + u64 single_buff_size; + u32 sample_size; + int ret; + + if (!args->metric_group_mask || !args->read_period_samples || + args->sampling_period_ns < MS_MIN_SAMPLE_PERIOD_NS) + return -EINVAL; + + mutex_lock(&file_priv->ms_lock); + + if (get_instance_by_mask(file_priv, args->metric_group_mask)) { + ivpu_err(vdev, "Instance already exists (mask %#llx)\n", args->metric_group_mask); + ret = -EALREADY; + goto unlock; + } + + ms = kzalloc(sizeof(*ms), GFP_KERNEL); + if (!ms) { + ret = -ENOMEM; + goto unlock; + } + + ms->mask = args->metric_group_mask; + + ret = ivpu_jsm_metric_streamer_info(vdev, ms->mask, 0, 0, &sample_size, NULL); + if (ret) + goto err_free_ms; + + single_buff_size = sample_size * + ((u64)args->read_period_samples * MS_READ_PERIOD_MULTIPLIER); + ms->bo = ivpu_bo_create_global(vdev, PAGE_ALIGN(single_buff_size * MS_NUM_BUFFERS), + DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE); + if (!ms->bo) { + ivpu_err(vdev, "Failed to allocate MS buffer (size %llu)\n", single_buff_size); + ret = -ENOMEM; + goto err_free_ms; + } + + ms->buff_size = ivpu_bo_size(ms->bo) / MS_NUM_BUFFERS; + ms->active_buff_vpu_addr = ms->bo->vpu_addr; + ms->inactive_buff_vpu_addr = ms->bo->vpu_addr + ms->buff_size; + ms->active_buff_ptr = ivpu_bo_vaddr(ms->bo); + ms->inactive_buff_ptr = ivpu_bo_vaddr(ms->bo) + ms->buff_size; + + ret = ivpu_jsm_metric_streamer_start(vdev, ms->mask, args->sampling_period_ns, + ms->active_buff_vpu_addr, ms->buff_size); + if (ret) + goto err_free_bo; + + args->sample_size = sample_size; + args->max_data_size = ivpu_bo_size(ms->bo); + list_add_tail(&ms->ms_instance_node, &file_priv->ms_instance_list); + goto unlock; + +err_free_bo: + ivpu_bo_free(ms->bo); +err_free_ms: + kfree(ms); +unlock: + mutex_unlock(&file_priv->ms_lock); + return ret; +} + +static int +copy_leftover_bytes(struct ivpu_ms_instance *ms, + void __user *user_ptr, u64 user_size, u64 *user_bytes_copied) +{ + u64 copy_bytes; + + if (ms->leftover_bytes) { + copy_bytes = min(user_size - *user_bytes_copied, ms->leftover_bytes); + if (copy_to_user(user_ptr + *user_bytes_copied, ms->leftover_addr, copy_bytes)) + return -EFAULT; + + ms->leftover_bytes -= copy_bytes; + ms->leftover_addr += copy_bytes; + *user_bytes_copied += copy_bytes; + } + + return 0; +} + +static int +copy_samples_to_user(struct ivpu_device *vdev, struct ivpu_ms_instance *ms, + void __user *user_ptr, u64 user_size, u64 *user_bytes_copied) +{ + u64 bytes_written; + int ret; + + *user_bytes_copied = 0; + + ret = copy_leftover_bytes(ms, user_ptr, user_size, user_bytes_copied); + if (ret) + return ret; + + if (*user_bytes_copied == user_size) + return 0; + + ret = ivpu_jsm_metric_streamer_update(vdev, ms->mask, ms->inactive_buff_vpu_addr, + ms->buff_size, &bytes_written); + if (ret) + return ret; + + swap(ms->active_buff_vpu_addr, ms->inactive_buff_vpu_addr); + swap(ms->active_buff_ptr, ms->inactive_buff_ptr); + + ms->leftover_bytes = bytes_written; + ms->leftover_addr = ms->inactive_buff_ptr; + + return copy_leftover_bytes(ms, user_ptr, user_size, user_bytes_copied); +} + +int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct drm_ivpu_metric_streamer_get_data *args = data; + struct ivpu_file_priv *file_priv = file->driver_priv; + struct ivpu_device *vdev = file_priv->vdev; + struct ivpu_ms_instance *ms; + u64 bytes_written; + int ret; + + if (!args->metric_group_mask) + return -EINVAL; + + mutex_lock(&file_priv->ms_lock); + + ms = get_instance_by_mask(file_priv, args->metric_group_mask); + if (!ms) { + ivpu_err(vdev, "Instance doesn't exist for mask: %#llx\n", args->metric_group_mask); + ret = -EINVAL; + goto unlock; + } + + if (!args->buffer_size) { + ret = ivpu_jsm_metric_streamer_update(vdev, ms->mask, 0, 0, &bytes_written); + if (ret) + goto unlock; + args->data_size = bytes_written + ms->leftover_bytes; + goto unlock; + } + + if (!args->buffer_ptr) { + ret = -EINVAL; + goto unlock; + } + + ret = copy_samples_to_user(vdev, ms, u64_to_user_ptr(args->buffer_ptr), + args->buffer_size, &args->data_size); +unlock: + mutex_unlock(&file_priv->ms_lock); + + return ret; +} + +static void free_instance(struct ivpu_file_priv *file_priv, struct ivpu_ms_instance *ms) +{ + lockdep_assert_held(&file_priv->ms_lock); + + list_del(&ms->ms_instance_node); + ivpu_jsm_metric_streamer_stop(file_priv->vdev, ms->mask); + ivpu_bo_free(ms->bo); + kfree(ms); +} + +int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct ivpu_file_priv *file_priv = file->driver_priv; + struct drm_ivpu_metric_streamer_stop *args = data; + struct ivpu_ms_instance *ms; + + if (!args->metric_group_mask) + return -EINVAL; + + mutex_lock(&file_priv->ms_lock); + + ms = get_instance_by_mask(file_priv, args->metric_group_mask); + if (ms) + free_instance(file_priv, ms); + + mutex_unlock(&file_priv->ms_lock); + + return ms ? 0 : -EINVAL; +} + +static inline struct ivpu_bo *get_ms_info_bo(struct ivpu_file_priv *file_priv) +{ + lockdep_assert_held(&file_priv->ms_lock); + + if (file_priv->ms_info_bo) + return file_priv->ms_info_bo; + + file_priv->ms_info_bo = ivpu_bo_create_global(file_priv->vdev, MS_INFO_BUFFER_SIZE, + DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE); + return file_priv->ms_info_bo; +} + +int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + struct drm_ivpu_metric_streamer_get_data *args = data; + struct ivpu_file_priv *file_priv = file->driver_priv; + struct ivpu_device *vdev = file_priv->vdev; + struct ivpu_bo *bo; + u64 info_size; + int ret; + + if (!args->metric_group_mask) + return -EINVAL; + + if (!args->buffer_size) + return ivpu_jsm_metric_streamer_info(vdev, args->metric_group_mask, + 0, 0, NULL, &args->data_size); + if (!args->buffer_ptr) + return -EINVAL; + + mutex_lock(&file_priv->ms_lock); + + bo = get_ms_info_bo(file_priv); + if (!bo) { + ret = -ENOMEM; + goto unlock; + } + + ret = ivpu_jsm_metric_streamer_info(vdev, args->metric_group_mask, bo->vpu_addr, + ivpu_bo_size(bo), NULL, &info_size); + if (ret) + goto unlock; + + if (args->buffer_size < info_size) { + ret = -ENOSPC; + goto unlock; + } + + if (copy_to_user(u64_to_user_ptr(args->buffer_ptr), ivpu_bo_vaddr(bo), info_size)) + ret = -EFAULT; + + args->data_size = info_size; +unlock: + mutex_unlock(&file_priv->ms_lock); + + return ret; +} + +void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv) +{ + struct ivpu_ms_instance *ms, *tmp; + + mutex_lock(&file_priv->ms_lock); + + if (file_priv->ms_info_bo) { + ivpu_bo_free(file_priv->ms_info_bo); + file_priv->ms_info_bo = NULL; + } + + list_for_each_entry_safe(ms, tmp, &file_priv->ms_instance_list, ms_instance_node) + free_instance(file_priv, ms); + + mutex_unlock(&file_priv->ms_lock); +} + +void ivpu_ms_cleanup_all(struct ivpu_device *vdev) +{ + struct ivpu_file_priv *file_priv; + unsigned long ctx_id; + + mutex_lock(&vdev->context_list_lock); + + xa_for_each(&vdev->context_xa, ctx_id, file_priv) + ivpu_ms_cleanup(file_priv); + + mutex_unlock(&vdev->context_list_lock); +} diff --git a/drivers/accel/ivpu/ivpu_ms.h b/drivers/accel/ivpu/ivpu_ms.h new file mode 100644 index 000000000000..fbd5ebebc3d9 --- /dev/null +++ b/drivers/accel/ivpu/ivpu_ms.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ +/* + * Copyright (C) 2020-2024 Intel Corporation + */ +#ifndef __IVPU_MS_H__ +#define __IVPU_MS_H__ + +#include <linux/list.h> + +struct drm_device; +struct drm_file; +struct ivpu_bo; +struct ivpu_device; +struct ivpu_file_priv; + +struct ivpu_ms_instance { + struct ivpu_bo *bo; + struct list_head ms_instance_node; + u64 mask; + u64 buff_size; + u64 active_buff_vpu_addr; + u64 inactive_buff_vpu_addr; + void *active_buff_ptr; + void *inactive_buff_ptr; + u64 leftover_bytes; + void *leftover_addr; +}; + +int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv); +void ivpu_ms_cleanup_all(struct ivpu_device *vdev); + +#endif /* __IVPU_MS_H__ */ diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index 4f5ea466731f..59d3170f5e35 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -18,6 +18,7 @@ #include "ivpu_job.h" #include "ivpu_jsm_msg.h" #include "ivpu_mmu.h" +#include "ivpu_ms.h" #include "ivpu_pm.h" static bool ivpu_disable_recovery; @@ -131,6 +132,7 @@ static void ivpu_pm_recovery_work(struct work_struct *work) ivpu_suspend(vdev); ivpu_pm_prepare_cold_boot(vdev); ivpu_jobs_abort_all(vdev); + ivpu_ms_cleanup_all(vdev); ret = ivpu_resume(vdev); if (ret) @@ -235,41 +237,37 @@ int ivpu_pm_runtime_suspend_cb(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); struct ivpu_device *vdev = to_ivpu_device(drm); - bool hw_is_idle = true; - int ret; + int ret, ret_d0i3; + bool is_idle; drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa)); drm_WARN_ON(&vdev->drm, work_pending(&vdev->pm->recovery_work)); ivpu_dbg(vdev, PM, "Runtime suspend..\n"); - if (!ivpu_hw_is_idle(vdev) && vdev->pm->suspend_reschedule_counter) { - ivpu_dbg(vdev, PM, "Failed to enter idle, rescheduling suspend, retries left %d\n", - vdev->pm->suspend_reschedule_counter); - pm_schedule_suspend(dev, vdev->timeout.reschedule_suspend); - vdev->pm->suspend_reschedule_counter--; - return -EAGAIN; - } + ivpu_mmu_disable(vdev); + + is_idle = ivpu_hw_is_idle(vdev) || vdev->pm->dct_active_percent; + if (!is_idle) + ivpu_err(vdev, "NPU is not idle before autosuspend\n"); - if (!vdev->pm->suspend_reschedule_counter) - hw_is_idle = false; - else if (ivpu_jsm_pwr_d0i3_enter(vdev)) - hw_is_idle = false; + ret_d0i3 = ivpu_jsm_pwr_d0i3_enter(vdev); + if (ret_d0i3) + ivpu_err(vdev, "Failed to prepare for d0i3: %d\n", ret_d0i3); ret = ivpu_suspend(vdev); if (ret) ivpu_err(vdev, "Failed to suspend NPU: %d\n", ret); - if (!hw_is_idle) { - ivpu_err(vdev, "NPU failed to enter idle, force suspended.\n"); + if (!is_idle || ret_d0i3) { + ivpu_err(vdev, "Forcing cold boot due to previous errors\n"); + atomic_inc(&vdev->pm->reset_counter); ivpu_fw_log_dump(vdev); ivpu_pm_prepare_cold_boot(vdev); } else { ivpu_pm_prepare_warm_boot(vdev); } - vdev->pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT; - ivpu_dbg(vdev, PM, "Runtime suspend done.\n"); return 0; @@ -297,17 +295,6 @@ int ivpu_rpm_get(struct ivpu_device *vdev) int ret; ret = pm_runtime_resume_and_get(vdev->drm.dev); - if (!drm_WARN_ON(&vdev->drm, ret < 0)) - vdev->pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT; - - return ret; -} - -int ivpu_rpm_get_if_active(struct ivpu_device *vdev) -{ - int ret; - - ret = pm_runtime_get_if_in_use(vdev->drm.dev); drm_WARN_ON(&vdev->drm, ret < 0); return ret; @@ -333,6 +320,8 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev) ivpu_hw_reset(vdev); ivpu_pm_prepare_cold_boot(vdev); ivpu_jobs_abort_all(vdev); + ivpu_ms_cleanup_all(vdev); + ivpu_dbg(vdev, PM, "Pre-reset done.\n"); } @@ -360,7 +349,6 @@ void ivpu_pm_init(struct ivpu_device *vdev) int delay; pm->vdev = vdev; - pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT; init_rwsem(&pm->reset_lock); atomic_set(&pm->reset_pending, 0); @@ -401,3 +389,68 @@ void ivpu_pm_disable(struct ivpu_device *vdev) pm_runtime_get_noresume(vdev->drm.dev); pm_runtime_forbid(vdev->drm.dev); } + +int ivpu_pm_dct_init(struct ivpu_device *vdev) +{ + if (vdev->pm->dct_active_percent) + return ivpu_pm_dct_enable(vdev, vdev->pm->dct_active_percent); + + return 0; +} + +int ivpu_pm_dct_enable(struct ivpu_device *vdev, u8 active_percent) +{ + u32 active_us, inactive_us; + int ret; + + if (active_percent == 0 || active_percent > 100) + return -EINVAL; + + active_us = (DCT_PERIOD_US * active_percent) / 100; + inactive_us = DCT_PERIOD_US - active_us; + + ret = ivpu_jsm_dct_enable(vdev, active_us, inactive_us); + if (ret) { + ivpu_err_ratelimited(vdev, "Filed to enable DCT: %d\n", ret); + return ret; + } + + vdev->pm->dct_active_percent = active_percent; + + ivpu_dbg(vdev, PM, "DCT set to %u%% (D0: %uus, D0i2: %uus)\n", + active_percent, active_us, inactive_us); + return 0; +} + +int ivpu_pm_dct_disable(struct ivpu_device *vdev) +{ + int ret; + + ret = ivpu_jsm_dct_disable(vdev); + if (ret) { + ivpu_err_ratelimited(vdev, "Filed to disable DCT: %d\n", ret); + return ret; + } + + vdev->pm->dct_active_percent = 0; + + ivpu_dbg(vdev, PM, "DCT disabled\n"); + return 0; +} + +void ivpu_pm_dct_irq_thread_handler(struct ivpu_device *vdev) +{ + bool enable; + int ret; + + if (ivpu_hw_btrs_dct_get_request(vdev, &enable)) + return; + + if (vdev->pm->dct_active_percent) + ret = ivpu_pm_dct_enable(vdev, DCT_DEFAULT_ACTIVE_PERCENT); + else + ret = ivpu_pm_dct_disable(vdev); + + if (!ret) + ivpu_hw_btrs_dct_set_status(vdev, enable, vdev->pm->dct_active_percent); +} diff --git a/drivers/accel/ivpu/ivpu_pm.h b/drivers/accel/ivpu/ivpu_pm.h index ec60fbeefefc..b70efe6c36e4 100644 --- a/drivers/accel/ivpu/ivpu_pm.h +++ b/drivers/accel/ivpu/ivpu_pm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #ifndef __IVPU_PM_H__ @@ -19,7 +19,7 @@ struct ivpu_pm_info { atomic_t reset_counter; atomic_t reset_pending; bool is_warmboot; - u32 suspend_reschedule_counter; + u8 dct_active_percent; }; void ivpu_pm_init(struct ivpu_device *vdev); @@ -36,11 +36,15 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev); void ivpu_pm_reset_done_cb(struct pci_dev *pdev); int __must_check ivpu_rpm_get(struct ivpu_device *vdev); -int __must_check ivpu_rpm_get_if_active(struct ivpu_device *vdev); void ivpu_rpm_put(struct ivpu_device *vdev); void ivpu_pm_trigger_recovery(struct ivpu_device *vdev, const char *reason); void ivpu_start_job_timeout_detection(struct ivpu_device *vdev); void ivpu_stop_job_timeout_detection(struct ivpu_device *vdev); +int ivpu_pm_dct_init(struct ivpu_device *vdev); +int ivpu_pm_dct_enable(struct ivpu_device *vdev, u8 active_percent); +int ivpu_pm_dct_disable(struct ivpu_device *vdev); +void ivpu_pm_dct_irq_thread_handler(struct ivpu_device *vdev); + #endif /* __IVPU_PM_H__ */ diff --git a/drivers/accel/ivpu/ivpu_sysfs.c b/drivers/accel/ivpu/ivpu_sysfs.c new file mode 100644 index 000000000000..913669f1786e --- /dev/null +++ b/drivers/accel/ivpu/ivpu_sysfs.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024 Intel Corporation + */ + +#include <linux/device.h> +#include <linux/err.h> + +#include "ivpu_hw.h" +#include "ivpu_sysfs.h" + +/* + * npu_busy_time_us is the time that the device spent executing jobs. + * The time is counted when and only when there are jobs submitted to firmware. + * + * This time can be used to measure the utilization of NPU, either by calculating + * npu_busy_time_us difference between two timepoints (i.e. measuring the time + * that the NPU was active during some workload) or monitoring utilization percentage + * by reading npu_busy_time_us periodically. + * + * When reading the value periodically, it shouldn't be read too often as it may have + * an impact on job submission performance. Recommended period is 1 second. + */ +static ssize_t +npu_busy_time_us_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct drm_device *drm = dev_get_drvdata(dev); + struct ivpu_device *vdev = to_ivpu_device(drm); + ktime_t total, now = 0; + + xa_lock(&vdev->submitted_jobs_xa); + total = vdev->busy_time; + if (!xa_empty(&vdev->submitted_jobs_xa)) + now = ktime_sub(ktime_get(), vdev->busy_start_ts); + xa_unlock(&vdev->submitted_jobs_xa); + + return sysfs_emit(buf, "%lld\n", ktime_to_us(ktime_add(total, now))); +} + +static DEVICE_ATTR_RO(npu_busy_time_us); + +static struct attribute *ivpu_dev_attrs[] = { + &dev_attr_npu_busy_time_us.attr, + NULL, +}; + +static struct attribute_group ivpu_dev_attr_group = { + .attrs = ivpu_dev_attrs, +}; + +void ivpu_sysfs_init(struct ivpu_device *vdev) +{ + int ret; + + ret = devm_device_add_group(vdev->drm.dev, &ivpu_dev_attr_group); + if (ret) + ivpu_warn(vdev, "Failed to add group to device, ret %d", ret); +} diff --git a/drivers/accel/ivpu/ivpu_sysfs.h b/drivers/accel/ivpu/ivpu_sysfs.h new file mode 100644 index 000000000000..9836f09b35a3 --- /dev/null +++ b/drivers/accel/ivpu/ivpu_sysfs.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2024 Intel Corporation + */ + +#ifndef __IVPU_SYSFS_H__ +#define __IVPU_SYSFS_H__ + +#include "ivpu_drv.h" + +void ivpu_sysfs_init(struct ivpu_device *vdev); + +#endif /* __IVPU_SYSFS_H__ */ diff --git a/drivers/accel/ivpu/vpu_boot_api.h b/drivers/accel/ivpu/vpu_boot_api.h index 87cac7bc730a..82954b91b748 100644 --- a/drivers/accel/ivpu/vpu_boot_api.h +++ b/drivers/accel/ivpu/vpu_boot_api.h @@ -27,7 +27,7 @@ * Minor version changes when API backward compatibility is preserved. * Resets to 0 if Major version is incremented. */ -#define VPU_BOOT_API_VER_MINOR 22 +#define VPU_BOOT_API_VER_MINOR 24 /* * API header changed (field names, documentation, formatting) but API itself has not been changed @@ -80,6 +80,11 @@ struct vpu_firmware_header { u32 preemption_buffer_2_size; /* Space reserved for future preemption-related fields. */ u32 preemption_reserved[6]; + /* FW image read only section start address, 4KB aligned */ + u64 ro_section_start_address; + /* FW image read only section size, 4KB aligned */ + u32 ro_section_size; + u32 reserved; }; /* @@ -333,7 +338,14 @@ struct vpu_boot_params { * The KMD is required to update this value on every VPU reset. */ u64 system_time_us; - u32 pad4[18]; + u32 pad4[2]; + /* + * The delta between device monotonic time and the current value of the + * HW timestamp register, in ticks. Written by the firmware during boot. + * Can be used by the KMD to calculate device time. + */ + u64 device_time_delta_ticks; + u32 pad7[14]; /* Warm boot information: 0x400 - 0x43F */ u32 warm_boot_sections_count; u32 warm_boot_start_address_reference; diff --git a/drivers/accel/ivpu/vpu_jsm_api.h b/drivers/accel/ivpu/vpu_jsm_api.h index e46f3531211a..33f462b1a25d 100644 --- a/drivers/accel/ivpu/vpu_jsm_api.h +++ b/drivers/accel/ivpu/vpu_jsm_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: MIT */ /* - * Copyright (c) 2020-2023, Intel Corporation. + * Copyright (c) 2020-2024, Intel Corporation. */ /** @@ -22,12 +22,12 @@ /* * Minor version changes when API backward compatibility is preserved. */ -#define VPU_JSM_API_VER_MINOR 15 +#define VPU_JSM_API_VER_MINOR 16 /* * API header changed (field names, documentation, formatting) but API itself has not been changed */ -#define VPU_JSM_API_VER_PATCH 6 +#define VPU_JSM_API_VER_PATCH 0 /* * Index in the API version table @@ -868,6 +868,14 @@ struct vpu_ipc_msg_payload_hws_set_scheduling_log { * is generated when an event log is written to this index. */ u64 notify_index; + /* + * Enable extra events to be output to log for debug of scheduling algorithm. + * Interpreted by VPU as a boolean to enable or disable, expected values are + * 0 and 1. + */ + u32 enable_extra_events; + /* Zero Padding */ + u32 reserved_0; }; /* diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index ce8651436609..8e41731d3642 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -802,4 +802,5 @@ module_exit(agp_amd64_cleanup); MODULE_AUTHOR("Dave Jones, Andi Kleen"); module_param(agp_try_unsupported, bool, 0); +MODULE_DESCRIPTION("GART driver for the AMD Opteron/Athlon64 on-CPU northbridge"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index c518b3a9db04..3111e320b2c5 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -12,7 +12,7 @@ #include <asm/smp.h> #include "agp.h" #include "intel-agp.h" -#include <drm/intel-gtt.h> +#include <drm/intel/intel-gtt.h> static int intel_fetch_size(void) { @@ -920,4 +920,5 @@ module_init(agp_intel_init); module_exit(agp_intel_cleanup); MODULE_AUTHOR("Dave Jones, Various @Intel"); +MODULE_DESCRIPTION("Intel AGPGART routines"); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index bf6716ff863b..ef30445527a2 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -25,7 +25,7 @@ #include <asm/smp.h> #include "agp.h" #include "intel-agp.h" -#include <drm/intel-gtt.h> +#include <drm/intel/intel-gtt.h> #include <asm/set_memory.h> /* @@ -1461,4 +1461,5 @@ void intel_gmch_remove(void) EXPORT_SYMBOL(intel_gmch_remove); MODULE_AUTHOR("Dave Jones, Various @Intel"); +MODULE_DESCRIPTION("Intel GTT (Graphics Translation Table) routines"); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index 484bb101c53b..a0deb97cedb0 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c @@ -433,4 +433,5 @@ module_param(agp_sis_force_delay, bool, 0); MODULE_PARM_DESC(agp_sis_force_delay,"forces sis delay hack"); module_param(agp_sis_agp_spec, int, 0); MODULE_PARM_DESC(agp_sis_agp_spec,"0=force sis init, 1=force generic agp3 init, default: autodetect"); +MODULE_DESCRIPTION("SiS AGPGART routines"); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index bc5140af2dcb..8b19a5d1a09b 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c @@ -575,5 +575,6 @@ static void __exit agp_via_cleanup(void) module_init(agp_via_init); module_exit(agp_via_cleanup); +MODULE_DESCRIPTION("VIA AGPGART routines"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Dave Jones"); diff --git a/drivers/dma-buf/dma-fence-array.c b/drivers/dma-buf/dma-fence-array.c index 9b3ce8948351..c74ac197d5fe 100644 --- a/drivers/dma-buf/dma-fence-array.c +++ b/drivers/dma-buf/dma-fence-array.c @@ -70,7 +70,7 @@ static void dma_fence_array_cb_func(struct dma_fence *f, static bool dma_fence_array_enable_signaling(struct dma_fence *fence) { struct dma_fence_array *array = to_dma_fence_array(fence); - struct dma_fence_array_cb *cb = (void *)(&array[1]); + struct dma_fence_array_cb *cb = array->callbacks; unsigned i; for (i = 0; i < array->num_fences; ++i) { @@ -168,22 +168,20 @@ struct dma_fence_array *dma_fence_array_create(int num_fences, bool signal_on_any) { struct dma_fence_array *array; - size_t size = sizeof(*array); WARN_ON(!num_fences || !fences); - /* Allocate the callback structures behind the array. */ - size += num_fences * sizeof(struct dma_fence_array_cb); - array = kzalloc(size, GFP_KERNEL); + array = kzalloc(struct_size(array, callbacks, num_fences), GFP_KERNEL); if (!array) return NULL; + array->num_fences = num_fences; + spin_lock_init(&array->lock); dma_fence_init(&array->base, &dma_fence_array_ops, &array->lock, context, seqno); init_irq_work(&array->work, irq_dma_fence_array_work); - array->num_fences = num_fences; atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences); array->fences = fences; diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index 84ae708fafe7..2298ca5e112e 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -50,8 +50,8 @@ static struct class *dma_heap_class; static DEFINE_XARRAY_ALLOC(dma_heap_minors); static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, - unsigned int fd_flags, - unsigned int heap_flags) + u32 fd_flags, + u64 heap_flags) { struct dma_buf *dmabuf; int fd; diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index e2869fb31140..5f8d010516f0 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -186,6 +186,13 @@ int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences) dma_resv_assert_held(obj); + /* Driver and component code should never call this function with + * num_fences=0. If they do it usually points to bugs when calculating + * the number of needed fences dynamically. + */ + if (WARN_ON(!num_fences)) + return -EINVAL; + old = dma_resv_fences_list(obj); if (old && old->max_fences) { if ((old->num_fences + num_fences) <= old->max_fences) diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index 4a63567e93ba..c384004b918e 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -274,8 +274,8 @@ static const struct dma_buf_ops cma_heap_buf_ops = { static struct dma_buf *cma_heap_allocate(struct dma_heap *heap, unsigned long len, - unsigned long fd_flags, - unsigned long heap_flags) + u32 fd_flags, + u64 heap_flags) { struct cma_heap *cma_heap = dma_heap_get_drvdata(heap); struct cma_heap_buffer *buffer; diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 9076d47ed2ef..d78cdb9d01e5 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -333,8 +333,8 @@ static struct page *alloc_largest_available(unsigned long size, static struct dma_buf *system_heap_allocate(struct dma_heap *heap, unsigned long len, - unsigned long fd_flags, - unsigned long heap_flags) + u32 fd_flags, + u64 heap_flags) { struct system_heap_buffer *buffer; DEFINE_DMA_BUF_EXPORT_INFO(exp_info); diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 026444eeb5c6..f5c989aed7e9 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -79,6 +79,7 @@ config DRM_KUNIT_TEST depends on DRM && KUNIT && MMU select DRM_BUDDY select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER select DRM_DISPLAY_HELPER select DRM_EXEC select DRM_EXPORT_FOR_TESTS if m @@ -106,7 +107,7 @@ config DRM_KMS_HELPER config DRM_PANIC bool "Display a user-friendly message when a kernel panic occurs" - depends on DRM && !FRAMEBUFFER_CONSOLE + depends on DRM && !(FRAMEBUFFER_CONSOLE && VT_CONSOLE) select DRM_KMS_HELPER select FONT_SUPPORT help @@ -136,6 +137,19 @@ config DRM_PANIC_DEBUG This is unsafe and should not be enabled on a production build. If in doubt, say "N". +config DRM_PANIC_SCREEN + string "Panic screen formater" + default "user" + depends on DRM_PANIC + help + This option enable to choose what will be displayed when a kernel + panic occurs. You can choose between "user", a short message telling + the user to reboot the system, or "kmsg" which will display the last + lines of kmsg. + This can also be overridden by drm.panic_screen=xxxx kernel parameter + or by writing to /sys/module/drm/parameters/panic_screen sysfs entry + Default is "user" + config DRM_DEBUG_DP_MST_TOPOLOGY_REFS bool "Enable refcount backtrace history in the DP MST helpers" depends on STACKTRACE_SUPPORT diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index f9ca4f8fa6c5..68cc9258ffc4 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -108,6 +108,7 @@ drm_dma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o drm_shmem_helper-y := drm_gem_shmem_helper.o +drm_shmem_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fbdev_shmem.o obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o drm_suballoc_helper-y := drm_suballoc.o @@ -117,6 +118,7 @@ drm_vram_helper-y := drm_gem_vram_helper.o obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o drm_ttm_helper-y := drm_gem_ttm_helper.o +drm_ttm_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fbdev_ttm.o obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o # @@ -142,9 +144,7 @@ drm_kms_helper-y := \ drm_self_refresh_helper.o \ drm_simple_kms_helper.o drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o -drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += \ - drm_fbdev_generic.o \ - drm_fb_helper.o +drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o # diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 9caba10315a8..cae7479c3ecf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -246,22 +246,6 @@ amdgpu_connector_find_encoder(struct drm_connector *connector, return NULL; } -struct edid *amdgpu_connector_edid(struct drm_connector *connector) -{ - struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - struct drm_property_blob *edid_blob = connector->edid_blob_ptr; - - if (amdgpu_connector->edid) { - return amdgpu_connector->edid; - } else if (edid_blob) { - struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL); - - if (edid) - amdgpu_connector->edid = edid; - } - return amdgpu_connector->edid; -} - static struct edid * amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h index 61fcef15ad72..eff833b6ed31 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.h @@ -24,7 +24,6 @@ #ifndef __AMDGPU_CONNECTORS_H__ #define __AMDGPU_CONNECTORS_H__ -struct edid *amdgpu_connector_edid(struct drm_connector *connector); void amdgpu_connector_hotplug(struct drm_connector *connector); int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector); u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 2da76fadf6ea..9f2db858c6e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -24,7 +24,7 @@ #include <drm/amdgpu_drm.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_ttm.h> #include <drm/drm_gem.h> #include <drm/drm_managed.h> #include <drm/drm_pciids.h> @@ -2346,9 +2346,9 @@ retry_init: !list_empty(&adev_to_drm(adev)->mode_config.connector_list)) { /* select 8 bpp console on low vram cards */ if (adev->gmc.real_vram_size <= (32*1024*1024)) - drm_fbdev_generic_setup(adev_to_drm(adev), 8); + drm_fbdev_ttm_setup(adev_to_drm(adev), 8); else - drm_fbdev_generic_setup(adev_to_drm(adev), 32); + drm_fbdev_ttm_setup(adev_to_drm(adev), 32); } ret = amdgpu_debugfs_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c index e30eecd02ae1..821f9491565b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c @@ -65,9 +65,7 @@ static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer) static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) { - struct drm_device *dev = crtc->dev; - unsigned int pipe = drm_crtc_index(crtc); - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); @@ -91,10 +89,8 @@ static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc, ktime_t *vblank_time, bool in_vblank_irq) { - struct drm_device *dev = crtc->dev; - unsigned int pipe = crtc->index; struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc); - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); if (!READ_ONCE(vblank->enabled)) { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index b44fce44c066..dddb5fe16f2c 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -1299,7 +1299,7 @@ static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder return; } - sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb); + sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb); if (sad_count < 0) { DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); sad_count = 0; @@ -1369,7 +1369,7 @@ static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder) return; } - sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads); + sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads); if (sad_count < 0) DRM_ERROR("Couldn't read SADs: %d\n", sad_count); if (sad_count <= 0) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 80b2e7f79acf..11780e4d7e9f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -1331,7 +1331,7 @@ static void dce_v11_0_audio_write_speaker_allocation(struct drm_encoder *encoder return; } - sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb); + sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb); if (sad_count < 0) { DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); sad_count = 0; @@ -1401,7 +1401,7 @@ static void dce_v11_0_audio_write_sad_regs(struct drm_encoder *encoder) return; } - sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads); + sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads); if (sad_count < 0) DRM_ERROR("Couldn't read SADs: %d\n", sad_count); if (sad_count <= 0) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index db20012600f5..05c0df97f01d 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -1217,7 +1217,7 @@ static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder) return; } - sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb); + sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb); if (sad_count < 0) { DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); sad_count = 0; @@ -1292,7 +1292,7 @@ static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder) return; } - sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads); + sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads); if (sad_count < 0) DRM_ERROR("Couldn't read SADs: %d\n", sad_count); if (sad_count <= 0) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 5b56100ec902..dc73e301d937 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -1272,7 +1272,7 @@ static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder) return; } - sad_count = drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector), &sadb); + sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb); if (sad_count < 0) { DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); sad_count = 0; @@ -1340,7 +1340,7 @@ static void dce_v8_0_audio_write_sad_regs(struct drm_encoder *encoder) return; } - sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads); + sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads); if (sad_count < 0) DRM_ERROR("Couldn't read SADs: %d\n", sad_count); if (sad_count <= 0) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6196de6cebbf..ac18cddeb191 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -534,7 +534,7 @@ static void dm_vupdate_high_irq(void *interrupt_params) if (acrtc) { vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc); drm_dev = acrtc->base.dev; - vblank = &drm_dev->vblank[acrtc->base.index]; + vblank = drm_crtc_vblank_crtc(&acrtc->base); previous_timestamp = atomic64_read(&irq_params->previous_timestamp); frame_duration_ns = vblank->time - previous_timestamp; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index 2c661f28410e..2ad33559a33a 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -5,6 +5,7 @@ * */ #include <linux/clk.h> +#include <linux/of.h> #include <linux/pm_runtime.h> #include <linux/spinlock.h> @@ -294,7 +295,6 @@ komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, struct komeda_dev *mdev = kcrtc->master->mdev; struct completion *flip_done; struct completion temp; - int timeout; /* if caller doesn't send a flip_done, use a private flip_done */ if (input_flip_done) { @@ -308,8 +308,7 @@ komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, mdev->funcs->flush(mdev, kcrtc->master->id, 0); /* wait the flip take affect.*/ - timeout = wait_for_completion_timeout(flip_done, HZ); - if (timeout == 0) { + if (wait_for_completion_timeout(flip_done, HZ) == 0) { DRM_ERROR("wait pipe%d flip done timeout\n", kcrtc->master->id); if (!input_flip_done) { unsigned long flags; @@ -610,12 +609,34 @@ get_crtc_primary(struct komeda_kms_dev *kms, struct komeda_crtc *crtc) return NULL; } +static int komeda_attach_bridge(struct device *dev, + struct komeda_pipeline *pipe, + struct drm_encoder *encoder) +{ + struct drm_bridge *bridge; + int err; + + bridge = devm_drm_of_get_bridge(dev, pipe->of_node, + KOMEDA_OF_PORT_OUTPUT, 0); + if (IS_ERR(bridge)) + return dev_err_probe(dev, PTR_ERR(bridge), "remote bridge not found for pipe: %s\n", + of_node_full_name(pipe->of_node)); + + err = drm_bridge_attach(encoder, bridge, NULL, 0); + if (err) + dev_err(dev, "bridge_attach() failed for pipe: %s\n", + of_node_full_name(pipe->of_node)); + + return err; +} + static int komeda_crtc_add(struct komeda_kms_dev *kms, struct komeda_crtc *kcrtc) { struct drm_crtc *crtc = &kcrtc->base; struct drm_device *base = &kms->base; - struct drm_bridge *bridge; + struct komeda_pipeline *pipe = kcrtc->master; + struct drm_encoder *encoder = &kcrtc->encoder; int err; err = drm_crtc_init_with_planes(base, crtc, @@ -626,27 +647,27 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms, drm_crtc_helper_add(crtc, &komeda_crtc_helper_funcs); - crtc->port = kcrtc->master->of_output_port; + crtc->port = pipe->of_output_port; /* Construct an encoder for each pipeline and attach it to the remote * bridge */ kcrtc->encoder.possible_crtcs = drm_crtc_mask(crtc); - err = drm_simple_encoder_init(base, &kcrtc->encoder, - DRM_MODE_ENCODER_TMDS); + err = drm_simple_encoder_init(base, encoder, DRM_MODE_ENCODER_TMDS); if (err) return err; - bridge = devm_drm_of_get_bridge(base->dev, kcrtc->master->of_node, - KOMEDA_OF_PORT_OUTPUT, 0); - if (IS_ERR(bridge)) - return PTR_ERR(bridge); - - err = drm_bridge_attach(&kcrtc->encoder, bridge, NULL, 0); + if (pipe->of_output_links[0]) { + err = komeda_attach_bridge(base->dev, pipe, encoder); + if (err) + return err; + } drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE); - return err; + komeda_pipeline_dump(pipe); + + return 0; } int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c index cc57ea4e13ae..55c3773befde 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c @@ -9,7 +9,7 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_module.h> #include <drm/drm_of.h> #include "komeda_dev.h" @@ -59,6 +59,10 @@ static int komeda_platform_probe(struct platform_device *pdev) struct komeda_drv *mdrv; int err; + err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); + if (err) + return dev_err_probe(dev, err, "DMA mask error\n"); + mdrv = devm_kzalloc(dev, sizeof(*mdrv), GFP_KERNEL); if (!mdrv) return -ENOMEM; @@ -80,7 +84,7 @@ static int komeda_platform_probe(struct platform_device *pdev) } dev_set_drvdata(dev, mdrv); - drm_fbdev_generic_setup(&mdrv->kms->base, 32); + drm_fbdev_dma_setup(&mdrv->kms->base, 32); return 0; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h index a4048724564d..83e61c4080c2 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h @@ -191,5 +191,6 @@ void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev); void komeda_kms_detach(struct komeda_kms_dev *kms); void komeda_kms_shutdown(struct komeda_kms_dev *kms); +void komeda_pipeline_dump(struct komeda_pipeline *pipe); #endif /*_KOMEDA_KMS_H_*/ diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c index 00f5864a0495..81e244f0c0ca 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c @@ -10,6 +10,7 @@ #include <drm/drm_print.h> #include "komeda_dev.h" +#include "komeda_kms.h" #include "komeda_pipeline.h" /** komeda_pipeline_add - Add a pipeline to &komeda_dev */ @@ -247,7 +248,7 @@ static void komeda_component_dump(struct komeda_component *c) c->max_active_outputs, c->supported_outputs); } -static void komeda_pipeline_dump(struct komeda_pipeline *pipe) +void komeda_pipeline_dump(struct komeda_pipeline *pipe) { struct komeda_component *c; int id; @@ -351,7 +352,6 @@ int komeda_assemble_pipelines(struct komeda_dev *mdev) pipe = mdev->pipelines[i]; komeda_pipeline_assemble(pipe); - komeda_pipeline_dump(pipe); } return 0; diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index f8c49ba68e78..aae019e79bda 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -33,7 +33,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_gem_shmem_helper.h> #include <drm/drm_module.h> #include <drm/drm_probe_helper.h> @@ -360,7 +360,7 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) return ret; - drm_fbdev_generic_setup(drm, 32); + drm_fbdev_shmem_setup(drm, 32); return 0; } diff --git a/drivers/gpu/drm/atmel-hlcdc/Kconfig b/drivers/gpu/drm/atmel-hlcdc/Kconfig index 3bdbab3a6333..945f3aa7bb24 100644 --- a/drivers/gpu/drm/atmel-hlcdc/Kconfig +++ b/drivers/gpu/drm/atmel-hlcdc/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_ATMEL_HLCDC tristate "DRM Support for ATMEL HLCDC Display Controller" - depends on DRM && OF && COMMON_CLK && MFD_ATMEL_HLCDC && ARM + depends on DRM && OF && COMMON_CLK && ((MFD_ATMEL_HLCDC && ARM) || COMPILE_TEST) select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index cc5cf4c2faf7..0f7ffb3ced20 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -30,10 +30,12 @@ * * @base: base CRTC state * @output_mode: RGBXXX output mode + * @dpi: output DPI mode */ struct atmel_hlcdc_crtc_state { struct drm_crtc_state base; unsigned int output_mode; + u8 dpi; }; static inline struct atmel_hlcdc_crtc_state * @@ -164,18 +166,24 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state); cfg = state->output_mode << 8; - if (adj->flags & DRM_MODE_FLAG_NVSYNC) - cfg |= ATMEL_HLCDC_VSPOL; + if (!crtc->dc->desc->is_xlcdc) { + if (adj->flags & DRM_MODE_FLAG_NVSYNC) + cfg |= ATMEL_HLCDC_VSPOL; - if (adj->flags & DRM_MODE_FLAG_NHSYNC) - cfg |= ATMEL_HLCDC_HSPOL; + if (adj->flags & DRM_MODE_FLAG_NHSYNC) + cfg |= ATMEL_HLCDC_HSPOL; + } else { + cfg |= state->dpi << 11; + } regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5), ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL | ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE | ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY | ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | - ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK, + ATMEL_HLCDC_GUARDTIME_MASK | + (crtc->dc->desc->is_xlcdc ? ATMEL_XLCDC_MODE_MASK | + ATMEL_XLCDC_DPI : ATMEL_HLCDC_MODE_MASK), cfg); clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); @@ -202,20 +210,37 @@ static void atmel_hlcdc_crtc_atomic_disable(struct drm_crtc *c, pm_runtime_get_sync(dev->dev); + if (crtc->dc->desc->is_xlcdc) { + regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_XLCDC_CM); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + !(status & ATMEL_XLCDC_CM), + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register CMSTS timeout\n"); + + regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_XLCDC_SD); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + status & ATMEL_XLCDC_SD, + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register SDSTS timeout\n"); + } + regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - (status & ATMEL_HLCDC_DISP)) - cpu_relax(); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + !(status & ATMEL_HLCDC_DISP), + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register DISPSTS timeout\n"); regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - (status & ATMEL_HLCDC_SYNC)) - cpu_relax(); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + !(status & ATMEL_HLCDC_SYNC), + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register LCDSTS timeout\n"); regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - (status & ATMEL_HLCDC_PIXEL_CLK)) - cpu_relax(); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + !(status & ATMEL_HLCDC_PIXEL_CLK), + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register CLKSTS timeout\n"); clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); pinctrl_pm_select_sleep_state(dev->dev); @@ -241,30 +266,95 @@ static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c, clk_prepare_enable(crtc->dc->hlcdc->sys_clk); regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - !(status & ATMEL_HLCDC_PIXEL_CLK)) - cpu_relax(); - + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + status & ATMEL_HLCDC_PIXEL_CLK, + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register CLKSTS timeout\n"); regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - !(status & ATMEL_HLCDC_SYNC)) - cpu_relax(); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + status & ATMEL_HLCDC_SYNC, + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register LCDSTS timeout\n"); regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - !(status & ATMEL_HLCDC_DISP)) - cpu_relax(); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + status & ATMEL_HLCDC_DISP, + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register DISPSTS timeout\n"); + + if (crtc->dc->desc->is_xlcdc) { + regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_XLCDC_CM); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + status & ATMEL_XLCDC_CM, + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register CMSTS timeout\n"); + + regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_XLCDC_SD); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + !(status & ATMEL_XLCDC_SD), + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register SDSTS timeout\n"); + } pm_runtime_put_sync(dev->dev); } -#define ATMEL_HLCDC_RGB444_OUTPUT BIT(0) -#define ATMEL_HLCDC_RGB565_OUTPUT BIT(1) -#define ATMEL_HLCDC_RGB666_OUTPUT BIT(2) -#define ATMEL_HLCDC_RGB888_OUTPUT BIT(3) -#define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0) +#define ATMEL_HLCDC_RGB444_OUTPUT BIT(0) +#define ATMEL_HLCDC_RGB565_OUTPUT BIT(1) +#define ATMEL_HLCDC_RGB666_OUTPUT BIT(2) +#define ATMEL_HLCDC_RGB888_OUTPUT BIT(3) +#define ATMEL_HLCDC_DPI_RGB565C1_OUTPUT BIT(4) +#define ATMEL_HLCDC_DPI_RGB565C2_OUTPUT BIT(5) +#define ATMEL_HLCDC_DPI_RGB565C3_OUTPUT BIT(6) +#define ATMEL_HLCDC_DPI_RGB666C1_OUTPUT BIT(7) +#define ATMEL_HLCDC_DPI_RGB666C2_OUTPUT BIT(8) +#define ATMEL_HLCDC_DPI_RGB888_OUTPUT BIT(9) +#define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0) +#define ATMEL_XLCDC_OUTPUT_MODE_MASK GENMASK(9, 0) + +static int atmel_xlcdc_connector_output_dsi(struct drm_encoder *encoder, + struct drm_display_info *info) +{ + int j; + unsigned int supported_fmts = 0; + + switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) { + case 0: + break; + case MEDIA_BUS_FMT_RGB565_1X16: + return ATMEL_HLCDC_DPI_RGB565C1_OUTPUT; + case MEDIA_BUS_FMT_RGB666_1X18: + return ATMEL_HLCDC_DPI_RGB666C1_OUTPUT; + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: + return ATMEL_HLCDC_DPI_RGB666C2_OUTPUT; + case MEDIA_BUS_FMT_RGB888_1X24: + return ATMEL_HLCDC_DPI_RGB888_OUTPUT; + default: + return -EINVAL; + } + + for (j = 0; j < info->num_bus_formats; j++) { + switch (info->bus_formats[j]) { + case MEDIA_BUS_FMT_RGB565_1X16: + supported_fmts |= ATMEL_HLCDC_DPI_RGB565C1_OUTPUT; + break; + case MEDIA_BUS_FMT_RGB666_1X18: + supported_fmts |= ATMEL_HLCDC_DPI_RGB666C1_OUTPUT; + break; + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: + supported_fmts |= ATMEL_HLCDC_DPI_RGB666C2_OUTPUT; + break; + case MEDIA_BUS_FMT_RGB888_1X24: + supported_fmts |= ATMEL_HLCDC_DPI_RGB888_OUTPUT; + break; + default: + break; + } + } + return supported_fmts; +} static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state) { @@ -277,6 +367,13 @@ static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state) encoder = state->best_encoder; if (!encoder) encoder = connector->encoder; + /* + * atmel-hlcdc to support DSI formats with DSI video pipeline + * when DRM_MODE_ENCODER_DSI type is set by + * connector driver component. + */ + if (encoder->encoder_type == DRM_MODE_ENCODER_DSI) + return atmel_xlcdc_connector_output_dsi(encoder, info); switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) { case 0: @@ -317,7 +414,7 @@ static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state) static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) { - unsigned int output_fmts = ATMEL_HLCDC_OUTPUT_MODE_MASK; + unsigned int output_fmts; struct atmel_hlcdc_crtc_state *hstate; struct drm_connector_state *cstate; struct drm_connector *connector; @@ -325,6 +422,8 @@ static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) int i; crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc); + output_fmts = crtc->dc->desc->is_xlcdc ? ATMEL_XLCDC_OUTPUT_MODE_MASK : + ATMEL_HLCDC_OUTPUT_MODE_MASK; for_each_new_connector_in_state(state->state, connector, cstate, i) { unsigned int supported_fmts = 0; @@ -345,7 +444,15 @@ static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) hstate = drm_crtc_state_to_atmel_hlcdc_crtc_state(state); hstate->output_mode = fls(output_fmts) - 1; - + if (crtc->dc->desc->is_xlcdc) { + /* check if MIPI DPI bit needs to be set */ + if (fls(output_fmts) > 3) { + hstate->output_mode -= 4; + hstate->dpi = 1; + } else { + hstate->dpi = 0; + } + } return 0; } @@ -449,6 +556,7 @@ static struct drm_crtc_state * atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc) { struct atmel_hlcdc_crtc_state *state, *cur; + struct atmel_hlcdc_crtc *c = drm_crtc_to_atmel_hlcdc_crtc(crtc); if (WARN_ON(!crtc->state)) return NULL; @@ -460,6 +568,8 @@ atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc) cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); state->output_mode = cur->output_mode; + if (c->dc->desc->is_xlcdc) + state->dpi = cur->dpi; return &state->base; } diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 84c54e8622d1..9ce429f889ca 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -58,6 +58,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9n12 = { .conflicting_output_formats = true, .nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9n12_layers), .layers = atmel_hlcdc_at91sam9n12_layers, + .ops = &atmel_hlcdc_ops, }; static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { @@ -151,6 +152,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9x5 = { .conflicting_output_formats = true, .nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9x5_layers), .layers = atmel_hlcdc_at91sam9x5_layers, + .ops = &atmel_hlcdc_ops, }; static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { @@ -269,6 +271,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d3 = { .conflicting_output_formats = true, .nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d3_layers), .layers = atmel_hlcdc_sama5d3_layers, + .ops = &atmel_hlcdc_ops, }; static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { @@ -364,6 +367,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d4 = { .max_hpw = 0x3ff, .nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers), .layers = atmel_hlcdc_sama5d4_layers, + .ops = &atmel_hlcdc_ops, }; static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sam9x60_layers[] = { @@ -460,6 +464,103 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sam9x60 = { .fixed_clksrc = true, .nlayers = ARRAY_SIZE(atmel_hlcdc_sam9x60_layers), .layers = atmel_hlcdc_sam9x60_layers, + .ops = &atmel_hlcdc_ops, +}; + +static const struct atmel_hlcdc_layer_desc atmel_xlcdc_sam9x75_layers[] = { + { + .name = "base", + .formats = &atmel_hlcdc_plane_rgb_formats, + .regs_offset = 0x60, + .id = 0, + .type = ATMEL_HLCDC_BASE_LAYER, + .cfgs_offset = 0x1c, + .layout = { + .xstride = { 2 }, + .default_color = 3, + .general_config = 4, + .disc_pos = 5, + .disc_size = 6, + }, + .clut_offset = 0x700, + }, + { + .name = "overlay1", + .formats = &atmel_hlcdc_plane_rgb_formats, + .regs_offset = 0x160, + .id = 1, + .type = ATMEL_HLCDC_OVERLAY_LAYER, + .cfgs_offset = 0x1c, + .layout = { + .pos = 2, + .size = 3, + .xstride = { 4 }, + .pstride = { 5 }, + .default_color = 6, + .chroma_key = 7, + .chroma_key_mask = 8, + .general_config = 9, + }, + .clut_offset = 0xb00, + }, + { + .name = "overlay2", + .formats = &atmel_hlcdc_plane_rgb_formats, + .regs_offset = 0x260, + .id = 2, + .type = ATMEL_HLCDC_OVERLAY_LAYER, + .cfgs_offset = 0x1c, + .layout = { + .pos = 2, + .size = 3, + .xstride = { 4 }, + .pstride = { 5 }, + .default_color = 6, + .chroma_key = 7, + .chroma_key_mask = 8, + .general_config = 9, + }, + .clut_offset = 0xf00, + }, + { + .name = "high-end-overlay", + .formats = &atmel_hlcdc_plane_rgb_and_yuv_formats, + .regs_offset = 0x360, + .id = 3, + .type = ATMEL_HLCDC_OVERLAY_LAYER, + .cfgs_offset = 0x30, + .layout = { + .pos = 2, + .size = 3, + .memsize = 4, + .xstride = { 5, 7 }, + .pstride = { 6, 8 }, + .default_color = 9, + .chroma_key = 10, + .chroma_key_mask = 11, + .general_config = 12, + .csc = 16, + .scaler_config = 23, + .vxs_config = 30, + .hxs_config = 31, + }, + .clut_offset = 0x1300, + }, +}; + +static const struct atmel_hlcdc_dc_desc atmel_xlcdc_dc_sam9x75 = { + .min_width = 0, + .min_height = 0, + .max_width = 2048, + .max_height = 2048, + .max_spw = 0x3ff, + .max_vpw = 0x3ff, + .max_hpw = 0x3ff, + .fixed_clksrc = true, + .is_xlcdc = true, + .nlayers = ARRAY_SIZE(atmel_xlcdc_sam9x75_layers), + .layers = atmel_xlcdc_sam9x75_layers, + .ops = &atmel_xlcdc_ops, }; static const struct of_device_id atmel_hlcdc_of_match[] = { @@ -487,6 +588,10 @@ static const struct of_device_id atmel_hlcdc_of_match[] = { .compatible = "microchip,sam9x60-hlcdc", .data = &atmel_hlcdc_dc_sam9x60, }, + { + .compatible = "microchip,sam9x75-xlcdc", + .data = &atmel_xlcdc_dc_sam9x75, + }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, atmel_hlcdc_of_match); diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index 5b5c774e0edf..e1a0bb24b511 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -15,6 +15,7 @@ #include <drm/drm_plane.h> +/* LCD controller common registers */ #define ATMEL_HLCDC_LAYER_CHER 0x0 #define ATMEL_HLCDC_LAYER_CHDR 0x4 #define ATMEL_HLCDC_LAYER_CHSR 0x8 @@ -128,6 +129,47 @@ #define ATMEL_HLCDC_MAX_LAYERS 6 +/* XLCDC controller specific registers */ +#define ATMEL_XLCDC_LAYER_ENR 0x10 +#define ATMEL_XLCDC_LAYER_EN BIT(0) + +#define ATMEL_XLCDC_LAYER_IER 0x0 +#define ATMEL_XLCDC_LAYER_IDR 0x4 +#define ATMEL_XLCDC_LAYER_ISR 0xc +#define ATMEL_XLCDC_LAYER_OVR_IRQ(p) BIT(2 + (8 * (p))) + +#define ATMEL_XLCDC_LAYER_PLANE_ADDR(p) (((p) * 0x4) + 0x18) + +#define ATMEL_XLCDC_LAYER_DMA_CFG 0 + +#define ATMEL_XLCDC_LAYER_DMA BIT(0) +#define ATMEL_XLCDC_LAYER_REP BIT(1) +#define ATMEL_XLCDC_LAYER_DISCEN BIT(4) + +#define ATMEL_XLCDC_LAYER_SFACTC_A0_MULT_AS (4 << 6) +#define ATMEL_XLCDC_LAYER_SFACTA_ONE BIT(9) +#define ATMEL_XLCDC_LAYER_DFACTC_M_A0_MULT_AS (6 << 11) +#define ATMEL_XLCDC_LAYER_DFACTA_ONE BIT(14) + +#define ATMEL_XLCDC_LAYER_A0_SHIFT 16 +#define ATMEL_XLCDC_LAYER_A0(x) \ + ((x) << ATMEL_XLCDC_LAYER_A0_SHIFT) + +#define ATMEL_XLCDC_LAYER_VSCALER_LUMA_ENABLE BIT(0) +#define ATMEL_XLCDC_LAYER_VSCALER_CHROMA_ENABLE BIT(1) +#define ATMEL_XLCDC_LAYER_HSCALER_LUMA_ENABLE BIT(4) +#define ATMEL_XLCDC_LAYER_HSCALER_CHROMA_ENABLE BIT(5) + +#define ATMEL_XLCDC_LAYER_VXSYCFG_ONE BIT(0) +#define ATMEL_XLCDC_LAYER_VXSYTAP2_ENABLE BIT(4) +#define ATMEL_XLCDC_LAYER_VXSCCFG_ONE BIT(16) +#define ATMEL_XLCDC_LAYER_VXSCTAP2_ENABLE BIT(20) + +#define ATMEL_XLCDC_LAYER_HXSYCFG_ONE BIT(0) +#define ATMEL_XLCDC_LAYER_HXSYTAP2_ENABLE BIT(4) +#define ATMEL_XLCDC_LAYER_HXSCCFG_ONE BIT(16) +#define ATMEL_XLCDC_LAYER_HXSCTAP2_ENABLE BIT(20) + /** * Atmel HLCDC Layer registers layout structure * @@ -156,6 +198,8 @@ * @disc_pos: discard area position register * @disc_size: discard area size register * @csc: color space conversion register + * @vxs_config: vertical scalar filter taps control register + * @hxs_config: horizontal scalar filter taps control register */ struct atmel_hlcdc_layer_cfg_layout { int xstride[ATMEL_HLCDC_LAYER_MAX_PLANES]; @@ -175,6 +219,8 @@ struct atmel_hlcdc_layer_cfg_layout { int disc_pos; int disc_size; int csc; + int vxs_config; + int hxs_config; }; /** @@ -289,6 +335,64 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *layer) } /** + * struct atmel_hlcdc_dc - Atmel HLCDC Display Controller. + * @desc: HLCDC Display Controller description + * @dscrpool: DMA coherent pool used to allocate DMA descriptors + * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device + * @crtc: CRTC provided by the display controller + * @layers: active HLCDC layers + * @suspend: used to store the HLCDC state when entering suspend + * @suspend.imr: used to read/write LCDC Interrupt Mask Register + * @suspend.state: Atomic commit structure + */ +struct atmel_hlcdc_dc { + const struct atmel_hlcdc_dc_desc *desc; + struct dma_pool *dscrpool; + struct atmel_hlcdc *hlcdc; + struct drm_crtc *crtc; + struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS]; + struct { + u32 imr; + struct drm_atomic_state *state; + } suspend; +}; + +struct atmel_hlcdc_plane_state; + +/** + * struct atmel_lcdc_dc_ops - describes atmel_lcdc ops group + * to differentiate HLCDC and XLCDC IP code support + * @plane_setup_scaler: update the vertical and horizontal scaling factors + * @update_lcdc_buffers: update the each LCDC layers DMA registers + * @lcdc_atomic_disable: disable LCDC interrupts and layers + * @lcdc_update_general_settings: update each LCDC layers general + * configuration register + * @lcdc_atomic_update: enable the LCDC layers and interrupts + * @lcdc_csc_init: update the color space conversion co-efficient of + * High-end overlay register + * @lcdc_irq_dbg: to raise alert incase of interrupt overrun in any LCDC layer + */ +struct atmel_lcdc_dc_ops { + void (*plane_setup_scaler)(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state); + void (*lcdc_update_buffers)(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state, + u32 sr, int i); + void (*lcdc_atomic_disable)(struct atmel_hlcdc_plane *plane); + void (*lcdc_update_general_settings)(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state); + void (*lcdc_atomic_update)(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_dc *dc); + void (*lcdc_csc_init)(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc); + void (*lcdc_irq_dbg)(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc); +}; + +extern const struct atmel_lcdc_dc_ops atmel_hlcdc_ops; +extern const struct atmel_lcdc_dc_ops atmel_xlcdc_ops; + +/** * Atmel HLCDC Display Controller description structure. * * This structure describes the HLCDC IP capabilities and depends on the @@ -304,8 +408,10 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *layer) * @conflicting_output_formats: true if RGBXXX output formats conflict with * each other. * @fixed_clksrc: true if clock source is fixed + * @is_xlcdc: true if XLCDC IP is supported * @layers: a layer description table describing available layers * @nlayers: layer description table size + * @ops: atmel lcdc dc ops */ struct atmel_hlcdc_dc_desc { int min_width; @@ -317,32 +423,10 @@ struct atmel_hlcdc_dc_desc { int max_hpw; bool conflicting_output_formats; bool fixed_clksrc; + bool is_xlcdc; const struct atmel_hlcdc_layer_desc *layers; int nlayers; -}; - -/** - * Atmel HLCDC Display Controller. - * - * @desc: HLCDC Display Controller description - * @dscrpool: DMA coherent pool used to allocate DMA descriptors - * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device - * @fbdev: framebuffer device attached to the Display Controller - * @crtc: CRTC provided by the display controller - * @planes: instantiated planes - * @layers: active HLCDC layers - * @suspend: used to store the HLCDC state when entering suspend - */ -struct atmel_hlcdc_dc { - const struct atmel_hlcdc_dc_desc *desc; - struct dma_pool *dscrpool; - struct atmel_hlcdc *hlcdc; - struct drm_crtc *crtc; - struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS]; - struct { - u32 imr; - struct drm_atomic_state *state; - } suspend; + const struct atmel_lcdc_dc_ops *ops; }; extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index daa508504f47..4a7ba0918eca 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -282,8 +282,9 @@ atmel_hlcdc_plane_scaler_set_phicoeff(struct atmel_hlcdc_plane *plane, coeff_tab[i]); } -static void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, - struct atmel_hlcdc_plane_state *state) +static +void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state) { const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; u32 xfactor, yfactor; @@ -330,11 +331,61 @@ static void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, yfactor)); } +static +void atmel_xlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state) +{ + const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + u32 xfactor, yfactor; + + if (!desc->layout.scaler_config) + return; + + if (state->crtc_w == state->src_w && state->crtc_h == state->src_h) { + atmel_hlcdc_layer_write_cfg(&plane->layer, + desc->layout.scaler_config, 0); + return; + } + + /* xfactor = round[(2^20 * XMEMSIZE)/XSIZE)] */ + xfactor = (u32)(((1 << 20) * state->src_w) / state->crtc_w); + + /* yfactor = round[(2^20 * YMEMSIZE)/YSIZE)] */ + yfactor = (u32)(((1 << 20) * state->src_h) / state->crtc_h); + + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config, + ATMEL_XLCDC_LAYER_VSCALER_LUMA_ENABLE | + ATMEL_XLCDC_LAYER_VSCALER_CHROMA_ENABLE | + ATMEL_XLCDC_LAYER_HSCALER_LUMA_ENABLE | + ATMEL_XLCDC_LAYER_HSCALER_CHROMA_ENABLE); + + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 1, + yfactor); + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 3, + xfactor); + + /* + * With YCbCr 4:2:2 and YCbYcr 4:2:0 window resampling, configuration + * register LCDC_HEOCFG25.VXSCFACT and LCDC_HEOCFG27.HXSCFACT is half + * the value of yfactor and xfactor. + */ + if (state->base.fb->format->format == DRM_FORMAT_YUV420) { + yfactor /= 2; + xfactor /= 2; + } + + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 2, + yfactor); + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 4, + xfactor); +} + static void atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane, struct atmel_hlcdc_plane_state *state) { const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; if (desc->layout.size) atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.size, @@ -352,12 +403,12 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane, ATMEL_HLCDC_LAYER_POS(state->crtc_x, state->crtc_y)); - atmel_hlcdc_plane_setup_scaler(plane, state); + dc->desc->ops->plane_setup_scaler(plane, state); } -static void -atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, - struct atmel_hlcdc_plane_state *state) +static +void atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state) { unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id; const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; @@ -393,6 +444,40 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, cfg); } +static +void atmel_xlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state) +{ + const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + const struct drm_format_info *format = state->base.fb->format; + unsigned int cfg; + + atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_XLCDC_LAYER_DMA_CFG, + ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id); + + cfg = ATMEL_XLCDC_LAYER_DMA | ATMEL_XLCDC_LAYER_REP; + + if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) { + /* + * Alpha Blending bits specific to SAM9X7 SoC + */ + cfg |= ATMEL_XLCDC_LAYER_SFACTC_A0_MULT_AS | + ATMEL_XLCDC_LAYER_SFACTA_ONE | + ATMEL_XLCDC_LAYER_DFACTC_M_A0_MULT_AS | + ATMEL_XLCDC_LAYER_DFACTA_ONE; + if (format->has_alpha) + cfg |= ATMEL_XLCDC_LAYER_A0(0xff); + else + cfg |= ATMEL_XLCDC_LAYER_A0(state->base.alpha); + } + + if (state->disc_h && state->disc_w) + cfg |= ATMEL_XLCDC_LAYER_DISCEN; + + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.general_config, + cfg); +} + static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane, struct atmel_hlcdc_plane_state *state) { @@ -437,36 +522,55 @@ static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane, } } +static void atmel_hlcdc_update_buffers(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state, + u32 sr, int i) +{ + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_HLCDC_LAYER_PLANE_HEAD(i), + state->dscrs[i]->self); + + if (sr & ATMEL_HLCDC_LAYER_EN) + return; + + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_HLCDC_LAYER_PLANE_ADDR(i), + state->dscrs[i]->addr); + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_HLCDC_LAYER_PLANE_CTRL(i), + state->dscrs[i]->ctrl); + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_HLCDC_LAYER_PLANE_NEXT(i), + state->dscrs[i]->self); +} + +static void atmel_xlcdc_update_buffers(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state, + u32 sr, int i) +{ + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_XLCDC_LAYER_PLANE_ADDR(i), + state->dscrs[i]->addr); +} + static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, - struct atmel_hlcdc_plane_state *state) + struct atmel_hlcdc_plane_state *state) { const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; struct drm_framebuffer *fb = state->base.fb; u32 sr; int i; - sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); + if (!dc->desc->is_xlcdc) + sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); for (i = 0; i < state->nplanes; i++) { struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i); state->dscrs[i]->addr = gem->dma_addr + state->offsets[i]; - atmel_hlcdc_layer_write_reg(&plane->layer, - ATMEL_HLCDC_LAYER_PLANE_HEAD(i), - state->dscrs[i]->self); - - if (!(sr & ATMEL_HLCDC_LAYER_EN)) { - atmel_hlcdc_layer_write_reg(&plane->layer, - ATMEL_HLCDC_LAYER_PLANE_ADDR(i), - state->dscrs[i]->addr); - atmel_hlcdc_layer_write_reg(&plane->layer, - ATMEL_HLCDC_LAYER_PLANE_CTRL(i), - state->dscrs[i]->ctrl); - atmel_hlcdc_layer_write_reg(&plane->layer, - ATMEL_HLCDC_LAYER_PLANE_NEXT(i), - state->dscrs[i]->self); - } + dc->desc->ops->lcdc_update_buffers(plane, state, sr, i); if (desc->layout.xstride[i]) atmel_hlcdc_layer_write_cfg(&plane->layer, @@ -712,11 +816,8 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, return 0; } -static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, - struct drm_atomic_state *state) +static void atmel_hlcdc_atomic_disable(struct atmel_hlcdc_plane *plane) { - struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); - /* Disable interrupts */ atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IDR, 0xffffffff); @@ -731,6 +832,70 @@ static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); } +static void atmel_xlcdc_atomic_disable(struct atmel_hlcdc_plane *plane) +{ + /* Disable interrupts */ + atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_IDR, + 0xffffffff); + + /* Disable the layer */ + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_XLCDC_LAYER_ENR, 0); + + /* Clear all pending interrupts */ + atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_XLCDC_LAYER_ISR); +} + +static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, + struct drm_atomic_state *state) +{ + struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; + + dc->desc->ops->lcdc_atomic_disable(plane); +} + +static void atmel_hlcdc_atomic_update(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_dc *dc) +{ + u32 sr; + + /* Enable the overrun interrupts. */ + atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER, + ATMEL_HLCDC_LAYER_OVR_IRQ(0) | + ATMEL_HLCDC_LAYER_OVR_IRQ(1) | + ATMEL_HLCDC_LAYER_OVR_IRQ(2)); + + /* Apply the new config at the next SOF event. */ + sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); + atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER, + ATMEL_HLCDC_LAYER_UPDATE | + (sr & ATMEL_HLCDC_LAYER_EN ? + ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN)); +} + +static void atmel_xlcdc_atomic_update(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_dc *dc) +{ + /* Enable the overrun interrupts. */ + atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_IER, + ATMEL_XLCDC_LAYER_OVR_IRQ(0) | + ATMEL_XLCDC_LAYER_OVR_IRQ(1) | + ATMEL_XLCDC_LAYER_OVR_IRQ(2)); + + atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_ENR, + ATMEL_XLCDC_LAYER_EN); + + /* + * Updating XLCDC_xxxCFGx, XLCDC_xxxFBA and XLCDC_xxxEN, + * (where xxx indicates each layer) requires writing one to the + * Update Attribute field for each layer in LCDC_ATTRE register for SAM9X7. + */ + regmap_write(dc->hlcdc->regmap, ATMEL_XLCDC_ATTRE, ATMEL_XLCDC_BASE_UPDATE | + ATMEL_XLCDC_OVR1_UPDATE | ATMEL_XLCDC_OVR3_UPDATE | + ATMEL_XLCDC_HEO_UPDATE); +} + static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, struct drm_atomic_state *state) { @@ -739,7 +904,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); struct atmel_hlcdc_plane_state *hstate = drm_plane_state_to_atmel_hlcdc_plane_state(new_s); - u32 sr; + struct atmel_hlcdc_dc *dc = p->dev->dev_private; if (!new_s->crtc || !new_s->fb) return; @@ -750,29 +915,83 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, } atmel_hlcdc_plane_update_pos_and_size(plane, hstate); - atmel_hlcdc_plane_update_general_settings(plane, hstate); + dc->desc->ops->lcdc_update_general_settings(plane, hstate); atmel_hlcdc_plane_update_format(plane, hstate); atmel_hlcdc_plane_update_clut(plane, hstate); atmel_hlcdc_plane_update_buffers(plane, hstate); atmel_hlcdc_plane_update_disc_area(plane, hstate); - /* Enable the overrun interrupts. */ - atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER, - ATMEL_HLCDC_LAYER_OVR_IRQ(0) | - ATMEL_HLCDC_LAYER_OVR_IRQ(1) | - ATMEL_HLCDC_LAYER_OVR_IRQ(2)); + dc->desc->ops->lcdc_atomic_update(plane, dc); +} - /* Apply the new config at the next SOF event. */ - sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); - atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER, - ATMEL_HLCDC_LAYER_UPDATE | - (sr & ATMEL_HLCDC_LAYER_EN ? - ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN)); +static void atmel_hlcdc_csc_init(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc) +{ + /* + * TODO: declare a "yuv-to-rgb-conv-factors" property to let + * userspace modify these factors (using a BLOB property ?). + */ + static const u32 hlcdc_csc_coeffs[] = { + 0x4c900091, + 0x7a5f5090, + 0x40040890 + }; + + for (int i = 0; i < ARRAY_SIZE(hlcdc_csc_coeffs); i++) { + atmel_hlcdc_layer_write_cfg(&plane->layer, + desc->layout.csc + i, + hlcdc_csc_coeffs[i]); + } +} + +static void atmel_xlcdc_csc_init(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc) +{ + /* + * yuv-to-rgb-conv-factors are now defined from LCDC_HEOCFG16 to + * LCDC_HEOCFG21 registers in SAM9X7. + */ + static const u32 xlcdc_csc_coeffs[] = { + 0x00000488, + 0x00000648, + 0x1EA00480, + 0x00001D28, + 0x08100480, + 0x00000000, + 0x00000007 + }; + + for (int i = 0; i < ARRAY_SIZE(xlcdc_csc_coeffs); i++) { + atmel_hlcdc_layer_write_cfg(&plane->layer, + desc->layout.csc + i, + xlcdc_csc_coeffs[i]); + } + + if (desc->layout.vxs_config && desc->layout.hxs_config) { + /* + * Updating vxs.config and hxs.config fixes the + * Green Color Issue in SAM9X7 EGT Video Player App + */ + atmel_hlcdc_layer_write_cfg(&plane->layer, + desc->layout.vxs_config, + ATMEL_XLCDC_LAYER_VXSYCFG_ONE | + ATMEL_XLCDC_LAYER_VXSYTAP2_ENABLE | + ATMEL_XLCDC_LAYER_VXSCCFG_ONE | + ATMEL_XLCDC_LAYER_VXSCTAP2_ENABLE); + + atmel_hlcdc_layer_write_cfg(&plane->layer, + desc->layout.hxs_config, + ATMEL_XLCDC_LAYER_HXSYCFG_ONE | + ATMEL_XLCDC_LAYER_HXSYTAP2_ENABLE | + ATMEL_XLCDC_LAYER_HXSCCFG_ONE | + ATMEL_XLCDC_LAYER_HXSCTAP2_ENABLE); + } } static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane) { const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; if (desc->type == ATMEL_HLCDC_OVERLAY_LAYER || desc->type == ATMEL_HLCDC_CURSOR_LAYER) { @@ -796,31 +1015,16 @@ static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane) return ret; } - if (desc->layout.csc) { - /* - * TODO: decare a "yuv-to-rgb-conv-factors" property to let - * userspace modify these factors (using a BLOB property ?). - */ - atmel_hlcdc_layer_write_cfg(&plane->layer, - desc->layout.csc, - 0x4c900091); - atmel_hlcdc_layer_write_cfg(&plane->layer, - desc->layout.csc + 1, - 0x7a5f5090); - atmel_hlcdc_layer_write_cfg(&plane->layer, - desc->layout.csc + 2, - 0x40040890); - } + if (desc->layout.csc) + dc->desc->ops->lcdc_csc_init(plane, desc); return 0; } -void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane) +static void atmel_hlcdc_irq_dbg(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc) { - const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; - u32 isr; - - isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); + u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); /* * There's not much we can do in case of overrun except informing @@ -834,6 +1038,51 @@ void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane) desc->name); } +static void atmel_xlcdc_irq_dbg(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc) +{ + u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_XLCDC_LAYER_ISR); + + /* + * There's not much we can do in case of overrun except informing + * the user. However, we are in interrupt context here, hence the + * use of dev_dbg(). + */ + if (isr & + (ATMEL_XLCDC_LAYER_OVR_IRQ(0) | ATMEL_XLCDC_LAYER_OVR_IRQ(1) | + ATMEL_XLCDC_LAYER_OVR_IRQ(2))) + dev_dbg(plane->base.dev->dev, "overrun on plane %s\n", + desc->name); +} + +void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane) +{ + const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; + + dc->desc->ops->lcdc_irq_dbg(plane, desc); +} + +const struct atmel_lcdc_dc_ops atmel_hlcdc_ops = { + .plane_setup_scaler = atmel_hlcdc_plane_setup_scaler, + .lcdc_update_buffers = atmel_hlcdc_update_buffers, + .lcdc_atomic_disable = atmel_hlcdc_atomic_disable, + .lcdc_update_general_settings = atmel_hlcdc_plane_update_general_settings, + .lcdc_atomic_update = atmel_hlcdc_atomic_update, + .lcdc_csc_init = atmel_hlcdc_csc_init, + .lcdc_irq_dbg = atmel_hlcdc_irq_dbg, +}; + +const struct atmel_lcdc_dc_ops atmel_xlcdc_ops = { + .plane_setup_scaler = atmel_xlcdc_plane_setup_scaler, + .lcdc_update_buffers = atmel_xlcdc_update_buffers, + .lcdc_atomic_disable = atmel_xlcdc_atomic_disable, + .lcdc_update_general_settings = atmel_xlcdc_plane_update_general_settings, + .lcdc_atomic_update = atmel_xlcdc_atomic_update, + .lcdc_csc_init = atmel_xlcdc_csc_init, + .lcdc_irq_dbg = atmel_xlcdc_irq_dbg, +}; + static const struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = { .atomic_check = atmel_hlcdc_plane_atomic_check, .atomic_update = atmel_hlcdc_plane_atomic_update, diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 66ccb61e2a66..3cd130965e9d 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -877,11 +877,6 @@ static int adv7511_connector_init(struct adv7511 *adv) struct drm_bridge *bridge = &adv->bridge; int ret; - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found"); - return -ENODEV; - } - if (adv->i2c_main->irq) adv->connector.polled = DRM_CONNECTOR_POLL_HPD; else diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c index c9e35731e6a1..b754947e3e00 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c @@ -47,7 +47,7 @@ struct anx6345 { struct drm_dp_aux aux; struct drm_bridge bridge; struct i2c_client *client; - struct edid *edid; + const struct drm_edid *drm_edid; struct drm_connector connector; struct drm_panel *panel; struct regulator *dvdd12; @@ -458,7 +458,7 @@ static int anx6345_get_modes(struct drm_connector *connector) mutex_lock(&anx6345->lock); - if (!anx6345->edid) { + if (!anx6345->drm_edid) { if (!anx6345->powered) { anx6345_poweron(anx6345); power_off = true; @@ -470,19 +470,18 @@ static int anx6345_get_modes(struct drm_connector *connector) goto unlock; } - anx6345->edid = drm_get_edid(connector, &anx6345->aux.ddc); - if (!anx6345->edid) + anx6345->drm_edid = drm_edid_read_ddc(connector, &anx6345->aux.ddc); + if (!anx6345->drm_edid) DRM_ERROR("Failed to read EDID from panel\n"); - err = drm_connector_update_edid_property(connector, - anx6345->edid); + err = drm_edid_connector_update(connector, anx6345->drm_edid); if (err) { DRM_ERROR("Failed to update EDID property: %d\n", err); goto unlock; } } - num_modes += drm_add_edid_modes(connector, anx6345->edid); + num_modes += drm_edid_connector_add_modes(connector); /* Driver currently supports only 6bpc */ connector->display_info.bpc = 6; @@ -528,11 +527,6 @@ static int anx6345_bridge_attach(struct drm_bridge *bridge, return -EINVAL; } - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found"); - return -ENODEV; - } - /* Register aux channel */ anx6345->aux.name = "DP-AUX"; anx6345->aux.dev = &anx6345->client->dev; @@ -793,7 +787,7 @@ static void anx6345_i2c_remove(struct i2c_client *client) unregister_i2c_dummy_clients(anx6345); - kfree(anx6345->edid); + drm_edid_free(anx6345->drm_edid); mutex_destroy(&anx6345->lock); } diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c index 5748a8581af4..f74694bb9c50 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c @@ -67,7 +67,7 @@ struct anx78xx { struct drm_dp_aux aux; struct drm_bridge bridge; struct i2c_client *client; - struct edid *edid; + const struct drm_edid *drm_edid; struct drm_connector connector; struct anx78xx_platform_data pdata; struct mutex lock; @@ -830,8 +830,8 @@ static int anx78xx_get_modes(struct drm_connector *connector) if (WARN_ON(!anx78xx->powered)) return 0; - if (anx78xx->edid) - return drm_add_edid_modes(connector, anx78xx->edid); + if (anx78xx->drm_edid) + return drm_edid_connector_add_modes(connector); mutex_lock(&anx78xx->lock); @@ -841,20 +841,21 @@ static int anx78xx_get_modes(struct drm_connector *connector) goto unlock; } - anx78xx->edid = drm_get_edid(connector, &anx78xx->aux.ddc); - if (!anx78xx->edid) { + anx78xx->drm_edid = drm_edid_read_ddc(connector, &anx78xx->aux.ddc); + + err = drm_edid_connector_update(connector, anx78xx->drm_edid); + + if (!anx78xx->drm_edid) { DRM_ERROR("Failed to read EDID\n"); goto unlock; } - err = drm_connector_update_edid_property(connector, - anx78xx->edid); if (err) { DRM_ERROR("Failed to update EDID property: %d\n", err); goto unlock; } - num_modes = drm_add_edid_modes(connector, anx78xx->edid); + num_modes = drm_edid_connector_add_modes(connector); unlock: mutex_unlock(&anx78xx->lock); @@ -897,11 +898,6 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge, return -EINVAL; } - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found"); - return -ENODEV; - } - /* Register aux channel */ anx78xx->aux.name = "DP-AUX"; anx78xx->aux.dev = &anx78xx->client->dev; @@ -1091,8 +1087,8 @@ static bool anx78xx_handle_common_int_4(struct anx78xx *anx78xx, u8 irq) event = true; anx78xx_poweroff(anx78xx); /* Free cached EDID */ - kfree(anx78xx->edid); - anx78xx->edid = NULL; + drm_edid_free(anx78xx->drm_edid); + anx78xx->drm_edid = NULL; } else if (irq & SP_HPD_PLUG) { DRM_DEBUG_KMS("IRQ: Hot plug detect - cable plug\n"); event = true; @@ -1363,7 +1359,7 @@ static void anx78xx_i2c_remove(struct i2c_client *client) unregister_i2c_dummy_clients(anx78xx); - kfree(anx78xx->edid); + drm_edid_free(anx78xx->drm_edid); } static const struct of_device_id anx78xx_match_table[] = { diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index df9370e0ff23..b5dbff21c187 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -234,28 +234,6 @@ static int analogix_dp_training_pattern_dis(struct analogix_dp_device *dp) return ret < 0 ? ret : 0; } -static void -analogix_dp_set_lane_lane_pre_emphasis(struct analogix_dp_device *dp, - int pre_emphasis, int lane) -{ - switch (lane) { - case 0: - analogix_dp_set_lane0_pre_emphasis(dp, pre_emphasis); - break; - case 1: - analogix_dp_set_lane1_pre_emphasis(dp, pre_emphasis); - break; - - case 2: - analogix_dp_set_lane2_pre_emphasis(dp, pre_emphasis); - break; - - case 3: - analogix_dp_set_lane3_pre_emphasis(dp, pre_emphasis); - break; - } -} - static int analogix_dp_link_start(struct analogix_dp_device *dp) { u8 buf[4]; @@ -286,10 +264,12 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp) return retval; } - /* Set TX pre-emphasis to minimum */ + /* Set TX voltage-swing and pre-emphasis to minimum */ for (lane = 0; lane < lane_count; lane++) - analogix_dp_set_lane_lane_pre_emphasis(dp, - PRE_EMPHASIS_LEVEL_0, lane); + dp->link_train.training_lane[lane] = + DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | + DP_TRAIN_PRE_EMPH_LEVEL_0; + analogix_dp_set_lane_link_training(dp); /* Wait for PLL lock */ pll_tries = 0; @@ -384,54 +364,6 @@ static unsigned char analogix_dp_get_adjust_request_pre_emphasis( return ((link_value >> shift) & 0xc) >> 2; } -static void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp, - u8 training_lane_set, int lane) -{ - switch (lane) { - case 0: - analogix_dp_set_lane0_link_training(dp, training_lane_set); - break; - case 1: - analogix_dp_set_lane1_link_training(dp, training_lane_set); - break; - - case 2: - analogix_dp_set_lane2_link_training(dp, training_lane_set); - break; - - case 3: - analogix_dp_set_lane3_link_training(dp, training_lane_set); - break; - } -} - -static unsigned int -analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, - int lane) -{ - u32 reg; - - switch (lane) { - case 0: - reg = analogix_dp_get_lane0_link_training(dp); - break; - case 1: - reg = analogix_dp_get_lane1_link_training(dp); - break; - case 2: - reg = analogix_dp_get_lane2_link_training(dp); - break; - case 3: - reg = analogix_dp_get_lane3_link_training(dp); - break; - default: - WARN_ON(1); - return 0; - } - - return reg; -} - static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp) { analogix_dp_training_pattern_dis(dp); @@ -478,11 +410,6 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) if (retval < 0) return retval; - retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1, - adjust_request, 2); - if (retval < 0) - return retval; - if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) { /* set training pattern 2 for EQ */ analogix_dp_set_training_pattern(dp, TRAINING_PTN2); @@ -495,38 +422,37 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) dev_dbg(dp->dev, "Link Training Clock Recovery success\n"); dp->link_train.lt_state = EQUALIZER_TRAINING; - } else { - for (lane = 0; lane < lane_count; lane++) { - training_lane = analogix_dp_get_lane_link_training( - dp, lane); - voltage_swing = analogix_dp_get_adjust_request_voltage( - adjust_request, lane); - pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( - adjust_request, lane); - - if (DPCD_VOLTAGE_SWING_GET(training_lane) == - voltage_swing && - DPCD_PRE_EMPHASIS_GET(training_lane) == - pre_emphasis) - dp->link_train.cr_loop[lane]++; - - if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP || - voltage_swing == VOLTAGE_LEVEL_3 || - pre_emphasis == PRE_EMPHASIS_LEVEL_3) { - dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", - dp->link_train.cr_loop[lane], - voltage_swing, pre_emphasis); - analogix_dp_reduce_link_rate(dp); - return -EIO; - } + + return 0; + } + + retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1, + adjust_request, 2); + if (retval < 0) + return retval; + + for (lane = 0; lane < lane_count; lane++) { + training_lane = analogix_dp_get_lane_link_training(dp, lane); + voltage_swing = analogix_dp_get_adjust_request_voltage(adjust_request, lane); + pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis(adjust_request, lane); + + if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing && + DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis) + dp->link_train.cr_loop[lane]++; + + if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP || + voltage_swing == VOLTAGE_LEVEL_3 || + pre_emphasis == PRE_EMPHASIS_LEVEL_3) { + dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", + dp->link_train.cr_loop[lane], + voltage_swing, pre_emphasis); + analogix_dp_reduce_link_rate(dp); + return -EIO; } } analogix_dp_get_adjust_training_lane(dp, adjust_request); - - for (lane = 0; lane < lane_count; lane++) - analogix_dp_set_lane_link_training(dp, - dp->link_train.training_lane[lane], lane); + analogix_dp_set_lane_link_training(dp); retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, dp->link_train.training_lane, lane_count); @@ -538,7 +464,7 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) { - int lane, lane_count, retval; + int lane_count, retval; u32 reg; u8 link_align, link_status[2], adjust_request[2]; @@ -598,9 +524,7 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) return -EIO; } - for (lane = 0; lane < lane_count; lane++) - analogix_dp_set_lane_link_training(dp, - dp->link_train.training_lane[lane], lane); + analogix_dp_set_lane_link_training(dp); retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, dp->link_train.training_lane, lane_count); @@ -712,7 +636,7 @@ static int analogix_dp_full_link_train(struct analogix_dp_device *dp, static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) { - int i, ret; + int ret; u8 link_align, link_status[2]; enum pll_status status; @@ -720,11 +644,7 @@ static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); analogix_dp_set_lane_count(dp, dp->link_train.lane_count); - - for (i = 0; i < dp->link_train.lane_count; i++) { - analogix_dp_set_lane_link_training(dp, - dp->link_train.training_lane[i], i); - } + analogix_dp_set_lane_link_training(dp); ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status, status != PLL_UNLOCKED, 120, @@ -1108,7 +1028,7 @@ out: static int analogix_dp_get_modes(struct drm_connector *connector) { struct analogix_dp_device *dp = to_dp(connector); - struct edid *edid; + const struct drm_edid *drm_edid; int ret, num_modes = 0; if (dp->plat_data->panel) { @@ -1120,12 +1040,13 @@ static int analogix_dp_get_modes(struct drm_connector *connector) return 0; } - edid = drm_get_edid(connector, &dp->aux.ddc); - if (edid) { - drm_connector_update_edid_property(&dp->connector, - edid); - num_modes += drm_add_edid_modes(&dp->connector, edid); - kfree(edid); + drm_edid = drm_edid_read_ddc(connector, &dp->aux.ddc); + + drm_edid_connector_update(&dp->connector, drm_edid); + + if (drm_edid) { + num_modes += drm_edid_connector_add_modes(&dp->connector); + drm_edid_free(drm_edid); } ret = analogix_dp_prepare_panel(dp, false, false); @@ -1228,11 +1149,6 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge, return -EINVAL; } - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found"); - return -ENODEV; - } - if (!dp->plat_data->skip_connector) { connector = &dp->connector; connector->polled = DRM_CONNECTOR_POLL_HPD; diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 433f2d7efa0c..382b2f068ab9 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -213,26 +213,8 @@ void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, bool enable); void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, enum pattern_set pattern); -void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, - u32 level); -void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, - u32 level); -void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, - u32 level); -void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, - u32 level); -void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, - u32 training_lane); -void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, - u32 training_lane); -void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, - u32 training_lane); -void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, - u32 training_lane); -u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp); -u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp); -u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp); -u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp); +void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane); void analogix_dp_reset_macro(struct analogix_dp_device *dp); void analogix_dp_init_video(struct analogix_dp_device *dp); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 6a4f20fccf84..d267cf05cbca 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -557,6 +557,20 @@ void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count) *count = reg; } +void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp) +{ + u8 lane; + + for (lane = 0; lane < dp->link_train.lane_count; lane++) + writel(dp->link_train.training_lane[lane], + dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane); +} + +u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane) +{ + return readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane); +} + void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, bool enable) { @@ -606,106 +620,6 @@ void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, } } -void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, - u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, - u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, - u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, - u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); -} - -u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp) -{ - return readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); -} - -u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp) -{ - return readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); -} - -u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp) -{ - return readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); -} - -u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp) -{ - return readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); -} - void analogix_dp_reset_macro(struct analogix_dp_device *dp) { u32 reg; @@ -1027,7 +941,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, u32 status_reg; u8 *buffer = msg->buffer; unsigned int i; - int num_transferred = 0; int ret; /* Buffer size of AUX CH is 16 bytes */ @@ -1079,7 +992,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, reg = buffer[i]; writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + 4 * i); - num_transferred++; } } @@ -1127,7 +1039,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + 4 * i); buffer[i] = (unsigned char)reg; - num_transferred++; } } @@ -1144,7 +1055,7 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ) msg->reply = DP_AUX_NATIVE_REPLY_ACK; - return num_transferred > 0 ? num_transferred : -EBUSY; + return msg->size; aux_error: /* if aux err happen, reset aux */ diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 59e9ad349969..88e4aa5830f3 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -464,9 +464,11 @@ static int anx7625_odfc_config(struct anx7625_data *ctx, */ static int anx7625_set_k_value(struct anx7625_data *ctx) { - struct edid *edid = (struct edid *)ctx->slimport_edid_p.edid_raw_data; + struct drm_edid_product_id id; - if (edid->mfg_id[0] == IVO_MID0 && edid->mfg_id[1] == IVO_MID1) + drm_edid_get_product_id(ctx->cached_drm_edid, &id); + + if (be16_to_cpu(id.manufacturer_name) == IVO_MID) return anx7625_reg_write(ctx, ctx->i2c.rx_p1_client, MIPI_DIGITAL_ADJ_1, 0x3B); @@ -1526,7 +1528,8 @@ static int anx7625_wait_hpd_asserted(struct drm_dp_aux *aux, static void anx7625_remove_edid(struct anx7625_data *ctx) { - ctx->slimport_edid_p.edid_block_num = -1; + drm_edid_free(ctx->cached_drm_edid); + ctx->cached_drm_edid = NULL; } static void anx7625_dp_adjust_swing(struct anx7625_data *ctx) @@ -1787,27 +1790,32 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux, static const struct drm_edid *anx7625_edid_read(struct anx7625_data *ctx) { struct device *dev = ctx->dev; - struct s_edid_data *p_edid = &ctx->slimport_edid_p; + u8 *edid_buf; int edid_num; - if (ctx->slimport_edid_p.edid_block_num > 0) + if (ctx->cached_drm_edid) goto out; + edid_buf = kmalloc(FOUR_BLOCK_SIZE, GFP_KERNEL); + if (!edid_buf) + return NULL; + pm_runtime_get_sync(dev); _anx7625_hpd_polling(ctx, 5000 * 100); - edid_num = sp_tx_edid_read(ctx, p_edid->edid_raw_data); + edid_num = sp_tx_edid_read(ctx, edid_buf); pm_runtime_put_sync(dev); if (edid_num < 1) { DRM_DEV_ERROR(dev, "Fail to read EDID: %d\n", edid_num); + kfree(edid_buf); return NULL; } - p_edid->edid_block_num = edid_num; + ctx->cached_drm_edid = drm_edid_alloc(edid_buf, FOUR_BLOCK_SIZE); + kfree(edid_buf); out: - return drm_edid_alloc(ctx->slimport_edid_p.edid_raw_data, - FOUR_BLOCK_SIZE); + return drm_edid_dup(ctx->cached_drm_edid); } static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx) @@ -2193,11 +2201,6 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge, if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) return -EINVAL; - if (!bridge->encoder) { - DRM_DEV_ERROR(dev, "Parent encoder object not found"); - return -ENODEV; - } - ctx->aux.drm_dev = bridge->dev; err = drm_dp_aux_register(&ctx->aux); if (err) { @@ -2435,11 +2438,6 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge, dev_dbg(dev, "drm atomic enable\n"); - if (!bridge->encoder) { - dev_err(dev, "Parent encoder object not found"); - return; - } - connector = drm_atomic_get_new_connector_for_encoder(state->base.state, bridge->encoder); if (!connector) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h index 39ed35d33836..eb5580f1ab2f 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.h +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h @@ -286,8 +286,7 @@ #define MIPI_LANE_CTRL_10 0x0F #define MIPI_DIGITAL_ADJ_1 0x1B -#define IVO_MID0 0x26 -#define IVO_MID1 0xCF +#define IVO_MID 0x26CF #define MIPI_PLL_M_NUM_23_16 0x1E #define MIPI_PLL_M_NUM_15_8 0x1F @@ -417,11 +416,6 @@ enum audio_wd_len { #define EDID_TRY_CNT 3 #define SUPPORT_PIXEL_CLOCK 300000 -struct s_edid_data { - int edid_block_num; - u8 edid_raw_data[FOUR_BLOCK_SIZE]; -}; - /***************** Display End *****************/ #define MAX_LANES_SUPPORT 4 @@ -466,7 +460,7 @@ struct anx7625_data { struct anx7625_i2c_client i2c; struct i2c_client *last_client; struct timer_list hdcp_timer; - struct s_edid_data slimport_edid_p; + const struct drm_edid *cached_drm_edid; struct device *codec_dev; hdmi_codec_plugged_cb plugged_cb; struct work_struct work; diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index 8a91ef0ae065..dee640ab1d3a 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -1697,11 +1697,6 @@ static int cdns_mhdp_connector_init(struct cdns_mhdp_device *mhdp) struct drm_bridge *bridge = &mhdp->bridge; int ret; - if (!bridge->encoder) { - dev_err(mhdp->dev, "Parent encoder object not found"); - return -ENODEV; - } - conn->polled = DRM_CONNECTOR_POLL_HPD; ret = drm_connector_init(bridge->dev, conn, &cdns_mhdp_conn_funcs, diff --git a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c index 6967325cd8ee..9b5bebbe357d 100644 --- a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c +++ b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c @@ -116,11 +116,6 @@ int ldb_bridge_attach_helper(struct drm_bridge *bridge, return -EINVAL; } - if (!bridge->encoder) { - DRM_DEV_ERROR(ldb->dev, "missing encoder\n"); - return -ENODEV; - } - return drm_bridge_attach(bridge->encoder, ldb_ch->next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c index d0868a6ac6c9..e6dbbdc87ce2 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c @@ -119,11 +119,6 @@ static int imx8qxp_pc_bridge_attach(struct drm_bridge *bridge, return -EINVAL; } - if (!bridge->encoder) { - DRM_DEV_ERROR(pc->dev, "missing encoder\n"); - return -ENODEV; - } - return drm_bridge_attach(bridge->encoder, ch->next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c index ed8b7a4e0e11..1d11cc1df43c 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c @@ -138,11 +138,6 @@ static int imx8qxp_pixel_link_bridge_attach(struct drm_bridge *bridge, return -EINVAL; } - if (!bridge->encoder) { - DRM_DEV_ERROR(pl->dev, "missing encoder\n"); - return -ENODEV; - } - return drm_bridge_attach(bridge->encoder, pl->next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c index 4a886cb808ca..fb7cf4369bb8 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c @@ -58,11 +58,6 @@ static int imx8qxp_pxl2dpi_bridge_attach(struct drm_bridge *bridge, return -EINVAL; } - if (!bridge->encoder) { - DRM_DEV_ERROR(p2d->dev, "missing encoder\n"); - return -ENODEV; - } - return drm_bridge_attach(bridge->encoder, p2d->next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 3f68c82888c2..1e1c06fdf206 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -1307,9 +1307,15 @@ static void it6505_video_reset(struct it6505 *it6505) it6505_link_reset_step_train(it6505); it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_VID_MUTE, EN_VID_MUTE); it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_VID_CTRL_PKT, 0x00); - it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET); + + it6505_set_bits(it6505, REG_VID_BUS_CTRL1, TX_FIFO_RESET, TX_FIFO_RESET); + it6505_set_bits(it6505, REG_VID_BUS_CTRL1, TX_FIFO_RESET, 0x00); + it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, RST_501_FIFO); it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, 0x00); + + it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET); + usleep_range(1000, 2000); it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, 0x00); } @@ -2245,12 +2251,11 @@ static void it6505_link_training_work(struct work_struct *work) if (ret) { it6505->auto_train_retry = AUTO_TRAIN_RETRY; it6505_link_train_ok(it6505); - return; } else { it6505->auto_train_retry--; + it6505_dump(it6505); } - it6505_dump(it6505); } static void it6505_plugged_status_to_codec(struct it6505 *it6505) @@ -2471,31 +2476,53 @@ static void it6505_irq_link_train_fail(struct it6505 *it6505) schedule_work(&it6505->link_works); } -static void it6505_irq_video_fifo_error(struct it6505 *it6505) +static bool it6505_test_bit(unsigned int bit, const unsigned int *addr) { - struct device *dev = it6505->dev; - - DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt"); - it6505->auto_train_retry = AUTO_TRAIN_RETRY; - flush_work(&it6505->link_works); - it6505_stop_hdcp(it6505); - it6505_video_reset(it6505); + return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE)); } -static void it6505_irq_io_latch_fifo_overflow(struct it6505 *it6505) +static void it6505_irq_video_handler(struct it6505 *it6505, const int *int_status) { struct device *dev = it6505->dev; + int reg_0d, reg_int03; - DRM_DEV_DEBUG_DRIVER(dev, "IO latch fifo overflow interrupt"); - it6505->auto_train_retry = AUTO_TRAIN_RETRY; - flush_work(&it6505->link_works); - it6505_stop_hdcp(it6505); - it6505_video_reset(it6505); -} + /* + * When video SCDT change with video not stable, + * Or video FIFO error, need video reset + */ -static bool it6505_test_bit(unsigned int bit, const unsigned int *addr) -{ - return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE)); + if ((!it6505_get_video_status(it6505) && + (it6505_test_bit(INT_SCDT_CHANGE, (unsigned int *)int_status))) || + (it6505_test_bit(BIT_INT_IO_FIFO_OVERFLOW, + (unsigned int *)int_status)) || + (it6505_test_bit(BIT_INT_VID_FIFO_ERROR, + (unsigned int *)int_status))) { + it6505->auto_train_retry = AUTO_TRAIN_RETRY; + flush_work(&it6505->link_works); + it6505_stop_hdcp(it6505); + it6505_video_reset(it6505); + + usleep_range(10000, 11000); + + /* + * Clear FIFO error IRQ to prevent fifo error -> reset loop + * HW will trigger SCDT change IRQ again when video stable + */ + + reg_int03 = it6505_read(it6505, INT_STATUS_03); + reg_0d = it6505_read(it6505, REG_SYSTEM_STS); + + reg_int03 &= (BIT(INT_VID_FIFO_ERROR) | BIT(INT_IO_LATCH_FIFO_OVERFLOW)); + it6505_write(it6505, INT_STATUS_03, reg_int03); + + DRM_DEV_DEBUG_DRIVER(dev, "reg08 = 0x%02x", reg_int03); + DRM_DEV_DEBUG_DRIVER(dev, "reg0D = 0x%02x", reg_0d); + + return; + } + + if (it6505_test_bit(INT_SCDT_CHANGE, (unsigned int *)int_status)) + it6505_irq_scdt(it6505); } static irqreturn_t it6505_int_threaded_handler(int unused, void *data) @@ -2508,15 +2535,12 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data) } irq_vec[] = { { BIT_INT_HPD, it6505_irq_hpd }, { BIT_INT_HPD_IRQ, it6505_irq_hpd_irq }, - { BIT_INT_SCDT, it6505_irq_scdt }, { BIT_INT_HDCP_FAIL, it6505_irq_hdcp_fail }, { BIT_INT_HDCP_DONE, it6505_irq_hdcp_done }, { BIT_INT_AUX_CMD_FAIL, it6505_irq_aux_cmd_fail }, { BIT_INT_HDCP_KSV_CHECK, it6505_irq_hdcp_ksv_check }, { BIT_INT_AUDIO_FIFO_ERROR, it6505_irq_audio_fifo_error }, { BIT_INT_LINK_TRAIN_FAIL, it6505_irq_link_train_fail }, - { BIT_INT_VID_FIFO_ERROR, it6505_irq_video_fifo_error }, - { BIT_INT_IO_FIFO_OVERFLOW, it6505_irq_io_latch_fifo_overflow }, }; int int_status[3], i; @@ -2546,6 +2570,7 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data) if (it6505_test_bit(irq_vec[i].bit, (unsigned int *)int_status)) irq_vec[i].handler(it6505); } + it6505_irq_video_handler(it6505, (unsigned int *)int_status); } pm_runtime_put_sync(dev); @@ -2590,7 +2615,7 @@ static int it6505_poweron(struct it6505 *it6505) gpiod_set_value_cansleep(pdata->gpiod_reset, 0); usleep_range(1000, 2000); gpiod_set_value_cansleep(pdata->gpiod_reset, 1); - usleep_range(10000, 20000); + usleep_range(25000, 35000); } it6505->powered = true; @@ -2882,11 +2907,6 @@ static int it6505_bridge_attach(struct drm_bridge *bridge, return -EINVAL; } - if (!bridge->encoder) { - dev_err(dev, "Parent encoder object not found"); - return -ENODEV; - } - /* Register aux channel */ it6505->aux.drm_dev = bridge->dev; diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index b99fe87ec738..73983f9b50cb 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -1195,4 +1195,5 @@ static struct i2c_driver lt9611_driver = { }; module_i2c_driver(lt9611_driver); +MODULE_DESCRIPTION("Lontium LT9611 DSI/HDMI bridge driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index ab702471f3ab..4e802b54a1cb 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -337,11 +337,6 @@ static int lt9611uxc_connector_init(struct drm_bridge *bridge, struct lt9611uxc { int ret; - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found"); - return -ENODEV; - } - lt9611uxc->connector.polled = DRM_CONNECTOR_POLL_HPD; drm_connector_helper_add(<9611uxc->connector, @@ -1021,6 +1016,7 @@ static struct i2c_driver lt9611uxc_driver = { module_i2c_driver(lt9611uxc_driver); MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>"); +MODULE_DESCRIPTION("Lontium LT9611UXC DSI/HDMI bridge driver"); MODULE_LICENSE("GPL v2"); MODULE_FIRMWARE(FW_FILE); diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c index 4480523244e4..37f1acf5c0f8 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -165,11 +165,6 @@ static int ge_b850v3_lvds_create_connector(struct drm_bridge *bridge) struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector; int ret; - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found"); - return -ENODEV; - } - connector->polled = DRM_CONNECTOR_POLL_HPD; drm_connector_helper_add(connector, diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index ed93fd4c3265..e77aab965fcf 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -229,11 +229,6 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge, if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) return 0; - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found"); - return -ENODEV; - } - ptn_bridge->connector.polled = DRM_CONNECTOR_POLL_HPD; ret = drm_connector_init(bridge->dev, &ptn_bridge->connector, &ptn3460_connector_funcs, DRM_MODE_CONNECTOR_LVDS); diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 32506524d9a2..56c40b516a8f 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -67,11 +67,6 @@ static int panel_bridge_attach(struct drm_bridge *bridge, if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) return 0; - if (!bridge->encoder) { - DRM_ERROR("Missing encoder\n"); - return -ENODEV; - } - drm_connector_helper_add(connector, &panel_bridge_connector_helper_funcs); diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 95fedc68b0ae..e7e53a9e42af 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -574,8 +574,8 @@ static unsigned long samsung_dsim_pll_find_pms(struct samsung_dsim *dsi, u16 _m, best_m; u8 _s, best_s; - p_min = DIV_ROUND_UP(fin, (12 * MHZ)); - p_max = fin / (6 * MHZ); + p_min = DIV_ROUND_UP(fin, (driver_data->pll_fin_max * MHZ)); + p_max = fin / (driver_data->pll_fin_min * MHZ); for (_p = p_min; _p <= p_max; ++_p) { for (_s = 0; _s <= 5; ++_s) { @@ -1606,6 +1606,27 @@ static int samsung_dsim_atomic_check(struct drm_bridge *bridge, adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); } + /* + * When using video sync pulses, the HFP, HBP, and HSA are divided between + * the available lanes if there is more than one lane. For certain + * timings and lane configurations, the HFP may not be evenly divisible. + * If the HFP is rounded down, it ends up being too small which can cause + * some monitors to not sync properly. In these instances, adjust htotal + * and hsync to round the HFP up, and recalculate the htotal. Through trial + * and error, it appears that the HBP and HSA do not appearto need the same + * correction that HFP does. + */ + if (dsi->lanes > 1) { + int hfp = adjusted_mode->hsync_start - adjusted_mode->hdisplay; + int remainder = hfp % dsi->lanes; + + if (remainder) { + adjusted_mode->hsync_start += remainder; + adjusted_mode->hsync_end += remainder; + adjusted_mode->htotal += remainder; + } + } + return 0; } diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index 2fbeda9025bf..7f91b0db161e 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -163,6 +163,14 @@ #define SII902X_AUDIO_PORT_INDEX 3 +/* + * The maximum resolution supported by the HDMI bridge is 1080p@60Hz + * and 1920x1200 requiring a pixel clock of 165MHz and the minimum + * resolution supported is 480p@60Hz requiring a pixel clock of 25MHz + */ +#define SII902X_MIN_PIXEL_CLOCK_KHZ 25000 +#define SII902X_MAX_PIXEL_CLOCK_KHZ 165000 + struct sii902x { struct i2c_client *i2c; struct regmap *regmap; @@ -310,20 +318,12 @@ static int sii902x_get_modes(struct drm_connector *connector) return num; } -static enum drm_mode_status sii902x_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - /* TODO: check mode */ - - return MODE_OK; -} - static const struct drm_connector_helper_funcs sii902x_connector_helper_funcs = { .get_modes = sii902x_get_modes, - .mode_valid = sii902x_mode_valid, }; -static void sii902x_bridge_disable(struct drm_bridge *bridge) +static void sii902x_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct sii902x *sii902x = bridge_to_sii902x(bridge); @@ -336,7 +336,8 @@ static void sii902x_bridge_disable(struct drm_bridge *bridge) mutex_unlock(&sii902x->mutex); } -static void sii902x_bridge_enable(struct drm_bridge *bridge) +static void sii902x_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct sii902x *sii902x = bridge_to_sii902x(bridge); @@ -495,6 +496,10 @@ static int sii902x_bridge_atomic_check(struct drm_bridge *bridge, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { + if (crtc_state->mode.clock < SII902X_MIN_PIXEL_CLOCK_KHZ || + crtc_state->mode.clock > SII902X_MAX_PIXEL_CLOCK_KHZ) + return -EINVAL; + /* * There might be flags negotiation supported in future but * set the bus flags in atomic_check statically for now. @@ -504,11 +509,25 @@ static int sii902x_bridge_atomic_check(struct drm_bridge *bridge, return 0; } +static enum drm_mode_status +sii902x_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + if (mode->clock < SII902X_MIN_PIXEL_CLOCK_KHZ) + return MODE_CLOCK_LOW; + + if (mode->clock > SII902X_MAX_PIXEL_CLOCK_KHZ) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + static const struct drm_bridge_funcs sii902x_bridge_funcs = { .attach = sii902x_bridge_attach, .mode_set = sii902x_bridge_mode_set, - .disable = sii902x_bridge_disable, - .enable = sii902x_bridge_enable, + .atomic_disable = sii902x_bridge_atomic_disable, + .atomic_enable = sii902x_bridge_atomic_enable, .detect = sii902x_bridge_detect, .edid_read = sii902x_bridge_edid_read, .atomic_reset = drm_atomic_helper_bridge_reset, @@ -516,6 +535,7 @@ static const struct drm_bridge_funcs sii902x_bridge_funcs = { .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_get_input_bus_fmts = sii902x_bridge_atomic_get_input_bus_fmts, .atomic_check = sii902x_bridge_atomic_check, + .mode_valid = sii902x_bridge_mode_valid, }; static int sii902x_mute(struct sii902x *sii902x, bool mute) diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c index d8373d918324..0c74cdc07032 100644 --- a/drivers/gpu/drm/bridge/sii9234.c +++ b/drivers/gpu/drm/bridge/sii9234.c @@ -961,4 +961,5 @@ static struct i2c_driver sii9234_driver = { }; module_i2c_driver(sii9234_driver); +MODULE_DESCRIPTION("Silicon Image SII9234 HDMI/MHL bridge driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c index 599164e3877d..6bb755e9f0a5 100644 --- a/drivers/gpu/drm/bridge/sil-sii8620.c +++ b/drivers/gpu/drm/bridge/sil-sii8620.c @@ -2384,4 +2384,5 @@ static struct i2c_driver sii8620_driver = { }; module_i2c_driver(sii8620_driver); +MODULE_DESCRIPTION("Silicon Image SiI8620 HDMI/MHL bridge driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c index 5813a2c4fc5e..ab0b0e36e97a 100644 --- a/drivers/gpu/drm/bridge/simple-bridge.c +++ b/drivers/gpu/drm/bridge/simple-bridge.c @@ -116,11 +116,6 @@ static int simple_bridge_attach(struct drm_bridge *bridge, if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) return 0; - if (!bridge->encoder) { - DRM_ERROR("Missing encoder\n"); - return -ENODEV; - } - drm_connector_helper_add(&sbridge->connector, &simple_bridge_con_helper_funcs); ret = drm_connector_init_with_ddc(bridge->dev, &sbridge->connector, @@ -175,7 +170,6 @@ static int simple_bridge_probe(struct platform_device *pdev) sbridge = devm_kzalloc(&pdev->dev, sizeof(*sbridge), GFP_KERNEL); if (!sbridge) return -ENOMEM; - platform_set_drvdata(pdev, sbridge); sbridge->info = of_device_get_match_data(&pdev->dev); @@ -213,16 +207,7 @@ static int simple_bridge_probe(struct platform_device *pdev) sbridge->bridge.of_node = pdev->dev.of_node; sbridge->bridge.timings = sbridge->info->timings; - drm_bridge_add(&sbridge->bridge); - - return 0; -} - -static void simple_bridge_remove(struct platform_device *pdev) -{ - struct simple_bridge *sbridge = platform_get_drvdata(pdev); - - drm_bridge_remove(&sbridge->bridge); + return devm_drm_bridge_add(&pdev->dev, &sbridge->bridge); } /* @@ -299,7 +284,6 @@ MODULE_DEVICE_TABLE(of, simple_bridge_match); static struct platform_driver simple_bridge_driver = { .probe = simple_bridge_probe, - .remove_new = simple_bridge_remove, .driver = { .name = "simple-bridge", .of_match_table = simple_bridge_match, diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 824fb3c65742..c4e9d96933dc 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -1071,11 +1071,6 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge, { struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found\n"); - return -ENODEV; - } - /* Set the encoder type as caller does not know it */ bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI; diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 166f9a3e9622..87c7346d037e 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -382,6 +382,9 @@ struct tc_data { /* HPD pin number (0 or 1) or -ENODEV */ int hpd_pin; + + /* Number of pixels to subtract from a line due to pixel clock delta */ + u32 line_pixel_subtract; }; static inline struct tc_data *aux_to_tc(struct drm_dp_aux *a) @@ -577,6 +580,11 @@ static int tc_pllupdate(struct tc_data *tc, unsigned int pllctrl) return 0; } +static u32 div64_round_up(u64 v, u32 d) +{ + return div_u64(v + d - 1, d); +} + static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) { int ret; @@ -658,8 +666,11 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) return -EINVAL; } - dev_dbg(tc->dev, "PLL: got %d, delta %d\n", best_pixelclock, - best_delta); + tc->line_pixel_subtract = tc->mode.htotal - + div64_round_up(tc->mode.htotal * (u64)best_pixelclock, pixelclock); + + dev_dbg(tc->dev, "PLL: got %d, delta %d (subtract %d px)\n", best_pixelclock, + best_delta, tc->line_pixel_subtract); dev_dbg(tc->dev, "PLL: %d / %d / %d * %d / %d\n", refclk, ext_div[best_pre], best_div, best_mul, ext_div[best_post]); @@ -885,6 +896,12 @@ static int tc_set_common_video_mode(struct tc_data *tc, upper_margin, lower_margin, vsync_len); dev_dbg(tc->dev, "total: %dx%d\n", mode->htotal, mode->vtotal); + if (right_margin > tc->line_pixel_subtract) { + right_margin -= tc->line_pixel_subtract; + } else { + dev_err(tc->dev, "Bridge pixel clock too slow for mode\n"); + right_margin = 0; + } /* * LCD Ctl Frame Size @@ -894,7 +911,7 @@ static int tc_set_common_video_mode(struct tc_data *tc, */ ret = regmap_write(tc->regmap, VPCTRL0, FIELD_PREP(VSDELAY, right_margin + 10) | - OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED); + OPXLFMT_RGB888 | FRMSYNC_ENABLED | MSF_DISABLED); if (ret) return ret; @@ -1629,7 +1646,7 @@ tc_edp_mode_valid(struct drm_bridge *bridge, u32 req, avail; u32 bits_per_pixel = 24; - /* DPI interface clock limitation: upto 154 MHz */ + /* DPI->(e)DP interface clock limitation: up to 154 MHz */ if (mode->clock > 154000) return MODE_CLOCK_HIGH; @@ -2135,7 +2152,7 @@ static irqreturn_t tc_irq_handler(int irq, void *arg) dev_err(tc->dev, "syserr %x\n", stat); } - if (tc->hpd_pin >= 0 && tc->bridge.dev) { + if (tc->hpd_pin >= 0 && tc->bridge.dev && tc->aux.drm_dev) { /* * H is triggered when the GPIO goes high. * diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index c7bef5c23927..b1b1e4d5a24a 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c @@ -133,11 +133,6 @@ static int tfp410_attach(struct drm_bridge *bridge, if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) return 0; - if (!bridge->encoder) { - dev_err(dvi->dev, "Missing encoder\n"); - return -ENODEV; - } - if (dvi->next_bridge->ops & DRM_BRIDGE_OP_DETECT) dvi->connector.polled = DRM_CONNECTOR_POLL_HPD; else diff --git a/drivers/gpu/drm/ci/build-igt.sh b/drivers/gpu/drm/ci/build-igt.sh index 500fa4f5c30a..eddb5f782a5e 100644 --- a/drivers/gpu/drm/ci/build-igt.sh +++ b/drivers/gpu/drm/ci/build-igt.sh @@ -3,6 +3,30 @@ set -ex +function generate_testlist { + set +x + while read -r line; do + if [ "$line" = "TESTLIST" ] || [ "$line" = "END TESTLIST" ]; then + continue + fi + + tests=$(echo "$line" | tr ' ' '\n') + + for test in $tests; do + output=$(/igt/libexec/igt-gpu-tools/"$test" --list-subtests || true) + + if [ -z "$output" ]; then + echo "$test" + else + echo "$output" | while read -r subtest; do + echo "$test@$subtest" + done + fi + done + done < /igt/libexec/igt-gpu-tools/test-list.txt > /igt/libexec/igt-gpu-tools/ci-testlist.txt + set -x +} + git clone https://gitlab.freedesktop.org/drm/igt-gpu-tools.git --single-branch --no-checkout cd igt-gpu-tools git checkout $IGT_VERSION @@ -21,15 +45,30 @@ MESON_OPTIONS="-Doverlay=disabled \ -Dlibunwind=enabled \ -Dprefix=/igt" +if [[ "$KERNEL_ARCH" = "arm64" ]] || [[ "$KERNEL_ARCH" = "arm" ]]; then + MESON_OPTIONS="$MESON_OPTIONS -Dxe_driver=disabled" +fi + mkdir -p /igt meson build $MESON_OPTIONS $EXTRA_MESON_ARGS ninja -C build -j${FDO_CI_CONCURRENT:-4} || ninja -C build -j 1 ninja -C build install +if [[ "$KERNEL_ARCH" = "arm64" ]]; then + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/igt/lib/aarch64-linux-gnu +elif [[ "$KERNEL_ARCH" = "arm" ]]; then + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/igt/lib +else + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/igt/lib64 +fi + +echo "Generating ci-testlist.txt" +generate_testlist + mkdir -p artifacts/ tar -cf artifacts/igt.tar /igt # Pass needed files to the test stage S3_ARTIFACT_NAME="igt.tar.gz" gzip -c artifacts/igt.tar > ${S3_ARTIFACT_NAME} -ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${KERNEL_ARCH}/${S3_ARTIFACT_NAME} +ci-fairy s3cp --token-file "${S3_JWT_FILE}" ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${KERNEL_ARCH}/${S3_ARTIFACT_NAME} diff --git a/drivers/gpu/drm/ci/build.sh b/drivers/gpu/drm/ci/build.sh index 106f2d40d222..5a3bdcffae32 100644 --- a/drivers/gpu/drm/ci/build.sh +++ b/drivers/gpu/drm/ci/build.sh @@ -12,6 +12,9 @@ rm -rf .git/rebase-apply apt-get update apt-get install -y libssl-dev +# for msm header validation +apt-get install -y python3-lxml + if [[ "$KERNEL_ARCH" = "arm64" ]]; then GCC_ARCH="aarch64-linux-gnu" DEBIAN_ARCH="arm64" @@ -128,6 +131,7 @@ fi # Pass needed files to the test stage mkdir -p install cp -rfv .gitlab-ci/* install/. +cp -rfv ci/* install/. cp -rfv install/common install/ci-common cp -rfv drivers/gpu/drm/ci/* install/. @@ -141,21 +145,21 @@ if [[ "$UPLOAD_TO_MINIO" = "1" ]]; then FILES_TO_UPLOAD="$FILES_TO_UPLOAD $(basename -a $DEVICE_TREES)" fi + ls -l "${S3_JWT_FILE}" for f in $FILES_TO_UPLOAD; do - ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" /lava-files/$f \ + ci-fairy s3cp --token-file "${S3_JWT_FILE}" /lava-files/$f \ https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/$f done S3_ARTIFACT_NAME="kernel-files.tar.zst" tar --zstd -cf $S3_ARTIFACT_NAME install - ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/${S3_ARTIFACT_NAME} + ci-fairy s3cp --token-file "${S3_JWT_FILE}" ${S3_ARTIFACT_NAME} https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/${S3_ARTIFACT_NAME} echo "Download vmlinux.xz from https://${PIPELINE_ARTIFACTS_BASE}/${DEBIAN_ARCH}/vmlinux.xz" fi mkdir -p artifacts/install/lib mv install/* artifacts/install/. -rm -rf artifacts/install/modules ln -s common artifacts/install/ci-common cp .config artifacts/${CI_JOB_NAME}_config diff --git a/drivers/gpu/drm/ci/build.yml b/drivers/gpu/drm/ci/build.yml index 17ab38304885..9c198239033d 100644 --- a/drivers/gpu/drm/ci/build.yml +++ b/drivers/gpu/drm/ci/build.yml @@ -106,6 +106,7 @@ build-nodebugfs:arm64: extends: .build:arm64 variables: DISABLE_KCONFIGS: "DEBUG_FS" + ENABLE_KCONFIGS: "EXPERT DRM_MSM_VALIDATE_XML" build:x86_64: extends: .build:x86_64 diff --git a/drivers/gpu/drm/ci/container.yml b/drivers/gpu/drm/ci/container.yml index 9764e7921a4f..d6edf3635b23 100644 --- a/drivers/gpu/drm/ci/container.yml +++ b/drivers/gpu/drm/ci/container.yml @@ -36,15 +36,15 @@ debian/android_build: rules: - when: never -debian/x86_64_test-android: +.debian/x86_64_test-android: rules: - when: never -windows_build_vs2019: +windows_build_msvc: rules: - when: never -windows_test_vs2019: +windows_test_msvc: rules: - when: never @@ -56,10 +56,6 @@ rustfmt: rules: - when: never -windows_vs2019: - rules: - - when: never - -clang-format: +windows_msvc: rules: - when: never
\ No newline at end of file diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml index 084e3ff8e3f4..80fb0f57ae46 100644 --- a/drivers/gpu/drm/ci/gitlab-ci.yml +++ b/drivers/gpu/drm/ci/gitlab-ci.yml @@ -1,11 +1,11 @@ variables: DRM_CI_PROJECT_PATH: &drm-ci-project-path mesa/mesa - DRM_CI_COMMIT_SHA: &drm-ci-commit-sha 9d162de9a05155e1c4041857a5848842749164cf + DRM_CI_COMMIT_SHA: &drm-ci-commit-sha e2b9c5a9e3e4f9b532067af8022eaef8d6fc6c00 UPSTREAM_REPO: git://anongit.freedesktop.org/drm/drm TARGET_BRANCH: drm-next - IGT_VERSION: d2af13d9f5be5ce23d996e4afd3e45990f5ab977 + IGT_VERSION: 0df7b9b97f9da0e364f5ee30fe331004b8c86b56 DEQP_RUNNER_GIT_URL: https://gitlab.freedesktop.org/anholt/deqp-runner.git DEQP_RUNNER_GIT_TAG: v0.15.0 @@ -19,33 +19,47 @@ variables: bash download-git-cache.sh rm download-git-cache.sh set +o xtrace + S3_JWT_FILE: /s3_jwt S3_HOST: s3.freedesktop.org + # This bucket is used to fetch the kernel image + S3_KERNEL_BUCKET: mesa-rootfs + # Bucket for git cache + S3_GITCACHE_BUCKET: git-cache + # Bucket for the pipeline artifacts pushed to S3 + S3_ARTIFACTS_BUCKET: artifacts # per-pipeline artifact storage on MinIO - PIPELINE_ARTIFACTS_BASE: ${S3_HOST}/artifacts/${CI_PROJECT_PATH}/${CI_PIPELINE_ID} + PIPELINE_ARTIFACTS_BASE: ${S3_HOST}/${S3_ARTIFACTS_BUCKET}/${CI_PROJECT_PATH}/${CI_PIPELINE_ID} # per-job artifact storage on MinIO JOB_ARTIFACTS_BASE: ${PIPELINE_ARTIFACTS_BASE}/${CI_JOB_ID} # default kernel for rootfs before injecting the current kernel tree KERNEL_REPO: "gfx-ci/linux" - KERNEL_TAG: "v6.6.4-for-mesa-ci-e4f4c500f7fb" - KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/${KERNEL_REPO}/${KERNEL_TAG} + KERNEL_TAG: "v6.6.21-mesa-f8ea" + KERNEL_IMAGE_BASE: https://${S3_HOST}/${S3_KERNEL_BUCKET}/${KERNEL_REPO}/${KERNEL_TAG} + PKG_REPO_REV: "3cc12a2a" LAVA_TAGS: subset-1-gfx LAVA_JOB_PRIORITY: 30 + ARTIFACTS_BASE_URL: https://${CI_PROJECT_ROOT_NAMESPACE}.${CI_PAGES_DOMAIN}/-/${CI_PROJECT_NAME}/-/jobs/${CI_JOB_ID}/artifacts + # Python scripts for structured logger + PYTHONPATH: "$PYTHONPATH:$CI_PROJECT_DIR/install" default: + id_tokens: + S3_JWT: + aud: https://s3.freedesktop.org before_script: - export SCRIPTS_DIR=$(mktemp -d) - curl -L -s --retry 4 -f --retry-all-errors --retry-delay 60 -O --output-dir "${SCRIPTS_DIR}" "${DRM_CI_PROJECT_URL}/-/raw/${DRM_CI_COMMIT_SHA}/.gitlab-ci/setup-test-env.sh" - source ${SCRIPTS_DIR}/setup-test-env.sh - echo -e "\e[0Ksection_start:$(date +%s):unset_env_vars_section[collapsed=true]\r\e[0KUnsetting vulnerable environment variables" - - export CI_JOB_JWT_FILE="${CI_JOB_JWT_FILE:-$(mktemp)}" - - echo -n "${CI_JOB_JWT}" > "${CI_JOB_JWT_FILE}" - - unset CI_JOB_JWT + - echo -n "${S3_JWT}" > "${S3_JWT_FILE}" + - unset CI_JOB_JWT S3_JWT - echo -e "\e[0Ksection_end:$(date +%s):unset_env_vars_section\r\e[0K" - echo -e "\e[0Ksection_start:$(date +%s):drm_ci_download_section[collapsed=true]\r\e[0KDownloading mesa from $DRM_CI_PROJECT_URL/-/archive/$DRM_CI_COMMIT_SHA/mesa-$DRM_CI_COMMIT_SHA.tar.gz" - cd $CI_PROJECT_DIR - curl --output - $DRM_CI_PROJECT_URL/-/archive/$DRM_CI_COMMIT_SHA/mesa-$DRM_CI_COMMIT_SHA.tar.gz | tar -xz - mv mesa-$DRM_CI_COMMIT_SHA/.gitlab-ci* . + - mv mesa-$DRM_CI_COMMIT_SHA/bin/ci . - rm -rf mesa-$DRM_CI_COMMIT_SHA/ - echo -e "\e[0Ksection_end:$(date +%s):drm_ci_download_section\r\e[0K" @@ -53,9 +67,9 @@ default: - > set +x - test -e "${CI_JOB_JWT_FILE}" && - export CI_JOB_JWT="$(<${CI_JOB_JWT_FILE})" && - rm "${CI_JOB_JWT_FILE}" + test -e "${S3_JWT_FILE}" && + export S3_JWT="$(<${S3_JWT_FILE})" && + rm "${S3_JWT_FILE}" include: - project: 'freedesktop/ci-templates' @@ -87,6 +101,7 @@ include: - '/src/intel/ci/gitlab-ci-inc.yml' - '/src/freedreno/ci/gitlab-ci-inc.yml' - '/src/amd/ci/gitlab-ci-inc.yml' + - '/src/virtio/ci/gitlab-ci-inc.yml' - drivers/gpu/drm/ci/image-tags.yml - drivers/gpu/drm/ci/container.yml - drivers/gpu/drm/ci/static-checks.yml @@ -98,6 +113,7 @@ include: stages: - sanity - container + - code-validation - git-archive - build - amdgpu @@ -107,7 +123,7 @@ stages: - msm - rockchip - virtio-gpu - - lint + - software-driver # YAML anchors for rule conditions # -------------------------------- @@ -218,14 +234,15 @@ make git archive: script: # Remove drm-ci files we just added - rm -rf .gitlab-ci.* + - rm -rf ci # Compactify the .git directory - git gc --aggressive # compress the current folder - tar -cvzf ../$CI_PROJECT_NAME.tar.gz . - # login with the JWT token file - - ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" ../$CI_PROJECT_NAME.tar.gz https://$S3_HOST/git-cache/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/$CI_PROJECT_NAME.tar.gz + # Use id_tokens for JWT auth + - ci-fairy s3cp --token-file "${S3_JWT_FILE}" ../$CI_PROJECT_NAME.tar.gz https://$S3_HOST/${S3_GITCACHE_BUCKET}/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/$CI_PROJECT_NAME.tar.gz # Sanity checks of MR settings and commit logs @@ -262,4 +279,4 @@ sanity: # Jobs that need to pass before spending hardware resources on further testing .required-for-hardware-jobs: - needs: []
\ No newline at end of file + needs: [] diff --git a/drivers/gpu/drm/ci/igt_runner.sh b/drivers/gpu/drm/ci/igt_runner.sh index f1a08b9b146f..79f41d7da772 100755 --- a/drivers/gpu/drm/ci/igt_runner.sh +++ b/drivers/gpu/drm/ci/igt_runner.sh @@ -30,10 +30,10 @@ case "$DRIVER_NAME" in export IGT_FORCE_DRIVER="panfrost" fi ;; - amdgpu) + amdgpu|vkms) # Cannot use HWCI_KERNEL_MODULES as at that point we don't have the module in /lib - mv /install/modules/lib/modules/* /lib/modules/. - modprobe amdgpu + mv /install/modules/lib/modules/* /lib/modules/. || true + modprobe --first-time $DRIVER_NAME ;; esac @@ -59,25 +59,26 @@ fi curl -L --retry 4 -f --retry-all-errors --retry-delay 60 -s ${FDO_HTTP_CACHE_URI:-}$PIPELINE_ARTIFACTS_BASE/$ARCH/igt.tar.gz | tar --zstd -v -x -C / +TESTLIST="/igt/libexec/igt-gpu-tools/ci-testlist.txt" # If the job is parallel at the gitab job level, take the corresponding fraction # of the caselist. if [ -n "$CI_NODE_INDEX" ]; then - sed -ni $CI_NODE_INDEX~$CI_NODE_TOTAL"p" /install/testlist.txt + sed -ni $CI_NODE_INDEX~$CI_NODE_TOTAL"p" $TESTLIST fi # core_getversion checks if the driver is loaded and probed correctly # so run it in all shards -if ! grep -q "core_getversion" /install/testlist.txt; then +if ! grep -q "core_getversion" $TESTLIST; then # Add the line to the file - echo "core_getversion" >> /install/testlist.txt + echo "core_getversion" >> $TESTLIST fi set +e igt-runner \ run \ --igt-folder /igt/libexec/igt-gpu-tools \ - --caselist /install/testlist.txt \ + --caselist $TESTLIST \ --output /results \ $IGT_SKIPS \ $IGT_FLAKES \ diff --git a/drivers/gpu/drm/ci/image-tags.yml b/drivers/gpu/drm/ci/image-tags.yml index 7ab4f2514da8..13eda37bdf05 100644 --- a/drivers/gpu/drm/ci/image-tags.yml +++ b/drivers/gpu/drm/ci/image-tags.yml @@ -1,10 +1,10 @@ variables: - CONTAINER_TAG: "2023-10-11-mesa-uprev" + CONTAINER_TAG: "2024-05-09-mesa-uprev" DEBIAN_X86_64_BUILD_BASE_IMAGE: "debian/x86_64_build-base" DEBIAN_BASE_TAG: "${CONTAINER_TAG}" DEBIAN_X86_64_BUILD_IMAGE_PATH: "debian/x86_64_build" - DEBIAN_BUILD_TAG: "2023-10-08-config" + DEBIAN_BUILD_TAG: "2024-06-10-vkms" KERNEL_ROOTFS_TAG: "2023-10-06-amd" diff --git a/drivers/gpu/drm/ci/lava-submit.sh b/drivers/gpu/drm/ci/lava-submit.sh index 3d39b0c916a8..0707fa706a48 100755 --- a/drivers/gpu/drm/ci/lava-submit.sh +++ b/drivers/gpu/drm/ci/lava-submit.sh @@ -27,7 +27,7 @@ KERNEL_IMAGE_BASE="https://${BASE_SYSTEM_HOST_PATH}" \ section_end variables tar zcf job-rootfs-overlay.tar.gz -C results/job-rootfs-overlay/ . -ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" job-rootfs-overlay.tar.gz "https://${JOB_ROOTFS_OVERLAY_PATH}" +ci-fairy s3cp --token-file "${S3_JWT_FILE}" job-rootfs-overlay.tar.gz "https://${JOB_ROOTFS_OVERLAY_PATH}" touch results/lava.log tail -f results/lava.log & @@ -45,7 +45,7 @@ PYTHONPATH=artifacts/ artifacts/lava/lava_job_submitter.py \ --ci-project-dir "${CI_PROJECT_DIR}" \ --device-type "${DEVICE_TYPE}" \ --dtb-filename "${DTB}" \ - --jwt-file "${CI_JOB_JWT_FILE}" \ + --jwt-file "${S3_JWT_FILE}" \ --kernel-image-name "${KERNEL_IMAGE_NAME}" \ --kernel-image-type "${KERNEL_IMAGE_TYPE}" \ --boot-method "${BOOT_METHOD}" \ diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml index 8bc63912fddb..ee908b66aad2 100644 --- a/drivers/gpu/drm/ci/test.yml +++ b/drivers/gpu/drm/ci/test.yml @@ -24,6 +24,7 @@ variables: HWCI_TEST_SCRIPT: "/install/igt_runner.sh" DEBIAN_ARCH: "armhf" + FARM: collabora dependencies: - testing:arm32 needs: @@ -39,6 +40,7 @@ variables: HWCI_TEST_SCRIPT: "/install/igt_runner.sh" DEBIAN_ARCH: "arm64" + FARM: collabora dependencies: - testing:arm64 needs: @@ -54,6 +56,7 @@ variables: HWCI_TEST_SCRIPT: "/install/igt_runner.sh" DEBIAN_ARCH: "amd64" + FARM: collabora dependencies: - testing:x86_64 needs: @@ -74,6 +77,7 @@ S3_ARTIFACT_NAME: "arm64/kernel-files" BM_KERNEL: https://${PIPELINE_ARTIFACTS_BASE}/arm64/Image.gz BM_CMDLINE: "ip=dhcp console=ttyMSM0,115200n8 $BM_KERNEL_EXTRA_ARGS root=/dev/nfs rw nfsrootdebug nfsroot=,tcp,nfsvers=4.2 init=/init $BM_KERNELARGS" + FARM: google needs: - debian/arm64_test - job: testing:arm64 @@ -116,8 +120,9 @@ msm:apq8016: - .baremetal-igt-arm64 stage: msm variables: + DEVICE_TYPE: apq8016-sbc-usb-host DRIVER_NAME: msm - BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8016-sbc-usb-host.dtb + BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/${DEVICE_TYPE}.dtb GPU_VERSION: apq8016 # disabling unused clocks congests with the MDSS runtime PM trying to # disable those clocks and causes boot to fail. @@ -132,9 +137,10 @@ msm:apq8096: - .baremetal-igt-arm64 stage: msm variables: + DEVICE_TYPE: apq8096-db820c DRIVER_NAME: msm BM_KERNEL_EXTRA_ARGS: maxcpus=2 - BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8096-db820c.dtb + BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/${DEVICE_TYPE}.dtb GPU_VERSION: apq8096 RUNNER_TAG: google-freedreno-db820c script: @@ -146,6 +152,7 @@ msm:sdm845: stage: msm parallel: 6 variables: + DEVICE_TYPE: sdm845-cheza-r3 DRIVER_NAME: msm BM_KERNEL: https://${PIPELINE_ARTIFACTS_BASE}/arm64/cheza-kernel GPU_VERSION: sdm845 @@ -184,6 +191,7 @@ rockchip:rk3399: extends: - .lava-igt:x86_64 stage: i915 + timeout: "1h30m" variables: DRIVER_NAME: i915 DTB: "" @@ -194,7 +202,6 @@ i915:apl: extends: - .i915 parallel: 3 - timeout: "1h30m" variables: DEVICE_TYPE: asus-C523NA-A20057-coral GPU_VERSION: apl @@ -204,7 +211,6 @@ i915:glk: extends: - .i915 parallel: 2 - timeout: "1h30m" variables: DEVICE_TYPE: hp-x360-12b-ca0010nr-n4020-octopus GPU_VERSION: glk @@ -214,7 +220,6 @@ i915:amly: extends: - .i915 parallel: 2 - timeout: "1h30m" variables: DEVICE_TYPE: asus-C433TA-AJ0005-rammus GPU_VERSION: amly @@ -233,7 +238,6 @@ i915:whl: extends: - .i915 parallel: 2 - timeout: "1h30m" variables: DEVICE_TYPE: dell-latitude-5400-8665U-sarien GPU_VERSION: whl @@ -243,7 +247,6 @@ i915:cml: extends: - .i915 parallel: 2 - timeout: "1h30m" variables: DEVICE_TYPE: asus-C436FA-Flip-hatch GPU_VERSION: cml @@ -335,7 +338,7 @@ meson:g12b: RUNNER_TAG: mesa-ci-x86-64-lava-meson-g12b-a311d-khadas-vim3 virtio_gpu:none: - stage: virtio-gpu + stage: software-driver variables: CROSVM_GALLIUM_DRIVER: llvmpipe DRIVER_NAME: virtio_gpu @@ -355,3 +358,25 @@ virtio_gpu:none: - debian/x86_64_test-gl - testing:x86_64 - igt:x86_64 + +vkms:none: + stage: software-driver + variables: + DRIVER_NAME: vkms + GPU_VERSION: none + extends: + - .test-gl + - .test-rules + tags: + - kvm + script: + - ln -sf $CI_PROJECT_DIR/install /install + - mv install/bzImage /lava-files/bzImage + - mkdir -p /lib/modules + - mkdir -p $CI_PROJECT_DIR/results + - ln -sf $CI_PROJECT_DIR/results /results + - ./install/crosvm-runner.sh ./install/igt_runner.sh + needs: + - debian/x86_64_test-gl + - testing:x86_64 + - igt:x86_64 diff --git a/drivers/gpu/drm/ci/testlist.txt b/drivers/gpu/drm/ci/testlist.txt deleted file mode 100644 index 3377f002f8c5..000000000000 --- a/drivers/gpu/drm/ci/testlist.txt +++ /dev/null @@ -1,2761 +0,0 @@ -core_auth@getclient-simple -core_auth@getclient-master-drop -core_auth@basic-auth -core_auth@many-magics -core_getclient -core_getstats -core_getversion -core_setmaster_vs_auth -drm_read@invalid-buffer -drm_read@fault-buffer -drm_read@empty-block -drm_read@empty-nonblock -drm_read@short-buffer-block -drm_read@short-buffer-nonblock -drm_read@short-buffer-wakeup -gem_eio@throttle -gem_eio@create -gem_eio@create-ext -gem_eio@context-create -gem_eio@execbuf -gem_eio@banned -gem_eio@suspend -gem_eio@hibernate -gem_eio@in-flight-external -gem_eio@in-flight-suspend -gem_eio@reset-stress -gem_eio@unwedge-stress -gem_eio@wait-immediate -gem_eio@wait-wedge-immediate -gem_eio@in-flight-immediate -gem_eio@in-flight-contexts-immediate -gem_eio@in-flight-internal-immediate -gem_eio@wait-1us -gem_eio@wait-wedge-1us -gem_eio@in-flight-1us -gem_eio@in-flight-contexts-1us -gem_eio@in-flight-internal-1us -gem_eio@wait-10ms -gem_eio@wait-wedge-10ms -gem_eio@in-flight-10ms -gem_eio@in-flight-contexts-10ms -gem_eio@in-flight-internal-10ms -gem_eio@kms -kms_3d -kms_addfb_basic@unused-handle -kms_addfb_basic@unused-pitches -kms_addfb_basic@unused-offsets -kms_addfb_basic@unused-modifier -kms_addfb_basic@clobberred-modifier -kms_addfb_basic@invalid-smem-bo-on-discrete -kms_addfb_basic@legacy-format -kms_addfb_basic@no-handle -kms_addfb_basic@basic -kms_addfb_basic@bad-pitch-0 -kms_addfb_basic@bad-pitch-32 -kms_addfb_basic@bad-pitch-63 -kms_addfb_basic@bad-pitch-128 -kms_addfb_basic@bad-pitch-256 -kms_addfb_basic@bad-pitch-1024 -kms_addfb_basic@bad-pitch-999 -kms_addfb_basic@bad-pitch-65536 -kms_addfb_basic@invalid-get-prop-any -kms_addfb_basic@invalid-get-prop -kms_addfb_basic@invalid-set-prop-any -kms_addfb_basic@invalid-set-prop -kms_addfb_basic@master-rmfb -kms_addfb_basic@addfb25-modifier-no-flag -kms_addfb_basic@addfb25-bad-modifier -kms_addfb_basic@addfb25-x-tiled-mismatch-legacy -kms_addfb_basic@addfb25-x-tiled-legacy -kms_addfb_basic@addfb25-framebuffer-vs-set-tiling -kms_addfb_basic@basic-x-tiled-legacy -kms_addfb_basic@framebuffer-vs-set-tiling -kms_addfb_basic@tile-pitch-mismatch -kms_addfb_basic@basic-y-tiled-legacy -kms_addfb_basic@size-max -kms_addfb_basic@too-wide -kms_addfb_basic@too-high -kms_addfb_basic@bo-too-small -kms_addfb_basic@small-bo -kms_addfb_basic@bo-too-small-due-to-tiling -kms_addfb_basic@addfb25-y-tiled-legacy -kms_addfb_basic@addfb25-yf-tiled-legacy -kms_addfb_basic@addfb25-y-tiled-small-legacy -kms_addfb_basic@addfb25-4-tiled -kms_async_flips@async-flip-with-page-flip-events -kms_async_flips@alternate-sync-async-flip -kms_async_flips@test-time-stamp -kms_async_flips@test-cursor -kms_async_flips@invalid-async-flip -kms_async_flips@crc -kms_atomic@plane-overlay-legacy -kms_atomic@plane-primary-legacy -kms_atomic@plane-primary-overlay-mutable-zpos -kms_atomic@plane-immutable-zpos -kms_atomic@test-only -kms_atomic@plane-cursor-legacy -kms_atomic@plane-invalid-params -kms_atomic@plane-invalid-params-fence -kms_atomic@crtc-invalid-params -kms_atomic@crtc-invalid-params-fence -kms_atomic@atomic-invalid-params -kms_atomic@atomic-plane-damage -kms_atomic_interruptible@legacy-setmode -kms_atomic_interruptible@atomic-setmode -kms_atomic_interruptible@legacy-dpms -kms_atomic_interruptible@legacy-pageflip -kms_atomic_interruptible@legacy-cursor -kms_atomic_interruptible@universal-setplane-primary -kms_atomic_interruptible@universal-setplane-cursor -kms_atomic_transition@plane-primary-toggle-with-vblank-wait -kms_atomic_transition@plane-all-transition -kms_atomic_transition@plane-all-transition-fencing -kms_atomic_transition@plane-all-transition-nonblocking -kms_atomic_transition@plane-all-transition-nonblocking-fencing -kms_atomic_transition@plane-use-after-nonblocking-unbind -kms_atomic_transition@plane-use-after-nonblocking-unbind-fencing -kms_atomic_transition@plane-all-modeset-transition -kms_atomic_transition@plane-all-modeset-transition-fencing -kms_atomic_transition@plane-all-modeset-transition-internal-panels -kms_atomic_transition@plane-all-modeset-transition-fencing-internal-panels -kms_atomic_transition@plane-toggle-modeset-transition -kms_atomic_transition@modeset-transition -kms_atomic_transition@modeset-transition-fencing -kms_atomic_transition@modeset-transition-nonblocking -kms_atomic_transition@modeset-transition-nonblocking-fencing -kms_big_fb@x-tiled-addfb-size-overflow -kms_big_fb@y-tiled-addfb-size-overflow -kms_big_fb@yf-tiled-addfb-size-overflow -kms_big_fb@4-tiled-addfb-size-overflow -kms_big_fb@x-tiled-addfb-size-offset-overflow -kms_big_fb@y-tiled-addfb-size-offset-overflow -kms_big_fb@yf-tiled-addfb-size-offset-overflow -kms_big_fb@4-tiled-addfb-size-offset-overflow -kms_big_fb@linear-addfb -kms_big_fb@x-tiled-addfb -kms_big_fb@y-tiled-addfb -kms_big_fb@yf-tiled-addfb -kms_big_fb@4-tiled-addfb -kms_big_fb@linear-8bpp-rotate-0 -kms_big_fb@linear-8bpp-rotate-90 -kms_big_fb@linear-8bpp-rotate-180 -kms_big_fb@linear-8bpp-rotate-270 -kms_big_fb@linear-16bpp-rotate-0 -kms_big_fb@linear-16bpp-rotate-90 -kms_big_fb@linear-16bpp-rotate-180 -kms_big_fb@linear-16bpp-rotate-270 -kms_big_fb@linear-32bpp-rotate-0 -kms_big_fb@linear-32bpp-rotate-90 -kms_big_fb@linear-32bpp-rotate-180 -kms_big_fb@linear-32bpp-rotate-270 -kms_big_fb@linear-64bpp-rotate-0 -kms_big_fb@linear-64bpp-rotate-90 -kms_big_fb@linear-64bpp-rotate-180 -kms_big_fb@linear-64bpp-rotate-270 -kms_big_fb@x-tiled-8bpp-rotate-0 -kms_big_fb@x-tiled-8bpp-rotate-90 -kms_big_fb@x-tiled-8bpp-rotate-180 -kms_big_fb@x-tiled-8bpp-rotate-270 -kms_big_fb@x-tiled-16bpp-rotate-0 -kms_big_fb@x-tiled-16bpp-rotate-90 -kms_big_fb@x-tiled-16bpp-rotate-180 -kms_big_fb@x-tiled-16bpp-rotate-270 -kms_big_fb@x-tiled-32bpp-rotate-0 -kms_big_fb@x-tiled-32bpp-rotate-90 -kms_big_fb@x-tiled-32bpp-rotate-180 -kms_big_fb@x-tiled-32bpp-rotate-270 -kms_big_fb@x-tiled-64bpp-rotate-0 -kms_big_fb@x-tiled-64bpp-rotate-90 -kms_big_fb@x-tiled-64bpp-rotate-180 -kms_big_fb@x-tiled-64bpp-rotate-270 -kms_big_fb@y-tiled-8bpp-rotate-0 -kms_big_fb@y-tiled-8bpp-rotate-90 -kms_big_fb@y-tiled-8bpp-rotate-180 -kms_big_fb@y-tiled-8bpp-rotate-270 -kms_big_fb@y-tiled-16bpp-rotate-0 -kms_big_fb@y-tiled-16bpp-rotate-90 -kms_big_fb@y-tiled-16bpp-rotate-180 -kms_big_fb@y-tiled-16bpp-rotate-270 -kms_big_fb@y-tiled-32bpp-rotate-0 -kms_big_fb@y-tiled-32bpp-rotate-90 -kms_big_fb@y-tiled-32bpp-rotate-180 -kms_big_fb@y-tiled-32bpp-rotate-270 -kms_big_fb@y-tiled-64bpp-rotate-0 -kms_big_fb@y-tiled-64bpp-rotate-90 -kms_big_fb@y-tiled-64bpp-rotate-180 -kms_big_fb@y-tiled-64bpp-rotate-270 -kms_big_fb@yf-tiled-8bpp-rotate-0 -kms_big_fb@yf-tiled-8bpp-rotate-90 -kms_big_fb@yf-tiled-8bpp-rotate-180 -kms_big_fb@yf-tiled-8bpp-rotate-270 -kms_big_fb@yf-tiled-16bpp-rotate-0 -kms_big_fb@yf-tiled-16bpp-rotate-90 -kms_big_fb@yf-tiled-16bpp-rotate-180 -kms_big_fb@yf-tiled-16bpp-rotate-270 -kms_big_fb@yf-tiled-32bpp-rotate-0 -kms_big_fb@yf-tiled-32bpp-rotate-90 -kms_big_fb@yf-tiled-32bpp-rotate-180 -kms_big_fb@yf-tiled-32bpp-rotate-270 -kms_big_fb@yf-tiled-64bpp-rotate-0 -kms_big_fb@yf-tiled-64bpp-rotate-90 -kms_big_fb@yf-tiled-64bpp-rotate-180 -kms_big_fb@yf-tiled-64bpp-rotate-270 -kms_big_fb@4-tiled-8bpp-rotate-0 -kms_big_fb@4-tiled-8bpp-rotate-90 -kms_big_fb@4-tiled-8bpp-rotate-180 -kms_big_fb@4-tiled-8bpp-rotate-270 -kms_big_fb@4-tiled-16bpp-rotate-0 -kms_big_fb@4-tiled-16bpp-rotate-90 -kms_big_fb@4-tiled-16bpp-rotate-180 -kms_big_fb@4-tiled-16bpp-rotate-270 -kms_big_fb@4-tiled-32bpp-rotate-0 -kms_big_fb@4-tiled-32bpp-rotate-90 -kms_big_fb@4-tiled-32bpp-rotate-180 -kms_big_fb@4-tiled-32bpp-rotate-270 -kms_big_fb@4-tiled-64bpp-rotate-0 -kms_big_fb@4-tiled-64bpp-rotate-90 -kms_big_fb@4-tiled-64bpp-rotate-180 -kms_big_fb@4-tiled-64bpp-rotate-270 -kms_big_fb@linear-max-hw-stride-32bpp-rotate-0 -kms_big_fb@linear-max-hw-stride-32bpp-rotate-180 -kms_big_fb@linear-max-hw-stride-64bpp-rotate-0 -kms_big_fb@linear-max-hw-stride-64bpp-rotate-180 -kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0 -kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0-async-flip -kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-180 -kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-180-async-flip -kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0 -kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0-async-flip -kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-180 -kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-180-async-flip -kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0-hflip -kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip -kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-180-hflip -kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip -kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0-hflip -kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip -kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-180-hflip -kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip -kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0 -kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0-async-flip -kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180 -kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-async-flip -kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0 -kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-async-flip -kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180 -kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-async-flip -kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0-hflip -kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip -kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-hflip -kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip -kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-hflip -kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip -kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip -kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip -kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0 -kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-async-flip -kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180 -kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-async-flip -kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0 -kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-async-flip -kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180 -kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180-async-flip -kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip -kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip -kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-hflip -kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip -kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip -kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip -kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180-hflip -kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip -kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0 -kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-async-flip -kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-180 -kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-180-async-flip -kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0 -kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-async-flip -kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180 -kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180-async-flip -kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip -kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip -kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-180-hflip -kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip -kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-hflip -kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip -kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180-hflip -kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip -kms_big_joiner@basic -kms_big_joiner@invalid-modeset -kms_big_joiner@2x-modeset -kms_busy@basic -kms_busy@basic-hang -kms_busy@extended-pageflip-modeset-hang-oldfb -kms_busy@extended-pageflip-hang-oldfb -kms_busy@extended-pageflip-hang-newfb -kms_busy@extended-modeset-hang-oldfb -kms_busy@extended-modeset-hang-newfb -kms_busy@extended-modeset-hang-oldfb-with-reset -kms_busy@extended-modeset-hang-newfb-with-reset -kms_bw@linear-tiling-1-displays-1920x1080p -kms_bw@linear-tiling-1-displays-2560x1440p -kms_bw@linear-tiling-1-displays-3840x2160p -kms_bw@linear-tiling-2-displays-1920x1080p -kms_bw@linear-tiling-2-displays-2560x1440p -kms_bw@linear-tiling-2-displays-3840x2160p -kms_bw@linear-tiling-3-displays-1920x1080p -kms_bw@linear-tiling-3-displays-2560x1440p -kms_bw@linear-tiling-3-displays-3840x2160p -kms_bw@linear-tiling-4-displays-1920x1080p -kms_bw@linear-tiling-4-displays-2560x1440p -kms_bw@linear-tiling-4-displays-3840x2160p -kms_bw@linear-tiling-5-displays-1920x1080p -kms_bw@linear-tiling-5-displays-2560x1440p -kms_bw@linear-tiling-5-displays-3840x2160p -kms_bw@linear-tiling-6-displays-1920x1080p -kms_bw@linear-tiling-6-displays-2560x1440p -kms_bw@linear-tiling-6-displays-3840x2160p -kms_bw@linear-tiling-7-displays-1920x1080p -kms_bw@linear-tiling-7-displays-2560x1440p -kms_bw@linear-tiling-7-displays-3840x2160p -kms_bw@linear-tiling-8-displays-1920x1080p -kms_bw@linear-tiling-8-displays-2560x1440p -kms_bw@linear-tiling-8-displays-3840x2160p -kms_ccs@pipe-A-bad-pixel-format-y-tiled-ccs -kms_ccs@pipe-A-bad-pixel-format-yf-tiled-ccs -kms_ccs@pipe-A-bad-pixel-format-y-tiled-gen12-rc-ccs -kms_ccs@pipe-A-bad-pixel-format-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-A-bad-pixel-format-y-tiled-gen12-mc-ccs -kms_ccs@pipe-A-bad-pixel-format-4-tiled-dg2-rc-ccs -kms_ccs@pipe-A-bad-pixel-format-4-tiled-dg2-mc-ccs -kms_ccs@pipe-A-bad-pixel-format-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-A-bad-pixel-format-4-tiled-mtl-rc-ccs -kms_ccs@pipe-A-bad-pixel-format-4-tiled-mtl-mc-ccs -kms_ccs@pipe-A-bad-pixel-format-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-A-bad-rotation-90-y-tiled-ccs -kms_ccs@pipe-A-bad-rotation-90-yf-tiled-ccs -kms_ccs@pipe-A-bad-rotation-90-y-tiled-gen12-rc-ccs -kms_ccs@pipe-A-bad-rotation-90-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-A-bad-rotation-90-y-tiled-gen12-mc-ccs -kms_ccs@pipe-A-bad-rotation-90-4-tiled-dg2-rc-ccs -kms_ccs@pipe-A-bad-rotation-90-4-tiled-dg2-mc-ccs -kms_ccs@pipe-A-bad-rotation-90-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-A-bad-rotation-90-4-tiled-mtl-rc-ccs -kms_ccs@pipe-A-bad-rotation-90-4-tiled-mtl-mc-ccs -kms_ccs@pipe-A-bad-rotation-90-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-A-crc-primary-basic-y-tiled-ccs -kms_ccs@pipe-A-crc-primary-basic-yf-tiled-ccs -kms_ccs@pipe-A-crc-primary-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-A-crc-primary-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-A-crc-primary-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-A-crc-primary-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-A-crc-primary-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-A-crc-primary-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-A-crc-primary-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-A-crc-primary-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-A-crc-primary-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-A-crc-primary-rotation-180-y-tiled-ccs -kms_ccs@pipe-A-crc-primary-rotation-180-yf-tiled-ccs -kms_ccs@pipe-A-crc-primary-rotation-180-y-tiled-gen12-rc-ccs -kms_ccs@pipe-A-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-A-crc-primary-rotation-180-y-tiled-gen12-mc-ccs -kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-dg2-rc-ccs -kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-dg2-mc-ccs -kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-mtl-rc-ccs -kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-mtl-mc-ccs -kms_ccs@pipe-A-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-A-random-ccs-data-y-tiled-ccs -kms_ccs@pipe-A-random-ccs-data-yf-tiled-ccs -kms_ccs@pipe-A-random-ccs-data-y-tiled-gen12-rc-ccs -kms_ccs@pipe-A-random-ccs-data-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-A-random-ccs-data-y-tiled-gen12-mc-ccs -kms_ccs@pipe-A-random-ccs-data-4-tiled-dg2-rc-ccs -kms_ccs@pipe-A-random-ccs-data-4-tiled-dg2-mc-ccs -kms_ccs@pipe-A-random-ccs-data-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-A-random-ccs-data-4-tiled-mtl-rc-ccs -kms_ccs@pipe-A-random-ccs-data-4-tiled-mtl-mc-ccs -kms_ccs@pipe-A-random-ccs-data-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-A-missing-ccs-buffer-y-tiled-ccs -kms_ccs@pipe-A-missing-ccs-buffer-yf-tiled-ccs -kms_ccs@pipe-A-missing-ccs-buffer-y-tiled-gen12-rc-ccs -kms_ccs@pipe-A-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-A-missing-ccs-buffer-y-tiled-gen12-mc-ccs -kms_ccs@pipe-A-missing-ccs-buffer-4-tiled-mtl-rc-ccs -kms_ccs@pipe-A-missing-ccs-buffer-4-tiled-mtl-mc-ccs -kms_ccs@pipe-A-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-A-ccs-on-another-bo-y-tiled-ccs -kms_ccs@pipe-A-ccs-on-another-bo-yf-tiled-ccs -kms_ccs@pipe-A-ccs-on-another-bo-y-tiled-gen12-rc-ccs -kms_ccs@pipe-A-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-A-ccs-on-another-bo-y-tiled-gen12-mc-ccs -kms_ccs@pipe-A-ccs-on-another-bo-4-tiled-mtl-rc-ccs -kms_ccs@pipe-A-ccs-on-another-bo-4-tiled-mtl-mc-ccs -kms_ccs@pipe-A-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-A-bad-aux-stride-y-tiled-ccs -kms_ccs@pipe-A-bad-aux-stride-yf-tiled-ccs -kms_ccs@pipe-A-bad-aux-stride-y-tiled-gen12-rc-ccs -kms_ccs@pipe-A-bad-aux-stride-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-A-bad-aux-stride-y-tiled-gen12-mc-ccs -kms_ccs@pipe-A-bad-aux-stride-4-tiled-mtl-rc-ccs -kms_ccs@pipe-A-bad-aux-stride-4-tiled-mtl-mc-ccs -kms_ccs@pipe-A-bad-aux-stride-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-A-crc-sprite-planes-basic-y-tiled-ccs -kms_ccs@pipe-A-crc-sprite-planes-basic-yf-tiled-ccs -kms_ccs@pipe-A-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-A-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-A-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-A-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-B-bad-pixel-format-y-tiled-ccs -kms_ccs@pipe-B-bad-pixel-format-yf-tiled-ccs -kms_ccs@pipe-B-bad-pixel-format-y-tiled-gen12-rc-ccs -kms_ccs@pipe-B-bad-pixel-format-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-B-bad-pixel-format-y-tiled-gen12-mc-ccs -kms_ccs@pipe-B-bad-pixel-format-4-tiled-dg2-rc-ccs -kms_ccs@pipe-B-bad-pixel-format-4-tiled-dg2-mc-ccs -kms_ccs@pipe-B-bad-pixel-format-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-B-bad-pixel-format-4-tiled-mtl-rc-ccs -kms_ccs@pipe-B-bad-pixel-format-4-tiled-mtl-mc-ccs -kms_ccs@pipe-B-bad-pixel-format-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-B-bad-rotation-90-y-tiled-ccs -kms_ccs@pipe-B-bad-rotation-90-yf-tiled-ccs -kms_ccs@pipe-B-bad-rotation-90-y-tiled-gen12-rc-ccs -kms_ccs@pipe-B-bad-rotation-90-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-B-bad-rotation-90-y-tiled-gen12-mc-ccs -kms_ccs@pipe-B-bad-rotation-90-4-tiled-dg2-rc-ccs -kms_ccs@pipe-B-bad-rotation-90-4-tiled-dg2-mc-ccs -kms_ccs@pipe-B-bad-rotation-90-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-B-bad-rotation-90-4-tiled-mtl-rc-ccs -kms_ccs@pipe-B-bad-rotation-90-4-tiled-mtl-mc-ccs -kms_ccs@pipe-B-bad-rotation-90-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-B-crc-primary-basic-y-tiled-ccs -kms_ccs@pipe-B-crc-primary-basic-yf-tiled-ccs -kms_ccs@pipe-B-crc-primary-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-B-crc-primary-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-B-crc-primary-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-B-crc-primary-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-B-crc-primary-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-B-crc-primary-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-B-crc-primary-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-B-crc-primary-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-B-crc-primary-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-B-crc-primary-rotation-180-y-tiled-ccs -kms_ccs@pipe-B-crc-primary-rotation-180-yf-tiled-ccs -kms_ccs@pipe-B-crc-primary-rotation-180-y-tiled-gen12-rc-ccs -kms_ccs@pipe-B-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-B-crc-primary-rotation-180-y-tiled-gen12-mc-ccs -kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-dg2-rc-ccs -kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-dg2-mc-ccs -kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-mtl-rc-ccs -kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-mtl-mc-ccs -kms_ccs@pipe-B-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-B-random-ccs-data-y-tiled-ccs -kms_ccs@pipe-B-random-ccs-data-yf-tiled-ccs -kms_ccs@pipe-B-random-ccs-data-y-tiled-gen12-rc-ccs -kms_ccs@pipe-B-random-ccs-data-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-B-random-ccs-data-y-tiled-gen12-mc-ccs -kms_ccs@pipe-B-random-ccs-data-4-tiled-dg2-rc-ccs -kms_ccs@pipe-B-random-ccs-data-4-tiled-dg2-mc-ccs -kms_ccs@pipe-B-random-ccs-data-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-B-random-ccs-data-4-tiled-mtl-rc-ccs -kms_ccs@pipe-B-random-ccs-data-4-tiled-mtl-mc-ccs -kms_ccs@pipe-B-random-ccs-data-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-B-missing-ccs-buffer-y-tiled-ccs -kms_ccs@pipe-B-missing-ccs-buffer-yf-tiled-ccs -kms_ccs@pipe-B-missing-ccs-buffer-y-tiled-gen12-rc-ccs -kms_ccs@pipe-B-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-B-missing-ccs-buffer-y-tiled-gen12-mc-ccs -kms_ccs@pipe-B-missing-ccs-buffer-4-tiled-mtl-rc-ccs -kms_ccs@pipe-B-missing-ccs-buffer-4-tiled-mtl-mc-ccs -kms_ccs@pipe-B-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-B-ccs-on-another-bo-y-tiled-ccs -kms_ccs@pipe-B-ccs-on-another-bo-yf-tiled-ccs -kms_ccs@pipe-B-ccs-on-another-bo-y-tiled-gen12-rc-ccs -kms_ccs@pipe-B-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-B-ccs-on-another-bo-y-tiled-gen12-mc-ccs -kms_ccs@pipe-B-ccs-on-another-bo-4-tiled-mtl-rc-ccs -kms_ccs@pipe-B-ccs-on-another-bo-4-tiled-mtl-mc-ccs -kms_ccs@pipe-B-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-B-bad-aux-stride-y-tiled-ccs -kms_ccs@pipe-B-bad-aux-stride-yf-tiled-ccs -kms_ccs@pipe-B-bad-aux-stride-y-tiled-gen12-rc-ccs -kms_ccs@pipe-B-bad-aux-stride-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-B-bad-aux-stride-y-tiled-gen12-mc-ccs -kms_ccs@pipe-B-bad-aux-stride-4-tiled-mtl-rc-ccs -kms_ccs@pipe-B-bad-aux-stride-4-tiled-mtl-mc-ccs -kms_ccs@pipe-B-bad-aux-stride-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-B-crc-sprite-planes-basic-y-tiled-ccs -kms_ccs@pipe-B-crc-sprite-planes-basic-yf-tiled-ccs -kms_ccs@pipe-B-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-B-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-B-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-B-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-C-bad-pixel-format-y-tiled-ccs -kms_ccs@pipe-C-bad-pixel-format-yf-tiled-ccs -kms_ccs@pipe-C-bad-pixel-format-y-tiled-gen12-rc-ccs -kms_ccs@pipe-C-bad-pixel-format-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-C-bad-pixel-format-y-tiled-gen12-mc-ccs -kms_ccs@pipe-C-bad-pixel-format-4-tiled-dg2-rc-ccs -kms_ccs@pipe-C-bad-pixel-format-4-tiled-dg2-mc-ccs -kms_ccs@pipe-C-bad-pixel-format-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-C-bad-pixel-format-4-tiled-mtl-rc-ccs -kms_ccs@pipe-C-bad-pixel-format-4-tiled-mtl-mc-ccs -kms_ccs@pipe-C-bad-pixel-format-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-C-bad-rotation-90-y-tiled-ccs -kms_ccs@pipe-C-bad-rotation-90-yf-tiled-ccs -kms_ccs@pipe-C-bad-rotation-90-y-tiled-gen12-rc-ccs -kms_ccs@pipe-C-bad-rotation-90-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-C-bad-rotation-90-y-tiled-gen12-mc-ccs -kms_ccs@pipe-C-bad-rotation-90-4-tiled-dg2-rc-ccs -kms_ccs@pipe-C-bad-rotation-90-4-tiled-dg2-mc-ccs -kms_ccs@pipe-C-bad-rotation-90-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-C-bad-rotation-90-4-tiled-mtl-rc-ccs -kms_ccs@pipe-C-bad-rotation-90-4-tiled-mtl-mc-ccs -kms_ccs@pipe-C-bad-rotation-90-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-C-crc-primary-basic-y-tiled-ccs -kms_ccs@pipe-C-crc-primary-basic-yf-tiled-ccs -kms_ccs@pipe-C-crc-primary-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-C-crc-primary-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-C-crc-primary-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-C-crc-primary-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-C-crc-primary-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-C-crc-primary-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-C-crc-primary-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-C-crc-primary-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-C-crc-primary-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-C-crc-primary-rotation-180-y-tiled-ccs -kms_ccs@pipe-C-crc-primary-rotation-180-yf-tiled-ccs -kms_ccs@pipe-C-crc-primary-rotation-180-y-tiled-gen12-rc-ccs -kms_ccs@pipe-C-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-C-crc-primary-rotation-180-y-tiled-gen12-mc-ccs -kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-dg2-rc-ccs -kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-dg2-mc-ccs -kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-mtl-rc-ccs -kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-mtl-mc-ccs -kms_ccs@pipe-C-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-C-random-ccs-data-y-tiled-ccs -kms_ccs@pipe-C-random-ccs-data-yf-tiled-ccs -kms_ccs@pipe-C-random-ccs-data-y-tiled-gen12-rc-ccs -kms_ccs@pipe-C-random-ccs-data-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-C-random-ccs-data-y-tiled-gen12-mc-ccs -kms_ccs@pipe-C-random-ccs-data-4-tiled-dg2-rc-ccs -kms_ccs@pipe-C-random-ccs-data-4-tiled-dg2-mc-ccs -kms_ccs@pipe-C-random-ccs-data-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-C-random-ccs-data-4-tiled-mtl-rc-ccs -kms_ccs@pipe-C-random-ccs-data-4-tiled-mtl-mc-ccs -kms_ccs@pipe-C-random-ccs-data-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-C-missing-ccs-buffer-y-tiled-ccs -kms_ccs@pipe-C-missing-ccs-buffer-yf-tiled-ccs -kms_ccs@pipe-C-missing-ccs-buffer-y-tiled-gen12-rc-ccs -kms_ccs@pipe-C-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-C-missing-ccs-buffer-y-tiled-gen12-mc-ccs -kms_ccs@pipe-C-missing-ccs-buffer-4-tiled-mtl-rc-ccs -kms_ccs@pipe-C-missing-ccs-buffer-4-tiled-mtl-mc-ccs -kms_ccs@pipe-C-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-C-ccs-on-another-bo-y-tiled-ccs -kms_ccs@pipe-C-ccs-on-another-bo-yf-tiled-ccs -kms_ccs@pipe-C-ccs-on-another-bo-y-tiled-gen12-rc-ccs -kms_ccs@pipe-C-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-C-ccs-on-another-bo-y-tiled-gen12-mc-ccs -kms_ccs@pipe-C-ccs-on-another-bo-4-tiled-mtl-rc-ccs -kms_ccs@pipe-C-ccs-on-another-bo-4-tiled-mtl-mc-ccs -kms_ccs@pipe-C-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-C-bad-aux-stride-y-tiled-ccs -kms_ccs@pipe-C-bad-aux-stride-yf-tiled-ccs -kms_ccs@pipe-C-bad-aux-stride-y-tiled-gen12-rc-ccs -kms_ccs@pipe-C-bad-aux-stride-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-C-bad-aux-stride-y-tiled-gen12-mc-ccs -kms_ccs@pipe-C-bad-aux-stride-4-tiled-mtl-rc-ccs -kms_ccs@pipe-C-bad-aux-stride-4-tiled-mtl-mc-ccs -kms_ccs@pipe-C-bad-aux-stride-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-C-crc-sprite-planes-basic-y-tiled-ccs -kms_ccs@pipe-C-crc-sprite-planes-basic-yf-tiled-ccs -kms_ccs@pipe-C-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-C-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-C-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-C-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-D-bad-pixel-format-y-tiled-ccs -kms_ccs@pipe-D-bad-pixel-format-yf-tiled-ccs -kms_ccs@pipe-D-bad-pixel-format-y-tiled-gen12-rc-ccs -kms_ccs@pipe-D-bad-pixel-format-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-D-bad-pixel-format-y-tiled-gen12-mc-ccs -kms_ccs@pipe-D-bad-pixel-format-4-tiled-dg2-rc-ccs -kms_ccs@pipe-D-bad-pixel-format-4-tiled-dg2-mc-ccs -kms_ccs@pipe-D-bad-pixel-format-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-D-bad-pixel-format-4-tiled-mtl-rc-ccs -kms_ccs@pipe-D-bad-pixel-format-4-tiled-mtl-mc-ccs -kms_ccs@pipe-D-bad-pixel-format-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-D-bad-rotation-90-y-tiled-ccs -kms_ccs@pipe-D-bad-rotation-90-yf-tiled-ccs -kms_ccs@pipe-D-bad-rotation-90-y-tiled-gen12-rc-ccs -kms_ccs@pipe-D-bad-rotation-90-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-D-bad-rotation-90-y-tiled-gen12-mc-ccs -kms_ccs@pipe-D-bad-rotation-90-4-tiled-dg2-rc-ccs -kms_ccs@pipe-D-bad-rotation-90-4-tiled-dg2-mc-ccs -kms_ccs@pipe-D-bad-rotation-90-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-D-bad-rotation-90-4-tiled-mtl-rc-ccs -kms_ccs@pipe-D-bad-rotation-90-4-tiled-mtl-mc-ccs -kms_ccs@pipe-D-bad-rotation-90-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-D-crc-primary-basic-y-tiled-ccs -kms_ccs@pipe-D-crc-primary-basic-yf-tiled-ccs -kms_ccs@pipe-D-crc-primary-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-D-crc-primary-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-D-crc-primary-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-D-crc-primary-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-D-crc-primary-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-D-crc-primary-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-D-crc-primary-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-D-crc-primary-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-D-crc-primary-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-D-crc-primary-rotation-180-y-tiled-ccs -kms_ccs@pipe-D-crc-primary-rotation-180-yf-tiled-ccs -kms_ccs@pipe-D-crc-primary-rotation-180-y-tiled-gen12-rc-ccs -kms_ccs@pipe-D-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-D-crc-primary-rotation-180-y-tiled-gen12-mc-ccs -kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-dg2-rc-ccs -kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-dg2-mc-ccs -kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-mtl-rc-ccs -kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-mtl-mc-ccs -kms_ccs@pipe-D-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-D-random-ccs-data-y-tiled-ccs -kms_ccs@pipe-D-random-ccs-data-yf-tiled-ccs -kms_ccs@pipe-D-random-ccs-data-y-tiled-gen12-rc-ccs -kms_ccs@pipe-D-random-ccs-data-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-D-random-ccs-data-y-tiled-gen12-mc-ccs -kms_ccs@pipe-D-random-ccs-data-4-tiled-dg2-rc-ccs -kms_ccs@pipe-D-random-ccs-data-4-tiled-dg2-mc-ccs -kms_ccs@pipe-D-random-ccs-data-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-D-random-ccs-data-4-tiled-mtl-rc-ccs -kms_ccs@pipe-D-random-ccs-data-4-tiled-mtl-mc-ccs -kms_ccs@pipe-D-random-ccs-data-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-D-missing-ccs-buffer-y-tiled-ccs -kms_ccs@pipe-D-missing-ccs-buffer-yf-tiled-ccs -kms_ccs@pipe-D-missing-ccs-buffer-y-tiled-gen12-rc-ccs -kms_ccs@pipe-D-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-D-missing-ccs-buffer-y-tiled-gen12-mc-ccs -kms_ccs@pipe-D-missing-ccs-buffer-4-tiled-mtl-rc-ccs -kms_ccs@pipe-D-missing-ccs-buffer-4-tiled-mtl-mc-ccs -kms_ccs@pipe-D-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-D-ccs-on-another-bo-y-tiled-ccs -kms_ccs@pipe-D-ccs-on-another-bo-yf-tiled-ccs -kms_ccs@pipe-D-ccs-on-another-bo-y-tiled-gen12-rc-ccs -kms_ccs@pipe-D-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-D-ccs-on-another-bo-y-tiled-gen12-mc-ccs -kms_ccs@pipe-D-ccs-on-another-bo-4-tiled-mtl-rc-ccs -kms_ccs@pipe-D-ccs-on-another-bo-4-tiled-mtl-mc-ccs -kms_ccs@pipe-D-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-D-bad-aux-stride-y-tiled-ccs -kms_ccs@pipe-D-bad-aux-stride-yf-tiled-ccs -kms_ccs@pipe-D-bad-aux-stride-y-tiled-gen12-rc-ccs -kms_ccs@pipe-D-bad-aux-stride-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-D-bad-aux-stride-y-tiled-gen12-mc-ccs -kms_ccs@pipe-D-bad-aux-stride-4-tiled-mtl-rc-ccs -kms_ccs@pipe-D-bad-aux-stride-4-tiled-mtl-mc-ccs -kms_ccs@pipe-D-bad-aux-stride-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-D-crc-sprite-planes-basic-y-tiled-ccs -kms_ccs@pipe-D-crc-sprite-planes-basic-yf-tiled-ccs -kms_ccs@pipe-D-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-D-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-D-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-D-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-E-bad-pixel-format-y-tiled-ccs -kms_ccs@pipe-E-bad-pixel-format-yf-tiled-ccs -kms_ccs@pipe-E-bad-pixel-format-y-tiled-gen12-rc-ccs -kms_ccs@pipe-E-bad-pixel-format-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-E-bad-pixel-format-y-tiled-gen12-mc-ccs -kms_ccs@pipe-E-bad-pixel-format-4-tiled-dg2-rc-ccs -kms_ccs@pipe-E-bad-pixel-format-4-tiled-dg2-mc-ccs -kms_ccs@pipe-E-bad-pixel-format-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-E-bad-pixel-format-4-tiled-mtl-rc-ccs -kms_ccs@pipe-E-bad-pixel-format-4-tiled-mtl-mc-ccs -kms_ccs@pipe-E-bad-pixel-format-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-E-bad-rotation-90-y-tiled-ccs -kms_ccs@pipe-E-bad-rotation-90-yf-tiled-ccs -kms_ccs@pipe-E-bad-rotation-90-y-tiled-gen12-rc-ccs -kms_ccs@pipe-E-bad-rotation-90-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-E-bad-rotation-90-y-tiled-gen12-mc-ccs -kms_ccs@pipe-E-bad-rotation-90-4-tiled-dg2-rc-ccs -kms_ccs@pipe-E-bad-rotation-90-4-tiled-dg2-mc-ccs -kms_ccs@pipe-E-bad-rotation-90-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-E-bad-rotation-90-4-tiled-mtl-rc-ccs -kms_ccs@pipe-E-bad-rotation-90-4-tiled-mtl-mc-ccs -kms_ccs@pipe-E-bad-rotation-90-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-E-crc-primary-basic-y-tiled-ccs -kms_ccs@pipe-E-crc-primary-basic-yf-tiled-ccs -kms_ccs@pipe-E-crc-primary-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-E-crc-primary-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-E-crc-primary-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-E-crc-primary-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-E-crc-primary-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-E-crc-primary-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-E-crc-primary-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-E-crc-primary-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-E-crc-primary-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-E-crc-primary-rotation-180-y-tiled-ccs -kms_ccs@pipe-E-crc-primary-rotation-180-yf-tiled-ccs -kms_ccs@pipe-E-crc-primary-rotation-180-y-tiled-gen12-rc-ccs -kms_ccs@pipe-E-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-E-crc-primary-rotation-180-y-tiled-gen12-mc-ccs -kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-dg2-rc-ccs -kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-dg2-mc-ccs -kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-mtl-rc-ccs -kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-mtl-mc-ccs -kms_ccs@pipe-E-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-E-random-ccs-data-y-tiled-ccs -kms_ccs@pipe-E-random-ccs-data-yf-tiled-ccs -kms_ccs@pipe-E-random-ccs-data-y-tiled-gen12-rc-ccs -kms_ccs@pipe-E-random-ccs-data-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-E-random-ccs-data-y-tiled-gen12-mc-ccs -kms_ccs@pipe-E-random-ccs-data-4-tiled-dg2-rc-ccs -kms_ccs@pipe-E-random-ccs-data-4-tiled-dg2-mc-ccs -kms_ccs@pipe-E-random-ccs-data-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-E-random-ccs-data-4-tiled-mtl-rc-ccs -kms_ccs@pipe-E-random-ccs-data-4-tiled-mtl-mc-ccs -kms_ccs@pipe-E-random-ccs-data-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-E-missing-ccs-buffer-y-tiled-ccs -kms_ccs@pipe-E-missing-ccs-buffer-yf-tiled-ccs -kms_ccs@pipe-E-missing-ccs-buffer-y-tiled-gen12-rc-ccs -kms_ccs@pipe-E-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-E-missing-ccs-buffer-y-tiled-gen12-mc-ccs -kms_ccs@pipe-E-missing-ccs-buffer-4-tiled-mtl-rc-ccs -kms_ccs@pipe-E-missing-ccs-buffer-4-tiled-mtl-mc-ccs -kms_ccs@pipe-E-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-E-ccs-on-another-bo-y-tiled-ccs -kms_ccs@pipe-E-ccs-on-another-bo-yf-tiled-ccs -kms_ccs@pipe-E-ccs-on-another-bo-y-tiled-gen12-rc-ccs -kms_ccs@pipe-E-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-E-ccs-on-another-bo-y-tiled-gen12-mc-ccs -kms_ccs@pipe-E-ccs-on-another-bo-4-tiled-mtl-rc-ccs -kms_ccs@pipe-E-ccs-on-another-bo-4-tiled-mtl-mc-ccs -kms_ccs@pipe-E-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-E-bad-aux-stride-y-tiled-ccs -kms_ccs@pipe-E-bad-aux-stride-yf-tiled-ccs -kms_ccs@pipe-E-bad-aux-stride-y-tiled-gen12-rc-ccs -kms_ccs@pipe-E-bad-aux-stride-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-E-bad-aux-stride-y-tiled-gen12-mc-ccs -kms_ccs@pipe-E-bad-aux-stride-4-tiled-mtl-rc-ccs -kms_ccs@pipe-E-bad-aux-stride-4-tiled-mtl-mc-ccs -kms_ccs@pipe-E-bad-aux-stride-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-E-crc-sprite-planes-basic-y-tiled-ccs -kms_ccs@pipe-E-crc-sprite-planes-basic-yf-tiled-ccs -kms_ccs@pipe-E-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-E-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-E-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-E-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-F-bad-pixel-format-y-tiled-ccs -kms_ccs@pipe-F-bad-pixel-format-yf-tiled-ccs -kms_ccs@pipe-F-bad-pixel-format-y-tiled-gen12-rc-ccs -kms_ccs@pipe-F-bad-pixel-format-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-F-bad-pixel-format-y-tiled-gen12-mc-ccs -kms_ccs@pipe-F-bad-pixel-format-4-tiled-dg2-rc-ccs -kms_ccs@pipe-F-bad-pixel-format-4-tiled-dg2-mc-ccs -kms_ccs@pipe-F-bad-pixel-format-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-F-bad-pixel-format-4-tiled-mtl-rc-ccs -kms_ccs@pipe-F-bad-pixel-format-4-tiled-mtl-mc-ccs -kms_ccs@pipe-F-bad-pixel-format-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-F-bad-rotation-90-y-tiled-ccs -kms_ccs@pipe-F-bad-rotation-90-yf-tiled-ccs -kms_ccs@pipe-F-bad-rotation-90-y-tiled-gen12-rc-ccs -kms_ccs@pipe-F-bad-rotation-90-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-F-bad-rotation-90-y-tiled-gen12-mc-ccs -kms_ccs@pipe-F-bad-rotation-90-4-tiled-dg2-rc-ccs -kms_ccs@pipe-F-bad-rotation-90-4-tiled-dg2-mc-ccs -kms_ccs@pipe-F-bad-rotation-90-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-F-bad-rotation-90-4-tiled-mtl-rc-ccs -kms_ccs@pipe-F-bad-rotation-90-4-tiled-mtl-mc-ccs -kms_ccs@pipe-F-bad-rotation-90-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-F-crc-primary-basic-y-tiled-ccs -kms_ccs@pipe-F-crc-primary-basic-yf-tiled-ccs -kms_ccs@pipe-F-crc-primary-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-F-crc-primary-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-F-crc-primary-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-F-crc-primary-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-F-crc-primary-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-F-crc-primary-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-F-crc-primary-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-F-crc-primary-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-F-crc-primary-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-F-crc-primary-rotation-180-y-tiled-ccs -kms_ccs@pipe-F-crc-primary-rotation-180-yf-tiled-ccs -kms_ccs@pipe-F-crc-primary-rotation-180-y-tiled-gen12-rc-ccs -kms_ccs@pipe-F-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-F-crc-primary-rotation-180-y-tiled-gen12-mc-ccs -kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-dg2-rc-ccs -kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-dg2-mc-ccs -kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-mtl-rc-ccs -kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-mtl-mc-ccs -kms_ccs@pipe-F-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-F-random-ccs-data-y-tiled-ccs -kms_ccs@pipe-F-random-ccs-data-yf-tiled-ccs -kms_ccs@pipe-F-random-ccs-data-y-tiled-gen12-rc-ccs -kms_ccs@pipe-F-random-ccs-data-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-F-random-ccs-data-y-tiled-gen12-mc-ccs -kms_ccs@pipe-F-random-ccs-data-4-tiled-dg2-rc-ccs -kms_ccs@pipe-F-random-ccs-data-4-tiled-dg2-mc-ccs -kms_ccs@pipe-F-random-ccs-data-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-F-random-ccs-data-4-tiled-mtl-rc-ccs -kms_ccs@pipe-F-random-ccs-data-4-tiled-mtl-mc-ccs -kms_ccs@pipe-F-random-ccs-data-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-F-missing-ccs-buffer-y-tiled-ccs -kms_ccs@pipe-F-missing-ccs-buffer-yf-tiled-ccs -kms_ccs@pipe-F-missing-ccs-buffer-y-tiled-gen12-rc-ccs -kms_ccs@pipe-F-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-F-missing-ccs-buffer-y-tiled-gen12-mc-ccs -kms_ccs@pipe-F-missing-ccs-buffer-4-tiled-mtl-rc-ccs -kms_ccs@pipe-F-missing-ccs-buffer-4-tiled-mtl-mc-ccs -kms_ccs@pipe-F-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-F-ccs-on-another-bo-y-tiled-ccs -kms_ccs@pipe-F-ccs-on-another-bo-yf-tiled-ccs -kms_ccs@pipe-F-ccs-on-another-bo-y-tiled-gen12-rc-ccs -kms_ccs@pipe-F-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-F-ccs-on-another-bo-y-tiled-gen12-mc-ccs -kms_ccs@pipe-F-ccs-on-another-bo-4-tiled-mtl-rc-ccs -kms_ccs@pipe-F-ccs-on-another-bo-4-tiled-mtl-mc-ccs -kms_ccs@pipe-F-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-F-bad-aux-stride-y-tiled-ccs -kms_ccs@pipe-F-bad-aux-stride-yf-tiled-ccs -kms_ccs@pipe-F-bad-aux-stride-y-tiled-gen12-rc-ccs -kms_ccs@pipe-F-bad-aux-stride-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-F-bad-aux-stride-y-tiled-gen12-mc-ccs -kms_ccs@pipe-F-bad-aux-stride-4-tiled-mtl-rc-ccs -kms_ccs@pipe-F-bad-aux-stride-4-tiled-mtl-mc-ccs -kms_ccs@pipe-F-bad-aux-stride-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-F-crc-sprite-planes-basic-y-tiled-ccs -kms_ccs@pipe-F-crc-sprite-planes-basic-yf-tiled-ccs -kms_ccs@pipe-F-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-F-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-F-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-F-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-G-bad-pixel-format-y-tiled-ccs -kms_ccs@pipe-G-bad-pixel-format-yf-tiled-ccs -kms_ccs@pipe-G-bad-pixel-format-y-tiled-gen12-rc-ccs -kms_ccs@pipe-G-bad-pixel-format-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-G-bad-pixel-format-y-tiled-gen12-mc-ccs -kms_ccs@pipe-G-bad-pixel-format-4-tiled-dg2-rc-ccs -kms_ccs@pipe-G-bad-pixel-format-4-tiled-dg2-mc-ccs -kms_ccs@pipe-G-bad-pixel-format-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-G-bad-pixel-format-4-tiled-mtl-rc-ccs -kms_ccs@pipe-G-bad-pixel-format-4-tiled-mtl-mc-ccs -kms_ccs@pipe-G-bad-pixel-format-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-G-bad-rotation-90-y-tiled-ccs -kms_ccs@pipe-G-bad-rotation-90-yf-tiled-ccs -kms_ccs@pipe-G-bad-rotation-90-y-tiled-gen12-rc-ccs -kms_ccs@pipe-G-bad-rotation-90-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-G-bad-rotation-90-y-tiled-gen12-mc-ccs -kms_ccs@pipe-G-bad-rotation-90-4-tiled-dg2-rc-ccs -kms_ccs@pipe-G-bad-rotation-90-4-tiled-dg2-mc-ccs -kms_ccs@pipe-G-bad-rotation-90-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-G-bad-rotation-90-4-tiled-mtl-rc-ccs -kms_ccs@pipe-G-bad-rotation-90-4-tiled-mtl-mc-ccs -kms_ccs@pipe-G-bad-rotation-90-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-G-crc-primary-basic-y-tiled-ccs -kms_ccs@pipe-G-crc-primary-basic-yf-tiled-ccs -kms_ccs@pipe-G-crc-primary-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-G-crc-primary-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-G-crc-primary-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-G-crc-primary-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-G-crc-primary-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-G-crc-primary-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-G-crc-primary-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-G-crc-primary-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-G-crc-primary-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-G-crc-primary-rotation-180-y-tiled-ccs -kms_ccs@pipe-G-crc-primary-rotation-180-yf-tiled-ccs -kms_ccs@pipe-G-crc-primary-rotation-180-y-tiled-gen12-rc-ccs -kms_ccs@pipe-G-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-G-crc-primary-rotation-180-y-tiled-gen12-mc-ccs -kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-dg2-rc-ccs -kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-dg2-mc-ccs -kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-mtl-rc-ccs -kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-mtl-mc-ccs -kms_ccs@pipe-G-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-G-random-ccs-data-y-tiled-ccs -kms_ccs@pipe-G-random-ccs-data-yf-tiled-ccs -kms_ccs@pipe-G-random-ccs-data-y-tiled-gen12-rc-ccs -kms_ccs@pipe-G-random-ccs-data-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-G-random-ccs-data-y-tiled-gen12-mc-ccs -kms_ccs@pipe-G-random-ccs-data-4-tiled-dg2-rc-ccs -kms_ccs@pipe-G-random-ccs-data-4-tiled-dg2-mc-ccs -kms_ccs@pipe-G-random-ccs-data-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-G-random-ccs-data-4-tiled-mtl-rc-ccs -kms_ccs@pipe-G-random-ccs-data-4-tiled-mtl-mc-ccs -kms_ccs@pipe-G-random-ccs-data-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-G-missing-ccs-buffer-y-tiled-ccs -kms_ccs@pipe-G-missing-ccs-buffer-yf-tiled-ccs -kms_ccs@pipe-G-missing-ccs-buffer-y-tiled-gen12-rc-ccs -kms_ccs@pipe-G-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-G-missing-ccs-buffer-y-tiled-gen12-mc-ccs -kms_ccs@pipe-G-missing-ccs-buffer-4-tiled-mtl-rc-ccs -kms_ccs@pipe-G-missing-ccs-buffer-4-tiled-mtl-mc-ccs -kms_ccs@pipe-G-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-G-ccs-on-another-bo-y-tiled-ccs -kms_ccs@pipe-G-ccs-on-another-bo-yf-tiled-ccs -kms_ccs@pipe-G-ccs-on-another-bo-y-tiled-gen12-rc-ccs -kms_ccs@pipe-G-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-G-ccs-on-another-bo-y-tiled-gen12-mc-ccs -kms_ccs@pipe-G-ccs-on-another-bo-4-tiled-mtl-rc-ccs -kms_ccs@pipe-G-ccs-on-another-bo-4-tiled-mtl-mc-ccs -kms_ccs@pipe-G-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-G-bad-aux-stride-y-tiled-ccs -kms_ccs@pipe-G-bad-aux-stride-yf-tiled-ccs -kms_ccs@pipe-G-bad-aux-stride-y-tiled-gen12-rc-ccs -kms_ccs@pipe-G-bad-aux-stride-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-G-bad-aux-stride-y-tiled-gen12-mc-ccs -kms_ccs@pipe-G-bad-aux-stride-4-tiled-mtl-rc-ccs -kms_ccs@pipe-G-bad-aux-stride-4-tiled-mtl-mc-ccs -kms_ccs@pipe-G-bad-aux-stride-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-G-crc-sprite-planes-basic-y-tiled-ccs -kms_ccs@pipe-G-crc-sprite-planes-basic-yf-tiled-ccs -kms_ccs@pipe-G-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-G-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-G-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-G-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-H-bad-pixel-format-y-tiled-ccs -kms_ccs@pipe-H-bad-pixel-format-yf-tiled-ccs -kms_ccs@pipe-H-bad-pixel-format-y-tiled-gen12-rc-ccs -kms_ccs@pipe-H-bad-pixel-format-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-H-bad-pixel-format-y-tiled-gen12-mc-ccs -kms_ccs@pipe-H-bad-pixel-format-4-tiled-dg2-rc-ccs -kms_ccs@pipe-H-bad-pixel-format-4-tiled-dg2-mc-ccs -kms_ccs@pipe-H-bad-pixel-format-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-H-bad-pixel-format-4-tiled-mtl-rc-ccs -kms_ccs@pipe-H-bad-pixel-format-4-tiled-mtl-mc-ccs -kms_ccs@pipe-H-bad-pixel-format-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-H-bad-rotation-90-y-tiled-ccs -kms_ccs@pipe-H-bad-rotation-90-yf-tiled-ccs -kms_ccs@pipe-H-bad-rotation-90-y-tiled-gen12-rc-ccs -kms_ccs@pipe-H-bad-rotation-90-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-H-bad-rotation-90-y-tiled-gen12-mc-ccs -kms_ccs@pipe-H-bad-rotation-90-4-tiled-dg2-rc-ccs -kms_ccs@pipe-H-bad-rotation-90-4-tiled-dg2-mc-ccs -kms_ccs@pipe-H-bad-rotation-90-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-H-bad-rotation-90-4-tiled-mtl-rc-ccs -kms_ccs@pipe-H-bad-rotation-90-4-tiled-mtl-mc-ccs -kms_ccs@pipe-H-bad-rotation-90-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-H-crc-primary-basic-y-tiled-ccs -kms_ccs@pipe-H-crc-primary-basic-yf-tiled-ccs -kms_ccs@pipe-H-crc-primary-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-H-crc-primary-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-H-crc-primary-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-H-crc-primary-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-H-crc-primary-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-H-crc-primary-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-H-crc-primary-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-H-crc-primary-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-H-crc-primary-basic-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-H-crc-primary-rotation-180-y-tiled-ccs -kms_ccs@pipe-H-crc-primary-rotation-180-yf-tiled-ccs -kms_ccs@pipe-H-crc-primary-rotation-180-y-tiled-gen12-rc-ccs -kms_ccs@pipe-H-crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-H-crc-primary-rotation-180-y-tiled-gen12-mc-ccs -kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-dg2-rc-ccs -kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-dg2-mc-ccs -kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-mtl-rc-ccs -kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-mtl-mc-ccs -kms_ccs@pipe-H-crc-primary-rotation-180-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-H-random-ccs-data-y-tiled-ccs -kms_ccs@pipe-H-random-ccs-data-yf-tiled-ccs -kms_ccs@pipe-H-random-ccs-data-y-tiled-gen12-rc-ccs -kms_ccs@pipe-H-random-ccs-data-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-H-random-ccs-data-y-tiled-gen12-mc-ccs -kms_ccs@pipe-H-random-ccs-data-4-tiled-dg2-rc-ccs -kms_ccs@pipe-H-random-ccs-data-4-tiled-dg2-mc-ccs -kms_ccs@pipe-H-random-ccs-data-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-H-random-ccs-data-4-tiled-mtl-rc-ccs -kms_ccs@pipe-H-random-ccs-data-4-tiled-mtl-mc-ccs -kms_ccs@pipe-H-random-ccs-data-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-H-missing-ccs-buffer-y-tiled-ccs -kms_ccs@pipe-H-missing-ccs-buffer-yf-tiled-ccs -kms_ccs@pipe-H-missing-ccs-buffer-y-tiled-gen12-rc-ccs -kms_ccs@pipe-H-missing-ccs-buffer-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-H-missing-ccs-buffer-y-tiled-gen12-mc-ccs -kms_ccs@pipe-H-missing-ccs-buffer-4-tiled-mtl-rc-ccs -kms_ccs@pipe-H-missing-ccs-buffer-4-tiled-mtl-mc-ccs -kms_ccs@pipe-H-missing-ccs-buffer-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-H-ccs-on-another-bo-y-tiled-ccs -kms_ccs@pipe-H-ccs-on-another-bo-yf-tiled-ccs -kms_ccs@pipe-H-ccs-on-another-bo-y-tiled-gen12-rc-ccs -kms_ccs@pipe-H-ccs-on-another-bo-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-H-ccs-on-another-bo-y-tiled-gen12-mc-ccs -kms_ccs@pipe-H-ccs-on-another-bo-4-tiled-mtl-rc-ccs -kms_ccs@pipe-H-ccs-on-another-bo-4-tiled-mtl-mc-ccs -kms_ccs@pipe-H-ccs-on-another-bo-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-H-bad-aux-stride-y-tiled-ccs -kms_ccs@pipe-H-bad-aux-stride-yf-tiled-ccs -kms_ccs@pipe-H-bad-aux-stride-y-tiled-gen12-rc-ccs -kms_ccs@pipe-H-bad-aux-stride-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-H-bad-aux-stride-y-tiled-gen12-mc-ccs -kms_ccs@pipe-H-bad-aux-stride-4-tiled-mtl-rc-ccs -kms_ccs@pipe-H-bad-aux-stride-4-tiled-mtl-mc-ccs -kms_ccs@pipe-H-bad-aux-stride-4-tiled-mtl-rc-ccs-cc -kms_ccs@pipe-H-crc-sprite-planes-basic-y-tiled-ccs -kms_ccs@pipe-H-crc-sprite-planes-basic-yf-tiled-ccs -kms_ccs@pipe-H-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs -kms_ccs@pipe-H-crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc -kms_ccs@pipe-H-crc-sprite-planes-basic-y-tiled-gen12-mc-ccs -kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs -kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-dg2-mc-ccs -kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-dg2-rc-ccs-cc -kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs -kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-mtl-mc-ccs -kms_ccs@pipe-H-crc-sprite-planes-basic-4-tiled-mtl-rc-ccs-cc -kms_cdclk@plane-scaling -kms_cdclk@mode-transition -kms_cdclk@mode-transition-all-outputs -kms_color@degamma -kms_color@gamma -kms_color@legacy-gamma -kms_color@legacy-gamma-reset -kms_color@ctm-red-to-blue -kms_color@ctm-green-to-red -kms_color@ctm-blue-to-red -kms_color@ctm-max -kms_color@ctm-negative -kms_color@ctm-0-25 -kms_color@ctm-0-50 -kms_color@ctm-0-75 -kms_color@ctm-signed -kms_color@deep-color -kms_color@invalid-gamma-lut-sizes -kms_color@invalid-degamma-lut-sizes -kms_color@invalid-ctm-matrix-sizes -kms_concurrent@multi-plane-atomic-lowres -kms_content_protection@legacy -kms_content_protection@atomic -kms_content_protection@atomic-dpms -kms_content_protection@lic -kms_content_protection@type1 -kms_content_protection@mei-interface -kms_content_protection@content-type-change -kms_content_protection@uevent -kms_content_protection@srm -kms_content_protection@dp-mst-type-0 -kms_content_protection@dp-mst-lic-type-0 -kms_content_protection@dp-mst-type-1 -kms_content_protection@dp-mst-lic-type-1 -kms_cursor_crc@cursor-size-change -kms_cursor_crc@cursor-alpha-opaque -kms_cursor_crc@cursor-alpha-transparent -kms_cursor_crc@cursor-dpms -kms_cursor_crc@cursor-suspend -kms_cursor_crc@cursor-onscreen-32x32 -kms_cursor_crc@cursor-offscreen-32x32 -kms_cursor_crc@cursor-sliding-32x32 -kms_cursor_crc@cursor-random-32x32 -kms_cursor_crc@cursor-rapid-movement-32x32 -kms_cursor_crc@cursor-onscreen-32x10 -kms_cursor_crc@cursor-offscreen-32x10 -kms_cursor_crc@cursor-sliding-32x10 -kms_cursor_crc@cursor-random-32x10 -kms_cursor_crc@cursor-rapid-movement-32x10 -kms_cursor_crc@cursor-onscreen-64x64 -kms_cursor_crc@cursor-offscreen-64x64 -kms_cursor_crc@cursor-sliding-64x64 -kms_cursor_crc@cursor-random-64x64 -kms_cursor_crc@cursor-rapid-movement-64x64 -kms_cursor_crc@cursor-onscreen-64x21 -kms_cursor_crc@cursor-offscreen-64x21 -kms_cursor_crc@cursor-sliding-64x21 -kms_cursor_crc@cursor-random-64x21 -kms_cursor_crc@cursor-rapid-movement-64x21 -kms_cursor_crc@cursor-onscreen-128x128 -kms_cursor_crc@cursor-offscreen-128x128 -kms_cursor_crc@cursor-sliding-128x128 -kms_cursor_crc@cursor-random-128x128 -kms_cursor_crc@cursor-rapid-movement-128x128 -kms_cursor_crc@cursor-onscreen-128x42 -kms_cursor_crc@cursor-offscreen-128x42 -kms_cursor_crc@cursor-sliding-128x42 -kms_cursor_crc@cursor-random-128x42 -kms_cursor_crc@cursor-rapid-movement-128x42 -kms_cursor_crc@cursor-onscreen-256x256 -kms_cursor_crc@cursor-offscreen-256x256 -kms_cursor_crc@cursor-sliding-256x256 -kms_cursor_crc@cursor-random-256x256 -kms_cursor_crc@cursor-rapid-movement-256x256 -kms_cursor_crc@cursor-onscreen-256x85 -kms_cursor_crc@cursor-offscreen-256x85 -kms_cursor_crc@cursor-sliding-256x85 -kms_cursor_crc@cursor-random-256x85 -kms_cursor_crc@cursor-rapid-movement-256x85 -kms_cursor_crc@cursor-onscreen-512x512 -kms_cursor_crc@cursor-offscreen-512x512 -kms_cursor_crc@cursor-sliding-512x512 -kms_cursor_crc@cursor-random-512x512 -kms_cursor_crc@cursor-rapid-movement-512x512 -kms_cursor_crc@cursor-onscreen-512x170 -kms_cursor_crc@cursor-offscreen-512x170 -kms_cursor_crc@cursor-sliding-512x170 -kms_cursor_crc@cursor-random-512x170 -kms_cursor_crc@cursor-rapid-movement-512x170 -kms_cursor_crc@cursor-onscreen-max-size -kms_cursor_crc@cursor-offscreen-max-size -kms_cursor_crc@cursor-sliding-max-size -kms_cursor_crc@cursor-random-max-size -kms_cursor_crc@cursor-rapid-movement-max-size -kms_cursor_legacy@single-bo -kms_cursor_legacy@single-move -kms_cursor_legacy@forked-bo -kms_cursor_legacy@forked-move -kms_cursor_legacy@torture-bo -kms_cursor_legacy@torture-move -kms_cursor_legacy@nonblocking-modeset-vs-cursor-atomic -kms_cursor_legacy@long-nonblocking-modeset-vs-cursor-atomic -kms_cursor_legacy@2x-flip-vs-cursor-legacy -kms_cursor_legacy@2x-flip-vs-cursor-atomic -kms_cursor_legacy@2x-long-flip-vs-cursor-legacy -kms_cursor_legacy@2x-long-flip-vs-cursor-atomic -kms_cursor_legacy@2x-nonblocking-modeset-vs-cursor-atomic -kms_cursor_legacy@2x-long-nonblocking-modeset-vs-cursor-atomic -kms_cursor_legacy@2x-cursor-vs-flip-legacy -kms_cursor_legacy@2x-long-cursor-vs-flip-legacy -kms_cursor_legacy@2x-cursor-vs-flip-atomic -kms_cursor_legacy@2x-long-cursor-vs-flip-atomic -kms_cursor_legacy@flip-vs-cursor-crc-legacy -kms_cursor_legacy@flip-vs-cursor-crc-atomic -kms_cursor_legacy@flip-vs-cursor-busy-crc-legacy -kms_cursor_legacy@flip-vs-cursor-busy-crc-atomic -kms_cursor_legacy@basic-flip-before-cursor-legacy -kms_cursor_legacy@basic-busy-flip-before-cursor-legacy -kms_cursor_legacy@basic-flip-after-cursor-legacy -kms_cursor_legacy@basic-flip-before-cursor-varying-size -kms_cursor_legacy@basic-busy-flip-before-cursor-varying-size -kms_cursor_legacy@basic-flip-after-cursor-varying-size -kms_cursor_legacy@short-flip-before-cursor-toggle -kms_cursor_legacy@short-busy-flip-before-cursor-toggle -kms_cursor_legacy@short-flip-after-cursor-toggle -kms_cursor_legacy@basic-flip-before-cursor-atomic -kms_cursor_legacy@basic-busy-flip-before-cursor-atomic -kms_cursor_legacy@basic-flip-after-cursor-atomic -kms_cursor_legacy@short-flip-before-cursor-atomic-transitions -kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions -kms_cursor_legacy@short-flip-after-cursor-atomic-transitions -kms_cursor_legacy@short-flip-before-cursor-atomic-transitions-varying-size -kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions-varying-size -kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size -kms_cursor_legacy@cursor-vs-flip-legacy -kms_cursor_legacy@flip-vs-cursor-legacy -kms_cursor_legacy@cursorA-vs-flipA-legacy -kms_cursor_legacy@cursorA-vs-flipB-legacy -kms_cursor_legacy@cursorB-vs-flipA-legacy -kms_cursor_legacy@cursorB-vs-flipB-legacy -kms_cursor_legacy@cursor-vs-flip-varying-size -kms_cursor_legacy@flip-vs-cursor-varying-size -kms_cursor_legacy@cursorA-vs-flipA-varying-size -kms_cursor_legacy@cursorA-vs-flipB-varying-size -kms_cursor_legacy@cursorB-vs-flipA-varying-size -kms_cursor_legacy@cursorB-vs-flipB-varying-size -kms_cursor_legacy@cursor-vs-flip-toggle -kms_cursor_legacy@flip-vs-cursor-toggle -kms_cursor_legacy@cursorA-vs-flipA-toggle -kms_cursor_legacy@cursorA-vs-flipB-toggle -kms_cursor_legacy@cursorB-vs-flipA-toggle -kms_cursor_legacy@cursorB-vs-flipB-toggle -kms_cursor_legacy@cursor-vs-flip-atomic -kms_cursor_legacy@flip-vs-cursor-atomic -kms_cursor_legacy@cursorA-vs-flipA-atomic -kms_cursor_legacy@cursorA-vs-flipB-atomic -kms_cursor_legacy@cursorB-vs-flipA-atomic -kms_cursor_legacy@cursorB-vs-flipB-atomic -kms_cursor_legacy@cursor-vs-flip-atomic-transitions -kms_cursor_legacy@flip-vs-cursor-atomic-transitions -kms_cursor_legacy@cursorA-vs-flipA-atomic-transitions -kms_cursor_legacy@cursorA-vs-flipB-atomic-transitions -kms_cursor_legacy@cursorB-vs-flipA-atomic-transitions -kms_cursor_legacy@cursorB-vs-flipB-atomic-transitions -kms_cursor_legacy@cursor-vs-flip-atomic-transitions-varying-size -kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size -kms_cursor_legacy@cursorA-vs-flipA-atomic-transitions-varying-size -kms_cursor_legacy@cursorA-vs-flipB-atomic-transitions-varying-size -kms_cursor_legacy@cursorB-vs-flipA-atomic-transitions-varying-size -kms_cursor_legacy@cursorB-vs-flipB-atomic-transitions-varying-size -kms_dither@fb-8bpc-vs-panel-6bpc -kms_dither@fb-8bpc-vs-panel-8bpc -kms_dp_aux_dev -kms_tiled_display@basic-test-pattern -kms_tiled_display@basic-test-pattern-with-chamelium -kms_draw_crc@draw-method-mmap-cpu -kms_draw_crc@draw-method-mmap-gtt -kms_draw_crc@draw-method-mmap-wc -kms_draw_crc@draw-method-pwrite -kms_draw_crc@draw-method-blt -kms_draw_crc@draw-method-render -kms_draw_crc@fill-fb -kms_dsc@dsc-basic -kms_dsc@dsc-with-formats -kms_dsc@dsc-with-bpc -kms_dsc@dsc-with-bpc-formats -kms_dsc@dsc-with-output-formats -kms_fbcon_fbt@fbc -kms_fbcon_fbt@psr -kms_fbcon_fbt@fbc-suspend -kms_fbcon_fbt@psr-suspend -kms_fence_pin_leak -kms_flip@nonblocking-read -kms_flip@wf_vblank-ts-check -kms_flip@2x-wf_vblank-ts-check -kms_flip@blocking-wf_vblank -kms_flip@2x-blocking-wf_vblank -kms_flip@absolute-wf_vblank -kms_flip@2x-absolute-wf_vblank -kms_flip@blocking-absolute-wf_vblank -kms_flip@2x-blocking-absolute-wf_vblank -kms_flip@basic-plain-flip -kms_flip@2x-plain-flip -kms_flip@busy-flip -kms_flip@2x-busy-flip -kms_flip@flip-vs-fences -kms_flip@2x-flip-vs-fences -kms_flip@plain-flip-ts-check -kms_flip@2x-plain-flip-ts-check -kms_flip@plain-flip-fb-recreate -kms_flip@2x-plain-flip-fb-recreate -kms_flip@flip-vs-rmfb -kms_flip@2x-flip-vs-rmfb -kms_flip@basic-flip-vs-dpms -kms_flip@2x-flip-vs-dpms -kms_flip@flip-vs-panning -kms_flip@2x-flip-vs-panning -kms_flip@basic-flip-vs-modeset -kms_flip@2x-flip-vs-modeset -kms_flip@flip-vs-expired-vblank -kms_flip@2x-flip-vs-expired-vblank -kms_flip@flip-vs-absolute-wf_vblank -kms_flip@2x-flip-vs-absolute-wf_vblank -kms_flip@basic-flip-vs-wf_vblank -kms_flip@2x-flip-vs-wf_vblank -kms_flip@flip-vs-blocking-wf-vblank -kms_flip@2x-flip-vs-blocking-wf-vblank -kms_flip@flip-vs-modeset-vs-hang -kms_flip@2x-flip-vs-modeset-vs-hang -kms_flip@flip-vs-panning-vs-hang -kms_flip@2x-flip-vs-panning-vs-hang -kms_flip@flip-vs-dpms-off-vs-modeset -kms_flip@2x-flip-vs-dpms-off-vs-modeset -kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset -kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset -kms_flip@dpms-off-confusion -kms_flip@nonexisting-fb -kms_flip@2x-nonexisting-fb -kms_flip@dpms-vs-vblank-race -kms_flip@2x-dpms-vs-vblank-race -kms_flip@modeset-vs-vblank-race -kms_flip@2x-modeset-vs-vblank-race -kms_flip@bo-too-big -kms_flip@flip-vs-suspend -kms_flip@2x-flip-vs-suspend -kms_flip@wf_vblank-ts-check-interruptible -kms_flip@2x-wf_vblank-ts-check-interruptible -kms_flip@absolute-wf_vblank-interruptible -kms_flip@2x-absolute-wf_vblank-interruptible -kms_flip@blocking-absolute-wf_vblank-interruptible -kms_flip@2x-blocking-absolute-wf_vblank-interruptible -kms_flip@plain-flip-interruptible -kms_flip@2x-plain-flip-interruptible -kms_flip@flip-vs-fences-interruptible -kms_flip@2x-flip-vs-fences-interruptible -kms_flip@plain-flip-ts-check-interruptible -kms_flip@2x-plain-flip-ts-check-interruptible -kms_flip@plain-flip-fb-recreate-interruptible -kms_flip@2x-plain-flip-fb-recreate-interruptible -kms_flip@flip-vs-rmfb-interruptible -kms_flip@2x-flip-vs-rmfb-interruptible -kms_flip@flip-vs-panning-interruptible -kms_flip@2x-flip-vs-panning-interruptible -kms_flip@flip-vs-expired-vblank-interruptible -kms_flip@2x-flip-vs-expired-vblank-interruptible -kms_flip@flip-vs-absolute-wf_vblank-interruptible -kms_flip@2x-flip-vs-absolute-wf_vblank-interruptible -kms_flip@flip-vs-wf_vblank-interruptible -kms_flip@2x-flip-vs-wf_vblank-interruptible -kms_flip@flip-vs-dpms-off-vs-modeset-interruptible -kms_flip@2x-flip-vs-dpms-off-vs-modeset-interruptible -kms_flip@single-buffer-flip-vs-dpms-off-vs-modeset-interruptible -kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset-interruptible -kms_flip@dpms-off-confusion-interruptible -kms_flip@nonexisting-fb-interruptible -kms_flip@2x-nonexisting-fb-interruptible -kms_flip@dpms-vs-vblank-race-interruptible -kms_flip@2x-dpms-vs-vblank-race-interruptible -kms_flip@modeset-vs-vblank-race-interruptible -kms_flip@2x-modeset-vs-vblank-race-interruptible -kms_flip@bo-too-big-interruptible -kms_flip@flip-vs-suspend-interruptible -kms_flip@2x-flip-vs-suspend-interruptible -kms_flip_event_leak@basic -kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling -kms_flip_scaled_crc@flip-32bpp-yftile-to-64bpp-yftile-downscaling -kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling -kms_flip_scaled_crc@flip-32bpp-4tile-to-64bpp-4tile-downscaling -kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling -kms_flip_scaled_crc@flip-64bpp-yftile-to-32bpp-yftile-downscaling -kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling -kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tile-downscaling -kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling -kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling -kms_flip_scaled_crc@flip-64bpp-yftile-to-16bpp-yftile-downscaling -kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling -kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-downscaling -kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling -kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling -kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-downscaling -kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs-downscaling -kms_flip_scaled_crc@flip-32bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling -kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-downscaling -kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-downscaling -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling -kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling -kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling -kms_flip_scaled_crc@flip-32bpp-yftile-to-64bpp-yftile-upscaling -kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling -kms_flip_scaled_crc@flip-32bpp-4tile-to-64bpp-4tile-upscaling -kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling -kms_flip_scaled_crc@flip-64bpp-yftile-to-32bpp-yftile-upscaling -kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling -kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tile-upscaling -kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling -kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling -kms_flip_scaled_crc@flip-64bpp-yftile-to-16bpp-yftile-upscaling -kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling -kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-upscaling -kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling -kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling -kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-upscaling -kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling -kms_flip_scaled_crc@flip-32bpp-4tile-to-32bpp-4tiledg2rcccs-upscaling -kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-upscaling -kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-upscaling -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling -kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tiledg2rcccs-upscaling -kms_force_connector_basic@force-load-detect -kms_force_connector_basic@force-connector-state -kms_force_connector_basic@force-edid -kms_force_connector_basic@prune-stale-modes -kms_frontbuffer_tracking@fbc-1p-rte -kms_frontbuffer_tracking@fbc-2p-rte -kms_frontbuffer_tracking@psr-1p-rte -kms_frontbuffer_tracking@psr-2p-rte -kms_frontbuffer_tracking@fbcpsr-1p-rte -kms_frontbuffer_tracking@fbcpsr-2p-rte -kms_frontbuffer_tracking@drrs-1p-rte -kms_frontbuffer_tracking@drrs-2p-rte -kms_frontbuffer_tracking@fbcdrrs-1p-rte -kms_frontbuffer_tracking@fbcdrrs-2p-rte -kms_frontbuffer_tracking@psrdrrs-1p-rte -kms_frontbuffer_tracking@psrdrrs-2p-rte -kms_frontbuffer_tracking@fbcpsrdrrs-1p-rte -kms_frontbuffer_tracking@fbcpsrdrrs-2p-rte -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-render -kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbc-2p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-blt -kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-render -kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-blt -kms_frontbuffer_tracking@psr-1p-offscren-pri-shrfb-draw-render -kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@drrs-1p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-blt -kms_frontbuffer_tracking@drrs-1p-offscren-pri-indfb-draw-render -kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-blt -kms_frontbuffer_tracking@drrs-1p-offscren-pri-shrfb-draw-render -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@drrs-2p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@drrs-2p-scndscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-1p-offscren-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-indfb-draw-render -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-1p-offscren-pri-shrfb-draw-render -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-offscren-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-indfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-pri-shrfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-draw-render -kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbc-1p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbc-1p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbc-1p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbc-2p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbc-2p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbc-2p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbc-2p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbc-2p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbc-2p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbc-2p-scndscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbc-2p-scndscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbc-2p-scndscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbc-2p-scndscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbc-2p-scndscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbc-2p-scndscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@psr-1p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@psr-1p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@psr-1p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@psr-1p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@psr-1p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@psr-1p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@psr-2p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@psr-2p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@psr-2p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@psr-2p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@psr-2p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@psr-2p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-msflip-blt -kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-plflip-blt -kms_frontbuffer_tracking@psr-2p-scndscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@psr-2p-scndscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@psr-2p-scndscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@drrs-1p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@drrs-1p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@drrs-1p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@drrs-1p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@drrs-1p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@drrs-1p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@drrs-2p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@drrs-2p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@drrs-2p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@drrs-2p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@drrs-2p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@drrs-2p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@drrs-2p-scndscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@drrs-2p-scndscrn-indfb-msflip-blt -kms_frontbuffer_tracking@drrs-2p-scndscrn-indfb-plflip-blt -kms_frontbuffer_tracking@drrs-2p-scndscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@drrs-2p-scndscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@drrs-2p-scndscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-indfb-msflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-indfb-plflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-indfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-indfb-msflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-indfb-plflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-shrfb-pgflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-shrfb-msflip-blt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-shrfb-plflip-blt -kms_frontbuffer_tracking@fbc-1p-indfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbc-1p-shrfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbc-2p-indfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbc-2p-shrfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-1p-indfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-1p-shrfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-2p-indfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-2p-shrfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-1p-indfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-1p-shrfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-2p-indfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-2p-shrfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-indfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-1p-shrfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-indfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-2p-shrfb-fliptrack-mmap-gtt -kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-move -kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-move -kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-onoff -kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@psr-1p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-move -kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-onoff -kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-move -kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-move -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-move -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-onoff -kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@drrs-1p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@drrs-2p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-move -kms_frontbuffer_tracking@drrs-2p-scndscrn-cur-indfb-onoff -kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-move -kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-move -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-move -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-onoff -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-move -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-cur-indfb-onoff -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-move -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-move -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-move -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-move -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-cur-indfb-onoff -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-move -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-onoff -kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbcpsr-2p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@drrs-1p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@drrs-2p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@drrs-2p-scndscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbcdrrs-2p-scndscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@psrdrrs-1p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@psrdrrs-2p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@psrdrrs-2p-scndscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbcpsrdrrs-1p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbcpsrdrrs-2p-primscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbcpsrdrrs-2p-scndscrn-spr-indfb-fullscreen -kms_frontbuffer_tracking@fbc-1p-pri-indfb-multidraw -kms_frontbuffer_tracking@fbc-2p-pri-indfb-multidraw -kms_frontbuffer_tracking@psr-1p-pri-indfb-multidraw -kms_frontbuffer_tracking@psr-2p-pri-indfb-multidraw -kms_frontbuffer_tracking@fbcpsr-1p-pri-indfb-multidraw -kms_frontbuffer_tracking@fbcpsr-2p-pri-indfb-multidraw -kms_frontbuffer_tracking@drrs-1p-pri-indfb-multidraw -kms_frontbuffer_tracking@drrs-2p-pri-indfb-multidraw -kms_frontbuffer_tracking@fbcdrrs-1p-pri-indfb-multidraw -kms_frontbuffer_tracking@fbcdrrs-2p-pri-indfb-multidraw -kms_frontbuffer_tracking@psrdrrs-1p-pri-indfb-multidraw -kms_frontbuffer_tracking@psrdrrs-2p-pri-indfb-multidraw -kms_frontbuffer_tracking@fbcpsrdrrs-1p-pri-indfb-multidraw -kms_frontbuffer_tracking@fbcpsrdrrs-2p-pri-indfb-multidraw -kms_frontbuffer_tracking@fbc-farfromfence-mmap-gtt -kms_frontbuffer_tracking@psr-farfromfence-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-farfromfence-mmap-gtt -kms_frontbuffer_tracking@drrs-farfromfence-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-farfromfence-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-farfromfence-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-farfromfence-mmap-gtt -kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-rgb101010-draw-mmap-cpu -kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-rgb101010-draw-mmap-gtt -kms_frontbuffer_tracking@fbc-rgb565-draw-mmap-wc -kms_frontbuffer_tracking@fbc-rgb101010-draw-mmap-wc -kms_frontbuffer_tracking@fbc-rgb565-draw-pwrite -kms_frontbuffer_tracking@fbc-rgb101010-draw-pwrite -kms_frontbuffer_tracking@fbc-rgb565-draw-blt -kms_frontbuffer_tracking@fbc-rgb101010-draw-blt -kms_frontbuffer_tracking@fbc-rgb565-draw-render -kms_frontbuffer_tracking@fbc-rgb101010-draw-render -kms_frontbuffer_tracking@psr-rgb565-draw-mmap-cpu -kms_frontbuffer_tracking@psr-rgb101010-draw-mmap-cpu -kms_frontbuffer_tracking@psr-rgb565-draw-mmap-gtt -kms_frontbuffer_tracking@psr-rgb101010-draw-mmap-gtt -kms_frontbuffer_tracking@psr-rgb565-draw-mmap-wc -kms_frontbuffer_tracking@psr-rgb101010-draw-mmap-wc -kms_frontbuffer_tracking@psr-rgb565-draw-pwrite -kms_frontbuffer_tracking@psr-rgb101010-draw-pwrite -kms_frontbuffer_tracking@psr-rgb565-draw-blt -kms_frontbuffer_tracking@psr-rgb101010-draw-blt -kms_frontbuffer_tracking@psr-rgb565-draw-render -kms_frontbuffer_tracking@psr-rgb101010-draw-render -kms_frontbuffer_tracking@fbcpsr-rgb565-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsr-rgb565-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsr-rgb565-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsr-rgb565-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-pwrite -kms_frontbuffer_tracking@fbcpsr-rgb565-draw-blt -kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-blt -kms_frontbuffer_tracking@fbcpsr-rgb565-draw-render -kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-render -kms_frontbuffer_tracking@drrs-rgb565-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-rgb101010-draw-mmap-cpu -kms_frontbuffer_tracking@drrs-rgb565-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-rgb101010-draw-mmap-gtt -kms_frontbuffer_tracking@drrs-rgb565-draw-mmap-wc -kms_frontbuffer_tracking@drrs-rgb101010-draw-mmap-wc -kms_frontbuffer_tracking@drrs-rgb565-draw-pwrite -kms_frontbuffer_tracking@drrs-rgb101010-draw-pwrite -kms_frontbuffer_tracking@drrs-rgb565-draw-blt -kms_frontbuffer_tracking@drrs-rgb101010-draw-blt -kms_frontbuffer_tracking@drrs-rgb565-draw-render -kms_frontbuffer_tracking@drrs-rgb101010-draw-render -kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-mmap-cpu -kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-mmap-gtt -kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-mmap-wc -kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-pwrite -kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-blt -kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-blt -kms_frontbuffer_tracking@fbcdrrs-rgb565-draw-render -kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-render -kms_frontbuffer_tracking@psrdrrs-rgb565-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-mmap-cpu -kms_frontbuffer_tracking@psrdrrs-rgb565-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-mmap-gtt -kms_frontbuffer_tracking@psrdrrs-rgb565-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-mmap-wc -kms_frontbuffer_tracking@psrdrrs-rgb565-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-pwrite -kms_frontbuffer_tracking@psrdrrs-rgb565-draw-blt -kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-blt -kms_frontbuffer_tracking@psrdrrs-rgb565-draw-render -kms_frontbuffer_tracking@psrdrrs-rgb101010-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-mmap-cpu -kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-mmap-gtt -kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-mmap-wc -kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-pwrite -kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-blt -kms_frontbuffer_tracking@fbcpsrdrrs-rgb565-draw-render -kms_frontbuffer_tracking@fbcpsrdrrs-rgb101010-draw-render -kms_frontbuffer_tracking@fbc-indfb-scaledprimary -kms_frontbuffer_tracking@fbc-shrfb-scaledprimary -kms_frontbuffer_tracking@psr-indfb-scaledprimary -kms_frontbuffer_tracking@psr-shrfb-scaledprimary -kms_frontbuffer_tracking@fbcpsr-indfb-scaledprimary -kms_frontbuffer_tracking@fbcpsr-shrfb-scaledprimary -kms_frontbuffer_tracking@drrs-indfb-scaledprimary -kms_frontbuffer_tracking@drrs-shrfb-scaledprimary -kms_frontbuffer_tracking@fbcdrrs-indfb-scaledprimary -kms_frontbuffer_tracking@fbcdrrs-shrfb-scaledprimary -kms_frontbuffer_tracking@psrdrrs-indfb-scaledprimary -kms_frontbuffer_tracking@psrdrrs-shrfb-scaledprimary -kms_frontbuffer_tracking@fbcpsrdrrs-indfb-scaledprimary -kms_frontbuffer_tracking@fbcpsrdrrs-shrfb-scaledprimary -kms_frontbuffer_tracking@fbc-modesetfrombusy -kms_frontbuffer_tracking@fbc-stridechange -kms_frontbuffer_tracking@fbc-tiling-linear -kms_frontbuffer_tracking@fbc-tiling-y -kms_frontbuffer_tracking@fbc-tiling-4 -kms_frontbuffer_tracking@fbc-suspend -kms_frontbuffer_tracking@psr-modesetfrombusy -kms_frontbuffer_tracking@psr-slowdraw -kms_frontbuffer_tracking@psr-suspend -kms_frontbuffer_tracking@fbcpsr-modesetfrombusy -kms_frontbuffer_tracking@fbcpsr-stridechange -kms_frontbuffer_tracking@fbcpsr-tiling-linear -kms_frontbuffer_tracking@fbcpsr-tiling-y -kms_frontbuffer_tracking@fbcpsr-tiling-4 -kms_frontbuffer_tracking@fbcpsr-slowdraw -kms_frontbuffer_tracking@fbcpsr-suspend -kms_frontbuffer_tracking@drrs-modesetfrombusy -kms_frontbuffer_tracking@drrs-slowdraw -kms_frontbuffer_tracking@drrs-suspend -kms_frontbuffer_tracking@fbcdrrs-modesetfrombusy -kms_frontbuffer_tracking@fbcdrrs-stridechange -kms_frontbuffer_tracking@fbcdrrs-tiling-linear -kms_frontbuffer_tracking@fbcdrrs-tiling-y -kms_frontbuffer_tracking@fbcdrrs-tiling-4 -kms_frontbuffer_tracking@fbcdrrs-slowdraw -kms_frontbuffer_tracking@fbcdrrs-suspend -kms_frontbuffer_tracking@psrdrrs-modesetfrombusy -kms_frontbuffer_tracking@psrdrrs-slowdraw -kms_frontbuffer_tracking@psrdrrs-suspend -kms_frontbuffer_tracking@fbcpsrdrrs-modesetfrombusy -kms_frontbuffer_tracking@fbcpsrdrrs-stridechange -kms_frontbuffer_tracking@fbcpsrdrrs-tiling-linear -kms_frontbuffer_tracking@fbcpsrdrrs-tiling-y -kms_frontbuffer_tracking@fbcpsrdrrs-tiling-4 -kms_frontbuffer_tracking@fbcpsrdrrs-slowdraw -kms_frontbuffer_tracking@fbcpsrdrrs-suspend -kms_frontbuffer_tracking@basic -kms_getfb@getfb-handle-zero -kms_getfb@getfb-handle-valid -kms_getfb@getfb-handle-closed -kms_getfb@getfb-handle-not-fb -kms_getfb@getfb-addfb-different-handles -kms_getfb@getfb-repeated-different-handles -kms_getfb@getfb-reject-ccs -kms_getfb@getfb2-handle-zero -kms_getfb@getfb2-handle-closed -kms_getfb@getfb2-handle-not-fb -kms_getfb@getfb2-accept-ccs -kms_getfb@getfb2-into-addfb2 -kms_getfb@getfb-handle-protection -kms_getfb@getfb2-handle-protection -kms_hdmi_inject@inject-4k -kms_hdmi_inject@inject-audio -kms_hdr@bpc-switch -kms_hdr@bpc-switch-dpms -kms_hdr@bpc-switch-suspend -kms_hdr@static-toggle -kms_hdr@static-toggle-dpms -kms_hdr@static-toggle-suspend -kms_hdr@static-swap -kms_hdr@invalid-metadata-sizes -kms_hdr@invalid-hdr -kms_invalid_mode@clock-too-high -kms_invalid_mode@zero-clock -kms_invalid_mode@int-max-clock -kms_invalid_mode@uint-max-clock -kms_invalid_mode@zero-hdisplay -kms_invalid_mode@zero-vdisplay -kms_invalid_mode@bad-hsync-start -kms_invalid_mode@bad-vsync-start -kms_invalid_mode@bad-hsync-end -kms_invalid_mode@bad-vsync-end -kms_invalid_mode@bad-htotal -kms_invalid_mode@bad-vtotal -kms_legacy_colorkey@basic -kms_legacy_colorkey@invalid-plane -kms_multipipe_modeset@basic-max-pipe-crc-check -kms_panel_fitting@legacy -kms_panel_fitting@atomic-fastset -kms_pipe_b_c_ivb@pipe-B-dpms-off-modeset-pipe-C -kms_pipe_b_c_ivb@pipe-B-double-modeset-then-modeset-pipe-C -kms_pipe_b_c_ivb@disable-pipe-B-enable-pipe-C -kms_pipe_b_c_ivb@from-pipe-C-to-B-with-3-lanes -kms_pipe_b_c_ivb@enable-pipe-C-while-B-has-3-lanes -kms_pipe_crc_basic@bad-source -kms_pipe_crc_basic@read-crc -kms_pipe_crc_basic@read-crc-frame-sequence -kms_pipe_crc_basic@nonblocking-crc -kms_pipe_crc_basic@nonblocking-crc-frame-sequence -kms_pipe_crc_basic@suspend-read-crc -kms_pipe_crc_basic@hang-read-crc -kms_pipe_crc_basic@disable-crc-after-crtc -kms_pipe_crc_basic@compare-crc-sanitycheck-xr24 -kms_pipe_crc_basic@compare-crc-sanitycheck-nv12 -kms_plane@pixel-format -kms_plane@pixel-format-source-clamping -kms_plane@plane-position-covered -kms_plane@plane-position-hole -kms_plane@plane-position-hole-dpms -kms_plane@plane-panning-top-left -kms_plane@plane-panning-bottom-right -kms_plane@plane-panning-bottom-right-suspend -kms_plane@planar-pixel-format-settings -kms_plane_alpha_blend@alpha-basic -kms_plane_alpha_blend@alpha-7efc -kms_plane_alpha_blend@coverage-7efc -kms_plane_alpha_blend@coverage-vs-premult-vs-constant -kms_plane_alpha_blend@alpha-transparent-fb -kms_plane_alpha_blend@alpha-opaque-fb -kms_plane_alpha_blend@constant-alpha-min -kms_plane_alpha_blend@constant-alpha-mid -kms_plane_alpha_blend@constant-alpha-max -kms_plane_cursor@primary -kms_plane_cursor@overlay -kms_plane_cursor@viewport -kms_plane_lowres@tiling-none -kms_plane_lowres@tiling-x -kms_plane_lowres@tiling-y -kms_plane_lowres@tiling-yf -kms_plane_lowres@tiling-4 -kms_plane_multiple@tiling-none -kms_plane_multiple@tiling-x -kms_plane_multiple@tiling-y -kms_plane_multiple@tiling-yf -kms_plane_multiple@tiling-4 -kms_plane_scaling@plane-upscale-20x20-with-pixel-format -kms_plane_scaling@plane-upscale-factor-0-25-with-pixel-format -kms_plane_scaling@plane-downscale-factor-0-25-with-pixel-format -kms_plane_scaling@plane-downscale-factor-0-5-with-pixel-format -kms_plane_scaling@plane-downscale-factor-0-75-with-pixel-format -kms_plane_scaling@plane-scaler-unity-scaling-with-pixel-format -kms_plane_scaling@plane-upscale-20x20-with-rotation -kms_plane_scaling@plane-upscale-factor-0-25-with-rotation -kms_plane_scaling@plane-downscale-factor-0-25-with-rotation -kms_plane_scaling@plane-downscale-factor-0-5-with-rotation -kms_plane_scaling@plane-downscale-factor-0-75-with-rotation -kms_plane_scaling@plane-scaler-unity-scaling-with-rotation -kms_plane_scaling@plane-upscale-20x20-with-modifiers -kms_plane_scaling@plane-upscale-factor-0-25-with-modifiers -kms_plane_scaling@plane-downscale-factor-0-25-with-modifiers -kms_plane_scaling@plane-downscale-factor-0-5-with-modifiers -kms_plane_scaling@plane-downscale-factor-0-75-with-modifiers -kms_plane_scaling@plane-scaler-unity-scaling-with-modifiers -kms_plane_scaling@plane-scaler-with-clipping-clamping-pixel-formats -kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation -kms_plane_scaling@plane-scaler-with-clipping-clamping-modifiers -kms_plane_scaling@planes-upscale-20x20 -kms_plane_scaling@planes-upscale-factor-0-25 -kms_plane_scaling@planes-scaler-unity-scaling -kms_plane_scaling@planes-downscale-factor-0-25 -kms_plane_scaling@planes-downscale-factor-0-5 -kms_plane_scaling@planes-downscale-factor-0-75 -kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-25 -kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-5 -kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-75 -kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-25 -kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5 -kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-75 -kms_plane_scaling@planes-unity-scaling-downscale-factor-0-25 -kms_plane_scaling@planes-unity-scaling-downscale-factor-0-5 -kms_plane_scaling@planes-unity-scaling-downscale-factor-0-75 -kms_plane_scaling@planes-downscale-factor-0-25-upscale-20x20 -kms_plane_scaling@planes-downscale-factor-0-25-upscale-factor-0-25 -kms_plane_scaling@planes-downscale-factor-0-25-unity-scaling -kms_plane_scaling@planes-downscale-factor-0-5-upscale-20x20 -kms_plane_scaling@planes-downscale-factor-0-5-upscale-factor-0-25 -kms_plane_scaling@planes-downscale-factor-0-5-unity-scaling -kms_plane_scaling@planes-downscale-factor-0-75-upscale-20x20 -kms_plane_scaling@planes-downscale-factor-0-75-upscale-factor-0-25 -kms_plane_scaling@planes-downscale-factor-0-75-unity-scaling -kms_plane_scaling@intel-max-src-size -kms_plane_scaling@invalid-num-scalers -kms_plane_scaling@invalid-parameters -kms_plane_scaling@2x-scaler-multi-pipe -kms_prime@basic-crc-hybrid -kms_prime@basic-modeset-hybrid -kms_prime@D3hot -kms_prime@basic-crc-vgem -kms_prop_blob@basic -kms_prop_blob@blob-prop-core -kms_prop_blob@blob-prop-validate -kms_prop_blob@blob-prop-lifetime -kms_prop_blob@blob-multiple -kms_prop_blob@invalid-get-prop-any -kms_prop_blob@invalid-get-prop -kms_prop_blob@invalid-set-prop-any -kms_prop_blob@invalid-set-prop -kms_properties@plane-properties-legacy -kms_properties@plane-properties-atomic -kms_properties@crtc-properties-legacy -kms_properties@crtc-properties-atomic -kms_properties@connector-properties-legacy -kms_properties@connector-properties-atomic -kms_properties@invalid-properties-legacy -kms_properties@invalid-properties-atomic -kms_properties@get_properties-sanity-atomic -kms_properties@get_properties-sanity-non-atomic -kms_psr@pr-basic -kms_psr@pr-no-drrs -kms_psr@pr-primary-page-flip -kms_psr@pr-primary-mmap-gtt -kms_psr@pr-primary-mmap-cpu -kms_psr@pr-primary-blt -kms_psr@pr-primary-render -kms_psr@pr-sprite-mmap-gtt -kms_psr@pr-cursor-mmap-gtt -kms_psr@pr-sprite-mmap-cpu -kms_psr@pr-cursor-mmap-cpu -kms_psr@pr-sprite-blt -kms_psr@pr-cursor-blt -kms_psr@pr-sprite-render -kms_psr@pr-cursor-render -kms_psr@pr-sprite-plane-move -kms_psr@pr-cursor-plane-move -kms_psr@pr-sprite-plane-onoff -kms_psr@pr-cursor-plane-onoff -kms_psr@pr-dpms -kms_psr@pr-suspend -kms_psr@psr-basic -kms_psr@psr-no-drrs -kms_psr@psr-primary-page-flip -kms_psr@psr-primary-mmap-gtt -kms_psr@psr-primary-mmap-cpu -kms_psr@psr-primary-blt -kms_psr@psr-primary-render -kms_psr@psr-sprite-mmap-gtt -kms_psr@psr-cursor-mmap-gtt -kms_psr@psr-sprite-mmap-cpu -kms_psr@psr-cursor-mmap-cpu -kms_psr@psr-sprite-blt -kms_psr@psr-cursor-blt -kms_psr@psr-sprite-render -kms_psr@psr-cursor-render -kms_psr@psr-sprite-plane-move -kms_psr@psr-cursor-plane-move -kms_psr@psr-sprite-plane-onoff -kms_psr@psr-cursor-plane-onoff -kms_psr@psr-dpms -kms_psr@psr-suspend -kms_psr@psr2-basic -kms_psr@psr2-no-drrs -kms_psr@psr2-primary-page-flip -kms_psr@psr2-primary-mmap-gtt -kms_psr@psr2-primary-mmap-cpu -kms_psr@psr2-primary-blt -kms_psr@psr2-primary-render -kms_psr@psr2-sprite-mmap-gtt -kms_psr@psr2-cursor-mmap-gtt -kms_psr@psr2-sprite-mmap-cpu -kms_psr@psr2-cursor-mmap-cpu -kms_psr@psr2-sprite-blt -kms_psr@psr2-cursor-blt -kms_psr@psr2-sprite-render -kms_psr@psr2-cursor-render -kms_psr@psr2-sprite-plane-move -kms_psr@psr2-cursor-plane-move -kms_psr@psr2-sprite-plane-onoff -kms_psr@psr2-cursor-plane-onoff -kms_psr@psr2-dpms -kms_psr@psr2-suspend -kms_psr2_sf@primary-plane-update-sf-dmg-area -kms_psr2_sf@primary-plane-update-sf-dmg-area-big-fb -kms_psr2_sf@overlay-plane-update-sf-dmg-area -kms_psr2_sf@cursor-plane-update-sf -kms_psr2_sf@cursor-plane-move-continuous-sf -kms_psr2_sf@cursor-plane-move-continuous-exceed-sf -kms_psr2_sf@cursor-plane-move-continuous-exceed-fully-sf -kms_psr2_sf@plane-move-sf-dmg-area -kms_psr2_sf@overlay-plane-move-continuous-sf -kms_psr2_sf@overlay-plane-move-continuous-exceed-sf -kms_psr2_sf@overlay-plane-move-continuous-exceed-fully-sf -kms_psr2_sf@overlay-primary-update-sf-dmg-area -kms_psr2_sf@overlay-plane-update-continuous-sf -kms_psr2_su@page_flip-XRGB8888 -kms_psr2_su@page_flip-NV12 -kms_psr2_su@page_flip-P010 -kms_psr2_su@frontbuffer-XRGB8888 -kms_pwrite_crc -kms_rmfb@rmfb-ioctl -kms_rmfb@close-fd -kms_rotation_crc@primary-rotation-90 -kms_rotation_crc@primary-rotation-180 -kms_rotation_crc@primary-rotation-270 -kms_rotation_crc@sprite-rotation-90 -kms_rotation_crc@sprite-rotation-180 -kms_rotation_crc@sprite-rotation-270 -kms_rotation_crc@cursor-rotation-180 -kms_rotation_crc@sprite-rotation-90-pos-100-0 -kms_rotation_crc@bad-pixel-format -kms_rotation_crc@bad-tiling -kms_rotation_crc@primary-x-tiled-reflect-x-0 -kms_rotation_crc@primary-x-tiled-reflect-x-180 -kms_rotation_crc@primary-y-tiled-reflect-x-0 -kms_rotation_crc@primary-y-tiled-reflect-x-90 -kms_rotation_crc@primary-y-tiled-reflect-x-180 -kms_rotation_crc@primary-y-tiled-reflect-x-270 -kms_rotation_crc@primary-yf-tiled-reflect-x-0 -kms_rotation_crc@primary-yf-tiled-reflect-x-90 -kms_rotation_crc@primary-yf-tiled-reflect-x-180 -kms_rotation_crc@primary-yf-tiled-reflect-x-270 -kms_rotation_crc@primary-4-tiled-reflect-x-0 -kms_rotation_crc@primary-4-tiled-reflect-x-180 -kms_rotation_crc@multiplane-rotation -kms_rotation_crc@multiplane-rotation-cropping-top -kms_rotation_crc@multiplane-rotation-cropping-bottom -kms_rotation_crc@exhaust-fences -kms_scaling_modes@scaling-mode-full -kms_scaling_modes@scaling-mode-center -kms_scaling_modes@scaling-mode-full-aspect -kms_scaling_modes@scaling-mode-none -kms_selftest@drm_cmdline_parser -kms_selftest@drm_damage_helper -kms_selftest@drm_dp_mst_helper -kms_selftest@drm_format_helper -kms_selftest@drm_format -kms_selftest@drm_framebuffer -kms_selftest@drm_plane_helper -kms_setmode@basic -kms_setmode@basic-clone-single-crtc -kms_setmode@invalid-clone-single-crtc -kms_setmode@invalid-clone-exclusive-crtc -kms_setmode@clone-exclusive-crtc -kms_setmode@invalid-clone-single-crtc-stealing -kms_sysfs_edid_timing -kms_tv_load_detect@load-detect -kms_universal_plane@universal-plane-functional -kms_universal_plane@universal-plane-sanity -kms_universal_plane@disable-primary-vs-flip -kms_universal_plane@cursor-fb-leak -kms_universal_plane@universal-plane-pageflip-windowed -kms_vblank@invalid -kms_vblank@crtc-id -kms_vblank@accuracy-idle -kms_vblank@query-idle -kms_vblank@query-idle-hang -kms_vblank@query-forked -kms_vblank@query-forked-hang -kms_vblank@query-busy -kms_vblank@query-busy-hang -kms_vblank@query-forked-busy -kms_vblank@query-forked-busy-hang -kms_vblank@wait-idle -kms_vblank@wait-idle-hang -kms_vblank@wait-forked -kms_vblank@wait-forked-hang -kms_vblank@wait-busy -kms_vblank@wait-busy-hang -kms_vblank@wait-forked-busy -kms_vblank@wait-forked-busy-hang -kms_vblank@ts-continuation-idle -kms_vblank@ts-continuation-idle-hang -kms_vblank@ts-continuation-dpms-rpm -kms_vblank@ts-continuation-dpms-suspend -kms_vblank@ts-continuation-suspend -kms_vblank@ts-continuation-modeset -kms_vblank@ts-continuation-modeset-hang -kms_vblank@ts-continuation-modeset-rpm -kms_vrr@flip-basic -kms_vrr@flip-dpms -kms_vrr@flip-suspend -kms_vrr@flipline -kms_vrr@negative-basic -kms_writeback@writeback-pixel-formats -kms_writeback@writeback-invalid-parameters -kms_writeback@writeback-fb-id -kms_writeback@writeback-check-output -prime_mmap_kms@buffer-sharing -msm_shrink@copy-gpu-sanitycheck-8 -msm_shrink@copy-gpu-sanitycheck-32 -msm_shrink@copy-gpu-8 -msm_shrink@copy-gpu-32 -msm_shrink@copy-gpu-madvise-8 -msm_shrink@copy-gpu-madvise-32 -msm_shrink@copy-gpu-oom-8 -msm_shrink@copy-gpu-oom-32 -msm_shrink@copy-mmap-sanitycheck-8 -msm_shrink@copy-mmap-sanitycheck-32 -msm_shrink@copy-mmap-8 -msm_shrink@copy-mmap-32 -msm_shrink@copy-mmap-madvise-8 -msm_shrink@copy-mmap-madvise-32 -msm_shrink@copy-mmap-oom-8 -msm_shrink@copy-mmap-oom-32 -msm_shrink@copy-mmap-dmabuf-sanitycheck-8 -msm_shrink@copy-mmap-dmabuf-sanitycheck-32 -msm_shrink@copy-mmap-dmabuf-8 -msm_shrink@copy-mmap-dmabuf-32 -msm_shrink@copy-mmap-dmabuf-madvise-8 -msm_shrink@copy-mmap-dmabuf-madvise-32 -msm_shrink@copy-mmap-dmabuf-oom-8 -msm_shrink@copy-mmap-dmabuf-oom-32 -msm_mapping@ring -msm_mapping@sqefw -msm_mapping@shadow -msm_submitoverhead@submitbench-10-bos -msm_submitoverhead@submitbench-10-bos-no-implicit-sync -msm_submitoverhead@submitbench-100-bos -msm_submitoverhead@submitbench-100-bos-no-implicit-sync -msm_submitoverhead@submitbench-250-bos -msm_submitoverhead@submitbench-250-bos-no-implicit-sync -msm_submitoverhead@submitbench-500-bos -msm_submitoverhead@submitbench-500-bos-no-implicit-sync -msm_submitoverhead@submitbench-1000-bos -msm_submitoverhead@submitbench-1000-bos-no-implicit-sync -msm_recovery@hangcheck -msm_recovery@gpu-fault -msm_recovery@gpu-fault-parallel -msm_recovery@iova-fault -msm_submit@empty-submit -msm_submit@invalid-queue-submit -msm_submit@invalid-flags-submit -msm_submit@invalid-in-fence-submit -msm_submit@invalid-duplicate-bo-submit -msm_submit@invalid-cmd-idx-submit -msm_submit@invalid-cmd-type-submit -msm_submit@valid-submit diff --git a/drivers/gpu/drm/ci/x86_64.config b/drivers/gpu/drm/ci/x86_64.config index 1cbd49a5b23a..8eaba388b141 100644 --- a/drivers/gpu/drm/ci/x86_64.config +++ b/drivers/gpu/drm/ci/x86_64.config @@ -24,6 +24,7 @@ CONFIG_DRM=y CONFIG_DRM_PANEL_SIMPLE=y CONFIG_PWM_CROS_EC=y CONFIG_BACKLIGHT_PWM=y +CONFIG_DRM_VKMS=m # Strip out some stuff we don't need for graphics testing, to reduce # the build. diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt index ea87dc46bc2b..e8c2f4044a92 100644 --- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt +++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-fails.txt @@ -1,27 +1,40 @@ +amdgpu/amd_abm@abm_enabled,Fail +amdgpu/amd_abm@abm_gradual,Fail +amdgpu/amd_abm@backlight_monotonic_abm,Fail +amdgpu/amd_abm@backlight_monotonic_basic,Fail +amdgpu/amd_assr@assr-links,Fail +amdgpu/amd_assr@assr-links-dpms,Fail +amdgpu/amd_mall@static-screen,Crash +amdgpu/amd_mode_switch@mode-switch-first-last-pipe-2,Crash +amdgpu/amd_plane@mpo-pan-nv12,Fail +amdgpu/amd_plane@mpo-pan-p010,Fail +amdgpu/amd_plane@mpo-pan-rgb,Crash +amdgpu/amd_plane@mpo-scale-nv12,Fail +amdgpu/amd_plane@mpo-scale-p010,Fail +amdgpu/amd_plane@mpo-scale-rgb,Crash +amdgpu/amd_plane@mpo-swizzle-toggle,Fail +amdgpu/amd_uvd_dec@amdgpu_uvd_decode,Fail +dumb_buffer@invalid-bpp,Fail kms_addfb_basic@bad-pitch-65536,Fail kms_addfb_basic@bo-too-small,Fail kms_addfb_basic@too-high,Fail -kms_async_flips@async-flip-with-page-flip-events,Fail -kms_async_flips@crc,Fail -kms_async_flips@invalid-async-flip,Fail kms_atomic_transition@plane-all-modeset-transition-internal-panels,Fail kms_atomic_transition@plane-all-transition,Fail kms_atomic_transition@plane-all-transition-nonblocking,Fail kms_atomic_transition@plane-toggle-modeset-transition,Fail kms_atomic_transition@plane-use-after-nonblocking-unbind,Fail -kms_bw@linear-tiling-1-displays-2560x1440p,Fail -kms_bw@linear-tiling-1-displays-3840x2160p,Fail -kms_bw@linear-tiling-2-displays-3840x2160p,Fail -kms_bw@linear-tiling-3-displays-1920x1080p,Fail -kms_color@degamma,Fail +kms_cursor_crc@cursor-onscreen-64x21,Fail +kms_cursor_crc@cursor-onscreen-64x64,Fail +kms_cursor_crc@cursor-random-64x21,Fail +kms_cursor_crc@cursor-random-64x64,Fail kms_cursor_crc@cursor-size-change,Fail -kms_cursor_crc@pipe-A-cursor-size-change,Fail -kms_cursor_crc@pipe-B-cursor-size-change,Fail +kms_cursor_crc@cursor-sliding-64x21,Fail +kms_cursor_crc@cursor-sliding-64x64,Fail kms_flip@flip-vs-modeset-vs-hang,Fail kms_flip@flip-vs-panning-vs-hang,Fail -kms_hdr@bpc-switch,Fail -kms_hdr@bpc-switch-dpms,Fail +kms_lease@lease-uevent,Fail kms_plane@pixel-format,Fail -kms_plane_multiple@atomic-pipe-A-tiling-none,Fail -kms_rmfb@close-fd,Fail +kms_plane_cursor@primary,Fail kms_rotation_crc@primary-rotation-180,Fail +perf@i915-ref-count,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt index 6faf75e667d3..ea512ff8c352 100644 --- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-flakes.txt @@ -1 +1,8 @@ +# Board Name: hp-11A-G6-EE-grunt +# Bug Report: https://lore.kernel.org/amd-gfx/3542730f-b8d7-404d-a947-b7a5e95d661c@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 kms_async_flips@async-flip-with-page-flip-events +kms_async_flips@crc +kms_plane@pixel-format-source-clamping diff --git a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt index e2c538a0f954..3a2ce45d3cb9 100644 --- a/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt +++ b/drivers/gpu/drm/ci/xfails/amdgpu-stoney-skips.txt @@ -1,2 +1,33 @@ # Suspend to RAM seems to be broken on this machine -.*suspend.*
\ No newline at end of file +.*suspend.* + +# Skip driver specific tests +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* +xe_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +amdgpu/amd_module_load@reload +core_hotunplug.* + +# GPU reset seen and it hangs the machine +amdgpu/amd_deadlock@amdgpu-deadlock-sdma +amdgpu/amd_deadlock@amdgpu-gfx-illegal-reg-access +amdgpu/amd_dispatch@amdgpu-reset-test-gfx-with-IP-GFX-and-COMPUTE + +# Hangs the machine and timeout occurs +amdgpu/amd_pci_unplug@amdgpu_hotunplug_simple +amdgpu/amd_pci_unplug@amdgpu_hotunplug_with_cs +amdgpu/amd_pci_unplug@amdgpu_hotunplug_with_exported_bo +amdgpu/amd_pci_unplug@amdgpu_hotunplug_with_exported_fence +amdgpu/amd_vrr_range@freesync-parsing +device_reset.* diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt b/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt index 59438e4df86e..6641520ac587 100644 --- a/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-amly-fails.txt @@ -1,3 +1,16 @@ +core_setmaster@master-drop-set-user,Fail +core_setmaster_vs_auth,Fail +i915_module_load@load,Fail +i915_module_load@reload,Fail +i915_module_load@reload-no-display,Fail +i915_module_load@resize-bar,Fail +i915_pm_rpm@gem-execbuf-stress,Timeout +i915_pm_rpm@module-reload,Fail +kms_async_flips@invalid-async-flip,Timeout +kms_atomic_transition@modeset-transition-fencing,Timeout +kms_ccs@crc-primary-rotation-180-yf-tiled-ccs,Timeout +kms_fb_coherency@memset-crc,Crash +kms_flip@flip-vs-dpms-off-vs-modeset,Timeout kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail @@ -20,7 +33,25 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail +kms_lease@lease-uevent,Fail kms_plane_alpha_blend@alpha-basic,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail +kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout +kms_pm_rpm@modeset-lpsp-stress,Timeout +kms_pm_rpm@modeset-stress-extra-wait,Timeout +kms_pm_rpm@universal-planes,Timeout +kms_pm_rpm@universal-planes-dpms,Timeout +perf@i915-ref-count,Fail +perf_pmu@module-unload,Fail +perf_pmu@rc6,Crash +sysfs_heartbeat_interval@long,Timeout +sysfs_heartbeat_interval@off,Timeout +sysfs_preempt_timeout@off,Timeout +sysfs_timeslice_duration@off,Timeout +xe_module_load@force-load,Fail +xe_module_load@load,Fail +xe_module_load@many-reload,Fail +xe_module_load@reload,Fail +xe_module_load@reload-no-display,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt new file mode 100644 index 000000000000..0a76547a103d --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/i915-amly-flakes.txt @@ -0,0 +1,9 @@ +# Board Name: asus-C433TA-AJ0005-rammus +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +i915_hangman@engine-engine-error +i915_hangman@gt-engine-hang +kms_async_flips@crc +kms_universal_plane@cursor-fb-leak diff --git a/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt b/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt index fe55540a3f9a..5663ed0420a7 100644 --- a/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-amly-skips.txt @@ -1,4 +1,24 @@ # Suspend to RAM seems to be broken on this machine .*suspend.* # This is generating kernel oops with divide error -kms_plane_scaling@invalid-parameters
\ No newline at end of file +kms_plane_scaling@invalid-parameters + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# GEM tests takes ~1000 hours, so skip it +gem_.* + +# Hangs the machine and timeout occurs +i915_pm_rc6_residency.* +i915_suspend.* +kms_scaling_modes.* + +# Kernel panic +drm_fdinfo.* diff --git a/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt index 2e3b7c5dac3c..e612281149aa 100644 --- a/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-apl-fails.txt @@ -1,13 +1,7 @@ -kms_3d,Timeout -kms_bw@linear-tiling-2-displays-1920x1080p,Fail -kms_bw@linear-tiling-2-displays-2560x1440p,Fail -kms_bw@linear-tiling-2-displays-3840x2160p,Fail -kms_bw@linear-tiling-3-displays-1920x1080p,Fail -kms_bw@linear-tiling-3-displays-2560x1440p,Fail -kms_bw@linear-tiling-3-displays-3840x2160p,Fail -kms_bw@linear-tiling-4-displays-1920x1080p,Fail -kms_bw@linear-tiling-4-displays-2560x1440p,Fail -kms_bw@linear-tiling-4-displays-3840x2160p,Fail +i915_module_load@load,Fail +i915_module_load@reload,Fail +i915_module_load@reload-no-display,Fail +i915_module_load@resize-bar,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail @@ -30,18 +24,30 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-upscaling,Fail +kms_lease@lease-uevent,Fail kms_plane_alpha_blend@alpha-basic,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail -kms_plane_alpha_blend@pipe-A-alpha-opaque-fb,Fail -kms_plane_alpha_blend@pipe-A-alpha-transparent-fb,Fail -kms_plane_alpha_blend@pipe-A-constant-alpha-max,Fail -kms_plane_alpha_blend@pipe-B-alpha-opaque-fb,Fail -kms_plane_alpha_blend@pipe-B-alpha-transparent-fb,Fail -kms_plane_alpha_blend@pipe-B-constant-alpha-max,Fail -kms_plane_alpha_blend@pipe-C-alpha-opaque-fb,Fail -kms_plane_alpha_blend@pipe-C-alpha-transparent-fb,Fail -kms_plane_alpha_blend@pipe-C-constant-alpha-max,Fail +kms_pm_backlight@basic-brightness,Fail +kms_pm_backlight@fade,Fail +kms_pm_backlight@fade-with-dpms,Fail +kms_pm_rpm@legacy-planes,Timeout +kms_pm_rpm@legacy-planes-dpms,Timeout +kms_pm_rpm@modeset-stress-extra-wait,Timeout +kms_pm_rpm@universal-planes,Timeout +kms_pm_rpm@universal-planes-dpms,Timeout kms_sysfs_edid_timing,Fail +perf@i915-ref-count,Fail +perf@non-zero-reason,Timeout +perf_pmu@module-unload,Fail +perf_pmu@rc6,Crash +sysfs_heartbeat_interval@long,Timeout +sysfs_heartbeat_interval@off,Timeout +sysfs_preempt_timeout@off,Timeout +sysfs_timeslice_duration@off,Timeout +xe_module_load@force-load,Fail +xe_module_load@load,Fail +xe_module_load@many-reload,Fail +xe_module_load@reload,Fail +xe_module_load@reload-no-display,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt new file mode 100644 index 000000000000..cb010c153a6a --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/i915-apl-flakes.txt @@ -0,0 +1,6 @@ +# Board Name: asus-C523NA-A20057-coral +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +kms_fb_coherency@memset-crc diff --git a/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt index 3430b215c06e..ab588e7a447c 100644 --- a/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-apl-skips.txt @@ -3,4 +3,28 @@ # This is generating kernel oops with divide error kms_plane_scaling@invalid-parameters # This is cascading issues -kms_3d
\ No newline at end of file +kms_3d + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# GEM tests takes ~1000 hours, so skip it +gem_.* + +# Hangs the machine and timeout occurs +i915_pm_rc6_residency.* +i915_suspend.* +i915_pm_rpm.* +device_reset.* +api_intel_allocator.* +kms_frontbuffer_tracking.* +kms_ccs.* + +# Kernel panic +drm_fdinfo.* diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt b/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt index 240ef8467c26..26cd62bbf30a 100644 --- a/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-cml-fails.txt @@ -1,3 +1,19 @@ +core_setmaster@master-drop-set-user,Fail +core_setmaster_vs_auth,Fail +i915_module_load@load,Fail +i915_module_load@reload,Fail +i915_module_load@reload-no-display,Fail +i915_module_load@resize-bar,Fail +i915_pipe_stress@stress-xrgb8888-untiled,Fail +i915_pipe_stress@stress-xrgb8888-ytiled,Fail +i915_pm_rpm@gem-execbuf-stress,Timeout +i915_pm_rpm@module-reload,Fail +i915_pm_rpm@system-suspend-execbuf,Timeout +kms_async_flips@invalid-async-flip,Timeout +kms_atomic_transition@modeset-transition-fencing,Timeout +kms_ccs@crc-primary-rotation-180-yf-tiled-ccs,Timeout +kms_fb_coherency@memset-crc,Crash +kms_flip@flip-vs-dpms-off-vs-modeset,Timeout kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail @@ -20,11 +36,33 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail +kms_lease@lease-uevent,Fail kms_plane_alpha_blend@alpha-basic,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail kms_plane_alpha_blend@constant-alpha-min,Fail +kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout +kms_pm_rpm@modeset-stress-extra-wait,Timeout +kms_pm_rpm@universal-planes,Timeout +kms_pm_rpm@universal-planes-dpms,Timeout +kms_psr2_sf@fbc-plane-move-sf-dmg-area,Timeout +kms_psr2_sf@overlay-plane-update-continuous-sf,Fail +kms_psr2_sf@overlay-plane-update-sf-dmg-area,Fail +kms_psr2_sf@primary-plane-update-sf-dmg-area,Fail +kms_psr2_sf@primary-plane-update-sf-dmg-area-big-fb,Fail kms_psr2_su@page_flip-NV12,Fail kms_psr2_su@page_flip-P010,Fail +kms_psr@psr-sprite-render,Timeout kms_setmode@basic,Fail +perf@i915-ref-count,Fail +perf_pmu@module-unload,Fail +perf_pmu@rc6,Crash +perf_pmu@rc6-suspend,Crash +sysfs_heartbeat_interval@long,Timeout +sysfs_heartbeat_interval@off,Timeout +sysfs_preempt_timeout@off,Timeout +sysfs_timeslice_duration@off,Timeout +xe_module_load@force-load,Fail +xe_module_load@load,Fail +xe_module_load@many-reload,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt new file mode 100644 index 000000000000..bb560ff1e2cd --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/i915-cml-flakes.txt @@ -0,0 +1,6 @@ +# Board Name: asus-C436FA-Flip-hatch +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +kms_plane_alpha_blend@constant-alpha-min diff --git a/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt b/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt index 6d3d7ddc377f..93b7736fffbb 100644 --- a/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-cml-skips.txt @@ -1,2 +1,25 @@ # This is generating kernel oops with divide error kms_plane_scaling@invalid-parameters + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# GEM tests takes ~1000 hours, so skip it +gem_.* + +# Hangs the machine and timeout occurs +i915_pm_rc6_residency.* +i915_suspend.* +xe_module_load.* +api_intel_allocator.* +kms_cursor_legacy.* + +# Kernel panic +drm_fdinfo.* +kms_frontbuffer_tracking.* diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt b/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt index 4596055d7e5e..fca15b487929 100644 --- a/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-glk-fails.txt @@ -1,5 +1,20 @@ -kms_fbcon_fbt@fbc,Fail -kms_flip@blocking-wf_vblank,Fail +core_setmaster@master-drop-set-user,Fail +i915_module_load@load,Fail +i915_module_load@reload,Fail +i915_module_load@reload-no-display,Fail +i915_module_load@resize-bar,Fail +kms_async_flips@invalid-async-flip,Timeout +kms_atomic_transition@modeset-transition-fencing,Timeout +kms_big_fb@linear-16bpp-rotate-0,Fail +kms_big_fb@linear-16bpp-rotate-180,Fail +kms_big_fb@linear-32bpp-rotate-0,Fail +kms_big_fb@linear-32bpp-rotate-180,Fail +kms_big_fb@linear-8bpp-rotate-0,Fail +kms_big_fb@linear-8bpp-rotate-180,Fail +kms_big_fb@linear-max-hw-stride-32bpp-rotate-0,Fail +kms_dirtyfb@default-dirtyfb-ioctl,Fail +kms_draw_crc@draw-method-render,Fail +kms_flip@flip-vs-dpms-off-vs-modeset,Timeout kms_flip@wf_vblank-ts-check,Fail kms_flip@wf_vblank-ts-check-interruptible,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail @@ -11,7 +26,6 @@ kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail @@ -26,11 +40,24 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail kms_frontbuffer_tracking@fbc-tiling-linear,Fail kms_frontbuffer_tracking@fbcdrrs-tiling-linear,Fail -kms_plane_alpha_blend@alpha-basic,Fail +kms_lease@lease-uevent,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail -kms_plane_alpha_blend@alpha-transparent-fb,Fail -kms_plane_alpha_blend@constant-alpha-max,Fail +kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout +kms_pm_rpm@legacy-planes,Timeout +kms_pm_rpm@legacy-planes-dpms,Timeout +kms_pm_rpm@modeset-stress-extra-wait,Timeout +kms_pm_rpm@universal-planes,Timeout +kms_pm_rpm@universal-planes-dpms,Timeout kms_rotation_crc@multiplane-rotation,Fail kms_rotation_crc@multiplane-rotation-cropping-bottom,Fail kms_rotation_crc@multiplane-rotation-cropping-top,Fail -kms_setmode@basic,Fail +perf@non-zero-reason,Timeout +sysfs_heartbeat_interval@long,Timeout +sysfs_heartbeat_interval@off,Timeout +sysfs_preempt_timeout@off,Timeout +sysfs_timeslice_duration@off,Timeout +xe_module_load@force-load,Fail +xe_module_load@load,Fail +xe_module_load@many-reload,Fail +xe_module_load@reload,Fail +xe_module_load@reload-no-display,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt new file mode 100644 index 000000000000..58fc424f8a42 --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/i915-glk-flakes.txt @@ -0,0 +1,7 @@ +# Board Name: hp-x360-12b-ca0010nr-n4020-octopus +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +core_hotunplug@unplug-rescan +kms_fb_coherency@memset-crc diff --git a/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt b/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt index 4c7d00ce14bc..b3226b2d9ba1 100644 --- a/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-glk-skips.txt @@ -2,4 +2,28 @@ .*suspend.* # This is generating kernel oops with divide error -kms_plane_scaling@invalid-parameters
\ No newline at end of file +kms_plane_scaling@invalid-parameters + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# GEM tests takes ~1000 hours, so skip it +gem_.* + +# Hangs the machine and timeout occurs +i915_pm_rc6_residency.* +i915_suspend.* +i915_pm_rpm.* +kms_ccs.* +kms_plane_multiple.* +perf.* + +# Kernel panic +drm_fdinfo.* +kms_plane_alpha_blend.* diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt index dab202716909..d4fba4f55ec1 100644 --- a/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-kbl-fails.txt @@ -1,32 +1,28 @@ -kms_bw@linear-tiling-2-displays-2560x1440p,Fail -kms_bw@linear-tiling-4-displays-2560x1440p,Fail -kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail -kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail +i915_module_load@load,Fail +i915_module_load@reload,Fail +i915_module_load@reload-no-display,Fail +i915_module_load@resize-bar,Fail +i915_pm_rpm@gem-execbuf-stress,Timeout kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail -kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail -kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail -kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-upscaling,Fail -kms_plane_alpha_blend@alpha-basic,Fail -kms_plane_alpha_blend@alpha-opaque-fb,Fail +kms_lease@lease-uevent,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail -kms_plane_alpha_blend@constant-alpha-max,Fail -kms_plane_alpha_blend@pipe-A-constant-alpha-max,Fail -kms_plane_alpha_blend@pipe-B-alpha-opaque-fb,Fail -kms_plane_alpha_blend@pipe-C-constant-alpha-max,Fail +perf@i915-ref-count,Fail +perf_pmu@busy-accuracy-50,Fail +perf_pmu@module-unload,Fail +perf_pmu@rc6,Crash +sysfs_heartbeat_interval@long,Timeout +sysfs_heartbeat_interval@off,Timeout +sysfs_preempt_timeout@off,Timeout +sysfs_timeslice_duration@off,Timeout +xe_module_load@force-load,Fail +xe_module_load@load,Fail +xe_module_load@many-reload,Fail +xe_module_load@reload,Fail +xe_module_load@reload-no-display,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt index a12f888530dd..6cf1fed2e575 100644 --- a/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/i915-kbl-flakes.txt @@ -1 +1,6 @@ -kms_async_flips@crc +# Board Name: hp-x360-14-G1-sona +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +prime_busy@hang diff --git a/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt index 4c7d00ce14bc..f0cf8a6dda25 100644 --- a/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-kbl-skips.txt @@ -2,4 +2,38 @@ .*suspend.* # This is generating kernel oops with divide error -kms_plane_scaling@invalid-parameters
\ No newline at end of file +kms_plane_scaling@invalid-parameters + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# GEM tests takes ~1000 hours, so skip it +gem_.* + +# Hangs the machine and timeout occurs +i915_.* +api_intel_bb.* + +# Kernel panic +drm_fdinfo.* +kms_.* +prime_mmap_coherency.* +perf.* +drm_read.* +api_intel_allocator.* +sysfs_preempt_timeout.* +dumb_buffer.* +gen9_exec_parse.* +debugfs_test.* +core_hotunplug.* +tools_test.* + +# GPU hang +sysfs_timeslice_.* +sysfs_heartbeat_.* diff --git a/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt index 27bfca1c6f2c..9a50e894c3e7 100644 --- a/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-tgl-fails.txt @@ -1,36 +1,43 @@ -kms_bw@linear-tiling-2-displays-3840x2160p,Fail -kms_bw@linear-tiling-3-displays-1920x1080p,Fail -kms_bw@linear-tiling-3-displays-2560x1440p,Fail -kms_bw@linear-tiling-3-displays-3840x2160p,Fail -kms_bw@linear-tiling-4-displays-1920x1080p,Fail -kms_bw@linear-tiling-4-displays-2560x1440p,Fail -kms_bw@linear-tiling-4-displays-3840x2160p,Fail -kms_bw@linear-tiling-5-displays-1920x1080p,Fail -kms_bw@linear-tiling-5-displays-2560x1440p,Fail -kms_bw@linear-tiling-5-displays-3840x2160p,Fail -kms_flip@flip-vs-panning-vs-hang,Timeout -kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail -kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail -kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail -kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-upscaling,Fail -kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling,Fail -kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-xtile-to-32bpp-xtile-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-upscaling,Fail -kms_rotation_crc@bad-pixel-format,Fail +api_intel_bb@blit-noreloc-keep-cache,Timeout +api_intel_bb@offset-control,Timeout +api_intel_bb@render-ccs,Timeout +core_getclient,Timeout +core_hotunplug@hotreplug-lateclose,Timeout +drm_read@short-buffer-block,Timeout +drm_read@short-buffer-nonblock,Timeout +dumb_buffer@map-uaf,Timeout +gen3_render_tiledx_blits,Timeout +gen7_exec_parse@basic-allocation,Timeout +gen7_exec_parse@batch-without-end,Timeout +gen9_exec_parse@batch-invalid-length,Timeout +gen9_exec_parse@bb-secure,Timeout +i915_module_load@load,Fail +i915_module_load@reload,Fail +i915_module_load@reload-no-display,Fail +i915_module_load@resize-bar,Fail +i915_pciid,Timeout +i915_query@engine-info,Timeout +kms_lease@lease-uevent,Fail kms_rotation_crc@multiplane-rotation,Fail -kms_rotation_crc@multiplane-rotation-cropping-bottom,Fail -kms_rotation_crc@multiplane-rotation-cropping-top,Fail +perf@i915-ref-count,Fail +perf_pmu@busy,Timeout +perf_pmu@enable-race,Timeout +perf_pmu@event-wait,Timeout +perf_pmu@gt-awake,Timeout +perf_pmu@module-unload,Fail +perf_pmu@rc6,Crash +prime_mmap@test_map_unmap,Timeout +prime_self_import@basic-with_one_bo,Timeout +syncobj_basic@bad-destroy,Timeout +syncobj_eventfd@invalid-bad-pad,Timeout +syncobj_wait@invalid-multi-wait-unsubmitted-signaled,Timeout +syncobj_wait@invalid-signal-illegal-handle,Timeout +syncobj_wait@invalid-single-wait-all-unsubmitted,Timeout +syncobj_wait@multi-wait-all-submitted,Timeout +syncobj_wait@multi-wait-for-submit-submitted-signaled,Timeout +syncobj_wait@wait-any-complex,Timeout +syncobj_wait@wait-delayed-signal,Timeout +xe_module_load@force-load,Fail +xe_module_load@load,Fail +xe_module_load@reload,Fail +xe_module_load@reload-no-display,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt index 1d0621750b14..e600782ef96a 100644 --- a/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-tgl-skips.txt @@ -8,4 +8,30 @@ gem_eio.* kms_flip@absolute-wf_vblank@a-edp1 # This is generating kernel oops with divide error -kms_plane_scaling@invalid-parameters
\ No newline at end of file +kms_plane_scaling@invalid-parameters + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# GEM tests takes ~1000 hours, so skip it +gem_.* + +# Kernel panic +drm_fdinfo.* + +# Hangs the machine and timeout occurs +i915_pm_rc6_residency.* +i915_suspend.* +sysfs_heartbeat_interval.* +syncobj_timeline.* +sysfs_timeslice_duration.* +syncobj_wait.* + +# Kernel panic and test hangs with multiple kms tests +kms_.* diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt b/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt index 967327ddc1ac..7582d313dd9b 100644 --- a/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt +++ b/drivers/gpu/drm/ci/xfails/i915-whl-fails.txt @@ -1,14 +1,25 @@ -kms_bw@linear-tiling-2-displays-1920x1080p,Fail -kms_bw@linear-tiling-2-displays-2560x1440p,Fail -kms_bw@linear-tiling-2-displays-3840x2160p,Fail -kms_bw@linear-tiling-3-displays-1920x1080p,Fail -kms_bw@linear-tiling-3-displays-2560x1440p,Fail -kms_bw@linear-tiling-3-displays-3840x2160p,Fail -kms_bw@linear-tiling-4-displays-1920x1080p,Fail -kms_bw@linear-tiling-4-displays-2560x1440p,Fail -kms_bw@linear-tiling-4-displays-3840x2160p,Fail -kms_fbcon_fbt@fbc,Fail -kms_fbcon_fbt@fbc-suspend,Fail +core_setmaster@master-drop-set-user,Fail +core_setmaster_vs_auth,Fail +i915_module_load@load,Fail +i915_module_load@reload,Fail +i915_module_load@reload-no-display,Fail +i915_module_load@resize-bar,Fail +i915_pm_rpm@gem-execbuf-stress,Timeout +i915_pm_rpm@module-reload,Fail +i915_pm_rpm@system-suspend-execbuf,Timeout +kms_async_flips@invalid-async-flip,Timeout +kms_atomic_transition@modeset-transition-fencing,Timeout +kms_big_fb@linear-16bpp-rotate-0,Fail +kms_big_fb@linear-16bpp-rotate-180,Fail +kms_big_fb@linear-32bpp-rotate-0,Fail +kms_big_fb@linear-32bpp-rotate-180,Fail +kms_big_fb@linear-8bpp-rotate-0,Fail +kms_big_fb@linear-8bpp-rotate-180,Fail +kms_big_fb@linear-max-hw-stride-32bpp-rotate-0,Fail +kms_ccs@crc-primary-rotation-180-yf-tiled-ccs,Timeout +kms_dirtyfb@default-dirtyfb-ioctl,Fail +kms_draw_crc@draw-method-render,Fail +kms_fb_coherency@memset-crc,Crash kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-linear-to-64bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-xtile-to-64bpp-xtile-downscaling,Fail @@ -18,8 +29,6 @@ kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-16bpp-linear-upscaling,Fail -kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-upscaling,Fail @@ -31,18 +40,26 @@ kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-downscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytile-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling,Fail kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-downscaling,Fail -kms_flip_scaled_crc@flip-64bpp-ytile-to-32bpp-ytilercccs-upscaling,Fail kms_frontbuffer_tracking@fbc-tiling-linear,Fail +kms_lease@lease-uevent,Fail kms_plane_alpha_blend@alpha-basic,Fail kms_plane_alpha_blend@alpha-opaque-fb,Fail kms_plane_alpha_blend@alpha-transparent-fb,Fail kms_plane_alpha_blend@constant-alpha-max,Fail -kms_plane_alpha_blend@pipe-A-alpha-opaque-fb,Fail -kms_plane_alpha_blend@pipe-A-alpha-transparent-fb,Fail -kms_plane_alpha_blend@pipe-A-constant-alpha-max,Fail -kms_plane_alpha_blend@pipe-B-alpha-opaque-fb,Fail -kms_plane_alpha_blend@pipe-B-alpha-transparent-fb,Fail -kms_plane_alpha_blend@pipe-B-constant-alpha-max,Fail -kms_plane_alpha_blend@pipe-C-alpha-opaque-fb,Fail -kms_plane_alpha_blend@pipe-C-alpha-transparent-fb,Fail -kms_plane_alpha_blend@pipe-C-constant-alpha-max,Fail +kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation,Timeout +kms_pm_rpm@modeset-stress-extra-wait,Timeout +kms_pm_rpm@universal-planes,Timeout +kms_pm_rpm@universal-planes-dpms,Timeout +perf@i915-ref-count,Fail +perf_pmu@module-unload,Fail +perf_pmu@rc6,Crash +perf_pmu@rc6-suspend,Crash +sysfs_heartbeat_interval@long,Timeout +sysfs_heartbeat_interval@off,Timeout +sysfs_preempt_timeout@off,Timeout +sysfs_timeslice_duration@off,Timeout +xe_module_load@force-load,Fail +xe_module_load@load,Fail +xe_module_load@many-reload,Fail +xe_module_load@reload,Fail +xe_module_load@reload-no-display,Fail diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt b/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt new file mode 100644 index 000000000000..1167a58c7dd1 --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/i915-whl-flakes.txt @@ -0,0 +1,6 @@ +# Board Name: dell-latitude-5400-8665U-sarien +# Bug Report: https://lore.kernel.org/intel-gfx/af4ca4df-a3ef-4943-bdbf-4c3af2c333af@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +kms_pm_rpm@modeset-lpsp-stress diff --git a/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt b/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt index f3be0888a214..20bd91525f45 100644 --- a/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt +++ b/drivers/gpu/drm/ci/xfails/i915-whl-skips.txt @@ -1,2 +1,22 @@ # This is generating kernel oops with divide error -kms_plane_scaling@invalid-parameters
\ No newline at end of file +kms_plane_scaling@invalid-parameters + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# GEM tests takes ~1000 hours, so skip it +gem_.* + +# Hangs the machine and timeout occurs +i915_pm_rc6_residency.* +i915_suspend.* +kms_flip.* + +# Kernel panic +drm_fdinfo.* diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt index ef0cb7c3698c..cc5e9c1c2d57 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-fails.txt @@ -1,36 +1,30 @@ +device_reset@cold-reset-bound,Fail +device_reset@reset-bound,Fail +device_reset@unbind-cold-reset-rebind,Fail +device_reset@unbind-reset-rebind,Fail +dumb_buffer@invalid-bpp,Fail +fbdev@eof,Fail +fbdev@read,Fail +fbdev@unaligned-write,Fail kms_3d,Fail kms_bw@linear-tiling-1-displays-1920x1080p,Fail +kms_bw@linear-tiling-1-displays-2160x1440p,Fail kms_bw@linear-tiling-1-displays-2560x1440p,Fail kms_bw@linear-tiling-1-displays-3840x2160p,Fail kms_bw@linear-tiling-2-displays-1920x1080p,Fail +kms_bw@linear-tiling-2-displays-2160x1440p,Fail kms_bw@linear-tiling-2-displays-2560x1440p,Fail kms_bw@linear-tiling-2-displays-3840x2160p,Fail -kms_bw@linear-tiling-3-displays-1920x1080p,Fail -kms_bw@linear-tiling-3-displays-2560x1440p,Fail -kms_bw@linear-tiling-3-displays-3840x2160p,Fail kms_color@invalid-gamma-lut-sizes,Fail -kms_color@pipe-A-invalid-gamma-lut-sizes,Fail -kms_color@pipe-B-invalid-gamma-lut-sizes,Fail kms_cursor_legacy@cursor-vs-flip-atomic,Fail kms_cursor_legacy@cursor-vs-flip-legacy,Fail kms_flip@flip-vs-modeset-vs-hang,Fail kms_flip@flip-vs-panning-vs-hang,Fail kms_flip@flip-vs-suspend,Fail kms_flip@flip-vs-suspend-interruptible,Fail -kms_force_connector_basic@force-edid,Fail -kms_force_connector_basic@force-load-detect,Fail -kms_force_connector_basic@prune-stale-modes,Fail -kms_hdmi_inject@inject-4k,Fail -kms_plane_scaling@planes-upscale-20x20,Fail -kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-25,Fail -kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-5,Fail -kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-75,Fail -kms_plane_scaling@upscale-with-modifier-20x20,Fail -kms_plane_scaling@upscale-with-pixel-format-20x20,Fail -kms_plane_scaling@upscale-with-rotation-20x20,Fail +kms_lease@lease-uevent,Fail kms_properties@get_properties-sanity-atomic,Fail kms_properties@plane-properties-atomic,Fail kms_properties@plane-properties-legacy,Fail kms_rmfb@close-fd,Fail -kms_selftest@drm_format,Timeout -kms_selftest@drm_format_helper,Timeout +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt new file mode 100644 index 000000000000..395ac0463404 --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-flakes.txt @@ -0,0 +1,11 @@ +# Board Name: mt8173-elm-hana +# Bug Report: https://lore.kernel.org/linux-mediatek/0b2a1899-15dd-42fa-8f63-ea0ca28dbb17@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +core_setmaster_vs_auth +dumb_buffer@create-clear +fbdev@unaligned-write +fbdev@write +kms_cursor_legacy@cursor-vs-flip-atomic-transitions +kms_prop_blob@invalid-set-prop diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt new file mode 100644 index 000000000000..0c6108392140 --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8173-skips.txt @@ -0,0 +1,16 @@ +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt index 67d690fc4037..9ef460646d76 100644 --- a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-fails.txt @@ -1,13 +1,8 @@ -kms_addfb_basic@addfb25-bad-modifier,Fail -kms_bw@linear-tiling-1-displays-2560x1440p,Fail -kms_bw@linear-tiling-2-displays-1920x1080p,Fail -kms_bw@linear-tiling-2-displays-2560x1440p,Fail -kms_bw@linear-tiling-2-displays-3840x2160p,Fail -kms_bw@linear-tiling-3-displays-2560x1440p,Fail -kms_bw@linear-tiling-3-displays-3840x2160p,Fail -kms_color@pipe-A-invalid-gamma-lut-sizes,Fail -kms_plane_cursor@overlay,Fail -kms_plane_cursor@primary,Fail -kms_plane_cursor@viewport,Fail -kms_plane_scaling@upscale-with-rotation-20x20,Fail -kms_rmfb@close-fd,Fail +dumb_buffer@create-clear,Fail +dumb_buffer@create-valid-dumb,Fail +dumb_buffer@invalid-bpp,Fail +dumb_buffer@map-invalid-size,Fail +dumb_buffer@map-uaf,Fail +dumb_buffer@map-valid,Fail +panfrost_prime@gem-prime-import,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt new file mode 100644 index 000000000000..715b9a8f4997 --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/mediatek-mt8183-skips.txt @@ -0,0 +1,18 @@ +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* + +# Panfrost is not a KMS driver, so skip the KMS tests +kms_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* diff --git a/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt b/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt index 56a2ae7047b4..9ef460646d76 100644 --- a/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt +++ b/drivers/gpu/drm/ci/xfails/meson-g12b-fails.txt @@ -1,16 +1,8 @@ -kms_3d,Fail -kms_cursor_legacy@forked-bo,Fail -kms_cursor_legacy@forked-move,Fail -kms_cursor_legacy@single-bo,Fail -kms_cursor_legacy@single-move,Fail -kms_cursor_legacy@torture-bo,Fail -kms_cursor_legacy@torture-move,Fail -kms_force_connector_basic@force-edid,Fail -kms_hdmi_inject@inject-4k,Fail -kms_plane_cursor@overlay,Fail -kms_plane_cursor@primary,Fail -kms_plane_cursor@viewport,Fail -kms_properties@connector-properties-atomic,Fail -kms_properties@connector-properties-legacy,Fail -kms_properties@get_properties-sanity-atomic,Fail -kms_properties@get_properties-sanity-non-atomic,Fail +dumb_buffer@create-clear,Fail +dumb_buffer@create-valid-dumb,Fail +dumb_buffer@invalid-bpp,Fail +dumb_buffer@map-invalid-size,Fail +dumb_buffer@map-uaf,Fail +dumb_buffer@map-valid,Fail +panfrost_prime@gem-prime-import,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt b/drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt new file mode 100644 index 000000000000..715b9a8f4997 --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/meson-g12b-skips.txt @@ -0,0 +1,18 @@ +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* + +# Panfrost is not a KMS driver, so skip the KMS tests +kms_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt index 44a5c62dedad..6e7fd1ccd1e3 100644 --- a/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt @@ -1,19 +1,15 @@ +device_reset@cold-reset-bound,Fail +device_reset@reset-bound,Fail +device_reset@unbind-cold-reset-rebind,Fail +device_reset@unbind-reset-rebind,Fail +dumb_buffer@invalid-bpp,Fail kms_3d,Fail -kms_addfb_basic@addfb25-bad-modifier,Fail -kms_cursor_legacy@all-pipes-forked-bo,Fail -kms_cursor_legacy@all-pipes-forked-move,Fail -kms_cursor_legacy@all-pipes-single-bo,Fail -kms_cursor_legacy@all-pipes-single-move,Fail -kms_cursor_legacy@all-pipes-torture-bo,Fail -kms_cursor_legacy@all-pipes-torture-move,Fail -kms_cursor_legacy@pipe-A-forked-bo,Fail -kms_cursor_legacy@pipe-A-forked-move,Fail -kms_cursor_legacy@pipe-A-single-bo,Fail -kms_cursor_legacy@pipe-A-single-move,Fail -kms_cursor_legacy@pipe-A-torture-bo,Fail -kms_cursor_legacy@pipe-A-torture-move,Fail +kms_cursor_legacy@forked-move,Fail +kms_cursor_legacy@single-bo,Fail +kms_cursor_legacy@torture-bo,Fail +kms_cursor_legacy@torture-move,Fail kms_force_connector_basic@force-edid,Fail kms_hdmi_inject@inject-4k,Fail -kms_selftest@drm_format,Timeout -kms_selftest@drm_format_helper,Timeout +kms_lease@lease-uevent,Fail msm_mapping@ring,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt b/drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt new file mode 100644 index 000000000000..ff12202abb6e --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/msm-apq8016-skips.txt @@ -0,0 +1,15 @@ +# Skip driver specific tests +^amdgpu.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt b/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt index 88a1fc0a3b0d..46ca69ce2ffe 100644 --- a/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-apq8096-fails.txt @@ -1,2 +1,8 @@ +device_reset@cold-reset-bound,Fail +device_reset@reset-bound,Fail +device_reset@unbind-cold-reset-rebind,Fail +device_reset@unbind-reset-rebind,Fail +dumb_buffer@invalid-bpp,Fail kms_3d,Fail -kms_addfb_basic@addfb25-bad-modifier,Fail +kms_lease@lease-uevent,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt new file mode 100644 index 000000000000..a275584c8bbb --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/msm-apq8096-flakes.txt @@ -0,0 +1,6 @@ +# Board Name: apq8096-db820c +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +dumb_buffer@create-clear diff --git a/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt b/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt index cd49c8ce2059..1c45fc6c512d 100644 --- a/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-apq8096-skips.txt @@ -1,2 +1,26 @@ # Whole machine hangs -kms_cursor_legacy@all-pipes-torture-move
\ No newline at end of file +kms_cursor_legacy@all-pipes-torture-move + +# Skip driver specific tests +^amdgpu.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* + +# gpu fault +# [IGT] msm_mapping: executing +# [IGT] msm_mapping: starting subtest shadow +# *** gpu fault: ttbr0=00000001030ea000 iova=0000000001074000 dir=WRITE type=PERMISSION source=1f030000 (0,0,0,0) +# msm_mdp 901000.display-controller: RBBM | ME master split | status=0x701000B0 +# watchdog: BUG: soft lockup - CPU#0 stuck for 26s! [kworker/u16:3:46] +msm_mapping@shadow diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt index f0576aa629e8..eb7a3886d397 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt @@ -1,18 +1,191 @@ +device_reset@cold-reset-bound,Fail +device_reset@reset-bound,Fail +device_reset@unbind-cold-reset-rebind,Fail +device_reset@unbind-reset-rebind,Fail +dumb_buffer@invalid-bpp,Fail +kms_atomic_transition@plane-primary-toggle-with-vblank-wait,Fail kms_color@ctm-0-25,Fail kms_color@ctm-0-50,Fail kms_color@ctm-0-75,Fail kms_color@ctm-blue-to-red,Fail kms_color@ctm-green-to-red,Fail +kms_color@ctm-max,Fail kms_color@ctm-negative,Fail kms_color@ctm-red-to-blue,Fail kms_color@ctm-signed,Fail +kms_content_protection@atomic,Crash +kms_content_protection@atomic-dpms,Crash +kms_content_protection@content-type-change,Crash +kms_content_protection@lic-type-0,Crash +kms_content_protection@lic-type-1,Crash +kms_content_protection@srm,Crash +kms_content_protection@type1,Crash +kms_content_protection@uevent,Crash +kms_cursor_crc@cursor-alpha-opaque,Fail +kms_cursor_crc@cursor-alpha-transparent,Fail +kms_cursor_crc@cursor-dpms,Fail +kms_cursor_crc@cursor-offscreen-128x128,Fail +kms_cursor_crc@cursor-offscreen-128x42,Fail +kms_cursor_crc@cursor-offscreen-256x256,Fail +kms_cursor_crc@cursor-offscreen-256x85,Fail +kms_cursor_crc@cursor-offscreen-32x10,Fail +kms_cursor_crc@cursor-offscreen-32x32,Fail +kms_cursor_crc@cursor-offscreen-512x170,Fail +kms_cursor_crc@cursor-offscreen-512x512,Fail +kms_cursor_crc@cursor-offscreen-64x21,Fail +kms_cursor_crc@cursor-offscreen-64x64,Fail +kms_cursor_crc@cursor-onscreen-128x128,Fail +kms_cursor_crc@cursor-onscreen-128x42,Fail +kms_cursor_crc@cursor-onscreen-256x256,Fail +kms_cursor_crc@cursor-onscreen-256x85,Fail +kms_cursor_crc@cursor-onscreen-32x10,Fail +kms_cursor_crc@cursor-onscreen-32x32,Fail +kms_cursor_crc@cursor-onscreen-512x170,Fail +kms_cursor_crc@cursor-onscreen-512x512,Fail +kms_cursor_crc@cursor-onscreen-64x21,Fail +kms_cursor_crc@cursor-onscreen-64x64,Fail +kms_cursor_crc@cursor-random-128x128,Fail +kms_cursor_crc@cursor-random-128x42,Fail +kms_cursor_crc@cursor-random-256x256,Fail +kms_cursor_crc@cursor-random-256x85,Fail +kms_cursor_crc@cursor-random-32x10,Fail +kms_cursor_crc@cursor-random-32x32,Fail +kms_cursor_crc@cursor-random-512x170,Fail +kms_cursor_crc@cursor-random-512x512,Fail +kms_cursor_crc@cursor-random-64x21,Fail +kms_cursor_crc@cursor-random-64x64,Fail +kms_cursor_crc@cursor-rapid-movement-128x128,Fail +kms_cursor_crc@cursor-rapid-movement-128x42,Fail +kms_cursor_crc@cursor-rapid-movement-256x256,Fail +kms_cursor_crc@cursor-rapid-movement-256x85,Fail +kms_cursor_crc@cursor-rapid-movement-32x10,Fail +kms_cursor_crc@cursor-rapid-movement-32x32,Fail +kms_cursor_crc@cursor-rapid-movement-512x170,Fail +kms_cursor_crc@cursor-rapid-movement-512x512,Fail +kms_cursor_crc@cursor-rapid-movement-64x21,Fail +kms_cursor_crc@cursor-rapid-movement-64x64,Fail +kms_cursor_crc@cursor-size-change,Fail +kms_cursor_crc@cursor-sliding-128x128,Fail +kms_cursor_crc@cursor-sliding-128x42,Fail +kms_cursor_crc@cursor-sliding-256x256,Fail +kms_cursor_crc@cursor-sliding-256x85,Fail +kms_cursor_crc@cursor-sliding-32x10,Fail +kms_cursor_crc@cursor-sliding-32x32,Fail +kms_cursor_crc@cursor-sliding-512x170,Fail +kms_cursor_crc@cursor-sliding-512x512,Fail +kms_cursor_crc@cursor-sliding-64x21,Fail +kms_cursor_crc@cursor-sliding-64x64,Fail +kms_cursor_edge_walk@128x128-left-edge,Fail +kms_cursor_edge_walk@128x128-right-edge,Fail +kms_cursor_edge_walk@128x128-top-bottom,Fail +kms_cursor_edge_walk@128x128-top-edge,Fail +kms_cursor_edge_walk@256x256-left-edge,Fail +kms_cursor_edge_walk@256x256-right-edge,Fail +kms_cursor_edge_walk@256x256-top-bottom,Fail +kms_cursor_edge_walk@256x256-top-edge,Fail +kms_cursor_edge_walk@64x64-left-edge,Fail +kms_cursor_edge_walk@64x64-right-edge,Fail +kms_cursor_edge_walk@64x64-top-bottom,Fail +kms_cursor_edge_walk@64x64-top-edge,Fail +kms_cursor_legacy@2x-cursor-vs-flip-atomic,Fail +kms_cursor_legacy@2x-cursor-vs-flip-legacy,Fail +kms_cursor_legacy@2x-flip-vs-cursor-atomic,Fail +kms_cursor_legacy@2x-flip-vs-cursor-legacy,Fail +kms_cursor_legacy@2x-long-cursor-vs-flip-atomic,Fail +kms_cursor_legacy@2x-long-cursor-vs-flip-legacy,Fail +kms_cursor_legacy@2x-long-flip-vs-cursor-atomic,Fail +kms_cursor_legacy@2x-long-flip-vs-cursor-legacy,Fail kms_cursor_legacy@cursor-vs-flip-toggle,Fail kms_cursor_legacy@cursor-vs-flip-varying-size,Fail +kms_display_modes@extended-mode-basic,Fail +kms_flip@2x-flip-vs-modeset-vs-hang,Fail +kms_flip@2x-flip-vs-panning-vs-hang,Fail +kms_flip@absolute-wf_vblank,Fail +kms_flip@absolute-wf_vblank-interruptible,Fail +kms_flip@basic-flip-vs-wf_vblank,Fail +kms_flip@basic-plain-flip,Fail +kms_flip@blocking-absolute-wf_vblank,Fail +kms_flip@blocking-absolute-wf_vblank-interruptible,Fail +kms_flip@blocking-wf_vblank,Fail +kms_flip@busy-flip,Fail +kms_flip@dpms-off-confusion,Fail +kms_flip@dpms-off-confusion-interruptible,Fail +kms_flip@dpms-vs-vblank-race,Fail +kms_flip@dpms-vs-vblank-race-interruptible,Fail +kms_flip@flip-vs-absolute-wf_vblank,Fail +kms_flip@flip-vs-absolute-wf_vblank-interruptible,Fail +kms_flip@flip-vs-blocking-wf-vblank,Fail +kms_flip@flip-vs-expired-vblank,Fail +kms_flip@flip-vs-expired-vblank-interruptible,Fail kms_flip@flip-vs-modeset-vs-hang,Fail +kms_flip@flip-vs-panning,Fail +kms_flip@flip-vs-panning-interruptible,Fail kms_flip@flip-vs-panning-vs-hang,Fail +kms_flip@flip-vs-rmfb,Fail +kms_flip@flip-vs-rmfb-interruptible,Fail +kms_flip@flip-vs-wf_vblank-interruptible,Fail +kms_flip@modeset-vs-vblank-race,Fail +kms_flip@modeset-vs-vblank-race-interruptible,Fail +kms_flip@plain-flip-fb-recreate,Fail +kms_flip@plain-flip-fb-recreate-interruptible,Fail +kms_flip@plain-flip-interruptible,Fail +kms_flip@plain-flip-ts-check,Fail +kms_flip@plain-flip-ts-check-interruptible,Fail +kms_flip@wf_vblank-ts-check,Fail +kms_flip@wf_vblank-ts-check-interruptible,Fail +kms_lease@cursor-implicit-plane,Fail +kms_lease@lease-uevent,Fail +kms_lease@page-flip-implicit-plane,Fail +kms_lease@setcrtc-implicit-plane,Fail +kms_lease@simple-lease,Fail +kms_multipipe_modeset@basic-max-pipe-crc-check,Fail kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail +kms_pipe_crc_basic@compare-crc-sanitycheck-xr24,Fail +kms_pipe_crc_basic@disable-crc-after-crtc,Fail +kms_pipe_crc_basic@nonblocking-crc,Fail +kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail +kms_pipe_crc_basic@read-crc,Fail +kms_pipe_crc_basic@read-crc-frame-sequence,Fail +kms_plane@pixel-format,Fail +kms_plane@pixel-format-source-clamping,Fail +kms_plane@plane-panning-bottom-right,Fail +kms_plane@plane-panning-top-left,Fail +kms_plane@plane-position-covered,Fail +kms_plane@plane-position-hole,Fail +kms_plane@plane-position-hole-dpms,Fail kms_plane_alpha_blend@alpha-7efc,Fail +kms_plane_alpha_blend@alpha-basic,Fail +kms_plane_alpha_blend@alpha-opaque-fb,Fail +kms_plane_alpha_blend@alpha-transparent-fb,Fail +kms_plane_alpha_blend@constant-alpha-max,Fail +kms_plane_alpha_blend@constant-alpha-mid,Fail +kms_plane_alpha_blend@constant-alpha-min,Fail kms_plane_alpha_blend@coverage-7efc,Fail kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail +kms_plane_cursor@primary,Fail +kms_plane_lowres@tiling-none,Fail +kms_plane_multiple@tiling-none,Fail kms_rmfb@close-fd,Fail -kms_universal_plane@universal-plane-sanity,Fail +kms_rotation_crc@cursor-rotation-180,Fail +kms_rotation_crc@primary-rotation-180,Fail +kms_sequence@get-busy,Fail +kms_sequence@get-forked,Fail +kms_sequence@get-forked-busy,Fail +kms_sequence@get-idle,Fail +kms_sequence@queue-busy,Fail +kms_sequence@queue-idle,Fail +kms_vblank@accuracy-idle,Fail +kms_vblank@crtc-id,Fail +kms_vblank@query-busy,Fail +kms_vblank@query-forked,Fail +kms_vblank@query-forked-busy,Fail +kms_vblank@query-idle,Fail +kms_vblank@ts-continuation-dpms-rpm,Fail +kms_vblank@ts-continuation-idle,Fail +kms_vblank@ts-continuation-modeset,Fail +kms_vblank@ts-continuation-modeset-rpm,Fail +kms_vblank@wait-busy,Fail +kms_vblank@wait-forked,Fail +kms_vblank@wait-forked-busy,Fail +kms_vblank@wait-idle,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt new file mode 100644 index 000000000000..6dec63d48cfb --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-flakes.txt @@ -0,0 +1,8 @@ +# Board Name: sc7180-trogdor-kingoftown +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +msm_mapping@shadow +msm_shrink@copy-gpu-oom-32 +msm_shrink@copy-gpu-oom-8 diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt index 327039f70252..68c96005ba54 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-skips.txt @@ -1,2 +1,21 @@ # Suspend to RAM seems to be broken on this machine .*suspend.* + +# Skip driver specific tests +^amdgpu.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* + +# Timeout occurs +kms_flip@2x-wf_vblank-ts-check diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt index f0576aa629e8..eb7a3886d397 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt @@ -1,18 +1,191 @@ +device_reset@cold-reset-bound,Fail +device_reset@reset-bound,Fail +device_reset@unbind-cold-reset-rebind,Fail +device_reset@unbind-reset-rebind,Fail +dumb_buffer@invalid-bpp,Fail +kms_atomic_transition@plane-primary-toggle-with-vblank-wait,Fail kms_color@ctm-0-25,Fail kms_color@ctm-0-50,Fail kms_color@ctm-0-75,Fail kms_color@ctm-blue-to-red,Fail kms_color@ctm-green-to-red,Fail +kms_color@ctm-max,Fail kms_color@ctm-negative,Fail kms_color@ctm-red-to-blue,Fail kms_color@ctm-signed,Fail +kms_content_protection@atomic,Crash +kms_content_protection@atomic-dpms,Crash +kms_content_protection@content-type-change,Crash +kms_content_protection@lic-type-0,Crash +kms_content_protection@lic-type-1,Crash +kms_content_protection@srm,Crash +kms_content_protection@type1,Crash +kms_content_protection@uevent,Crash +kms_cursor_crc@cursor-alpha-opaque,Fail +kms_cursor_crc@cursor-alpha-transparent,Fail +kms_cursor_crc@cursor-dpms,Fail +kms_cursor_crc@cursor-offscreen-128x128,Fail +kms_cursor_crc@cursor-offscreen-128x42,Fail +kms_cursor_crc@cursor-offscreen-256x256,Fail +kms_cursor_crc@cursor-offscreen-256x85,Fail +kms_cursor_crc@cursor-offscreen-32x10,Fail +kms_cursor_crc@cursor-offscreen-32x32,Fail +kms_cursor_crc@cursor-offscreen-512x170,Fail +kms_cursor_crc@cursor-offscreen-512x512,Fail +kms_cursor_crc@cursor-offscreen-64x21,Fail +kms_cursor_crc@cursor-offscreen-64x64,Fail +kms_cursor_crc@cursor-onscreen-128x128,Fail +kms_cursor_crc@cursor-onscreen-128x42,Fail +kms_cursor_crc@cursor-onscreen-256x256,Fail +kms_cursor_crc@cursor-onscreen-256x85,Fail +kms_cursor_crc@cursor-onscreen-32x10,Fail +kms_cursor_crc@cursor-onscreen-32x32,Fail +kms_cursor_crc@cursor-onscreen-512x170,Fail +kms_cursor_crc@cursor-onscreen-512x512,Fail +kms_cursor_crc@cursor-onscreen-64x21,Fail +kms_cursor_crc@cursor-onscreen-64x64,Fail +kms_cursor_crc@cursor-random-128x128,Fail +kms_cursor_crc@cursor-random-128x42,Fail +kms_cursor_crc@cursor-random-256x256,Fail +kms_cursor_crc@cursor-random-256x85,Fail +kms_cursor_crc@cursor-random-32x10,Fail +kms_cursor_crc@cursor-random-32x32,Fail +kms_cursor_crc@cursor-random-512x170,Fail +kms_cursor_crc@cursor-random-512x512,Fail +kms_cursor_crc@cursor-random-64x21,Fail +kms_cursor_crc@cursor-random-64x64,Fail +kms_cursor_crc@cursor-rapid-movement-128x128,Fail +kms_cursor_crc@cursor-rapid-movement-128x42,Fail +kms_cursor_crc@cursor-rapid-movement-256x256,Fail +kms_cursor_crc@cursor-rapid-movement-256x85,Fail +kms_cursor_crc@cursor-rapid-movement-32x10,Fail +kms_cursor_crc@cursor-rapid-movement-32x32,Fail +kms_cursor_crc@cursor-rapid-movement-512x170,Fail +kms_cursor_crc@cursor-rapid-movement-512x512,Fail +kms_cursor_crc@cursor-rapid-movement-64x21,Fail +kms_cursor_crc@cursor-rapid-movement-64x64,Fail +kms_cursor_crc@cursor-size-change,Fail +kms_cursor_crc@cursor-sliding-128x128,Fail +kms_cursor_crc@cursor-sliding-128x42,Fail +kms_cursor_crc@cursor-sliding-256x256,Fail +kms_cursor_crc@cursor-sliding-256x85,Fail +kms_cursor_crc@cursor-sliding-32x10,Fail +kms_cursor_crc@cursor-sliding-32x32,Fail +kms_cursor_crc@cursor-sliding-512x170,Fail +kms_cursor_crc@cursor-sliding-512x512,Fail +kms_cursor_crc@cursor-sliding-64x21,Fail +kms_cursor_crc@cursor-sliding-64x64,Fail +kms_cursor_edge_walk@128x128-left-edge,Fail +kms_cursor_edge_walk@128x128-right-edge,Fail +kms_cursor_edge_walk@128x128-top-bottom,Fail +kms_cursor_edge_walk@128x128-top-edge,Fail +kms_cursor_edge_walk@256x256-left-edge,Fail +kms_cursor_edge_walk@256x256-right-edge,Fail +kms_cursor_edge_walk@256x256-top-bottom,Fail +kms_cursor_edge_walk@256x256-top-edge,Fail +kms_cursor_edge_walk@64x64-left-edge,Fail +kms_cursor_edge_walk@64x64-right-edge,Fail +kms_cursor_edge_walk@64x64-top-bottom,Fail +kms_cursor_edge_walk@64x64-top-edge,Fail +kms_cursor_legacy@2x-cursor-vs-flip-atomic,Fail +kms_cursor_legacy@2x-cursor-vs-flip-legacy,Fail +kms_cursor_legacy@2x-flip-vs-cursor-atomic,Fail +kms_cursor_legacy@2x-flip-vs-cursor-legacy,Fail +kms_cursor_legacy@2x-long-cursor-vs-flip-atomic,Fail +kms_cursor_legacy@2x-long-cursor-vs-flip-legacy,Fail +kms_cursor_legacy@2x-long-flip-vs-cursor-atomic,Fail +kms_cursor_legacy@2x-long-flip-vs-cursor-legacy,Fail kms_cursor_legacy@cursor-vs-flip-toggle,Fail kms_cursor_legacy@cursor-vs-flip-varying-size,Fail +kms_display_modes@extended-mode-basic,Fail +kms_flip@2x-flip-vs-modeset-vs-hang,Fail +kms_flip@2x-flip-vs-panning-vs-hang,Fail +kms_flip@absolute-wf_vblank,Fail +kms_flip@absolute-wf_vblank-interruptible,Fail +kms_flip@basic-flip-vs-wf_vblank,Fail +kms_flip@basic-plain-flip,Fail +kms_flip@blocking-absolute-wf_vblank,Fail +kms_flip@blocking-absolute-wf_vblank-interruptible,Fail +kms_flip@blocking-wf_vblank,Fail +kms_flip@busy-flip,Fail +kms_flip@dpms-off-confusion,Fail +kms_flip@dpms-off-confusion-interruptible,Fail +kms_flip@dpms-vs-vblank-race,Fail +kms_flip@dpms-vs-vblank-race-interruptible,Fail +kms_flip@flip-vs-absolute-wf_vblank,Fail +kms_flip@flip-vs-absolute-wf_vblank-interruptible,Fail +kms_flip@flip-vs-blocking-wf-vblank,Fail +kms_flip@flip-vs-expired-vblank,Fail +kms_flip@flip-vs-expired-vblank-interruptible,Fail kms_flip@flip-vs-modeset-vs-hang,Fail +kms_flip@flip-vs-panning,Fail +kms_flip@flip-vs-panning-interruptible,Fail kms_flip@flip-vs-panning-vs-hang,Fail +kms_flip@flip-vs-rmfb,Fail +kms_flip@flip-vs-rmfb-interruptible,Fail +kms_flip@flip-vs-wf_vblank-interruptible,Fail +kms_flip@modeset-vs-vblank-race,Fail +kms_flip@modeset-vs-vblank-race-interruptible,Fail +kms_flip@plain-flip-fb-recreate,Fail +kms_flip@plain-flip-fb-recreate-interruptible,Fail +kms_flip@plain-flip-interruptible,Fail +kms_flip@plain-flip-ts-check,Fail +kms_flip@plain-flip-ts-check-interruptible,Fail +kms_flip@wf_vblank-ts-check,Fail +kms_flip@wf_vblank-ts-check-interruptible,Fail +kms_lease@cursor-implicit-plane,Fail +kms_lease@lease-uevent,Fail +kms_lease@page-flip-implicit-plane,Fail +kms_lease@setcrtc-implicit-plane,Fail +kms_lease@simple-lease,Fail +kms_multipipe_modeset@basic-max-pipe-crc-check,Fail kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail +kms_pipe_crc_basic@compare-crc-sanitycheck-xr24,Fail +kms_pipe_crc_basic@disable-crc-after-crtc,Fail +kms_pipe_crc_basic@nonblocking-crc,Fail +kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail +kms_pipe_crc_basic@read-crc,Fail +kms_pipe_crc_basic@read-crc-frame-sequence,Fail +kms_plane@pixel-format,Fail +kms_plane@pixel-format-source-clamping,Fail +kms_plane@plane-panning-bottom-right,Fail +kms_plane@plane-panning-top-left,Fail +kms_plane@plane-position-covered,Fail +kms_plane@plane-position-hole,Fail +kms_plane@plane-position-hole-dpms,Fail kms_plane_alpha_blend@alpha-7efc,Fail +kms_plane_alpha_blend@alpha-basic,Fail +kms_plane_alpha_blend@alpha-opaque-fb,Fail +kms_plane_alpha_blend@alpha-transparent-fb,Fail +kms_plane_alpha_blend@constant-alpha-max,Fail +kms_plane_alpha_blend@constant-alpha-mid,Fail +kms_plane_alpha_blend@constant-alpha-min,Fail kms_plane_alpha_blend@coverage-7efc,Fail kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail +kms_plane_cursor@primary,Fail +kms_plane_lowres@tiling-none,Fail +kms_plane_multiple@tiling-none,Fail kms_rmfb@close-fd,Fail -kms_universal_plane@universal-plane-sanity,Fail +kms_rotation_crc@cursor-rotation-180,Fail +kms_rotation_crc@primary-rotation-180,Fail +kms_sequence@get-busy,Fail +kms_sequence@get-forked,Fail +kms_sequence@get-forked-busy,Fail +kms_sequence@get-idle,Fail +kms_sequence@queue-busy,Fail +kms_sequence@queue-idle,Fail +kms_vblank@accuracy-idle,Fail +kms_vblank@crtc-id,Fail +kms_vblank@query-busy,Fail +kms_vblank@query-forked,Fail +kms_vblank@query-forked-busy,Fail +kms_vblank@query-idle,Fail +kms_vblank@ts-continuation-dpms-rpm,Fail +kms_vblank@ts-continuation-idle,Fail +kms_vblank@ts-continuation-modeset,Fail +kms_vblank@ts-continuation-modeset-rpm,Fail +kms_vblank@wait-busy,Fail +kms_vblank@wait-forked,Fail +kms_vblank@wait-forked-busy,Fail +kms_vblank@wait-idle,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt new file mode 100644 index 000000000000..dcb24b835dc3 --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-flakes.txt @@ -0,0 +1,6 @@ +# Board Name: sc7180-trogdor-lazor-limozeen-nots-r5 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +msm_mapping@shadow diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt index 327039f70252..1168c53acd2d 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-skips.txt @@ -1,2 +1,18 @@ # Suspend to RAM seems to be broken on this machine .*suspend.* + +# Skip driver specific tests +^amdgpu.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* diff --git a/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt index e9043a00383e..8f010c8a9c4f 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt @@ -1,3 +1,8 @@ +device_reset@cold-reset-bound,Fail +device_reset@reset-bound,Fail +device_reset@unbind-cold-reset-rebind,Fail +device_reset@unbind-reset-rebind,Fail +dumb_buffer@invalid-bpp,Fail kms_color@ctm-0-25,Fail kms_color@ctm-0-50,Fail kms_color@ctm-0-75,Fail @@ -6,17 +11,6 @@ kms_color@ctm-green-to-red,Fail kms_color@ctm-negative,Fail kms_color@ctm-red-to-blue,Fail kms_color@ctm-signed,Fail -kms_color@pipe-A-ctm-0-25,Fail -kms_color@pipe-A-ctm-0-5,Fail -kms_color@pipe-A-ctm-0-75,Fail -kms_color@pipe-A-ctm-blue-to-red,Fail -kms_color@pipe-A-ctm-green-to-red,Fail -kms_color@pipe-A-ctm-max,Fail -kms_color@pipe-A-ctm-negative,Fail -kms_color@pipe-A-ctm-red-to-blue,Fail -kms_color@pipe-A-legacy-gamma,Fail -kms_cursor_legacy@basic-flip-after-cursor-atomic,Fail -kms_cursor_legacy@basic-flip-after-cursor-varying-size,Fail kms_cursor_legacy@basic-flip-before-cursor-atomic,Fail kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail kms_cursor_legacy@cursor-vs-flip-atomic,Fail @@ -31,30 +25,12 @@ kms_cursor_legacy@flip-vs-cursor-crc-legacy,Fail kms_cursor_legacy@flip-vs-cursor-legacy,Fail kms_flip@flip-vs-modeset-vs-hang,Fail kms_flip@flip-vs-panning-vs-hang,Fail +kms_lease@lease-uevent,Fail kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail kms_plane_alpha_blend@alpha-7efc,Fail kms_plane_alpha_blend@coverage-7efc,Fail kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail -kms_plane_alpha_blend@pipe-A-alpha-7efc,Fail -kms_plane_alpha_blend@pipe-A-coverage-7efc,Fail -kms_plane_alpha_blend@pipe-A-coverage-vs-premult-vs-constant,Fail kms_plane_cursor@overlay,Fail -kms_plane_cursor@pipe-A-overlay-size-128,Fail -kms_plane_cursor@pipe-A-overlay-size-256,Fail -kms_plane_cursor@pipe-A-overlay-size-64,Fail -kms_plane_cursor@pipe-A-viewport-size-128,Fail -kms_plane_cursor@pipe-A-viewport-size-256,Fail -kms_plane_cursor@pipe-A-viewport-size-64,Fail kms_plane_cursor@viewport,Fail -kms_plane_scaling@downscale-with-pixel-format-factor-0-25,Timeout -kms_plane_scaling@downscale-with-pixel-format-factor-0-5,Timeout -kms_plane_scaling@downscale-with-pixel-format-factor-0-75,Timeout -kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-25,Timeout -kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-5,Timeout -kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-75,Timeout -kms_plane_scaling@plane-scaler-with-clipping-clamping-pixel-formats,Timeout -kms_plane_scaling@plane-scaler-with-pixel-format-unity-scaling,Timeout -kms_plane_scaling@planes-downscale-factor-0-25,Fail -kms_plane_scaling@scaler-with-clipping-clamping,Timeout -kms_plane_scaling@scaler-with-pixel-format-unity-scaling,Timeout kms_rmfb@close-fd,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt index 8a492f01eaa4..2c5f62b07632 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt @@ -1,22 +1,19 @@ -# Board Name: msm:sdm845 -# Bug Report: https://lore.kernel.org/dri-devel/46287831-edfa-78e8-6055-d7a08831c445@collabora.com/T/#u +# Board Name: sdm845-cheza-r3 +# Bug Report: https://lore.kernel.org/linux-arm-msm/661483c8-ad82-400d-bcd8-e94986d20d7d@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 # Failure Rate: 50 -# IGT Version: 1.28-gd2af13d9f -# Linux Version: 6.7.0-rc3 - -# Reported by deqp-runner +kms_cursor_legacy@basic-flip-after-cursor-atomic kms_cursor_legacy@basic-flip-after-cursor-legacy -kms_cursor_legacy@flip-vs-cursor-toggle +kms_cursor_legacy@basic-flip-after-cursor-varying-size +kms_cursor_legacy@basic-flip-before-cursor-varying-size +kms_cursor_legacy@flip-vs-cursor-atomic-transitions +kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size kms_cursor_legacy@flip-vs-cursor-varying-size +kms_cursor_legacy@short-flip-after-cursor-atomic-transitions +kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size kms_cursor_legacy@short-flip-after-cursor-toggle kms_cursor_legacy@short-flip-before-cursor-atomic-transitions kms_cursor_legacy@short-flip-before-cursor-atomic-transitions-varying-size msm_shrink@copy-gpu-32 msm_shrink@copy-gpu-oom-32 - -# The below test shows inconsistency across multiple runs, giving -# results of Pass and Fail alternately. -kms_cursor_legacy@basic-flip-before-cursor-varying-size -kms_cursor_legacy@flip-vs-cursor-atomic-transitions -kms_cursor_legacy@short-flip-after-cursor-atomic-transitions -kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size diff --git a/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt index 618e3a3a7277..5185212c8fb2 100644 --- a/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt +++ b/drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt @@ -5,3 +5,22 @@ kms_bw.* # https://gitlab.freedesktop.org/gfx-ci/linux/-/commit/4b49f902ec6f2bb382cbbf489870573f4b43371e # https://gitlab.freedesktop.org/gfx-ci/linux/-/commit/38cdf4c5559771e2474ae0fecef8469f65147bc1 msm_mapping@* + +# Skip driver specific tests +^amdgpu.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* + +# Whole machine hangs +kms_cursor_crc.* diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt index 90c63f519e9e..f9b99bf27105 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-fails.txt @@ -1,54 +1,8 @@ -kms_3d,Crash -kms_bw@linear-tiling-2-displays-1920x1080p,Fail -kms_bw@linear-tiling-2-displays-2560x1440p,Fail -kms_bw@linear-tiling-2-displays-3840x2160p,Fail -kms_bw@linear-tiling-3-displays-1920x1080p,Fail -kms_bw@linear-tiling-3-displays-2560x1440p,Fail -kms_bw@linear-tiling-3-displays-3840x2160p,Fail -kms_flip@flip-vs-modeset-vs-hang,Crash -kms_flip@flip-vs-panning-vs-hang,Crash -kms_force_connector_basic@force-load-detect,Fail -kms_invalid_mode@int-max-clock,Crash -kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Crash -kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Crash -kms_pipe_crc_basic@read-crc-frame-sequence,Crash -kms_plane@pixel-format,Crash -kms_plane@pixel-format-source-clamping,Crash -kms_plane@plane-position-hole,Crash -kms_plane@plane-position-hole-dpms,Crash -kms_plane_cursor@overlay,Crash -kms_plane_cursor@pipe-A-overlay-size-128,Fail -kms_plane_cursor@pipe-A-overlay-size-256,Fail -kms_plane_cursor@pipe-A-overlay-size-64,Fail -kms_plane_cursor@pipe-A-primary-size-128,Fail -kms_plane_cursor@pipe-A-primary-size-256,Fail -kms_plane_cursor@pipe-A-primary-size-64,Fail -kms_plane_cursor@pipe-A-viewport-size-128,Fail -kms_plane_cursor@pipe-A-viewport-size-256,Fail -kms_plane_cursor@pipe-A-viewport-size-64,Fail -kms_plane_cursor@pipe-B-overlay-size-128,Fail -kms_plane_cursor@pipe-B-overlay-size-256,Fail -kms_plane_cursor@pipe-B-overlay-size-64,Fail -kms_plane_cursor@pipe-B-primary-size-128,Fail -kms_plane_cursor@pipe-B-primary-size-256,Fail -kms_plane_cursor@pipe-B-primary-size-64,Fail -kms_plane_cursor@pipe-B-viewport-size-128,Fail -kms_plane_cursor@pipe-B-viewport-size-256,Fail -kms_plane_cursor@pipe-B-viewport-size-64,Fail -kms_plane_cursor@primary,Crash -kms_plane_cursor@viewport,Crash -kms_plane_lowres@tiling-none,Fail -kms_plane_scaling@downscale-with-modifier-factor-0-25,Fail -kms_plane_scaling@downscale-with-rotation-factor-0-25,Fail -kms_plane_scaling@upscale-with-modifier-20x20,Fail -kms_plane_scaling@upscale-with-modifier-factor-0-25,Fail -kms_plane_scaling@upscale-with-pixel-format-20x20,Fail -kms_plane_scaling@upscale-with-pixel-format-factor-0-25,Fail -kms_plane_scaling@upscale-with-rotation-20x20,Fail -kms_prime@basic-crc,Fail -kms_properties@connector-properties-atomic,Crash -kms_properties@connector-properties-legacy,Crash -kms_properties@get_properties-sanity-atomic,Crash -kms_properties@get_properties-sanity-non-atomic,Crash -kms_rmfb@close-fd,Crash -kms_setmode@invalid-clone-single-crtc,Crash +dumb_buffer@create-clear,Crash +dumb_buffer@create-valid-dumb,Crash +dumb_buffer@invalid-bpp,Crash +dumb_buffer@map-invalid-size,Crash +dumb_buffer@map-uaf,Crash +dumb_buffer@map-valid,Crash +panfrost_prime@gem-prime-import,Crash +tools_test@tools_test,Crash diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt index f20c3574b75a..6d3757dca83b 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3288-skips.txt @@ -49,4 +49,23 @@ kms_plane_lowres@pipe-F-tiling-y kms_cursor_crc.* # Machine is hanging in this test, so skip it -kms_pipe_crc_basic@disable-crc-after-crtc
\ No newline at end of file +kms_pipe_crc_basic@disable-crc-after-crtc + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* + +# Panfrost is not a KMS driver, so skip the KMS tests +kms_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt index d516d9c1d546..9ef460646d76 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-fails.txt @@ -1,75 +1,8 @@ -kms_color@gamma,Fail -kms_color@legacy-gamma,Fail -kms_color@pipe-A-legacy-gamma,Fail -kms_color@pipe-B-legacy-gamma,Fail -kms_cursor_crc@cursor-alpha-opaque,Fail -kms_cursor_crc@cursor-alpha-transparent,Fail -kms_cursor_crc@cursor-dpms,Fail -kms_cursor_crc@cursor-offscreen-32x10,Fail -kms_cursor_crc@cursor-offscreen-32x32,Fail -kms_cursor_crc@cursor-offscreen-64x64,Fail -kms_cursor_crc@cursor-onscreen-32x10,Fail -kms_cursor_crc@cursor-onscreen-32x32,Fail -kms_cursor_crc@cursor-onscreen-64x21,Fail -kms_cursor_crc@cursor-onscreen-64x64,Fail -kms_cursor_crc@cursor-random-32x10,Fail -kms_cursor_crc@cursor-random-32x32,Fail -kms_cursor_crc@cursor-random-64x21,Fail -kms_cursor_crc@cursor-random-64x64,Fail -kms_cursor_crc@cursor-rapid-movement-32x32,Fail -kms_cursor_crc@cursor-rapid-movement-64x21,Fail -kms_cursor_crc@cursor-rapid-movement-64x64,Fail -kms_cursor_crc@cursor-size-change,Fail -kms_cursor_crc@cursor-sliding-32x10,Fail -kms_cursor_crc@cursor-sliding-32x32,Fail -kms_cursor_crc@cursor-sliding-64x21,Fail -kms_cursor_crc@cursor-sliding-64x64,Fail -kms_flip@basic-flip-vs-wf_vblank,Fail -kms_flip@blocking-wf_vblank,Fail -kms_flip@dpms-vs-vblank-race,Fail -kms_flip@flip-vs-absolute-wf_vblank,Fail -kms_flip@flip-vs-absolute-wf_vblank-interruptible,Fail -kms_flip@flip-vs-blocking-wf-vblank,Fail -kms_flip@flip-vs-modeset-vs-hang,Fail -kms_flip@flip-vs-panning,Fail -kms_flip@flip-vs-panning-interruptible,Fail -kms_flip@flip-vs-panning-vs-hang,Fail -kms_flip@modeset-vs-vblank-race,Fail -kms_flip@plain-flip-fb-recreate,Fail -kms_flip@plain-flip-fb-recreate-interruptible,Fail -kms_flip@plain-flip-ts-check,Fail -kms_flip@plain-flip-ts-check-interruptible,Fail -kms_flip@wf_vblank-ts-check,Fail -kms_flip@wf_vblank-ts-check-interruptible,Fail -kms_invalid_mode@int-max-clock,Fail -kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail -kms_pipe_crc_basic@compare-crc-sanitycheck-xr24,Fail -kms_pipe_crc_basic@disable-crc-after-crtc,Fail -kms_pipe_crc_basic@nonblocking-crc,Fail -kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail -kms_pipe_crc_basic@read-crc,Fail -kms_pipe_crc_basic@read-crc-frame-sequence,Fail -kms_plane@pixel-format,Fail -kms_plane@pixel-format-source-clamping,Fail -kms_plane@plane-panning-bottom-right,Fail -kms_plane@plane-panning-top-left,Fail -kms_plane@plane-position-covered,Fail -kms_plane@plane-position-hole,Fail -kms_plane@plane-position-hole-dpms,Fail -kms_plane_cursor@overlay,Fail -kms_plane_cursor@pipe-B-overlay-size-128,Fail -kms_plane_cursor@pipe-B-overlay-size-256,Fail -kms_plane_cursor@pipe-B-overlay-size-64,Fail -kms_plane_cursor@pipe-B-primary-size-128,Fail -kms_plane_cursor@pipe-B-primary-size-256,Fail -kms_plane_cursor@pipe-B-primary-size-64,Fail -kms_plane_cursor@pipe-B-viewport-size-128,Fail -kms_plane_cursor@pipe-B-viewport-size-256,Fail -kms_plane_cursor@pipe-B-viewport-size-64,Fail -kms_plane_cursor@primary,Fail -kms_plane_cursor@viewport,Fail -kms_plane_multiple@atomic-pipe-B-tiling-none,Fail -kms_plane_multiple@tiling-none,Fail -kms_prime@basic-crc,Fail -kms_rmfb@close-fd,Fail -kms_universal_plane@universal-plane-pipe-B-functional,Fail +dumb_buffer@create-clear,Fail +dumb_buffer@create-valid-dumb,Fail +dumb_buffer@invalid-bpp,Fail +dumb_buffer@map-invalid-size,Fail +dumb_buffer@map-uaf,Fail +dumb_buffer@map-valid,Fail +panfrost_prime@gem-prime-import,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt index c9fdc623ab91..742c27d9a598 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-flakes.txt @@ -1,7 +1,6 @@ -kms_bw@linear-tiling-2-displays-1920x1080p -kms_cursor_crc@cursor-offscreen-64x21 -kms_flip@dpms-vs-vblank-race-interruptible -kms_flip@flip-vs-wf_vblank-interruptible -kms_plane_cursor@overlay -kms_plane_cursor@primary -kms_plane_cursor@viewport +# Board Name: rk3399-gru-kevin +# Bug Report: https://lore.kernel.org/dri-devel/5cc34a8b-c1fa-4744-9031-2d33ecf41011@collabora.com/T/#u +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +# Failure Rate: 50 +panfrost_submit@pan-unhandled-pagefault diff --git a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt index 10c3d81a919a..5c52b25b4213 100644 --- a/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt +++ b/drivers/gpu/drm/ci/xfails/rockchip-rk3399-skips.txt @@ -3,3 +3,22 @@ # Too unstable, machine ends up hanging after lots of Oopses kms_cursor_legacy.* + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* + +# Panfrost is not a KMS driver, so skip the KMS tests +kms_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* diff --git a/drivers/gpu/drm/ci/xfails/update-xfails.py b/drivers/gpu/drm/ci/xfails/update-xfails.py index e9f0ec7fed8d..a446e98d72a1 100755 --- a/drivers/gpu/drm/ci/xfails/update-xfails.py +++ b/drivers/gpu/drm/ci/xfails/update-xfails.py @@ -93,10 +93,10 @@ def add_unit_test_or_update_result_to_fails_if_present(fails_txt, unit_test, fai def split_unit_test_from_collate(xfails): for job_name in xfails.keys(): for job_id in xfails[job_name].copy().keys(): - if "not found" in xfails[job_name][job_id]: + if "not found" in xfails[job_name][job_id].content_as_str: del xfails[job_name][job_id] continue - xfails[job_name][job_id] = xfails[job_name][job_id].strip().split("\n") + xfails[job_name][job_id] = xfails[job_name][job_id].content_as_str.splitlines() def get_xfails_from_pipeline_url(pipeline_url): diff --git a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt index 007f21e56d89..fdf09fe11566 100644 --- a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt +++ b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-fails.txt @@ -1,33 +1,72 @@ -kms_addfb_basic@addfb25-bad-modifier,Fail kms_addfb_basic@bad-pitch-65536,Fail kms_addfb_basic@bo-too-small,Fail kms_addfb_basic@size-max,Fail kms_addfb_basic@too-high,Fail kms_atomic_transition@plane-primary-toggle-with-vblank-wait,Fail kms_bw@linear-tiling-1-displays-1920x1080p,Fail +kms_bw@linear-tiling-1-displays-2160x1440p,Fail kms_bw@linear-tiling-1-displays-2560x1440p,Fail kms_bw@linear-tiling-1-displays-3840x2160p,Fail +kms_bw@linear-tiling-10-displays-1920x1080p,Fail +kms_bw@linear-tiling-10-displays-2160x1440p,Fail +kms_bw@linear-tiling-10-displays-2560x1440p,Fail +kms_bw@linear-tiling-10-displays-3840x2160p,Fail +kms_bw@linear-tiling-11-displays-1920x1080p,Fail +kms_bw@linear-tiling-11-displays-2160x1440p,Fail +kms_bw@linear-tiling-11-displays-2560x1440p,Fail +kms_bw@linear-tiling-11-displays-3840x2160p,Fail +kms_bw@linear-tiling-12-displays-1920x1080p,Fail +kms_bw@linear-tiling-12-displays-2160x1440p,Fail +kms_bw@linear-tiling-12-displays-2560x1440p,Fail +kms_bw@linear-tiling-12-displays-3840x2160p,Fail +kms_bw@linear-tiling-13-displays-1920x1080p,Fail +kms_bw@linear-tiling-13-displays-2160x1440p,Fail +kms_bw@linear-tiling-13-displays-2560x1440p,Fail +kms_bw@linear-tiling-13-displays-3840x2160p,Fail +kms_bw@linear-tiling-14-displays-1920x1080p,Fail +kms_bw@linear-tiling-14-displays-2160x1440p,Fail +kms_bw@linear-tiling-14-displays-2560x1440p,Fail +kms_bw@linear-tiling-14-displays-3840x2160p,Fail +kms_bw@linear-tiling-15-displays-1920x1080p,Fail +kms_bw@linear-tiling-15-displays-2160x1440p,Fail +kms_bw@linear-tiling-15-displays-2560x1440p,Fail +kms_bw@linear-tiling-15-displays-3840x2160p,Fail +kms_bw@linear-tiling-16-displays-1920x1080p,Fail +kms_bw@linear-tiling-16-displays-2160x1440p,Fail +kms_bw@linear-tiling-16-displays-2560x1440p,Fail +kms_bw@linear-tiling-16-displays-3840x2160p,Fail kms_bw@linear-tiling-2-displays-1920x1080p,Fail +kms_bw@linear-tiling-2-displays-2160x1440p,Fail kms_bw@linear-tiling-2-displays-2560x1440p,Fail kms_bw@linear-tiling-2-displays-3840x2160p,Fail kms_bw@linear-tiling-3-displays-1920x1080p,Fail +kms_bw@linear-tiling-3-displays-2160x1440p,Fail kms_bw@linear-tiling-3-displays-2560x1440p,Fail kms_bw@linear-tiling-3-displays-3840x2160p,Fail kms_bw@linear-tiling-4-displays-1920x1080p,Fail +kms_bw@linear-tiling-4-displays-2160x1440p,Fail kms_bw@linear-tiling-4-displays-2560x1440p,Fail kms_bw@linear-tiling-4-displays-3840x2160p,Fail kms_bw@linear-tiling-5-displays-1920x1080p,Fail +kms_bw@linear-tiling-5-displays-2160x1440p,Fail kms_bw@linear-tiling-5-displays-2560x1440p,Fail kms_bw@linear-tiling-5-displays-3840x2160p,Fail kms_bw@linear-tiling-6-displays-1920x1080p,Fail +kms_bw@linear-tiling-6-displays-2160x1440p,Fail kms_bw@linear-tiling-6-displays-2560x1440p,Fail kms_bw@linear-tiling-6-displays-3840x2160p,Fail kms_bw@linear-tiling-7-displays-1920x1080p,Fail +kms_bw@linear-tiling-7-displays-2160x1440p,Fail kms_bw@linear-tiling-7-displays-2560x1440p,Fail kms_bw@linear-tiling-7-displays-3840x2160p,Fail kms_bw@linear-tiling-8-displays-1920x1080p,Fail +kms_bw@linear-tiling-8-displays-2160x1440p,Fail kms_bw@linear-tiling-8-displays-2560x1440p,Fail kms_bw@linear-tiling-8-displays-3840x2160p,Fail +kms_bw@linear-tiling-9-displays-1920x1080p,Fail +kms_bw@linear-tiling-9-displays-2160x1440p,Fail +kms_bw@linear-tiling-9-displays-2560x1440p,Fail +kms_bw@linear-tiling-9-displays-3840x2160p,Fail kms_flip@absolute-wf_vblank,Fail kms_flip@absolute-wf_vblank-interruptible,Fail kms_flip@basic-flip-vs-wf_vblank,Fail @@ -54,31 +93,34 @@ kms_flip@plain-flip-ts-check-interruptible,Fail kms_flip@wf_vblank-ts-check,Fail kms_flip@wf_vblank-ts-check-interruptible,Fail kms_invalid_mode@int-max-clock,Fail -kms_plane_scaling@downscale-with-modifier-factor-0-25,Fail -kms_plane_scaling@downscale-with-rotation-factor-0-25,Fail -kms_plane_scaling@planes-upscale-20x20,Fail -kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-25,Fail -kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-5,Fail -kms_plane_scaling@planes-upscale-20x20-downscale-factor-0-75,Fail -kms_plane_scaling@upscale-with-modifier-20x20,Fail -kms_plane_scaling@upscale-with-modifier-factor-0-25,Fail -kms_plane_scaling@upscale-with-pixel-format-20x20,Fail -kms_plane_scaling@upscale-with-pixel-format-factor-0-25,Fail -kms_plane_scaling@upscale-with-rotation-20x20,Fail -kms_selftest@drm_format,Timeout -kms_selftest@drm_format_helper,Timeout +kms_lease@cursor-implicit-plane,Fail +kms_lease@lease-uevent,Fail +kms_lease@page-flip-implicit-plane,Fail +kms_lease@setcrtc-implicit-plane,Fail +kms_lease@simple-lease,Fail +kms_sequence@get-busy,Fail +kms_sequence@get-forked,Fail +kms_sequence@get-forked-busy,Fail +kms_sequence@get-idle,Fail +kms_sequence@queue-busy,Fail +kms_sequence@queue-idle,Fail kms_setmode@basic,Fail +kms_vblank@accuracy-idle,Fail kms_vblank@crtc-id,Fail kms_vblank@invalid,Fail -kms_vblank@pipe-A-accuracy-idle,Fail -kms_vblank@pipe-A-query-busy,Fail -kms_vblank@pipe-A-query-forked,Fail -kms_vblank@pipe-A-query-forked-busy,Fail -kms_vblank@pipe-A-query-idle,Fail -kms_vblank@pipe-A-ts-continuation-idle,Fail -kms_vblank@pipe-A-ts-continuation-modeset,Fail -kms_vblank@pipe-A-ts-continuation-suspend,Fail -kms_vblank@pipe-A-wait-busy,Fail -kms_vblank@pipe-A-wait-forked,Fail -kms_vblank@pipe-A-wait-forked-busy,Fail -kms_vblank@pipe-A-wait-idle,Fail +kms_vblank@query-busy,Fail +kms_vblank@query-forked,Fail +kms_vblank@query-forked-busy,Fail +kms_vblank@query-idle,Fail +kms_vblank@ts-continuation-dpms-rpm,Fail +kms_vblank@ts-continuation-dpms-suspend,Fail +kms_vblank@ts-continuation-idle,Fail +kms_vblank@ts-continuation-modeset,Fail +kms_vblank@ts-continuation-modeset-rpm,Fail +kms_vblank@ts-continuation-suspend,Fail +kms_vblank@wait-busy,Fail +kms_vblank@wait-forked,Fail +kms_vblank@wait-forked-busy,Fail +kms_vblank@wait-idle,Fail +perf@i915-ref-count,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt index 78be18174012..e0ca4fadb84f 100644 --- a/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt +++ b/drivers/gpu/drm/ci/xfails/virtio_gpu-none-skips.txt @@ -3,4 +3,22 @@ kms_cursor_legacy.* # Job just hangs without any output -kms_flip@flip-vs-suspend.*
\ No newline at end of file +kms_flip@flip-vs-suspend.* + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* +xe_.* + +# Currently fails and causes coverage loss for other tests +# since core_getversion also fails. +core_hotunplug.* diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt new file mode 100644 index 000000000000..691c383b21a0 --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/vkms-none-fails.txt @@ -0,0 +1,57 @@ +core_hotunplug@hotrebind,Fail +core_hotunplug@hotrebind-lateclose,Fail +core_hotunplug@hotreplug,Fail +core_hotunplug@hotreplug-lateclose,Fail +core_hotunplug@hotunbind-rebind,Fail +core_hotunplug@hotunplug-rescan,Fail +core_hotunplug@unbind-rebind,Fail +core_hotunplug@unplug-rescan,Fail +device_reset@cold-reset-bound,Fail +device_reset@reset-bound,Fail +device_reset@unbind-cold-reset-rebind,Fail +device_reset@unbind-reset-rebind,Fail +dumb_buffer@invalid-bpp,Fail +kms_content_protection@atomic,Crash +kms_content_protection@atomic-dpms,Crash +kms_content_protection@content-type-change,Crash +kms_content_protection@lic-type-0,Crash +kms_content_protection@lic-type-1,Crash +kms_content_protection@srm,Crash +kms_content_protection@type1,Crash +kms_content_protection@uevent,Crash +kms_cursor_crc@cursor-rapid-movement-128x128,Fail +kms_cursor_crc@cursor-rapid-movement-128x42,Fail +kms_cursor_crc@cursor-rapid-movement-256x256,Fail +kms_cursor_crc@cursor-rapid-movement-256x85,Fail +kms_cursor_crc@cursor-rapid-movement-32x10,Fail +kms_cursor_crc@cursor-rapid-movement-32x32,Fail +kms_cursor_crc@cursor-rapid-movement-512x170,Fail +kms_cursor_crc@cursor-rapid-movement-512x512,Fail +kms_cursor_crc@cursor-rapid-movement-64x21,Fail +kms_cursor_crc@cursor-rapid-movement-64x64,Fail +kms_cursor_legacy@basic-flip-before-cursor-atomic,Fail +kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail +kms_cursor_legacy@cursor-vs-flip-atomic,Fail +kms_cursor_legacy@cursor-vs-flip-legacy,Fail +kms_cursor_legacy@cursor-vs-flip-toggle,Fail +kms_cursor_legacy@cursor-vs-flip-varying-size,Fail +kms_cursor_legacy@flip-vs-cursor-atomic,Fail +kms_cursor_legacy@flip-vs-cursor-crc-atomic,Fail +kms_cursor_legacy@flip-vs-cursor-crc-legacy,Fail +kms_cursor_legacy@flip-vs-cursor-legacy,Fail +kms_flip@flip-vs-modeset-vs-hang,Fail +kms_flip@flip-vs-panning-vs-hang,Fail +kms_flip@flip-vs-suspend,Timeout +kms_flip@flip-vs-suspend-interruptible,Timeout +kms_flip@plain-flip-fb-recreate,Fail +kms_lease@lease-uevent,Fail +kms_pipe_crc_basic@nonblocking-crc,Fail +kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail +kms_writeback@writeback-check-output,Fail +kms_writeback@writeback-check-output-XRGB2101010,Fail +kms_writeback@writeback-fb-id,Fail +kms_writeback@writeback-fb-id-XRGB2101010,Fail +kms_writeback@writeback-invalid-parameters,Fail +kms_writeback@writeback-pixel-formats,Fail +perf@i915-ref-count,Fail +tools_test@tools_test,Fail diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt b/drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt new file mode 100644 index 000000000000..eeaa1d5825af --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/vkms-none-flakes.txt @@ -0,0 +1,69 @@ +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +kms_cursor_legacy@long-nonblocking-modeset-vs-cursor-atomic + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +kms_flip@basic-flip-vs-wf_vblank + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +kms_flip@flip-vs-expired-vblank-interruptible + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +kms_flip@flip-vs-wf_vblank-interruptible + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +kms_flip@plain-flip-fb-recreate-interruptible + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +kms_flip@plain-flip-ts-check + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +kms_flip@plain-flip-ts-check-interruptible + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +kms_flip@flip-vs-absolute-wf_vblank + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +kms_flip@flip-vs-absolute-wf_vblank-interruptible + +# Board Name: vkms +# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u +# Failure Rate: 50 +# IGT Version: 1.28-g0df7b9b97 +# Linux Version: 6.9.0-rc7 +kms_flip@flip-vs-blocking-wf-vblank diff --git a/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt b/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt new file mode 100644 index 000000000000..fd5d1271115f --- /dev/null +++ b/drivers/gpu/drm/ci/xfails/vkms-none-skips.txt @@ -0,0 +1,119 @@ +# keeps printing vkms_vblank_simulate: vblank timer overrun and never ends +kms_invalid_mode@int-max-clock + +# Kernel panic +kms_cursor_crc@cursor-rapid-movement-32x10 +# Oops: 0000 [#1] PREEMPT SMP NOPTI +# CPU: 0 PID: 2635 Comm: kworker/u8:13 Not tainted 6.9.0-rc7-g40935263a1fd #1 +# Hardware name: ChromiumOS crosvm, BIOS 0 +# Workqueue: vkms_composer vkms_composer_worker [vkms] +# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms] +# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34 +# RSP: 0018:ffffbb4700c17d58 EFLAGS: 00010246 +# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002 +# RDX: 0000000000000000 RSI: ffffa2ad0788c000 RDI: 00000000fff479a8 +# RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffffa2ad0bb14000 R11: 0000000000000000 R12: ffffa2ad03e21700 +# R13: 0000000000000003 R14: 0000000000000004 R15: 0000000000000000 +# FS: 0000000000000000(0000) GS:ffffa2ad2bc00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 0000000000000078 CR3: 000000010bd30000 CR4: 0000000000350ef0 +# Call Trace: +# <TASK> +# ? __die+0x1e/0x60 +# ? page_fault_oops+0x17b/0x490 +# ? exc_page_fault+0x6d/0x230 +# ? asm_exc_page_fault+0x26/0x30 +# ? compose_active_planes+0x1c7/0x4e0 [vkms] +# ? compose_active_planes+0x2a3/0x4e0 [vkms] +# ? srso_return_thunk+0x5/0x5f +# vkms_composer_worker+0x205/0x240 [vkms] +# process_one_work+0x1f4/0x6b0 +# ? lock_is_held_type+0x9e/0x110 +# worker_thread+0x17e/0x350 +# ? __pfx_worker_thread+0x10/0x10 +# kthread+0xce/0x100 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork+0x2f/0x50 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork_asm+0x1a/0x30 +# </TASK> +# Modules linked in: vkms +# CR2: 0000000000000078 +# ---[ end trace 0000000000000000 ]--- +# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms] +# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34 +# RSP: 0018:ffffbb4700c17d58 EFLAGS: 00010246 +# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002 +# RDX: 0000000000000000 RSI: ffffa2ad0788c000 RDI: 00000000fff479a8 +# RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffffa2ad0bb14000 R11: 0000000000000000 R12: ffffa2ad03e21700 +# R13: 0000000000000003 R14: 0000000000000004 R15: 0000000000000000 +# FS: 0000000000000000(0000) GS:ffffa2ad2bc00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + +kms_cursor_crc@cursor-rapid-movement-256x85 +# [drm:drm_crtc_add_crc_entry] *ERROR* Overflow of CRC buffer, userspace reads too slow. +# Oops: 0000 [#1] PREEMPT SMP NOPTI +# CPU: 1 PID: 10 Comm: kworker/u8:0 Not tainted 6.9.0-rc7-g646381cde463 #1 +# Hardware name: ChromiumOS crosvm, BIOS 0 +# Workqueue: vkms_composer vkms_composer_worker [vkms] +# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms] +# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34 +# RSP: 0018:ffffa7e980057d58 EFLAGS: 00010246 +# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002 +# RDX: 0000000000000000 RSI: ffff977987aa5c00 RDI: 000000001b43a85f +# RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff977981bf0000 R11: 0000000000000000 R12: ffff977989622590 +# R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000000 +# FS: 0000000000000000(0000) GS:ffff9779abd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 0000000000000078 CR3: 0000000109b38000 CR4: 0000000000350ef0 +# Call Trace: +# <TASK> +# ? __die+0x1e/0x60 +# ? page_fault_oops+0x17b/0x490 +# ? exc_page_fault+0x6d/0x230 +# ? asm_exc_page_fault+0x26/0x30 +# ? compose_active_planes+0x1c7/0x4e0 [vkms] +# ? compose_active_planes+0x2a3/0x4e0 [vkms] +# ? srso_return_thunk+0x5/0x5f +# vkms_composer_worker+0x205/0x240 [vkms] +# process_one_work+0x1f4/0x6b0 +# ? lock_is_held_type+0x9e/0x110 +# worker_thread+0x17e/0x350 +# ? __pfx_worker_thread+0x10/0x10 +# kthread+0xce/0x100 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork+0x2f/0x50 +# ? __pfx_kthread+0x10/0x10 +# ret_from_fork_asm+0x1a/0x30 +# </TASK> +# Modules linked in: vkms +# CR2: 0000000000000078 +# ---[ end trace 0000000000000000 ]--- +# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms] +# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34 +# RSP: 0018:ffffa7e980057d58 EFLAGS: 00010246 +# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002 +# RDX: 0000000000000000 RSI: ffff977987aa5c00 RDI: 000000001b43a85f +# RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000 +# R10: ffff977981bf0000 R11: 0000000000000000 R12: ffff977989622590 +# R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000000 +# FS: 0000000000000000(0000) GS:ffff9779abd00000(0000) knlGS:0000000000000000 +# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +# CR2: 0000000000000078 CR3: 0000000109b38000 CR4: 0000000000350ef0 + +# Skip driver specific tests +^amdgpu.* +msm_.* +nouveau_.* +panfrost_.* +^v3d.* +^vc4.* +^vmwgfx* + +# Skip intel specific tests +gem_.* +i915_.* +xe_.* diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig index 864a6488bfdf..479e62690d75 100644 --- a/drivers/gpu/drm/display/Kconfig +++ b/drivers/gpu/drm/display/Kconfig @@ -70,3 +70,10 @@ config DRM_DISPLAY_HDMI_HELPER depends on DRM_DISPLAY_HELPER help DRM display helpers for HDMI. + +config DRM_DISPLAY_HDMI_STATE_HELPER + bool + depends on DRM_DISPLAY_HELPER + select DRM_DISPLAY_HDMI_HELPER + help + DRM KMS state helpers for HDMI. diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile index 17d2cc73ff56..629df2f4d322 100644 --- a/drivers/gpu/drm/display/Makefile +++ b/drivers/gpu/drm/display/Makefile @@ -14,6 +14,8 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \ drm_hdmi_helper.o \ drm_scdc_helper.o +drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_STATE_HELPER) += \ + drm_hdmi_state_helper.o drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV) += drm_dp_aux_dev.o drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CEC) += drm_dp_cec.o diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c b/drivers/gpu/drm/display/drm_hdmi_helper.c index faf5e9efa7d3..74dd4d01dd9b 100644 --- a/drivers/gpu/drm/display/drm_hdmi_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_helper.c @@ -195,3 +195,64 @@ void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame, frame->itc = conn_state->content_type != DRM_MODE_CONTENT_TYPE_NO_DATA; } EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type); + +/** + * drm_hdmi_compute_mode_clock() - Computes the TMDS Character Rate + * @mode: Display mode to compute the clock for + * @bpc: Bits per character + * @fmt: Output Pixel Format used + * + * Returns the TMDS Character Rate for a given mode, bpc count and output format. + * + * RETURNS: + * The TMDS Character Rate, in Hertz, or 0 on error. + */ +unsigned long long +drm_hdmi_compute_mode_clock(const struct drm_display_mode *mode, + unsigned int bpc, enum hdmi_colorspace fmt) +{ + unsigned long long clock = mode->clock * 1000ULL; + unsigned int vic = drm_match_cea_mode(mode); + + /* + * CTA-861-G Spec, section 5.4 - Color Coding and Quantization + * mandates that VIC 1 always uses 8 bpc. + */ + if (vic == 1 && bpc != 8) + return 0; + + if (fmt == HDMI_COLORSPACE_YUV422) { + /* + * HDMI 1.0 Spec, section 6.5 - Pixel Encoding states that + * YUV422 sends 24 bits over three channels, with Cb and Cr + * components being sent on odd and even pixels, respectively. + * + * If fewer than 12 bpc are sent, data are left justified. + */ + if (bpc > 12) + return 0; + + /* + * HDMI 1.0 Spec, section 6.5 - Pixel Encoding + * specifies that YUV422 sends two 12-bits components over + * three TMDS channels per pixel clock, which is equivalent to + * three 8-bits components over three channels used by RGB as + * far as the clock rate goes. + */ + bpc = 8; + } + + /* + * HDMI 2.0 Spec, Section 7.1 - YCbCr 4:2:0 Pixel Encoding + * specifies that YUV420 encoding is carried at a TMDS Character Rate + * equal to half the pixel clock rate. + */ + if (fmt == HDMI_COLORSPACE_YUV420) + clock = clock / 2; + + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + clock = clock * 2; + + return DIV_ROUND_CLOSEST_ULL(clock * bpc, 8); +} +EXPORT_SYMBOL(drm_hdmi_compute_mode_clock); diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c new file mode 100644 index 000000000000..2dab3ad8ce64 --- /dev/null +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -0,0 +1,752 @@ +// SPDX-License-Identifier: MIT + +#include <drm/drm_atomic.h> +#include <drm/drm_connector.h> +#include <drm/drm_edid.h> +#include <drm/drm_print.h> + +#include <drm/display/drm_hdmi_helper.h> +#include <drm/display/drm_hdmi_state_helper.h> + +/** + * __drm_atomic_helper_connector_hdmi_reset() - Initializes all HDMI @drm_connector_state resources + * @connector: DRM connector + * @new_conn_state: connector state to reset + * + * Initializes all HDMI resources from a @drm_connector_state without + * actually allocating it. This is useful for HDMI drivers, in + * combination with __drm_atomic_helper_connector_reset() or + * drm_atomic_helper_connector_reset(). + */ +void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector, + struct drm_connector_state *new_conn_state) +{ + unsigned int max_bpc = connector->max_bpc; + + new_conn_state->max_bpc = max_bpc; + new_conn_state->max_requested_bpc = max_bpc; + new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO; +} +EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset); + +static const struct drm_display_mode * +connector_state_get_mode(const struct drm_connector_state *conn_state) +{ + struct drm_atomic_state *state; + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + + state = conn_state->state; + if (!state) + return NULL; + + crtc = conn_state->crtc; + if (!crtc) + return NULL; + + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + if (!crtc_state) + return NULL; + + return &crtc_state->mode; +} + +static bool hdmi_is_limited_range(const struct drm_connector *connector, + const struct drm_connector_state *conn_state) +{ + const struct drm_display_info *info = &connector->display_info; + const struct drm_display_mode *mode = + connector_state_get_mode(conn_state); + + /* + * The Broadcast RGB property only applies to RGB format, and + * i915 just assumes limited range for YCbCr output, so let's + * just do the same. + */ + if (conn_state->hdmi.output_format != HDMI_COLORSPACE_RGB) + return true; + + if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL) + return false; + + if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED) + return true; + + if (!info->is_hdmi) + return false; + + return drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED; +} + +static bool +sink_supports_format_bpc(const struct drm_connector *connector, + const struct drm_display_info *info, + const struct drm_display_mode *mode, + unsigned int format, unsigned int bpc) +{ + struct drm_device *dev = connector->dev; + u8 vic = drm_match_cea_mode(mode); + + /* + * CTA-861-F, section 5.4 - Color Coding & Quantization states + * that the bpc must be 8, 10, 12 or 16 except for the default + * 640x480 VIC1 where the value must be 8. + * + * The definition of default here is ambiguous but the spec + * refers to VIC1 being the default timing in several occasions + * so our understanding is that for the default timing (ie, + * VIC1), the bpc must be 8. + */ + if (vic == 1 && bpc != 8) { + drm_dbg_kms(dev, "VIC1 requires a bpc of 8, got %u\n", bpc); + return false; + } + + if (!info->is_hdmi && + (format != HDMI_COLORSPACE_RGB || bpc != 8)) { + drm_dbg_kms(dev, "DVI Monitors require an RGB output at 8 bpc\n"); + return false; + } + + if (!(connector->hdmi.supported_formats & BIT(format))) { + drm_dbg_kms(dev, "%s format unsupported by the connector.\n", + drm_hdmi_connector_get_output_format_name(format)); + return false; + } + + switch (format) { + case HDMI_COLORSPACE_RGB: + drm_dbg_kms(dev, "RGB Format, checking the constraints.\n"); + + /* + * In some cases, like when the EDID readout fails, or + * is not an HDMI compliant EDID for some reason, the + * color_formats field will be blank and not report any + * format supported. In such a case, assume that RGB is + * supported so we can keep things going and light up + * the display. + */ + if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) + drm_warn(dev, "HDMI Sink doesn't support RGB, something's wrong.\n"); + + if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { + drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); + return false; + } + + if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { + drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); + return false; + } + + drm_dbg_kms(dev, "RGB format supported in that configuration.\n"); + + return true; + + case HDMI_COLORSPACE_YUV420: + /* TODO: YUV420 is unsupported at the moment. */ + drm_dbg_kms(dev, "YUV420 format isn't supported yet.\n"); + return false; + + case HDMI_COLORSPACE_YUV422: + drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n"); + + if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { + drm_dbg_kms(dev, "Sink doesn't support YUV422.\n"); + return false; + } + + if (bpc > 12) { + drm_dbg_kms(dev, "YUV422 only supports 12 bpc or lower.\n"); + return false; + } + + /* + * HDMI Spec 1.3 - Section 6.5 Pixel Encodings and Color Depth + * states that Deep Color is not relevant for YUV422 so we + * don't need to check the Deep Color bits in the EDIDs here. + */ + + drm_dbg_kms(dev, "YUV422 format supported in that configuration.\n"); + + return true; + + case HDMI_COLORSPACE_YUV444: + drm_dbg_kms(dev, "YUV444 format, checking the constraints.\n"); + + if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) { + drm_dbg_kms(dev, "Sink doesn't support YUV444.\n"); + return false; + } + + if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) { + drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); + return false; + } + + if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) { + drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); + return false; + } + + drm_dbg_kms(dev, "YUV444 format supported in that configuration.\n"); + + return true; + } + + drm_dbg_kms(dev, "Unsupported pixel format.\n"); + return false; +} + +static enum drm_mode_status +hdmi_clock_valid(const struct drm_connector *connector, + const struct drm_display_mode *mode, + unsigned long long clock) +{ + const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; + const struct drm_display_info *info = &connector->display_info; + + if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000) + return MODE_CLOCK_HIGH; + + if (funcs && funcs->tmds_char_rate_valid) { + enum drm_mode_status status; + + status = funcs->tmds_char_rate_valid(connector, mode, clock); + if (status != MODE_OK) + return status; + } + + return MODE_OK; +} + +static int +hdmi_compute_clock(const struct drm_connector *connector, + struct drm_connector_state *conn_state, + const struct drm_display_mode *mode, + unsigned int bpc, enum hdmi_colorspace fmt) +{ + enum drm_mode_status status; + unsigned long long clock; + + clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt); + if (!clock) + return -EINVAL; + + status = hdmi_clock_valid(connector, mode, clock); + if (status != MODE_OK) + return -EINVAL; + + conn_state->hdmi.tmds_char_rate = clock; + + return 0; +} + +static bool +hdmi_try_format_bpc(const struct drm_connector *connector, + struct drm_connector_state *conn_state, + const struct drm_display_mode *mode, + unsigned int bpc, enum hdmi_colorspace fmt) +{ + const struct drm_display_info *info = &connector->display_info; + struct drm_device *dev = connector->dev; + int ret; + + drm_dbg_kms(dev, "Trying %s output format\n", + drm_hdmi_connector_get_output_format_name(fmt)); + + if (!sink_supports_format_bpc(connector, info, mode, fmt, bpc)) { + drm_dbg_kms(dev, "%s output format not supported with %u bpc\n", + drm_hdmi_connector_get_output_format_name(fmt), + bpc); + return false; + } + + ret = hdmi_compute_clock(connector, conn_state, mode, bpc, fmt); + if (ret) { + drm_dbg_kms(dev, "Couldn't compute clock for %s output format and %u bpc\n", + drm_hdmi_connector_get_output_format_name(fmt), + bpc); + return false; + } + + drm_dbg_kms(dev, "%s output format supported with %u (TMDS char rate: %llu Hz)\n", + drm_hdmi_connector_get_output_format_name(fmt), + bpc, conn_state->hdmi.tmds_char_rate); + + return true; +} + +static int +hdmi_compute_format(const struct drm_connector *connector, + struct drm_connector_state *conn_state, + const struct drm_display_mode *mode, + unsigned int bpc) +{ + struct drm_device *dev = connector->dev; + + /* + * TODO: Add support for YCbCr420 output for HDMI 2.0 capable + * devices, for modes that only support YCbCr420. + */ + if (hdmi_try_format_bpc(connector, conn_state, mode, bpc, HDMI_COLORSPACE_RGB)) { + conn_state->hdmi.output_format = HDMI_COLORSPACE_RGB; + return 0; + } + + drm_dbg_kms(dev, "Failed. No Format Supported for that bpc count.\n"); + + return -EINVAL; +} + +static int +hdmi_compute_config(const struct drm_connector *connector, + struct drm_connector_state *conn_state, + const struct drm_display_mode *mode) +{ + struct drm_device *dev = connector->dev; + unsigned int max_bpc = clamp_t(unsigned int, + conn_state->max_bpc, + 8, connector->max_bpc); + unsigned int bpc; + int ret; + + for (bpc = max_bpc; bpc >= 8; bpc -= 2) { + drm_dbg_kms(dev, "Trying with a %d bpc output\n", bpc); + + ret = hdmi_compute_format(connector, conn_state, mode, bpc); + if (ret) + continue; + + conn_state->hdmi.output_bpc = bpc; + + drm_dbg_kms(dev, + "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n", + mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), + conn_state->hdmi.output_bpc, + drm_hdmi_connector_get_output_format_name(conn_state->hdmi.output_format), + conn_state->hdmi.tmds_char_rate); + + return 0; + } + + return -EINVAL; +} + +static int hdmi_generate_avi_infoframe(const struct drm_connector *connector, + struct drm_connector_state *conn_state) +{ + const struct drm_display_mode *mode = + connector_state_get_mode(conn_state); + struct drm_connector_hdmi_infoframe *infoframe = + &conn_state->hdmi.infoframes.avi; + struct hdmi_avi_infoframe *frame = + &infoframe->data.avi; + bool is_limited_range = conn_state->hdmi.is_limited_range; + enum hdmi_quantization_range rgb_quant_range = + is_limited_range ? HDMI_QUANTIZATION_RANGE_LIMITED : HDMI_QUANTIZATION_RANGE_FULL; + int ret; + + ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, mode); + if (ret) + return ret; + + frame->colorspace = conn_state->hdmi.output_format; + + /* + * FIXME: drm_hdmi_avi_infoframe_quant_range() doesn't handle + * YUV formats at all at the moment, so if we ever support YUV + * formats this needs to be revised. + */ + drm_hdmi_avi_infoframe_quant_range(frame, connector, mode, rgb_quant_range); + drm_hdmi_avi_infoframe_colorimetry(frame, conn_state); + drm_hdmi_avi_infoframe_bars(frame, conn_state); + + infoframe->set = true; + + return 0; +} + +static int hdmi_generate_spd_infoframe(const struct drm_connector *connector, + struct drm_connector_state *conn_state) +{ + struct drm_connector_hdmi_infoframe *infoframe = + &conn_state->hdmi.infoframes.spd; + struct hdmi_spd_infoframe *frame = + &infoframe->data.spd; + int ret; + + ret = hdmi_spd_infoframe_init(frame, + connector->hdmi.vendor, + connector->hdmi.product); + if (ret) + return ret; + + frame->sdi = HDMI_SPD_SDI_PC; + + infoframe->set = true; + + return 0; +} + +static int hdmi_generate_hdr_infoframe(const struct drm_connector *connector, + struct drm_connector_state *conn_state) +{ + struct drm_connector_hdmi_infoframe *infoframe = + &conn_state->hdmi.infoframes.hdr_drm; + struct hdmi_drm_infoframe *frame = + &infoframe->data.drm; + int ret; + + if (connector->max_bpc < 10) + return 0; + + if (!conn_state->hdr_output_metadata) + return 0; + + ret = drm_hdmi_infoframe_set_hdr_metadata(frame, conn_state); + if (ret) + return ret; + + infoframe->set = true; + + return 0; +} + +static int hdmi_generate_hdmi_vendor_infoframe(const struct drm_connector *connector, + struct drm_connector_state *conn_state) +{ + const struct drm_display_info *info = &connector->display_info; + const struct drm_display_mode *mode = + connector_state_get_mode(conn_state); + struct drm_connector_hdmi_infoframe *infoframe = + &conn_state->hdmi.infoframes.hdmi; + struct hdmi_vendor_infoframe *frame = + &infoframe->data.vendor.hdmi; + int ret; + + if (!info->has_hdmi_infoframe) + return 0; + + ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, connector, mode); + if (ret) + return ret; + + infoframe->set = true; + + return 0; +} + +static int +hdmi_generate_infoframes(const struct drm_connector *connector, + struct drm_connector_state *conn_state) +{ + const struct drm_display_info *info = &connector->display_info; + int ret; + + if (!info->is_hdmi) + return 0; + + ret = hdmi_generate_avi_infoframe(connector, conn_state); + if (ret) + return ret; + + ret = hdmi_generate_spd_infoframe(connector, conn_state); + if (ret) + return ret; + + /* + * Audio Infoframes will be generated by ALSA, and updated by + * drm_atomic_helper_connector_hdmi_update_audio_infoframe(). + */ + + ret = hdmi_generate_hdr_infoframe(connector, conn_state); + if (ret) + return ret; + + ret = hdmi_generate_hdmi_vendor_infoframe(connector, conn_state); + if (ret) + return ret; + + return 0; +} + +/** + * drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector atomic state + * @connector: DRM Connector + * @state: the DRM State object + * + * Provides a default connector state check handler for HDMI connectors. + * Checks that a desired connector update is valid, and updates various + * fields of derived state. + * + * RETURNS: + * Zero on success, or an errno code otherwise. + */ +int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *old_conn_state = + drm_atomic_get_old_connector_state(state, connector); + struct drm_connector_state *new_conn_state = + drm_atomic_get_new_connector_state(state, connector); + const struct drm_display_mode *mode = + connector_state_get_mode(new_conn_state); + int ret; + + new_conn_state->hdmi.is_limited_range = hdmi_is_limited_range(connector, new_conn_state); + + ret = hdmi_compute_config(connector, new_conn_state, mode); + if (ret) + return ret; + + ret = hdmi_generate_infoframes(connector, new_conn_state); + if (ret) + return ret; + + if (old_conn_state->hdmi.broadcast_rgb != new_conn_state->hdmi.broadcast_rgb || + old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc || + old_conn_state->hdmi.output_format != new_conn_state->hdmi.output_format) { + struct drm_crtc *crtc = new_conn_state->crtc; + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + crtc_state->mode_changed = true; + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check); + +#define HDMI_MAX_INFOFRAME_SIZE 29 + +static int clear_device_infoframe(struct drm_connector *connector, + enum hdmi_infoframe_type type) +{ + const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; + struct drm_device *dev = connector->dev; + int ret; + + drm_dbg_kms(dev, "Clearing infoframe type 0x%x\n", type); + + if (!funcs || !funcs->clear_infoframe) { + drm_dbg_kms(dev, "Function not implemented, bailing.\n"); + return 0; + } + + ret = funcs->clear_infoframe(connector, type); + if (ret) { + drm_dbg_kms(dev, "Call failed: %d\n", ret); + return ret; + } + + return 0; +} + +static int clear_infoframe(struct drm_connector *connector, + struct drm_connector_hdmi_infoframe *old_frame) +{ + int ret; + + ret = clear_device_infoframe(connector, old_frame->data.any.type); + if (ret) + return ret; + + return 0; +} + +static int write_device_infoframe(struct drm_connector *connector, + union hdmi_infoframe *frame) +{ + const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; + struct drm_device *dev = connector->dev; + u8 buffer[HDMI_MAX_INFOFRAME_SIZE]; + int ret; + int len; + + drm_dbg_kms(dev, "Writing infoframe type %x\n", frame->any.type); + + if (!funcs || !funcs->write_infoframe) { + drm_dbg_kms(dev, "Function not implemented, bailing.\n"); + return -EINVAL; + } + + len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer)); + if (len < 0) + return len; + + ret = funcs->write_infoframe(connector, frame->any.type, buffer, len); + if (ret) { + drm_dbg_kms(dev, "Call failed: %d\n", ret); + return ret; + } + + return 0; +} + +static int write_infoframe(struct drm_connector *connector, + struct drm_connector_hdmi_infoframe *new_frame) +{ + int ret; + + ret = write_device_infoframe(connector, &new_frame->data); + if (ret) + return ret; + + return 0; +} + +static int write_or_clear_infoframe(struct drm_connector *connector, + struct drm_connector_hdmi_infoframe *old_frame, + struct drm_connector_hdmi_infoframe *new_frame) +{ + if (new_frame->set) + return write_infoframe(connector, new_frame); + + if (old_frame->set && !new_frame->set) + return clear_infoframe(connector, old_frame); + + return 0; +} + +/** + * drm_atomic_helper_connector_hdmi_update_infoframes - Update the Infoframes + * @connector: A pointer to the HDMI connector + * @state: The HDMI connector state to generate the infoframe from + * + * This function is meant for HDMI connector drivers to write their + * infoframes. It will typically be used in a + * @drm_connector_helper_funcs.atomic_enable implementation. + * + * Returns: + * Zero on success, error code on failure. + */ +int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *old_conn_state = + drm_atomic_get_old_connector_state(state, connector); + struct drm_connector_state *new_conn_state = + drm_atomic_get_new_connector_state(state, connector); + struct drm_display_info *info = &connector->display_info; + int ret; + + if (!info->is_hdmi) + return 0; + + mutex_lock(&connector->hdmi.infoframes.lock); + + ret = write_or_clear_infoframe(connector, + &old_conn_state->hdmi.infoframes.avi, + &new_conn_state->hdmi.infoframes.avi); + if (ret) + goto out; + + if (connector->hdmi.infoframes.audio.set) { + ret = write_infoframe(connector, + &connector->hdmi.infoframes.audio); + if (ret) + goto out; + } + + ret = write_or_clear_infoframe(connector, + &old_conn_state->hdmi.infoframes.hdr_drm, + &new_conn_state->hdmi.infoframes.hdr_drm); + if (ret) + goto out; + + ret = write_or_clear_infoframe(connector, + &old_conn_state->hdmi.infoframes.spd, + &new_conn_state->hdmi.infoframes.spd); + if (ret) + goto out; + + if (info->has_hdmi_infoframe) { + ret = write_or_clear_infoframe(connector, + &old_conn_state->hdmi.infoframes.hdmi, + &new_conn_state->hdmi.infoframes.hdmi); + if (ret) + goto out; + } + +out: + mutex_unlock(&connector->hdmi.infoframes.lock); + return ret; +} +EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_infoframes); + +/** + * drm_atomic_helper_connector_hdmi_update_audio_infoframe - Update the Audio Infoframe + * @connector: A pointer to the HDMI connector + * @frame: A pointer to the audio infoframe to write + * + * This function is meant for HDMI connector drivers to update their + * audio infoframe. It will typically be used in one of the ALSA hooks + * (most likely prepare). + * + * Returns: + * Zero on success, error code on failure. + */ +int +drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *connector, + struct hdmi_audio_infoframe *frame) +{ + struct drm_connector_hdmi_infoframe *infoframe = + &connector->hdmi.infoframes.audio; + struct drm_display_info *info = &connector->display_info; + int ret; + + if (!info->is_hdmi) + return 0; + + mutex_lock(&connector->hdmi.infoframes.lock); + + memcpy(&infoframe->data, frame, sizeof(infoframe->data)); + infoframe->set = true; + + ret = write_infoframe(connector, infoframe); + + mutex_unlock(&connector->hdmi.infoframes.lock); + + return ret; +} +EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_audio_infoframe); + +/** + * drm_atomic_helper_connector_hdmi_disable_audio_infoframe - Stop sending the Audio Infoframe + * @connector: A pointer to the HDMI connector + * + * This function is meant for HDMI connector drivers to stop sending their + * audio infoframe. It will typically be used in one of the ALSA hooks + * (most likely shutdown). + * + * Returns: + * Zero on success, error code on failure. + */ +int +drm_atomic_helper_connector_hdmi_disable_audio_infoframe(struct drm_connector *connector) +{ + struct drm_connector_hdmi_infoframe *infoframe = + &connector->hdmi.infoframes.audio; + struct drm_display_info *info = &connector->display_info; + int ret; + + if (!info->is_hdmi) + return 0; + + mutex_lock(&connector->hdmi.infoframes.lock); + + infoframe->set = false; + + ret = clear_infoframe(connector, infoframe); + + memset(&infoframe->data, 0, sizeof(infoframe->data)); + + mutex_unlock(&connector->hdmi.infoframes.lock); + + return ret; +} +EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_disable_audio_infoframe); diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index a91737adf8e7..07b4b394e3bf 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1143,6 +1143,17 @@ static void drm_atomic_connector_print_state(struct drm_printer *p, drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc); drm_printf(p, "\tcolorspace=%s\n", drm_get_colorspace_name(state->colorspace)); + if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || + connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) { + drm_printf(p, "\tbroadcast_rgb=%s\n", + drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb)); + drm_printf(p, "\tis_limited_range=%c\n", state->hdmi.is_limited_range ? 'y' : 'n'); + drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc); + drm_printf(p, "\toutput_format=%s\n", + drm_hdmi_connector_get_output_format_name(state->hdmi.output_format)); + drm_printf(p, "\ttmds_char_rate=%llu\n", state->hdmi.tmds_char_rate); + } + if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) if (state->writeback_job && state->writeback_job->fb) drm_printf(p, "\tfb=%d\n", state->writeback_job->fb->base.id); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index fc16fddee5c5..22bbb2d83e30 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -776,6 +776,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, state->max_requested_bpc = val; } else if (property == connector->privacy_screen_sw_state_property) { state->privacy_screen_sw_state = val; + } else if (property == connector->broadcast_rgb_property) { + state->hdmi.broadcast_rgb = val; } else if (connector->funcs->atomic_set_property) { return connector->funcs->atomic_set_property(connector, state, property, val); @@ -859,6 +861,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = state->max_requested_bpc; } else if (property == connector->privacy_screen_sw_state_property) { *val = state->privacy_screen_sw_state; + } else if (property == connector->broadcast_rgb_property) { + *val = state->hdmi.broadcast_rgb; } else if (connector->funcs->atomic_get_property) { return connector->funcs->atomic_get_property(connector, state, property, val); diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 28abe9aa99ca..d44f055dbe3e 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -353,13 +353,8 @@ err_reset_bridge: bridge->encoder = NULL; list_del(&bridge->chain_node); -#ifdef CONFIG_OF DRM_ERROR("failed to attach bridge %pOF to encoder %s: %d\n", bridge->of_node, encoder->name, ret); -#else - DRM_ERROR("failed to attach bridge to encoder %s: %d\n", - encoder->name, ret); -#endif return ret; } @@ -473,43 +468,6 @@ void drm_bridge_detach(struct drm_bridge *bridge) */ /** - * drm_bridge_chain_mode_fixup - fixup proposed mode for all bridges in the - * encoder chain - * @bridge: bridge control structure - * @mode: desired mode to be set for the bridge - * @adjusted_mode: updated mode that works for this bridge - * - * Calls &drm_bridge_funcs.mode_fixup for all the bridges in the - * encoder chain, starting from the first bridge to the last. - * - * Note: the bridge passed should be the one closest to the encoder - * - * RETURNS: - * true on success, false on failure - */ -bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_encoder *encoder; - - if (!bridge) - return true; - - encoder = bridge->encoder; - list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { - if (!bridge->funcs->mode_fixup) - continue; - - if (!bridge->funcs->mode_fixup(bridge, mode, adjusted_mode)) - return false; - } - - return true; -} -EXPORT_SYMBOL(drm_bridge_chain_mode_fixup); - -/** * drm_bridge_chain_mode_valid - validate the mode against all bridges in the * encoder chain. * @bridge: bridge control structure diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c index 982552c9f92c..0869b663f17e 100644 --- a/drivers/gpu/drm/drm_bridge_connector.c +++ b/drivers/gpu/drm/drm_bridge_connector.c @@ -15,8 +15,10 @@ #include <drm/drm_connector.h> #include <drm/drm_device.h> #include <drm/drm_edid.h> +#include <drm/drm_managed.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_probe_helper.h> +#include <drm/display/drm_hdmi_state_helper.h> /** * DOC: overview @@ -86,6 +88,13 @@ struct drm_bridge_connector { * connector modes detection, if any (see &DRM_BRIDGE_OP_MODES). */ struct drm_bridge *bridge_modes; + /** + * @bridge_hdmi: + * + * The bridge in the chain that implements necessary support for the + * HDMI connector infrastructure, if any (see &DRM_BRIDGE_OP_HDMI). + */ + struct drm_bridge *bridge_hdmi; }; #define to_drm_bridge_connector(x) \ @@ -193,19 +202,6 @@ drm_bridge_connector_detect(struct drm_connector *connector, bool force) return status; } -static void drm_bridge_connector_destroy(struct drm_connector *connector) -{ - struct drm_bridge_connector *bridge_connector = - to_drm_bridge_connector(connector); - - drm_connector_unregister(connector); - drm_connector_cleanup(connector); - - fwnode_handle_put(connector->fwnode); - - kfree(bridge_connector); -} - static void drm_bridge_connector_debugfs_init(struct drm_connector *connector, struct dentry *root) { @@ -224,7 +220,6 @@ static const struct drm_connector_funcs drm_bridge_connector_funcs = { .reset = drm_atomic_helper_connector_reset, .detect = drm_bridge_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_bridge_connector_destroy, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .debugfs_init = drm_bridge_connector_debugfs_init, @@ -300,6 +295,60 @@ static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs .disable_hpd = drm_bridge_connector_disable_hpd, }; +static enum drm_mode_status +drm_bridge_connector_tmds_char_rate_valid(const struct drm_connector *connector, + const struct drm_display_mode *mode, + unsigned long long tmds_rate) +{ + struct drm_bridge_connector *bridge_connector = + to_drm_bridge_connector(connector); + struct drm_bridge *bridge; + + bridge = bridge_connector->bridge_hdmi; + if (!bridge) + return MODE_ERROR; + + if (bridge->funcs->hdmi_tmds_char_rate_valid) + return bridge->funcs->hdmi_tmds_char_rate_valid(bridge, mode, tmds_rate); + else + return MODE_OK; +} + +static int drm_bridge_connector_clear_infoframe(struct drm_connector *connector, + enum hdmi_infoframe_type type) +{ + struct drm_bridge_connector *bridge_connector = + to_drm_bridge_connector(connector); + struct drm_bridge *bridge; + + bridge = bridge_connector->bridge_hdmi; + if (!bridge) + return -EINVAL; + + return bridge->funcs->hdmi_clear_infoframe(bridge, type); +} + +static int drm_bridge_connector_write_infoframe(struct drm_connector *connector, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len) +{ + struct drm_bridge_connector *bridge_connector = + to_drm_bridge_connector(connector); + struct drm_bridge *bridge; + + bridge = bridge_connector->bridge_hdmi; + if (!bridge) + return -EINVAL; + + return bridge->funcs->hdmi_write_infoframe(bridge, type, buffer, len); +} + +static const struct drm_connector_hdmi_funcs drm_bridge_connector_hdmi_funcs = { + .tmds_char_rate_valid = drm_bridge_connector_tmds_char_rate_valid, + .clear_infoframe = drm_bridge_connector_clear_infoframe, + .write_infoframe = drm_bridge_connector_write_infoframe, +}; + /* ----------------------------------------------------------------------------- * Bridge Connector Initialisation */ @@ -325,10 +374,12 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, struct drm_connector *connector; struct i2c_adapter *ddc = NULL; struct drm_bridge *bridge, *panel_bridge = NULL; + unsigned int supported_formats = BIT(HDMI_COLORSPACE_RGB); + unsigned int max_bpc = 8; int connector_type; int ret; - bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL); + bridge_connector = drmm_kzalloc(drm, sizeof(*bridge_connector), GFP_KERNEL); if (!bridge_connector) return ERR_PTR(-ENOMEM); @@ -361,6 +412,20 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, bridge_connector->bridge_detect = bridge; if (bridge->ops & DRM_BRIDGE_OP_MODES) bridge_connector->bridge_modes = bridge; + if (bridge->ops & DRM_BRIDGE_OP_HDMI) { + if (bridge_connector->bridge_hdmi) + return ERR_PTR(-EBUSY); + if (!bridge->funcs->hdmi_write_infoframe || + !bridge->funcs->hdmi_clear_infoframe) + return ERR_PTR(-EINVAL); + + bridge_connector->bridge_hdmi = bridge; + + if (bridge->supported_formats) + supported_formats = bridge->supported_formats; + if (bridge->max_bpc) + max_bpc = bridge->max_bpc; + } if (!drm_bridge_get_next_bridge(bridge)) connector_type = bridge->type; @@ -383,7 +448,17 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, return ERR_PTR(-EINVAL); } - ret = drm_connector_init_with_ddc(drm, connector, + if (bridge_connector->bridge_hdmi) + ret = drmm_connector_hdmi_init(drm, connector, + bridge_connector->bridge_hdmi->vendor, + bridge_connector->bridge_hdmi->product, + &drm_bridge_connector_funcs, + &drm_bridge_connector_hdmi_funcs, + connector_type, ddc, + supported_formats, + max_bpc); + else + ret = drmm_connector_init(drm, connector, &drm_bridge_connector_funcs, connector_type, ddc); if (ret) { diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 4d2df7f64dc5..ab6ab7ff7ea8 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -278,6 +278,7 @@ static int __drm_connector_init(struct drm_device *dev, INIT_LIST_HEAD(&connector->modes); mutex_init(&connector->mutex); mutex_init(&connector->edid_override_mutex); + mutex_init(&connector->hdmi.infoframes.lock); connector->edid_blob_ptr = NULL; connector->epoch_counter = 0; connector->tile_blob_ptr = NULL; @@ -453,6 +454,86 @@ int drmm_connector_init(struct drm_device *dev, EXPORT_SYMBOL(drmm_connector_init); /** + * drmm_connector_hdmi_init - Init a preallocated HDMI connector + * @dev: DRM device + * @connector: A pointer to the HDMI connector to init + * @vendor: HDMI Controller Vendor name + * @product: HDMI Controller Product name + * @funcs: callbacks for this connector + * @hdmi_funcs: HDMI-related callbacks for this connector + * @connector_type: user visible type of the connector + * @ddc: optional pointer to the associated ddc adapter + * @supported_formats: Bitmask of @hdmi_colorspace listing supported output formats + * @max_bpc: Maximum bits per char the HDMI connector supports + * + * Initialises a preallocated HDMI connector. Connectors can be + * subclassed as part of driver connector objects. + * + * Cleanup is automatically handled with a call to + * drm_connector_cleanup() in a DRM-managed action. + * + * The connector structure should be allocated with drmm_kzalloc(). + * + * Returns: + * Zero on success, error code on failure. + */ +int drmm_connector_hdmi_init(struct drm_device *dev, + struct drm_connector *connector, + const char *vendor, const char *product, + const struct drm_connector_funcs *funcs, + const struct drm_connector_hdmi_funcs *hdmi_funcs, + int connector_type, + struct i2c_adapter *ddc, + unsigned long supported_formats, + unsigned int max_bpc) +{ + int ret; + + if (!vendor || !product) + return -EINVAL; + + if ((strlen(vendor) > DRM_CONNECTOR_HDMI_VENDOR_LEN) || + (strlen(product) > DRM_CONNECTOR_HDMI_PRODUCT_LEN)) + return -EINVAL; + + if (!(connector_type == DRM_MODE_CONNECTOR_HDMIA || + connector_type == DRM_MODE_CONNECTOR_HDMIB)) + return -EINVAL; + + if (!supported_formats || !(supported_formats & BIT(HDMI_COLORSPACE_RGB))) + return -EINVAL; + + if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12)) + return -EINVAL; + + ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc); + if (ret) + return ret; + + connector->hdmi.supported_formats = supported_formats; + strtomem_pad(connector->hdmi.vendor, vendor, 0); + strtomem_pad(connector->hdmi.product, product, 0); + + /* + * drm_connector_attach_max_bpc_property() requires the + * connector to have a state. + */ + if (connector->funcs->reset) + connector->funcs->reset(connector); + + drm_connector_attach_max_bpc_property(connector, 8, max_bpc); + connector->max_bpc = max_bpc; + + if (max_bpc > 8) + drm_connector_attach_hdr_output_metadata_property(connector); + + connector->hdmi.funcs = hdmi_funcs; + + return 0; +} +EXPORT_SYMBOL(drmm_connector_hdmi_init); + +/** * drm_connector_attach_edid_property - attach edid property. * @connector: the connector * @@ -584,6 +665,7 @@ void drm_connector_cleanup(struct drm_connector *connector) connector->funcs->atomic_destroy_state(connector, connector->state); + mutex_destroy(&connector->hdmi.infoframes.lock); mutex_destroy(&connector->mutex); memset(connector, 0, sizeof(*connector)); @@ -1005,6 +1087,7 @@ static const struct drm_prop_enum_list drm_tv_mode_enum_list[] = { { DRM_MODE_TV_MODE_PAL_M, "PAL-M" }, { DRM_MODE_TV_MODE_PAL_N, "PAL-N" }, { DRM_MODE_TV_MODE_SECAM, "SECAM" }, + { DRM_MODE_TV_MODE_MONOCHROME, "Mono" }, }; DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list) @@ -1144,6 +1227,53 @@ static const u32 dp_colorspaces = BIT(DRM_MODE_COLORIMETRY_BT2020_CYCC) | BIT(DRM_MODE_COLORIMETRY_BT2020_YCC); +static const struct drm_prop_enum_list broadcast_rgb_names[] = { + { DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic" }, + { DRM_HDMI_BROADCAST_RGB_FULL, "Full" }, + { DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235" }, +}; + +/* + * drm_hdmi_connector_get_broadcast_rgb_name - Return a string for HDMI connector RGB broadcast selection + * @broadcast_rgb: Broadcast RGB selection to compute name of + * + * Returns: the name of the Broadcast RGB selection, or NULL if the type + * is not valid. + */ +const char * +drm_hdmi_connector_get_broadcast_rgb_name(enum drm_hdmi_broadcast_rgb broadcast_rgb) +{ + if (broadcast_rgb >= ARRAY_SIZE(broadcast_rgb_names)) + return NULL; + + return broadcast_rgb_names[broadcast_rgb].name; +} +EXPORT_SYMBOL(drm_hdmi_connector_get_broadcast_rgb_name); + +static const char * const output_format_str[] = { + [HDMI_COLORSPACE_RGB] = "RGB", + [HDMI_COLORSPACE_YUV420] = "YUV 4:2:0", + [HDMI_COLORSPACE_YUV422] = "YUV 4:2:2", + [HDMI_COLORSPACE_YUV444] = "YUV 4:4:4", +}; + +/* + * drm_hdmi_connector_get_output_format_name() - Return a string for HDMI connector output format + * @fmt: Output format to compute name of + * + * Returns: the name of the output format, or NULL if the type is not + * valid. + */ +const char * +drm_hdmi_connector_get_output_format_name(enum hdmi_colorspace fmt) +{ + if (fmt >= ARRAY_SIZE(output_format_str)) + return NULL; + + return output_format_str[fmt]; +} +EXPORT_SYMBOL(drm_hdmi_connector_get_output_format_name); + /** * DOC: standard connector properties * @@ -1616,6 +1746,38 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property); /** * DOC: HDMI connector properties * + * Broadcast RGB (HDMI specific) + * Indicates the Quantization Range (Full vs Limited) used. The color + * processing pipeline will be adjusted to match the value of the + * property, and the Infoframes will be generated and sent accordingly. + * + * This property is only relevant if the HDMI output format is RGB. If + * it's one of the YCbCr variant, it will be ignored. + * + * The CRTC attached to the connector must be configured by user-space to + * always produce full-range pixels. + * + * The value of this property can be one of the following: + * + * Automatic: + * The quantization range is selected automatically based on the + * mode according to the HDMI specifications (HDMI 1.4b - Section + * 6.6 - Video Quantization Ranges). + * + * Full: + * Full quantization range is forced. + * + * Limited 16:235: + * Limited quantization range is forced. Unlike the name suggests, + * this works for any number of bits-per-component. + * + * Property values other than Automatic can result in colors being off (if + * limited is selected but the display expects full), or a black screen + * (if full is selected but the display expects limited). + * + * Drivers can set up this property by calling + * drm_connector_attach_broadcast_rgb_property(). + * * content type (HDMI specific): * Indicates content type setting to be used in HDMI infoframes to indicate * content type for the external device, so that it adjusts its display @@ -1697,6 +1859,12 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property); * TV Mode is CCIR System B (aka 625-lines) together with * the SECAM Color Encoding. * + * Mono: + * + * Use timings appropriate to the DRM mode, including + * equalizing pulses for a 525-line or 625-line mode, + * with no pedestal or color encoding. + * * Drivers can set up this property by calling * drm_mode_create_tv_properties(). */ @@ -2479,6 +2647,39 @@ int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *conn EXPORT_SYMBOL(drm_connector_attach_hdr_output_metadata_property); /** + * drm_connector_attach_broadcast_rgb_property - attach "Broadcast RGB" property + * @connector: connector to attach the property on. + * + * This is used to add support for forcing the RGB range on a connector + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_attach_broadcast_rgb_property(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_property *prop; + + prop = connector->broadcast_rgb_property; + if (!prop) { + prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, + "Broadcast RGB", + broadcast_rgb_names, + ARRAY_SIZE(broadcast_rgb_names)); + if (!prop) + return -EINVAL; + + connector->broadcast_rgb_property = prop; + } + + drm_object_attach_property(&connector->base, prop, + DRM_HDMI_BROADCAST_RGB_AUTO); + + return 0; +} +EXPORT_SYMBOL(drm_connector_attach_broadcast_rgb_property); + +/** * drm_connector_attach_colorspace_property - attach "Colorspace" property * @connector: connector to attach the property on. * diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 25aaae937ceb..20e9d7b206a2 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -303,6 +303,8 @@ const u8 *drm_edid_find_extension(const struct drm_edid *drm_edid, int ext_id, int *ext_index); void drm_edid_cta_sad_get(const struct cea_sad *cta_sad, u8 *sad); void drm_edid_cta_sad_set(struct cea_sad *cta_sad, const u8 *sad); +ssize_t drm_edid_connector_property_show(struct drm_connector *connector, + char *buf, loff_t off, size_t count); /* drm_edid_load.c */ #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 08fcefd804bc..6b239a24f1df 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -520,6 +520,156 @@ static const struct file_operations drm_connector_fops = { .write = connector_write }; +#define HDMI_MAX_INFOFRAME_SIZE 29 + +static ssize_t +audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) +{ + struct drm_connector_hdmi_infoframe *infoframe; + struct drm_connector *connector; + union hdmi_infoframe *frame; + u8 buf[HDMI_INFOFRAME_SIZE(AUDIO)]; + ssize_t len = 0; + + connector = filp->private_data; + mutex_lock(&connector->hdmi.infoframes.lock); + + infoframe = &connector->hdmi.infoframes.audio; + if (!infoframe->set) + goto out; + + frame = &infoframe->data; + len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); + if (len < 0) + goto out; + + len = simple_read_from_buffer(ubuf, count, ppos, buf, len); + +out: + mutex_unlock(&connector->hdmi.infoframes.lock); + return len; +} + +static const struct file_operations audio_infoframe_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = audio_infoframe_read, +}; + +static int create_hdmi_audio_infoframe_file(struct drm_connector *connector, + struct dentry *parent) +{ + struct dentry *file; + + file = debugfs_create_file("audio", 0400, parent, connector, &audio_infoframe_fops); + if (IS_ERR(file)) + return PTR_ERR(file); + + return 0; +} + +#define DEFINE_INFOFRAME_FILE(_f) \ +static ssize_t _f##_read_infoframe(struct file *filp, \ + char __user *ubuf, \ + size_t count, \ + loff_t *ppos) \ +{ \ + struct drm_connector_hdmi_infoframe *infoframe; \ + struct drm_connector_state *conn_state; \ + struct drm_connector *connector; \ + union hdmi_infoframe *frame; \ + struct drm_device *dev; \ + u8 buf[HDMI_MAX_INFOFRAME_SIZE]; \ + ssize_t len = 0; \ + \ + connector = filp->private_data; \ + dev = connector->dev; \ + \ + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); \ + \ + conn_state = connector->state; \ + infoframe = &conn_state->hdmi.infoframes._f; \ + if (!infoframe->set) \ + goto out; \ + \ + frame = &infoframe->data; \ + len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); \ + if (len < 0) \ + goto out; \ + \ + len = simple_read_from_buffer(ubuf, count, ppos, buf, len); \ + \ +out: \ + drm_modeset_unlock(&dev->mode_config.connection_mutex); \ + return len; \ +} \ +\ +static const struct file_operations _f##_infoframe_fops = { \ + .owner = THIS_MODULE, \ + .open = simple_open, \ + .read = _f##_read_infoframe, \ +}; \ +\ +static int create_hdmi_## _f ## _infoframe_file(struct drm_connector *connector, \ + struct dentry *parent) \ +{ \ + struct dentry *file; \ + \ + file = debugfs_create_file(#_f, 0400, parent, connector, &_f ## _infoframe_fops); \ + if (IS_ERR(file)) \ + return PTR_ERR(file); \ + \ + return 0; \ +} + +DEFINE_INFOFRAME_FILE(avi); +DEFINE_INFOFRAME_FILE(hdmi); +DEFINE_INFOFRAME_FILE(hdr_drm); +DEFINE_INFOFRAME_FILE(spd); + +static int create_hdmi_infoframe_files(struct drm_connector *connector, + struct dentry *parent) +{ + int ret; + + ret = create_hdmi_audio_infoframe_file(connector, parent); + if (ret) + return ret; + + ret = create_hdmi_avi_infoframe_file(connector, parent); + if (ret) + return ret; + + ret = create_hdmi_hdmi_infoframe_file(connector, parent); + if (ret) + return ret; + + ret = create_hdmi_hdr_drm_infoframe_file(connector, parent); + if (ret) + return ret; + + ret = create_hdmi_spd_infoframe_file(connector, parent); + if (ret) + return ret; + + return 0; +} + +static void hdmi_debugfs_add(struct drm_connector *connector) +{ + struct dentry *dir; + + if (!(connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || + connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)) + return; + + dir = debugfs_create_dir("infoframes", connector->debugfs_entry); + if (IS_ERR(dir)) + return; + + create_hdmi_infoframe_files(connector, dir); +} + void drm_debugfs_connector_add(struct drm_connector *connector) { struct drm_device *dev = connector->dev; @@ -547,6 +697,8 @@ void drm_debugfs_connector_add(struct drm_connector *connector) debugfs_create_file("output_bpc", 0444, root, connector, &output_bpc_fops); + hdmi_debugfs_add(connector); + if (connector->funcs->debugfs_init) connector->funcs->debugfs_init(connector, root); } @@ -597,10 +749,10 @@ static int bridges_show(struct seq_file *m, void *data) drm_printf(&p, "\ttype: [%d] %s\n", bridge->type, drm_get_connector_type_name(bridge->type)); -#ifdef CONFIG_OF + if (bridge->of_node) drm_printf(&p, "\tOF: %pOFfc\n", bridge->of_node); -#endif + drm_printf(&p, "\tops: [0x%x]", bridge->ops); if (bridge->ops & DRM_BRIDGE_OP_DETECT) drm_puts(&p, " detect"); @@ -610,6 +762,8 @@ static int bridges_show(struct seq_file *m, void *data) drm_puts(&p, " hpd"); if (bridge->ops & DRM_BRIDGE_OP_MODES) drm_puts(&p, " modes"); + if (bridge->ops & DRM_BRIDGE_OP_HDMI) + drm_puts(&p, " hdmi"); drm_puts(&p, "\n"); } diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 535b624d4c9d..93543071a500 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -346,7 +346,7 @@ void drm_minor_release(struct drm_minor *minor) * if (ret) * return ret; * - * drm_fbdev_generic_setup(drm, 32); + * drm_fbdev_{...}_setup(drm, 32); * * return 0; * } @@ -947,9 +947,9 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) } drm_panic_register(dev); - DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", + DRM_INFO("Initialized %s %d.%d.%d for %s on minor %d\n", driver->name, driver->major, driver->minor, - driver->patchlevel, driver->date, + driver->patchlevel, dev->dev ? dev_name(dev->dev) : "virtual device", dev->primary ? dev->primary->index : dev->accel->index); diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 4f54c91b31b2..f68a41eeb1fa 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2465,34 +2465,6 @@ fail: } /** - * drm_do_get_edid - get EDID data using a custom EDID block read function - * @connector: connector we're probing - * @read_block: EDID block read function - * @context: private data passed to the block read function - * - * When the I2C adapter connected to the DDC bus is hidden behind a device that - * exposes a different interface to read EDID blocks this function can be used - * to get EDID data using a custom block read function. - * - * As in the general case the DDC bus is accessible by the kernel at the I2C - * level, drivers must make all reasonable efforts to expose it as an I2C - * adapter and use drm_get_edid() instead of abusing this function. - * - * The EDID may be overridden using debugfs override_edid or firmware EDID - * (drm_edid_load_firmware() and drm.edid_firmware parameter), in this priority - * order. Having either of them bypasses actual EDID reads. - * - * Return: Pointer to valid EDID or NULL if we couldn't find any. - */ -struct edid *drm_do_get_edid(struct drm_connector *connector, - read_block_fn read_block, - void *context) -{ - return _drm_do_get_edid(connector, read_block, context, NULL); -} -EXPORT_SYMBOL_GPL(drm_do_get_edid); - -/** * drm_edid_raw - Get a pointer to the raw EDID data. * @drm_edid: drm_edid container * @@ -6969,6 +6941,39 @@ out: return ret; } +/* For sysfs edid show implementation */ +ssize_t drm_edid_connector_property_show(struct drm_connector *connector, + char *buf, loff_t off, size_t count) +{ + const void *edid; + size_t size; + ssize_t ret = 0; + + mutex_lock(&connector->dev->mode_config.mutex); + + if (!connector->edid_blob_ptr) + goto unlock; + + edid = connector->edid_blob_ptr->data; + size = connector->edid_blob_ptr->length; + if (!edid) + goto unlock; + + if (off >= size) + goto unlock; + + if (off + count > size) + count = size - off; + + memcpy(buf, edid + off, count); + + ret = count; +unlock: + mutex_unlock(&connector->dev->mode_config.mutex); + + return ret; +} + /** * drm_edid_connector_update - Update connector information from EDID * @connector: Connector diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index d612133e2cf7..e2e19f49342e 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -85,12 +85,8 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); * The fb helper functions are useful to provide an fbdev on top of a drm kernel * mode setting driver. They can be used mostly independently from the crtc * helper functions used by many drivers to implement the kernel mode setting - * interfaces. - * - * Drivers that support a dumb buffer with a virtual address and mmap support, - * should try out the generic fbdev emulation using drm_fbdev_generic_setup(). - * It will automatically set up deferred I/O if the driver requires a shadow - * buffer. + * interfaces. Drivers that use one of the shared memory managers, TTM, SHMEM, + * DMA, should instead use the corresponding fbdev emulation. * * Existing fbdev implementations should restore the fbdev console by using * drm_fb_helper_lastclose() as their &drm_driver.lastclose callback. @@ -126,9 +122,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); * atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io * callback it will also schedule dirty_work with the damage collected from the * mmap page writes. - * - * Deferred I/O is not compatible with SHMEM. Such drivers should request an - * fbdev shadow buffer and call drm_fbdev_generic_setup() instead. */ static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/drm_fbdev_dma.c b/drivers/gpu/drm/drm_fbdev_dma.c index 6c9427bb4053..97ef6300d47e 100644 --- a/drivers/gpu/drm/drm_fbdev_dma.c +++ b/drivers/gpu/drm/drm_fbdev_dma.c @@ -4,6 +4,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_drv.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_dma_helper.h> @@ -35,6 +36,22 @@ static int drm_fbdev_dma_fb_release(struct fb_info *info, int user) return 0; } +FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(drm_fbdev_dma, + drm_fb_helper_damage_range, + drm_fb_helper_damage_area); + +static int drm_fbdev_dma_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + struct drm_fb_helper *fb_helper = info->par; + struct drm_framebuffer *fb = fb_helper->fb; + struct drm_gem_dma_object *dma = drm_fb_dma_get_gem_obj(fb, 0); + + if (!dma->map_noncoherent) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + return fb_deferred_io_mmap(info, vma); +} + static void drm_fbdev_dma_fb_destroy(struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; @@ -42,6 +59,7 @@ static void drm_fbdev_dma_fb_destroy(struct fb_info *info) if (!fb_helper->dev) return; + fb_deferred_io_cleanup(info); drm_fb_helper_fini(fb_helper); drm_client_buffer_vunmap(fb_helper->buffer); @@ -51,20 +69,13 @@ static void drm_fbdev_dma_fb_destroy(struct fb_info *info) kfree(fb_helper); } -static int drm_fbdev_dma_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - struct drm_fb_helper *fb_helper = info->par; - - return drm_gem_prime_mmap(fb_helper->buffer->gem, vma); -} - static const struct fb_ops drm_fbdev_dma_fb_ops = { .owner = THIS_MODULE, .fb_open = drm_fbdev_dma_fb_open, .fb_release = drm_fbdev_dma_fb_release, - __FB_DEFAULT_DMAMEM_OPS_RDWR, + __FB_DEFAULT_DEFERRED_OPS_RDWR(drm_fbdev_dma), DRM_FB_HELPER_DEFAULT_OPS, - __FB_DEFAULT_DMAMEM_OPS_DRAW, + __FB_DEFAULT_DEFERRED_OPS_DRAW(drm_fbdev_dma), .fb_mmap = drm_fbdev_dma_fb_mmap, .fb_destroy = drm_fbdev_dma_fb_destroy, }; @@ -98,10 +109,6 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper, dma_obj = to_drm_gem_dma_obj(buffer->gem); fb = buffer->fb; - if (drm_WARN_ON(dev, fb->funcs->dirty)) { - ret = -ENODEV; /* damage handling not supported; use generic emulation */ - goto err_drm_client_buffer_delete; - } ret = drm_client_buffer_vmap(buffer, &map); if (ret) { @@ -112,7 +119,7 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper, } fb_helper->buffer = buffer; - fb_helper->fb = buffer->fb; + fb_helper->fb = fb; info = drm_fb_helper_alloc_info(fb_helper); if (IS_ERR(info)) { @@ -133,8 +140,19 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper, info->fix.smem_start = page_to_phys(virt_to_page(info->screen_buffer)); info->fix.smem_len = info->screen_size; + /* deferred I/O */ + fb_helper->fbdefio.delay = HZ / 20; + fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io; + + info->fbdefio = &fb_helper->fbdefio; + ret = fb_deferred_io_init(info); + if (ret) + goto err_drm_fb_helper_release_info; + return 0; +err_drm_fb_helper_release_info: + drm_fb_helper_release_info(fb_helper); err_drm_client_buffer_vunmap: fb_helper->fb = NULL; fb_helper->buffer = NULL; @@ -144,8 +162,28 @@ err_drm_client_buffer_delete: return ret; } +static int drm_fbdev_dma_helper_fb_dirty(struct drm_fb_helper *helper, + struct drm_clip_rect *clip) +{ + struct drm_device *dev = helper->dev; + int ret; + + /* Call damage handlers only if necessary */ + if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2)) + return 0; + + if (helper->fb->funcs->dirty) { + ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1); + if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret)) + return ret; + } + + return 0; +} + static const struct drm_fb_helper_funcs drm_fbdev_dma_helper_funcs = { .fb_probe = drm_fbdev_dma_helper_fb_probe, + .fb_dirty = drm_fbdev_dma_helper_fb_dirty, }; /* diff --git a/drivers/gpu/drm/drm_fbdev_shmem.c b/drivers/gpu/drm/drm_fbdev_shmem.c new file mode 100644 index 000000000000..0c785007f11b --- /dev/null +++ b/drivers/gpu/drm/drm_fbdev_shmem.c @@ -0,0 +1,317 @@ +// SPDX-License-Identifier: MIT + +#include <linux/fb.h> + +#include <drm/drm_crtc_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_framebuffer.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_shmem_helper.h> + +#include <drm/drm_fbdev_shmem.h> + +/* + * struct fb_ops + */ + +static int drm_fbdev_shmem_fb_open(struct fb_info *info, int user) +{ + struct drm_fb_helper *fb_helper = info->par; + + /* No need to take a ref for fbcon because it unbinds on unregister */ + if (user && !try_module_get(fb_helper->dev->driver->fops->owner)) + return -ENODEV; + + return 0; +} + +static int drm_fbdev_shmem_fb_release(struct fb_info *info, int user) +{ + struct drm_fb_helper *fb_helper = info->par; + + if (user) + module_put(fb_helper->dev->driver->fops->owner); + + return 0; +} + +FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(drm_fbdev_shmem, + drm_fb_helper_damage_range, + drm_fb_helper_damage_area); + +static int drm_fbdev_shmem_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + struct drm_fb_helper *fb_helper = info->par; + struct drm_framebuffer *fb = fb_helper->fb; + struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0); + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); + + if (shmem->map_wc) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + return fb_deferred_io_mmap(info, vma); +} + +static void drm_fbdev_shmem_fb_destroy(struct fb_info *info) +{ + struct drm_fb_helper *fb_helper = info->par; + + if (!fb_helper->dev) + return; + + fb_deferred_io_cleanup(info); + drm_fb_helper_fini(fb_helper); + + drm_client_buffer_vunmap(fb_helper->buffer); + drm_client_framebuffer_delete(fb_helper->buffer); + drm_client_release(&fb_helper->client); + drm_fb_helper_unprepare(fb_helper); + kfree(fb_helper); +} + +static const struct fb_ops drm_fbdev_shmem_fb_ops = { + .owner = THIS_MODULE, + .fb_open = drm_fbdev_shmem_fb_open, + .fb_release = drm_fbdev_shmem_fb_release, + __FB_DEFAULT_DEFERRED_OPS_RDWR(drm_fbdev_shmem), + DRM_FB_HELPER_DEFAULT_OPS, + __FB_DEFAULT_DEFERRED_OPS_DRAW(drm_fbdev_shmem), + .fb_mmap = drm_fbdev_shmem_fb_mmap, + .fb_destroy = drm_fbdev_shmem_fb_destroy, +}; + +static struct page *drm_fbdev_shmem_get_page(struct fb_info *info, unsigned long offset) +{ + struct drm_fb_helper *fb_helper = info->par; + struct drm_framebuffer *fb = fb_helper->fb; + struct drm_gem_object *obj = drm_gem_fb_get_obj(fb, 0); + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); + unsigned int i = offset >> PAGE_SHIFT; + struct page *page; + + if (fb_WARN_ON_ONCE(info, offset > obj->size)) + return NULL; + + page = shmem->pages[i]; // protected by active vmap + if (page) + get_page(page); + fb_WARN_ON_ONCE(info, !page); + + return page; +} + +/* + * struct drm_fb_helper + */ + +static int drm_fbdev_shmem_helper_fb_probe(struct drm_fb_helper *fb_helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct drm_client_dev *client = &fb_helper->client; + struct drm_device *dev = fb_helper->dev; + struct drm_client_buffer *buffer; + struct drm_gem_shmem_object *shmem; + struct drm_framebuffer *fb; + struct fb_info *info; + u32 format; + struct iosys_map map; + int ret; + + drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n", + sizes->surface_width, sizes->surface_height, + sizes->surface_bpp); + + format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp, sizes->surface_depth); + buffer = drm_client_framebuffer_create(client, sizes->surface_width, + sizes->surface_height, format); + if (IS_ERR(buffer)) + return PTR_ERR(buffer); + shmem = to_drm_gem_shmem_obj(buffer->gem); + + fb = buffer->fb; + + ret = drm_client_buffer_vmap(buffer, &map); + if (ret) { + goto err_drm_client_buffer_delete; + } else if (drm_WARN_ON(dev, map.is_iomem)) { + ret = -ENODEV; /* I/O memory not supported; use generic emulation */ + goto err_drm_client_buffer_delete; + } + + fb_helper->buffer = buffer; + fb_helper->fb = fb; + + info = drm_fb_helper_alloc_info(fb_helper); + if (IS_ERR(info)) { + ret = PTR_ERR(info); + goto err_drm_client_buffer_vunmap; + } + + drm_fb_helper_fill_info(info, fb_helper, sizes); + + info->fbops = &drm_fbdev_shmem_fb_ops; + + /* screen */ + info->flags |= FBINFO_VIRTFB; /* system memory */ + if (!shmem->map_wc) + info->flags |= FBINFO_READS_FAST; /* signal caching */ + info->screen_size = sizes->surface_height * fb->pitches[0]; + info->screen_buffer = map.vaddr; + info->fix.smem_len = info->screen_size; + + /* deferred I/O */ + fb_helper->fbdefio.delay = HZ / 20; + fb_helper->fbdefio.get_page = drm_fbdev_shmem_get_page; + fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io; + + info->fbdefio = &fb_helper->fbdefio; + ret = fb_deferred_io_init(info); + if (ret) + goto err_drm_fb_helper_release_info; + + return 0; + +err_drm_fb_helper_release_info: + drm_fb_helper_release_info(fb_helper); +err_drm_client_buffer_vunmap: + fb_helper->fb = NULL; + fb_helper->buffer = NULL; + drm_client_buffer_vunmap(buffer); +err_drm_client_buffer_delete: + drm_client_framebuffer_delete(buffer); + return ret; +} + +static int drm_fbdev_shmem_helper_fb_dirty(struct drm_fb_helper *helper, + struct drm_clip_rect *clip) +{ + struct drm_device *dev = helper->dev; + int ret; + + /* Call damage handlers only if necessary */ + if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2)) + return 0; + + if (helper->fb->funcs->dirty) { + ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1); + if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret)) + return ret; + } + + return 0; +} + +static const struct drm_fb_helper_funcs drm_fbdev_shmem_helper_funcs = { + .fb_probe = drm_fbdev_shmem_helper_fb_probe, + .fb_dirty = drm_fbdev_shmem_helper_fb_dirty, +}; + +/* + * struct drm_client_funcs + */ + +static void drm_fbdev_shmem_client_unregister(struct drm_client_dev *client) +{ + struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); + + if (fb_helper->info) { + drm_fb_helper_unregister_info(fb_helper); + } else { + drm_client_release(&fb_helper->client); + drm_fb_helper_unprepare(fb_helper); + kfree(fb_helper); + } +} + +static int drm_fbdev_shmem_client_restore(struct drm_client_dev *client) +{ + drm_fb_helper_lastclose(client->dev); + + return 0; +} + +static int drm_fbdev_shmem_client_hotplug(struct drm_client_dev *client) +{ + struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); + struct drm_device *dev = client->dev; + int ret; + + if (dev->fb_helper) + return drm_fb_helper_hotplug_event(dev->fb_helper); + + ret = drm_fb_helper_init(dev, fb_helper); + if (ret) + goto err_drm_err; + + if (!drm_drv_uses_atomic_modeset(dev)) + drm_helper_disable_unused_functions(dev); + + ret = drm_fb_helper_initial_config(fb_helper); + if (ret) + goto err_drm_fb_helper_fini; + + return 0; + +err_drm_fb_helper_fini: + drm_fb_helper_fini(fb_helper); +err_drm_err: + drm_err(dev, "fbdev-shmem: Failed to setup emulation (ret=%d)\n", ret); + return ret; +} + +static const struct drm_client_funcs drm_fbdev_shmem_client_funcs = { + .owner = THIS_MODULE, + .unregister = drm_fbdev_shmem_client_unregister, + .restore = drm_fbdev_shmem_client_restore, + .hotplug = drm_fbdev_shmem_client_hotplug, +}; + +/** + * drm_fbdev_shmem_setup() - Setup fbdev emulation for GEM SHMEM helpers + * @dev: DRM device + * @preferred_bpp: Preferred bits per pixel for the device. + * 32 is used if this is zero. + * + * This function sets up fbdev emulation for GEM DMA drivers that support + * dumb buffers with a virtual address and that can be mmap'ed. + * drm_fbdev_shmem_setup() shall be called after the DRM driver registered + * the new DRM device with drm_dev_register(). + * + * Restore, hotplug events and teardown are all taken care of. Drivers that do + * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves. + * Simple drivers might use drm_mode_config_helper_suspend(). + * + * This function is safe to call even when there are no connectors present. + * Setup will be retried on the next hotplug event. + * + * The fbdev is destroyed by drm_dev_unregister(). + */ +void drm_fbdev_shmem_setup(struct drm_device *dev, unsigned int preferred_bpp) +{ + struct drm_fb_helper *fb_helper; + int ret; + + drm_WARN(dev, !dev->registered, "Device has not been registered.\n"); + drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n"); + + fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL); + if (!fb_helper) + return; + drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fbdev_shmem_helper_funcs); + + ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_shmem_client_funcs); + if (ret) { + drm_err(dev, "Failed to register client: %d\n", ret); + goto err_drm_client_init; + } + + drm_client_register(&fb_helper->client); + + return; + +err_drm_client_init: + drm_fb_helper_unprepare(fb_helper); + kfree(fb_helper); +} +EXPORT_SYMBOL(drm_fbdev_shmem_setup); diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_ttm.c index 97e579c33d84..bb7898cd7dc6 100644 --- a/drivers/gpu/drm/drm_fbdev_generic.c +++ b/drivers/gpu/drm/drm_fbdev_ttm.c @@ -10,10 +10,10 @@ #include <drm/drm_gem.h> #include <drm/drm_print.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_ttm.h> /* @user: 1=userspace, 0=fbcon */ -static int drm_fbdev_generic_fb_open(struct fb_info *info, int user) +static int drm_fbdev_ttm_fb_open(struct fb_info *info, int user) { struct drm_fb_helper *fb_helper = info->par; @@ -24,7 +24,7 @@ static int drm_fbdev_generic_fb_open(struct fb_info *info, int user) return 0; } -static int drm_fbdev_generic_fb_release(struct fb_info *info, int user) +static int drm_fbdev_ttm_fb_release(struct fb_info *info, int user) { struct drm_fb_helper *fb_helper = info->par; @@ -34,11 +34,11 @@ static int drm_fbdev_generic_fb_release(struct fb_info *info, int user) return 0; } -FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(drm_fbdev_generic, +FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(drm_fbdev_ttm, drm_fb_helper_damage_range, drm_fb_helper_damage_area); -static void drm_fbdev_generic_fb_destroy(struct fb_info *info) +static void drm_fbdev_ttm_fb_destroy(struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; void *shadow = info->screen_buffer; @@ -56,19 +56,19 @@ static void drm_fbdev_generic_fb_destroy(struct fb_info *info) kfree(fb_helper); } -static const struct fb_ops drm_fbdev_generic_fb_ops = { +static const struct fb_ops drm_fbdev_ttm_fb_ops = { .owner = THIS_MODULE, - .fb_open = drm_fbdev_generic_fb_open, - .fb_release = drm_fbdev_generic_fb_release, - FB_DEFAULT_DEFERRED_OPS(drm_fbdev_generic), + .fb_open = drm_fbdev_ttm_fb_open, + .fb_release = drm_fbdev_ttm_fb_release, + FB_DEFAULT_DEFERRED_OPS(drm_fbdev_ttm), DRM_FB_HELPER_DEFAULT_OPS, - .fb_destroy = drm_fbdev_generic_fb_destroy, + .fb_destroy = drm_fbdev_ttm_fb_destroy, }; /* * This function uses the client API to create a framebuffer backed by a dumb buffer. */ -static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper, +static int drm_fbdev_ttm_helper_fb_probe(struct drm_fb_helper *fb_helper, struct drm_fb_helper_surface_size *sizes) { struct drm_client_dev *client = &fb_helper->client; @@ -108,7 +108,7 @@ static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper, drm_fb_helper_fill_info(info, fb_helper, sizes); - info->fbops = &drm_fbdev_generic_fb_ops; + info->fbops = &drm_fbdev_ttm_fb_ops; /* screen */ info->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST; @@ -137,9 +137,9 @@ err_drm_client_framebuffer_delete: return ret; } -static void drm_fbdev_generic_damage_blit_real(struct drm_fb_helper *fb_helper, - struct drm_clip_rect *clip, - struct iosys_map *dst) +static void drm_fbdev_ttm_damage_blit_real(struct drm_fb_helper *fb_helper, + struct drm_clip_rect *clip, + struct iosys_map *dst) { struct drm_framebuffer *fb = fb_helper->fb; size_t offset = clip->y1 * fb->pitches[0]; @@ -176,8 +176,8 @@ static void drm_fbdev_generic_damage_blit_real(struct drm_fb_helper *fb_helper, } } -static int drm_fbdev_generic_damage_blit(struct drm_fb_helper *fb_helper, - struct drm_clip_rect *clip) +static int drm_fbdev_ttm_damage_blit(struct drm_fb_helper *fb_helper, + struct drm_clip_rect *clip) { struct drm_client_buffer *buffer = fb_helper->buffer; struct iosys_map map, dst; @@ -201,7 +201,7 @@ static int drm_fbdev_generic_damage_blit(struct drm_fb_helper *fb_helper, goto out; dst = map; - drm_fbdev_generic_damage_blit_real(fb_helper, clip, &dst); + drm_fbdev_ttm_damage_blit_real(fb_helper, clip, &dst); drm_client_buffer_vunmap_local(buffer); @@ -211,8 +211,8 @@ out: return ret; } -static int drm_fbdev_generic_helper_fb_dirty(struct drm_fb_helper *helper, - struct drm_clip_rect *clip) +static int drm_fbdev_ttm_helper_fb_dirty(struct drm_fb_helper *helper, + struct drm_clip_rect *clip) { struct drm_device *dev = helper->dev; int ret; @@ -221,7 +221,7 @@ static int drm_fbdev_generic_helper_fb_dirty(struct drm_fb_helper *helper, if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2)) return 0; - ret = drm_fbdev_generic_damage_blit(helper, clip); + ret = drm_fbdev_ttm_damage_blit(helper, clip); if (drm_WARN_ONCE(dev, ret, "Damage blitter failed: ret=%d\n", ret)) return ret; @@ -234,12 +234,12 @@ static int drm_fbdev_generic_helper_fb_dirty(struct drm_fb_helper *helper, return 0; } -static const struct drm_fb_helper_funcs drm_fbdev_generic_helper_funcs = { - .fb_probe = drm_fbdev_generic_helper_fb_probe, - .fb_dirty = drm_fbdev_generic_helper_fb_dirty, +static const struct drm_fb_helper_funcs drm_fbdev_ttm_helper_funcs = { + .fb_probe = drm_fbdev_ttm_helper_fb_probe, + .fb_dirty = drm_fbdev_ttm_helper_fb_dirty, }; -static void drm_fbdev_generic_client_unregister(struct drm_client_dev *client) +static void drm_fbdev_ttm_client_unregister(struct drm_client_dev *client) { struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); @@ -252,14 +252,14 @@ static void drm_fbdev_generic_client_unregister(struct drm_client_dev *client) } } -static int drm_fbdev_generic_client_restore(struct drm_client_dev *client) +static int drm_fbdev_ttm_client_restore(struct drm_client_dev *client) { drm_fb_helper_lastclose(client->dev); return 0; } -static int drm_fbdev_generic_client_hotplug(struct drm_client_dev *client) +static int drm_fbdev_ttm_client_hotplug(struct drm_client_dev *client) { struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); struct drm_device *dev = client->dev; @@ -284,32 +284,32 @@ static int drm_fbdev_generic_client_hotplug(struct drm_client_dev *client) err_drm_fb_helper_fini: drm_fb_helper_fini(fb_helper); err_drm_err: - drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret); + drm_err(dev, "fbdev: Failed to setup emulation (ret=%d)\n", ret); return ret; } -static const struct drm_client_funcs drm_fbdev_generic_client_funcs = { +static const struct drm_client_funcs drm_fbdev_ttm_client_funcs = { .owner = THIS_MODULE, - .unregister = drm_fbdev_generic_client_unregister, - .restore = drm_fbdev_generic_client_restore, - .hotplug = drm_fbdev_generic_client_hotplug, + .unregister = drm_fbdev_ttm_client_unregister, + .restore = drm_fbdev_ttm_client_restore, + .hotplug = drm_fbdev_ttm_client_hotplug, }; /** - * drm_fbdev_generic_setup() - Setup generic fbdev emulation + * drm_fbdev_ttm_setup() - Setup fbdev emulation for TTM-based drivers * @dev: DRM device * @preferred_bpp: Preferred bits per pixel for the device. * - * This function sets up generic fbdev emulation for drivers that supports + * This function sets up fbdev emulation for TTM-based drivers that support * dumb buffers with a virtual address and that can be mmap'ed. - * drm_fbdev_generic_setup() shall be called after the DRM driver registered + * drm_fbdev_ttm_setup() shall be called after the DRM driver registered * the new DRM device with drm_dev_register(). * * Restore, hotplug events and teardown are all taken care of. Drivers that do * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves. * Simple drivers might use drm_mode_config_helper_suspend(). * - * In order to provide fixed mmap-able memory ranges, generic fbdev emulation + * In order to provide fixed mmap-able memory ranges, fbdev emulation * uses a shadow buffer in system memory. The implementation blits the shadow * fbdev buffer onto the real buffer in regular intervals. * @@ -318,7 +318,7 @@ static const struct drm_client_funcs drm_fbdev_generic_client_funcs = { * * The fbdev is destroyed by drm_dev_unregister(). */ -void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp) +void drm_fbdev_ttm_setup(struct drm_device *dev, unsigned int preferred_bpp) { struct drm_fb_helper *fb_helper; int ret; @@ -329,9 +329,9 @@ void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp) fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL); if (!fb_helper) return; - drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fbdev_generic_helper_funcs); + drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fbdev_ttm_helper_funcs); - ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_generic_client_funcs); + ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_ttm_client_funcs); if (ret) { drm_err(dev, "Failed to register client: %d\n", ret); goto err_drm_client_init; @@ -346,4 +346,4 @@ err_drm_client_init: kfree(fb_helper); return; } -EXPORT_SYMBOL(drm_fbdev_generic_setup); +EXPORT_SYMBOL(drm_fbdev_ttm_setup); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index e368fc084c77..51f39912866f 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -529,9 +529,10 @@ int drm_version(struct drm_device *dev, void *data, version->version_patchlevel = dev->driver->patchlevel; err = drm_copy_field(version->name, &version->name_len, dev->driver->name); + + /* Driver date is deprecated. Userspace expects a non-empty string. */ if (!err) - err = drm_copy_field(version->date, &version->date_len, - dev->driver->date); + err = drm_copy_field(version->date, &version->date_len, "0"); if (!err) err = drm_copy_field(version->desc, &version->desc_len, dev->driver->desc); diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index daac649aabdb..34bca7567576 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -206,6 +206,7 @@ int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer * struct drm_rect *clip, bool swap, struct drm_format_conv_state *fmtcnv_state) { + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst); int ret; @@ -222,8 +223,18 @@ int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer * else drm_fb_memcpy(&dst_map, NULL, src, fb, clip); break; + case DRM_FORMAT_RGB888: + drm_fb_memcpy(&dst_map, NULL, src, fb, clip); + break; case DRM_FORMAT_XRGB8888: - drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, fmtcnv_state, swap); + switch (dbidev->pixel_format) { + case DRM_FORMAT_RGB565: + drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, fmtcnv_state, swap); + break; + case DRM_FORMAT_RGB888: + drm_fb_xrgb8888_to_rgb888(&dst_map, NULL, src, fb, clip, fmtcnv_state); + break; + } break; default: drm_err_once(fb->dev, "Format is not supported: %p4cc\n", @@ -260,9 +271,11 @@ static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb, struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); unsigned int height = rect->y2 - rect->y1; unsigned int width = rect->x2 - rect->x1; + const struct drm_format_info *dst_format; struct mipi_dbi *dbi = &dbidev->dbi; bool swap = dbi->swap_bytes; int ret = 0; + size_t len; bool full; void *tr; @@ -283,8 +296,13 @@ static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb, mipi_dbi_set_window_address(dbidev, rect->x1, rect->x2 - 1, rect->y1, rect->y2 - 1); - ret = mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START, tr, - width * height * 2); + if (fb->format->format == DRM_FORMAT_XRGB8888) + dst_format = drm_format_info(dbidev->pixel_format); + else + dst_format = fb->format; + len = drm_format_info_min_pitch(dst_format, 0, width) * height; + + ret = mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START, tr, len); err_msg: if (ret) drm_err_once(fb->dev, "Failed to update display %d\n", ret); @@ -572,7 +590,7 @@ static const uint32_t mipi_dbi_formats[] = { * has one fixed &drm_display_mode which is rotated according to @rotation. * This mode is used to set the mode config min/max width/height properties. * - * Use mipi_dbi_dev_init() if you don't need custom formats. + * Use mipi_dbi_dev_init() if you want native RGB565 and emulated XRGB8888 format. * * Note: * Some of the helper functions expects RGB565 to be the default format and the @@ -631,6 +649,9 @@ int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev, drm->mode_config.min_height = dbidev->mode.vdisplay; drm->mode_config.max_height = dbidev->mode.vdisplay; dbidev->rotation = rotation; + dbidev->pixel_format = formats[0]; + if (formats[0] == DRM_FORMAT_RGB888) + dbidev->dbi.write_memory_bpw = 8; DRM_DEBUG_KMS("rotation = %u\n", rotation); @@ -824,15 +845,6 @@ u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len) } EXPORT_SYMBOL(mipi_dbi_spi_cmd_max_speed); -static bool mipi_dbi_machine_little_endian(void) -{ -#if defined(__LITTLE_ENDIAN) - return true; -#else - return false; -#endif -} - /* * MIPI DBI Type C Option 1 * @@ -855,7 +867,7 @@ static int mipi_dbi_spi1e_transfer(struct mipi_dbi *dbi, int dc, const void *buf, size_t len, unsigned int bpw) { - bool swap_bytes = (bpw == 16 && mipi_dbi_machine_little_endian()); + bool swap_bytes = (bpw == 16); size_t chunk, max_chunk = dbi->tx_buf9_len; struct spi_device *spi = dbi->spi; struct spi_transfer tr = { @@ -1004,7 +1016,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc, size_t chunk = min(len, max_chunk); unsigned int i; - if (bpw == 16 && mipi_dbi_machine_little_endian()) { + if (bpw == 16) { for (i = 0; i < (chunk * 2); i += 2) { dst16[i] = *src16 >> 8; dst16[i + 1] = *src16++ & 0xFF; @@ -1088,7 +1100,7 @@ static int mipi_dbi_typec1_command_read(struct mipi_dbi *dbi, u8 *cmd, static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd, u8 *parameters, size_t num) { - unsigned int bpw = (*cmd == MIPI_DCS_WRITE_MEMORY_START) ? 16 : 8; + unsigned int bpw = 8; int ret; if (mipi_dbi_command_is_read(dbi, *cmd)) @@ -1100,6 +1112,9 @@ static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd, if (ret || !num) return ret; + if (*cmd == MIPI_DCS_WRITE_MEMORY_START) + bpw = dbi->write_memory_bpw; + return mipi_dbi_spi1_transfer(dbi, 1, parameters, num, bpw); } @@ -1193,8 +1208,8 @@ static int mipi_dbi_typec3_command(struct mipi_dbi *dbi, u8 *cmd, if (ret || !num) return ret; - if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !dbi->swap_bytes) - bpw = 16; + if (*cmd == MIPI_DCS_WRITE_MEMORY_START) + bpw = dbi->write_memory_bpw; spi_bus_lock(spi->controller); gpiod_set_value_cansleep(dbi->dc, 1); @@ -1218,11 +1233,23 @@ static int mipi_dbi_typec3_command(struct mipi_dbi *dbi, u8 *cmd, * If @dc is set, a Type C Option 3 interface is assumed, if not * Type C Option 1. * - * If the SPI master driver doesn't support the necessary bits per word, - * the following transformation is used: + * If the command is %MIPI_DCS_WRITE_MEMORY_START and the pixel format is RGB565, endianness has + * to be taken into account. The MIPI DBI serial interface is big endian and framebuffers are + * assumed stored in memory as little endian (%DRM_FORMAT_BIG_ENDIAN is not supported). * - * - 9-bit: reorder buffer as 9x 8-bit words, padded with no-op command. - * - 16-bit: if big endian send as 8-bit, if little endian swap bytes + * This is how endianness is handled: + * + * Option 1 (D/C as a bit): The buffer is sent on the wire byte by byte so the 16-bit buffer is + * byteswapped before transfer. + * + * Option 3 (D/C as a gpio): If the SPI controller supports 16 bits per word the buffer can be + * sent as-is. If not the caller is responsible for swapping the bytes + * before calling mipi_dbi_command_buf() and the buffer is sent 8 bpw. + * + * This handling is optimised for %DRM_FORMAT_RGB565 framebuffers. + * + * If the interface is Option 1 and the SPI controller doesn't support 9 bits per word, + * the buffer is sent as 9x 8-bit words, padded with MIPI DCS no-op commands if necessary. * * Returns: * Zero on success, negative error code on failure. @@ -1253,12 +1280,15 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi, dbi->spi = spi; dbi->read_commands = mipi_dbi_dcs_read_commands; + dbi->write_memory_bpw = 16; if (dc) { dbi->command = mipi_dbi_typec3_command; dbi->dc = dc; - if (mipi_dbi_machine_little_endian() && !spi_is_bpw_supported(spi, 16)) + if (!spi_is_bpw_supported(spi, 16)) { + dbi->write_memory_bpw = 8; dbi->swap_bytes = true; + } } else { dbi->command = mipi_dbi_typec1_command; dbi->tx_buf9_len = SZ_16K; @@ -1475,4 +1505,5 @@ EXPORT_SYMBOL(mipi_dbi_debugfs_init); #endif +MODULE_DESCRIPTION("MIPI Display Bus Interface (DBI) LCD controller support"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 795001bb7ff1..a471c46f5ca6 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -765,6 +765,62 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload, EXPORT_SYMBOL(mipi_dsi_generic_write); /** + * mipi_dsi_generic_write_chatty() - mipi_dsi_generic_write() w/ an error log + * @dsi: DSI peripheral device + * @payload: buffer containing the payload + * @size: size of payload buffer + * + * Like mipi_dsi_generic_write() but includes a dev_err() + * call for you and returns 0 upon success, not the number of bytes sent. + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_generic_write_chatty(struct mipi_dsi_device *dsi, + const void *payload, size_t size) +{ + struct device *dev = &dsi->dev; + ssize_t ret; + + ret = mipi_dsi_generic_write(dsi, payload, size); + if (ret < 0) { + dev_err(dev, "sending generic data %*ph failed: %zd\n", + (int)size, payload, ret); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_generic_write_chatty); + +/** + * mipi_dsi_generic_write_multi() - mipi_dsi_generic_write_chatty() w/ accum_err + * @ctx: Context for multiple DSI transactions + * @payload: buffer containing the payload + * @size: size of payload buffer + * + * Like mipi_dsi_generic_write_chatty() but deals with errors in a way that + * makes it convenient to make several calls in a row. + */ +void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx, + const void *payload, size_t size) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t ret; + + if (ctx->accum_err) + return; + + ret = mipi_dsi_generic_write(dsi, payload, size); + if (ret < 0) { + ctx->accum_err = ret; + dev_err(dev, "sending generic data %*ph failed: %d\n", + (int)size, payload, ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_generic_write_multi); + +/** * mipi_dsi_generic_read() - receive data using a generic read packet * @dsi: DSI peripheral device * @params: buffer containing the request parameters @@ -853,6 +909,62 @@ ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi, EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer); /** + * mipi_dsi_dcs_write_buffer_chatty - mipi_dsi_dcs_write_buffer() w/ an error log + * @dsi: DSI peripheral device + * @data: buffer containing data to be transmitted + * @len: size of transmission buffer + * + * Like mipi_dsi_dcs_write_buffer() but includes a dev_err() + * call for you and returns 0 upon success, not the number of bytes sent. + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_write_buffer_chatty(struct mipi_dsi_device *dsi, + const void *data, size_t len) +{ + struct device *dev = &dsi->dev; + ssize_t ret; + + ret = mipi_dsi_dcs_write_buffer(dsi, data, len); + if (ret < 0) { + dev_err(dev, "sending dcs data %*ph failed: %zd\n", + (int)len, data, ret); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_chatty); + +/** + * mipi_dsi_dcs_write_buffer_multi - mipi_dsi_dcs_write_buffer_chatty() w/ accum_err + * @ctx: Context for multiple DSI transactions + * @data: buffer containing data to be transmitted + * @len: size of transmission buffer + * + * Like mipi_dsi_dcs_write_buffer_chatty() but deals with errors in a way that + * makes it convenient to make several calls in a row. + */ +void mipi_dsi_dcs_write_buffer_multi(struct mipi_dsi_multi_context *ctx, + const void *data, size_t len) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t ret; + + if (ctx->accum_err) + return; + + ret = mipi_dsi_dcs_write_buffer(dsi, data, len); + if (ret < 0) { + ctx->accum_err = ret; + dev_err(dev, "sending dcs data %*ph failed: %d\n", + (int)len, data, ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer_multi); + +/** * mipi_dsi_dcs_write() - send DCS write command * @dsi: DSI peripheral device * @cmd: DCS command @@ -1317,6 +1429,216 @@ int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi, } EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness_large); +/** + * mipi_dsi_picture_parameter_set_multi() - transmit the DSC PPS to the peripheral + * @ctx: Context for multiple DSI transactions + * @pps: VESA DSC 1.1 Picture Parameter Set + * + * Like mipi_dsi_picture_parameter_set() but deals with errors in a way that + * makes it convenient to make several calls in a row. + */ +void mipi_dsi_picture_parameter_set_multi(struct mipi_dsi_multi_context *ctx, + const struct drm_dsc_picture_parameter_set *pps) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t ret; + + if (ctx->accum_err) + return; + + ret = mipi_dsi_picture_parameter_set(dsi, pps); + if (ret < 0) { + ctx->accum_err = ret; + dev_err(dev, "sending PPS failed: %d\n", + ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_picture_parameter_set_multi); + +/** + * mipi_dsi_compression_mode_ext_multi() - enable/disable DSC on the peripheral + * @ctx: Context for multiple DSI transactions + * @enable: Whether to enable or disable the DSC + * @algo: Selected compression algorithm + * @pps_selector: Select PPS from the table of pre-stored or uploaded PPS entries + * + * Like mipi_dsi_compression_mode_ext() but deals with errors in a way that + * makes it convenient to make several calls in a row. + */ +void mipi_dsi_compression_mode_ext_multi(struct mipi_dsi_multi_context *ctx, + bool enable, + enum mipi_dsi_compression_algo algo, + unsigned int pps_selector) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t ret; + + if (ctx->accum_err) + return; + + ret = mipi_dsi_compression_mode_ext(dsi, enable, algo, pps_selector); + if (ret < 0) { + ctx->accum_err = ret; + dev_err(dev, "sending COMPRESSION_MODE failed: %d\n", + ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_compression_mode_ext_multi); + +/** + * mipi_dsi_dcs_nop_multi() - send DCS NOP packet + * @ctx: Context for multiple DSI transactions + * + * Like mipi_dsi_dcs_nop() but deals with errors in a way that + * makes it convenient to make several calls in a row. + */ +void mipi_dsi_dcs_nop_multi(struct mipi_dsi_multi_context *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t ret; + + if (ctx->accum_err) + return; + + ret = mipi_dsi_dcs_nop(dsi); + if (ret < 0) { + ctx->accum_err = ret; + dev_err(dev, "sending DCS NOP failed: %d\n", + ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_dcs_nop_multi); + +/** + * mipi_dsi_dcs_enter_sleep_mode_multi() - send DCS ENTER_SLEEP_MODE packet + * @ctx: Context for multiple DSI transactions + * + * Like mipi_dsi_dcs_enter_sleep_mode() but deals with errors in a way that + * makes it convenient to make several calls in a row. + */ +void mipi_dsi_dcs_enter_sleep_mode_multi(struct mipi_dsi_multi_context *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t ret; + + if (ctx->accum_err) + return; + + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); + if (ret < 0) { + ctx->accum_err = ret; + dev_err(dev, "sending DCS ENTER_SLEEP_MODE failed: %d\n", + ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode_multi); + +/** + * mipi_dsi_dcs_exit_sleep_mode_multi() - send DCS EXIT_SLEEP_MODE packet + * @ctx: Context for multiple DSI transactions + * + * Like mipi_dsi_dcs_exit_sleep_mode() but deals with errors in a way that + * makes it convenient to make several calls in a row. + */ +void mipi_dsi_dcs_exit_sleep_mode_multi(struct mipi_dsi_multi_context *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t ret; + + if (ctx->accum_err) + return; + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) { + ctx->accum_err = ret; + dev_err(dev, "sending DCS EXIT_SLEEP_MODE failed: %d\n", + ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode_multi); + +/** + * mipi_dsi_dcs_set_display_off_multi() - send DCS SET_DISPLAY_OFF packet + * @ctx: Context for multiple DSI transactions + * + * Like mipi_dsi_dcs_set_display_off() but deals with errors in a way that + * makes it convenient to make several calls in a row. + */ +void mipi_dsi_dcs_set_display_off_multi(struct mipi_dsi_multi_context *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t ret; + + if (ctx->accum_err) + return; + + ret = mipi_dsi_dcs_set_display_off(dsi); + if (ret < 0) { + ctx->accum_err = ret; + dev_err(dev, "sending DCS SET_DISPLAY_OFF failed: %d\n", + ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off_multi); + +/** + * mipi_dsi_dcs_set_display_on_multi() - send DCS SET_DISPLAY_ON packet + * @ctx: Context for multiple DSI transactions + * + * Like mipi_dsi_dcs_set_display_on() but deals with errors in a way that + * makes it convenient to make several calls in a row. + */ +void mipi_dsi_dcs_set_display_on_multi(struct mipi_dsi_multi_context *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t ret; + + if (ctx->accum_err) + return; + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret < 0) { + ctx->accum_err = ret; + dev_err(dev, "sending DCS SET_DISPLAY_ON failed: %d\n", + ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on_multi); + +/** + * mipi_dsi_dcs_set_tear_on_multi() - send DCS SET_TEAR_ON packet + * @ctx: Context for multiple DSI transactions + * @mode: the Tearing Effect Output Line mode + * + * Like mipi_dsi_dcs_set_tear_on() but deals with errors in a way that + * makes it convenient to make several calls in a row. + */ +void mipi_dsi_dcs_set_tear_on_multi(struct mipi_dsi_multi_context *ctx, + enum mipi_dsi_dcs_tear_mode mode) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + ssize_t ret; + + if (ctx->accum_err) + return; + + ret = mipi_dsi_dcs_set_tear_on(dsi, mode); + if (ret < 0) { + ctx->accum_err = ret; + dev_err(dev, "sending DCS SET_TEAR_ON failed: %d\n", + ctx->accum_err); + } +} +EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on_multi); + static int mipi_dsi_drv_probe(struct device *dev) { struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver); diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 8257f9d4f619..5ace481c1901 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -649,41 +649,6 @@ void drm_mm_remove_node(struct drm_mm_node *node) EXPORT_SYMBOL(drm_mm_remove_node); /** - * drm_mm_replace_node - move an allocation from @old to @new - * @old: drm_mm_node to remove from the allocator - * @new: drm_mm_node which should inherit @old's allocation - * - * This is useful for when drivers embed the drm_mm_node structure and hence - * can't move allocations by reassigning pointers. It's a combination of remove - * and insert with the guarantee that the allocation start will match. - */ -void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) -{ - struct drm_mm *mm = old->mm; - - DRM_MM_BUG_ON(!drm_mm_node_allocated(old)); - - *new = *old; - - __set_bit(DRM_MM_NODE_ALLOCATED_BIT, &new->flags); - list_replace(&old->node_list, &new->node_list); - rb_replace_node_cached(&old->rb, &new->rb, &mm->interval_tree); - - if (drm_mm_hole_follows(old)) { - list_replace(&old->hole_stack, &new->hole_stack); - rb_replace_node_cached(&old->rb_hole_size, - &new->rb_hole_size, - &mm->holes_size); - rb_replace_node(&old->rb_hole_addr, - &new->rb_hole_addr, - &mm->holes_addr); - } - - clear_bit_unlock(DRM_MM_NODE_ALLOCATED_BIT, &old->flags); -} -EXPORT_SYMBOL(drm_mm_replace_node); - -/** * DOC: lru scan roster * * Very often GPUs need to have continuous allocations for a given object. When diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index 0e8355063eee..df4cc0e8e263 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -478,6 +478,7 @@ struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj, return NULL; } +EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_mode_obj_find_prop_id); static int set_property_legacy(struct drm_mode_object *obj, struct drm_property *prop, diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 2d8b0371619d..1a0890083aee 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -531,7 +531,8 @@ static int fill_analog_mode(struct drm_device *dev, * @interlace: whether to compute an interlaced mode * * This function creates a struct drm_display_mode instance suited for - * an analog TV output, for one of the usual analog TV mode. + * an analog TV output, for one of the usual analog TV modes. Where + * this is DRM_MODE_TV_MODE_MONOCHROME, a 625-line mode will be created. * * Note that @hdisplay is larger than the usual constraints for the PAL * and NTSC timings, and we'll choose to ignore most timings constraints @@ -569,6 +570,8 @@ struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev, case DRM_MODE_TV_MODE_PAL_N: fallthrough; case DRM_MODE_TV_MODE_SECAM: + fallthrough; + case DRM_MODE_TV_MODE_MONOCHROME: analog = DRM_MODE_ANALOG_PAL; break; diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index aa93129c3397..ca5a2222ebc0 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -501,4 +501,5 @@ EXPORT_SYMBOL(drm_get_panel_orientation_quirk); #endif +MODULE_DESCRIPTION("Quirks for non-normal panel orientation"); MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c index 7ece67086cec..293d4dcbc80d 100644 --- a/drivers/gpu/drm/drm_panic.c +++ b/drivers/gpu/drm/drm_panic.c @@ -12,6 +12,7 @@ #include <linux/kmsg_dump.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/printk.h> #include <linux/types.h> #include <drm/drm_drv.h> @@ -27,6 +28,12 @@ MODULE_AUTHOR("Jocelyn Falempe"); MODULE_DESCRIPTION("DRM panic handler"); MODULE_LICENSE("GPL"); +static char drm_panic_screen[16] = CONFIG_DRM_PANIC_SCREEN; +module_param_string(panic_screen, drm_panic_screen, sizeof(drm_panic_screen), 0644); +MODULE_PARM_DESC(panic_screen, + "Choose what will be displayed by drm_panic, 'user' or 'kmsg' [default=" + CONFIG_DRM_PANIC_SCREEN "]"); + /** * DOC: overview * @@ -194,40 +201,42 @@ static u32 convert_from_xrgb8888(u32 color, u32 format) /* * Blit & Fill */ +/* check if the pixel at coord x,y is 1 (foreground) or 0 (background) */ +static bool drm_panic_is_pixel_fg(const u8 *sbuf8, unsigned int spitch, int x, int y) +{ + return (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) != 0; +} + static void drm_panic_blit16(struct iosys_map *dmap, unsigned int dpitch, const u8 *sbuf8, unsigned int spitch, unsigned int height, unsigned int width, - u16 fg16, u16 bg16) + u16 fg16) { unsigned int y, x; - u16 val16; - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - val16 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg16 : bg16; - iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, val16); - } - } + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + if (drm_panic_is_pixel_fg(sbuf8, spitch, x, y)) + iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, fg16); } static void drm_panic_blit24(struct iosys_map *dmap, unsigned int dpitch, const u8 *sbuf8, unsigned int spitch, unsigned int height, unsigned int width, - u32 fg32, u32 bg32) + u32 fg32) { unsigned int y, x; - u32 val32; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { u32 off = y * dpitch + x * 3; - val32 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32; - - /* write blue-green-red to output in little endianness */ - iosys_map_wr(dmap, off, u8, (val32 & 0x000000FF) >> 0); - iosys_map_wr(dmap, off + 1, u8, (val32 & 0x0000FF00) >> 8); - iosys_map_wr(dmap, off + 2, u8, (val32 & 0x00FF0000) >> 16); + if (drm_panic_is_pixel_fg(sbuf8, spitch, x, y)) { + /* write blue-green-red to output in little endianness */ + iosys_map_wr(dmap, off, u8, (fg32 & 0x000000FF) >> 0); + iosys_map_wr(dmap, off + 1, u8, (fg32 & 0x0000FF00) >> 8); + iosys_map_wr(dmap, off + 2, u8, (fg32 & 0x00FF0000) >> 16); + } } } } @@ -235,55 +244,64 @@ static void drm_panic_blit24(struct iosys_map *dmap, unsigned int dpitch, static void drm_panic_blit32(struct iosys_map *dmap, unsigned int dpitch, const u8 *sbuf8, unsigned int spitch, unsigned int height, unsigned int width, - u32 fg32, u32 bg32) + u32 fg32) { unsigned int y, x; - u32 val32; - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - val32 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32; - iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, val32); - } - } + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + if (drm_panic_is_pixel_fg(sbuf8, spitch, x, y)) + iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, fg32); +} + +static void drm_panic_blit_pixel(struct drm_scanout_buffer *sb, struct drm_rect *clip, + const u8 *sbuf8, unsigned int spitch, u32 fg_color) +{ + unsigned int y, x; + + for (y = 0; y < drm_rect_height(clip); y++) + for (x = 0; x < drm_rect_width(clip); x++) + if (drm_panic_is_pixel_fg(sbuf8, spitch, x, y)) + sb->set_pixel(sb, clip->x1 + x, clip->y1 + y, fg_color); } /* * drm_panic_blit - convert a monochrome image to a linear framebuffer - * @dmap: destination iosys_map - * @dpitch: destination pitch in bytes + * @sb: destination scanout buffer + * @clip: destination rectangle * @sbuf8: source buffer, in monochrome format, 8 pixels per byte. * @spitch: source pitch in bytes - * @height: height of the image to copy, in pixels - * @width: width of the image to copy, in pixels * @fg_color: foreground color, in destination format - * @bg_color: background color, in destination format - * @pixel_width: pixel width in bytes. * * This can be used to draw a font character, which is a monochrome image, to a * framebuffer in other supported format. */ -static void drm_panic_blit(struct iosys_map *dmap, unsigned int dpitch, - const u8 *sbuf8, unsigned int spitch, - unsigned int height, unsigned int width, - u32 fg_color, u32 bg_color, - unsigned int pixel_width) +static void drm_panic_blit(struct drm_scanout_buffer *sb, struct drm_rect *clip, + const u8 *sbuf8, unsigned int spitch, u32 fg_color) { - switch (pixel_width) { + struct iosys_map map; + + if (sb->set_pixel) + return drm_panic_blit_pixel(sb, clip, sbuf8, spitch, fg_color); + + map = sb->map[0]; + iosys_map_incr(&map, clip->y1 * sb->pitch[0] + clip->x1 * sb->format->cpp[0]); + + switch (sb->format->cpp[0]) { case 2: - drm_panic_blit16(dmap, dpitch, sbuf8, spitch, - height, width, fg_color, bg_color); + drm_panic_blit16(&map, sb->pitch[0], sbuf8, spitch, + drm_rect_height(clip), drm_rect_width(clip), fg_color); break; case 3: - drm_panic_blit24(dmap, dpitch, sbuf8, spitch, - height, width, fg_color, bg_color); + drm_panic_blit24(&map, sb->pitch[0], sbuf8, spitch, + drm_rect_height(clip), drm_rect_width(clip), fg_color); break; case 4: - drm_panic_blit32(dmap, dpitch, sbuf8, spitch, - height, width, fg_color, bg_color); + drm_panic_blit32(&map, sb->pitch[0], sbuf8, spitch, + drm_rect_height(clip), drm_rect_width(clip), fg_color); break; default: - WARN_ONCE(1, "Can't blit with pixel width %d\n", pixel_width); + WARN_ONCE(1, "Can't blit with pixel width %d\n", sb->format->cpp[0]); } } @@ -327,33 +345,51 @@ static void drm_panic_fill32(struct iosys_map *dmap, unsigned int dpitch, iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, color); } +static void drm_panic_fill_pixel(struct drm_scanout_buffer *sb, + struct drm_rect *clip, + u32 color) +{ + unsigned int y, x; + + for (y = 0; y < drm_rect_height(clip); y++) + for (x = 0; x < drm_rect_width(clip); x++) + sb->set_pixel(sb, clip->x1 + x, clip->y1 + y, color); +} + /* * drm_panic_fill - Fill a rectangle with a color - * @dmap: destination iosys_map, pointing to the top left corner of the rectangle - * @dpitch: destination pitch in bytes - * @height: height of the rectangle, in pixels - * @width: width of the rectangle, in pixels - * @color: color to fill the rectangle. - * @pixel_width: pixel width in bytes + * @sb: destination scanout buffer + * @clip: destination rectangle + * @color: foreground color, in destination format * * Fill a rectangle with a color, in a linear framebuffer. */ -static void drm_panic_fill(struct iosys_map *dmap, unsigned int dpitch, - unsigned int height, unsigned int width, - u32 color, unsigned int pixel_width) +static void drm_panic_fill(struct drm_scanout_buffer *sb, struct drm_rect *clip, + u32 color) { - switch (pixel_width) { + struct iosys_map map; + + if (sb->set_pixel) + return drm_panic_fill_pixel(sb, clip, color); + + map = sb->map[0]; + iosys_map_incr(&map, clip->y1 * sb->pitch[0] + clip->x1 * sb->format->cpp[0]); + + switch (sb->format->cpp[0]) { case 2: - drm_panic_fill16(dmap, dpitch, height, width, color); + drm_panic_fill16(&map, sb->pitch[0], drm_rect_height(clip), + drm_rect_width(clip), color); break; case 3: - drm_panic_fill24(dmap, dpitch, height, width, color); + drm_panic_fill24(&map, sb->pitch[0], drm_rect_height(clip), + drm_rect_width(clip), color); break; case 4: - drm_panic_fill32(dmap, dpitch, height, width, color); + drm_panic_fill32(&map, sb->pitch[0], drm_rect_height(clip), + drm_rect_width(clip), color); break; default: - WARN_ONCE(1, "Can't fill with pixel width %d\n", pixel_width); + WARN_ONCE(1, "Can't fill with pixel width %d\n", sb->format->cpp[0]); } } @@ -381,53 +417,46 @@ static void draw_txt_rectangle(struct drm_scanout_buffer *sb, unsigned int msg_lines, bool centered, struct drm_rect *clip, - u32 fg_color, - u32 bg_color) + u32 color) { int i, j; const u8 *src; size_t font_pitch = DIV_ROUND_UP(font->width, 8); - struct iosys_map dst; - unsigned int px_width = sb->format->cpp[0]; - int left = 0; + struct drm_rect rec; msg_lines = min(msg_lines, drm_rect_height(clip) / font->height); for (i = 0; i < msg_lines; i++) { size_t line_len = min(msg[i].len, drm_rect_width(clip) / font->width); + rec.y1 = clip->y1 + i * font->height; + rec.y2 = rec.y1 + font->height; + rec.x1 = clip->x1; + if (centered) - left = (drm_rect_width(clip) - (line_len * font->width)) / 2; + rec.x1 += (drm_rect_width(clip) - (line_len * font->width)) / 2; - dst = sb->map[0]; - iosys_map_incr(&dst, (clip->y1 + i * font->height) * sb->pitch[0] + - (clip->x1 + left) * px_width); for (j = 0; j < line_len; j++) { src = get_char_bitmap(font, msg[i].txt[j], font_pitch); - drm_panic_blit(&dst, sb->pitch[0], src, font_pitch, - font->height, font->width, - fg_color, bg_color, px_width); - iosys_map_incr(&dst, font->width * px_width); + rec.x2 = rec.x1 + font->width; + drm_panic_blit(sb, &rec, src, font_pitch, color); + rec.x1 += font->width; } } } -/* - * Draw the panic message at the center of the screen - */ -static void draw_panic_static(struct drm_scanout_buffer *sb) +static void draw_panic_static_user(struct drm_scanout_buffer *sb) { size_t msg_lines = ARRAY_SIZE(panic_msg); size_t logo_lines = ARRAY_SIZE(logo); - u32 fg_color = CONFIG_DRM_PANIC_FOREGROUND_COLOR; - u32 bg_color = CONFIG_DRM_PANIC_BACKGROUND_COLOR; + u32 fg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR, sb->format->format); + u32 bg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR, sb->format->format); const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL); - struct drm_rect r_logo, r_msg; + struct drm_rect r_screen, r_logo, r_msg; if (!font) return; - fg_color = convert_from_xrgb8888(fg_color, sb->format->format); - bg_color = convert_from_xrgb8888(bg_color, sb->format->format); + r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height); r_logo = DRM_RECT_INIT(0, 0, get_max_line_len(logo, logo_lines) * font->width, @@ -440,14 +469,92 @@ static void draw_panic_static(struct drm_scanout_buffer *sb) drm_rect_translate(&r_msg, (sb->width - r_msg.x2) / 2, (sb->height - r_msg.y2) / 2); /* Fill with the background color, and draw text on top */ - drm_panic_fill(&sb->map[0], sb->pitch[0], sb->height, sb->width, - bg_color, sb->format->cpp[0]); + drm_panic_fill(sb, &r_screen, bg_color); if ((r_msg.x1 >= drm_rect_width(&r_logo) || r_msg.y1 >= drm_rect_height(&r_logo)) && drm_rect_width(&r_logo) < sb->width && drm_rect_height(&r_logo) < sb->height) { - draw_txt_rectangle(sb, font, logo, logo_lines, false, &r_logo, fg_color, bg_color); + draw_txt_rectangle(sb, font, logo, logo_lines, false, &r_logo, fg_color); + } + draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color); +} + +/* + * Draw one line of kmsg, and handle wrapping if it won't fit in the screen width. + * Return the y-offset of the next line. + */ +static int draw_line_with_wrap(struct drm_scanout_buffer *sb, const struct font_desc *font, + struct drm_panic_line *line, int yoffset, u32 fg_color) +{ + int chars_per_row = sb->width / font->width; + struct drm_rect r_txt = DRM_RECT_INIT(0, yoffset, sb->width, sb->height); + struct drm_panic_line line_wrap; + + if (line->len > chars_per_row) { + line_wrap.len = line->len % chars_per_row; + line_wrap.txt = line->txt + line->len - line_wrap.len; + draw_txt_rectangle(sb, font, &line_wrap, 1, false, &r_txt, fg_color); + r_txt.y1 -= font->height; + if (r_txt.y1 < 0) + return r_txt.y1; + while (line_wrap.txt > line->txt) { + line_wrap.txt -= chars_per_row; + line_wrap.len = chars_per_row; + draw_txt_rectangle(sb, font, &line_wrap, 1, false, &r_txt, fg_color); + r_txt.y1 -= font->height; + if (r_txt.y1 < 0) + return r_txt.y1; + } + } else { + draw_txt_rectangle(sb, font, line, 1, false, &r_txt, fg_color); + r_txt.y1 -= font->height; + } + return r_txt.y1; +} + +/* + * Draw the kmsg buffer to the screen, starting from the youngest message at the bottom, + * and going up until reaching the top of the screen. + */ +static void draw_panic_static_kmsg(struct drm_scanout_buffer *sb) +{ + u32 fg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR, sb->format->format); + u32 bg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR, sb->format->format); + const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL); + struct drm_rect r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height); + struct kmsg_dump_iter iter; + char kmsg_buf[512]; + size_t kmsg_len; + struct drm_panic_line line; + int yoffset; + + if (!font) + return; + + yoffset = sb->height - font->height - (sb->height % font->height) / 2; + + /* Fill with the background color, and draw text on top */ + drm_panic_fill(sb, &r_screen, bg_color); + + kmsg_dump_rewind(&iter); + while (kmsg_dump_get_buffer(&iter, false, kmsg_buf, sizeof(kmsg_buf), &kmsg_len)) { + char *start; + char *end; + + /* ignore terminating NUL and newline */ + start = kmsg_buf + kmsg_len - 2; + end = kmsg_buf + kmsg_len - 1; + while (start > kmsg_buf && yoffset >= 0) { + while (start > kmsg_buf && *start != '\n') + start--; + /* don't count the newline character */ + line.txt = start + (start == kmsg_buf ? 0 : 1); + line.len = end - line.txt; + + yoffset = draw_line_with_wrap(sb, font, &line, yoffset, fg_color); + end = start; + start--; + } } - draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color, bg_color); } /* @@ -464,6 +571,15 @@ static bool drm_panic_is_format_supported(const struct drm_format_info *format) return convert_from_xrgb8888(0xffffff, format->format) != 0; } +static void draw_panic_dispatch(struct drm_scanout_buffer *sb) +{ + if (!strcmp(drm_panic_screen, "kmsg")) { + draw_panic_static_kmsg(sb); + } else { + draw_panic_static_user(sb); + } +} + static void draw_panic_plane(struct drm_plane *plane) { struct drm_scanout_buffer sb; @@ -476,7 +592,7 @@ static void draw_panic_plane(struct drm_plane *plane) ret = plane->helper_private->get_scanout_buffer(plane, &sb); if (!ret && drm_panic_is_format_supported(sb.format)) { - draw_panic_static(&sb); + draw_panic_dispatch(&sb); if (plane->helper_private->panic_flush) plane->helper_private->panic_flush(plane); } diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index cf2efb44722c..cf24dfdeb6b2 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -176,6 +176,32 @@ void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf) } EXPORT_SYMBOL(__drm_printfn_seq_file); +static void __drm_dev_vprintk(const struct device *dev, const char *level, + const void *origin, const char *prefix, + struct va_format *vaf) +{ + const char *prefix_pad = prefix ? " " : ""; + + if (!prefix) + prefix = ""; + + if (dev) { + if (origin) + dev_printk(level, dev, "[" DRM_NAME ":%ps]%s%s %pV", + origin, prefix_pad, prefix, vaf); + else + dev_printk(level, dev, "[" DRM_NAME "]%s%s %pV", + prefix_pad, prefix, vaf); + } else { + if (origin) + printk("%s" "[" DRM_NAME ":%ps]%s%s %pV", + level, origin, prefix_pad, prefix, vaf); + else + printk("%s" "[" DRM_NAME "]%s%s %pV", + level, prefix_pad, prefix, vaf); + } +} + void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf) { dev_info(p->arg, "[" DRM_NAME "] %pV", vaf); @@ -187,19 +213,11 @@ void __drm_printfn_dbg(struct drm_printer *p, struct va_format *vaf) const struct drm_device *drm = p->arg; const struct device *dev = drm ? drm->dev : NULL; enum drm_debug_category category = p->category; - const char *prefix = p->prefix ?: ""; - const char *prefix_pad = p->prefix ? " " : ""; if (!__drm_debug_enabled(category)) return; - /* Note: __builtin_return_address(0) is useless here. */ - if (dev) - dev_printk(KERN_DEBUG, dev, "[" DRM_NAME "]%s%s %pV", - prefix_pad, prefix, vaf); - else - printk(KERN_DEBUG "[" DRM_NAME "]%s%s %pV", - prefix_pad, prefix, vaf); + __drm_dev_vprintk(dev, KERN_DEBUG, p->origin, p->prefix, vaf); } EXPORT_SYMBOL(__drm_printfn_dbg); @@ -287,12 +305,7 @@ void drm_dev_printk(const struct device *dev, const char *level, vaf.fmt = format; vaf.va = &args; - if (dev) - dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV", - __builtin_return_address(0), &vaf); - else - printk("%s" "[" DRM_NAME ":%ps] %pV", - level, __builtin_return_address(0), &vaf); + __drm_dev_vprintk(dev, level, __builtin_return_address(0), NULL, &vaf); va_end(args); } @@ -312,36 +325,12 @@ void __drm_dev_dbg(struct _ddebug *desc, const struct device *dev, vaf.fmt = format; vaf.va = &args; - if (dev) - dev_printk(KERN_DEBUG, dev, "[" DRM_NAME ":%ps] %pV", - __builtin_return_address(0), &vaf); - else - printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV", - __builtin_return_address(0), &vaf); + __drm_dev_vprintk(dev, KERN_DEBUG, __builtin_return_address(0), NULL, &vaf); va_end(args); } EXPORT_SYMBOL(__drm_dev_dbg); -void ___drm_dbg(struct _ddebug *desc, enum drm_debug_category category, const char *format, ...) -{ - struct va_format vaf; - va_list args; - - if (!__drm_debug_enabled(category)) - return; - - va_start(args, format); - vaf.fmt = format; - vaf.va = &args; - - printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV", - __builtin_return_address(0), &vaf); - - va_end(args); -} -EXPORT_SYMBOL(___drm_dbg); - void __drm_err(const char *format, ...) { struct va_format vaf; @@ -351,8 +340,7 @@ void __drm_err(const char *format, ...) vaf.fmt = format; vaf.va = &args; - printk(KERN_ERR "[" DRM_NAME ":%ps] *ERROR* %pV", - __builtin_return_address(0), &vaf); + __drm_dev_vprintk(NULL, KERN_ERR, __builtin_return_address(0), "*ERROR*", &vaf); va_end(args); } diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 4f75a1cfd820..bb49d552e671 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -474,6 +474,10 @@ static int __drm_helper_update_and_validate(struct drm_connector *connector, if (mode->status != MODE_OK) continue; + mode->status = drm_mode_validate_ycbcr420(mode, connector); + if (mode->status != MODE_OK) + continue; + ret = drm_mode_validate_pipeline(mode, connector, ctx, &mode->status); if (ret) { @@ -486,10 +490,6 @@ static int __drm_helper_update_and_validate(struct drm_connector *connector, else return -EDEADLK; } - - if (mode->status != MODE_OK) - continue; - mode->status = drm_mode_validate_ycbcr420(mode, connector); } return 0; @@ -1259,8 +1259,9 @@ int drm_connector_helper_tv_get_modes(struct drm_connector *connector) for (i = 0; i < tv_mode_property->num_values; i++) supported_tv_modes |= BIT(tv_mode_property->values[i]); - if ((supported_tv_modes & ntsc_modes) && - (supported_tv_modes & pal_modes)) { + if (((supported_tv_modes & ntsc_modes) && + (supported_tv_modes & pal_modes)) || + (supported_tv_modes & BIT(DRM_MODE_TV_MODE_MONOCHROME))) { uint64_t default_mode; if (drm_object_property_get_default_value(&connector->base, diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 270523ae36d4..250819fbc5ce 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -453,4 +453,5 @@ int drm_simple_display_pipe_init(struct drm_device *dev, } EXPORT_SYMBOL(drm_simple_display_pipe_init); +MODULE_DESCRIPTION("Helpers for drivers for simple display hardware"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index bd9b8ab4f82b..fb3bbb6adcd1 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -266,29 +266,9 @@ static ssize_t edid_show(struct file *filp, struct kobject *kobj, { struct device *connector_dev = kobj_to_dev(kobj); struct drm_connector *connector = to_drm_connector(connector_dev); - unsigned char *edid; - size_t size; - ssize_t ret = 0; + ssize_t ret; - mutex_lock(&connector->dev->mode_config.mutex); - if (!connector->edid_blob_ptr) - goto unlock; - - edid = connector->edid_blob_ptr->data; - size = connector->edid_blob_ptr->length; - if (!edid) - goto unlock; - - if (off >= size) - goto unlock; - - if (off + count > size) - count = size - off; - memcpy(buf, edid + off, count); - - ret = count; -unlock: - mutex_unlock(&connector->dev->mode_config.mutex); + ret = drm_edid_connector_property_show(connector, buf, off, count); return ret; } diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index dd1eb7e9877d..cc2ed9b3fd2d 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -1547,7 +1547,7 @@ cdv_intel_dp_start_link_train(struct gma_encoder *encoder) } if (!clock_recovery) { - DRM_DEBUG_KMS("failure in DP patter 1 training, train set %x\n", intel_dp->train_set[0]); + DRM_DEBUG_KMS("failure in DP pattern 1 training, train set %x\n", intel_dp->train_set[0]); } intel_dp->DP = DP; diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c index 9d7bf8ee45f1..ac6bbf920c72 100644 --- a/drivers/gpu/drm/gud/gud_drv.c +++ b/drivers/gpu/drm/gud/gud_drv.c @@ -18,7 +18,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_debugfs.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> @@ -622,7 +622,7 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id) drm_kms_helper_poll_init(drm); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_shmem_setup(drm, 0); return 0; } @@ -678,4 +678,5 @@ static struct usb_driver gud_usb_driver = { module_usb_driver(gud_usb_driver); MODULE_AUTHOR("Noralf Trønnes"); +MODULE_DESCRIPTION("GUD USB Display driver"); MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 57c21ec452b7..9f9b19ea0587 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -17,7 +17,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_ttm.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_vram_helper.h> #include <drm/drm_managed.h> @@ -339,7 +339,7 @@ static int hibmc_pci_probe(struct pci_dev *pdev, goto err_unload; } - drm_fbdev_generic_setup(dev, 32); + drm_fbdev_ttm_setup(dev, 32); return 0; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index 94e2c573a7af..409c551c92af 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -24,14 +24,16 @@ static int hibmc_connector_get_modes(struct drm_connector *connector) { - int count; - void *edid; struct hibmc_connector *hibmc_connector = to_hibmc_connector(connector); + const struct drm_edid *drm_edid; + int count; + + drm_edid = drm_edid_read_ddc(connector, &hibmc_connector->adapter); - edid = drm_get_edid(connector, &hibmc_connector->adapter); - if (edid) { - drm_connector_update_edid_property(connector, edid); - count = drm_add_edid_modes(connector, edid); + drm_edid_connector_update(connector, drm_edid); + + if (drm_edid) { + count = drm_edid_connector_add_modes(connector); if (count) goto out; } @@ -42,7 +44,8 @@ static int hibmc_connector_get_modes(struct drm_connector *connector) drm_set_preferred_mode(connector, 1024, 768); out: - kfree(edid); + drm_edid_free(drm_edid); + return count; } diff --git a/drivers/gpu/drm/hisilicon/kirin/Kconfig b/drivers/gpu/drm/hisilicon/kirin/Kconfig index c5265675bf0c..0772f79567ef 100644 --- a/drivers/gpu/drm/hisilicon/kirin/Kconfig +++ b/drivers/gpu/drm/hisilicon/kirin/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_HISI_KIRIN tristate "DRM Support for Hisilicon Kirin series SoCs Platform" - depends on DRM && OF && ARM64 + depends on DRM && OF && (ARM64 || COMPILE_TEST) select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_MIPI_DSI diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c index 566de4658719..a39cc549c20b 100644 --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c @@ -157,8 +157,8 @@ static u32 dsi_calc_phy_rate(u32 req_kHz, struct mipi_phy_params *phy) q_pll = 0x10 >> (7 - phy->hstx_ckg_sel); temp = f_kHz * (u64)q_pll * (u64)ref_clk_ps; - m_n_int = temp / (u64)1000000000; - m_n = (temp % (u64)1000000000) / (u64)100000000; + m_n_int = div64_u64_rem(temp, 1000000000, &temp); + m_n = div_u64(temp, 100000000); if (m_n_int % 2 == 0) { if (m_n * 6 >= 50) { @@ -229,9 +229,8 @@ static u32 dsi_calc_phy_rate(u32 req_kHz, struct mipi_phy_params *phy) phy->pll_fbd_div5f = 1; } - f_kHz = (u64)1000000000 * (u64)m_pll / - ((u64)ref_clk_ps * (u64)n_pll * (u64)q_pll); - + f_kHz = div64_u64((u64)1000000000 * (u64)m_pll, + (u64)ref_clk_ps * (u64)n_pll * (u64)q_pll); if (f_kHz >= req_kHz) break; @@ -490,7 +489,7 @@ static void dsi_set_mode_timing(void __iomem *base, hsa_time = (hsw * lane_byte_clk_kHz) / pixel_clk_kHz; hbp_time = (hbp * lane_byte_clk_kHz) / pixel_clk_kHz; tmp = (u64)htot * (u64)lane_byte_clk_kHz; - hline_time = DIV_ROUND_UP(tmp, pixel_clk_kHz); + hline_time = DIV_ROUND_UP_ULL(tmp, pixel_clk_kHz); /* all specified in byte-lane clocks */ writel(hsa_time, base + VID_HSA_TIME); diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h b/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h index d79fc031e53d..a87d1135856f 100644 --- a/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h +++ b/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h @@ -7,6 +7,8 @@ #ifndef __DW_DSI_REG_H__ #define __DW_DSI_REG_H__ +#include <linux/io.h> + #define MASK(x) (BIT(x) - 1) /* diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h index be9e789c2d04..36f923cc7594 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h @@ -10,7 +10,7 @@ /* * ADE Registers */ -#define MASK(x) (BIT(x) - 1) +#define MASK(x) (BIT_ULL(x) - 1) #define ADE_CTRL 0x0004 #define FRM_END_START_OFST 0 diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index 75292a2f4644..12666985686b 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -19,7 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_module.h> @@ -237,7 +237,7 @@ static int kirin_drm_bind(struct device *dev) if (ret) goto err_kms_cleanup; - drm_fbdev_generic_setup(drm_dev, 32); + drm_fbdev_dma_setup(drm_dev, 32); return 0; diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c index cff85086f2d6..ff93e08d5036 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c @@ -11,7 +11,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_gem_shmem_helper.h> #include <drm/drm_simple_kms_helper.h> @@ -149,7 +149,7 @@ static int hyperv_vmbus_probe(struct hv_device *hdev, goto err_free_mmio; } - drm_fbdev_generic_setup(dev, 0); + drm_fbdev_shmem_setup(dev, 0); return 0; diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index d8d7de18dd65..2160f05bbd16 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1283,7 +1283,7 @@ static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length) static int tda998x_connector_get_modes(struct drm_connector *connector) { struct tda998x_priv *priv = conn_to_tda998x_priv(connector); - struct edid *edid; + const struct drm_edid *drm_edid; int n; /* @@ -1297,25 +1297,26 @@ static int tda998x_connector_get_modes(struct drm_connector *connector) if (priv->rev == TDA19988) reg_clear(priv, REG_TX4, TX4_PD_RAM); - edid = drm_do_get_edid(connector, read_edid_block, priv); + drm_edid = drm_edid_read_custom(connector, read_edid_block, priv); if (priv->rev == TDA19988) reg_set(priv, REG_TX4, TX4_PD_RAM); - if (!edid) { + drm_edid_connector_update(connector, drm_edid); + cec_notifier_set_phys_addr(priv->cec_notify, + connector->display_info.source_physical_address); + + if (!drm_edid) { dev_warn(&priv->hdmi->dev, "failed to read EDID\n"); return 0; } - drm_connector_update_edid_property(connector, edid); - cec_notifier_set_phys_addr_from_edid(priv->cec_notify, edid); - mutex_lock(&priv->audio_mutex); - n = drm_add_edid_modes(connector, edid); - priv->sink_has_audio = drm_detect_monitor_audio(edid); + n = drm_edid_connector_add_modes(connector); + priv->sink_has_audio = connector->display_info.has_audio; mutex_unlock(&priv->audio_mutex); - kfree(edid); + drm_edid_free(drm_edid); return n; } diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 5932024f8f95..faa253b27664 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -29,7 +29,6 @@ config DRM_I915 select X86_PLATFORM_DEVICES if ACPI select ACPI_WMI if ACPI select ACPI_VIDEO if ACPI - select ACPI_BUTTON if ACPI select SYNC_FILE select IOSF_MBI if X86 select CRC32 diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index c8c8b31da4fb..c63fa2133ccb 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -3,31 +3,8 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -# Unconditionally enable W=1 warnings locally -# --- begin copy-paste W=1 warnings from scripts/Makefile.extrawarn -subdir-ccflags-y += -Wextra -Wunused -Wno-unused-parameter -subdir-ccflags-y += -Wmissing-declarations -subdir-ccflags-y += $(call cc-option, -Wrestrict) -subdir-ccflags-y += -Wmissing-format-attribute -subdir-ccflags-y += -Wmissing-prototypes -subdir-ccflags-y += -Wold-style-definition -subdir-ccflags-y += -Wmissing-include-dirs -subdir-ccflags-y += $(call cc-option, -Wunused-but-set-variable) -subdir-ccflags-y += $(call cc-option, -Wunused-const-variable) -subdir-ccflags-y += $(call cc-option, -Wpacked-not-aligned) -subdir-ccflags-y += $(call cc-option, -Wformat-overflow) +# Enable W=1 warnings not enabled in drm subsystem Makefile subdir-ccflags-y += $(call cc-option, -Wformat-truncation) -subdir-ccflags-y += $(call cc-option, -Wstringop-truncation) -# The following turn off the warnings enabled by -Wextra -ifeq ($(findstring 2, $(KBUILD_EXTRA_WARN)),) -subdir-ccflags-y += -Wno-missing-field-initializers -subdir-ccflags-y += -Wno-type-limits -subdir-ccflags-y += -Wno-shift-negative-value -endif -ifeq ($(findstring 3, $(KBUILD_EXTRA_WARN)),) -subdir-ccflags-y += -Wno-sign-compare -endif -# --- end copy-paste # Enable -Werror in CI and development subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror @@ -243,6 +220,7 @@ i915-y += \ display/hsw_ips.o \ display/i9xx_plane.o \ display/i9xx_wm.o \ + display/intel_alpm.o \ display/intel_atomic.o \ display/intel_atomic_plane.o \ display/intel_audio.o \ @@ -351,6 +329,7 @@ i915-y += \ display/intel_dsi_dcs_backlight.o \ display/intel_dsi_vbt.o \ display/intel_dvo.o \ + display/intel_encoder.o \ display/intel_gmbus.o \ display/intel_hdmi.o \ display/intel_lspcon.o \ diff --git a/drivers/gpu/drm/i915/display/dvo_ns2501.c b/drivers/gpu/drm/i915/display/dvo_ns2501.c index 1df212fb000e..21486008dae9 100644 --- a/drivers/gpu/drm/i915/display/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/display/dvo_ns2501.c @@ -27,7 +27,6 @@ */ #include "i915_drv.h" -#include "i915_reg.h" #include "intel_display_types.h" #include "intel_dvo_dev.h" diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index 06ec04e667e3..a8e746a0f670 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -20,6 +20,7 @@ #include "intel_dp_aux.h" #include "intel_dp_link_training.h" #include "intel_dpio_phy.h" +#include "intel_encoder.h" #include "intel_fifo_underrun.h" #include "intel_hdmi.h" #include "intel_hotplug.h" @@ -706,7 +707,7 @@ static void intel_enable_dp(struct intel_atomic_state *state, intel_dp_configure_protocol_converter(intel_dp, pipe_config); intel_dp_check_frl_training(intel_dp); intel_dp_pcon_dsc_configure(intel_dp, pipe_config); - intel_dp_start_link_train(intel_dp, pipe_config); + intel_dp_start_link_train(state, intel_dp, pipe_config); intel_dp_stop_link_train(intel_dp, pipe_config); } @@ -1159,9 +1160,7 @@ intel_dp_hotplug(struct intel_encoder *encoder, struct intel_connector *connector) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct drm_modeset_acquire_ctx ctx; enum intel_hotplug_state state; - int ret; if (intel_dp->compliance.test_active && intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) { @@ -1172,23 +1171,7 @@ intel_dp_hotplug(struct intel_encoder *encoder, state = intel_encoder_hotplug(encoder, connector); - drm_modeset_acquire_init(&ctx, 0); - - for (;;) { - ret = intel_dp_retrain_link(encoder, &ctx); - - if (ret == -EDEADLK) { - drm_modeset_backoff(&ctx); - continue; - } - - break; - } - - drm_modeset_drop_locks(&ctx); - drm_modeset_acquire_fini(&ctx); - drm_WARN(encoder->base.dev, ret, - "Acquiring modeset locks failed with %i\n", ret); + intel_dp_check_link_state(intel_dp); /* * Keeping it consistent with intel_ddi_hotplug() and @@ -1228,7 +1211,7 @@ static bool g4x_digital_port_connected(struct intel_encoder *encoder) return false; } - return intel_de_read(dev_priv, PORT_HOTPLUG_STAT) & bit; + return intel_de_read(dev_priv, PORT_HOTPLUG_STAT(dev_priv)) & bit; } static bool ilk_digital_port_connected(struct intel_encoder *encoder) @@ -1239,6 +1222,15 @@ static bool ilk_digital_port_connected(struct intel_encoder *encoder) return intel_de_read(dev_priv, DEISR) & bit; } +static void g4x_dp_suspend_complete(struct intel_encoder *encoder) +{ + /* + * TODO: Move this to intel_dp_encoder_suspend(), + * once modeset locking around that is removed. + */ + intel_encoder_link_check_flush_work(encoder); +} + static void intel_dp_encoder_destroy(struct drm_encoder *encoder) { intel_dp_encoder_flush_work(encoder); @@ -1325,6 +1317,8 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv, "DP %c", port_name(port))) goto err_encoder_init; + intel_encoder_link_check_init(intel_encoder, intel_dp_link_check); + intel_encoder->hotplug = intel_dp_hotplug; intel_encoder->compute_config = intel_dp_compute_config; intel_encoder->get_hw_state = intel_dp_get_hw_state; @@ -1333,6 +1327,7 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv, intel_encoder->initial_fastset_check = intel_dp_initial_fastset_check; intel_encoder->update_pipe = intel_backlight_update; intel_encoder->suspend = intel_dp_encoder_suspend; + intel_encoder->suspend_complete = g4x_dp_suspend_complete; intel_encoder->shutdown = intel_dp_encoder_shutdown; if (IS_CHERRYVIEW(dev_priv)) { intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 0279c8aabdd1..864d94406894 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -10,6 +10,7 @@ #include "i915_reg.h" #include "i9xx_plane.h" +#include "i9xx_plane_regs.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" #include "intel_de.h" @@ -266,7 +267,7 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) * despite them not using the linear offset anymore. */ if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) { - u32 alignment = intel_surf_alignment(fb, 0); + unsigned int alignment = intel_surf_alignment(fb, 0); int cpp = fb->format->cpp[0]; while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].mapping_stride) { @@ -422,7 +423,7 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), + intel_de_write_fw(dev_priv, DSPSTRIDE(dev_priv, i9xx_plane), plane_state->view.color_plane[0].mapping_stride); if (DISPLAY_VER(dev_priv) < 4) { @@ -436,9 +437,9 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane, * generator but let's assume we still need to * program whatever is there. */ - intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane), + intel_de_write_fw(dev_priv, DSPPOS(dev_priv, i9xx_plane), DISP_POS_Y(crtc_y) | DISP_POS_X(crtc_x)); - intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane), + intel_de_write_fw(dev_priv, DSPSIZE(dev_priv, i9xx_plane), DISP_HEIGHT(crtc_h - 1) | DISP_WIDTH(crtc_w - 1)); } } @@ -455,6 +456,11 @@ static void i9xx_plane_update_arm(struct intel_plane *plane, dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state); + /* see intel_plane_atomic_calc_changes() */ + if (plane->need_async_flip_toggle_wa && + crtc_state->async_flip_planes & BIT(plane->id)) + dspcntr |= DISP_ASYNC_FLIP; + linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); if (DISPLAY_VER(dev_priv) >= 4) @@ -468,20 +474,21 @@ static void i9xx_plane_update_arm(struct intel_plane *plane, int crtc_w = drm_rect_width(&plane_state->uapi.dst); int crtc_h = drm_rect_height(&plane_state->uapi.dst); - intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane), + intel_de_write_fw(dev_priv, PRIMPOS(dev_priv, i9xx_plane), PRIM_POS_Y(crtc_y) | PRIM_POS_X(crtc_x)); - intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane), + intel_de_write_fw(dev_priv, PRIMSIZE(dev_priv, i9xx_plane), PRIM_HEIGHT(crtc_h - 1) | PRIM_WIDTH(crtc_w - 1)); - intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0); + intel_de_write_fw(dev_priv, + PRIMCNSTALPHA(dev_priv, i9xx_plane), 0); } if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane), + intel_de_write_fw(dev_priv, DSPOFFSET(dev_priv, i9xx_plane), DISP_OFFSET_Y(y) | DISP_OFFSET_X(x)); } else if (DISPLAY_VER(dev_priv) >= 4) { - intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane), + intel_de_write_fw(dev_priv, DSPLINOFF(dev_priv, i9xx_plane), linear_offset); - intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane), + intel_de_write_fw(dev_priv, DSPTILEOFF(dev_priv, i9xx_plane), DISP_OFFSET_Y(y) | DISP_OFFSET_X(x)); } @@ -490,13 +497,13 @@ static void i9xx_plane_update_arm(struct intel_plane *plane, * disabled. Try to make the plane enable atomic by writing * the control register just before the surface register. */ - intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + intel_de_write_fw(dev_priv, DSPCNTR(dev_priv, i9xx_plane), dspcntr); if (DISPLAY_VER(dev_priv) >= 4) - intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), + intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); else - intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), + intel_de_write_fw(dev_priv, DSPADDR(dev_priv, i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); } @@ -533,12 +540,12 @@ static void i9xx_plane_disable_arm(struct intel_plane *plane, */ dspcntr = i9xx_plane_ctl_crtc(crtc_state); - intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + intel_de_write_fw(dev_priv, DSPCNTR(dev_priv, i9xx_plane), dspcntr); if (DISPLAY_VER(dev_priv) >= 4) - intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0); + intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane), 0); else - intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0); + intel_de_write_fw(dev_priv, DSPADDR(dev_priv, i9xx_plane), 0); } static void @@ -555,9 +562,9 @@ g4x_primary_async_flip(struct intel_plane *plane, if (async_flip) dspcntr |= DISP_ASYNC_FLIP; - intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + intel_de_write_fw(dev_priv, DSPCNTR(dev_priv, i9xx_plane), dspcntr); - intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), + intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); } @@ -571,7 +578,7 @@ vlv_primary_async_flip(struct intel_plane *plane, u32 dspaddr_offset = plane_state->view.color_plane[0].offset; enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - intel_de_write_fw(dev_priv, DSPADDR_VLV(i9xx_plane), + intel_de_write_fw(dev_priv, DSPADDR_VLV(dev_priv, i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); } @@ -679,7 +686,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane, if (!wakeref) return false; - val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane)); + val = intel_de_read(dev_priv, DSPCNTR(dev_priv, i9xx_plane)); ret = val & DISP_ENABLE; @@ -736,23 +743,25 @@ i965_plane_max_stride(struct intel_plane *plane, } static unsigned int -i9xx_plane_max_stride(struct intel_plane *plane, +i915_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + if (modifier == I915_FORMAT_MOD_X_TILED) + return 8 * 1024; + else + return 16 * 1024; +} - if (DISPLAY_VER(dev_priv) >= 3) { - if (modifier == I915_FORMAT_MOD_X_TILED) - return 8*1024; - else - return 16*1024; - } else { - if (plane->i9xx_plane == PLANE_C) - return 4*1024; - else - return 8*1024; - } +static unsigned int +i8xx_plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation) +{ + if (plane->i9xx_plane == PLANE_C) + return 4 * 1024; + else + return 8 * 1024; } static const struct drm_plane_funcs i965_plane_funcs = { @@ -849,8 +858,10 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) if (HAS_GMCH(dev_priv)) { if (DISPLAY_VER(dev_priv) >= 4) plane->max_stride = i965_plane_max_stride; + else if (DISPLAY_VER(dev_priv) == 3) + plane->max_stride = i915_plane_max_stride; else - plane->max_stride = i9xx_plane_max_stride; + plane->max_stride = i8xx_plane_max_stride; } else { if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) plane->max_stride = hsw_primary_max_stride; @@ -873,7 +884,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->enable_flip_done = vlv_primary_enable_flip_done; plane->disable_flip_done = vlv_primary_disable_flip_done; } else if (IS_BROADWELL(dev_priv)) { - plane->need_async_flip_disable_wa = true; + plane->need_async_flip_toggle_wa = true; plane->async_flip = g4x_primary_async_flip; plane->enable_flip_done = bdw_primary_enable_flip_done; plane->disable_flip_done = bdw_primary_disable_flip_done; @@ -1002,7 +1013,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, fb->dev = dev; - val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane)); + val = intel_de_read(dev_priv, DSPCNTR(dev_priv, i9xx_plane)); if (DISPLAY_VER(dev_priv) >= 4) { if (val & DISP_TILED) { @@ -1023,29 +1034,30 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, fb->format = drm_format_info(fourcc); if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - offset = intel_de_read(dev_priv, DSPOFFSET(i9xx_plane)); - base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & DISP_ADDR_MASK; + offset = intel_de_read(dev_priv, + DSPOFFSET(dev_priv, i9xx_plane)); + base = intel_de_read(dev_priv, DSPSURF(dev_priv, i9xx_plane)) & DISP_ADDR_MASK; } else if (DISPLAY_VER(dev_priv) >= 4) { if (plane_config->tiling) offset = intel_de_read(dev_priv, - DSPTILEOFF(i9xx_plane)); + DSPTILEOFF(dev_priv, i9xx_plane)); else offset = intel_de_read(dev_priv, - DSPLINOFF(i9xx_plane)); - base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & DISP_ADDR_MASK; + DSPLINOFF(dev_priv, i9xx_plane)); + base = intel_de_read(dev_priv, DSPSURF(dev_priv, i9xx_plane)) & DISP_ADDR_MASK; } else { offset = 0; - base = intel_de_read(dev_priv, DSPADDR(i9xx_plane)); + base = intel_de_read(dev_priv, DSPADDR(dev_priv, i9xx_plane)); } plane_config->base = base; drm_WARN_ON(&dev_priv->drm, offset != 0); - val = intel_de_read(dev_priv, PIPESRC(pipe)); + val = intel_de_read(dev_priv, PIPESRC(dev_priv, pipe)); fb->width = REG_FIELD_GET(PIPESRC_WIDTH_MASK, val) + 1; fb->height = REG_FIELD_GET(PIPESRC_HEIGHT_MASK, val) + 1; - val = intel_de_read(dev_priv, DSPSTRIDE(i9xx_plane)); + val = intel_de_read(dev_priv, DSPSTRIDE(dev_priv, i9xx_plane)); fb->pitches[0] = val & 0xffffffc0; aligned_height = intel_fb_align_height(fb, 0, fb->height); @@ -1084,9 +1096,9 @@ bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc, return false; if (DISPLAY_VER(dev_priv) >= 4) - intel_de_write(dev_priv, DSPSURF(i9xx_plane), base); + intel_de_write(dev_priv, DSPSURF(dev_priv, i9xx_plane), base); else - intel_de_write(dev_priv, DSPADDR(i9xx_plane), base); + intel_de_write(dev_priv, DSPADDR(dev_priv, i9xx_plane), base); return true; } diff --git a/drivers/gpu/drm/i915/display/i9xx_plane_regs.h b/drivers/gpu/drm/i915/display/i9xx_plane_regs.h new file mode 100644 index 000000000000..5d7ba824f354 --- /dev/null +++ b/drivers/gpu/drm/i915/display/i9xx_plane_regs.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __I9XX_PLANE_REGS_H__ +#define __I9XX_PLANE_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define _DSPAADDR_VLV 0x7017C /* vlv/chv */ +#define DSPADDR_VLV(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPAADDR_VLV) + +#define _DSPACNTR 0x70180 +#define DSPCNTR(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPACNTR) +#define DISP_ENABLE REG_BIT(31) +#define DISP_PIPE_GAMMA_ENABLE REG_BIT(30) +#define DISP_FORMAT_MASK REG_GENMASK(29, 26) +#define DISP_FORMAT_8BPP REG_FIELD_PREP(DISP_FORMAT_MASK, 2) +#define DISP_FORMAT_BGRA555 REG_FIELD_PREP(DISP_FORMAT_MASK, 3) +#define DISP_FORMAT_BGRX555 REG_FIELD_PREP(DISP_FORMAT_MASK, 4) +#define DISP_FORMAT_BGRX565 REG_FIELD_PREP(DISP_FORMAT_MASK, 5) +#define DISP_FORMAT_BGRX888 REG_FIELD_PREP(DISP_FORMAT_MASK, 6) +#define DISP_FORMAT_BGRA888 REG_FIELD_PREP(DISP_FORMAT_MASK, 7) +#define DISP_FORMAT_RGBX101010 REG_FIELD_PREP(DISP_FORMAT_MASK, 8) +#define DISP_FORMAT_RGBA101010 REG_FIELD_PREP(DISP_FORMAT_MASK, 9) +#define DISP_FORMAT_BGRX101010 REG_FIELD_PREP(DISP_FORMAT_MASK, 10) +#define DISP_FORMAT_BGRA101010 REG_FIELD_PREP(DISP_FORMAT_MASK, 11) +#define DISP_FORMAT_RGBX161616 REG_FIELD_PREP(DISP_FORMAT_MASK, 12) +#define DISP_FORMAT_RGBX888 REG_FIELD_PREP(DISP_FORMAT_MASK, 14) +#define DISP_FORMAT_RGBA888 REG_FIELD_PREP(DISP_FORMAT_MASK, 15) +#define DISP_STEREO_ENABLE REG_BIT(25) +#define DISP_PIPE_CSC_ENABLE REG_BIT(24) /* ilk+ */ +#define DISP_PIPE_SEL_MASK REG_GENMASK(25, 24) +#define DISP_PIPE_SEL(pipe) REG_FIELD_PREP(DISP_PIPE_SEL_MASK, (pipe)) +#define DISP_SRC_KEY_ENABLE REG_BIT(22) +#define DISP_LINE_DOUBLE REG_BIT(20) +#define DISP_STEREO_POLARITY_SECOND REG_BIT(18) +#define DISP_ALPHA_PREMULTIPLY REG_BIT(16) /* CHV pipe B */ +#define DISP_ROTATE_180 REG_BIT(15) /* i965+ */ +#define DISP_ALPHA_TRANS_ENABLE REG_BIT(15) /* pre-g4x plane B */ +#define DISP_TRICKLE_FEED_DISABLE REG_BIT(14) /* g4x+ */ +#define DISP_TILED REG_BIT(10) /* i965+ */ +#define DISP_ASYNC_FLIP REG_BIT(9) /* g4x+ */ +#define DISP_MIRROR REG_BIT(8) /* CHV pipe B */ +#define DISP_SPRITE_ABOVE_OVERLAY REG_BIT(0) /* pre-g4x plane B/C */ + +#define _DSPAADDR 0x70184 /* pre-i965 */ +#define DSPADDR(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPAADDR) + +#define _DSPALINOFF 0x70184 /* i965+ */ +#define DSPLINOFF(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPALINOFF) + +#define _DSPASTRIDE 0x70188 +#define DSPSTRIDE(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPASTRIDE) + +#define _DSPAPOS 0x7018C /* pre-g4x */ +#define DSPPOS(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPAPOS) +#define DISP_POS_Y_MASK REG_GENMASK(31, 16) +#define DISP_POS_Y(y) REG_FIELD_PREP(DISP_POS_Y_MASK, (y)) +#define DISP_POS_X_MASK REG_GENMASK(15, 0) +#define DISP_POS_X(x) REG_FIELD_PREP(DISP_POS_X_MASK, (x)) + +#define _DSPASIZE 0x70190 /* pre-g4x */ +#define DSPSIZE(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPASIZE) +#define DISP_HEIGHT_MASK REG_GENMASK(31, 16) +#define DISP_HEIGHT(h) REG_FIELD_PREP(DISP_HEIGHT_MASK, (h)) +#define DISP_WIDTH_MASK REG_GENMASK(15, 0) +#define DISP_WIDTH(w) REG_FIELD_PREP(DISP_WIDTH_MASK, (w)) + +#define _DSPASURF 0x7019C /* i965+ */ +#define DSPSURF(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPASURF) +#define DISP_ADDR_MASK REG_GENMASK(31, 12) + +#define _DSPATILEOFF 0x701A4 /* i965+ */ +#define DSPTILEOFF(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPATILEOFF) +#define DISP_OFFSET_Y_MASK REG_GENMASK(31, 16) +#define DISP_OFFSET_Y(y) REG_FIELD_PREP(DISP_OFFSET_Y_MASK, (y)) +#define DISP_OFFSET_X_MASK REG_GENMASK(15, 0) +#define DISP_OFFSET_X(x) REG_FIELD_PREP(DISP_OFFSET_X_MASK, (x)) + +#define _DSPAOFFSET 0x701A4 /* hsw+ */ +#define DSPOFFSET(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPAOFFSET) + +#define _DSPASURFLIVE 0x701AC /* g4x+ */ +#define DSPSURFLIVE(dev_priv, plane) _MMIO_PIPE2(dev_priv, plane, _DSPASURFLIVE) + +#define _DSPAGAMC 0x701E0 /* pre-g4x */ +#define DSPGAMC(dev_priv, plane, i) _MMIO_PIPE2(dev_priv, plane, _DSPAGAMC + (5 - (i)) * 4) /* plane C only, 6 x u0.8 */ + +/* CHV pipe B primary plane */ +#define _PRIMPOS_A 0x60a08 +#define PRIMPOS(dev_priv, plane) _MMIO_TRANS2(dev_priv, plane, _PRIMPOS_A) +#define PRIM_POS_Y_MASK REG_GENMASK(31, 16) +#define PRIM_POS_Y(y) REG_FIELD_PREP(PRIM_POS_Y_MASK, (y)) +#define PRIM_POS_X_MASK REG_GENMASK(15, 0) +#define PRIM_POS_X(x) REG_FIELD_PREP(PRIM_POS_X_MASK, (x)) + +#define _PRIMSIZE_A 0x60a0c +#define PRIMSIZE(dev_priv, plane) _MMIO_TRANS2(dev_priv, plane, _PRIMSIZE_A) +#define PRIM_HEIGHT_MASK REG_GENMASK(31, 16) +#define PRIM_HEIGHT(h) REG_FIELD_PREP(PRIM_HEIGHT_MASK, (h)) +#define PRIM_WIDTH_MASK REG_GENMASK(15, 0) +#define PRIM_WIDTH(w) REG_FIELD_PREP(PRIM_WIDTH_MASK, (w)) + +#define _PRIMCNSTALPHA_A 0x60a10 +#define PRIMCNSTALPHA(dev_priv, plane) _MMIO_TRANS2(dev_priv, plane, _PRIMCNSTALPHA_A) +#define PRIM_CONST_ALPHA_ENABLE REG_BIT(31) +#define PRIM_CONST_ALPHA_MASK REG_GENMASK(7, 0) +#define PRIM_CONST_ALPHA(alpha) REG_FIELD_PREP(PRIM_CONST_ALPHA_MASK, (alpha)) + +#endif /* __I9XX_PLANE_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 628e7192ebc9..2b7c3d270b17 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -70,25 +70,24 @@ static const struct cxsr_latency cxsr_latency_table[] = { {0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */ }; -static const struct cxsr_latency *intel_get_cxsr_latency(struct drm_i915_private *i915) +static const struct cxsr_latency *pnv_get_cxsr_latency(struct drm_i915_private *i915) { int i; - if (i915->fsb_freq == 0 || i915->mem_freq == 0) - return NULL; - for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) { const struct cxsr_latency *latency = &cxsr_latency_table[i]; bool is_desktop = !IS_MOBILE(i915); if (is_desktop == latency->is_desktop && i915->is_ddr3 == latency->is_ddr3 && - i915->fsb_freq == latency->fsb_freq && - i915->mem_freq == latency->mem_freq) + DIV_ROUND_CLOSEST(i915->fsb_freq, 1000) == latency->fsb_freq && + DIV_ROUND_CLOSEST(i915->mem_freq, 1000) == latency->mem_freq) return latency; } - drm_dbg_kms(&i915->drm, "Unknown FSB/MEM found, disable CxSR\n"); + drm_dbg_kms(&i915->drm, + "Could not find CxSR latency for DDR%s, FSB %u kHz, MEM %u kHz\n", + i915->is_ddr3 ? "3" : "2", i915->fsb_freq, i915->mem_freq); return NULL; } @@ -149,14 +148,14 @@ static bool _intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enabl intel_uncore_write(&dev_priv->uncore, FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0); intel_uncore_posting_read(&dev_priv->uncore, FW_BLC_SELF); } else if (IS_PINEVIEW(dev_priv)) { - val = intel_uncore_read(&dev_priv->uncore, DSPFW3); + val = intel_uncore_read(&dev_priv->uncore, DSPFW3(dev_priv)); was_enabled = val & PINEVIEW_SELF_REFRESH_EN; if (enable) val |= PINEVIEW_SELF_REFRESH_EN; else val &= ~PINEVIEW_SELF_REFRESH_EN; - intel_uncore_write(&dev_priv->uncore, DSPFW3, val); - intel_uncore_posting_read(&dev_priv->uncore, DSPFW3); + intel_uncore_write(&dev_priv->uncore, DSPFW3(dev_priv), val); + intel_uncore_posting_read(&dev_priv->uncore, DSPFW3(dev_priv)); } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) { was_enabled = intel_uncore_read(&dev_priv->uncore, FW_BLC_SELF) & FW_BLC_SELF_EN; val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) : @@ -269,13 +268,15 @@ static void vlv_get_fifo_size(struct intel_crtc_state *crtc_state) switch (pipe) { case PIPE_A: - dsparb = intel_uncore_read(&dev_priv->uncore, DSPARB); + dsparb = intel_uncore_read(&dev_priv->uncore, + DSPARB(dev_priv)); dsparb2 = intel_uncore_read(&dev_priv->uncore, DSPARB2); sprite0_start = VLV_FIFO_START(dsparb, dsparb2, 0, 0); sprite1_start = VLV_FIFO_START(dsparb, dsparb2, 8, 4); break; case PIPE_B: - dsparb = intel_uncore_read(&dev_priv->uncore, DSPARB); + dsparb = intel_uncore_read(&dev_priv->uncore, + DSPARB(dev_priv)); dsparb2 = intel_uncore_read(&dev_priv->uncore, DSPARB2); sprite0_start = VLV_FIFO_START(dsparb, dsparb2, 16, 8); sprite1_start = VLV_FIFO_START(dsparb, dsparb2, 24, 12); @@ -300,7 +301,7 @@ static void vlv_get_fifo_size(struct intel_crtc_state *crtc_state) static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv, enum i9xx_plane_id i9xx_plane) { - u32 dsparb = intel_uncore_read(&dev_priv->uncore, DSPARB); + u32 dsparb = intel_uncore_read(&dev_priv->uncore, DSPARB(dev_priv)); int size; size = dsparb & 0x7f; @@ -316,7 +317,7 @@ static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv, static int i830_get_fifo_size(struct drm_i915_private *dev_priv, enum i9xx_plane_id i9xx_plane) { - u32 dsparb = intel_uncore_read(&dev_priv->uncore, DSPARB); + u32 dsparb = intel_uncore_read(&dev_priv->uncore, DSPARB(dev_priv)); int size; size = dsparb & 0x1ff; @@ -333,7 +334,7 @@ static int i830_get_fifo_size(struct drm_i915_private *dev_priv, static int i845_get_fifo_size(struct drm_i915_private *dev_priv, enum i9xx_plane_id i9xx_plane) { - u32 dsparb = intel_uncore_read(&dev_priv->uncore, DSPARB); + u32 dsparb = intel_uncore_read(&dev_priv->uncore, DSPARB(dev_priv)); int size; size = dsparb & 0x7f; @@ -635,10 +636,9 @@ static void pnv_update_wm(struct drm_i915_private *dev_priv) u32 reg; unsigned int wm; - latency = intel_get_cxsr_latency(dev_priv); + latency = pnv_get_cxsr_latency(dev_priv); if (!latency) { - drm_dbg_kms(&dev_priv->drm, - "Unknown FSB/MEM found, disable CxSR\n"); + drm_dbg_kms(&dev_priv->drm, "Unknown FSB/MEM, disabling CxSR\n"); intel_set_memory_cxsr(dev_priv, false); return; } @@ -655,10 +655,10 @@ static void pnv_update_wm(struct drm_i915_private *dev_priv) &pnv_display_wm, pnv_display_wm.fifo_size, cpp, latency->display_sr); - reg = intel_uncore_read(&dev_priv->uncore, DSPFW1); + reg = intel_uncore_read(&dev_priv->uncore, DSPFW1(dev_priv)); reg &= ~DSPFW_SR_MASK; reg |= FW_WM(wm, SR); - intel_uncore_write(&dev_priv->uncore, DSPFW1, reg); + intel_uncore_write(&dev_priv->uncore, DSPFW1(dev_priv), reg); drm_dbg_kms(&dev_priv->drm, "DSPFW1 register is %x\n", reg); /* cursor SR */ @@ -666,7 +666,8 @@ static void pnv_update_wm(struct drm_i915_private *dev_priv) &pnv_cursor_wm, pnv_display_wm.fifo_size, 4, latency->cursor_sr); - intel_uncore_rmw(&dev_priv->uncore, DSPFW3, DSPFW_CURSOR_SR_MASK, + intel_uncore_rmw(&dev_priv->uncore, DSPFW3(dev_priv), + DSPFW_CURSOR_SR_MASK, FW_WM(wm, CURSOR_SR)); /* Display HPLL off SR */ @@ -674,17 +675,18 @@ static void pnv_update_wm(struct drm_i915_private *dev_priv) &pnv_display_hplloff_wm, pnv_display_hplloff_wm.fifo_size, cpp, latency->display_hpll_disable); - intel_uncore_rmw(&dev_priv->uncore, DSPFW3, DSPFW_HPLL_SR_MASK, FW_WM(wm, HPLL_SR)); + intel_uncore_rmw(&dev_priv->uncore, DSPFW3(dev_priv), + DSPFW_HPLL_SR_MASK, FW_WM(wm, HPLL_SR)); /* cursor HPLL off SR */ wm = intel_calculate_wm(dev_priv, pixel_rate, &pnv_cursor_hplloff_wm, pnv_display_hplloff_wm.fifo_size, 4, latency->cursor_hpll_disable); - reg = intel_uncore_read(&dev_priv->uncore, DSPFW3); + reg = intel_uncore_read(&dev_priv->uncore, DSPFW3(dev_priv)); reg &= ~DSPFW_HPLL_CURSOR_MASK; reg |= FW_WM(wm, HPLL_CURSOR); - intel_uncore_write(&dev_priv->uncore, DSPFW3, reg); + intel_uncore_write(&dev_priv->uncore, DSPFW3(dev_priv), reg); drm_dbg_kms(&dev_priv->drm, "DSPFW3 register is %x\n", reg); intel_set_memory_cxsr(dev_priv, true); @@ -718,25 +720,25 @@ static void g4x_write_wm_values(struct drm_i915_private *dev_priv, for_each_pipe(dev_priv, pipe) trace_g4x_wm(intel_crtc_for_pipe(dev_priv, pipe), wm); - intel_uncore_write(&dev_priv->uncore, DSPFW1, + intel_uncore_write(&dev_priv->uncore, DSPFW1(dev_priv), FW_WM(wm->sr.plane, SR) | FW_WM(wm->pipe[PIPE_B].plane[PLANE_CURSOR], CURSORB) | FW_WM(wm->pipe[PIPE_B].plane[PLANE_PRIMARY], PLANEB) | FW_WM(wm->pipe[PIPE_A].plane[PLANE_PRIMARY], PLANEA)); - intel_uncore_write(&dev_priv->uncore, DSPFW2, + intel_uncore_write(&dev_priv->uncore, DSPFW2(dev_priv), (wm->fbc_en ? DSPFW_FBC_SR_EN : 0) | FW_WM(wm->sr.fbc, FBC_SR) | FW_WM(wm->hpll.fbc, FBC_HPLL_SR) | FW_WM(wm->pipe[PIPE_B].plane[PLANE_SPRITE0], SPRITEB) | FW_WM(wm->pipe[PIPE_A].plane[PLANE_CURSOR], CURSORA) | FW_WM(wm->pipe[PIPE_A].plane[PLANE_SPRITE0], SPRITEA)); - intel_uncore_write(&dev_priv->uncore, DSPFW3, + intel_uncore_write(&dev_priv->uncore, DSPFW3(dev_priv), (wm->hpll_en ? DSPFW_HPLL_SR_EN : 0) | FW_WM(wm->sr.cursor, CURSOR_SR) | FW_WM(wm->hpll.cursor, HPLL_CURSOR) | FW_WM(wm->hpll.plane, HPLL_SR)); - intel_uncore_posting_read(&dev_priv->uncore, DSPFW1); + intel_uncore_posting_read(&dev_priv->uncore, DSPFW1(dev_priv)); } #define FW_WM_VLV(value, plane) \ @@ -768,16 +770,16 @@ static void vlv_write_wm_values(struct drm_i915_private *dev_priv, intel_uncore_write(&dev_priv->uncore, DSPFW5, 0); intel_uncore_write(&dev_priv->uncore, DSPFW6, 0); - intel_uncore_write(&dev_priv->uncore, DSPFW1, + intel_uncore_write(&dev_priv->uncore, DSPFW1(dev_priv), FW_WM(wm->sr.plane, SR) | FW_WM(wm->pipe[PIPE_B].plane[PLANE_CURSOR], CURSORB) | FW_WM_VLV(wm->pipe[PIPE_B].plane[PLANE_PRIMARY], PLANEB) | FW_WM_VLV(wm->pipe[PIPE_A].plane[PLANE_PRIMARY], PLANEA)); - intel_uncore_write(&dev_priv->uncore, DSPFW2, + intel_uncore_write(&dev_priv->uncore, DSPFW2(dev_priv), FW_WM_VLV(wm->pipe[PIPE_A].plane[PLANE_SPRITE1], SPRITEB) | FW_WM(wm->pipe[PIPE_A].plane[PLANE_CURSOR], CURSORA) | FW_WM_VLV(wm->pipe[PIPE_A].plane[PLANE_SPRITE0], SPRITEA)); - intel_uncore_write(&dev_priv->uncore, DSPFW3, + intel_uncore_write(&dev_priv->uncore, DSPFW3(dev_priv), FW_WM(wm->sr.cursor, CURSOR_SR)); if (IS_CHERRYVIEW(dev_priv)) { @@ -815,7 +817,7 @@ static void vlv_write_wm_values(struct drm_i915_private *dev_priv, FW_WM(wm->pipe[PIPE_A].plane[PLANE_PRIMARY] >> 8, PLANEA_HI)); } - intel_uncore_posting_read(&dev_priv->uncore, DSPFW1); + intel_uncore_posting_read(&dev_priv->uncore, DSPFW1(dev_priv)); } #undef FW_WM_VLV @@ -1787,7 +1789,7 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state, switch (crtc->pipe) { case PIPE_A: - dsparb = intel_uncore_read_fw(uncore, DSPARB); + dsparb = intel_uncore_read_fw(uncore, DSPARB(dev_priv)); dsparb2 = intel_uncore_read_fw(uncore, DSPARB2); dsparb &= ~(VLV_FIFO(SPRITEA, 0xff) | @@ -1800,11 +1802,11 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state, dsparb2 |= (VLV_FIFO(SPRITEA_HI, sprite0_start >> 8) | VLV_FIFO(SPRITEB_HI, sprite1_start >> 8)); - intel_uncore_write_fw(uncore, DSPARB, dsparb); + intel_uncore_write_fw(uncore, DSPARB(dev_priv), dsparb); intel_uncore_write_fw(uncore, DSPARB2, dsparb2); break; case PIPE_B: - dsparb = intel_uncore_read_fw(uncore, DSPARB); + dsparb = intel_uncore_read_fw(uncore, DSPARB(dev_priv)); dsparb2 = intel_uncore_read_fw(uncore, DSPARB2); dsparb &= ~(VLV_FIFO(SPRITEC, 0xff) | @@ -1817,7 +1819,7 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state, dsparb2 |= (VLV_FIFO(SPRITEC_HI, sprite0_start >> 8) | VLV_FIFO(SPRITED_HI, sprite1_start >> 8)); - intel_uncore_write_fw(uncore, DSPARB, dsparb); + intel_uncore_write_fw(uncore, DSPARB(dev_priv), dsparb); intel_uncore_write_fw(uncore, DSPARB2, dsparb2); break; case PIPE_C: @@ -1841,7 +1843,7 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state, break; } - intel_uncore_posting_read_fw(uncore, DSPARB); + intel_uncore_posting_read_fw(uncore, DSPARB(dev_priv)); spin_unlock(&uncore->lock); } @@ -2065,14 +2067,17 @@ static void i965_update_wm(struct drm_i915_private *dev_priv) srwm); /* 965 has limitations... */ - intel_uncore_write(&dev_priv->uncore, DSPFW1, FW_WM(srwm, SR) | - FW_WM(8, CURSORB) | - FW_WM(8, PLANEB) | - FW_WM(8, PLANEA)); - intel_uncore_write(&dev_priv->uncore, DSPFW2, FW_WM(8, CURSORA) | - FW_WM(8, PLANEC_OLD)); + intel_uncore_write(&dev_priv->uncore, DSPFW1(dev_priv), + FW_WM(srwm, SR) | + FW_WM(8, CURSORB) | + FW_WM(8, PLANEB) | + FW_WM(8, PLANEA)); + intel_uncore_write(&dev_priv->uncore, DSPFW2(dev_priv), + FW_WM(8, CURSORA) | + FW_WM(8, PLANEC_OLD)); /* update cursor SR watermark */ - intel_uncore_write(&dev_priv->uncore, DSPFW3, FW_WM(cursor_sr, CURSOR_SR)); + intel_uncore_write(&dev_priv->uncore, DSPFW3(dev_priv), + FW_WM(cursor_sr, CURSOR_SR)); if (cxsr_enabled) intel_set_memory_cxsr(dev_priv, true); @@ -3519,13 +3524,13 @@ static void g4x_read_wm_values(struct drm_i915_private *dev_priv, { u32 tmp; - tmp = intel_uncore_read(&dev_priv->uncore, DSPFW1); + tmp = intel_uncore_read(&dev_priv->uncore, DSPFW1(dev_priv)); wm->sr.plane = _FW_WM(tmp, SR); wm->pipe[PIPE_B].plane[PLANE_CURSOR] = _FW_WM(tmp, CURSORB); wm->pipe[PIPE_B].plane[PLANE_PRIMARY] = _FW_WM(tmp, PLANEB); wm->pipe[PIPE_A].plane[PLANE_PRIMARY] = _FW_WM(tmp, PLANEA); - tmp = intel_uncore_read(&dev_priv->uncore, DSPFW2); + tmp = intel_uncore_read(&dev_priv->uncore, DSPFW2(dev_priv)); wm->fbc_en = tmp & DSPFW_FBC_SR_EN; wm->sr.fbc = _FW_WM(tmp, FBC_SR); wm->hpll.fbc = _FW_WM(tmp, FBC_HPLL_SR); @@ -3533,7 +3538,7 @@ static void g4x_read_wm_values(struct drm_i915_private *dev_priv, wm->pipe[PIPE_A].plane[PLANE_CURSOR] = _FW_WM(tmp, CURSORA); wm->pipe[PIPE_A].plane[PLANE_SPRITE0] = _FW_WM(tmp, SPRITEA); - tmp = intel_uncore_read(&dev_priv->uncore, DSPFW3); + tmp = intel_uncore_read(&dev_priv->uncore, DSPFW3(dev_priv)); wm->hpll_en = tmp & DSPFW_HPLL_SR_EN; wm->sr.cursor = _FW_WM(tmp, CURSOR_SR); wm->hpll.cursor = _FW_WM(tmp, HPLL_CURSOR); @@ -3559,18 +3564,18 @@ static void vlv_read_wm_values(struct drm_i915_private *dev_priv, (tmp >> DDL_SPRITE_SHIFT(1)) & (DDL_PRECISION_HIGH | DRAIN_LATENCY_MASK); } - tmp = intel_uncore_read(&dev_priv->uncore, DSPFW1); + tmp = intel_uncore_read(&dev_priv->uncore, DSPFW1(dev_priv)); wm->sr.plane = _FW_WM(tmp, SR); wm->pipe[PIPE_B].plane[PLANE_CURSOR] = _FW_WM(tmp, CURSORB); wm->pipe[PIPE_B].plane[PLANE_PRIMARY] = _FW_WM_VLV(tmp, PLANEB); wm->pipe[PIPE_A].plane[PLANE_PRIMARY] = _FW_WM_VLV(tmp, PLANEA); - tmp = intel_uncore_read(&dev_priv->uncore, DSPFW2); + tmp = intel_uncore_read(&dev_priv->uncore, DSPFW2(dev_priv)); wm->pipe[PIPE_A].plane[PLANE_SPRITE1] = _FW_WM_VLV(tmp, SPRITEB); wm->pipe[PIPE_A].plane[PLANE_CURSOR] = _FW_WM(tmp, CURSORA); wm->pipe[PIPE_A].plane[PLANE_SPRITE0] = _FW_WM_VLV(tmp, SPRITEA); - tmp = intel_uncore_read(&dev_priv->uncore, DSPFW3); + tmp = intel_uncore_read(&dev_priv->uncore, DSPFW3(dev_priv)); wm->sr.cursor = _FW_WM(tmp, CURSOR_SR); if (IS_CHERRYVIEW(dev_priv)) { @@ -4022,13 +4027,8 @@ void i9xx_wm_init(struct drm_i915_private *dev_priv) g4x_setup_wm_latency(dev_priv); dev_priv->display.funcs.wm = &g4x_wm_funcs; } else if (IS_PINEVIEW(dev_priv)) { - if (!intel_get_cxsr_latency(dev_priv)) { - drm_info(&dev_priv->drm, - "failed to find known CxSR latency " - "(found ddr%s fsb freq %d, mem freq %d), " - "disabling CxSR\n", - (dev_priv->is_ddr3 == 1) ? "3" : "2", - dev_priv->fsb_freq, dev_priv->mem_freq); + if (!pnv_get_cxsr_latency(dev_priv)) { + drm_info(&dev_priv->drm, "Unknown FSB/MEM, disabling CxSR\n"); /* Disable CxSR and never update its watermark again */ intel_set_memory_cxsr(dev_priv, false); dev_priv->display.funcs.wm = &nop_funcs; diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 79ecfc339430..ae8f6617aa70 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -784,7 +784,8 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, if (intel_dsi->dual_link) { for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); - intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL2(dsi_trans), + intel_de_rmw(dev_priv, + TRANS_DDI_FUNC_CTL2(dev_priv, dsi_trans), 0, PORT_SYNC_MODE_ENABLE); } @@ -796,7 +797,8 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, dsi_trans = dsi_port_to_transcoder(port); /* select data lane width */ - tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(dsi_trans)); + tmp = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans)); tmp &= ~DDI_PORT_WIDTH_MASK; tmp |= DDI_PORT_WIDTH(intel_dsi->lane_count); @@ -822,7 +824,8 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, /* enable DDI buffer */ tmp |= TRANS_DDI_FUNC_ENABLE; - intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dsi_trans), tmp); + intel_de_write(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans), tmp); } /* wait for link ready */ @@ -915,7 +918,7 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder, /* program TRANS_HTOTAL register */ for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); - intel_de_write(dev_priv, TRANS_HTOTAL(dsi_trans), + intel_de_write(dev_priv, TRANS_HTOTAL(dev_priv, dsi_trans), HACTIVE(hactive - 1) | HTOTAL(htotal - 1)); } @@ -938,7 +941,8 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder, for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); - intel_de_write(dev_priv, TRANS_HSYNC(dsi_trans), + intel_de_write(dev_priv, + TRANS_HSYNC(dev_priv, dsi_trans), HSYNC_START(hsync_start - 1) | HSYNC_END(hsync_end - 1)); } } @@ -952,7 +956,7 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder, * struct drm_display_mode. * For interlace mode: program required pixel minus 2 */ - intel_de_write(dev_priv, TRANS_VTOTAL(dsi_trans), + intel_de_write(dev_priv, TRANS_VTOTAL(dev_priv, dsi_trans), VACTIVE(vactive - 1) | VTOTAL(vtotal - 1)); } @@ -966,7 +970,8 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder, if (is_vid_mode(intel_dsi)) { for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); - intel_de_write(dev_priv, TRANS_VSYNC(dsi_trans), + intel_de_write(dev_priv, + TRANS_VSYNC(dev_priv, dsi_trans), VSYNC_START(vsync_start - 1) | VSYNC_END(vsync_end - 1)); } } @@ -980,7 +985,8 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder, if (is_vid_mode(intel_dsi)) { for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); - intel_de_write(dev_priv, TRANS_VSYNCSHIFT(dsi_trans), + intel_de_write(dev_priv, + TRANS_VSYNCSHIFT(dev_priv, dsi_trans), vsync_shift); } } @@ -994,7 +1000,8 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder, if (DISPLAY_VER(dev_priv) >= 12) { for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); - intel_de_write(dev_priv, TRANS_VBLANK(dsi_trans), + intel_de_write(dev_priv, + TRANS_VBLANK(dev_priv, dsi_trans), VBLANK_START(vactive - 1) | VBLANK_END(vtotal - 1)); } } @@ -1009,10 +1016,11 @@ static void gen11_dsi_enable_transcoder(struct intel_encoder *encoder) for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); - intel_de_rmw(dev_priv, TRANSCONF(dsi_trans), 0, TRANSCONF_ENABLE); + intel_de_rmw(dev_priv, TRANSCONF(dev_priv, dsi_trans), 0, + TRANSCONF_ENABLE); /* wait for transcoder to be enabled */ - if (intel_de_wait_for_set(dev_priv, TRANSCONF(dsi_trans), + if (intel_de_wait_for_set(dev_priv, TRANSCONF(dev_priv, dsi_trans), TRANSCONF_STATE_ENABLE, 10)) drm_err(&dev_priv->drm, "DSI transcoder not enabled\n"); @@ -1275,10 +1283,11 @@ static void gen11_dsi_disable_transcoder(struct intel_encoder *encoder) dsi_trans = dsi_port_to_transcoder(port); /* disable transcoder */ - intel_de_rmw(dev_priv, TRANSCONF(dsi_trans), TRANSCONF_ENABLE, 0); + intel_de_rmw(dev_priv, TRANSCONF(dev_priv, dsi_trans), + TRANSCONF_ENABLE, 0); /* wait for transcoder to be disabled */ - if (intel_de_wait_for_clear(dev_priv, TRANSCONF(dsi_trans), + if (intel_de_wait_for_clear(dev_priv, TRANSCONF(dev_priv, dsi_trans), TRANSCONF_STATE_ENABLE, 50)) drm_err(&dev_priv->drm, "DSI trancoder not disabled\n"); @@ -1327,7 +1336,8 @@ static void gen11_dsi_deconfigure_trancoder(struct intel_encoder *encoder) /* disable ddi function */ for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); - intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(dsi_trans), + intel_de_rmw(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans), TRANS_DDI_FUNC_ENABLE, 0); } @@ -1335,7 +1345,8 @@ static void gen11_dsi_deconfigure_trancoder(struct intel_encoder *encoder) if (intel_dsi->dual_link) { for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); - intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL2(dsi_trans), + intel_de_rmw(dev_priv, + TRANS_DDI_FUNC_CTL2(dev_priv, dsi_trans), PORT_SYNC_MODE_ENABLE, 0); } } @@ -1691,7 +1702,8 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder, for_each_dsi_port(port, intel_dsi->ports) { dsi_trans = dsi_port_to_transcoder(port); - tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(dsi_trans)); + tmp = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans)); switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { case TRANS_DDI_EDP_INPUT_A_ON: *pipe = PIPE_A; @@ -1710,7 +1722,7 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder, goto out; } - tmp = intel_de_read(dev_priv, TRANSCONF(dsi_trans)); + tmp = intel_de_read(dev_priv, TRANSCONF(dev_priv, dsi_trans)); ret = tmp & TRANSCONF_ENABLE; } out: diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c new file mode 100644 index 000000000000..c7092af7da33 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2024, Intel Corporation. + */ + +#include "intel_alpm.h" +#include "intel_crtc.h" +#include "intel_de.h" +#include "intel_display_types.h" +#include "intel_dp.h" +#include "intel_dp_aux.h" +#include "intel_psr_regs.h" + +bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp) +{ + return intel_dp->alpm_dpcd & DP_ALPM_CAP; +} + +bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp) +{ + return intel_dp->alpm_dpcd & DP_ALPM_AUX_LESS_CAP; +} + +void intel_alpm_init_dpcd(struct intel_dp *intel_dp) +{ + u8 dpcd; + + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_RECEIVER_ALPM_CAP, &dpcd) < 0) + return; + + intel_dp->alpm_dpcd = dpcd; +} + +/* + * See Bspec: 71632 for the table + * + * Silence_period = tSilence,Min + ((tSilence,Max - tSilence,Min) / 2) + * + * Half cycle duration: + * + * Link rates 1.62 - 4.32 and tLFPS_Cycle = 70 ns + * FLOOR( (Link Rate * tLFPS_Cycle) / (2 * 10) ) + * + * Link rates 5.4 - 8.1 + * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ] = 10 + * LFPS Period chosen is the mid-point of the min:max values from the table + * FLOOR( LFPS Period in Symbol clocks / + * (2 * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ]) ) + */ +static bool _lnl_get_silence_period_and_lfps_half_cycle(int link_rate, + int *silence_period, + int *lfps_half_cycle) +{ + switch (link_rate) { + case 162000: + *silence_period = 20; + *lfps_half_cycle = 5; + break; + case 216000: + *silence_period = 27; + *lfps_half_cycle = 7; + break; + case 243000: + *silence_period = 31; + *lfps_half_cycle = 8; + break; + case 270000: + *silence_period = 34; + *lfps_half_cycle = 9; + break; + case 324000: + *silence_period = 41; + *lfps_half_cycle = 11; + break; + case 432000: + *silence_period = 56; + *lfps_half_cycle = 15; + break; + case 540000: + *silence_period = 69; + *lfps_half_cycle = 12; + break; + case 648000: + *silence_period = 84; + *lfps_half_cycle = 15; + break; + case 675000: + *silence_period = 87; + *lfps_half_cycle = 15; + break; + case 810000: + *silence_period = 104; + *lfps_half_cycle = 19; + break; + default: + *silence_period = *lfps_half_cycle = -1; + return false; + } + return true; +} + +/* + * AUX-Less Wake Time = CEILING( ((PHY P2 to P0) + tLFPS_Period, Max+ + * tSilence, Max+ tPHY Establishment + tCDS) / tline) + * For the "PHY P2 to P0" latency see the PHY Power Control page + * (PHY P2 to P0) : https://gfxspecs.intel.com/Predator/Home/Index/68965 + * : 12 us + * The tLFPS_Period, Max term is 800ns + * The tSilence, Max term is 180ns + * The tPHY Establishment (a.k.a. t1) term is 50us + * The tCDS term is 1 or 2 times t2 + * t2 = Number ML_PHY_LOCK * tML_PHY_LOCK + * Number ML_PHY_LOCK = ( 7 + CEILING( 6.5us / tML_PHY_LOCK ) + 1) + * Rounding up the 6.5us padding to the next ML_PHY_LOCK boundary and + * adding the "+ 1" term ensures all ML_PHY_LOCK sequences that start + * within the CDS period complete within the CDS period regardless of + * entry into the period + * tML_PHY_LOCK = TPS4 Length * ( 10 / (Link Rate in MHz) ) + * TPS4 Length = 252 Symbols + */ +static int _lnl_compute_aux_less_wake_time(int port_clock) +{ + int tphy2_p2_to_p0 = 12 * 1000; + int tlfps_period_max = 800; + int tsilence_max = 180; + int t1 = 50 * 1000; + int tps4 = 252; + /* port_clock is link rate in 10kbit/s units */ + int tml_phy_lock = 1000 * 1000 * tps4 / port_clock; + int num_ml_phy_lock = 7 + DIV_ROUND_UP(6500, tml_phy_lock) + 1; + int t2 = num_ml_phy_lock * tml_phy_lock; + int tcds = 1 * t2; + + return DIV_ROUND_UP(tphy2_p2_to_p0 + tlfps_period_max + tsilence_max + + t1 + tcds, 1000); +} + +static int _lnl_compute_aux_less_alpm_params(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + int aux_less_wake_time, aux_less_wake_lines, silence_period, + lfps_half_cycle; + + aux_less_wake_time = + _lnl_compute_aux_less_wake_time(crtc_state->port_clock); + aux_less_wake_lines = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, + aux_less_wake_time); + + if (!_lnl_get_silence_period_and_lfps_half_cycle(crtc_state->port_clock, + &silence_period, + &lfps_half_cycle)) + return false; + + if (aux_less_wake_lines > ALPM_CTL_AUX_LESS_WAKE_TIME_MASK || + silence_period > PORT_ALPM_CTL_SILENCE_PERIOD_MASK || + lfps_half_cycle > PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION_MASK) + return false; + + if (i915->display.params.psr_safest_params) + aux_less_wake_lines = ALPM_CTL_AUX_LESS_WAKE_TIME_MASK; + + intel_dp->alpm_parameters.aux_less_wake_lines = aux_less_wake_lines; + intel_dp->alpm_parameters.silence_period_sym_clocks = silence_period; + intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms = lfps_half_cycle; + + return true; +} + +static bool _lnl_compute_alpm_params(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + int check_entry_lines; + + if (DISPLAY_VER(i915) < 20) + return true; + + /* ALPM Entry Check = 2 + CEILING( 5us /tline ) */ + check_entry_lines = 2 + + intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 5); + + if (check_entry_lines > 15) + return false; + + if (!_lnl_compute_aux_less_alpm_params(intel_dp, crtc_state)) + return false; + + if (i915->display.params.psr_safest_params) + check_entry_lines = 15; + + intel_dp->alpm_parameters.check_entry_lines = check_entry_lines; + + return true; +} + +/* + * IO wake time for DISPLAY_VER < 12 is not directly mentioned in Bspec. There + * are 50 us io wake time and 32 us fast wake time. Clearly preharge pulses are + * not (improperly) included in 32 us fast wake time. 50 us - 32 us = 18 us. + */ +static int skl_io_buffer_wake_time(void) +{ + return 18; +} + +static int tgl_io_buffer_wake_time(void) +{ + return 10; +} + +static int io_buffer_wake_time(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (DISPLAY_VER(i915) >= 12) + return tgl_io_buffer_wake_time(); + else + return skl_io_buffer_wake_time(); +} + +bool intel_alpm_compute_params(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + int io_wake_lines, io_wake_time, fast_wake_lines, fast_wake_time; + int tfw_exit_latency = 20; /* eDP spec */ + int phy_wake = 4; /* eDP spec */ + int preamble = 8; /* eDP spec */ + int precharge = intel_dp_aux_fw_sync_len() - preamble; + u8 max_wake_lines; + + io_wake_time = max(precharge, io_buffer_wake_time(crtc_state)) + + preamble + phy_wake + tfw_exit_latency; + fast_wake_time = precharge + preamble + phy_wake + + tfw_exit_latency; + + if (DISPLAY_VER(i915) >= 20) + max_wake_lines = 68; + else if (DISPLAY_VER(i915) >= 12) + max_wake_lines = 12; + else + max_wake_lines = 8; + + io_wake_lines = intel_usecs_to_scanlines( + &crtc_state->hw.adjusted_mode, io_wake_time); + fast_wake_lines = intel_usecs_to_scanlines( + &crtc_state->hw.adjusted_mode, fast_wake_time); + + if (io_wake_lines > max_wake_lines || + fast_wake_lines > max_wake_lines) + return false; + + if (!_lnl_compute_alpm_params(intel_dp, crtc_state)) + return false; + + if (i915->display.params.psr_safest_params) + io_wake_lines = fast_wake_lines = max_wake_lines; + + /* According to Bspec lower limit should be set as 7 lines. */ + intel_dp->alpm_parameters.io_wake_lines = max(io_wake_lines, 7); + intel_dp->alpm_parameters.fast_wake_lines = max(fast_wake_lines, 7); + + return true; +} + +void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int waketime_in_lines, first_sdp_position; + int context_latency, guardband; + + if (!intel_dp_is_edp(intel_dp)) + return; + + if (DISPLAY_VER(i915) < 20) + return; + + if (!intel_dp_as_sdp_supported(intel_dp)) + return; + + if (crtc_state->has_psr) + return; + + if (!(intel_alpm_aux_wake_supported(intel_dp) || + intel_alpm_aux_less_wake_supported(intel_dp))) + return; + + if (!intel_alpm_compute_params(intel_dp, crtc_state)) + return; + + context_latency = adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay; + guardband = adjusted_mode->crtc_vtotal - + adjusted_mode->crtc_vdisplay - context_latency; + first_sdp_position = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vsync_start; + if (intel_alpm_aux_less_wake_supported(intel_dp)) + waketime_in_lines = intel_dp->alpm_parameters.io_wake_lines; + else + waketime_in_lines = intel_dp->alpm_parameters.aux_less_wake_lines; + + crtc_state->has_lobf = (context_latency + guardband) > + (first_sdp_position + waketime_in_lines); +} + +static void lnl_alpm_configure(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + enum port port = dp_to_dig_port(intel_dp)->base.port; + u32 alpm_ctl; + + if (DISPLAY_VER(dev_priv) < 20 || (!intel_dp->psr.sel_update_enabled && + !intel_dp_is_edp(intel_dp))) + return; + + /* + * Panel Replay on eDP is always using ALPM aux less. I.e. no need to + * check panel support at this point. + */ + if ((intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) || + (crtc_state->has_lobf && intel_alpm_aux_less_wake_supported(intel_dp))) { + alpm_ctl = ALPM_CTL_ALPM_ENABLE | + ALPM_CTL_ALPM_AUX_LESS_ENABLE | + ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS | + ALPM_CTL_AUX_LESS_WAKE_TIME(intel_dp->alpm_parameters.aux_less_wake_lines); + + intel_de_write(dev_priv, + PORT_ALPM_CTL(dev_priv, port), + PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE | + PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) | + PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) | + PORT_ALPM_CTL_SILENCE_PERIOD( + intel_dp->alpm_parameters.silence_period_sym_clocks)); + + intel_de_write(dev_priv, + PORT_ALPM_LFPS_CTL(dev_priv, port), + PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(10) | + PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION( + intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) | + PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION( + intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) | + PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION( + intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms)); + } else { + alpm_ctl = ALPM_CTL_EXTENDED_FAST_WAKE_ENABLE | + ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines); + } + + if (crtc_state->has_lobf) + alpm_ctl |= ALPM_CTL_LOBF_ENABLE; + + alpm_ctl |= ALPM_CTL_ALPM_ENTRY_CHECK(intel_dp->alpm_parameters.check_entry_lines); + + intel_de_write(dev_priv, ALPM_CTL(dev_priv, cpu_transcoder), alpm_ctl); +} + +void intel_alpm_configure(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + lnl_alpm_configure(intel_dp, crtc_state); +} + +static int i915_edp_lobf_info_show(struct seq_file *m, void *data) +{ + struct intel_connector *connector = m->private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_crtc *crtc; + struct intel_crtc_state *crtc_state; + enum transcoder cpu_transcoder; + u32 alpm_ctl; + int ret; + + ret = drm_modeset_lock_single_interruptible(&dev_priv->drm.mode_config.connection_mutex); + if (ret) + return ret; + + crtc = connector->base.state->crtc; + if (connector->base.status != connector_status_connected || !crtc) { + ret = -ENODEV; + goto out; + } + + crtc_state = to_intel_crtc_state(crtc->state); + cpu_transcoder = crtc_state->cpu_transcoder; + alpm_ctl = intel_de_read(dev_priv, ALPM_CTL(dev_priv, cpu_transcoder)); + seq_printf(m, "LOBF status: %s\n", str_enabled_disabled(alpm_ctl & ALPM_CTL_LOBF_ENABLE)); + seq_printf(m, "Aux-wake alpm status: %s\n", + str_enabled_disabled(!(alpm_ctl & ALPM_CTL_ALPM_AUX_LESS_ENABLE))); + seq_printf(m, "Aux-less alpm status: %s\n", + str_enabled_disabled(alpm_ctl & ALPM_CTL_ALPM_AUX_LESS_ENABLE)); +out: + drm_modeset_unlock(&dev_priv->drm.mode_config.connection_mutex); + + return ret; +} + +DEFINE_SHOW_ATTRIBUTE(i915_edp_lobf_info); + +void intel_alpm_lobf_debugfs_add(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct dentry *root = connector->base.debugfs_entry; + + if (DISPLAY_VER(i915) < 20 || + connector->base.connector_type != DRM_MODE_CONNECTOR_eDP) + return; + + debugfs_create_file("i915_edp_lobf_info", 0444, root, + connector, &i915_edp_lobf_info_fops); +} diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h new file mode 100644 index 000000000000..d4fb60393c91 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_alpm.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright © 2024 Intel Corporation + */ + +#ifndef _INTEL_ALPM_H +#define _INTEL_ALPM_H + +#include <linux/types.h> + +struct intel_dp; +struct intel_crtc_state; +struct drm_connector_state; +struct intel_connector; + +void intel_alpm_init_dpcd(struct intel_dp *intel_dp); +bool intel_alpm_compute_params(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state); +void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state); +void intel_alpm_configure(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); +void intel_alpm_lobf_debugfs_add(struct intel_connector *connector); +bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp); +bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp); +#endif diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 7a77ae3dc394..76aa10b6f647 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -35,7 +35,6 @@ #include <drm/drm_fourcc.h> #include "i915_drv.h" -#include "i915_reg.h" #include "intel_atomic.h" #include "intel_cdclk.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 76d77d5a0409..8ec1bab1b15d 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -32,6 +32,7 @@ */ #include <linux/dma-fence-chain.h> +#include <linux/dma-resv.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_gem_atomic_helper.h> @@ -39,7 +40,7 @@ #include <drm/drm_fourcc.h> #include "i915_config.h" -#include "i915_reg.h" +#include "i9xx_plane_regs.h" #include "intel_atomic_plane.h" #include "intel_cdclk.h" #include "intel_display_rps.h" @@ -144,6 +145,14 @@ intel_plane_destroy_state(struct drm_plane *plane, kfree(plane_state); } +bool intel_plane_needs_physical(struct intel_plane *plane) +{ + struct drm_i915_private *i915 = to_i915(plane->base.dev); + + return plane->id == PLANE_CURSOR && + DISPLAY_INFO(i915)->cursor_needs_physical; +} + unsigned int intel_adjusted_rate(const struct drm_rect *src, const struct drm_rect *dst, unsigned int rate) @@ -327,10 +336,10 @@ void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, intel_plane_clear_hw_state(plane_state); /* - * For the bigjoiner slave uapi.crtc will point at - * the master crtc. So we explicitly assign the right - * slave crtc to hw.crtc. uapi.crtc!=NULL simply indicates - * the plane is logically enabled on the uapi level. + * For the joiner secondary uapi.crtc will point at + * the primary crtc. So we explicitly assign the right + * secondary crtc to hw.crtc. uapi.crtc!=NULL simply + * indicates the plane is logically enabled on the uapi level. */ plane_state->hw.crtc = from_plane_state->uapi.crtc ? &crtc->base : NULL; @@ -429,10 +438,16 @@ static bool intel_plane_do_async_flip(struct intel_plane *plane, * In platforms after DISPLAY13, we might need to override * first async flip in order to change watermark levels * as part of optimization. - * So for those, we are checking if this is a first async flip. - * For platforms earlier than DISPLAY13 we always do async flip. + * + * And let's do this for all skl+ so that we can eg. change the + * modifier as well. + * + * TODO: For older platforms there is less reason to do this as + * only X-tile is supported with async flips, though we could + * extend this so other scanout parameters (stride/etc) could + * be changed as well... */ - return DISPLAY_VER(i915) < 13 || old_crtc_state->uapi.async_flip; + return DISPLAY_VER(i915) < 9 || old_crtc_state->uapi.async_flip; } static bool i9xx_must_disable_cxsr(const struct intel_crtc_state *new_crtc_state, @@ -594,6 +609,17 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr if (intel_plane_do_async_flip(plane, old_crtc_state, new_crtc_state)) { new_crtc_state->do_async_flip = true; new_crtc_state->async_flip_planes |= BIT(plane->id); + } else if (plane->need_async_flip_toggle_wa && + new_crtc_state->uapi.async_flip) { + /* + * On platforms with double buffered async flip bit we + * set the bit already one frame early during the sync + * flip (see {i9xx,skl}_plane_update_arm()). The + * hardware will therefore be ready to perform a real + * async flip during the next commit, without having + * to wait yet another frame for the bit to latch. + */ + new_crtc_state->async_flip_planes |= BIT(plane->id); } return 0; @@ -688,27 +714,27 @@ int intel_plane_atomic_check(struct intel_atomic_state *state, intel_atomic_get_new_plane_state(state, plane); const struct intel_plane_state *old_plane_state = intel_atomic_get_old_plane_state(state, plane); - const struct intel_plane_state *new_master_plane_state; + const struct intel_plane_state *new_primary_crtc_plane_state; struct intel_crtc *crtc = intel_crtc_for_pipe(i915, plane->pipe); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - if (new_crtc_state && intel_crtc_is_bigjoiner_slave(new_crtc_state)) { - struct intel_crtc *master_crtc = - intel_master_crtc(new_crtc_state); - struct intel_plane *master_plane = - intel_crtc_get_plane(master_crtc, plane->id); + if (new_crtc_state && intel_crtc_is_joiner_secondary(new_crtc_state)) { + struct intel_crtc *primary_crtc = + intel_primary_crtc(new_crtc_state); + struct intel_plane *primary_crtc_plane = + intel_crtc_get_plane(primary_crtc, plane->id); - new_master_plane_state = - intel_atomic_get_new_plane_state(state, master_plane); + new_primary_crtc_plane_state = + intel_atomic_get_new_plane_state(state, primary_crtc_plane); } else { - new_master_plane_state = new_plane_state; + new_primary_crtc_plane_state = new_plane_state; } intel_plane_copy_uapi_to_hw_state(new_plane_state, - new_master_plane_state, + new_primary_crtc_plane_state, crtc); new_plane_state->uapi.visible = false; diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index 191dad0efc8e..e7a0699f17c8 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -66,5 +66,6 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state); void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); void intel_plane_helper_add(struct intel_plane *plane); +bool intel_plane_needs_physical(struct intel_plane *plane); #endif /* __INTEL_ATOMIC_PLANE_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 40e7d862675e..b9bafec06fb8 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -26,7 +26,7 @@ #include <drm/drm_edid.h> #include <drm/drm_eld.h> -#include <drm/i915_component.h> +#include <drm/intel/i915_component.h> #include "i915_drv.h" #include "intel_atomic.h" @@ -183,6 +183,15 @@ static const struct hdmi_aud_ncts hdmi_aud_ncts_36bpp[] = { { 192000, TMDS_445_5M, 20480, 371250 }, }; +/* + * WA_14020863754: Implement Audio Workaround + * Corner case with Min Hblank Fix can cause audio hang + */ +static bool needs_wa_14020863754(struct drm_i915_private *i915) +{ + return (DISPLAY_VER(i915) == 20 || IS_BATTLEMAGE(i915)); +} + /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state) { @@ -415,6 +424,9 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, AUDIO_OUTPUT_ENABLE(cpu_transcoder), 0); + if (needs_wa_14020863754(i915)) + intel_de_rmw(i915, AUD_CHICKENBIT_REG3, DACBE_DISABLE_MIN_HBLANK_FIX, 0); + mutex_unlock(&i915->display.audio.mutex); } @@ -540,6 +552,9 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP)) enable_audio_dsc_wa(encoder, crtc_state); + if (needs_wa_14020863754(i915)) + intel_de_rmw(i915, AUD_CHICKENBIT_REG3, 0, DACBE_DISABLE_MIN_HBLANK_FIX); + /* Enable audio presence detect */ intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, 0, AUDIO_OUTPUT_ENABLE(cpu_transcoder)); diff --git a/drivers/gpu/drm/i915/display/intel_audio_regs.h b/drivers/gpu/drm/i915/display/intel_audio_regs.h index 88ea2740365d..4c31844d21df 100644 --- a/drivers/gpu/drm/i915/display/intel_audio_regs.h +++ b/drivers/gpu/drm/i915/display/intel_audio_regs.h @@ -164,4 +164,7 @@ _VLV_AUD_PORT_EN_D_DBG) #define VLV_AMP_MUTE (1 << 1) +#define AUD_CHICKENBIT_REG3 _MMIO(0x65F1C) +#define DACBE_DISABLE_MIN_HBLANK_FIX REG_BIT(18) + #endif /* __INTEL_AUDIO_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 5fb48b6129b6..ec1e3a380360 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -36,6 +36,7 @@ #include "intel_display.h" #include "intel_display_types.h" #include "intel_gmbus.h" +#include "intel_uncore.h" #define _INTEL_BIOS_PRIVATE #include "intel_vbt_defs.h" @@ -170,22 +171,22 @@ static const struct { .min_size = sizeof(struct bdb_driver_features), }, { .section_id = BDB_SDVO_LVDS_OPTIONS, .min_size = sizeof(struct bdb_sdvo_lvds_options), }, - { .section_id = BDB_SDVO_PANEL_DTDS, - .min_size = sizeof(struct bdb_sdvo_panel_dtds), }, + { .section_id = BDB_SDVO_LVDS_DTD, + .min_size = sizeof(struct bdb_sdvo_lvds_dtd), }, { .section_id = BDB_EDP, .min_size = sizeof(struct bdb_edp), }, - { .section_id = BDB_LVDS_OPTIONS, - .min_size = sizeof(struct bdb_lvds_options), }, + { .section_id = BDB_LFP_OPTIONS, + .min_size = sizeof(struct bdb_lfp_options), }, /* - * BDB_LVDS_LFP_DATA depends on BDB_LVDS_LFP_DATA_PTRS, + * BDB_LFP_DATA depends on BDB_LFP_DATA_PTRS, * so keep the two ordered. */ - { .section_id = BDB_LVDS_LFP_DATA_PTRS, - .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), }, - { .section_id = BDB_LVDS_LFP_DATA, + { .section_id = BDB_LFP_DATA_PTRS, + .min_size = sizeof(struct bdb_lfp_data_ptrs), }, + { .section_id = BDB_LFP_DATA, .min_size = 0, /* special case */ }, - { .section_id = BDB_LVDS_BACKLIGHT, - .min_size = sizeof(struct bdb_lfp_backlight_data), }, + { .section_id = BDB_LFP_BACKLIGHT, + .min_size = sizeof(struct bdb_lfp_backlight), }, { .section_id = BDB_LFP_POWER, .min_size = sizeof(struct bdb_lfp_power), }, { .section_id = BDB_MIPI_CONFIG, @@ -200,30 +201,30 @@ static const struct { static size_t lfp_data_min_size(struct drm_i915_private *i915) { - const struct bdb_lvds_lfp_data_ptrs *ptrs; + const struct bdb_lfp_data_ptrs *ptrs; size_t size; - ptrs = bdb_find_section(i915, BDB_LVDS_LFP_DATA_PTRS); + ptrs = bdb_find_section(i915, BDB_LFP_DATA_PTRS); if (!ptrs) return 0; - size = sizeof(struct bdb_lvds_lfp_data); + size = sizeof(struct bdb_lfp_data); if (ptrs->panel_name.table_size) size = max(size, ptrs->panel_name.offset + - sizeof(struct bdb_lvds_lfp_data_tail)); + sizeof(struct bdb_lfp_data_tail)); return size; } static bool validate_lfp_data_ptrs(const void *bdb, - const struct bdb_lvds_lfp_data_ptrs *ptrs) + const struct bdb_lfp_data_ptrs *ptrs) { int fp_timing_size, dvo_timing_size, panel_pnp_id_size, panel_name_size; int data_block_size, lfp_data_size; const void *data_block; int i; - data_block = find_raw_section(bdb, BDB_LVDS_LFP_DATA); + data_block = find_raw_section(bdb, BDB_LFP_DATA); if (!data_block) return false; @@ -232,7 +233,7 @@ static bool validate_lfp_data_ptrs(const void *bdb, return false; /* always 3 indicating the presence of fp_timing+dvo_timing+panel_pnp_id */ - if (ptrs->lvds_entries != 3) + if (ptrs->num_entries != 3) return false; fp_timing_size = ptrs->ptr[0].fp_timing.table_size; @@ -242,13 +243,13 @@ static bool validate_lfp_data_ptrs(const void *bdb, /* fp_timing has variable size */ if (fp_timing_size < 32 || - dvo_timing_size != sizeof(struct lvds_dvo_timing) || - panel_pnp_id_size != sizeof(struct lvds_pnp_id)) + dvo_timing_size != sizeof(struct bdb_edid_dtd) || + panel_pnp_id_size != sizeof(struct bdb_edid_pnp_id)) return false; /* panel_name is not present in old VBTs */ if (panel_name_size != 0 && - panel_name_size != sizeof(struct lvds_lfp_panel_name)) + panel_name_size != sizeof(struct bdb_edid_product_name)) return false; lfp_data_size = ptrs->ptr[1].fp_timing.offset - ptrs->ptr[0].fp_timing.offset; @@ -311,11 +312,11 @@ static bool validate_lfp_data_ptrs(const void *bdb, /* make the data table offsets relative to the data block */ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block) { - struct bdb_lvds_lfp_data_ptrs *ptrs = ptrs_block; + struct bdb_lfp_data_ptrs *ptrs = ptrs_block; u32 offset; int i; - offset = raw_block_offset(bdb, BDB_LVDS_LFP_DATA); + offset = raw_block_offset(bdb, BDB_LFP_DATA); for (i = 0; i < 16; i++) { if (ptrs->ptr[i].fp_timing.offset < offset || @@ -338,7 +339,7 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block) return validate_lfp_data_ptrs(bdb, ptrs); } -static int make_lfp_data_ptr(struct lvds_lfp_data_ptr_table *table, +static int make_lfp_data_ptr(struct lfp_data_ptr_table *table, int table_size, int total_size) { if (total_size < table_size) @@ -350,8 +351,8 @@ static int make_lfp_data_ptr(struct lvds_lfp_data_ptr_table *table, return total_size - table_size; } -static void next_lfp_data_ptr(struct lvds_lfp_data_ptr_table *next, - const struct lvds_lfp_data_ptr_table *prev, +static void next_lfp_data_ptr(struct lfp_data_ptr_table *next, + const struct lfp_data_ptr_table *prev, int size) { next->table_size = prev->table_size; @@ -362,7 +363,7 @@ static void *generate_lfp_data_ptrs(struct drm_i915_private *i915, const void *bdb) { int i, size, table_size, block_size, offset, fp_timing_size; - struct bdb_lvds_lfp_data_ptrs *ptrs; + struct bdb_lfp_data_ptrs *ptrs; const void *block; void *ptrs_block; @@ -377,7 +378,7 @@ static void *generate_lfp_data_ptrs(struct drm_i915_private *i915, fp_timing_size = 38; - block = find_raw_section(bdb, BDB_LVDS_LFP_DATA); + block = find_raw_section(bdb, BDB_LFP_DATA); if (!block) return NULL; @@ -385,8 +386,8 @@ static void *generate_lfp_data_ptrs(struct drm_i915_private *i915, block_size = get_blocksize(block); - size = fp_timing_size + sizeof(struct lvds_dvo_timing) + - sizeof(struct lvds_pnp_id); + size = fp_timing_size + sizeof(struct bdb_edid_dtd) + + sizeof(struct bdb_edid_pnp_id); if (size * 16 > block_size) return NULL; @@ -394,40 +395,40 @@ static void *generate_lfp_data_ptrs(struct drm_i915_private *i915, if (!ptrs_block) return NULL; - *(u8 *)(ptrs_block + 0) = BDB_LVDS_LFP_DATA_PTRS; + *(u8 *)(ptrs_block + 0) = BDB_LFP_DATA_PTRS; *(u16 *)(ptrs_block + 1) = sizeof(*ptrs); ptrs = ptrs_block + 3; - table_size = sizeof(struct lvds_pnp_id); + table_size = sizeof(struct bdb_edid_pnp_id); size = make_lfp_data_ptr(&ptrs->ptr[0].panel_pnp_id, table_size, size); - table_size = sizeof(struct lvds_dvo_timing); + table_size = sizeof(struct bdb_edid_dtd); size = make_lfp_data_ptr(&ptrs->ptr[0].dvo_timing, table_size, size); table_size = fp_timing_size; size = make_lfp_data_ptr(&ptrs->ptr[0].fp_timing, table_size, size); if (ptrs->ptr[0].fp_timing.table_size) - ptrs->lvds_entries++; + ptrs->num_entries++; if (ptrs->ptr[0].dvo_timing.table_size) - ptrs->lvds_entries++; + ptrs->num_entries++; if (ptrs->ptr[0].panel_pnp_id.table_size) - ptrs->lvds_entries++; + ptrs->num_entries++; - if (size != 0 || ptrs->lvds_entries != 3) { + if (size != 0 || ptrs->num_entries != 3) { kfree(ptrs_block); return NULL; } - size = fp_timing_size + sizeof(struct lvds_dvo_timing) + - sizeof(struct lvds_pnp_id); + size = fp_timing_size + sizeof(struct bdb_edid_dtd) + + sizeof(struct bdb_edid_pnp_id); for (i = 1; i < 16; i++) { next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size); next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size); next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size); } - table_size = sizeof(struct lvds_lfp_panel_name); + table_size = sizeof(struct bdb_edid_product_name); if (16 * (size + table_size) <= block_size) { ptrs->panel_name.table_size = table_size; @@ -461,7 +462,7 @@ init_bdb_block(struct drm_i915_private *i915, block = find_raw_section(bdb, section_id); /* Modern VBTs lack the LFP data table pointers block, make one up */ - if (!block && section_id == BDB_LVDS_LFP_DATA_PTRS) { + if (!block && section_id == BDB_LFP_DATA_PTRS) { temp_block = generate_lfp_data_ptrs(i915, bdb); if (temp_block) block = temp_block + 3; @@ -496,7 +497,7 @@ init_bdb_block(struct drm_i915_private *i915, drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n", section_id, block_size, min_size); - if (section_id == BDB_LVDS_LFP_DATA_PTRS && + if (section_id == BDB_LFP_DATA_PTRS && !fixup_lfp_data_ptrs(bdb, entry->data + 3)) { drm_err(&i915->drm, "VBT has malformed LFP data table pointers\n"); kfree(entry); @@ -515,7 +516,7 @@ static void init_bdb_blocks(struct drm_i915_private *i915, enum bdb_block_id section_id = bdb_blocks[i].section_id; size_t min_size = bdb_blocks[i].min_size; - if (section_id == BDB_LVDS_LFP_DATA) + if (section_id == BDB_LFP_DATA) min_size = lfp_data_min_size(i915); init_bdb_block(i915, bdb, section_id, min_size); @@ -525,7 +526,7 @@ static void init_bdb_blocks(struct drm_i915_private *i915, static void fill_detail_timing_data(struct drm_i915_private *i915, struct drm_display_mode *panel_fixed_mode, - const struct lvds_dvo_timing *dvo_timing) + const struct bdb_edid_dtd *dvo_timing) { panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | dvo_timing->hactive_lo; @@ -579,36 +580,36 @@ fill_detail_timing_data(struct drm_i915_private *i915, drm_mode_set_name(panel_fixed_mode); } -static const struct lvds_dvo_timing * -get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *data, - const struct bdb_lvds_lfp_data_ptrs *ptrs, - int index) +static const struct bdb_edid_dtd * +get_lfp_dvo_timing(const struct bdb_lfp_data *data, + const struct bdb_lfp_data_ptrs *ptrs, + int index) { return (const void *)data + ptrs->ptr[index].dvo_timing.offset; } -static const struct lvds_fp_timing * -get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data, - const struct bdb_lvds_lfp_data_ptrs *ptrs, - int index) +static const struct fp_timing * +get_lfp_fp_timing(const struct bdb_lfp_data *data, + const struct bdb_lfp_data_ptrs *ptrs, + int index) { return (const void *)data + ptrs->ptr[index].fp_timing.offset; } static const struct drm_edid_product_id * -get_lvds_pnp_id(const struct bdb_lvds_lfp_data *data, - const struct bdb_lvds_lfp_data_ptrs *ptrs, - int index) +get_lfp_pnp_id(const struct bdb_lfp_data *data, + const struct bdb_lfp_data_ptrs *ptrs, + int index) { /* These two are supposed to have the same layout in memory. */ - BUILD_BUG_ON(sizeof(struct lvds_pnp_id) != sizeof(struct drm_edid_product_id)); + BUILD_BUG_ON(sizeof(struct bdb_edid_pnp_id) != sizeof(struct drm_edid_product_id)); return (const void *)data + ptrs->ptr[index].panel_pnp_id.offset; } -static const struct bdb_lvds_lfp_data_tail * -get_lfp_data_tail(const struct bdb_lvds_lfp_data *data, - const struct bdb_lvds_lfp_data_ptrs *ptrs) +static const struct bdb_lfp_data_tail * +get_lfp_data_tail(const struct bdb_lfp_data *data, + const struct bdb_lfp_data_ptrs *ptrs) { if (ptrs->panel_name.table_size) return (const void *)data + ptrs->panel_name.offset; @@ -627,33 +628,33 @@ static int vbt_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, const struct drm_edid *drm_edid, bool use_fallback) { - const struct bdb_lvds_options *lvds_options; + const struct bdb_lfp_options *lfp_options; - lvds_options = bdb_find_section(i915, BDB_LVDS_OPTIONS); - if (!lvds_options) + lfp_options = bdb_find_section(i915, BDB_LFP_OPTIONS); + if (!lfp_options) return -1; - if (lvds_options->panel_type > 0xf && - lvds_options->panel_type != 0xff) { + if (lfp_options->panel_type > 0xf && + lfp_options->panel_type != 0xff) { drm_dbg_kms(&i915->drm, "Invalid VBT panel type 0x%x\n", - lvds_options->panel_type); + lfp_options->panel_type); return -1; } if (devdata && devdata->child.handle == DEVICE_HANDLE_LFP2) - return lvds_options->panel_type2; + return lfp_options->panel_type2; drm_WARN_ON(&i915->drm, devdata && devdata->child.handle != DEVICE_HANDLE_LFP1); - return lvds_options->panel_type; + return lfp_options->panel_type; } static int pnpid_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, const struct drm_edid *drm_edid, bool use_fallback) { - const struct bdb_lvds_lfp_data *data; - const struct bdb_lvds_lfp_data_ptrs *ptrs; + const struct bdb_lfp_data *data; + const struct bdb_lfp_data_ptrs *ptrs; struct drm_edid_product_id product_id, product_id_nodate; struct drm_printer p; int i, best = -1; @@ -670,17 +671,17 @@ static int pnpid_get_panel_type(struct drm_i915_private *i915, p = drm_dbg_printer(&i915->drm, DRM_UT_KMS, "EDID"); drm_edid_print_product_id(&p, &product_id, true); - ptrs = bdb_find_section(i915, BDB_LVDS_LFP_DATA_PTRS); + ptrs = bdb_find_section(i915, BDB_LFP_DATA_PTRS); if (!ptrs) return -1; - data = bdb_find_section(i915, BDB_LVDS_LFP_DATA); + data = bdb_find_section(i915, BDB_LFP_DATA); if (!data) return -1; for (i = 0; i < 16; i++) { const struct drm_edid_product_id *vbt_id = - get_lvds_pnp_id(data, ptrs, i); + get_lfp_pnp_id(data, ptrs, i); /* full match? */ if (!memcmp(vbt_id, &product_id, sizeof(*vbt_id))) @@ -786,25 +787,25 @@ static void parse_panel_options(struct drm_i915_private *i915, struct intel_panel *panel) { - const struct bdb_lvds_options *lvds_options; + const struct bdb_lfp_options *lfp_options; int panel_type = panel->vbt.panel_type; int drrs_mode; - lvds_options = bdb_find_section(i915, BDB_LVDS_OPTIONS); - if (!lvds_options) + lfp_options = bdb_find_section(i915, BDB_LFP_OPTIONS); + if (!lfp_options) return; - panel->vbt.lvds_dither = lvds_options->pixel_dither; + panel->vbt.lvds_dither = lfp_options->pixel_dither; /* * Empirical evidence indicates the block size can be * either 4,14,16,24+ bytes. For older VBTs no clear * relationship between the block size vs. BDB version. */ - if (get_blocksize(lvds_options) < 16) + if (get_blocksize(lfp_options) < 16) return; - drrs_mode = panel_bits(lvds_options->dps_panel_type_bits, + drrs_mode = panel_bits(lfp_options->dps_panel_type_bits, panel_type, 2); /* * VBT has static DRRS = 0 and seamless DRRS = 2. @@ -832,17 +833,17 @@ parse_panel_options(struct drm_i915_private *i915, static void parse_lfp_panel_dtd(struct drm_i915_private *i915, struct intel_panel *panel, - const struct bdb_lvds_lfp_data *lvds_lfp_data, - const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs) + const struct bdb_lfp_data *lfp_data, + const struct bdb_lfp_data_ptrs *lfp_data_ptrs) { - const struct lvds_dvo_timing *panel_dvo_timing; - const struct lvds_fp_timing *fp_timing; + const struct bdb_edid_dtd *panel_dvo_timing; + const struct fp_timing *fp_timing; struct drm_display_mode *panel_fixed_mode; int panel_type = panel->vbt.panel_type; - panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data, - lvds_lfp_data_ptrs, - panel_type); + panel_dvo_timing = get_lfp_dvo_timing(lfp_data, + lfp_data_ptrs, + panel_type); panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); if (!panel_fixed_mode) @@ -850,15 +851,15 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915, fill_detail_timing_data(i915, panel_fixed_mode, panel_dvo_timing); - panel->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; + panel->vbt.lfp_vbt_mode = panel_fixed_mode; drm_dbg_kms(&i915->drm, "Found panel mode in BIOS VBT legacy lfp table: " DRM_MODE_FMT "\n", DRM_MODE_ARG(panel_fixed_mode)); - fp_timing = get_lvds_fp_timing(lvds_lfp_data, - lvds_lfp_data_ptrs, - panel_type); + fp_timing = get_lfp_fp_timing(lfp_data, + lfp_data_ptrs, + panel_type); /* check the resolution, just to be sure */ if (fp_timing->x_res == panel_fixed_mode->hdisplay && @@ -874,25 +875,25 @@ static void parse_lfp_data(struct drm_i915_private *i915, struct intel_panel *panel) { - const struct bdb_lvds_lfp_data *data; - const struct bdb_lvds_lfp_data_tail *tail; - const struct bdb_lvds_lfp_data_ptrs *ptrs; + const struct bdb_lfp_data *data; + const struct bdb_lfp_data_tail *tail; + const struct bdb_lfp_data_ptrs *ptrs; const struct drm_edid_product_id *pnp_id; struct drm_printer p; int panel_type = panel->vbt.panel_type; - ptrs = bdb_find_section(i915, BDB_LVDS_LFP_DATA_PTRS); + ptrs = bdb_find_section(i915, BDB_LFP_DATA_PTRS); if (!ptrs) return; - data = bdb_find_section(i915, BDB_LVDS_LFP_DATA); + data = bdb_find_section(i915, BDB_LFP_DATA); if (!data) return; - if (!panel->vbt.lfp_lvds_vbt_mode) + if (!panel->vbt.lfp_vbt_mode) parse_lfp_panel_dtd(i915, panel, data, ptrs); - pnp_id = get_lvds_pnp_id(data, ptrs, panel_type); + pnp_id = get_lfp_pnp_id(data, ptrs, panel_type); p = drm_dbg_printer(&i915->drm, DRM_UT_KMS, "Panel"); drm_edid_print_product_id(&p, pnp_id, false); @@ -1001,19 +1002,19 @@ parse_generic_dtd(struct drm_i915_private *i915, "Found panel mode in BIOS VBT generic dtd table: " DRM_MODE_FMT "\n", DRM_MODE_ARG(panel_fixed_mode)); - panel->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; + panel->vbt.lfp_vbt_mode = panel_fixed_mode; } static void parse_lfp_backlight(struct drm_i915_private *i915, struct intel_panel *panel) { - const struct bdb_lfp_backlight_data *backlight_data; + const struct bdb_lfp_backlight *backlight_data; const struct lfp_backlight_data_entry *entry; int panel_type = panel->vbt.panel_type; u16 level; - backlight_data = bdb_find_section(i915, BDB_LVDS_BACKLIGHT); + backlight_data = bdb_find_section(i915, BDB_LFP_BACKLIGHT); if (!backlight_data) return; @@ -1091,19 +1092,18 @@ parse_lfp_backlight(struct drm_i915_private *i915, panel->vbt.backlight.controller); } -/* Try to find sdvo panel data */ static void -parse_sdvo_panel_data(struct drm_i915_private *i915, - struct intel_panel *panel) +parse_sdvo_lvds_data(struct drm_i915_private *i915, + struct intel_panel *panel) { - const struct bdb_sdvo_panel_dtds *dtds; + const struct bdb_sdvo_lvds_dtd *dtd; struct drm_display_mode *panel_fixed_mode; int index; index = i915->display.params.vbt_sdvo_panel_type; if (index == -2) { drm_dbg_kms(&i915->drm, - "Ignore SDVO panel mode from BIOS VBT tables.\n"); + "Ignore SDVO LVDS mode from BIOS VBT tables.\n"); return; } @@ -1117,20 +1117,32 @@ parse_sdvo_panel_data(struct drm_i915_private *i915, index = sdvo_lvds_options->panel_type; } - dtds = bdb_find_section(i915, BDB_SDVO_PANEL_DTDS); - if (!dtds) + dtd = bdb_find_section(i915, BDB_SDVO_LVDS_DTD); + if (!dtd) return; + /* + * This should not happen, as long as the panel_type + * enumeration doesn't grow over 4 items. But if it does, it + * could lead to hard-to-detect bugs, so better double-check + * it here to be sure. + */ + if (index >= ARRAY_SIZE(dtd->dtd)) { + drm_err(&i915->drm, "index %d is larger than dtd->dtd[4] array\n", + index); + return; + } + panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); if (!panel_fixed_mode) return; - fill_detail_timing_data(i915, panel_fixed_mode, &dtds->dtds[index]); + fill_detail_timing_data(i915, panel_fixed_mode, &dtd->dtd[index]); panel->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode; drm_dbg_kms(&i915->drm, - "Found SDVO panel mode in BIOS VBT tables: " DRM_MODE_FMT "\n", + "Found SDVO LVDS mode in BIOS VBT tables: " DRM_MODE_FMT "\n", DRM_MODE_ARG(panel_fixed_mode)); } @@ -1513,6 +1525,10 @@ parse_edp(struct drm_i915_private *i915, if (i915->display.vbt.version >= 244) panel->vbt.edp.max_link_rate = edp->edp_max_port_link_rate[panel_type] * 20; + + if (i915->display.vbt.version >= 251) + panel->vbt.edp.dsc_disable = + panel_bool(edp->edp_dsc_disable, panel_type); } static void @@ -1677,7 +1693,7 @@ parse_mipi_config(struct drm_i915_private *i915, panel->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID; /* Block #40 is already parsed and panel_fixed_mode is - * stored in i915->lfp_lvds_vbt_mode + * stored in i915->lfp_vbt_mode * resuse this when needed */ @@ -2220,15 +2236,14 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) const u8 *ddc_pin_map; int i, n_entries; - if (IS_DGFX(i915)) - return vbt_pin; - if (INTEL_PCH_TYPE(i915) >= PCH_MTL || IS_ALDERLAKE_P(i915)) { ddc_pin_map = adlp_ddc_pin_map; n_entries = ARRAY_SIZE(adlp_ddc_pin_map); } else if (IS_ALDERLAKE_S(i915)) { ddc_pin_map = adls_ddc_pin_map; n_entries = ARRAY_SIZE(adls_ddc_pin_map); + } else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) { + return vbt_pin; } else if (IS_ROCKETLAKE(i915) && INTEL_PCH_TYPE(i915) == PCH_TGP) { ddc_pin_map = rkl_pch_tgp_ddc_pin_map; n_entries = ARRAY_SIZE(rkl_pch_tgp_ddc_pin_map); @@ -3258,7 +3273,7 @@ static void intel_bios_init_panel(struct drm_i915_private *i915, parse_generic_dtd(i915, panel); parse_lfp_data(i915, panel); parse_lfp_backlight(i915, panel); - parse_sdvo_panel_data(i915, panel); + parse_sdvo_lvds_data(i915, panel); parse_panel_driver_features(i915, panel); parse_power_conservation_features(i915, panel); parse_edp(i915, panel); @@ -3307,8 +3322,8 @@ void intel_bios_fini_panel(struct intel_panel *panel) { kfree(panel->vbt.sdvo_lvds_vbt_mode); panel->vbt.sdvo_lvds_vbt_mode = NULL; - kfree(panel->vbt.lfp_lvds_vbt_mode); - panel->vbt.lfp_lvds_vbt_mode = NULL; + kfree(panel->vbt.lfp_vbt_mode); + panel->vbt.lfp_vbt_mode = NULL; kfree(panel->vbt.dsi.data); panel->vbt.dsi.data = NULL; kfree(panel->vbt.dsi.pps); diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 972ea887e232..47036d4abb33 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -22,6 +22,8 @@ struct intel_qgv_point { u16 dclk, t_rp, t_rdpre, t_rc, t_ras, t_rcd; }; +#define DEPROGBWPCLIMIT 60 + struct intel_psf_gv_point { u8 clk; /* clock in multiples of 16.6666 MHz */ }; @@ -241,6 +243,9 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv, qi->channel_width = 16; qi->deinterleave = 4; break; + case INTEL_DRAM_GDDR: + qi->channel_width = 32; + break; default: MISSING_CASE(dram_info->type); return -EINVAL; @@ -387,6 +392,12 @@ static const struct intel_sa_info mtl_sa_info = { .derating = 10, }; +static const struct intel_sa_info xe2_hpd_sa_info = { + .derating = 30, + .deprogbwlimit = 53, + /* Other values not used by simplified algorithm */ +}; + static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa) { struct intel_qgv_info qi = {}; @@ -493,7 +504,7 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel dclk_max = icl_sagv_max_dclk(&qi); peakbw = num_channels * DIV_ROUND_UP(qi.channel_width, 8) * dclk_max; - maxdebw = min(sa->deprogbwlimit * 1000, peakbw * 6 / 10); /* 60% */ + maxdebw = min(sa->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 100); ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels); /* @@ -598,6 +609,54 @@ static void dg2_get_bw_info(struct drm_i915_private *i915) i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED; } +static int xe2_hpd_get_bw_info(struct drm_i915_private *i915, + const struct intel_sa_info *sa) +{ + struct intel_qgv_info qi = {}; + int num_channels = i915->dram_info.num_channels; + int peakbw, maxdebw; + int ret, i; + + ret = icl_get_qgv_points(i915, &qi, true); + if (ret) { + drm_dbg_kms(&i915->drm, + "Failed to get memory subsystem information, ignoring bandwidth limits"); + return ret; + } + + peakbw = num_channels * qi.channel_width / 8 * icl_sagv_max_dclk(&qi); + maxdebw = min(sa->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 10); + + for (i = 0; i < qi.num_points; i++) { + const struct intel_qgv_point *point = &qi.points[i]; + int bw = num_channels * (qi.channel_width / 8) * point->dclk; + + i915->display.bw.max[0].deratedbw[i] = + min(maxdebw, (100 - sa->derating) * bw / 100); + i915->display.bw.max[0].peakbw[i] = bw; + + drm_dbg_kms(&i915->drm, "QGV %d: deratedbw=%u peakbw: %u\n", + i, i915->display.bw.max[0].deratedbw[i], + i915->display.bw.max[0].peakbw[i]); + } + + /* Bandwidth does not depend on # of planes; set all groups the same */ + i915->display.bw.max[0].num_planes = 1; + i915->display.bw.max[0].num_qgv_points = qi.num_points; + for (i = 1; i < ARRAY_SIZE(i915->display.bw.max); i++) + memcpy(&i915->display.bw.max[i], &i915->display.bw.max[0], + sizeof(i915->display.bw.max[0])); + + /* + * Xe2_HPD should always have exactly two QGV points representing + * battery and plugged-in operation. + */ + drm_WARN_ON(&i915->drm, qi.num_points != 2); + i915->display.sagv.status = I915_SAGV_ENABLED; + + return 0; +} + static unsigned int icl_max_bw_index(struct drm_i915_private *dev_priv, int num_planes, int qgv_point) { @@ -684,7 +743,9 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; - if (DISPLAY_VER(dev_priv) >= 14) + if (DISPLAY_VER_FULL(dev_priv) >= IP_VER(14, 1) && IS_DGFX(dev_priv)) + xe2_hpd_get_bw_info(dev_priv, &xe2_hpd_sa_info); + else if (DISPLAY_VER(dev_priv) >= 14) tgl_get_bw_info(dev_priv, &mtl_sa_info); else if (IS_DG2(dev_priv)) dg2_get_bw_info(dev_priv); diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 7a833b5f2de2..16d5550f7e5e 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -23,6 +23,7 @@ #include <linux/time.h> +#include "soc/intel_dram.h" #include "hsw_ips.h" #include "i915_reg.h" #include "intel_atomic.h" @@ -113,7 +114,7 @@ struct intel_cdclk_funcs { void (*set_cdclk)(struct drm_i915_private *i915, const struct intel_cdclk_config *cdclk_config, enum pipe pipe); - int (*modeset_calc_cdclk)(struct intel_cdclk_state *state); + int (*modeset_calc_cdclk)(struct intel_atomic_state *state); u8 (*calc_voltage_level)(int cdclk); }; @@ -130,10 +131,11 @@ static void intel_cdclk_set_cdclk(struct drm_i915_private *dev_priv, dev_priv->display.funcs.cdclk->set_cdclk(dev_priv, cdclk_config, pipe); } -static int intel_cdclk_modeset_calc_cdclk(struct drm_i915_private *dev_priv, - struct intel_cdclk_state *cdclk_config) +static int intel_cdclk_modeset_calc_cdclk(struct intel_atomic_state *state) { - return dev_priv->display.funcs.cdclk->modeset_calc_cdclk(cdclk_config); + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + + return dev_priv->display.funcs.cdclk->modeset_calc_cdclk(state); } static u8 intel_cdclk_calc_voltage_level(struct drm_i915_private *dev_priv, @@ -1443,6 +1445,14 @@ static const struct intel_cdclk_vals xe2lpd_cdclk_table[] = { {} }; +/* + * Xe2_HPD always uses the minimal cdclk table from Wa_15015413771 + */ +static const struct intel_cdclk_vals xe2hpd_cdclk_table[] = { + { .refclk = 38400, .cdclk = 652800, .ratio = 34, .waveform = 0xffff }, + {} +}; + static const int cdclk_squash_len = 16; static int cdclk_squash_divider(u16 waveform) @@ -2723,7 +2733,7 @@ static int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state) min_cdclk = max_t(int, min_cdclk, DIV_ROUND_UP(crtc_state->pixel_rate, num_vdsc_instances)); - if (crtc_state->bigjoiner_pipes) { + if (crtc_state->joiner_pipes) { int pixel_clock = intel_dp_mode_to_fec_clock(crtc_state->hw.adjusted_mode.clock); /* @@ -2826,10 +2836,11 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) return min_cdclk; } -static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state) +static int intel_compute_min_cdclk(struct intel_atomic_state *state) { - struct intel_atomic_state *state = cdclk_state->base.state; struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_cdclk_state *cdclk_state = + intel_atomic_get_new_cdclk_state(state); const struct intel_bw_state *bw_state; struct intel_crtc *crtc; struct intel_crtc_state *crtc_state; @@ -2908,10 +2919,11 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state) * future platforms this code will need to be * adjusted. */ -static int bxt_compute_min_voltage_level(struct intel_cdclk_state *cdclk_state) +static int bxt_compute_min_voltage_level(struct intel_atomic_state *state) { - struct intel_atomic_state *state = cdclk_state->base.state; struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_cdclk_state *cdclk_state = + intel_atomic_get_new_cdclk_state(state); struct intel_crtc *crtc; struct intel_crtc_state *crtc_state; u8 min_voltage_level; @@ -2944,13 +2956,14 @@ static int bxt_compute_min_voltage_level(struct intel_cdclk_state *cdclk_state) return min_voltage_level; } -static int vlv_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) +static int vlv_modeset_calc_cdclk(struct intel_atomic_state *state) { - struct intel_atomic_state *state = cdclk_state->base.state; struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_cdclk_state *cdclk_state = + intel_atomic_get_new_cdclk_state(state); int min_cdclk, cdclk; - min_cdclk = intel_compute_min_cdclk(cdclk_state); + min_cdclk = intel_compute_min_cdclk(state); if (min_cdclk < 0) return min_cdclk; @@ -2973,11 +2986,13 @@ static int vlv_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) return 0; } -static int bdw_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) +static int bdw_modeset_calc_cdclk(struct intel_atomic_state *state) { + struct intel_cdclk_state *cdclk_state = + intel_atomic_get_new_cdclk_state(state); int min_cdclk, cdclk; - min_cdclk = intel_compute_min_cdclk(cdclk_state); + min_cdclk = intel_compute_min_cdclk(state); if (min_cdclk < 0) return min_cdclk; @@ -3000,10 +3015,11 @@ static int bdw_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) return 0; } -static int skl_dpll0_vco(struct intel_cdclk_state *cdclk_state) +static int skl_dpll0_vco(struct intel_atomic_state *state) { - struct intel_atomic_state *state = cdclk_state->base.state; struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_cdclk_state *cdclk_state = + intel_atomic_get_new_cdclk_state(state); struct intel_crtc *crtc; struct intel_crtc_state *crtc_state; int vco, i; @@ -3037,15 +3053,17 @@ static int skl_dpll0_vco(struct intel_cdclk_state *cdclk_state) return vco; } -static int skl_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) +static int skl_modeset_calc_cdclk(struct intel_atomic_state *state) { + struct intel_cdclk_state *cdclk_state = + intel_atomic_get_new_cdclk_state(state); int min_cdclk, cdclk, vco; - min_cdclk = intel_compute_min_cdclk(cdclk_state); + min_cdclk = intel_compute_min_cdclk(state); if (min_cdclk < 0) return min_cdclk; - vco = skl_dpll0_vco(cdclk_state); + vco = skl_dpll0_vco(state); cdclk = skl_calc_cdclk(min_cdclk, vco); @@ -3068,17 +3086,18 @@ static int skl_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) return 0; } -static int bxt_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) +static int bxt_modeset_calc_cdclk(struct intel_atomic_state *state) { - struct intel_atomic_state *state = cdclk_state->base.state; struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_cdclk_state *cdclk_state = + intel_atomic_get_new_cdclk_state(state); int min_cdclk, min_voltage_level, cdclk, vco; - min_cdclk = intel_compute_min_cdclk(cdclk_state); + min_cdclk = intel_compute_min_cdclk(state); if (min_cdclk < 0) return min_cdclk; - min_voltage_level = bxt_compute_min_voltage_level(cdclk_state); + min_voltage_level = bxt_compute_min_voltage_level(state); if (min_voltage_level < 0) return min_voltage_level; @@ -3106,7 +3125,7 @@ static int bxt_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) return 0; } -static int fixed_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) +static int fixed_modeset_calc_cdclk(struct intel_atomic_state *state) { int min_cdclk; @@ -3115,7 +3134,7 @@ static int fixed_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state) * check that the required minimum frequency doesn't exceed * the actual cdclk frequency. */ - min_cdclk = intel_compute_min_cdclk(cdclk_state); + min_cdclk = intel_compute_min_cdclk(state); if (min_cdclk < 0) return min_cdclk; @@ -3255,7 +3274,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) new_cdclk_state->active_pipes = intel_calc_active_pipes(state, old_cdclk_state->active_pipes); - ret = intel_cdclk_modeset_calc_cdclk(dev_priv, new_cdclk_state); + ret = intel_cdclk_modeset_calc_cdclk(state); if (ret) return ret; @@ -3521,60 +3540,10 @@ static int vlv_hrawclk(struct drm_i915_private *dev_priv) CCK_DISPLAY_REF_CLOCK_CONTROL); } -static int i9xx_hrawclk(struct drm_i915_private *dev_priv) +static int i9xx_hrawclk(struct drm_i915_private *i915) { - u32 clkcfg; - - /* - * hrawclock is 1/4 the FSB frequency - * - * Note that this only reads the state of the FSB - * straps, not the actual FSB frequency. Some BIOSen - * let you configure each independently. Ideally we'd - * read out the actual FSB frequency but sadly we - * don't know which registers have that information, - * and all the relevant docs have gone to bit heaven :( - */ - clkcfg = intel_de_read(dev_priv, CLKCFG) & CLKCFG_FSB_MASK; - - if (IS_MOBILE(dev_priv)) { - switch (clkcfg) { - case CLKCFG_FSB_400: - return 100000; - case CLKCFG_FSB_533: - return 133333; - case CLKCFG_FSB_667: - return 166667; - case CLKCFG_FSB_800: - return 200000; - case CLKCFG_FSB_1067: - return 266667; - case CLKCFG_FSB_1333: - return 333333; - default: - MISSING_CASE(clkcfg); - return 133333; - } - } else { - switch (clkcfg) { - case CLKCFG_FSB_400_ALT: - return 100000; - case CLKCFG_FSB_533: - return 133333; - case CLKCFG_FSB_667: - return 166667; - case CLKCFG_FSB_800: - return 200000; - case CLKCFG_FSB_1067_ALT: - return 266667; - case CLKCFG_FSB_1333_ALT: - return 333333; - case CLKCFG_FSB_1600_ALT: - return 400000; - default: - return 133333; - } - } + /* hrawclock is 1/4 the FSB frequency */ + return DIV_ROUND_CLOSEST(i9xx_fsb_freq(i915), 4); } /** @@ -3778,6 +3747,9 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) if (DISPLAY_VER(dev_priv) >= 20) { dev_priv->display.funcs.cdclk = &rplu_cdclk_funcs; dev_priv->display.cdclk.table = xe2lpd_cdclk_table; + } else if (DISPLAY_VER_FULL(dev_priv) >= IP_VER(14, 1)) { + dev_priv->display.funcs.cdclk = &rplu_cdclk_funcs; + dev_priv->display.cdclk.table = xe2hpd_cdclk_table; } else if (DISPLAY_VER(dev_priv) >= 14) { dev_priv->display.funcs.cdclk = &rplu_cdclk_funcs; dev_priv->display.cdclk.table = mtl_cdclk_table; diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index d23163dc64d4..98553e8a5149 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -22,7 +22,7 @@ * */ -#include "i915_reg.h" +#include "i9xx_plane_regs.h" #include "intel_color.h" #include "intel_color_regs.h" #include "intel_de.h" @@ -30,7 +30,8 @@ #include "intel_dsb.h" struct intel_color_funcs { - int (*color_check)(struct intel_crtc_state *crtc_state); + int (*color_check)(struct intel_atomic_state *state, + struct intel_crtc *crtc); /* * Program non-arming double buffered color management registers * before vblank evasion. The registers should then latch after @@ -1038,7 +1039,7 @@ static void i9xx_get_config(struct intel_crtc_state *crtc_state) enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; u32 tmp; - tmp = intel_de_read(dev_priv, DSPCNTR(i9xx_plane)); + tmp = intel_de_read(dev_priv, DSPCNTR(dev_priv, i9xx_plane)); if (tmp & DISP_PIPE_GAMMA_ENABLE) crtc_state->gamma_enable = true; @@ -1284,9 +1285,9 @@ static void i965_load_lut_10p6(struct intel_crtc *crtc, i965_lut_10p6_udw(&lut[i])); } - intel_de_write_fw(dev_priv, PIPEGCMAX(pipe, 0), lut[i].red); - intel_de_write_fw(dev_priv, PIPEGCMAX(pipe, 1), lut[i].green); - intel_de_write_fw(dev_priv, PIPEGCMAX(pipe, 2), lut[i].blue); + intel_de_write_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 0), lut[i].red); + intel_de_write_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 1), lut[i].green); + intel_de_write_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 2), lut[i].blue); } static void i965_load_luts(const struct intel_crtc_state *crtc_state) @@ -1913,7 +1914,7 @@ void intel_color_prepare_commit(struct intel_crtc_state *crtc_state) if (!crtc_state->pre_csc_lut && !crtc_state->post_csc_lut) return; - crtc_state->dsb = intel_dsb_prepare(crtc_state, 1024); + crtc_state->dsb = intel_dsb_prepare(crtc_state, INTEL_DSB_0, 1024); if (!crtc_state->dsb) return; @@ -1942,11 +1943,9 @@ bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state) return crtc_state->dsb; } -static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state) +static bool intel_can_preload_luts(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct intel_atomic_state *state = - to_intel_atomic_state(new_crtc_state->uapi.state); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); @@ -1954,11 +1953,9 @@ static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state !old_crtc_state->pre_csc_lut; } -static bool vlv_can_preload_luts(const struct intel_crtc_state *new_crtc_state) +static bool vlv_can_preload_luts(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct intel_atomic_state *state = - to_intel_atomic_state(new_crtc_state->uapi.state); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); @@ -1966,13 +1963,13 @@ static bool vlv_can_preload_luts(const struct intel_crtc_state *new_crtc_state) !old_crtc_state->post_csc_lut; } -static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state) +static bool chv_can_preload_luts(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct intel_atomic_state *state = - to_intel_atomic_state(new_crtc_state->uapi.state); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); /* * CGM_PIPE_MODE is itself single buffered. We'd have to @@ -1982,14 +1979,29 @@ static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state) if (old_crtc_state->cgm_mode || new_crtc_state->cgm_mode) return false; - return vlv_can_preload_luts(new_crtc_state); + return vlv_can_preload_luts(state, crtc); } -int intel_color_check(struct intel_crtc_state *crtc_state) +int intel_color_check(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); - return i915->display.funcs.color->color_check(crtc_state); + /* + * May need to update pipe gamma enable bits + * when C8 planes are getting enabled/disabled. + */ + if (!old_crtc_state->c8_planes != !new_crtc_state->c8_planes) + new_crtc_state->uapi.color_mgmt_changed = true; + + if (!intel_crtc_needs_color_update(new_crtc_state)) + return 0; + + return i915->display.funcs.color->color_check(state, crtc); } void intel_color_get_config(struct intel_crtc_state *crtc_state) @@ -2039,14 +2051,14 @@ static bool need_plane_update(struct intel_plane *plane, } static int -intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state) +intel_color_add_affected_planes(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct drm_i915_private *i915 = to_i915(crtc->base.dev); - struct intel_atomic_state *state = - to_intel_atomic_state(new_crtc_state->uapi.state); + struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct intel_plane *plane; if (!new_crtc_state->hw.active || @@ -2240,9 +2252,12 @@ static void intel_assign_luts(struct intel_crtc_state *crtc_state) crtc_state->hw.gamma_lut); } -static int i9xx_color_check(struct intel_crtc_state *crtc_state) +static int i9xx_color_check(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); int ret; ret = check_luts(crtc_state); @@ -2262,13 +2277,13 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state) return ret; } - ret = intel_color_add_affected_planes(crtc_state); + ret = intel_color_add_affected_planes(state, crtc); if (ret) return ret; intel_assign_luts(crtc_state); - crtc_state->preload_luts = intel_can_preload_luts(crtc_state); + crtc_state->preload_luts = intel_can_preload_luts(state, crtc); return 0; } @@ -2277,8 +2292,11 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state) * VLV color pipeline: * u0.10 -> WGC csc -> u0.10 -> pipe gamma -> u0.10 */ -static int vlv_color_check(struct intel_crtc_state *crtc_state) +static int vlv_color_check(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); int ret; ret = check_luts(crtc_state); @@ -2293,7 +2311,7 @@ static int vlv_color_check(struct intel_crtc_state *crtc_state) crtc_state->wgc_enable = crtc_state->hw.ctm; - ret = intel_color_add_affected_planes(crtc_state); + ret = intel_color_add_affected_planes(state, crtc); if (ret) return ret; @@ -2301,7 +2319,7 @@ static int vlv_color_check(struct intel_crtc_state *crtc_state) vlv_assign_csc(crtc_state); - crtc_state->preload_luts = vlv_can_preload_luts(crtc_state); + crtc_state->preload_luts = vlv_can_preload_luts(state, crtc); return 0; } @@ -2336,8 +2354,11 @@ static u32 chv_cgm_mode(const struct intel_crtc_state *crtc_state) * We always bypass the WGC csc and use the CGM csc * instead since it has degamma and better precision. */ -static int chv_color_check(struct intel_crtc_state *crtc_state) +static int chv_color_check(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); int ret; ret = check_luts(crtc_state); @@ -2362,7 +2383,7 @@ static int chv_color_check(struct intel_crtc_state *crtc_state) */ crtc_state->wgc_enable = false; - ret = intel_color_add_affected_planes(crtc_state); + ret = intel_color_add_affected_planes(state, crtc); if (ret) return ret; @@ -2370,7 +2391,7 @@ static int chv_color_check(struct intel_crtc_state *crtc_state) chv_assign_csc(crtc_state); - crtc_state->preload_luts = chv_can_preload_luts(crtc_state); + crtc_state->preload_luts = chv_can_preload_luts(state, crtc); return 0; } @@ -2454,9 +2475,12 @@ static int ilk_assign_luts(struct intel_crtc_state *crtc_state) return 0; } -static int ilk_color_check(struct intel_crtc_state *crtc_state) +static int ilk_color_check(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); int ret; ret = check_luts(crtc_state); @@ -2484,7 +2508,7 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state) crtc_state->csc_mode = ilk_csc_mode(crtc_state); - ret = intel_color_add_affected_planes(crtc_state); + ret = intel_color_add_affected_planes(state, crtc); if (ret) return ret; @@ -2494,7 +2518,7 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state) ilk_assign_csc(crtc_state); - crtc_state->preload_luts = intel_can_preload_luts(crtc_state); + crtc_state->preload_luts = intel_can_preload_luts(state, crtc); return 0; } @@ -2555,9 +2579,12 @@ static int ivb_assign_luts(struct intel_crtc_state *crtc_state) return 0; } -static int ivb_color_check(struct intel_crtc_state *crtc_state) +static int ivb_color_check(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); int ret; ret = check_luts(crtc_state); @@ -2592,7 +2619,7 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) crtc_state->csc_mode = ivb_csc_mode(crtc_state); - ret = intel_color_add_affected_planes(crtc_state); + ret = intel_color_add_affected_planes(state, crtc); if (ret) return ret; @@ -2602,7 +2629,7 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) ilk_assign_csc(crtc_state); - crtc_state->preload_luts = intel_can_preload_luts(crtc_state); + crtc_state->preload_luts = intel_can_preload_luts(state, crtc); return 0; } @@ -2686,9 +2713,12 @@ static int glk_check_luts(const struct intel_crtc_state *crtc_state) return _check_luts(crtc_state, degamma_tests, gamma_tests); } -static int glk_color_check(struct intel_crtc_state *crtc_state) +static int glk_color_check(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); int ret; ret = glk_check_luts(crtc_state); @@ -2725,7 +2755,7 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) crtc_state->csc_mode = 0; - ret = intel_color_add_affected_planes(crtc_state); + ret = intel_color_add_affected_planes(state, crtc); if (ret) return ret; @@ -2735,7 +2765,7 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) ilk_assign_csc(crtc_state); - crtc_state->preload_luts = intel_can_preload_luts(crtc_state); + crtc_state->preload_luts = intel_can_preload_luts(state, crtc); return 0; } @@ -2783,8 +2813,11 @@ static u32 icl_csc_mode(const struct intel_crtc_state *crtc_state) return csc_mode; } -static int icl_color_check(struct intel_crtc_state *crtc_state) +static int icl_color_check(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); int ret; ret = check_luts(crtc_state); @@ -2799,7 +2832,7 @@ static int icl_color_check(struct intel_crtc_state *crtc_state) icl_assign_csc(crtc_state); - crtc_state->preload_luts = intel_can_preload_luts(crtc_state); + crtc_state->preload_luts = intel_can_preload_luts(state, crtc); return 0; } @@ -3239,9 +3272,9 @@ static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc) i965_lut_10p6_pack(&lut[i], ldw, udw); } - lut[i].red = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(pipe, 0))); - lut[i].green = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(pipe, 1))); - lut[i].blue = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(pipe, 2))); + lut[i].red = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 0))); + lut[i].green = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 1))); + lut[i].blue = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 2))); return blob; } diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 8ecd36149def..21ba4aa02e7b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -8,6 +8,7 @@ #include <linux/types.h> +struct intel_atomic_state; struct intel_crtc_state; struct intel_crtc; struct drm_i915_private; @@ -16,7 +17,8 @@ struct drm_property_blob; void intel_color_init_hooks(struct drm_i915_private *i915); int intel_color_init(struct drm_i915_private *i915); void intel_color_crtc_init(struct intel_crtc *crtc); -int intel_color_check(struct intel_crtc_state *crtc_state); +int intel_color_check(struct intel_atomic_state *state, + struct intel_crtc *crtc); void intel_color_prepare_commit(struct intel_crtc_state *crtc_state); void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state); bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_color_regs.h b/drivers/gpu/drm/i915/display/intel_color_regs.h index bb99ea533842..8eb643cfead7 100644 --- a/drivers/gpu/drm/i915/display/intel_color_regs.h +++ b/drivers/gpu/drm/i915/display/intel_color_regs.h @@ -36,6 +36,11 @@ _CHV_PALETTE_C, _CHV_PALETTE_C) + \ (i) * 4) +/* i965/g4x/vlv/chv */ +#define _PIPEAGCMAX 0x70010 +#define _PIPEBGCMAX 0x71010 +#define PIPEGCMAX(dev_priv, pipe, i) _MMIO_PIPE2(dev_priv, pipe, _PIPEAGCMAX + (i) * 4) /* u1.16 */ + /* ilk+ palette */ #define _LGC_PALETTE_A 0x4a000 #define _LGC_PALETTE_B 0x4a800 diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 10e95dc425a6..835c8b844494 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -193,7 +193,7 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, adpa |= ADPA_PIPE_SEL(crtc->pipe); if (!HAS_PCH_SPLIT(dev_priv)) - intel_de_write(dev_priv, BCLRPAT(crtc->pipe), 0); + intel_de_write(dev_priv, BCLRPAT(dev_priv, crtc->pipe), 0); switch (mode) { case DRM_MODE_DPMS_ON: @@ -603,18 +603,19 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) CRT_HOTPLUG_FORCE_DETECT, CRT_HOTPLUG_FORCE_DETECT); /* wait for FORCE_DETECT to go off */ - if (intel_de_wait_for_clear(dev_priv, PORT_HOTPLUG_EN, + if (intel_de_wait_for_clear(dev_priv, PORT_HOTPLUG_EN(dev_priv), CRT_HOTPLUG_FORCE_DETECT, 1000)) drm_dbg_kms(&dev_priv->drm, "timed out waiting for FORCE_DETECT to go off"); } - stat = intel_de_read(dev_priv, PORT_HOTPLUG_STAT); + stat = intel_de_read(dev_priv, PORT_HOTPLUG_STAT(dev_priv)); if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE) ret = true; /* clear the interrupt we just generated, if any */ - intel_de_write(dev_priv, PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS); + intel_de_write(dev_priv, PORT_HOTPLUG_STAT(dev_priv), + CRT_HOTPLUG_INT_STATUS); i915_hotplug_interrupt_update(dev_priv, CRT_HOTPLUG_FORCE_DETECT, 0); @@ -707,9 +708,12 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe) drm_dbg_kms(&dev_priv->drm, "starting load-detect on CRT\n"); - save_bclrpat = intel_de_read(dev_priv, BCLRPAT(cpu_transcoder)); - save_vtotal = intel_de_read(dev_priv, TRANS_VTOTAL(cpu_transcoder)); - vblank = intel_de_read(dev_priv, TRANS_VBLANK(cpu_transcoder)); + save_bclrpat = intel_de_read(dev_priv, + BCLRPAT(dev_priv, cpu_transcoder)); + save_vtotal = intel_de_read(dev_priv, + TRANS_VTOTAL(dev_priv, cpu_transcoder)); + vblank = intel_de_read(dev_priv, + TRANS_VBLANK(dev_priv, cpu_transcoder)); vtotal = REG_FIELD_GET(VTOTAL_MASK, save_vtotal) + 1; vactive = REG_FIELD_GET(VACTIVE_MASK, save_vtotal) + 1; @@ -718,14 +722,16 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe) vblank_end = REG_FIELD_GET(VBLANK_END_MASK, vblank) + 1; /* Set the border color to purple. */ - intel_de_write(dev_priv, BCLRPAT(cpu_transcoder), 0x500050); + intel_de_write(dev_priv, BCLRPAT(dev_priv, cpu_transcoder), 0x500050); if (DISPLAY_VER(dev_priv) != 2) { - u32 transconf = intel_de_read(dev_priv, TRANSCONF(cpu_transcoder)); + u32 transconf = intel_de_read(dev_priv, + TRANSCONF(dev_priv, cpu_transcoder)); - intel_de_write(dev_priv, TRANSCONF(cpu_transcoder), + intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), transconf | TRANSCONF_FORCE_BORDER); - intel_de_posting_read(dev_priv, TRANSCONF(cpu_transcoder)); + intel_de_posting_read(dev_priv, + TRANSCONF(dev_priv, cpu_transcoder)); /* Wait for next Vblank to substitue * border color for Color info */ intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe)); @@ -734,7 +740,8 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe) connector_status_connected : connector_status_disconnected; - intel_de_write(dev_priv, TRANSCONF(cpu_transcoder), transconf); + intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), + transconf); } else { bool restore_vblank = false; int count, detect; @@ -744,11 +751,13 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe) * Yes, this will flicker */ if (vblank_start <= vactive && vblank_end >= vtotal) { - u32 vsync = intel_de_read(dev_priv, TRANS_VSYNC(cpu_transcoder)); + u32 vsync = intel_de_read(dev_priv, + TRANS_VSYNC(dev_priv, cpu_transcoder)); u32 vsync_start = REG_FIELD_GET(VSYNC_START_MASK, vsync) + 1; vblank_start = vsync_start; - intel_de_write(dev_priv, TRANS_VBLANK(cpu_transcoder), + intel_de_write(dev_priv, + TRANS_VBLANK(dev_priv, cpu_transcoder), VBLANK_START(vblank_start - 1) | VBLANK_END(vblank_end - 1)); restore_vblank = true; @@ -762,9 +771,9 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe) /* * Wait for the border to be displayed */ - while (intel_de_read(dev_priv, PIPEDSL(pipe)) >= vactive) + while (intel_de_read(dev_priv, PIPEDSL(dev_priv, pipe)) >= vactive) ; - while ((dsl = intel_de_read(dev_priv, PIPEDSL(pipe))) <= vsample) + while ((dsl = intel_de_read(dev_priv, PIPEDSL(dev_priv, pipe))) <= vsample) ; /* * Watch ST00 for an entire scanline @@ -777,11 +786,13 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe) st00 = intel_de_read8(dev_priv, _VGA_MSR_WRITE); if (st00 & (1 << 4)) detect++; - } while ((intel_de_read(dev_priv, PIPEDSL(pipe)) == dsl)); + } while ((intel_de_read(dev_priv, PIPEDSL(dev_priv, pipe)) == dsl)); /* restore vblank if necessary */ if (restore_vblank) - intel_de_write(dev_priv, TRANS_VBLANK(cpu_transcoder), vblank); + intel_de_write(dev_priv, + TRANS_VBLANK(dev_priv, cpu_transcoder), + vblank); /* * If more than 3/4 of the scanline detected a monitor, * then it is assumed to be present. This works even on i830, @@ -794,7 +805,8 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe) } /* Restore previous settings */ - intel_de_write(dev_priv, BCLRPAT(cpu_transcoder), save_bclrpat); + intel_de_write(dev_priv, BCLRPAT(dev_priv, cpu_transcoder), + save_bclrpat); return status; } diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 25593f6aae7d..54b529bfc935 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -78,8 +78,7 @@ void intel_wait_for_vblank_if_active(struct drm_i915_private *i915, u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) { - struct drm_device *dev = crtc->base.dev; - struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); if (!crtc->active) return 0; @@ -311,8 +310,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) crtc->num_scalers = DISPLAY_RUNTIME_INFO(dev_priv)->num_scalers[pipe]; if (DISPLAY_VER(dev_priv) >= 9) - primary = skl_universal_plane_create(dev_priv, pipe, - PLANE_PRIMARY); + primary = skl_universal_plane_create(dev_priv, pipe, PLANE_1); else primary = intel_primary_plane_create(dev_priv, pipe); if (IS_ERR(primary)) { @@ -327,8 +325,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) struct intel_plane *plane; if (DISPLAY_VER(dev_priv) >= 9) - plane = skl_universal_plane_create(dev_priv, pipe, - PLANE_SPRITE0 + sprite); + plane = skl_universal_plane_create(dev_priv, pipe, PLANE_2 + sprite); else plane = intel_sprite_plane_create(dev_priv, pipe, sprite); if (IS_ERR(plane)) { @@ -414,8 +411,8 @@ static void intel_crtc_vblank_work(struct kthread_work *base) if (crtc_state->uapi.event) { spin_lock_irq(&crtc->base.dev->event_lock); drm_crtc_send_vblank_event(&crtc->base, crtc_state->uapi.event); - crtc_state->uapi.event = NULL; spin_unlock_irq(&crtc->base.dev->event_lock); + crtc_state->uapi.event = NULL; } trace_intel_crtc_vblank_work_end(crtc); @@ -457,8 +454,8 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, if (!adjusted_mode->crtc_htotal) return 1; - return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock, - 1000 * adjusted_mode->crtc_htotal); + return DIV_ROUND_UP_ULL(mul_u32_u32(usecs, adjusted_mode->crtc_clock), + 1000 * adjusted_mode->crtc_htotal); } /** diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index ccaa4cb2809b..6df526e189b5 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -222,10 +222,10 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, transcoder_name(pipe_config->master_transcoder), pipe_config->sync_mode_slaves_mask); - drm_printf(&p, "bigjoiner: %s, pipes: 0x%x\n", - intel_crtc_is_bigjoiner_slave(pipe_config) ? "slave" : - intel_crtc_is_bigjoiner_master(pipe_config) ? "master" : "no", - pipe_config->bigjoiner_pipes); + drm_printf(&p, "joiner: %s, pipes: 0x%x\n", + intel_crtc_is_joiner_secondary(pipe_config) ? "secondary" : + intel_crtc_is_joiner_primary(pipe_config) ? "primary" : "no", + pipe_config->joiner_pipes); drm_printf(&p, "splitter: %s, link count %d, overlap %d\n", str_enabled_disabled(pipe_config->splitter.enable), @@ -251,9 +251,10 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, drm_printf(&p, "sdp split: %s\n", str_enabled_disabled(pipe_config->sdp_split_enable)); - drm_printf(&p, "psr: %s, psr2: %s, panel replay: %s, selective fetch: %s\n", - str_enabled_disabled(pipe_config->has_psr), - str_enabled_disabled(pipe_config->has_psr2), + drm_printf(&p, "psr: %s, selective update: %s, panel replay: %s, selective fetch: %s\n", + str_enabled_disabled(pipe_config->has_psr && + !pipe_config->has_panel_replay), + str_enabled_disabled(pipe_config->has_sel_update), str_enabled_disabled(pipe_config->has_panel_replay), str_enabled_disabled(pipe_config->enable_psr2_sel_fetch)); } diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 23a122ee20c9..66436e526021 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -14,6 +14,7 @@ #include "intel_atomic.h" #include "intel_atomic_plane.h" #include "intel_cursor.h" +#include "intel_cursor_regs.h" #include "intel_de.h" #include "intel_display.h" #include "intel_display_types.h" @@ -293,17 +294,17 @@ static void i845_cursor_update_arm(struct intel_plane *plane, if (plane->cursor.base != base || plane->cursor.size != size || plane->cursor.cntl != cntl) { - intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0); - intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base); - intel_de_write_fw(dev_priv, CURSIZE(PIPE_A), size); - intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos); - intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl); + intel_de_write_fw(dev_priv, CURCNTR(dev_priv, PIPE_A), 0); + intel_de_write_fw(dev_priv, CURBASE(dev_priv, PIPE_A), base); + intel_de_write_fw(dev_priv, CURSIZE(dev_priv, PIPE_A), size); + intel_de_write_fw(dev_priv, CURPOS(dev_priv, PIPE_A), pos); + intel_de_write_fw(dev_priv, CURCNTR(dev_priv, PIPE_A), cntl); plane->cursor.base = base; plane->cursor.size = size; plane->cursor.cntl = cntl; } else { - intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos); + intel_de_write_fw(dev_priv, CURPOS(dev_priv, PIPE_A), pos); } } @@ -326,7 +327,7 @@ static bool i845_cursor_get_hw_state(struct intel_plane *plane, if (!wakeref) return false; - ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE; + ret = intel_de_read(dev_priv, CURCNTR(dev_priv, PIPE_A)) & CURSOR_ENABLE; *pipe = PIPE_A; @@ -506,7 +507,7 @@ static void i9xx_cursor_disable_sel_fetch_arm(struct intel_plane *plane, if (!crtc_state->enable_psr2_sel_fetch) return; - intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_CTL(pipe, plane->id), 0); + intel_de_write_fw(dev_priv, SEL_FETCH_CUR_CTL(pipe), 0); } static void wa_16021440873(struct intel_plane *plane, @@ -521,10 +522,10 @@ static void wa_16021440873(struct intel_plane *plane, ctl &= ~MCURSOR_MODE_MASK; ctl |= MCURSOR_MODE_64_2B; - intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_CTL(pipe, plane->id), ctl); + intel_de_write_fw(dev_priv, SEL_FETCH_CUR_CTL(pipe), ctl); - intel_de_write(dev_priv, PIPE_SRCSZ_ERLY_TPT(pipe), - PIPESRC_HEIGHT(et_y_position)); + intel_de_write(dev_priv, CURPOS_ERLY_TPT(dev_priv, pipe), + CURSOR_POS_Y(et_y_position)); } static void i9xx_cursor_update_sel_fetch_arm(struct intel_plane *plane, @@ -541,10 +542,12 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_plane *plane, if (crtc_state->enable_psr2_su_region_et) { u32 val = intel_cursor_position(crtc_state, plane_state, true); - intel_de_write_fw(dev_priv, CURPOS_ERLY_TPT(pipe), val); + intel_de_write_fw(dev_priv, + CURPOS_ERLY_TPT(dev_priv, pipe), + val); } - intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_CTL(pipe, plane->id), + intel_de_write_fw(dev_priv, SEL_FETCH_CUR_CTL(pipe), plane_state->ctl); } else { /* Wa_16021440873 */ @@ -555,6 +558,60 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_plane *plane, } } +static u32 skl_cursor_ddb_reg_val(const struct skl_ddb_entry *entry) +{ + if (!entry->end) + return 0; + + return CUR_BUF_END(entry->end - 1) | + CUR_BUF_START(entry->start); +} + +static u32 skl_cursor_wm_reg_val(const struct skl_wm_level *level) +{ + u32 val = 0; + + if (level->enable) + val |= CUR_WM_EN; + if (level->ignore_lines) + val |= CUR_WM_IGNORE_LINES; + val |= REG_FIELD_PREP(CUR_WM_BLOCKS_MASK, level->blocks); + val |= REG_FIELD_PREP(CUR_WM_LINES_MASK, level->lines); + + return val; +} + +static void skl_write_cursor_wm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(plane->base.dev); + enum plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; + const struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; + int level; + + for (level = 0; level < i915->display.wm.num_levels; level++) + intel_de_write_fw(i915, CUR_WM(pipe, level), + skl_cursor_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level))); + + intel_de_write_fw(i915, CUR_WM_TRANS(pipe), + skl_cursor_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id))); + + if (HAS_HW_SAGV_WM(i915)) { + const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; + + intel_de_write_fw(i915, CUR_WM_SAGV(pipe), + skl_cursor_wm_reg_val(&wm->sagv.wm0)); + intel_de_write_fw(i915, CUR_WM_SAGV_TRANS(pipe), + skl_cursor_wm_reg_val(&wm->sagv.trans_wm)); + } + + intel_de_write_fw(i915, CUR_BUF_CFG(pipe), + skl_cursor_ddb_reg_val(ddb)); +} + /* TODO: split into noarm+arm pair */ static void i9xx_cursor_update_arm(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, @@ -611,18 +668,19 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane, plane->cursor.size != fbc_ctl || plane->cursor.cntl != cntl) { if (HAS_CUR_FBC(dev_priv)) - intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe), + intel_de_write_fw(dev_priv, + CUR_FBC_CTL(dev_priv, pipe), fbc_ctl); - intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl); - intel_de_write_fw(dev_priv, CURPOS(pipe), pos); - intel_de_write_fw(dev_priv, CURBASE(pipe), base); + intel_de_write_fw(dev_priv, CURCNTR(dev_priv, pipe), cntl); + intel_de_write_fw(dev_priv, CURPOS(dev_priv, pipe), pos); + intel_de_write_fw(dev_priv, CURBASE(dev_priv, pipe), base); plane->cursor.base = base; plane->cursor.size = fbc_ctl; plane->cursor.cntl = cntl; } else { - intel_de_write_fw(dev_priv, CURPOS(pipe), pos); - intel_de_write_fw(dev_priv, CURBASE(pipe), base); + intel_de_write_fw(dev_priv, CURPOS(dev_priv, pipe), pos); + intel_de_write_fw(dev_priv, CURBASE(dev_priv, pipe), base); } } @@ -651,7 +709,7 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane, if (!wakeref) return false; - val = intel_de_read(dev_priv, CURCNTR(plane->pipe)); + val = intel_de_read(dev_priv, CURCNTR(dev_priv, plane->pipe)); ret = val & MCURSOR_MODE_MASK; @@ -703,12 +761,12 @@ intel_legacy_cursor_update(struct drm_plane *_plane, * PSR2 plane and transcoder registers can only be updated during * vblank. * - * FIXME bigjoiner fastpath would be good + * FIXME joiner fastpath would be good */ if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) || intel_crtc_needs_fastset(crtc_state) || - crtc_state->bigjoiner_pipes) + crtc_state->joiner_pipes) goto slow; /* diff --git a/drivers/gpu/drm/i915/display/intel_cursor_regs.h b/drivers/gpu/drm/i915/display/intel_cursor_regs.h new file mode 100644 index 000000000000..aaa66331063e --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_cursor_regs.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __INTEL_CURSOR_REGS_H__ +#define __INTEL_CURSOR_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define _CURACNTR 0x70080 +#define CURCNTR(dev_priv, pipe) _MMIO_CURSOR2((dev_priv), (pipe), _CURACNTR) +/* Old style CUR*CNTR flags (desktop 8xx) */ +#define CURSOR_ENABLE REG_BIT(31) +#define CURSOR_PIPE_GAMMA_ENABLE REG_BIT(30) +#define CURSOR_STRIDE_MASK REG_GENMASK(29, 28) +#define CURSOR_STRIDE(stride) REG_FIELD_PREP(CURSOR_STRIDE_MASK, ffs(stride) - 9) /* 256,512,1k,2k */ +#define CURSOR_FORMAT_MASK REG_GENMASK(26, 24) +#define CURSOR_FORMAT_2C REG_FIELD_PREP(CURSOR_FORMAT_MASK, 0) +#define CURSOR_FORMAT_3C REG_FIELD_PREP(CURSOR_FORMAT_MASK, 1) +#define CURSOR_FORMAT_4C REG_FIELD_PREP(CURSOR_FORMAT_MASK, 2) +#define CURSOR_FORMAT_ARGB REG_FIELD_PREP(CURSOR_FORMAT_MASK, 4) +#define CURSOR_FORMAT_XRGB REG_FIELD_PREP(CURSOR_FORMAT_MASK, 5) +/* New style CUR*CNTR flags */ +#define MCURSOR_ARB_SLOTS_MASK REG_GENMASK(30, 28) /* icl+ */ +#define MCURSOR_ARB_SLOTS(x) REG_FIELD_PREP(MCURSOR_ARB_SLOTS_MASK, (x)) /* icl+ */ +#define MCURSOR_PIPE_SEL_MASK REG_GENMASK(29, 28) +#define MCURSOR_PIPE_SEL(pipe) REG_FIELD_PREP(MCURSOR_PIPE_SEL_MASK, (pipe)) +#define MCURSOR_PIPE_GAMMA_ENABLE REG_BIT(26) +#define MCURSOR_PIPE_CSC_ENABLE REG_BIT(24) /* ilk+ */ +#define MCURSOR_ROTATE_180 REG_BIT(15) +#define MCURSOR_TRICKLE_FEED_DISABLE REG_BIT(14) +#define MCURSOR_MODE_MASK 0x27 +#define MCURSOR_MODE_DISABLE 0x00 +#define MCURSOR_MODE_128_32B_AX 0x02 +#define MCURSOR_MODE_256_32B_AX 0x03 +#define MCURSOR_MODE_64_2B 0x04 +#define MCURSOR_MODE_64_32B_AX 0x07 +#define MCURSOR_MODE_128_ARGB_AX (0x20 | MCURSOR_MODE_128_32B_AX) +#define MCURSOR_MODE_256_ARGB_AX (0x20 | MCURSOR_MODE_256_32B_AX) +#define MCURSOR_MODE_64_ARGB_AX (0x20 | MCURSOR_MODE_64_32B_AX) + +#define _CURABASE 0x70084 +#define CURBASE(dev_priv, pipe) _MMIO_CURSOR2((dev_priv), (pipe), _CURABASE) + +#define _CURAPOS 0x70088 +#define CURPOS(dev_priv, pipe) _MMIO_CURSOR2((dev_priv), (pipe), _CURAPOS) +#define CURSOR_POS_Y_SIGN REG_BIT(31) +#define CURSOR_POS_Y_MASK REG_GENMASK(30, 16) +#define CURSOR_POS_Y(y) REG_FIELD_PREP(CURSOR_POS_Y_MASK, (y)) +#define CURSOR_POS_X_SIGN REG_BIT(15) +#define CURSOR_POS_X_MASK REG_GENMASK(14, 0) +#define CURSOR_POS_X(x) REG_FIELD_PREP(CURSOR_POS_X_MASK, (x)) + +#define _CURAPOS_ERLY_TPT 0x7008c +#define CURPOS_ERLY_TPT(dev_priv, pipe) _MMIO_CURSOR2((dev_priv), (pipe), _CURAPOS_ERLY_TPT) + +#define _CURASIZE 0x700a0 /* 845/865 */ +#define CURSIZE(dev_priv, pipe) _MMIO_CURSOR2((dev_priv), (pipe), _CURASIZE) +#define CURSOR_HEIGHT_MASK REG_GENMASK(21, 12) +#define CURSOR_HEIGHT(h) REG_FIELD_PREP(CURSOR_HEIGHT_MASK, (h)) +#define CURSOR_WIDTH_MASK REG_GENMASK(9, 0) +#define CURSOR_WIDTH(w) REG_FIELD_PREP(CURSOR_WIDTH_MASK, (w)) + +#define _CUR_FBC_CTL_A 0x700a0 /* ivb+ */ +#define CUR_FBC_CTL(dev_priv, pipe) _MMIO_CURSOR2((dev_priv), (pipe), _CUR_FBC_CTL_A) +#define CUR_FBC_EN REG_BIT(31) +#define CUR_FBC_HEIGHT_MASK REG_GENMASK(7, 0) +#define CUR_FBC_HEIGHT(h) REG_FIELD_PREP(CUR_FBC_HEIGHT_MASK, (h)) + +#define _CUR_CHICKEN_A 0x700a4 /* mtl+ */ +#define CUR_CHICKEN(dev_priv, pipe) _MMIO_CURSOR2((dev_priv), (pipe), _CUR_CHICKEN_A) + +#define _CURASURFLIVE 0x700ac /* g4x+ */ +#define CURSURFLIVE(dev_priv, pipe) _MMIO_CURSOR2((dev_priv), (pipe), _CURASURFLIVE) + +/* skl+ */ +#define _CUR_WM_A_0 0x70140 +#define _CUR_WM_B_0 0x71140 +#define CUR_WM(pipe, level) _MMIO(_PIPE((pipe), _CUR_WM_A_0, _CUR_WM_B_0) + (level) * 4) +#define CUR_WM_EN REG_BIT(31) +#define CUR_WM_IGNORE_LINES REG_BIT(30) +#define CUR_WM_LINES_MASK REG_GENMASK(26, 14) +#define CUR_WM_BLOCKS_MASK REG_GENMASK(11, 0) + +#define _CUR_WM_SAGV_A 0x70158 +#define _CUR_WM_SAGV_B 0x71158 +#define CUR_WM_SAGV(pipe) _MMIO_PIPE((pipe), _CUR_WM_SAGV_A, _CUR_WM_SAGV_B) + +#define _CUR_WM_SAGV_TRANS_A 0x7015C +#define _CUR_WM_SAGV_TRANS_B 0x7115C +#define CUR_WM_SAGV_TRANS(pipe) _MMIO_PIPE((pipe), _CUR_WM_SAGV_TRANS_A, _CUR_WM_SAGV_TRANS_B) + +#define _CUR_WM_TRANS_A 0x70168 +#define _CUR_WM_TRANS_B 0x71168 +#define CUR_WM_TRANS(pipe) _MMIO_PIPE((pipe), _CUR_WM_TRANS_A, _CUR_WM_TRANS_B) + +#define _CUR_BUF_CFG_A 0x7017c +#define _CUR_BUF_CFG_B 0x7117c +#define CUR_BUF_CFG(pipe) _MMIO_PIPE((pipe), _CUR_BUF_CFG_A, _CUR_BUF_CFG_B) +/* skl+: 10 bits, icl+ 11 bits, adlp+ 12 bits */ +#define CUR_BUF_END_MASK REG_GENMASK(27, 16) +#define CUR_BUF_END(end) REG_FIELD_PREP(CUR_BUF_END_MASK, (end)) +#define CUR_BUF_START_MASK REG_GENMASK(11, 0) +#define CUR_BUF_START(start) REG_FIELD_PREP(CUR_BUF_START_MASK, (start)) + +/* tgl+ */ +#define _SEL_FETCH_CUR_CTL_A 0x70880 +#define _SEL_FETCH_CUR_CTL_B 0x71880 +#define SEL_FETCH_CUR_CTL(pipe) _MMIO_PIPE((pipe), _SEL_FETCH_CUR_CTL_A, _SEL_FETCH_CUR_CTL_B) + +#endif /* __INTEL_CURSOR_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 8e3b13884bb8..41f684c970dc 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -946,6 +946,183 @@ static const struct intel_c20pll_state * const mtl_c20_dp_tables[] = { }; /* + * eDP link rates with 38.4 MHz reference clock. + */ + +static const struct intel_c20pll_state xe2hpd_c20_edp_r216 = { + .clock = 216000, + .tx = { 0xbe88, + 0x4800, + 0x0000, + }, + .cmn = { 0x0500, + 0x0005, + 0x0000, + 0x0000, + }, + .mpllb = { 0x50e1, + 0x2120, + 0x8e18, + 0xbfc1, + 0x9000, + 0x78f6, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + }, +}; + +static const struct intel_c20pll_state xe2hpd_c20_edp_r243 = { + .clock = 243000, + .tx = { 0xbe88, + 0x4800, + 0x0000, + }, + .cmn = { 0x0500, + 0x0005, + 0x0000, + 0x0000, + }, + .mpllb = { 0x50fd, + 0x2120, + 0x8f18, + 0xbfc1, + 0xa200, + 0x8814, + 0x2000, + 0x0001, + 0x1000, + 0x0000, + 0x0000, + }, +}; + +static const struct intel_c20pll_state xe2hpd_c20_edp_r324 = { + .clock = 324000, + .tx = { 0xbe88, + 0x4800, + 0x0000, + }, + .cmn = { 0x0500, + 0x0005, + 0x0000, + 0x0000, + }, + .mpllb = { 0x30a8, + 0x2110, + 0xcd9a, + 0xbfc1, + 0x6c00, + 0x5ab8, + 0x2000, + 0x0001, + 0x6000, + 0x0000, + 0x0000, + }, +}; + +static const struct intel_c20pll_state xe2hpd_c20_edp_r432 = { + .clock = 432000, + .tx = { 0xbe88, + 0x4800, + 0x0000, + }, + .cmn = { 0x0500, + 0x0005, + 0x0000, + 0x0000, + }, + .mpllb = { 0x30e1, + 0x2110, + 0x8e18, + 0xbfc1, + 0x9000, + 0x78f6, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + }, +}; + +static const struct intel_c20pll_state xe2hpd_c20_edp_r675 = { + .clock = 675000, + .tx = { 0xbe88, + 0x4800, + 0x0000, + }, + .cmn = { 0x0500, + 0x0005, + 0x0000, + 0x0000, + }, + .mpllb = { 0x10af, + 0x2108, + 0xce1a, + 0xbfc1, + 0x7080, + 0x5e80, + 0x2000, + 0x0001, + 0x6400, + 0x0000, + 0x0000, + }, +}; + +static const struct intel_c20pll_state * const xe2hpd_c20_edp_tables[] = { + &mtl_c20_dp_rbr, + &xe2hpd_c20_edp_r216, + &xe2hpd_c20_edp_r243, + &mtl_c20_dp_hbr1, + &xe2hpd_c20_edp_r324, + &xe2hpd_c20_edp_r432, + &mtl_c20_dp_hbr2, + &xe2hpd_c20_edp_r675, + &mtl_c20_dp_hbr3, + NULL, +}; + +static const struct intel_c20pll_state xe2hpd_c20_dp_uhbr13_5 = { + .clock = 1350000, /* 13.5 Gbps */ + .tx = { 0xbea0, /* tx cfg0 */ + 0x4800, /* tx cfg1 */ + 0x0000, /* tx cfg2 */ + }, + .cmn = {0x0500, /* cmn cfg0*/ + 0x0005, /* cmn cfg1 */ + 0x0000, /* cmn cfg2 */ + 0x0000, /* cmn cfg3 */ + }, + .mpllb = { 0x015f, /* mpllb cfg0 */ + 0x2205, /* mpllb cfg1 */ + 0x1b17, /* mpllb cfg2 */ + 0xffc1, /* mpllb cfg3 */ + 0xbd00, /* mpllb cfg4 */ + 0x9ec3, /* mpllb cfg5 */ + 0x2000, /* mpllb cfg6 */ + 0x0001, /* mpllb cfg7 */ + 0x4800, /* mpllb cfg8 */ + 0x0000, /* mpllb cfg9 */ + 0x0000, /* mpllb cfg10 */ + }, +}; + +static const struct intel_c20pll_state * const xe2hpd_c20_dp_tables[] = { + &mtl_c20_dp_rbr, + &mtl_c20_dp_hbr1, + &mtl_c20_dp_hbr2, + &mtl_c20_dp_hbr3, + &mtl_c20_dp_uhbr10, + &xe2hpd_c20_dp_uhbr13_5, + NULL, +}; + +/* * HDMI link rates with 38.4 MHz reference clock. */ @@ -1861,6 +2038,7 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, if (crtc_state->port_clock == tables[i]->clock) { crtc_state->dpll_hw_state.cx0pll.c10 = *tables[i]; intel_c10pll_update_pll(crtc_state, encoder); + crtc_state->dpll_hw_state.cx0pll.use_c10 = true; return 0; } @@ -1928,8 +2106,8 @@ static void intel_c10_pll_program(struct drm_i915_private *i915, MB_WRITE_COMMITTED); } -void intel_c10pll_dump_hw_state(struct drm_i915_private *i915, - const struct intel_c10pll_state *hw_state) +static void intel_c10pll_dump_hw_state(struct drm_i915_private *i915, + const struct intel_c10pll_state *hw_state) { bool fracen; int i; @@ -2061,10 +2239,20 @@ static const struct intel_c20pll_state * const * intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { - if (intel_crtc_has_dp_encoder(crtc_state)) - return mtl_c20_dp_tables; - else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + if (intel_crtc_has_dp_encoder(crtc_state)) { + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) + return xe2hpd_c20_edp_tables; + + if (DISPLAY_VER_FULL(i915) == IP_VER(14, 1)) + return xe2hpd_c20_dp_tables; + else + return mtl_c20_dp_tables; + + } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { return mtl_c20_hdmi_tables; + } MISSING_CASE(encoder->type); return NULL; @@ -2090,6 +2278,7 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, for (i = 0; tables[i]; i++) { if (crtc_state->port_clock == tables[i]->clock) { crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i]; + crtc_state->dpll_hw_state.cx0pll.use_c10 = false; return 0; } } @@ -2161,6 +2350,7 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, bool cntx; intel_wakeref_t wakeref; int i; + struct drm_i915_private *i915 = to_i915(encoder->base.dev); wakeref = intel_cx0_phy_transaction_begin(encoder); @@ -2170,42 +2360,50 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, /* Read Tx configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) { if (cntx) - pll_state->tx[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, - PHY_C20_B_TX_CNTX_CFG(i)); + pll_state->tx[i] = intel_c20_sram_read(encoder, + INTEL_CX0_LANE0, + PHY_C20_B_TX_CNTX_CFG(i915, i)); else - pll_state->tx[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, - PHY_C20_A_TX_CNTX_CFG(i)); + pll_state->tx[i] = intel_c20_sram_read(encoder, + INTEL_CX0_LANE0, + PHY_C20_A_TX_CNTX_CFG(i915, i)); } /* Read common configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->cmn); i++) { if (cntx) - pll_state->cmn[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, - PHY_C20_B_CMN_CNTX_CFG(i)); + pll_state->cmn[i] = intel_c20_sram_read(encoder, + INTEL_CX0_LANE0, + PHY_C20_B_CMN_CNTX_CFG(i915, i)); else - pll_state->cmn[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, - PHY_C20_A_CMN_CNTX_CFG(i)); + pll_state->cmn[i] = intel_c20_sram_read(encoder, + INTEL_CX0_LANE0, + PHY_C20_A_CMN_CNTX_CFG(i915, i)); } if (intel_c20phy_use_mpllb(pll_state)) { /* MPLLB configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) { if (cntx) - pll_state->mpllb[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, - PHY_C20_B_MPLLB_CNTX_CFG(i)); + pll_state->mpllb[i] = intel_c20_sram_read(encoder, + INTEL_CX0_LANE0, + PHY_C20_B_MPLLB_CNTX_CFG(i915, i)); else - pll_state->mpllb[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, - PHY_C20_A_MPLLB_CNTX_CFG(i)); + pll_state->mpllb[i] = intel_c20_sram_read(encoder, + INTEL_CX0_LANE0, + PHY_C20_A_MPLLB_CNTX_CFG(i915, i)); } } else { /* MPLLA configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) { if (cntx) - pll_state->mplla[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, - PHY_C20_B_MPLLA_CNTX_CFG(i)); + pll_state->mplla[i] = intel_c20_sram_read(encoder, + INTEL_CX0_LANE0, + PHY_C20_B_MPLLA_CNTX_CFG(i915, i)); else - pll_state->mplla[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, - PHY_C20_A_MPLLA_CNTX_CFG(i)); + pll_state->mplla[i] = intel_c20_sram_read(encoder, + INTEL_CX0_LANE0, + PHY_C20_A_MPLLA_CNTX_CFG(i915, i)); } } @@ -2214,8 +2412,8 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, intel_cx0_phy_transaction_end(encoder, wakeref); } -void intel_c20pll_dump_hw_state(struct drm_i915_private *i915, - const struct intel_c20pll_state *hw_state) +static void intel_c20pll_dump_hw_state(struct drm_i915_private *i915, + const struct intel_c20pll_state *hw_state) { int i; @@ -2234,6 +2432,15 @@ void intel_c20pll_dump_hw_state(struct drm_i915_private *i915, } } +void intel_cx0pll_dump_hw_state(struct drm_i915_private *i915, + const struct intel_cx0pll_state *hw_state) +{ + if (hw_state->use_c10) + intel_c10pll_dump_hw_state(i915, &hw_state->c10); + else + intel_c20pll_dump_hw_state(i915, &hw_state->c20); +} + static u8 intel_c20_get_dp_rate(u32 clock) { switch (clock) { @@ -2337,7 +2544,7 @@ static void intel_c20_pll_program(struct drm_i915_private *i915, { const struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20; bool dp = false; - int lane = crtc_state->lane_count > 2 ? INTEL_CX0_BOTH_LANES : INTEL_CX0_LANE0; + u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); u32 clock = crtc_state->port_clock; bool cntx; int i; @@ -2363,17 +2570,25 @@ static void intel_c20_pll_program(struct drm_i915_private *i915, /* 3.1 Tx configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) { if (cntx) - intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_A_TX_CNTX_CFG(i), pll_state->tx[i]); + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, + PHY_C20_A_TX_CNTX_CFG(i915, i), + pll_state->tx[i]); else - intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_B_TX_CNTX_CFG(i), pll_state->tx[i]); + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, + PHY_C20_B_TX_CNTX_CFG(i915, i), + pll_state->tx[i]); } /* 3.2 common configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->cmn); i++) { if (cntx) - intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_A_CMN_CNTX_CFG(i), pll_state->cmn[i]); + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, + PHY_C20_A_CMN_CNTX_CFG(i915, i), + pll_state->cmn[i]); else - intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_B_CMN_CNTX_CFG(i), pll_state->cmn[i]); + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, + PHY_C20_B_CMN_CNTX_CFG(i915, i), + pll_state->cmn[i]); } /* 3.3 mpllb or mplla configuration */ @@ -2381,40 +2596,40 @@ static void intel_c20_pll_program(struct drm_i915_private *i915, for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) { if (cntx) intel_c20_sram_write(encoder, INTEL_CX0_LANE0, - PHY_C20_A_MPLLB_CNTX_CFG(i), + PHY_C20_A_MPLLB_CNTX_CFG(i915, i), pll_state->mpllb[i]); else intel_c20_sram_write(encoder, INTEL_CX0_LANE0, - PHY_C20_B_MPLLB_CNTX_CFG(i), + PHY_C20_B_MPLLB_CNTX_CFG(i915, i), pll_state->mpllb[i]); } } else { for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) { if (cntx) intel_c20_sram_write(encoder, INTEL_CX0_LANE0, - PHY_C20_A_MPLLA_CNTX_CFG(i), + PHY_C20_A_MPLLA_CNTX_CFG(i915, i), pll_state->mplla[i]); else intel_c20_sram_write(encoder, INTEL_CX0_LANE0, - PHY_C20_B_MPLLA_CNTX_CFG(i), + PHY_C20_B_MPLLA_CNTX_CFG(i915, i), pll_state->mplla[i]); } } /* 4. Program custom width to match the link protocol */ - intel_cx0_rmw(encoder, lane, PHY_C20_VDR_CUSTOM_WIDTH, + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_WIDTH, PHY_C20_CUSTOM_WIDTH_MASK, PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(clock, dp)), MB_WRITE_COMMITTED); /* 5. For DP or 6. For HDMI */ if (dp) { - intel_cx0_rmw(encoder, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE, + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, BIT(6) | PHY_C20_CUSTOM_SERDES_MASK, BIT(6) | PHY_C20_CUSTOM_SERDES(intel_c20_get_dp_rate(clock)), MB_WRITE_COMMITTED); } else { - intel_cx0_rmw(encoder, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE, + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, BIT(7) | PHY_C20_CUSTOM_SERDES_MASK, is_hdmi_frl(clock) ? BIT(7) : 0, MB_WRITE_COMMITTED); @@ -2428,7 +2643,7 @@ static void intel_c20_pll_program(struct drm_i915_private *i915, * 7. Write Vendor specific registers to toggle context setting to load * the updated programming toggle context bit */ - intel_cx0_rmw(encoder, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE, + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, BIT(0), cntx ? 0 : 1, MB_WRITE_COMMITTED); } @@ -2900,17 +3115,28 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder, intel_cx0pll_enable(encoder, crtc_state); } +static u8 cx0_power_control_disable_val(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + if (intel_encoder_is_c10phy(encoder)) + return CX0_P2PG_STATE_DISABLE; + + if (IS_BATTLEMAGE(i915) && encoder->port == PORT_A) + return CX0_P2PG_STATE_DISABLE; + + return CX0_P4PG_STATE_DISABLE; +} + static void intel_cx0pll_disable(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); enum phy phy = intel_encoder_to_phy(encoder); - bool is_c10 = intel_encoder_is_c10phy(encoder); intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder); /* 1. Change owned PHY lane power to Disable state. */ intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, - is_c10 ? CX0_P2PG_STATE_DISABLE : - CX0_P4PG_STATE_DISABLE); + cx0_power_control_disable_val(encoder)); /* * 2. Follow the Display Voltage Frequency Switching Sequence Before @@ -3028,9 +3254,6 @@ static void intel_c10pll_state_verify(const struct intel_crtc_state *state, const struct intel_c10pll_state *mpllb_sw_state = &state->dpll_hw_state.cx0pll.c10; int i; - if (intel_crtc_needs_fastset(state)) - return; - for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) { u8 expected = mpllb_sw_state->pll[i]; @@ -3054,10 +3277,64 @@ static void intel_c10pll_state_verify(const struct intel_crtc_state *state, void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { - if (intel_encoder_is_c10phy(encoder)) + pll_state->use_c10 = false; + + if (intel_encoder_is_c10phy(encoder)) { intel_c10pll_readout_hw_state(encoder, &pll_state->c10); - else + pll_state->use_c10 = true; + } else { intel_c20pll_readout_hw_state(encoder, &pll_state->c20); + } +} + +static bool mtl_compare_hw_state_c10(const struct intel_c10pll_state *a, + const struct intel_c10pll_state *b) +{ + if (a->tx != b->tx) + return false; + + if (a->cmn != b->cmn) + return false; + + if (memcmp(&a->pll, &b->pll, sizeof(a->pll)) != 0) + return false; + + return true; +} + +static bool mtl_compare_hw_state_c20(const struct intel_c20pll_state *a, + const struct intel_c20pll_state *b) +{ + if (memcmp(&a->tx, &b->tx, sizeof(a->tx)) != 0) + return false; + + if (memcmp(&a->cmn, &b->cmn, sizeof(a->cmn)) != 0) + return false; + + if (a->tx[0] & C20_PHY_USE_MPLLB) { + if (memcmp(&a->mpllb, &b->mpllb, sizeof(a->mpllb)) != 0) + return false; + } else { + if (memcmp(&a->mplla, &b->mplla, sizeof(a->mplla)) != 0) + return false; + } + + return true; +} + +bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a, + const struct intel_cx0pll_state *b) +{ + + if (a->use_c10 != b->use_c10) + return false; + + if (a->use_c10) + return mtl_compare_hw_state_c10(&a->c10, + &b->c10); + else + return mtl_compare_hw_state_c20(&a->c20, + &b->c20); } int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, @@ -3078,9 +3355,10 @@ static void intel_c20pll_state_verify(const struct intel_crtc_state *state, const struct intel_c20pll_state *mpll_sw_state = &state->dpll_hw_state.cx0pll.c20; bool sw_use_mpllb = intel_c20phy_use_mpllb(mpll_sw_state); bool hw_use_mpllb = intel_c20phy_use_mpllb(mpll_hw_state); + int clock = intel_c20pll_calc_port_clock(encoder, mpll_sw_state); int i; - I915_STATE_WARN(i915, mpll_hw_state->clock != mpll_sw_state->clock, + I915_STATE_WARN(i915, mpll_hw_state->clock != clock, "[CRTC:%d:%s] mismatch in C20: Register CLOCK (expected %d, found %d)", crtc->base.base.id, crtc->base.name, mpll_sw_state->clock, mpll_hw_state->clock); diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index 3e03af3e006c..9004b99bb51f 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -35,12 +35,12 @@ void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state); -void intel_c10pll_dump_hw_state(struct drm_i915_private *dev_priv, - const struct intel_c10pll_state *hw_state); +void intel_cx0pll_dump_hw_state(struct drm_i915_private *dev_priv, + const struct intel_cx0pll_state *hw_state); void intel_cx0pll_state_verify(struct intel_atomic_state *state, struct intel_crtc *crtc); -void intel_c20pll_dump_hw_state(struct drm_i915_private *i915, - const struct intel_c20pll_state *hw_state); +bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a, + const struct intel_cx0pll_state *b); void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock); diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h index bdd0c8c4ef97..ab3ae110b68f 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h @@ -254,18 +254,50 @@ #define PHY_C20_VDR_CUSTOM_WIDTH 0xD02 #define PHY_C20_CUSTOM_WIDTH_MASK REG_GENMASK(1, 0) #define PHY_C20_CUSTOM_WIDTH(val) REG_FIELD_PREP8(PHY_C20_CUSTOM_WIDTH_MASK, val) -#define PHY_C20_A_TX_CNTX_CFG(idx) (0xCF2E - (idx)) -#define PHY_C20_B_TX_CNTX_CFG(idx) (0xCF2A - (idx)) + +#define _MTL_C20_A_TX_CNTX_CFG 0xCF2E +#define _MTL_C20_B_TX_CNTX_CFG 0xCF2A +#define _MTL_C20_A_CMN_CNTX_CFG 0xCDAA +#define _MTL_C20_B_CMN_CNTX_CFG 0xCDA5 +#define _MTL_C20_A_MPLLA_CFG 0xCCF0 +#define _MTL_C20_B_MPLLA_CFG 0xCCE5 +#define _MTL_C20_A_MPLLB_CFG 0xCB5A +#define _MTL_C20_B_MPLLB_CFG 0xCB4E + +#define _XE2HPD_C20_A_TX_CNTX_CFG 0xCF5E +#define _XE2HPD_C20_B_TX_CNTX_CFG 0xCF5A +#define _XE2HPD_C20_A_CMN_CNTX_CFG 0xCE8E +#define _XE2HPD_C20_B_CMN_CNTX_CFG 0xCE89 +#define _XE2HPD_C20_A_MPLLA_CFG 0xCE58 +#define _XE2HPD_C20_B_MPLLA_CFG 0xCE4D +#define _XE2HPD_C20_A_MPLLB_CFG 0xCCC2 +#define _XE2HPD_C20_B_MPLLB_CFG 0xCCB6 + +#define _IS_XE2HPD_C20(i915) (DISPLAY_VER_FULL(i915) == IP_VER(14, 1)) + +#define PHY_C20_A_TX_CNTX_CFG(i915, idx) \ + ((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_A_TX_CNTX_CFG : _MTL_C20_A_TX_CNTX_CFG) - (idx)) +#define PHY_C20_B_TX_CNTX_CFG(i915, idx) \ + ((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_B_TX_CNTX_CFG : _MTL_C20_B_TX_CNTX_CFG) - (idx)) #define C20_PHY_TX_RATE REG_GENMASK(2, 0) -#define PHY_C20_A_CMN_CNTX_CFG(idx) (0xCDAA - (idx)) -#define PHY_C20_B_CMN_CNTX_CFG(idx) (0xCDA5 - (idx)) -#define PHY_C20_A_MPLLA_CNTX_CFG(idx) (0xCCF0 - (idx)) -#define PHY_C20_B_MPLLA_CNTX_CFG(idx) (0xCCE5 - (idx)) + +#define PHY_C20_A_CMN_CNTX_CFG(i915, idx) \ + ((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_A_CMN_CNTX_CFG : _MTL_C20_A_CMN_CNTX_CFG) - (idx)) +#define PHY_C20_B_CMN_CNTX_CFG(i915, idx) \ + ((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_B_CMN_CNTX_CFG : _MTL_C20_B_CMN_CNTX_CFG) - (idx)) +#define PHY_C20_A_MPLLA_CNTX_CFG(i915, idx) \ + ((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_A_MPLLA_CFG : _MTL_C20_A_MPLLA_CFG) - (idx)) +#define PHY_C20_B_MPLLA_CNTX_CFG(i915, idx) \ + ((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_B_MPLLA_CFG : _MTL_C20_B_MPLLA_CFG) - (idx)) #define C20_MPLLA_FRACEN REG_BIT(14) #define C20_FB_CLK_DIV4_EN REG_BIT(13) #define C20_MPLLA_TX_CLK_DIV_MASK REG_GENMASK(10, 8) -#define PHY_C20_A_MPLLB_CNTX_CFG(idx) (0xCB5A - (idx)) -#define PHY_C20_B_MPLLB_CNTX_CFG(idx) (0xCB4E - (idx)) + +#define PHY_C20_A_MPLLB_CNTX_CFG(i915, idx) \ + ((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_A_MPLLB_CFG : _MTL_C20_A_MPLLB_CFG) - (idx)) +#define PHY_C20_B_MPLLB_CNTX_CFG(i915, idx) \ + ((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_B_MPLLB_CFG : _MTL_C20_B_MPLLB_CFG) - (idx)) + #define C20_MPLLB_TX_CLK_DIV_MASK REG_GENMASK(15, 13) #define C20_MPLLB_FRACEN REG_BIT(13) #define C20_REF_CLK_MPLLB_DIV_MASK REG_GENMASK(12, 10) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 3c3fc53376ce..bb13a3ca8c7c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -57,6 +57,7 @@ #include "intel_dp_tunnel.h" #include "intel_dpio_phy.h" #include "intel_dsi.h" +#include "intel_encoder.h" #include "intel_fdi.h" #include "intel_fifo_underrun.h" #include "intel_gmbus.h" @@ -440,7 +441,8 @@ void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state, if (intel_dp_needs_vsc_sdp(crtc_state, conn_state)) temp |= DP_MSA_MISC_COLOR_VSC_SDP; - intel_de_write(dev_priv, TRANS_MSA_MISC(cpu_transcoder), temp); + intel_de_write(dev_priv, TRANS_MSA_MISC(dev_priv, cpu_transcoder), + temp); } static u32 bdw_trans_port_sync_master_select(enum transcoder master_transcoder) @@ -603,10 +605,11 @@ void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder, } intel_de_write(dev_priv, - TRANS_DDI_FUNC_CTL2(cpu_transcoder), ctl2); + TRANS_DDI_FUNC_CTL2(dev_priv, cpu_transcoder), + ctl2); } - intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), + intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder), intel_ddi_transcoder_func_reg_val_get(encoder, crtc_state)); } @@ -626,7 +629,8 @@ intel_ddi_config_transcoder_func(struct intel_encoder *encoder, ctl = intel_ddi_transcoder_func_reg_val_get(encoder, crtc_state); ctl &= ~TRANS_DDI_FUNC_ENABLE; - intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), ctl); + intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder), + ctl); } void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state) @@ -639,9 +643,11 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state if (DISPLAY_VER(dev_priv) >= 11) intel_de_write(dev_priv, - TRANS_DDI_FUNC_CTL2(cpu_transcoder), 0); + TRANS_DDI_FUNC_CTL2(dev_priv, cpu_transcoder), + 0); - ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); + ctl = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)); drm_WARN_ON(crtc->base.dev, ctl & TRANS_DDI_HDCP_SIGNALLING); @@ -660,7 +666,8 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state ctl &= ~(TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK); } - intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), ctl); + intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder), + ctl); if (intel_has_quirk(display, QUIRK_INCREASE_DDI_DISABLED_TIME) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { @@ -684,7 +691,7 @@ int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder, if (drm_WARN_ON(dev, !wakeref)) return -ENXIO; - intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), + intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder), hdcp_mask, enable ? hdcp_mask : 0); intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref); return ret; @@ -718,7 +725,8 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector) else cpu_transcoder = (enum transcoder) pipe; - tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); + tmp = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)); switch (tmp & TRANS_DDI_MODE_SELECT_MASK) { case TRANS_DDI_MODE_SELECT_HDMI: @@ -782,7 +790,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder, if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A) { tmp = intel_de_read(dev_priv, - TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); + TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_EDP)); switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { default: @@ -823,7 +831,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder, } tmp = intel_de_read(dev_priv, - TRANS_DDI_FUNC_CTL(cpu_transcoder)); + TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)); intel_display_power_put(dev_priv, POWER_DOMAIN_TRANSCODER(cpu_transcoder), trans_wakeref); @@ -2072,9 +2080,9 @@ void intel_ddi_sanitize_encoder_pll_mapping(struct intel_encoder *encoder) !encoder->is_clock_enabled(encoder)) return; - drm_notice(&i915->drm, - "[ENCODER:%d:%s] is disabled/in DSI mode with an ungated DDI clock, gate it\n", - encoder->base.base.id, encoder->base.name); + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] is disabled/in DSI mode with an ungated DDI clock, gate it\n", + encoder->base.base.id, encoder->base.name); encoder->disable_clock(encoder); } @@ -2178,7 +2186,8 @@ i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); if (DISPLAY_VER(dev_priv) >= 12) - return TGL_DP_TP_CTL(tgl_dp_tp_transcoder(crtc_state)); + return TGL_DP_TP_CTL(dev_priv, + tgl_dp_tp_transcoder(crtc_state)); else return DP_TP_CTL(encoder->port); } @@ -2189,7 +2198,8 @@ i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); if (DISPLAY_VER(dev_priv) >= 12) - return TGL_DP_TP_STATUS(tgl_dp_tp_transcoder(crtc_state)); + return TGL_DP_TP_STATUS(dev_priv, + tgl_dp_tp_transcoder(crtc_state)); else return DP_TP_STATUS(encoder->port); } @@ -2586,7 +2596,7 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state, * Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent) * (timeout after 800 us) */ - intel_dp_start_link_train(intel_dp, crtc_state); + intel_dp_start_link_train(state, intel_dp, crtc_state); /* 6.n Set DP_TP_CTL link training to Normal */ if (!is_trans_port_sync_mode(crtc_state)) @@ -2728,7 +2738,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state, * Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent) * (timeout after 800 us) */ - intel_dp_start_link_train(intel_dp, crtc_state); + intel_dp_start_link_train(state, intel_dp, crtc_state); /* 7.k Set DP_TP_CTL link training to Normal */ if (!is_trans_port_sync_mode(crtc_state)) @@ -2795,7 +2805,7 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state, to_intel_connector(conn_state->connector), crtc_state); intel_dp_sink_set_fec_ready(intel_dp, crtc_state, true); - intel_dp_start_link_train(intel_dp, crtc_state); + intel_dp_start_link_train(state, intel_dp, crtc_state); if ((port != PORT_A || DISPLAY_VER(dev_priv) >= 9) && !is_trans_port_sync_mode(crtc_state)) intel_dp_stop_link_train(intel_dp, crtc_state); @@ -3025,7 +3035,8 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state, if (is_mst) { enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; - intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), + intel_de_rmw(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder), TGL_TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK, 0); } @@ -3506,11 +3517,10 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state, bool is_tc_port = intel_encoder_is_tc(encoder); if (is_tc_port) { - struct intel_crtc *master_crtc = - to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); intel_tc_port_get_link(dig_port, crtc_state->lane_count); - intel_ddi_update_active_dpll(state, encoder, master_crtc); + intel_ddi_update_active_dpll(state, encoder, crtc); } main_link_aux_power_domain_get(dig_port, crtc_state); @@ -3752,14 +3762,16 @@ static enum transcoder bdw_transcoder_master_readout(struct drm_i915_private *de u32 master_select; if (DISPLAY_VER(dev_priv) >= 11) { - u32 ctl2 = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL2(cpu_transcoder)); + u32 ctl2 = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL2(dev_priv, cpu_transcoder)); if ((ctl2 & PORT_SYNC_MODE_ENABLE) == 0) return INVALID_TRANSCODER; master_select = REG_FIELD_GET(PORT_SYNC_MODE_MASTER_SELECT_MASK, ctl2); } else { - u32 ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); + u32 ctl = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)); if ((ctl & TRANS_DDI_PORT_SYNC_ENABLE) == 0) return INVALID_TRANSCODER; @@ -3815,7 +3827,8 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder, struct intel_digital_port *dig_port = enc_to_dig_port(encoder); u32 temp, flags = 0; - temp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); + temp = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)); if (temp & TRANS_DDI_PHSYNC) flags |= DRM_MODE_FLAG_PHSYNC; else @@ -4264,10 +4277,10 @@ static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state { /* * FIXME the modeset sequence is currently wrong and - * can't deal with bigjoiner + port sync at the same time. + * can't deal with joiner + port sync at the same time. */ return crtc_state1->hw.active && crtc_state2->hw.active && - !crtc_state1->bigjoiner_pipes && !crtc_state2->bigjoiner_pipes && + !crtc_state1->joiner_pipes && !crtc_state2->joiner_pipes && crtc_state1->output_types == crtc_state2->output_types && crtc_state1->output_format == crtc_state2->output_format && crtc_state1->lane_count == crtc_state2->lane_count && @@ -4441,35 +4454,6 @@ intel_ddi_init_dp_connector(struct intel_digital_port *dig_port) return connector; } -static int modeset_pipe(struct drm_crtc *crtc, - struct drm_modeset_acquire_ctx *ctx) -{ - struct drm_atomic_state *state; - struct drm_crtc_state *crtc_state; - int ret; - - state = drm_atomic_state_alloc(crtc->dev); - if (!state) - return -ENOMEM; - - state->acquire_ctx = ctx; - to_intel_atomic_state(state)->internal = true; - - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - ret = PTR_ERR(crtc_state); - goto out; - } - - crtc_state->connectors_changed = true; - - ret = drm_atomic_commit(state); -out: - drm_atomic_state_put(state); - - return ret; -} - static int intel_hdmi_reset_link(struct intel_encoder *encoder, struct drm_modeset_acquire_ctx *ctx) { @@ -4539,7 +4523,18 @@ static int intel_hdmi_reset_link(struct intel_encoder *encoder, * would be perfectly happy if were to just reconfigure * the SCDC settings on the fly. */ - return modeset_pipe(&crtc->base, ctx); + return intel_modeset_commit_pipes(dev_priv, BIT(crtc->pipe), ctx); +} + +static void intel_ddi_link_check(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + + /* TODO: Move checking the HDMI link state here as well. */ + drm_WARN_ON(&i915->drm, !dig_port->dp.attached_connector); + + intel_dp_link_check(encoder); } static enum intel_hotplug_state @@ -4563,14 +4558,13 @@ intel_ddi_hotplug(struct intel_encoder *encoder, state = intel_encoder_hotplug(encoder, connector); if (!intel_tc_port_link_reset(dig_port)) { - intel_modeset_lock_ctx_retry(&ctx, NULL, 0, ret) { - if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) + if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) { + intel_modeset_lock_ctx_retry(&ctx, NULL, 0, ret) ret = intel_hdmi_reset_link(encoder, &ctx); - else - ret = intel_dp_retrain_link(encoder, &ctx); + drm_WARN_ON(encoder->base.dev, ret); + } else { + intel_dp_check_link_state(intel_dp); } - - drm_WARN_ON(encoder->base.dev, ret); } /* @@ -4785,6 +4779,11 @@ static void intel_ddi_tc_encoder_suspend_complete(struct intel_encoder *encoder) struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + /* + * TODO: Move this to intel_dp_encoder_suspend(), + * once modeset locking around that is removed. + */ + intel_encoder_link_check_flush_work(encoder); intel_tc_port_suspend(dig_port); } @@ -4975,6 +4974,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, "DDI %c/PHY %c", port_name(port), phy_name(phy)); } + intel_encoder_link_check_init(encoder, intel_ddi_link_check); + mutex_init(&dig_port->hdcp_mutex); dig_port->num_hdcp_streams = 0; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 273323f30ae2..7bc4f3de691e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -54,6 +54,7 @@ #include "i915_reg.h" #include "i915_utils.h" #include "i9xx_plane.h" +#include "i9xx_plane_regs.h" #include "i9xx_wm.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" @@ -65,6 +66,8 @@ #include "intel_crt.h" #include "intel_crtc.h" #include "intel_crtc_state_dump.h" +#include "intel_cursor_regs.h" +#include "intel_cx0_phy.h" #include "intel_ddi.h" #include "intel_de.h" #include "intel_display_driver.h" @@ -109,6 +112,7 @@ #include "intel_sdvo.h" #include "intel_snps_phy.h" #include "intel_tc.h" +#include "intel_tdf.h" #include "intel_tv.h" #include "intel_vblank.h" #include "intel_vdsc.h" @@ -118,6 +122,7 @@ #include "intel_wm.h" #include "skl_scaler.h" #include "skl_universal_plane.h" +#include "skl_universal_plane_regs.h" #include "skl_watermark.h" #include "vlv_dpio_phy_regs.h" #include "vlv_dsi.h" @@ -241,53 +246,53 @@ is_trans_port_sync_mode(const struct intel_crtc_state *crtc_state) is_trans_port_sync_slave(crtc_state); } -static enum pipe bigjoiner_master_pipe(const struct intel_crtc_state *crtc_state) +static enum pipe joiner_primary_pipe(const struct intel_crtc_state *crtc_state) { - return ffs(crtc_state->bigjoiner_pipes) - 1; + return ffs(crtc_state->joiner_pipes) - 1; } -u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state) +u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state) { - if (crtc_state->bigjoiner_pipes) - return crtc_state->bigjoiner_pipes & ~BIT(bigjoiner_master_pipe(crtc_state)); + if (crtc_state->joiner_pipes) + return crtc_state->joiner_pipes & ~BIT(joiner_primary_pipe(crtc_state)); else return 0; } -bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state) +bool intel_crtc_is_joiner_secondary(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - return crtc_state->bigjoiner_pipes && - crtc->pipe != bigjoiner_master_pipe(crtc_state); + return crtc_state->joiner_pipes && + crtc->pipe != joiner_primary_pipe(crtc_state); } -bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state) +bool intel_crtc_is_joiner_primary(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - return crtc_state->bigjoiner_pipes && - crtc->pipe == bigjoiner_master_pipe(crtc_state); + return crtc_state->joiner_pipes && + crtc->pipe == joiner_primary_pipe(crtc_state); } -static int intel_bigjoiner_num_pipes(const struct intel_crtc_state *crtc_state) +static int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state) { - return hweight8(crtc_state->bigjoiner_pipes); + return hweight8(crtc_state->joiner_pipes); } u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - return BIT(crtc->pipe) | crtc_state->bigjoiner_pipes; + return BIT(crtc->pipe) | crtc_state->joiner_pipes; } -struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state) +struct intel_crtc *intel_primary_crtc(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - if (intel_crtc_is_bigjoiner_slave(crtc_state)) - return intel_crtc_for_pipe(i915, bigjoiner_master_pipe(crtc_state)); + if (intel_crtc_is_joiner_secondary(crtc_state)) + return intel_crtc_for_pipe(i915, joiner_primary_pipe(crtc_state)); else return to_intel_crtc(crtc_state->uapi.crtc); } @@ -302,7 +307,7 @@ intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state) enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; /* Wait for the Pipe State to go off */ - if (intel_de_wait_for_clear(dev_priv, TRANSCONF(cpu_transcoder), + if (intel_de_wait_for_clear(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), TRANSCONF_STATE_ENABLE, 100)) drm_WARN(&dev_priv->drm, 1, "pipe_off wait timed out\n"); } else { @@ -324,7 +329,8 @@ void assert_transcoder(struct drm_i915_private *dev_priv, power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); if (wakeref) { - u32 val = intel_de_read(dev_priv, TRANSCONF(cpu_transcoder)); + u32 val = intel_de_read(dev_priv, + TRANSCONF(dev_priv, cpu_transcoder)); cur_state = !!(val & TRANSCONF_ENABLE); intel_display_power_put(dev_priv, power_domain, wakeref); @@ -377,11 +383,11 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, fallthrough; case PORT_B: port_mask = DPLL_PORTB_READY_MASK; - dpll_reg = DPLL(0); + dpll_reg = DPLL(dev_priv, 0); break; case PORT_C: port_mask = DPLL_PORTC_READY_MASK; - dpll_reg = DPLL(0); + dpll_reg = DPLL(dev_priv, 0); expected_mask <<= 4; break; case PORT_D: @@ -433,7 +439,7 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state) /* Wa_22012358565:adl-p */ if (DISPLAY_VER(dev_priv) == 13) - intel_de_rmw(dev_priv, PIPE_ARB_CTL(pipe), + intel_de_rmw(dev_priv, PIPE_ARB_CTL(dev_priv, pipe), 0, PIPE_ARB_USE_PROG_SLOTS); if (DISPLAY_VER(dev_priv) >= 14) { @@ -448,7 +454,7 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state) clear, set); } - val = intel_de_read(dev_priv, TRANSCONF(cpu_transcoder)); + val = intel_de_read(dev_priv, TRANSCONF(dev_priv, cpu_transcoder)); if (val & TRANSCONF_ENABLE) { /* we keep both pipes enabled on 830 */ drm_WARN_ON(&dev_priv->drm, !IS_I830(dev_priv)); @@ -463,9 +469,9 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state) TRANSCONF_PIXEL_COUNT_SCALING_X4); } - intel_de_write(dev_priv, TRANSCONF(cpu_transcoder), + intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), val | TRANSCONF_ENABLE); - intel_de_posting_read(dev_priv, TRANSCONF(cpu_transcoder)); + intel_de_posting_read(dev_priv, TRANSCONF(dev_priv, cpu_transcoder)); /* * Until the pipe starts PIPEDSL reads will return a stale value, @@ -494,7 +500,7 @@ void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state) */ assert_planes_disabled(crtc); - val = intel_de_read(dev_priv, TRANSCONF(cpu_transcoder)); + val = intel_de_read(dev_priv, TRANSCONF(dev_priv, cpu_transcoder)); if ((val & TRANSCONF_ENABLE) == 0) return; @@ -514,7 +520,7 @@ void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state) old_crtc_state->dsc.compression_enable) val &= ~TRANSCONF_PIXEL_COUNT_SCALING_MASK; - intel_de_write(dev_priv, TRANSCONF(cpu_transcoder), val); + intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), val); if (DISPLAY_VER(dev_priv) >= 12) intel_de_rmw(dev_priv, hsw_chicken_trans_reg(dev_priv, cpu_transcoder), @@ -797,14 +803,14 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, const struct drm_connector_state *connector_state; const struct drm_connector *connector; struct intel_encoder *encoder = NULL; - struct intel_crtc *master_crtc; + struct intel_crtc *primary_crtc; int num_encoders = 0; int i; - master_crtc = intel_master_crtc(crtc_state); + primary_crtc = intel_primary_crtc(crtc_state); for_each_new_connector_in_state(&state->base, connector, connector_state, i) { - if (connector_state->crtc != &master_crtc->base) + if (connector_state->crtc != &primary_crtc->base) continue; encoder = to_intel_encoder(connector_state->best_encoder); @@ -813,7 +819,7 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, drm_WARN(state->base.dev, num_encoders != 1, "%d encoders for pipe %c\n", - num_encoders, pipe_name(master_crtc->pipe)); + num_encoders, pipe_name(primary_crtc->pipe)); return encoder; } @@ -1000,6 +1006,13 @@ static bool vrr_params_changed(const struct intel_crtc_state *old_crtc_state, old_crtc_state->vrr.pipeline_full != new_crtc_state->vrr.pipeline_full; } +static bool cmrr_params_changed(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) +{ + return old_crtc_state->cmrr.cmrr_m != new_crtc_state->cmrr.cmrr_m || + old_crtc_state->cmrr.cmrr_n != new_crtc_state->cmrr.cmrr_n; +} + static bool vrr_enabling(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state) { @@ -1140,7 +1153,7 @@ static void intel_crtc_async_flip_disable_wa(struct intel_atomic_state *state, int i; for_each_old_intel_plane_in_state(state, plane, old_plane_state, i) { - if (plane->need_async_flip_disable_wa && + if (plane->need_async_flip_toggle_wa && plane->pipe == crtc->pipe && disable_async_flip_planes & BIT(plane->id)) { /* @@ -1641,7 +1654,7 @@ static void hsw_configure_cpu_transcoder(const struct intel_crtc_state *crtc_sta intel_vrr_set_transcoder_timings(crtc_state); if (cpu_transcoder != TRANSCODER_EDP) - intel_de_write(dev_priv, TRANS_MULT(cpu_transcoder), + intel_de_write(dev_priv, TRANS_MULT(dev_priv, cpu_transcoder), crtc_state->pixel_multiplier - 1); hsw_set_frame_start_delay(crtc_state); @@ -1856,16 +1869,17 @@ static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) * according to register description and PRM. */ drm_WARN_ON(&dev_priv->drm, - intel_de_read(dev_priv, PFIT_CONTROL) & PFIT_ENABLE); + intel_de_read(dev_priv, PFIT_CONTROL(dev_priv)) & PFIT_ENABLE); assert_transcoder_disabled(dev_priv, crtc_state->cpu_transcoder); - intel_de_write(dev_priv, PFIT_PGM_RATIOS, + intel_de_write(dev_priv, PFIT_PGM_RATIOS(dev_priv), crtc_state->gmch_pfit.pgm_ratios); - intel_de_write(dev_priv, PFIT_CONTROL, crtc_state->gmch_pfit.control); + intel_de_write(dev_priv, PFIT_CONTROL(dev_priv), + crtc_state->gmch_pfit.control); /* Border color in case we don't scale up to the full screen. Black by * default, change to something else for debugging. */ - intel_de_write(dev_priv, BCLRPAT(crtc->pipe), 0); + intel_de_write(dev_priv, BCLRPAT(dev_priv, crtc->pipe), 0); } /* Prefer intel_encoder_is_combo() */ @@ -1894,11 +1908,10 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy) bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy) { /* - * DG2's "TC1", although TC-capable output, doesn't share the same flow - * as other platforms on the display engine side and rather rely on the - * SNPS PHY, that is programmed separately + * Discrete GPU phy's are not attached to FIA's to support TC + * subsystem Legacy or non-legacy, and only support native DP/HDMI */ - if (IS_DG2(dev_priv)) + if (IS_DGFX(dev_priv)) return false; if (DISPLAY_VER(dev_priv) >= 13) @@ -2102,8 +2115,9 @@ static void valleyview_crtc_enable(struct intel_atomic_state *state, intel_de_write(dev_priv, VLV_PIPE_MSA_MISC(pipe), 0); if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { - intel_de_write(dev_priv, CHV_BLEND(pipe), CHV_BLEND_LEGACY); - intel_de_write(dev_priv, CHV_CANVAS(pipe), 0); + intel_de_write(dev_priv, CHV_BLEND(dev_priv, pipe), + CHV_BLEND_LEGACY); + intel_de_write(dev_priv, CHV_CANVAS(dev_priv, pipe), 0); } crtc->active = true; @@ -2191,8 +2205,8 @@ static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state) assert_transcoder_disabled(dev_priv, old_crtc_state->cpu_transcoder); drm_dbg_kms(&dev_priv->drm, "disabling pfit, current: 0x%08x\n", - intel_de_read(dev_priv, PFIT_CONTROL)); - intel_de_write(dev_priv, PFIT_CONTROL, 0); + intel_de_read(dev_priv, PFIT_CONTROL(dev_priv))); + intel_de_write(dev_priv, PFIT_CONTROL(dev_priv), 0); } static void i9xx_crtc_disable(struct intel_atomic_state *state, @@ -2314,10 +2328,10 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) ilk_pipe_pixel_rate(crtc_state); } -static void intel_bigjoiner_adjust_timings(const struct intel_crtc_state *crtc_state, - struct drm_display_mode *mode) +static void intel_joiner_adjust_timings(const struct intel_crtc_state *crtc_state, + struct drm_display_mode *mode) { - int num_pipes = intel_bigjoiner_num_pipes(crtc_state); + int num_pipes = intel_joiner_num_pipes(crtc_state); if (num_pipes < 2) return; @@ -2381,11 +2395,11 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state drm_mode_copy(mode, pipe_mode); intel_mode_from_crtc_timings(mode, mode); mode->hdisplay = drm_rect_width(&crtc_state->pipe_src) * - (intel_bigjoiner_num_pipes(crtc_state) ?: 1); + (intel_joiner_num_pipes(crtc_state) ?: 1); mode->vdisplay = drm_rect_height(&crtc_state->pipe_src); - /* Derive per-pipe timings in case bigjoiner is used */ - intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); + /* Derive per-pipe timings in case joiner is used */ + intel_joiner_adjust_timings(crtc_state, pipe_mode); intel_mode_from_crtc_timings(pipe_mode, pipe_mode); intel_crtc_compute_pixel_rate(crtc_state); @@ -2399,9 +2413,9 @@ void intel_encoder_get_config(struct intel_encoder *encoder, intel_crtc_readout_derived_state(crtc_state); } -static void intel_bigjoiner_compute_pipe_src(struct intel_crtc_state *crtc_state) +static void intel_joiner_compute_pipe_src(struct intel_crtc_state *crtc_state) { - int num_pipes = intel_bigjoiner_num_pipes(crtc_state); + int num_pipes = intel_joiner_num_pipes(crtc_state); int width, height; if (num_pipes < 2) @@ -2419,7 +2433,7 @@ static int intel_crtc_compute_pipe_src(struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); - intel_bigjoiner_compute_pipe_src(crtc_state); + intel_joiner_compute_pipe_src(crtc_state); /* * Pipe horizontal size must be even in: @@ -2464,8 +2478,8 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state) /* Expand MSO per-segment transcoder timings to full */ intel_splitter_adjust_timings(crtc_state, pipe_mode); - /* Derive per-pipe timings in case bigjoiner is used */ - intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); + /* Derive per-pipe timings in case joiner is used */ + intel_joiner_adjust_timings(crtc_state, pipe_mode); intel_mode_from_crtc_timings(pipe_mode, pipe_mode); if (DISPLAY_VER(i915) < 4) { @@ -2634,8 +2648,10 @@ void intel_cpu_transcoder_set_m1_n1(struct intel_crtc *crtc, if (DISPLAY_VER(dev_priv) >= 5) intel_set_m_n(dev_priv, m_n, - PIPE_DATA_M1(transcoder), PIPE_DATA_N1(transcoder), - PIPE_LINK_M1(transcoder), PIPE_LINK_N1(transcoder)); + PIPE_DATA_M1(dev_priv, transcoder), + PIPE_DATA_N1(dev_priv, transcoder), + PIPE_LINK_M1(dev_priv, transcoder), + PIPE_LINK_N1(dev_priv, transcoder)); else intel_set_m_n(dev_priv, m_n, PIPE_DATA_M_G4X(pipe), PIPE_DATA_N_G4X(pipe), @@ -2652,8 +2668,10 @@ void intel_cpu_transcoder_set_m2_n2(struct intel_crtc *crtc, return; intel_set_m_n(dev_priv, m_n, - PIPE_DATA_M2(transcoder), PIPE_DATA_N2(transcoder), - PIPE_LINK_M2(transcoder), PIPE_LINK_N2(transcoder)); + PIPE_DATA_M2(dev_priv, transcoder), + PIPE_DATA_N2(dev_priv, transcoder), + PIPE_LINK_M2(dev_priv, transcoder), + PIPE_LINK_N2(dev_priv, transcoder)); } static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state) @@ -2692,7 +2710,8 @@ static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_sta * TRANS_SET_CONTEXT_LATENCY to configure the pipe vblank start. */ if (DISPLAY_VER(dev_priv) >= 13) { - intel_de_write(dev_priv, TRANS_SET_CONTEXT_LATENCY(cpu_transcoder), + intel_de_write(dev_priv, + TRANS_SET_CONTEXT_LATENCY(dev_priv, cpu_transcoder), crtc_vblank_start - crtc_vdisplay); /* @@ -2703,26 +2722,27 @@ static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_sta } if (DISPLAY_VER(dev_priv) >= 4) - intel_de_write(dev_priv, TRANS_VSYNCSHIFT(cpu_transcoder), + intel_de_write(dev_priv, + TRANS_VSYNCSHIFT(dev_priv, cpu_transcoder), vsyncshift); - intel_de_write(dev_priv, TRANS_HTOTAL(cpu_transcoder), + intel_de_write(dev_priv, TRANS_HTOTAL(dev_priv, cpu_transcoder), HACTIVE(adjusted_mode->crtc_hdisplay - 1) | HTOTAL(adjusted_mode->crtc_htotal - 1)); - intel_de_write(dev_priv, TRANS_HBLANK(cpu_transcoder), + intel_de_write(dev_priv, TRANS_HBLANK(dev_priv, cpu_transcoder), HBLANK_START(adjusted_mode->crtc_hblank_start - 1) | HBLANK_END(adjusted_mode->crtc_hblank_end - 1)); - intel_de_write(dev_priv, TRANS_HSYNC(cpu_transcoder), + intel_de_write(dev_priv, TRANS_HSYNC(dev_priv, cpu_transcoder), HSYNC_START(adjusted_mode->crtc_hsync_start - 1) | HSYNC_END(adjusted_mode->crtc_hsync_end - 1)); - intel_de_write(dev_priv, TRANS_VTOTAL(cpu_transcoder), + intel_de_write(dev_priv, TRANS_VTOTAL(dev_priv, cpu_transcoder), VACTIVE(crtc_vdisplay - 1) | VTOTAL(crtc_vtotal - 1)); - intel_de_write(dev_priv, TRANS_VBLANK(cpu_transcoder), + intel_de_write(dev_priv, TRANS_VBLANK(dev_priv, cpu_transcoder), VBLANK_START(crtc_vblank_start - 1) | VBLANK_END(crtc_vblank_end - 1)); - intel_de_write(dev_priv, TRANS_VSYNC(cpu_transcoder), + intel_de_write(dev_priv, TRANS_VSYNC(dev_priv, cpu_transcoder), VSYNC_START(adjusted_mode->crtc_vsync_start - 1) | VSYNC_END(adjusted_mode->crtc_vsync_end - 1)); @@ -2732,7 +2752,7 @@ static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_sta * bits. */ if (IS_HASWELL(dev_priv) && cpu_transcoder == TRANSCODER_EDP && (pipe == PIPE_B || pipe == PIPE_C)) - intel_de_write(dev_priv, TRANS_VTOTAL(pipe), + intel_de_write(dev_priv, TRANS_VTOTAL(dev_priv, pipe), VACTIVE(crtc_vdisplay - 1) | VTOTAL(crtc_vtotal - 1)); } @@ -2756,14 +2776,14 @@ static void intel_set_transcoder_timings_lrr(const struct intel_crtc_state *crtc * The hardware actually ignores TRANS_VBLANK.VBLANK_END in DP mode. * But let's write it anyway to keep the state checker happy. */ - intel_de_write(dev_priv, TRANS_VBLANK(cpu_transcoder), + intel_de_write(dev_priv, TRANS_VBLANK(dev_priv, cpu_transcoder), VBLANK_START(crtc_vblank_start - 1) | VBLANK_END(crtc_vblank_end - 1)); /* * The double buffer latch point for TRANS_VTOTAL * is the transcoder's undelayed vblank. */ - intel_de_write(dev_priv, TRANS_VTOTAL(cpu_transcoder), + intel_de_write(dev_priv, TRANS_VTOTAL(dev_priv, cpu_transcoder), VACTIVE(crtc_vdisplay - 1) | VTOTAL(crtc_vtotal - 1)); } @@ -2779,7 +2799,7 @@ static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state) /* pipesrc controls the size that is scaled from, which should * always be the user's requested size. */ - intel_de_write(dev_priv, PIPESRC(pipe), + intel_de_write(dev_priv, PIPESRC(dev_priv, pipe), PIPESRC_WIDTH(width - 1) | PIPESRC_HEIGHT(height - 1)); } @@ -2793,9 +2813,11 @@ static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state) if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) - return intel_de_read(dev_priv, TRANSCONF(cpu_transcoder)) & TRANSCONF_INTERLACE_MASK_HSW; + return intel_de_read(dev_priv, + TRANSCONF(dev_priv, cpu_transcoder)) & TRANSCONF_INTERLACE_MASK_HSW; else - return intel_de_read(dev_priv, TRANSCONF(cpu_transcoder)) & TRANSCONF_INTERLACE_MASK; + return intel_de_read(dev_priv, + TRANSCONF(dev_priv, cpu_transcoder)) & TRANSCONF_INTERLACE_MASK; } static void intel_get_transcoder_timings(struct intel_crtc *crtc, @@ -2807,31 +2829,33 @@ static void intel_get_transcoder_timings(struct intel_crtc *crtc, struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; u32 tmp; - tmp = intel_de_read(dev_priv, TRANS_HTOTAL(cpu_transcoder)); + tmp = intel_de_read(dev_priv, TRANS_HTOTAL(dev_priv, cpu_transcoder)); adjusted_mode->crtc_hdisplay = REG_FIELD_GET(HACTIVE_MASK, tmp) + 1; adjusted_mode->crtc_htotal = REG_FIELD_GET(HTOTAL_MASK, tmp) + 1; if (!transcoder_is_dsi(cpu_transcoder)) { - tmp = intel_de_read(dev_priv, TRANS_HBLANK(cpu_transcoder)); + tmp = intel_de_read(dev_priv, + TRANS_HBLANK(dev_priv, cpu_transcoder)); adjusted_mode->crtc_hblank_start = REG_FIELD_GET(HBLANK_START_MASK, tmp) + 1; adjusted_mode->crtc_hblank_end = REG_FIELD_GET(HBLANK_END_MASK, tmp) + 1; } - tmp = intel_de_read(dev_priv, TRANS_HSYNC(cpu_transcoder)); + tmp = intel_de_read(dev_priv, TRANS_HSYNC(dev_priv, cpu_transcoder)); adjusted_mode->crtc_hsync_start = REG_FIELD_GET(HSYNC_START_MASK, tmp) + 1; adjusted_mode->crtc_hsync_end = REG_FIELD_GET(HSYNC_END_MASK, tmp) + 1; - tmp = intel_de_read(dev_priv, TRANS_VTOTAL(cpu_transcoder)); + tmp = intel_de_read(dev_priv, TRANS_VTOTAL(dev_priv, cpu_transcoder)); adjusted_mode->crtc_vdisplay = REG_FIELD_GET(VACTIVE_MASK, tmp) + 1; adjusted_mode->crtc_vtotal = REG_FIELD_GET(VTOTAL_MASK, tmp) + 1; /* FIXME TGL+ DSI transcoders have this! */ if (!transcoder_is_dsi(cpu_transcoder)) { - tmp = intel_de_read(dev_priv, TRANS_VBLANK(cpu_transcoder)); + tmp = intel_de_read(dev_priv, + TRANS_VBLANK(dev_priv, cpu_transcoder)); adjusted_mode->crtc_vblank_start = REG_FIELD_GET(VBLANK_START_MASK, tmp) + 1; adjusted_mode->crtc_vblank_end = REG_FIELD_GET(VBLANK_END_MASK, tmp) + 1; } - tmp = intel_de_read(dev_priv, TRANS_VSYNC(cpu_transcoder)); + tmp = intel_de_read(dev_priv, TRANS_VSYNC(dev_priv, cpu_transcoder)); adjusted_mode->crtc_vsync_start = REG_FIELD_GET(VSYNC_START_MASK, tmp) + 1; adjusted_mode->crtc_vsync_end = REG_FIELD_GET(VSYNC_END_MASK, tmp) + 1; @@ -2844,24 +2868,25 @@ static void intel_get_transcoder_timings(struct intel_crtc *crtc, if (DISPLAY_VER(dev_priv) >= 13 && !transcoder_is_dsi(cpu_transcoder)) adjusted_mode->crtc_vblank_start = adjusted_mode->crtc_vdisplay + - intel_de_read(dev_priv, TRANS_SET_CONTEXT_LATENCY(cpu_transcoder)); + intel_de_read(dev_priv, + TRANS_SET_CONTEXT_LATENCY(dev_priv, cpu_transcoder)); } -static void intel_bigjoiner_adjust_pipe_src(struct intel_crtc_state *crtc_state) +static void intel_joiner_adjust_pipe_src(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - int num_pipes = intel_bigjoiner_num_pipes(crtc_state); - enum pipe master_pipe, pipe = crtc->pipe; + int num_pipes = intel_joiner_num_pipes(crtc_state); + enum pipe primary_pipe, pipe = crtc->pipe; int width; if (num_pipes < 2) return; - master_pipe = bigjoiner_master_pipe(crtc_state); + primary_pipe = joiner_primary_pipe(crtc_state); width = drm_rect_width(&crtc_state->pipe_src); drm_rect_translate_to(&crtc_state->pipe_src, - (pipe - master_pipe) * width, 0); + (pipe - primary_pipe) * width, 0); } static void intel_get_pipe_src_size(struct intel_crtc *crtc, @@ -2871,13 +2896,13 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = to_i915(dev); u32 tmp; - tmp = intel_de_read(dev_priv, PIPESRC(crtc->pipe)); + tmp = intel_de_read(dev_priv, PIPESRC(dev_priv, crtc->pipe)); drm_rect_init(&pipe_config->pipe_src, 0, 0, REG_FIELD_GET(PIPESRC_WIDTH_MASK, tmp) + 1, REG_FIELD_GET(PIPESRC_HEIGHT_MASK, tmp) + 1); - intel_bigjoiner_adjust_pipe_src(pipe_config); + intel_joiner_adjust_pipe_src(pipe_config); } void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) @@ -2944,8 +2969,8 @@ void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) val |= TRANSCONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1); - intel_de_write(dev_priv, TRANSCONF(cpu_transcoder), val); - intel_de_posting_read(dev_priv, TRANSCONF(cpu_transcoder)); + intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), val); + intel_de_posting_read(dev_priv, TRANSCONF(dev_priv, cpu_transcoder)); } static bool i9xx_has_pfit(struct drm_i915_private *dev_priv) @@ -2967,7 +2992,7 @@ static void i9xx_get_pfit_config(struct intel_crtc_state *crtc_state) if (!i9xx_has_pfit(dev_priv)) return; - tmp = intel_de_read(dev_priv, PFIT_CONTROL); + tmp = intel_de_read(dev_priv, PFIT_CONTROL(dev_priv)); if (!(tmp & PFIT_ENABLE)) return; @@ -2982,7 +3007,7 @@ static void i9xx_get_pfit_config(struct intel_crtc_state *crtc_state) crtc_state->gmch_pfit.control = tmp; crtc_state->gmch_pfit.pgm_ratios = - intel_de_read(dev_priv, PFIT_PGM_RATIOS); + intel_de_read(dev_priv, PFIT_PGM_RATIOS(dev_priv)); } static enum intel_output_format @@ -3027,7 +3052,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, ret = false; - tmp = intel_de_read(dev_priv, TRANSCONF(pipe_config->cpu_transcoder)); + tmp = intel_de_read(dev_priv, + TRANSCONF(dev_priv, pipe_config->cpu_transcoder)); if (!(tmp & TRANSCONF_ENABLE)) goto out; @@ -3174,8 +3200,8 @@ void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state) val |= TRANSCONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1); val |= TRANSCONF_MSA_TIMING_DELAY(crtc_state->msa_timing_delay); - intel_de_write(dev_priv, TRANSCONF(cpu_transcoder), val); - intel_de_posting_read(dev_priv, TRANSCONF(cpu_transcoder)); + intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), val); + intel_de_posting_read(dev_priv, TRANSCONF(dev_priv, cpu_transcoder)); } static void hsw_set_transconf(const struct intel_crtc_state *crtc_state) @@ -3204,8 +3230,8 @@ static void hsw_set_transconf(const struct intel_crtc_state *crtc_state) crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) val |= TRANSCONF_OUTPUT_COLORSPACE_YUV_HSW; - intel_de_write(dev_priv, TRANSCONF(cpu_transcoder), val); - intel_de_posting_read(dev_priv, TRANSCONF(cpu_transcoder)); + intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), val); + intel_de_posting_read(dev_priv, TRANSCONF(dev_priv, cpu_transcoder)); } static void bdw_set_pipe_misc(const struct intel_crtc_state *crtc_state) @@ -3324,8 +3350,10 @@ void intel_cpu_transcoder_get_m1_n1(struct intel_crtc *crtc, if (DISPLAY_VER(dev_priv) >= 5) intel_get_m_n(dev_priv, m_n, - PIPE_DATA_M1(transcoder), PIPE_DATA_N1(transcoder), - PIPE_LINK_M1(transcoder), PIPE_LINK_N1(transcoder)); + PIPE_DATA_M1(dev_priv, transcoder), + PIPE_DATA_N1(dev_priv, transcoder), + PIPE_LINK_M1(dev_priv, transcoder), + PIPE_LINK_N1(dev_priv, transcoder)); else intel_get_m_n(dev_priv, m_n, PIPE_DATA_M_G4X(pipe), PIPE_DATA_N_G4X(pipe), @@ -3342,8 +3370,10 @@ void intel_cpu_transcoder_get_m2_n2(struct intel_crtc *crtc, return; intel_get_m_n(dev_priv, m_n, - PIPE_DATA_M2(transcoder), PIPE_DATA_N2(transcoder), - PIPE_LINK_M2(transcoder), PIPE_LINK_N2(transcoder)); + PIPE_DATA_M2(dev_priv, transcoder), + PIPE_DATA_N2(dev_priv, transcoder), + PIPE_LINK_M2(dev_priv, transcoder), + PIPE_LINK_N2(dev_priv, transcoder)); } static void ilk_get_pfit_config(struct intel_crtc_state *crtc_state) @@ -3400,7 +3430,8 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc, pipe_config->shared_dpll = NULL; ret = false; - tmp = intel_de_read(dev_priv, TRANSCONF(pipe_config->cpu_transcoder)); + tmp = intel_de_read(dev_priv, + TRANSCONF(dev_priv, pipe_config->cpu_transcoder)); if (!(tmp & TRANSCONF_ENABLE)) goto out; @@ -3461,7 +3492,7 @@ out: return ret; } -static u8 bigjoiner_pipes(struct drm_i915_private *i915) +static u8 joiner_pipes(struct drm_i915_private *i915) { u8 pipes; @@ -3485,21 +3516,22 @@ static bool transcoder_ddi_func_is_enabled(struct drm_i915_private *dev_priv, power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) - tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); + tmp = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)); return tmp & TRANS_DDI_FUNC_ENABLE; } -static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv, - u8 *master_pipes, u8 *slave_pipes) +static void enabled_joiner_pipes(struct drm_i915_private *dev_priv, + u8 *primary_pipes, u8 *secondary_pipes) { struct intel_crtc *crtc; - *master_pipes = 0; - *slave_pipes = 0; + *primary_pipes = 0; + *secondary_pipes = 0; for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc, - bigjoiner_pipes(dev_priv)) { + joiner_pipes(dev_priv)) { enum intel_display_power_domain power_domain; enum pipe pipe = crtc->pipe; intel_wakeref_t wakeref; @@ -3511,10 +3543,10 @@ static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv, if (!(tmp & BIG_JOINER_ENABLE)) continue; - if (tmp & MASTER_BIG_JOINER_ENABLE) - *master_pipes |= BIT(pipe); + if (tmp & PRIMARY_BIG_JOINER_ENABLE) + *primary_pipes |= BIT(pipe); else - *slave_pipes |= BIT(pipe); + *secondary_pipes |= BIT(pipe); } if (DISPLAY_VER(dev_priv) < 13) @@ -3524,48 +3556,48 @@ static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv, with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) { u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe)); - if (tmp & UNCOMPRESSED_JOINER_MASTER) - *master_pipes |= BIT(pipe); - if (tmp & UNCOMPRESSED_JOINER_SLAVE) - *slave_pipes |= BIT(pipe); + if (tmp & UNCOMPRESSED_JOINER_PRIMARY) + *primary_pipes |= BIT(pipe); + if (tmp & UNCOMPRESSED_JOINER_SECONDARY) + *secondary_pipes |= BIT(pipe); } } - /* Bigjoiner pipes should always be consecutive master and slave */ - drm_WARN(&dev_priv->drm, *slave_pipes != *master_pipes << 1, - "Bigjoiner misconfigured (master pipes 0x%x, slave pipes 0x%x)\n", - *master_pipes, *slave_pipes); + /* Joiner pipes should always be consecutive primary and secondary */ + drm_WARN(&dev_priv->drm, *secondary_pipes != *primary_pipes << 1, + "Joiner misconfigured (primary pipes 0x%x, secondary pipes 0x%x)\n", + *primary_pipes, *secondary_pipes); } -static enum pipe get_bigjoiner_master_pipe(enum pipe pipe, u8 master_pipes, u8 slave_pipes) +static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes, u8 secondary_pipes) { - if ((slave_pipes & BIT(pipe)) == 0) + if ((secondary_pipes & BIT(pipe)) == 0) return pipe; /* ignore everything above our pipe */ - master_pipes &= ~GENMASK(7, pipe); + primary_pipes &= ~GENMASK(7, pipe); - /* highest remaining bit should be our master pipe */ - return fls(master_pipes) - 1; + /* highest remaining bit should be our primary pipe */ + return fls(primary_pipes) - 1; } -static u8 get_bigjoiner_slave_pipes(enum pipe pipe, u8 master_pipes, u8 slave_pipes) +static u8 get_joiner_secondary_pipes(enum pipe pipe, u8 primary_pipes, u8 secondary_pipes) { - enum pipe master_pipe, next_master_pipe; + enum pipe primary_pipe, next_primary_pipe; - master_pipe = get_bigjoiner_master_pipe(pipe, master_pipes, slave_pipes); + primary_pipe = get_joiner_primary_pipe(pipe, primary_pipes, secondary_pipes); - if ((master_pipes & BIT(master_pipe)) == 0) + if ((primary_pipes & BIT(primary_pipe)) == 0) return 0; - /* ignore our master pipe and everything below it */ - master_pipes &= ~GENMASK(master_pipe, 0); + /* ignore our primary pipe and everything below it */ + primary_pipes &= ~GENMASK(primary_pipe, 0); /* make sure a high bit is set for the ffs() */ - master_pipes |= BIT(7); - /* lowest remaining bit should be the next master pipe */ - next_master_pipe = ffs(master_pipes) - 1; + primary_pipes |= BIT(7); + /* lowest remaining bit should be the next primary pipe */ + next_primary_pipe = ffs(primary_pipes) - 1; - return slave_pipes & GENMASK(next_master_pipe - 1, master_pipe); + return secondary_pipes & GENMASK(next_primary_pipe - 1, primary_pipe); } static u8 hsw_panel_transcoders(struct drm_i915_private *i915) @@ -3584,7 +3616,7 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = to_i915(dev); u8 panel_transcoder_mask = hsw_panel_transcoders(dev_priv); enum transcoder cpu_transcoder; - u8 master_pipes, slave_pipes; + u8 primary_pipes, secondary_pipes; u8 enabled_transcoders = 0; /* @@ -3600,7 +3632,8 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc) power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) - tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); + tmp = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)); if (!(tmp & TRANS_DDI_FUNC_ENABLE)) continue; @@ -3630,16 +3663,16 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc) enabled_transcoders |= BIT(cpu_transcoder); } - /* single pipe or bigjoiner master */ + /* single pipe or joiner primary */ cpu_transcoder = (enum transcoder) crtc->pipe; if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder)) enabled_transcoders |= BIT(cpu_transcoder); - /* bigjoiner slave -> consider the master pipe's transcoder as well */ - enabled_bigjoiner_pipes(dev_priv, &master_pipes, &slave_pipes); - if (slave_pipes & BIT(crtc->pipe)) { + /* joiner secondary -> consider the primary pipe's transcoder as well */ + enabled_joiner_pipes(dev_priv, &primary_pipes, &secondary_pipes); + if (secondary_pipes & BIT(crtc->pipe)) { cpu_transcoder = (enum transcoder) - get_bigjoiner_master_pipe(crtc->pipe, master_pipes, slave_pipes); + get_joiner_primary_pipe(crtc->pipe, primary_pipes, secondary_pipes); if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder)) enabled_transcoders |= BIT(cpu_transcoder); } @@ -3707,13 +3740,15 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, return false; if (hsw_panel_transcoders(dev_priv) & BIT(pipe_config->cpu_transcoder)) { - tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder)); + tmp = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, pipe_config->cpu_transcoder)); if ((tmp & TRANS_DDI_EDP_INPUT_MASK) == TRANS_DDI_EDP_INPUT_A_ONOFF) pipe_config->pch_pfit.force_thru = true; } - tmp = intel_de_read(dev_priv, TRANSCONF(pipe_config->cpu_transcoder)); + tmp = intel_de_read(dev_priv, + TRANSCONF(dev_priv, pipe_config->cpu_transcoder)); return tmp & TRANSCONF_ENABLE; } @@ -3764,21 +3799,21 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc, return transcoder_is_dsi(pipe_config->cpu_transcoder); } -static void intel_bigjoiner_get_config(struct intel_crtc_state *crtc_state) +static void intel_joiner_get_config(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); - u8 master_pipes, slave_pipes; + u8 primary_pipes, secondary_pipes; enum pipe pipe = crtc->pipe; - enabled_bigjoiner_pipes(i915, &master_pipes, &slave_pipes); + enabled_joiner_pipes(i915, &primary_pipes, &secondary_pipes); - if (((master_pipes | slave_pipes) & BIT(pipe)) == 0) + if (((primary_pipes | secondary_pipes) & BIT(pipe)) == 0) return; - crtc_state->bigjoiner_pipes = - BIT(get_bigjoiner_master_pipe(pipe, master_pipes, slave_pipes)) | - get_bigjoiner_slave_pipes(pipe, master_pipes, slave_pipes); + crtc_state->joiner_pipes = + BIT(get_joiner_primary_pipe(pipe, primary_pipes, secondary_pipes)) | + get_joiner_secondary_pipes(pipe, primary_pipes, secondary_pipes); } static bool hsw_get_pipe_config(struct intel_crtc *crtc, @@ -3805,7 +3840,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, if (!active) goto out; - intel_bigjoiner_get_config(pipe_config); + intel_joiner_get_config(pipe_config); intel_dsc_get_config(pipe_config); if (!transcoder_is_dsi(pipe_config->cpu_transcoder) || @@ -3819,7 +3854,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, if (IS_HASWELL(dev_priv)) { u32 tmp = intel_de_read(dev_priv, - TRANSCONF(pipe_config->cpu_transcoder)); + TRANSCONF(dev_priv, pipe_config->cpu_transcoder)); if (tmp & TRANSCONF_OUTPUT_COLORSPACE_YUV_HSW) pipe_config->output_format = INTEL_OUTPUT_FORMAT_YCBCR444; @@ -3854,7 +3889,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, !transcoder_is_dsi(pipe_config->cpu_transcoder)) { pipe_config->pixel_multiplier = intel_de_read(dev_priv, - TRANS_MULT(pipe_config->cpu_transcoder)) + 1; + TRANS_MULT(dev_priv, pipe_config->cpu_transcoder)) + 1; } else { pipe_config->pixel_multiplier = 1; } @@ -4030,11 +4065,12 @@ static int icl_add_linked_planes(struct intel_atomic_state *state) return 0; } -static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) +static int icl_check_nv12_planes(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct intel_plane *plane, *linked; struct intel_plane_state *plane_state; int i; @@ -4119,13 +4155,13 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) linked_state->uapi.dst = plane_state->uapi.dst; if (icl_is_hdr_plane(dev_priv, plane->id)) { - if (linked->id == PLANE_SPRITE5) + if (linked->id == PLANE_7) plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_7_ICL; - else if (linked->id == PLANE_SPRITE4) + else if (linked->id == PLANE_6) plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_6_ICL; - else if (linked->id == PLANE_SPRITE3) + else if (linked->id == PLANE_5) plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_5_RKL; - else if (linked->id == PLANE_SPRITE2) + else if (linked->id == PLANE_4) plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_4_RKL; else MISSING_CASE(linked->id); @@ -4135,17 +4171,6 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) return 0; } -static bool c8_planes_changed(const struct intel_crtc_state *new_crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct intel_atomic_state *state = - to_intel_atomic_state(new_crtc_state->uapi.state); - const struct intel_crtc_state *old_crtc_state = - intel_atomic_get_old_crtc_state(state, crtc); - - return !old_crtc_state->c8_planes != !new_crtc_state->c8_planes; -} - static u16 hsw_linetime_wm(const struct intel_crtc_state *crtc_state) { const struct drm_display_mode *pipe_mode = @@ -4244,18 +4269,9 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, return ret; } - /* - * May need to update pipe gamma enable bits - * when C8 planes are getting enabled/disabled. - */ - if (c8_planes_changed(crtc_state)) - crtc_state->uapi.color_mgmt_changed = true; - - if (intel_crtc_needs_color_update(crtc_state)) { - ret = intel_color_check(crtc_state); - if (ret) - return ret; - } + ret = intel_color_check(state, crtc); + if (ret) + return ret; ret = intel_compute_pipe_wm(state, crtc); if (ret) { @@ -4464,7 +4480,7 @@ intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state)); + WARN_ON(intel_crtc_is_joiner_secondary(crtc_state)); drm_property_replace_blob(&crtc_state->hw.degamma_lut, crtc_state->uapi.degamma_lut); @@ -4481,7 +4497,7 @@ intel_crtc_copy_uapi_to_hw_state_modeset(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state)); + WARN_ON(intel_crtc_is_joiner_secondary(crtc_state)); crtc_state->hw.enable = crtc_state->uapi.enable; crtc_state->hw.active = crtc_state->uapi.active; @@ -4495,79 +4511,79 @@ intel_crtc_copy_uapi_to_hw_state_modeset(struct intel_atomic_state *state, } static void -copy_bigjoiner_crtc_state_nomodeset(struct intel_atomic_state *state, - struct intel_crtc *slave_crtc) +copy_joiner_crtc_state_nomodeset(struct intel_atomic_state *state, + struct intel_crtc *secondary_crtc) { - struct intel_crtc_state *slave_crtc_state = - intel_atomic_get_new_crtc_state(state, slave_crtc); - struct intel_crtc *master_crtc = intel_master_crtc(slave_crtc_state); - const struct intel_crtc_state *master_crtc_state = - intel_atomic_get_new_crtc_state(state, master_crtc); + struct intel_crtc_state *secondary_crtc_state = + intel_atomic_get_new_crtc_state(state, secondary_crtc); + struct intel_crtc *primary_crtc = intel_primary_crtc(secondary_crtc_state); + const struct intel_crtc_state *primary_crtc_state = + intel_atomic_get_new_crtc_state(state, primary_crtc); - drm_property_replace_blob(&slave_crtc_state->hw.degamma_lut, - master_crtc_state->hw.degamma_lut); - drm_property_replace_blob(&slave_crtc_state->hw.gamma_lut, - master_crtc_state->hw.gamma_lut); - drm_property_replace_blob(&slave_crtc_state->hw.ctm, - master_crtc_state->hw.ctm); + drm_property_replace_blob(&secondary_crtc_state->hw.degamma_lut, + primary_crtc_state->hw.degamma_lut); + drm_property_replace_blob(&secondary_crtc_state->hw.gamma_lut, + primary_crtc_state->hw.gamma_lut); + drm_property_replace_blob(&secondary_crtc_state->hw.ctm, + primary_crtc_state->hw.ctm); - slave_crtc_state->uapi.color_mgmt_changed = master_crtc_state->uapi.color_mgmt_changed; + secondary_crtc_state->uapi.color_mgmt_changed = primary_crtc_state->uapi.color_mgmt_changed; } static int -copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state, - struct intel_crtc *slave_crtc) -{ - struct intel_crtc_state *slave_crtc_state = - intel_atomic_get_new_crtc_state(state, slave_crtc); - struct intel_crtc *master_crtc = intel_master_crtc(slave_crtc_state); - const struct intel_crtc_state *master_crtc_state = - intel_atomic_get_new_crtc_state(state, master_crtc); +copy_joiner_crtc_state_modeset(struct intel_atomic_state *state, + struct intel_crtc *secondary_crtc) +{ + struct intel_crtc_state *secondary_crtc_state = + intel_atomic_get_new_crtc_state(state, secondary_crtc); + struct intel_crtc *primary_crtc = intel_primary_crtc(secondary_crtc_state); + const struct intel_crtc_state *primary_crtc_state = + intel_atomic_get_new_crtc_state(state, primary_crtc); struct intel_crtc_state *saved_state; - WARN_ON(master_crtc_state->bigjoiner_pipes != - slave_crtc_state->bigjoiner_pipes); + WARN_ON(primary_crtc_state->joiner_pipes != + secondary_crtc_state->joiner_pipes); - saved_state = kmemdup(master_crtc_state, sizeof(*saved_state), GFP_KERNEL); + saved_state = kmemdup(primary_crtc_state, sizeof(*saved_state), GFP_KERNEL); if (!saved_state) return -ENOMEM; /* preserve some things from the slave's original crtc state */ - saved_state->uapi = slave_crtc_state->uapi; - saved_state->scaler_state = slave_crtc_state->scaler_state; - saved_state->shared_dpll = slave_crtc_state->shared_dpll; - saved_state->crc_enabled = slave_crtc_state->crc_enabled; - - intel_crtc_free_hw_state(slave_crtc_state); - if (slave_crtc_state->dp_tunnel_ref.tunnel) - drm_dp_tunnel_ref_put(&slave_crtc_state->dp_tunnel_ref); - memcpy(slave_crtc_state, saved_state, sizeof(*slave_crtc_state)); + saved_state->uapi = secondary_crtc_state->uapi; + saved_state->scaler_state = secondary_crtc_state->scaler_state; + saved_state->shared_dpll = secondary_crtc_state->shared_dpll; + saved_state->crc_enabled = secondary_crtc_state->crc_enabled; + + intel_crtc_free_hw_state(secondary_crtc_state); + if (secondary_crtc_state->dp_tunnel_ref.tunnel) + drm_dp_tunnel_ref_put(&secondary_crtc_state->dp_tunnel_ref); + memcpy(secondary_crtc_state, saved_state, sizeof(*secondary_crtc_state)); kfree(saved_state); /* Re-init hw state */ - memset(&slave_crtc_state->hw, 0, sizeof(slave_crtc_state->hw)); - slave_crtc_state->hw.enable = master_crtc_state->hw.enable; - slave_crtc_state->hw.active = master_crtc_state->hw.active; - drm_mode_copy(&slave_crtc_state->hw.mode, - &master_crtc_state->hw.mode); - drm_mode_copy(&slave_crtc_state->hw.pipe_mode, - &master_crtc_state->hw.pipe_mode); - drm_mode_copy(&slave_crtc_state->hw.adjusted_mode, - &master_crtc_state->hw.adjusted_mode); - slave_crtc_state->hw.scaling_filter = master_crtc_state->hw.scaling_filter; - - if (master_crtc_state->dp_tunnel_ref.tunnel) - drm_dp_tunnel_ref_get(master_crtc_state->dp_tunnel_ref.tunnel, - &slave_crtc_state->dp_tunnel_ref); - - copy_bigjoiner_crtc_state_nomodeset(state, slave_crtc); - - slave_crtc_state->uapi.mode_changed = master_crtc_state->uapi.mode_changed; - slave_crtc_state->uapi.connectors_changed = master_crtc_state->uapi.connectors_changed; - slave_crtc_state->uapi.active_changed = master_crtc_state->uapi.active_changed; - - WARN_ON(master_crtc_state->bigjoiner_pipes != - slave_crtc_state->bigjoiner_pipes); + memset(&secondary_crtc_state->hw, 0, sizeof(secondary_crtc_state->hw)); + secondary_crtc_state->hw.enable = primary_crtc_state->hw.enable; + secondary_crtc_state->hw.active = primary_crtc_state->hw.active; + drm_mode_copy(&secondary_crtc_state->hw.mode, + &primary_crtc_state->hw.mode); + drm_mode_copy(&secondary_crtc_state->hw.pipe_mode, + &primary_crtc_state->hw.pipe_mode); + drm_mode_copy(&secondary_crtc_state->hw.adjusted_mode, + &primary_crtc_state->hw.adjusted_mode); + secondary_crtc_state->hw.scaling_filter = primary_crtc_state->hw.scaling_filter; + + if (primary_crtc_state->dp_tunnel_ref.tunnel) + drm_dp_tunnel_ref_get(primary_crtc_state->dp_tunnel_ref.tunnel, + &secondary_crtc_state->dp_tunnel_ref); + + copy_joiner_crtc_state_nomodeset(state, secondary_crtc); + + secondary_crtc_state->uapi.mode_changed = primary_crtc_state->uapi.mode_changed; + secondary_crtc_state->uapi.connectors_changed = primary_crtc_state->uapi.connectors_changed; + secondary_crtc_state->uapi.active_changed = primary_crtc_state->uapi.active_changed; + + WARN_ON(primary_crtc_state->joiner_pipes != + secondary_crtc_state->joiner_pipes); return 0; } @@ -5000,6 +5016,24 @@ pipe_config_pll_mismatch(struct drm_printer *p, bool fastset, intel_dpll_dump_hw_state(i915, p, b); } +static void +pipe_config_cx0pll_mismatch(struct drm_printer *p, bool fastset, + const struct intel_crtc *crtc, + const char *name, + const struct intel_cx0pll_state *a, + const struct intel_cx0pll_state *b) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + char *chipname = a->use_c10 ? "C10" : "C20"; + + pipe_config_mismatch(p, fastset, crtc, name, chipname); + + drm_printf(p, "expected:\n"); + intel_cx0pll_dump_hw_state(i915, a); + drm_printf(p, "found:\n"); + intel_cx0pll_dump_hw_state(i915, b); +} + bool intel_pipe_config_compare(const struct intel_crtc_state *current_config, const struct intel_crtc_state *pipe_config, @@ -5051,6 +5085,16 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) +#define PIPE_CONF_CHECK_LLI(name) do { \ + if (current_config->name != pipe_config->name) { \ + pipe_config_mismatch(&p, fastset, crtc, __stringify(name), \ + "(expected %lli, found %lli)", \ + current_config->name, \ + pipe_config->name); \ + ret = false; \ + } \ +} while (0) + #define PIPE_CONF_CHECK_BOOL(name) do { \ if (current_config->name != pipe_config->name) { \ BUILD_BUG_ON_MSG(!__same_type(current_config->name, bool), \ @@ -5103,6 +5147,16 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) +#define PIPE_CONF_CHECK_PLL_CX0(name) do { \ + if (!intel_cx0pll_compare_hw_state(¤t_config->name, \ + &pipe_config->name)) { \ + pipe_config_cx0pll_mismatch(&p, fastset, crtc, __stringify(name), \ + ¤t_config->name, \ + &pipe_config->name); \ + ret = false; \ + } \ +} while (0) + #define PIPE_CONF_CHECK_TIMINGS(name) do { \ PIPE_CONF_CHECK_I(name.crtc_hdisplay); \ PIPE_CONF_CHECK_I(name.crtc_htotal); \ @@ -5318,9 +5372,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, * Panel replay has to be enabled before link training. PSR doesn't have * this requirement -> check these only if using panel replay */ - if (current_config->has_panel_replay || pipe_config->has_panel_replay) { + if (current_config->active_planes && + (current_config->has_panel_replay || + pipe_config->has_panel_replay)) { PIPE_CONF_CHECK_BOOL(has_psr); - PIPE_CONF_CHECK_BOOL(has_psr2); + PIPE_CONF_CHECK_BOOL(has_sel_update); PIPE_CONF_CHECK_BOOL(enable_psr2_sel_fetch); PIPE_CONF_CHECK_BOOL(enable_psr2_su_region_et); PIPE_CONF_CHECK_BOOL(has_panel_replay); @@ -5335,6 +5391,10 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if (dev_priv->display.dpll.mgr || HAS_GMCH(dev_priv)) PIPE_CONF_CHECK_PLL(dpll_hw_state); + /* FIXME convert MTL+ platforms over to dpll_mgr */ + if (DISPLAY_VER(dev_priv) >= 14) + PIPE_CONF_CHECK_PLL_CX0(dpll_hw_state.cx0pll); + PIPE_CONF_CHECK_X(dsi_pll.ctrl); PIPE_CONF_CHECK_X(dsi_pll.div); @@ -5365,7 +5425,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(sync_mode_slaves_mask); PIPE_CONF_CHECK_I(master_transcoder); - PIPE_CONF_CHECK_X(bigjoiner_pipes); + PIPE_CONF_CHECK_X(joiner_pipes); PIPE_CONF_CHECK_BOOL(dsc.config.block_pred_enable); PIPE_CONF_CHECK_BOOL(dsc.config.convert_rgb); @@ -5415,10 +5475,14 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(vrr.guardband); PIPE_CONF_CHECK_I(vrr.vsync_start); PIPE_CONF_CHECK_I(vrr.vsync_end); + PIPE_CONF_CHECK_LLI(cmrr.cmrr_m); + PIPE_CONF_CHECK_LLI(cmrr.cmrr_n); + PIPE_CONF_CHECK_BOOL(cmrr.enable); } #undef PIPE_CONF_CHECK_X #undef PIPE_CONF_CHECK_I +#undef PIPE_CONF_CHECK_LLI #undef PIPE_CONF_CHECK_BOOL #undef PIPE_CONF_CHECK_P #undef PIPE_CONF_CHECK_FLAGS @@ -5567,6 +5631,40 @@ int intel_modeset_all_pipes_late(struct intel_atomic_state *state, return 0; } +int intel_modeset_commit_pipes(struct drm_i915_private *i915, + u8 pipe_mask, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_atomic_state *state; + struct intel_crtc *crtc; + int ret; + + state = drm_atomic_state_alloc(&i915->drm); + if (!state) + return -ENOMEM; + + state->acquire_ctx = ctx; + to_intel_atomic_state(state)->internal = true; + + for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_crtc_state(state, crtc); + + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto out; + } + + crtc_state->uapi.connectors_changed = true; + } + + ret = drm_atomic_commit(state); +out: + drm_atomic_state_put(state); + + return ret; +} + /* * This implements the workaround described in the "notes" section of the mode * set sequence documentation. When going from no pipes or single pipe to @@ -5729,9 +5827,9 @@ static bool active_planes_affects_min_cdclk(struct drm_i915_private *dev_priv) IS_IVYBRIDGE(dev_priv); } -static int intel_crtc_add_bigjoiner_planes(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_crtc *other) +static int intel_crtc_add_joiner_planes(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_crtc *other) { const struct intel_plane_state __maybe_unused *plane_state; struct intel_plane *plane; @@ -5746,7 +5844,7 @@ static int intel_crtc_add_bigjoiner_planes(struct intel_atomic_state *state, return intel_crtc_add_planes_to_state(state, other, plane_ids); } -static int intel_bigjoiner_add_affected_planes(struct intel_atomic_state *state) +static int intel_joiner_add_affected_planes(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_crtc_state *crtc_state; @@ -5757,13 +5855,13 @@ static int intel_bigjoiner_add_affected_planes(struct intel_atomic_state *state) struct intel_crtc *other; for_each_intel_crtc_in_pipe_mask(&i915->drm, other, - crtc_state->bigjoiner_pipes) { + crtc_state->joiner_pipes) { int ret; if (crtc == other) continue; - ret = intel_crtc_add_bigjoiner_planes(state, crtc, other); + ret = intel_crtc_add_joiner_planes(state, crtc, other); if (ret) return ret; } @@ -5785,7 +5883,7 @@ static int intel_atomic_check_planes(struct intel_atomic_state *state) if (ret) return ret; - ret = intel_bigjoiner_add_affected_planes(state); + ret = intel_joiner_add_affected_planes(state); if (ret) return ret; @@ -5803,7 +5901,7 @@ static int intel_atomic_check_planes(struct intel_atomic_state *state) new_crtc_state, i) { u8 old_active_planes, new_active_planes; - ret = icl_check_nv12_planes(new_crtc_state); + ret = icl_check_nv12_planes(state, crtc); if (ret) return ret; @@ -5885,70 +5983,70 @@ static bool intel_pipes_need_modeset(struct intel_atomic_state *state, return false; } -static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state, - struct intel_crtc *master_crtc) +static int intel_atomic_check_joiner(struct intel_atomic_state *state, + struct intel_crtc *primary_crtc) { struct drm_i915_private *i915 = to_i915(state->base.dev); - struct intel_crtc_state *master_crtc_state = - intel_atomic_get_new_crtc_state(state, master_crtc); - struct intel_crtc *slave_crtc; + struct intel_crtc_state *primary_crtc_state = + intel_atomic_get_new_crtc_state(state, primary_crtc); + struct intel_crtc *secondary_crtc; - if (!master_crtc_state->bigjoiner_pipes) + if (!primary_crtc_state->joiner_pipes) return 0; /* sanity check */ if (drm_WARN_ON(&i915->drm, - master_crtc->pipe != bigjoiner_master_pipe(master_crtc_state))) + primary_crtc->pipe != joiner_primary_pipe(primary_crtc_state))) return -EINVAL; - if (master_crtc_state->bigjoiner_pipes & ~bigjoiner_pipes(i915)) { + if (primary_crtc_state->joiner_pipes & ~joiner_pipes(i915)) { drm_dbg_kms(&i915->drm, - "[CRTC:%d:%s] Cannot act as big joiner master " + "[CRTC:%d:%s] Cannot act as joiner primary " "(need 0x%x as pipes, only 0x%x possible)\n", - master_crtc->base.base.id, master_crtc->base.name, - master_crtc_state->bigjoiner_pipes, bigjoiner_pipes(i915)); + primary_crtc->base.base.id, primary_crtc->base.name, + primary_crtc_state->joiner_pipes, joiner_pipes(i915)); return -EINVAL; } - for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, - intel_crtc_bigjoiner_slave_pipes(master_crtc_state)) { - struct intel_crtc_state *slave_crtc_state; + for_each_intel_crtc_in_pipe_mask(&i915->drm, secondary_crtc, + intel_crtc_joiner_secondary_pipes(primary_crtc_state)) { + struct intel_crtc_state *secondary_crtc_state; int ret; - slave_crtc_state = intel_atomic_get_crtc_state(&state->base, slave_crtc); - if (IS_ERR(slave_crtc_state)) - return PTR_ERR(slave_crtc_state); + secondary_crtc_state = intel_atomic_get_crtc_state(&state->base, secondary_crtc); + if (IS_ERR(secondary_crtc_state)) + return PTR_ERR(secondary_crtc_state); - /* master being enabled, slave was already configured? */ - if (slave_crtc_state->uapi.enable) { + /* primary being enabled, secondary was already configured? */ + if (secondary_crtc_state->uapi.enable) { drm_dbg_kms(&i915->drm, - "[CRTC:%d:%s] Slave is enabled as normal CRTC, but " - "[CRTC:%d:%s] claiming this CRTC for bigjoiner.\n", - slave_crtc->base.base.id, slave_crtc->base.name, - master_crtc->base.base.id, master_crtc->base.name); + "[CRTC:%d:%s] secondary is enabled as normal CRTC, but " + "[CRTC:%d:%s] claiming this CRTC for joiner.\n", + secondary_crtc->base.base.id, secondary_crtc->base.name, + primary_crtc->base.base.id, primary_crtc->base.name); return -EINVAL; } /* - * The state copy logic assumes the master crtc gets processed - * before the slave crtc during the main compute_config loop. + * The state copy logic assumes the primary crtc gets processed + * before the secondary crtc during the main compute_config loop. * This works because the crtcs are created in pipe order, - * and the hardware requires master pipe < slave pipe as well. + * and the hardware requires primary pipe < secondary pipe as well. * Should that change we need to rethink the logic. */ - if (WARN_ON(drm_crtc_index(&master_crtc->base) > - drm_crtc_index(&slave_crtc->base))) + if (WARN_ON(drm_crtc_index(&primary_crtc->base) > + drm_crtc_index(&secondary_crtc->base))) return -EINVAL; drm_dbg_kms(&i915->drm, - "[CRTC:%d:%s] Used as slave for big joiner master [CRTC:%d:%s]\n", - slave_crtc->base.base.id, slave_crtc->base.name, - master_crtc->base.base.id, master_crtc->base.name); + "[CRTC:%d:%s] Used as secondary for joiner primary [CRTC:%d:%s]\n", + secondary_crtc->base.base.id, secondary_crtc->base.name, + primary_crtc->base.base.id, primary_crtc->base.name); - slave_crtc_state->bigjoiner_pipes = - master_crtc_state->bigjoiner_pipes; + secondary_crtc_state->joiner_pipes = + primary_crtc_state->joiner_pipes; - ret = copy_bigjoiner_crtc_state_modeset(state, slave_crtc); + ret = copy_joiner_crtc_state_modeset(state, secondary_crtc); if (ret) return ret; } @@ -5956,25 +6054,25 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state, return 0; } -static void kill_bigjoiner_slave(struct intel_atomic_state *state, - struct intel_crtc *master_crtc) +static void kill_joiner_secondaries(struct intel_atomic_state *state, + struct intel_crtc *primary_crtc) { struct drm_i915_private *i915 = to_i915(state->base.dev); - struct intel_crtc_state *master_crtc_state = - intel_atomic_get_new_crtc_state(state, master_crtc); - struct intel_crtc *slave_crtc; + struct intel_crtc_state *primary_crtc_state = + intel_atomic_get_new_crtc_state(state, primary_crtc); + struct intel_crtc *secondary_crtc; - for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, - intel_crtc_bigjoiner_slave_pipes(master_crtc_state)) { - struct intel_crtc_state *slave_crtc_state = - intel_atomic_get_new_crtc_state(state, slave_crtc); + for_each_intel_crtc_in_pipe_mask(&i915->drm, secondary_crtc, + intel_crtc_joiner_secondary_pipes(primary_crtc_state)) { + struct intel_crtc_state *secondary_crtc_state = + intel_atomic_get_new_crtc_state(state, secondary_crtc); - slave_crtc_state->bigjoiner_pipes = 0; + secondary_crtc_state->joiner_pipes = 0; - intel_crtc_copy_uapi_to_hw_state_modeset(state, slave_crtc); + intel_crtc_copy_uapi_to_hw_state_modeset(state, secondary_crtc); } - master_crtc_state->bigjoiner_pipes = 0; + primary_crtc_state->joiner_pipes = 0; } /** @@ -6024,12 +6122,12 @@ static int intel_async_flip_check_uapi(struct intel_atomic_state *state, } /* - * FIXME: Bigjoiner+async flip is busted currently. + * FIXME: joiner+async flip is busted currently. * Remove this check once the issues are fixed. */ - if (new_crtc_state->bigjoiner_pipes) { + if (new_crtc_state->joiner_pipes) { drm_dbg_kms(&i915->drm, - "[CRTC:%d:%s] async flip disallowed with bigjoiner\n", + "[CRTC:%d:%s] async flip disallowed with joiner\n", crtc->base.base.id, crtc->base.name); return -EINVAL; } @@ -6166,6 +6264,13 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in return -EINVAL; } + /* + * We turn the first async flip request into a sync flip + * so that we can reconfigure the plane (eg. change modifier). + */ + if (!new_crtc_state->do_async_flip) + continue; + if (old_plane_state->view.color_plane[0].mapping_stride != new_plane_state->view.color_plane[0].mapping_stride) { drm_dbg_kms(&i915->drm, @@ -6247,7 +6352,7 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in return 0; } -static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state) +static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_crtc_state *crtc_state; @@ -6257,9 +6362,9 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state) int i; for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { - affected_pipes |= crtc_state->bigjoiner_pipes; + affected_pipes |= crtc_state->joiner_pipes; if (intel_crtc_needs_modeset(crtc_state)) - modeset_pipes |= crtc_state->bigjoiner_pipes; + modeset_pipes |= crtc_state->joiner_pipes; } for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, affected_pipes) { @@ -6285,10 +6390,10 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state) } for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { - /* Kill old bigjoiner link, we may re-establish afterwards */ + /* Kill old joiner link, we may re-establish afterwards */ if (intel_crtc_needs_modeset(crtc_state) && - intel_crtc_is_bigjoiner_master(crtc_state)) - kill_bigjoiner_slave(state, crtc); + intel_crtc_is_joiner_primary(crtc_state)) + kill_joiner_secondaries(state, crtc); } return 0; @@ -6306,7 +6411,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state, *failed_pipe = INVALID_PIPE; - ret = intel_bigjoiner_add_affected_crtcs(state); + ret = intel_joiner_add_affected_crtcs(state); if (ret) return ret; @@ -6316,14 +6421,14 @@ static int intel_atomic_check_config(struct intel_atomic_state *state, for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { if (!intel_crtc_needs_modeset(new_crtc_state)) { - if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) - copy_bigjoiner_crtc_state_nomodeset(state, crtc); + if (intel_crtc_is_joiner_secondary(new_crtc_state)) + copy_joiner_crtc_state_nomodeset(state, crtc); else intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc); continue; } - if (drm_WARN_ON(&i915->drm, intel_crtc_is_bigjoiner_slave(new_crtc_state))) + if (drm_WARN_ON(&i915->drm, intel_crtc_is_joiner_secondary(new_crtc_state))) continue; ret = intel_crtc_prepare_cleared_state(state, crtc); @@ -6342,7 +6447,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state, if (!intel_crtc_needs_modeset(new_crtc_state)) continue; - if (drm_WARN_ON(&i915->drm, intel_crtc_is_bigjoiner_slave(new_crtc_state))) + if (drm_WARN_ON(&i915->drm, intel_crtc_is_joiner_secondary(new_crtc_state))) continue; if (!new_crtc_state->hw.enable) @@ -6453,12 +6558,12 @@ int intel_atomic_check(struct drm_device *dev, if (!intel_crtc_needs_modeset(new_crtc_state)) continue; - if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) { + if (intel_crtc_is_joiner_secondary(new_crtc_state)) { drm_WARN_ON(&dev_priv->drm, new_crtc_state->uapi.enable); continue; } - ret = intel_atomic_check_bigjoiner(state, crtc); + ret = intel_atomic_check_joiner(state, crtc); if (ret) goto fail; } @@ -6468,7 +6573,7 @@ int intel_atomic_check(struct drm_device *dev, if (!intel_crtc_needs_modeset(new_crtc_state)) continue; - intel_bigjoiner_adjust_pipe_src(new_crtc_state); + intel_joiner_adjust_pipe_src(new_crtc_state); intel_crtc_check_fastset(old_crtc_state, new_crtc_state); } @@ -6508,8 +6613,8 @@ int intel_atomic_check(struct drm_device *dev, intel_crtc_flag_modeset(new_crtc_state); } - if (new_crtc_state->bigjoiner_pipes) { - if (intel_pipes_need_modeset(state, new_crtc_state->bigjoiner_pipes)) + if (new_crtc_state->joiner_pipes) { + if (intel_pipes_need_modeset(state, new_crtc_state->joiner_pipes)) intel_crtc_flag_modeset(new_crtc_state); } } @@ -6800,7 +6905,8 @@ static void intel_pre_update_crtc(struct intel_atomic_state *state, intel_crtc_needs_fastset(new_crtc_state)) icl_set_pipe_chicken(new_crtc_state); - if (vrr_params_changed(old_crtc_state, new_crtc_state)) + if (vrr_params_changed(old_crtc_state, new_crtc_state) || + cmrr_params_changed(old_crtc_state, new_crtc_state)) intel_vrr_set_transcoder_timings(new_crtc_state); } @@ -6923,7 +7029,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) if ((disable_pipes & BIT(crtc->pipe)) == 0) continue; - if (intel_crtc_is_bigjoiner_slave(old_crtc_state)) + if (intel_crtc_is_joiner_secondary(old_crtc_state)) continue; /* In case of Transcoder port Sync master slave CRTCs can be @@ -6945,7 +7051,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) if ((disable_pipes & BIT(crtc->pipe)) == 0) continue; - if (intel_crtc_is_bigjoiner_slave(old_crtc_state)) + if (intel_crtc_is_joiner_secondary(old_crtc_state)) continue; intel_old_crtc_state_disables(state, crtc); @@ -7024,8 +7130,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) while (update_pipes) { /* - * Commit in reverse order to make bigjoiner master - * send the uapi events after slaves are done. + * Commit in reverse order to make joiner primary + * send the uapi events after secondaries are done. */ for_each_oldnew_intel_crtc_in_state_reverse(state, crtc, old_crtc_state, new_crtc_state, i) { @@ -7070,7 +7176,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) if ((modeset_pipes & BIT(pipe)) == 0) continue; - if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) + if (intel_crtc_is_joiner_secondary(new_crtc_state)) continue; if (intel_dp_mst_is_slave_trans(new_crtc_state) || @@ -7084,7 +7190,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) /* * Then we enable all remaining pipes that depend on other - * pipes: MST slaves and port sync masters, big joiner master + * pipes: MST slaves and port sync masters */ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { enum pipe pipe = crtc->pipe; @@ -7092,7 +7198,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) if ((modeset_pipes & BIT(pipe)) == 0) continue; - if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) + if (intel_crtc_is_joiner_secondary(new_crtc_state)) continue; modeset_pipes &= ~intel_crtc_joined_pipe_mask(new_crtc_state); @@ -7113,8 +7219,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) } /* - * Commit in reverse order to make bigjoiner master - * send the uapi events after slaves are done. + * Commit in reverse order to make joiner primary + * send the uapi events after secondaries are done. */ for_each_new_intel_crtc_in_state_reverse(state, crtc, new_crtc_state, i) { enum pipe pipe = crtc->pipe; @@ -7227,6 +7333,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_atomic_commit_fence_wait(state); + intel_td_flush(dev_priv); + drm_atomic_helper_wait_for_dependencies(&state->base); drm_dp_mst_atomic_wait_for_dependencies(&state->base); intel_atomic_global_state_wait_for_dependencies(state); @@ -7839,7 +7947,7 @@ static int max_dotclock(struct drm_i915_private *i915) { int max_dotclock = i915->display.cdclk.max_dotclk_freq; - /* icl+ might use bigjoiner */ + /* icl+ might use joiner */ if (DISPLAY_VER(i915) >= 11) max_dotclock *= 2; @@ -7964,7 +8072,7 @@ enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *de enum drm_mode_status intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv, const struct drm_display_mode *mode, - bool bigjoiner) + bool joiner) { int plane_width_max, plane_height_max; @@ -7981,7 +8089,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv, * too big for that. */ if (DISPLAY_VER(dev_priv) >= 11) { - plane_width_max = 5120 << bigjoiner; + plane_width_max = 5120 << joiner; plane_height_max = 4320; } else { plane_width_max = 5120; @@ -8163,19 +8271,19 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) PLL_REF_INPUT_DREFCLK | DPLL_VCO_ENABLE; - intel_de_write(dev_priv, TRANS_HTOTAL(cpu_transcoder), + intel_de_write(dev_priv, TRANS_HTOTAL(dev_priv, cpu_transcoder), HACTIVE(640 - 1) | HTOTAL(800 - 1)); - intel_de_write(dev_priv, TRANS_HBLANK(cpu_transcoder), + intel_de_write(dev_priv, TRANS_HBLANK(dev_priv, cpu_transcoder), HBLANK_START(640 - 1) | HBLANK_END(800 - 1)); - intel_de_write(dev_priv, TRANS_HSYNC(cpu_transcoder), + intel_de_write(dev_priv, TRANS_HSYNC(dev_priv, cpu_transcoder), HSYNC_START(656 - 1) | HSYNC_END(752 - 1)); - intel_de_write(dev_priv, TRANS_VTOTAL(cpu_transcoder), + intel_de_write(dev_priv, TRANS_VTOTAL(dev_priv, cpu_transcoder), VACTIVE(480 - 1) | VTOTAL(525 - 1)); - intel_de_write(dev_priv, TRANS_VBLANK(cpu_transcoder), + intel_de_write(dev_priv, TRANS_VBLANK(dev_priv, cpu_transcoder), VBLANK_START(480 - 1) | VBLANK_END(525 - 1)); - intel_de_write(dev_priv, TRANS_VSYNC(cpu_transcoder), + intel_de_write(dev_priv, TRANS_VSYNC(dev_priv, cpu_transcoder), VSYNC_START(490 - 1) | VSYNC_END(492 - 1)); - intel_de_write(dev_priv, PIPESRC(pipe), + intel_de_write(dev_priv, PIPESRC(dev_priv, pipe), PIPESRC_WIDTH(640 - 1) | PIPESRC_HEIGHT(480 - 1)); intel_de_write(dev_priv, FP0(pipe), fp); @@ -8186,11 +8294,12 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) * the P1/P2 dividers. Otherwise the DPLL will keep using the old * dividers, even though the register value does change. */ - intel_de_write(dev_priv, DPLL(pipe), dpll & ~DPLL_VGA_MODE_DIS); - intel_de_write(dev_priv, DPLL(pipe), dpll); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), + dpll & ~DPLL_VGA_MODE_DIS); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), dpll); /* Wait for the clocks to stabilize. */ - intel_de_posting_read(dev_priv, DPLL(pipe)); + intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe)); udelay(150); /* The pixel multiplier can only be updated once the @@ -8198,17 +8307,17 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) * * So write it again. */ - intel_de_write(dev_priv, DPLL(pipe), dpll); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), dpll); /* We do this three times for luck */ for (i = 0; i < 3 ; i++) { - intel_de_write(dev_priv, DPLL(pipe), dpll); - intel_de_posting_read(dev_priv, DPLL(pipe)); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), dpll); + intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe)); udelay(150); /* wait for warmup */ } - intel_de_write(dev_priv, TRANSCONF(pipe), TRANSCONF_ENABLE); - intel_de_posting_read(dev_priv, TRANSCONF(pipe)); + intel_de_write(dev_priv, TRANSCONF(dev_priv, pipe), TRANSCONF_ENABLE); + intel_de_posting_read(dev_priv, TRANSCONF(dev_priv, pipe)); intel_wait_for_pipe_scanline_moving(crtc); } @@ -8221,23 +8330,23 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) pipe_name(pipe)); drm_WARN_ON(&dev_priv->drm, - intel_de_read(dev_priv, DSPCNTR(PLANE_A)) & DISP_ENABLE); + intel_de_read(dev_priv, DSPCNTR(dev_priv, PLANE_A)) & DISP_ENABLE); drm_WARN_ON(&dev_priv->drm, - intel_de_read(dev_priv, DSPCNTR(PLANE_B)) & DISP_ENABLE); + intel_de_read(dev_priv, DSPCNTR(dev_priv, PLANE_B)) & DISP_ENABLE); drm_WARN_ON(&dev_priv->drm, - intel_de_read(dev_priv, DSPCNTR(PLANE_C)) & DISP_ENABLE); + intel_de_read(dev_priv, DSPCNTR(dev_priv, PLANE_C)) & DISP_ENABLE); drm_WARN_ON(&dev_priv->drm, - intel_de_read(dev_priv, CURCNTR(PIPE_A)) & MCURSOR_MODE_MASK); + intel_de_read(dev_priv, CURCNTR(dev_priv, PIPE_A)) & MCURSOR_MODE_MASK); drm_WARN_ON(&dev_priv->drm, - intel_de_read(dev_priv, CURCNTR(PIPE_B)) & MCURSOR_MODE_MASK); + intel_de_read(dev_priv, CURCNTR(dev_priv, PIPE_B)) & MCURSOR_MODE_MASK); - intel_de_write(dev_priv, TRANSCONF(pipe), 0); - intel_de_posting_read(dev_priv, TRANSCONF(pipe)); + intel_de_write(dev_priv, TRANSCONF(dev_priv, pipe), 0); + intel_de_posting_read(dev_priv, TRANSCONF(dev_priv, pipe)); intel_wait_for_pipe_scanline_stopped(crtc); - intel_de_write(dev_priv, DPLL(pipe), DPLL_VGA_MODE_DIS); - intel_de_posting_read(dev_priv, DPLL(pipe)); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), DPLL_VGA_MODE_DIS); + intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe)); } void intel_hpd_poll_fini(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 56d1c0e3e62c..b0cf6ca70952 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -415,7 +415,7 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv, enum drm_mode_status intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv, const struct drm_display_mode *mode, - bool bigjoiner); + bool joiner); enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915, const struct drm_display_mode *mode); @@ -423,10 +423,10 @@ enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port); bool is_trans_port_sync_mode(const struct intel_crtc_state *state); bool is_trans_port_sync_master(const struct intel_crtc_state *state); u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state); -bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state); -bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state); -u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state); -struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state); +bool intel_crtc_is_joiner_secondary(const struct intel_crtc_state *crtc_state); +bool intel_crtc_is_joiner_primary(const struct intel_crtc_state *crtc_state); +u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state); +struct intel_crtc *intel_primary_crtc(const struct intel_crtc_state *crtc_state); bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state); bool intel_pipe_config_compare(const struct intel_crtc_state *current_config, const struct intel_crtc_state *pipe_config, @@ -537,6 +537,9 @@ int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state, const char *reason, u8 pipe_mask); int intel_modeset_all_pipes_late(struct intel_atomic_state *state, const char *reason); +int intel_modeset_commit_pipes(struct drm_i915_private *i915, + u8 pipe_mask, + struct drm_modeset_acquire_ctx *ctx); void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state, struct intel_power_domain_mask *old_domains); void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 35f9f86ef70f..91757fed9c6d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -13,6 +13,7 @@ #include "i915_debugfs.h" #include "i915_irq.h" #include "i915_reg.h" +#include "intel_alpm.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_crtc_state_dump.h" @@ -23,6 +24,7 @@ #include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dp.h" +#include "intel_dp_link_training.h" #include "intel_dp_mst.h" #include "intel_drrs.h" #include "intel_fbc.h" @@ -76,7 +78,7 @@ static int i915_sr_status(struct seq_file *m, void *unused) else if (IS_I915GM(dev_priv)) sr_enabled = intel_de_read(dev_priv, INSTPM) & INSTPM_SELF_EN; else if (IS_PINEVIEW(dev_priv)) - sr_enabled = intel_de_read(dev_priv, DSPFW3) & PINEVIEW_SELF_REFRESH_EN; + sr_enabled = intel_de_read(dev_priv, DSPFW3(dev_priv)) & PINEVIEW_SELF_REFRESH_EN; else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) sr_enabled = intel_de_read(dev_priv, FW_BLC_SELF_VLV) & FW_CSPWRDWNEN; @@ -574,10 +576,10 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) intel_scaler_info(m, crtc); - if (crtc_state->bigjoiner_pipes) + if (crtc_state->joiner_pipes) seq_printf(m, "\tLinked to 0x%x pipes as a %s\n", - crtc_state->bigjoiner_pipes, - intel_crtc_is_bigjoiner_slave(crtc_state) ? "slave" : "master"); + crtc_state->joiner_pipes, + intel_crtc_is_joiner_secondary(crtc_state) ? "slave" : "master"); for_each_intel_encoder_mask(&dev_priv->drm, encoder, crtc_state->uapi.encoder_mask) @@ -1515,6 +1517,8 @@ void intel_connector_debugfs_add(struct intel_connector *connector) intel_drrs_connector_debugfs_add(connector); intel_pps_connector_debugfs_add(connector); intel_psr_connector_debugfs_add(connector); + intel_alpm_lobf_debugfs_add(connector); + intel_dp_link_training_debugfs_add(connector); if (connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector_type == DRM_MODE_CONNECTOR_HDMIA || diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c index 120e209ee74a..dd7dce4b0e7a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.c +++ b/drivers/gpu/drm/i915/display/intel_display_device.c @@ -3,7 +3,7 @@ * Copyright © 2023 Intel Corporation */ -#include <drm/i915_pciids.h> +#include <drm/intel/i915_pciids.h> #include <drm/drm_color_mgmt.h> #include <linux/pci.h> @@ -20,6 +20,25 @@ __diag_push(); __diag_ignore_all("-Woverride-init", "Allow field initialization overrides for display info"); +struct subplatform_desc { + enum intel_display_subplatform subplatform; + const char *name; + const u16 *pciidlist; +}; + +struct platform_desc { + enum intel_display_platform platform; + const char *name; + const struct subplatform_desc *subplatforms; + const struct intel_display_device_info *info; /* NULL for GMD ID */ +}; + +#define PLATFORM(_platform) \ + .platform = (INTEL_DISPLAY_##_platform), \ + .name = #_platform + +#define ID(id) (id) + static const struct intel_display_device_info no_display = {}; #define PIPE_A_OFFSET 0x70000 @@ -200,33 +219,45 @@ static const struct intel_display_device_info no_display = {}; .__runtime_defaults.pipe_mask = BIT(PIPE_A), \ .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) -static const struct intel_display_device_info i830_display = { - I830_DISPLAY, +static const struct platform_desc i830_desc = { + PLATFORM(I830), + .info = &(const struct intel_display_device_info) { + I830_DISPLAY, - .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C), /* DVO A/B/C */ + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C), /* DVO A/B/C */ + }, }; -static const struct intel_display_device_info i845_display = { - I845_DISPLAY, +static const struct platform_desc i845_desc = { + PLATFORM(I845G), + .info = &(const struct intel_display_device_info) { + I845_DISPLAY, - .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* DVO B/C */ + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* DVO B/C */ + }, }; -static const struct intel_display_device_info i85x_display = { - I830_DISPLAY, +static const struct platform_desc i85x_desc = { + PLATFORM(I85X), + .info = &(const struct intel_display_device_info) { + I830_DISPLAY, - .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* DVO B/C */ - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* DVO B/C */ + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; -static const struct intel_display_device_info i865g_display = { - I845_DISPLAY, +static const struct platform_desc i865g_desc = { + PLATFORM(I865G), + .info = &(const struct intel_display_device_info) { + I845_DISPLAY, - .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* DVO B/C */ - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* DVO B/C */ + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; -#define GEN3_DISPLAY \ +#define GEN3_DISPLAY \ .has_gmch = 1, \ .has_overlay = 1, \ I9XX_PIPE_OFFSETS, \ @@ -238,52 +269,70 @@ static const struct intel_display_device_info i865g_display = { BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) /* SDVO B/C */ -static const struct intel_display_device_info i915g_display = { - GEN3_DISPLAY, - I845_COLORS, - .cursor_needs_physical = 1, - .overlay_needs_physical = 1, +static const struct platform_desc i915g_desc = { + PLATFORM(I915G), + .info = &(const struct intel_display_device_info) { + GEN3_DISPLAY, + I845_COLORS, + .cursor_needs_physical = 1, + .overlay_needs_physical = 1, + }, }; -static const struct intel_display_device_info i915gm_display = { - GEN3_DISPLAY, - I9XX_COLORS, - .cursor_needs_physical = 1, - .overlay_needs_physical = 1, - .supports_tv = 1, - - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), +static const struct platform_desc i915gm_desc = { + PLATFORM(I915GM), + .info = &(const struct intel_display_device_info) { + GEN3_DISPLAY, + I9XX_COLORS, + .cursor_needs_physical = 1, + .overlay_needs_physical = 1, + .supports_tv = 1, + + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; -static const struct intel_display_device_info i945g_display = { - GEN3_DISPLAY, - I845_COLORS, - .has_hotplug = 1, - .cursor_needs_physical = 1, - .overlay_needs_physical = 1, +static const struct platform_desc i945g_desc = { + PLATFORM(I945G), + .info = &(const struct intel_display_device_info) { + GEN3_DISPLAY, + I845_COLORS, + .has_hotplug = 1, + .cursor_needs_physical = 1, + .overlay_needs_physical = 1, + }, }; -static const struct intel_display_device_info i945gm_display = { - GEN3_DISPLAY, - I9XX_COLORS, - .has_hotplug = 1, - .cursor_needs_physical = 1, - .overlay_needs_physical = 1, - .supports_tv = 1, - - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), +static const struct platform_desc i945gm_desc = { + PLATFORM(I915GM), + .info = &(const struct intel_display_device_info) { + GEN3_DISPLAY, + I9XX_COLORS, + .has_hotplug = 1, + .cursor_needs_physical = 1, + .overlay_needs_physical = 1, + .supports_tv = 1, + + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; -static const struct intel_display_device_info g33_display = { - GEN3_DISPLAY, - I845_COLORS, - .has_hotplug = 1, +static const struct platform_desc g33_desc = { + PLATFORM(G33), + .info = &(const struct intel_display_device_info) { + GEN3_DISPLAY, + I845_COLORS, + .has_hotplug = 1, + }, }; -static const struct intel_display_device_info pnv_display = { - GEN3_DISPLAY, - I9XX_COLORS, - .has_hotplug = 1, +static const struct platform_desc pnv_desc = { + PLATFORM(PINEVIEW), + .info = &(const struct intel_display_device_info) { + GEN3_DISPLAY, + I9XX_COLORS, + .has_hotplug = 1, + }, }; #define GEN4_DISPLAY \ @@ -298,34 +347,46 @@ static const struct intel_display_device_info pnv_display = { .__runtime_defaults.cpu_transcoder_mask = \ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) -static const struct intel_display_device_info i965g_display = { - GEN4_DISPLAY, - .has_overlay = 1, +static const struct platform_desc i965g_desc = { + PLATFORM(I965G), + .info = &(const struct intel_display_device_info) { + GEN4_DISPLAY, + .has_overlay = 1, - .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* SDVO B/C */ + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* SDVO B/C */ + }, }; -static const struct intel_display_device_info i965gm_display = { - GEN4_DISPLAY, - .has_overlay = 1, - .supports_tv = 1, +static const struct platform_desc i965gm_desc = { + PLATFORM(I965GM), + .info = &(const struct intel_display_device_info) { + GEN4_DISPLAY, + .has_overlay = 1, + .supports_tv = 1, - .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* SDVO B/C */ - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* SDVO B/C */ + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; -static const struct intel_display_device_info g45_display = { - GEN4_DISPLAY, +static const struct platform_desc g45_desc = { + PLATFORM(G45), + .info = &(const struct intel_display_device_info) { + GEN4_DISPLAY, - .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* SDVO/HDMI/DP B/C, DP D */ + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* SDVO/HDMI/DP B/C, DP D */ + }, }; -static const struct intel_display_device_info gm45_display = { - GEN4_DISPLAY, - .supports_tv = 1, +static const struct platform_desc gm45_desc = { + PLATFORM(GM45), + .info = &(const struct intel_display_device_info) { + GEN4_DISPLAY, + .supports_tv = 1, - .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* SDVO/HDMI/DP B/C, DP D */ - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* SDVO/HDMI/DP B/C, DP D */ + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; #define ILK_DISPLAY \ @@ -340,112 +401,175 @@ static const struct intel_display_device_info gm45_display = { BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */ -static const struct intel_display_device_info ilk_d_display = { - ILK_DISPLAY, +static const struct platform_desc ilk_d_desc = { + PLATFORM(IRONLAKE), + .info = &(const struct intel_display_device_info) { + ILK_DISPLAY, + }, }; -static const struct intel_display_device_info ilk_m_display = { - ILK_DISPLAY, +static const struct platform_desc ilk_m_desc = { + PLATFORM(IRONLAKE), + .info = &(const struct intel_display_device_info) { + ILK_DISPLAY, - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; -static const struct intel_display_device_info snb_display = { - .has_hotplug = 1, - I9XX_PIPE_OFFSETS, - I9XX_CURSOR_OFFSETS, - ILK_COLORS, - - .__runtime_defaults.ip.ver = 6, - .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), - .__runtime_defaults.cpu_transcoder_mask = +static const struct platform_desc snb_desc = { + PLATFORM(SANDYBRIDGE), + .info = &(const struct intel_display_device_info) { + .has_hotplug = 1, + I9XX_PIPE_OFFSETS, + I9XX_CURSOR_OFFSETS, + ILK_COLORS, + + .__runtime_defaults.ip.ver = 6, + .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), + .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), - .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */ - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */ + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; -static const struct intel_display_device_info ivb_display = { - .has_hotplug = 1, - IVB_PIPE_OFFSETS, - IVB_CURSOR_OFFSETS, - IVB_COLORS, - - .__runtime_defaults.ip.ver = 7, - .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), - .__runtime_defaults.cpu_transcoder_mask = +static const struct platform_desc ivb_desc = { + PLATFORM(IVYBRIDGE), + .info = &(const struct intel_display_device_info) { + .has_hotplug = 1, + IVB_PIPE_OFFSETS, + IVB_CURSOR_OFFSETS, + IVB_COLORS, + + .__runtime_defaults.ip.ver = 7, + .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), + .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), - .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */ - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */ + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; -static const struct intel_display_device_info vlv_display = { - .has_gmch = 1, - .has_hotplug = 1, - .mmio_offset = VLV_DISPLAY_BASE, - I9XX_PIPE_OFFSETS, - I9XX_CURSOR_OFFSETS, - I9XX_COLORS, - - .__runtime_defaults.ip.ver = 7, - .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), - .__runtime_defaults.cpu_transcoder_mask = +static const struct platform_desc vlv_desc = { + PLATFORM(VALLEYVIEW), + .info = &(const struct intel_display_device_info) { + .has_gmch = 1, + .has_hotplug = 1, + .mmio_offset = VLV_DISPLAY_BASE, + I9XX_PIPE_OFFSETS, + I9XX_CURSOR_OFFSETS, + I9XX_COLORS, + + .__runtime_defaults.ip.ver = 7, + .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), + .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), - .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* HDMI/DP B/C */ + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* HDMI/DP B/C */ + }, }; -static const struct intel_display_device_info hsw_display = { - .has_ddi = 1, - .has_dp_mst = 1, - .has_fpga_dbg = 1, - .has_hotplug = 1, - .has_psr = 1, - .has_psr_hw_tracking = 1, - HSW_PIPE_OFFSETS, - IVB_CURSOR_OFFSETS, - IVB_COLORS, +static const u16 hsw_ult_ids[] = { + INTEL_HSW_ULT_GT1_IDS(ID), + INTEL_HSW_ULT_GT2_IDS(ID), + INTEL_HSW_ULT_GT3_IDS(ID), + 0 +}; - .__runtime_defaults.ip.ver = 7, - .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), - .__runtime_defaults.cpu_transcoder_mask = +static const u16 hsw_ulx_ids[] = { + INTEL_HSW_ULX_GT1_IDS(ID), + INTEL_HSW_ULX_GT2_IDS(ID), + 0 +}; + +static const struct platform_desc hsw_desc = { + PLATFORM(HASWELL), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_HASWELL_ULT, "ULT", hsw_ult_ids }, + { INTEL_DISPLAY_HASWELL_ULX, "ULX", hsw_ulx_ids }, + {}, + }, + .info = &(const struct intel_display_device_info) { + .has_ddi = 1, + .has_dp_mst = 1, + .has_fpga_dbg = 1, + .has_hotplug = 1, + .has_psr = 1, + .has_psr_hw_tracking = 1, + HSW_PIPE_OFFSETS, + IVB_CURSOR_OFFSETS, + IVB_COLORS, + + .__runtime_defaults.ip.ver = 7, + .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), + .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP), - .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; -static const struct intel_display_device_info bdw_display = { - .has_ddi = 1, - .has_dp_mst = 1, - .has_fpga_dbg = 1, - .has_hotplug = 1, - .has_psr = 1, - .has_psr_hw_tracking = 1, - HSW_PIPE_OFFSETS, - IVB_CURSOR_OFFSETS, - IVB_COLORS, +static const u16 bdw_ult_ids[] = { + INTEL_BDW_ULT_GT1_IDS(ID), + INTEL_BDW_ULT_GT2_IDS(ID), + INTEL_BDW_ULT_GT3_IDS(ID), + INTEL_BDW_ULT_RSVD_IDS(ID), + 0 +}; - .__runtime_defaults.ip.ver = 8, - .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), - .__runtime_defaults.cpu_transcoder_mask = +static const u16 bdw_ulx_ids[] = { + INTEL_BDW_ULX_GT1_IDS(ID), + INTEL_BDW_ULX_GT2_IDS(ID), + INTEL_BDW_ULX_GT3_IDS(ID), + INTEL_BDW_ULX_RSVD_IDS(ID), + 0 +}; + +static const struct platform_desc bdw_desc = { + PLATFORM(BROADWELL), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_BROADWELL_ULT, "ULT", bdw_ult_ids }, + { INTEL_DISPLAY_BROADWELL_ULX, "ULX", bdw_ulx_ids }, + {}, + }, + .info = &(const struct intel_display_device_info) { + .has_ddi = 1, + .has_dp_mst = 1, + .has_fpga_dbg = 1, + .has_hotplug = 1, + .has_psr = 1, + .has_psr_hw_tracking = 1, + HSW_PIPE_OFFSETS, + IVB_CURSOR_OFFSETS, + IVB_COLORS, + + .__runtime_defaults.ip.ver = 8, + .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), + .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP), - .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), + }, }; -static const struct intel_display_device_info chv_display = { - .has_hotplug = 1, - .has_gmch = 1, - .mmio_offset = VLV_DISPLAY_BASE, - CHV_PIPE_OFFSETS, - CHV_CURSOR_OFFSETS, - CHV_COLORS, - - .__runtime_defaults.ip.ver = 8, - .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), - .__runtime_defaults.cpu_transcoder_mask = +static const struct platform_desc chv_desc = { + PLATFORM(CHERRYVIEW), + .info = &(const struct intel_display_device_info) { + .has_hotplug = 1, + .has_gmch = 1, + .mmio_offset = VLV_DISPLAY_BASE, + CHV_PIPE_OFFSETS, + CHV_CURSOR_OFFSETS, + CHV_COLORS, + + .__runtime_defaults.ip.ver = 8, + .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), + .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), - .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* HDMI/DP B/C/D */ + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* HDMI/DP B/C/D */ + }, }; static const struct intel_display_device_info skl_display = { @@ -467,13 +591,99 @@ static const struct intel_display_device_info skl_display = { .__runtime_defaults.has_hdcp = 1, .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), .__runtime_defaults.cpu_transcoder_mask = - BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | - BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP), + BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | + BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP), .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), }; -#define GEN9_LP_DISPLAY \ +static const u16 skl_ult_ids[] = { + INTEL_SKL_ULT_GT1_IDS(ID), + INTEL_SKL_ULT_GT2_IDS(ID), + INTEL_SKL_ULT_GT3_IDS(ID), + 0 +}; + +static const u16 skl_ulx_ids[] = { + INTEL_SKL_ULX_GT1_IDS(ID), + INTEL_SKL_ULX_GT2_IDS(ID), + 0 +}; + +static const struct platform_desc skl_desc = { + PLATFORM(SKYLAKE), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_SKYLAKE_ULT, "ULT", skl_ult_ids }, + { INTEL_DISPLAY_SKYLAKE_ULX, "ULX", skl_ulx_ids }, + {}, + }, + .info = &skl_display, +}; + +static const u16 kbl_ult_ids[] = { + INTEL_KBL_ULT_GT1_IDS(ID), + INTEL_KBL_ULT_GT2_IDS(ID), + INTEL_KBL_ULT_GT3_IDS(ID), + 0 +}; + +static const u16 kbl_ulx_ids[] = { + INTEL_KBL_ULX_GT1_IDS(ID), + INTEL_KBL_ULX_GT2_IDS(ID), + INTEL_AML_KBL_GT2_IDS(ID), + 0 +}; + +static const struct platform_desc kbl_desc = { + PLATFORM(KABYLAKE), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_KABYLAKE_ULT, "ULT", kbl_ult_ids }, + { INTEL_DISPLAY_KABYLAKE_ULX, "ULX", kbl_ulx_ids }, + {}, + }, + .info = &skl_display, +}; + +static const u16 cfl_ult_ids[] = { + INTEL_CFL_U_GT2_IDS(ID), + INTEL_CFL_U_GT3_IDS(ID), + INTEL_WHL_U_GT1_IDS(ID), + INTEL_WHL_U_GT2_IDS(ID), + INTEL_WHL_U_GT3_IDS(ID), + 0 +}; + +static const u16 cfl_ulx_ids[] = { + INTEL_AML_CFL_GT2_IDS(ID), + 0 +}; + +static const struct platform_desc cfl_desc = { + PLATFORM(COFFEELAKE), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_COFFEELAKE_ULT, "ULT", cfl_ult_ids }, + { INTEL_DISPLAY_COFFEELAKE_ULX, "ULX", cfl_ulx_ids }, + {}, + }, + .info = &skl_display, +}; + +static const u16 cml_ult_ids[] = { + INTEL_CML_U_GT1_IDS(ID), + INTEL_CML_U_GT2_IDS(ID), + 0 +}; + +static const struct platform_desc cml_desc = { + PLATFORM(COMETLAKE), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_COMETLAKE_ULT, "ULT", cml_ult_ids }, + {}, + }, + .info = &skl_display, +}; + +#define GEN9_LP_DISPLAY \ .dbuf.slice_mask = BIT(DBUF_S1), \ .has_dp_mst = 1, \ .has_ddi = 1, \ @@ -496,19 +706,25 @@ static const struct intel_display_device_info skl_display = { BIT(TRANSCODER_DSI_A) | BIT(TRANSCODER_DSI_C), \ .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) -static const struct intel_display_device_info bxt_display = { - GEN9_LP_DISPLAY, - .dbuf.size = 512 - 4, /* 4 blocks for bypass path allocation */ +static const struct platform_desc bxt_desc = { + PLATFORM(BROXTON), + .info = &(const struct intel_display_device_info) { + GEN9_LP_DISPLAY, + .dbuf.size = 512 - 4, /* 4 blocks for bypass path allocation */ - .__runtime_defaults.ip.ver = 9, + .__runtime_defaults.ip.ver = 9, + }, }; -static const struct intel_display_device_info glk_display = { - GEN9_LP_DISPLAY, - .dbuf.size = 1024 - 4, /* 4 blocks for bypass path allocation */ - GLK_COLORS, +static const struct platform_desc glk_desc = { + PLATFORM(GEMINILAKE), + .info = &(const struct intel_display_device_info) { + GEN9_LP_DISPLAY, + .dbuf.size = 1024 - 4, /* 4 blocks for bypass path allocation */ + GLK_COLORS, - .__runtime_defaults.ip.ver = 10, + .__runtime_defaults.ip.ver = 10, + }, }; #define ICL_DISPLAY \ @@ -552,10 +768,22 @@ static const struct intel_display_device_info glk_display = { BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A) -static const struct intel_display_device_info icl_display = { - ICL_DISPLAY, +static const u16 icl_port_f_ids[] = { + INTEL_ICL_PORT_F_IDS(ID), + 0 +}; - .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), +static const struct platform_desc icl_desc = { + PLATFORM(ICELAKE), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_ICELAKE_PORT_F, "Port F", icl_port_f_ids }, + {}, + }, + .info = &(const struct intel_display_device_info) { + ICL_DISPLAY, + + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), + }, }; static const struct intel_display_device_info jsl_ehl_display = { @@ -564,6 +792,16 @@ static const struct intel_display_device_info jsl_ehl_display = { .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), }; +static const struct platform_desc jsl_desc = { + PLATFORM(JASPERLAKE), + .info = &jsl_ehl_display, +}; + +static const struct platform_desc ehl_desc = { + PLATFORM(ELKHARTLAKE), + .info = &jsl_ehl_display, +}; + #define XE_D_DISPLAY \ .abox_mask = GENMASK(2, 1), \ .dbuf.size = 2048, \ @@ -607,44 +845,74 @@ static const struct intel_display_device_info jsl_ehl_display = { BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A) -static const struct intel_display_device_info tgl_display = { - XE_D_DISPLAY, +static const u16 tgl_uy_ids[] = { + INTEL_TGL_GT2_IDS(ID), + 0 +}; - /* - * FIXME DDI C/combo PHY C missing due to combo PHY - * code making a mess on SKUs where the PHY is missing. - */ - .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | +static const struct platform_desc tgl_desc = { + PLATFORM(TIGERLAKE), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_TIGERLAKE_UY, "UY", tgl_uy_ids }, + {}, + }, + .info = &(const struct intel_display_device_info) { + XE_D_DISPLAY, + + /* + * FIXME DDI C/combo PHY C missing due to combo PHY + * code making a mess on SKUs where the PHY is missing. + */ + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4) | BIT(PORT_TC5) | BIT(PORT_TC6), + }, }; -static const struct intel_display_device_info dg1_display = { - XE_D_DISPLAY, +static const struct platform_desc dg1_desc = { + PLATFORM(DG1), + .info = &(const struct intel_display_device_info) { + XE_D_DISPLAY, - .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_TC1) | BIT(PORT_TC2), + }, }; -static const struct intel_display_device_info rkl_display = { - XE_D_DISPLAY, - .abox_mask = BIT(0), - .has_hti = 1, - .has_psr_hw_tracking = 0, +static const struct platform_desc rkl_desc = { + PLATFORM(ROCKETLAKE), + .info = &(const struct intel_display_device_info) { + XE_D_DISPLAY, + .abox_mask = BIT(0), + .has_hti = 1, + .has_psr_hw_tracking = 0, - .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), - .__runtime_defaults.cpu_transcoder_mask = + .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), + .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), - .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_TC1) | BIT(PORT_TC2), + }, }; -static const struct intel_display_device_info adl_s_display = { - XE_D_DISPLAY, - .has_hti = 1, - .has_psr_hw_tracking = 0, +static const u16 adls_rpls_ids[] = { + INTEL_RPLS_IDS(ID), + 0 +}; - .__runtime_defaults.port_mask = BIT(PORT_A) | +static const struct platform_desc adl_s_desc = { + PLATFORM(ALDERLAKE_S), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_ALDERLAKE_S_RAPTORLAKE_S, "RPL-S", adls_rpls_ids }, + {}, + }, + .info = &(const struct intel_display_device_info) { + XE_D_DISPLAY, + .has_hti = 1, + .has_psr_hw_tracking = 0, + + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4), + }, }; #define XE_LPD_FEATURES \ @@ -703,6 +971,32 @@ static const struct intel_display_device_info xe_lpd_display = { BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4), }; +static const u16 adlp_adln_ids[] = { + INTEL_ADLN_IDS(ID), + 0 +}; + +static const u16 adlp_rplu_ids[] = { + INTEL_RPLU_IDS(ID), + 0 +}; + +static const u16 adlp_rplp_ids[] = { + INTEL_RPLP_IDS(ID), + 0 +}; + +static const struct platform_desc adl_p_desc = { + PLATFORM(ALDERLAKE_P), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_ALDERLAKE_P_ALDERLAKE_N, "ADL-N", adlp_adln_ids }, + { INTEL_DISPLAY_ALDERLAKE_P_RAPTORLAKE_U, "RPL-U", adlp_rplu_ids }, + { INTEL_DISPLAY_ALDERLAKE_P_RAPTORLAKE_P, "RPL-P", adlp_rplp_ids }, + {}, + }, + .info = &xe_lpd_display, +}; + static const struct intel_display_device_info xe_hpd_display = { XE_LPD_FEATURES, .has_cdclk_squash = 1, @@ -714,6 +1008,32 @@ static const struct intel_display_device_info xe_hpd_display = { BIT(PORT_TC1), }; +static const u16 dg2_g10_ids[] = { + INTEL_DG2_G10_IDS(ID), + 0 +}; + +static const u16 dg2_g11_ids[] = { + INTEL_DG2_G11_IDS(ID), + 0 +}; + +static const u16 dg2_g12_ids[] = { + INTEL_DG2_G12_IDS(ID), + 0 +}; + +static const struct platform_desc dg2_desc = { + PLATFORM(DG2), + .subplatforms = (const struct subplatform_desc[]) { + { INTEL_DISPLAY_DG2_G10, "G10", dg2_g10_ids }, + { INTEL_DISPLAY_DG2_G11, "G11", dg2_g11_ids }, + { INTEL_DISPLAY_DG2_G12, "G12", dg2_g12_ids }, + {}, + }, + .info = &xe_hpd_display, +}; + #define XE_LPDP_FEATURES \ .abox_mask = GENMASK(1, 0), \ .color = { \ @@ -771,6 +1091,29 @@ static const struct intel_display_device_info xe2_lpd_display = { BIT(INTEL_FBC_C) | BIT(INTEL_FBC_D), }; +static const struct intel_display_device_info xe2_hpd_display = { + XE_LPDP_FEATURES, + .__runtime_defaults.port_mask = BIT(PORT_A) | + BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4), +}; + +/* + * Do not initialize the .info member of the platform desc for GMD ID based + * platforms. Their display will be probed automatically based on the IP version + * reported by the hardware. + */ +static const struct platform_desc mtl_desc = { + PLATFORM(METEORLAKE), +}; + +static const struct platform_desc lnl_desc = { + PLATFORM(LUNARLAKE), +}; + +static const struct platform_desc bmg_desc = { + PLATFORM(BATTLEMAGE), +}; + __diag_pop(); /* @@ -782,68 +1125,64 @@ __diag_pop(); static bool has_no_display(struct pci_dev *pdev) { static const struct pci_device_id ids[] = { - INTEL_IVB_Q_IDS(0), + INTEL_IVB_Q_IDS(INTEL_VGA_DEVICE, 0), {} }; return pci_match_id(ids, pdev); } -#undef INTEL_VGA_DEVICE -#define INTEL_VGA_DEVICE(id, info) { id, info } +#define INTEL_DISPLAY_DEVICE(_id, _desc) { .devid = (_id), .desc = (_desc) } static const struct { u32 devid; - const struct intel_display_device_info *info; + const struct platform_desc *desc; } intel_display_ids[] = { - INTEL_I830_IDS(&i830_display), - INTEL_I845G_IDS(&i845_display), - INTEL_I85X_IDS(&i85x_display), - INTEL_I865G_IDS(&i865g_display), - INTEL_I915G_IDS(&i915g_display), - INTEL_I915GM_IDS(&i915gm_display), - INTEL_I945G_IDS(&i945g_display), - INTEL_I945GM_IDS(&i945gm_display), - INTEL_I965G_IDS(&i965g_display), - INTEL_G33_IDS(&g33_display), - INTEL_I965GM_IDS(&i965gm_display), - INTEL_GM45_IDS(&gm45_display), - INTEL_G45_IDS(&g45_display), - INTEL_PINEVIEW_G_IDS(&pnv_display), - INTEL_PINEVIEW_M_IDS(&pnv_display), - INTEL_IRONLAKE_D_IDS(&ilk_d_display), - INTEL_IRONLAKE_M_IDS(&ilk_m_display), - INTEL_SNB_D_IDS(&snb_display), - INTEL_SNB_M_IDS(&snb_display), - INTEL_IVB_M_IDS(&ivb_display), - INTEL_IVB_D_IDS(&ivb_display), - INTEL_HSW_IDS(&hsw_display), - INTEL_VLV_IDS(&vlv_display), - INTEL_BDW_IDS(&bdw_display), - INTEL_CHV_IDS(&chv_display), - INTEL_SKL_IDS(&skl_display), - INTEL_BXT_IDS(&bxt_display), - INTEL_GLK_IDS(&glk_display), - INTEL_KBL_IDS(&skl_display), - INTEL_CFL_IDS(&skl_display), - INTEL_ICL_11_IDS(&icl_display), - INTEL_EHL_IDS(&jsl_ehl_display), - INTEL_JSL_IDS(&jsl_ehl_display), - INTEL_TGL_12_IDS(&tgl_display), - INTEL_DG1_IDS(&dg1_display), - INTEL_RKL_IDS(&rkl_display), - INTEL_ADLS_IDS(&adl_s_display), - INTEL_RPLS_IDS(&adl_s_display), - INTEL_ADLP_IDS(&xe_lpd_display), - INTEL_ADLN_IDS(&xe_lpd_display), - INTEL_RPLP_IDS(&xe_lpd_display), - INTEL_DG2_IDS(&xe_hpd_display), - - /* - * Do not add any GMD_ID-based platforms to this list. They will - * be probed automatically based on the IP version reported by - * the hardware. - */ + INTEL_I830_IDS(INTEL_DISPLAY_DEVICE, &i830_desc), + INTEL_I845G_IDS(INTEL_DISPLAY_DEVICE, &i845_desc), + INTEL_I85X_IDS(INTEL_DISPLAY_DEVICE, &i85x_desc), + INTEL_I865G_IDS(INTEL_DISPLAY_DEVICE, &i865g_desc), + INTEL_I915G_IDS(INTEL_DISPLAY_DEVICE, &i915g_desc), + INTEL_I915GM_IDS(INTEL_DISPLAY_DEVICE, &i915gm_desc), + INTEL_I945G_IDS(INTEL_DISPLAY_DEVICE, &i945g_desc), + INTEL_I945GM_IDS(INTEL_DISPLAY_DEVICE, &i945gm_desc), + INTEL_I965G_IDS(INTEL_DISPLAY_DEVICE, &i965g_desc), + INTEL_G33_IDS(INTEL_DISPLAY_DEVICE, &g33_desc), + INTEL_I965GM_IDS(INTEL_DISPLAY_DEVICE, &i965gm_desc), + INTEL_GM45_IDS(INTEL_DISPLAY_DEVICE, &gm45_desc), + INTEL_G45_IDS(INTEL_DISPLAY_DEVICE, &g45_desc), + INTEL_PNV_IDS(INTEL_DISPLAY_DEVICE, &pnv_desc), + INTEL_ILK_D_IDS(INTEL_DISPLAY_DEVICE, &ilk_d_desc), + INTEL_ILK_M_IDS(INTEL_DISPLAY_DEVICE, &ilk_m_desc), + INTEL_SNB_IDS(INTEL_DISPLAY_DEVICE, &snb_desc), + INTEL_IVB_IDS(INTEL_DISPLAY_DEVICE, &ivb_desc), + INTEL_HSW_IDS(INTEL_DISPLAY_DEVICE, &hsw_desc), + INTEL_VLV_IDS(INTEL_DISPLAY_DEVICE, &vlv_desc), + INTEL_BDW_IDS(INTEL_DISPLAY_DEVICE, &bdw_desc), + INTEL_CHV_IDS(INTEL_DISPLAY_DEVICE, &chv_desc), + INTEL_SKL_IDS(INTEL_DISPLAY_DEVICE, &skl_desc), + INTEL_BXT_IDS(INTEL_DISPLAY_DEVICE, &bxt_desc), + INTEL_GLK_IDS(INTEL_DISPLAY_DEVICE, &glk_desc), + INTEL_KBL_IDS(INTEL_DISPLAY_DEVICE, &kbl_desc), + INTEL_CFL_IDS(INTEL_DISPLAY_DEVICE, &cfl_desc), + INTEL_WHL_IDS(INTEL_DISPLAY_DEVICE, &cfl_desc), + INTEL_CML_IDS(INTEL_DISPLAY_DEVICE, &cml_desc), + INTEL_ICL_IDS(INTEL_DISPLAY_DEVICE, &icl_desc), + INTEL_EHL_IDS(INTEL_DISPLAY_DEVICE, &ehl_desc), + INTEL_JSL_IDS(INTEL_DISPLAY_DEVICE, &jsl_desc), + INTEL_TGL_IDS(INTEL_DISPLAY_DEVICE, &tgl_desc), + INTEL_DG1_IDS(INTEL_DISPLAY_DEVICE, &dg1_desc), + INTEL_RKL_IDS(INTEL_DISPLAY_DEVICE, &rkl_desc), + INTEL_ADLS_IDS(INTEL_DISPLAY_DEVICE, &adl_s_desc), + INTEL_RPLS_IDS(INTEL_DISPLAY_DEVICE, &adl_s_desc), + INTEL_ADLP_IDS(INTEL_DISPLAY_DEVICE, &adl_p_desc), + INTEL_ADLN_IDS(INTEL_DISPLAY_DEVICE, &adl_p_desc), + INTEL_RPLU_IDS(INTEL_DISPLAY_DEVICE, &adl_p_desc), + INTEL_RPLP_IDS(INTEL_DISPLAY_DEVICE, &adl_p_desc), + INTEL_DG2_IDS(INTEL_DISPLAY_DEVICE, &dg2_desc), + INTEL_MTL_IDS(INTEL_DISPLAY_DEVICE, &mtl_desc), + INTEL_LNL_IDS(INTEL_DISPLAY_DEVICE, &lnl_desc), + INTEL_BMG_IDS(INTEL_DISPLAY_DEVICE, &bmg_desc), }; static const struct { @@ -852,30 +1191,23 @@ static const struct { const struct intel_display_device_info *display; } gmdid_display_map[] = { { 14, 0, &xe_lpdp_display }, + { 14, 1, &xe2_hpd_display }, { 20, 0, &xe2_lpd_display }, }; static const struct intel_display_device_info * -probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step) +probe_gmdid_display(struct drm_i915_private *i915, struct intel_display_ip_ver *ip_ver) { struct pci_dev *pdev = to_pci_dev(i915->drm.dev); + struct intel_display_ip_ver gmd_id; void __iomem *addr; u32 val; int i; - /* The caller expects to ver, rel and step to be initialized - * here, and there's no good way to check when there was a - * failure and no_display was returned. So initialize all these - * values here zero, to be sure. - */ - *ver = 0; - *rel = 0; - *step = 0; - addr = pci_iomap_range(pdev, 0, i915_mmio_reg_offset(GMD_ID_DISPLAY), sizeof(u32)); if (!addr) { drm_err(&i915->drm, "Cannot map MMIO BAR to read display GMD_ID\n"); - return &no_display; + return NULL; } val = ioread32(addr); @@ -883,57 +1215,82 @@ probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step if (val == 0) { drm_dbg_kms(&i915->drm, "Device doesn't have display\n"); - return &no_display; + return NULL; } - *ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val); - *rel = REG_FIELD_GET(GMD_ID_RELEASE_MASK, val); - *step = REG_FIELD_GET(GMD_ID_STEP, val); + gmd_id.ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val); + gmd_id.rel = REG_FIELD_GET(GMD_ID_RELEASE_MASK, val); + gmd_id.step = REG_FIELD_GET(GMD_ID_STEP, val); - for (i = 0; i < ARRAY_SIZE(gmdid_display_map); i++) - if (*ver == gmdid_display_map[i].ver && - *rel == gmdid_display_map[i].rel) + for (i = 0; i < ARRAY_SIZE(gmdid_display_map); i++) { + if (gmd_id.ver == gmdid_display_map[i].ver && + gmd_id.rel == gmdid_display_map[i].rel) { + *ip_ver = gmd_id; return gmdid_display_map[i].display; + } + } drm_err(&i915->drm, "Unrecognized display IP version %d.%02d; disabling display.\n", - *ver, *rel); - return &no_display; + gmd_id.ver, gmd_id.rel); + return NULL; } -static const struct intel_display_device_info * -probe_display(struct drm_i915_private *i915) +static const struct platform_desc *find_platform_desc(struct pci_dev *pdev) { - struct pci_dev *pdev = to_pci_dev(i915->drm.dev); int i; - if (has_no_display(pdev)) { - drm_dbg_kms(&i915->drm, "Device doesn't have display\n"); - return &no_display; - } - for (i = 0; i < ARRAY_SIZE(intel_display_ids); i++) { if (intel_display_ids[i].devid == pdev->device) - return intel_display_ids[i].info; + return intel_display_ids[i].desc; } - drm_dbg(&i915->drm, "No display ID found for device ID %04x; disabling display.\n", - pdev->device); + return NULL; +} + +static const struct subplatform_desc * +find_subplatform_desc(struct pci_dev *pdev, const struct platform_desc *desc) +{ + const struct subplatform_desc *sp; + const u16 *id; + + for (sp = desc->subplatforms; sp && sp->subplatform; sp++) + for (id = sp->pciidlist; *id; id++) + if (*id == pdev->device) + return sp; - return &no_display; + return NULL; } void intel_display_device_probe(struct drm_i915_private *i915) { + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); const struct intel_display_device_info *info; - u16 ver, rel, step; + struct intel_display_ip_ver ip_ver = {}; + const struct platform_desc *desc; + const struct subplatform_desc *subdesc; /* Add drm device backpointer as early as possible. */ i915->display.drm = &i915->drm; - if (HAS_GMD_ID(i915)) - info = probe_gmdid_display(i915, &ver, &rel, &step); - else - info = probe_display(i915); + intel_display_params_copy(&i915->display.params); + + if (has_no_display(pdev)) { + drm_dbg_kms(&i915->drm, "Device doesn't have display\n"); + goto no_display; + } + + desc = find_platform_desc(pdev); + if (!desc) { + drm_dbg_kms(&i915->drm, "Unknown device ID %04x; disabling display.\n", + pdev->device); + goto no_display; + } + + info = desc->info; + if (!info) + info = probe_gmdid_display(i915, &ip_ver); + if (!info) + goto no_display; DISPLAY_INFO(i915) = info; @@ -941,13 +1298,27 @@ void intel_display_device_probe(struct drm_i915_private *i915) &DISPLAY_INFO(i915)->__runtime_defaults, sizeof(*DISPLAY_RUNTIME_INFO(i915))); - if (HAS_GMD_ID(i915)) { - DISPLAY_RUNTIME_INFO(i915)->ip.ver = ver; - DISPLAY_RUNTIME_INFO(i915)->ip.rel = rel; - DISPLAY_RUNTIME_INFO(i915)->ip.step = step; + drm_WARN_ON(&i915->drm, !desc->platform || !desc->name); + DISPLAY_RUNTIME_INFO(i915)->platform = desc->platform; + + subdesc = find_subplatform_desc(pdev, desc); + if (subdesc) { + drm_WARN_ON(&i915->drm, !subdesc->subplatform || !subdesc->name); + DISPLAY_RUNTIME_INFO(i915)->subplatform = subdesc->subplatform; } - intel_display_params_copy(&i915->display.params); + if (ip_ver.ver || ip_ver.rel || ip_ver.step) + DISPLAY_RUNTIME_INFO(i915)->ip = ip_ver; + + drm_info(&i915->drm, "Found %s%s%s (device ID %04x) display version %u.%02u\n", + desc->name, subdesc ? "/" : "", subdesc ? subdesc->name : "", + pdev->device, DISPLAY_RUNTIME_INFO(i915)->ip.ver, + DISPLAY_RUNTIME_INFO(i915)->ip.rel); + + return; + +no_display: + DISPLAY_INFO(i915) = &no_display; } void intel_display_device_remove(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index 17ddf82f0b6e..13453ea4daea 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -14,6 +14,89 @@ struct drm_i915_private; struct drm_printer; +/* Keep in gen based order, and chronological order within a gen */ +enum intel_display_platform { + INTEL_DISPLAY_PLATFORM_UNINITIALIZED = 0, + /* Display ver 2 */ + INTEL_DISPLAY_I830, + INTEL_DISPLAY_I845G, + INTEL_DISPLAY_I85X, + INTEL_DISPLAY_I865G, + /* Display ver 3 */ + INTEL_DISPLAY_I915G, + INTEL_DISPLAY_I915GM, + INTEL_DISPLAY_I945G, + INTEL_DISPLAY_I945GM, + INTEL_DISPLAY_G33, + INTEL_DISPLAY_PINEVIEW, + /* Display ver 4 */ + INTEL_DISPLAY_I965G, + INTEL_DISPLAY_I965GM, + INTEL_DISPLAY_G45, + INTEL_DISPLAY_GM45, + /* Display ver 5 */ + INTEL_DISPLAY_IRONLAKE, + /* Display ver 6 */ + INTEL_DISPLAY_SANDYBRIDGE, + /* Display ver 7 */ + INTEL_DISPLAY_IVYBRIDGE, + INTEL_DISPLAY_VALLEYVIEW, + INTEL_DISPLAY_HASWELL, + /* Display ver 8 */ + INTEL_DISPLAY_BROADWELL, + INTEL_DISPLAY_CHERRYVIEW, + /* Display ver 9 */ + INTEL_DISPLAY_SKYLAKE, + INTEL_DISPLAY_BROXTON, + INTEL_DISPLAY_KABYLAKE, + INTEL_DISPLAY_GEMINILAKE, + INTEL_DISPLAY_COFFEELAKE, + INTEL_DISPLAY_COMETLAKE, + /* Display ver 11 */ + INTEL_DISPLAY_ICELAKE, + INTEL_DISPLAY_JASPERLAKE, + INTEL_DISPLAY_ELKHARTLAKE, + /* Display ver 12 */ + INTEL_DISPLAY_TIGERLAKE, + INTEL_DISPLAY_ROCKETLAKE, + INTEL_DISPLAY_DG1, + INTEL_DISPLAY_ALDERLAKE_S, + /* Display ver 13 */ + INTEL_DISPLAY_ALDERLAKE_P, + INTEL_DISPLAY_DG2, + /* Display ver 14 (based on GMD ID) */ + INTEL_DISPLAY_METEORLAKE, + /* Display ver 20 (based on GMD ID) */ + INTEL_DISPLAY_LUNARLAKE, + /* Display ver 14.1 (based on GMD ID) */ + INTEL_DISPLAY_BATTLEMAGE, +}; + +enum intel_display_subplatform { + INTEL_DISPLAY_SUBPLATFORM_UNINITIALIZED = 0, + INTEL_DISPLAY_HASWELL_ULT, + INTEL_DISPLAY_HASWELL_ULX, + INTEL_DISPLAY_BROADWELL_ULT, + INTEL_DISPLAY_BROADWELL_ULX, + INTEL_DISPLAY_SKYLAKE_ULT, + INTEL_DISPLAY_SKYLAKE_ULX, + INTEL_DISPLAY_KABYLAKE_ULT, + INTEL_DISPLAY_KABYLAKE_ULX, + INTEL_DISPLAY_COFFEELAKE_ULT, + INTEL_DISPLAY_COFFEELAKE_ULX, + INTEL_DISPLAY_COMETLAKE_ULT, + INTEL_DISPLAY_COMETLAKE_ULX, + INTEL_DISPLAY_ICELAKE_PORT_F, + INTEL_DISPLAY_TIGERLAKE_UY, + INTEL_DISPLAY_ALDERLAKE_S_RAPTORLAKE_S, + INTEL_DISPLAY_ALDERLAKE_P_ALDERLAKE_N, + INTEL_DISPLAY_ALDERLAKE_P_RAPTORLAKE_P, + INTEL_DISPLAY_ALDERLAKE_P_RAPTORLAKE_U, + INTEL_DISPLAY_DG2_G10, + INTEL_DISPLAY_DG2_G11, + INTEL_DISPLAY_DG2_G12, +}; + #define DEV_INFO_DISPLAY_FOR_EACH_FLAG(func) \ /* Keep in alphabetical order */ \ func(cursor_needs_physical); \ @@ -71,6 +154,7 @@ struct drm_printer; BIT(trans)) != 0) #define HAS_VRR(i915) (DISPLAY_VER(i915) >= 11) #define HAS_AS_SDP(i915) (DISPLAY_VER(i915) >= 13) +#define HAS_CMRR(i915) (DISPLAY_VER(i915) >= 20) #define INTEL_NUM_PIPES(i915) (hweight8(DISPLAY_RUNTIME_INFO(i915)->pipe_mask)) #define I915_HAS_HOTPLUG(i915) (DISPLAY_INFO(i915)->has_hotplug) #define OVERLAY_NEEDS_PHYSICAL(i915) (DISPLAY_INFO(i915)->overlay_needs_physical) @@ -111,7 +195,10 @@ struct drm_printer; (DISPLAY_VER(i915) >= (from) && DISPLAY_VER(i915) <= (until)) struct intel_display_runtime_info { - struct { + enum intel_display_platform platform; + enum intel_display_subplatform subplatform; + + struct intel_display_ip_ver { u16 ver; u16 rel; u16 step; diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index c337e0597541..82e1369e5d76 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -18,6 +18,7 @@ #include "intel_fifo_underrun.h" #include "intel_gmbus.h" #include "intel_hotplug_irq.h" +#include "intel_pipe_crc_regs.h" #include "intel_pmdemand.h" #include "intel_psr.h" #include "intel_psr_regs.h" @@ -224,7 +225,7 @@ out: void i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 status_mask) { - i915_reg_t reg = PIPESTAT(pipe); + i915_reg_t reg = PIPESTAT(dev_priv, pipe); u32 enable_mask; drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, @@ -247,7 +248,7 @@ void i915_enable_pipestat(struct drm_i915_private *dev_priv, void i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 status_mask) { - i915_reg_t reg = PIPESTAT(pipe); + i915_reg_t reg = PIPESTAT(dev_priv, pipe); u32 enable_mask; drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, @@ -356,7 +357,7 @@ static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) { display_pipe_crc_irq_handler(dev_priv, pipe, - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), + intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_HSW(pipe)), 0, 0, 0, 0); } @@ -377,19 +378,21 @@ static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, u32 res1, res2; if (DISPLAY_VER(dev_priv) >= 3) - res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe)); + res1 = intel_uncore_read(&dev_priv->uncore, + PIPE_CRC_RES_RES1_I915(dev_priv, pipe)); else res1 = 0; if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) - res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe)); + res2 = intel_uncore_read(&dev_priv->uncore, + PIPE_CRC_RES_RES2_G4X(dev_priv, pipe)); else res2 = 0; display_pipe_crc_irq_handler(dev_priv, pipe, - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)), + intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(dev_priv, pipe)), + intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(dev_priv, pipe)), + intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(dev_priv, pipe)), res1, res2); } @@ -398,7 +401,8 @@ void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) enum pipe pipe; for_each_pipe(dev_priv, pipe) { - intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe), + intel_uncore_write(&dev_priv->uncore, + PIPESTAT(dev_priv, pipe), PIPESTAT_INT_STATUS_MASK | PIPE_FIFO_UNDERRUN_STATUS); @@ -451,7 +455,7 @@ void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, if (!status_mask) continue; - reg = PIPESTAT(pipe); + reg = PIPESTAT(dev_priv, pipe); pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask; enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); @@ -876,7 +880,8 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) struct intel_dp *intel_dp = enc_to_intel_dp(encoder); if (DISPLAY_VER(dev_priv) >= 12) - iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder); + iir_reg = TRANS_PSR_IIR(dev_priv, + intel_dp->psr.transcoder); else iir_reg = EDP_PSR_IIR; @@ -909,7 +914,8 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, * Incase of dual link, TE comes from DSI_1 * this is to check if dual link is enabled */ - val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0)); + val = intel_uncore_read(&dev_priv->uncore, + TRANS_DDI_FUNC_CTL2(dev_priv, TRANSCODER_DSI_0)); val &= PORT_SYNC_MODE_ENABLE; /* @@ -930,7 +936,8 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, } /* Get PIPE for handling VBLANK event */ - val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans)); + val = intel_uncore_read(&dev_priv->uncore, + TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans)); switch (val & TRANS_DDI_EDP_INPUT_MASK) { case TRANS_DDI_EDP_INPUT_A_ON: pipe = PIPE_A; @@ -1374,7 +1381,7 @@ void vlv_display_irq_reset(struct drm_i915_private *dev_priv) intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); - intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0); + intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT(dev_priv), 0, 0); i9xx_pipestat_irq_reset(dev_priv); @@ -1455,8 +1462,12 @@ void gen11_display_irq_reset(struct drm_i915_private *dev_priv) if (!intel_display_power_is_enabled(dev_priv, domain)) continue; - intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff); - intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff); + intel_uncore_write(uncore, + TRANS_PSR_IMR(dev_priv, trans), + 0xffffffff); + intel_uncore_write(uncore, + TRANS_PSR_IIR(dev_priv, trans), + 0xffffffff); } } else { intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); @@ -1688,7 +1699,8 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) if (!intel_display_power_is_enabled(dev_priv, domain)) continue; - gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans)); + gen3_assert_iir_is_zero(uncore, + TRANS_PSR_IIR(dev_priv, trans)); } } else { gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); diff --git a/drivers/gpu/drm/i915/display/intel_display_limits.h b/drivers/gpu/drm/i915/display/intel_display_limits.h index 5126d0b5ae5d..c4775c99dc83 100644 --- a/drivers/gpu/drm/i915/display/intel_display_limits.h +++ b/drivers/gpu/drm/i915/display/intel_display_limits.h @@ -60,16 +60,23 @@ enum transcoder { * (eg. PLANE_CTL(), PS_PLANE_SEL(), etc.) so adjust with care. */ enum plane_id { - PLANE_PRIMARY, - PLANE_SPRITE0, - PLANE_SPRITE1, - PLANE_SPRITE2, - PLANE_SPRITE3, - PLANE_SPRITE4, - PLANE_SPRITE5, + /* skl+ universal plane names */ + PLANE_1, + PLANE_2, + PLANE_3, + PLANE_4, + PLANE_5, + PLANE_6, + PLANE_7, + PLANE_CURSOR, I915_MAX_PLANES, + + /* pre-skl plane names */ + PLANE_PRIMARY = PLANE_1, + PLANE_SPRITE0, + PLANE_SPRITE1, }; enum port { diff --git a/drivers/gpu/drm/i915/display/intel_display_params.c b/drivers/gpu/drm/i915/display/intel_display_params.c index 1799a6643128..79107607a6ff 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.c +++ b/drivers/gpu/drm/i915/display/intel_display_params.c @@ -116,7 +116,7 @@ intel_display_param_named(psr_safest_params, bool, 0400, "Default: 0"); intel_display_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, - "Enable PSR2 selective fetch " + "Enable PSR2 and Panel Replay selective fetch " "(0=disabled, 1=enabled) " "Default: 1"); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 03dc7edcc443..e288a1b21d7e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -675,6 +675,12 @@ intel_display_power_put_async_work(struct work_struct *work) release_async_put_domains(power_domains, &power_domains->async_put_domains[0]); + /* + * Cancel the work that got queued after this one got dequeued, + * since here we released the corresponding async-put reference. + */ + cancel_async_put_work(power_domains, false); + /* Requeue the work if more domains were async put meanwhile. */ if (!bitmap_empty(power_domains->async_put_domains[1].bits, POWER_DOMAIN_NUM)) { bitmap_copy(power_domains->async_put_domains[0].bits, @@ -686,12 +692,6 @@ intel_display_power_put_async_work(struct work_struct *work) fetch_and_zero(&new_work_wakeref), power_domains->async_put_next_delay); power_domains->async_put_next_delay = 0; - } else { - /* - * Cancel the work that got queued after this one got dequeued, - * since here we released the corresponding async-put reference. - */ - cancel_async_put_work(power_domains, false); } out_verify: @@ -1207,7 +1207,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) intel_de_read(dev_priv, WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n"); I915_STATE_WARN(dev_priv, - intel_de_read(dev_priv, PP_STATUS(0)) & PP_ON, + intel_de_read(dev_priv, PP_STATUS(dev_priv, 0)) & PP_ON, "Panel power on\n"); I915_STATE_WARN(dev_priv, intel_de_read(dev_priv, BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE, @@ -1688,6 +1688,10 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, if (IS_DG2(dev_priv)) intel_snps_phy_wait_for_calibration(dev_priv); + /* 9. XE2_HPD: Program CHICKEN_MISC_2 before any cursor or planes are enabled */ + if (DISPLAY_VER_FULL(dev_priv) == IP_VER(14, 1)) + intel_de_rmw(dev_priv, CHICKEN_MISC_2, BMG_DARB_HALF_BLK_END_BURST, 1); + if (resume) intel_dmc_load_program(dev_priv); @@ -1768,7 +1772,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv) * current lane status. */ if (intel_power_well_is_enabled(dev_priv, cmn_bc)) { - u32 status = intel_de_read(dev_priv, DPLL(PIPE_A)); + u32 status = intel_de_read(dev_priv, DPLL(dev_priv, PIPE_A)); unsigned int mask; mask = status & DPLL_PORTB_READY_MASK; diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index 83f616097a29..919f712fef13 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -1044,9 +1044,9 @@ static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv, static void i830_pipes_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - if ((intel_de_read(dev_priv, TRANSCONF(PIPE_A)) & TRANSCONF_ENABLE) == 0) + if ((intel_de_read(dev_priv, TRANSCONF(dev_priv, PIPE_A)) & TRANSCONF_ENABLE) == 0) i830_enable_pipe(dev_priv, PIPE_A); - if ((intel_de_read(dev_priv, TRANSCONF(PIPE_B)) & TRANSCONF_ENABLE) == 0) + if ((intel_de_read(dev_priv, TRANSCONF(dev_priv, PIPE_B)) & TRANSCONF_ENABLE) == 0) i830_enable_pipe(dev_priv, PIPE_B); } @@ -1060,8 +1060,8 @@ static void i830_pipes_power_well_disable(struct drm_i915_private *dev_priv, static bool i830_pipes_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - return intel_de_read(dev_priv, TRANSCONF(PIPE_A)) & TRANSCONF_ENABLE && - intel_de_read(dev_priv, TRANSCONF(PIPE_B)) & TRANSCONF_ENABLE; + return intel_de_read(dev_priv, TRANSCONF(dev_priv, PIPE_A)) & TRANSCONF_ENABLE && + intel_de_read(dev_priv, TRANSCONF(dev_priv, PIPE_B)) & TRANSCONF_ENABLE; } static void i830_pipes_power_well_sync_hw(struct drm_i915_private *dev_priv, @@ -1196,13 +1196,13 @@ static void vlv_display_power_well_init(struct drm_i915_private *dev_priv) * CHV DPLL B/C have some issues if VGA mode is enabled. */ for_each_pipe(dev_priv, pipe) { - u32 val = intel_de_read(dev_priv, DPLL(pipe)); + u32 val = intel_de_read(dev_priv, DPLL(dev_priv, pipe)); val |= DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; if (pipe != PIPE_A) val |= DPLL_INTEGRATED_CRI_CLK_VLV; - intel_de_write(dev_priv, DPLL(pipe), val); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), val); } vlv_init_display_clock_gating(dev_priv); @@ -1355,7 +1355,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv) */ if (BITS_SET(phy_control, PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)) && - (intel_de_read(dev_priv, DPLL(PIPE_B)) & DPLL_VCO_ENABLE) == 0) + (intel_de_read(dev_priv, DPLL(dev_priv, PIPE_B)) & DPLL_VCO_ENABLE) == 0) phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1); if (BITS_SET(phy_control, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 62f7a30c37dc..8fe7942511f8 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -44,9 +44,10 @@ #include <drm/drm_rect.h> #include <drm/drm_vblank.h> #include <drm/drm_vblank_work.h> -#include <drm/i915_hdcp_interface.h> +#include <drm/intel/i915_hdcp_interface.h> #include <media/cec-notifier.h> +#include "gem/i915_gem_object_types.h" /* for to_intel_bo() */ #include "i915_vma.h" #include "i915_vma_types.h" #include "intel_bios.h" @@ -160,6 +161,11 @@ struct intel_encoder { enum port port; u16 cloneable; u8 pipe_mask; + + /* Check and recover a bad link state. */ + struct delayed_work link_check_work; + void (*link_check)(struct intel_encoder *encoder); + enum intel_hotplug_state (*hotplug)(struct intel_encoder *encoder, struct intel_connector *connector); enum intel_output_type (*compute_output_type)(struct intel_encoder *, @@ -305,7 +311,7 @@ enum drrs_type { }; struct intel_vbt_panel_data { - struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ + struct drm_display_mode *lfp_vbt_mode; /* if any */ struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ /* Feature bits */ @@ -329,6 +335,7 @@ struct intel_vbt_panel_data { u8 drrs_msa_timing_delay; bool low_vswing; bool hobl; + bool dsc_disable; } edp; struct { @@ -401,7 +408,12 @@ struct intel_panel { } vesa; struct { bool sdr_uses_aux; - } intel; + bool supports_2084_decode; + bool supports_2020_gamut; + bool supports_segmented_backlight; + bool supports_sdp_colorimetry; + bool supports_tone_mapping; + } intel_cap; } edp; struct backlight_device *device; @@ -1042,7 +1054,7 @@ struct intel_crtc_state { * * During initial hw readout, they need to be copied to uapi. * - * Bigjoiner will allow a transcoder mode that spans 2 pipes; + * Joiner will allow a transcoder mode that spans 2 pipes; * Use the pipe_mode for calculations like watermarks, pipe * scaler, and bandwidth. * @@ -1189,7 +1201,7 @@ struct intel_crtc_state { /* PSR is supported but might not be enabled due the lack of enabled planes */ bool has_psr; - bool has_psr2; + bool has_sel_update; bool enable_psr2_sel_fetch; bool enable_psr2_su_region_et; bool req_psr2_sdp_prior_scanline; @@ -1338,8 +1350,8 @@ struct intel_crtc_state { /* enable vlv/chv wgc csc? */ bool wgc_enable; - /* big joiner pipe bitmask */ - u8 bigjoiner_pipes; + /* joiner pipe bitmask */ + u8 joiner_pipes; /* Display Stream compression state */ struct { @@ -1396,6 +1408,12 @@ struct intel_crtc_state { u32 vsync_end, vsync_start; } vrr; + /* Content Match Refresh Rate state */ + struct { + bool enable; + u64 cmrr_n, cmrr_m; + } cmrr; + /* Stream Splitter for eDP MSO */ struct { bool enable; @@ -1405,6 +1423,9 @@ struct intel_crtc_state { /* for loading single buffered registers during vblank */ struct drm_vblank_work vblank_work; + + /* LOBF flag */ + bool has_lobf; }; enum intel_pipe_crc_source { @@ -1521,7 +1542,7 @@ struct intel_plane { enum i9xx_plane_id i9xx_plane; enum plane_id id; enum pipe pipe; - bool need_async_flip_disable_wa; + bool need_async_flip_toggle_wa; u32 frontbuffer_bit; struct { @@ -1682,6 +1703,7 @@ struct intel_psr { #define I915_PSR_DEBUG_ENABLE_SEL_FETCH 0x4 #define I915_PSR_DEBUG_IRQ 0x10 #define I915_PSR_DEBUG_SU_REGION_ET_DISABLE 0x20 +#define I915_PSR_DEBUG_PANEL_REPLAY_DISABLE 0x40 u32 debug; bool sink_support; @@ -1695,22 +1717,12 @@ struct intel_psr { unsigned int busy_frontbuffer_bits; bool sink_psr2_support; bool link_standby; - bool psr2_enabled; + bool sel_update_enabled; bool psr2_sel_fetch_enabled; bool psr2_sel_fetch_cff_enabled; + bool su_region_et_enabled; bool req_psr2_sdp_prior_scanline; u8 sink_sync_latency; - - struct { - u8 io_wake_lines; - u8 fast_wake_lines; - - /* LNL and beyond */ - u8 check_entry_lines; - u8 silence_period_sym_clocks; - u8 lfps_half_cycle_num_of_syms; - } alpm_parameters; - ktime_t last_entry_attempt; ktime_t last_exit; bool sink_not_reliable; @@ -1719,6 +1731,7 @@ struct intel_psr { u16 su_y_granularity; bool source_panel_replay_support; bool sink_panel_replay_support; + bool sink_panel_replay_su_support; bool panel_replay_enabled; u32 dc3co_exitline; u32 dc3co_exit_delay; @@ -1733,10 +1746,10 @@ struct intel_dp { u8 lane_count; u8 sink_count; bool link_trained; - bool reset_link_params; bool use_max_params; u8 dpcd[DP_RECEIVER_CAP_SIZE]; u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE]; + u8 pr_dpcd; u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE]; u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE]; @@ -1754,10 +1767,21 @@ struct intel_dp { /* intersection of source and sink rates */ int num_common_rates; int common_rates[DP_MAX_SUPPORTED_RATES]; - /* Max lane count for the current link */ - int max_link_lane_count; - /* Max rate for the current link */ - int max_link_rate; + struct { + /* TODO: move the rest of link specific fields to here */ + /* Max lane count for the current link */ + int max_lane_count; + /* Max rate for the current link */ + int max_rate; + int force_lane_count; + int force_rate; + bool retrain_disabled; + /* Sequential link training failures after a passing LT */ + int seq_train_failures; + int force_train_failure; + bool force_retrain; + } link; + bool reset_link_params; int mso_link_count; int mso_pixel_overlap; /* sink or branch descriptor */ @@ -1840,6 +1864,19 @@ struct intel_dp { unsigned long last_oui_write; bool colorimetry_support; + + struct { + u8 io_wake_lines; + u8 fast_wake_lines; + + /* LNL and beyond */ + u8 check_entry_lines; + u8 aux_less_wake_lines; + u8 silence_period_sym_clocks; + u8 lfps_half_cycle_num_of_syms; + } alpm_parameters; + + u8 alpm_dpcd; }; enum lspcon_vendor { diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.c b/drivers/gpu/drm/i915/display/intel_dkl_phy.c index a001232ad445..b146b4c46943 100644 --- a/drivers/gpu/drm/i915/display/intel_dkl_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.c @@ -4,7 +4,6 @@ */ #include "i915_drv.h" -#include "i915_reg.h" #include "intel_de.h" #include "intel_display.h" diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index cbd2ac5671b1..73977b173898 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -30,6 +30,7 @@ #include "intel_de.h" #include "intel_dmc.h" #include "intel_dmc_regs.h" +#include "intel_step.h" /** * DOC: DMC Firmware Support @@ -115,6 +116,9 @@ static bool dmc_firmware_param_disabled(struct drm_i915_private *i915) #define XE2LPD_DMC_PATH DMC_PATH(xe2lpd) MODULE_FIRMWARE(XE2LPD_DMC_PATH); +#define BMG_DMC_PATH DMC_PATH(bmg) +MODULE_FIRMWARE(BMG_DMC_PATH); + #define MTL_DMC_PATH DMC_PATH(mtl) MODULE_FIRMWARE(MTL_DMC_PATH); @@ -166,6 +170,9 @@ static const char *dmc_firmware_default(struct drm_i915_private *i915, u32 *size if (DISPLAY_VER_FULL(i915) == IP_VER(20, 0)) { fw_path = XE2LPD_DMC_PATH; max_fw_size = XE2LPD_DMC_MAX_FW_SIZE; + } else if (DISPLAY_VER_FULL(i915) == IP_VER(14, 1)) { + fw_path = BMG_DMC_PATH; + max_fw_size = XELPDP_DMC_MAX_FW_SIZE; } else if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0)) { fw_path = MTL_DMC_PATH; max_fw_size = XELPDP_DMC_MAX_FW_SIZE; @@ -1177,7 +1184,7 @@ void intel_dmc_fini(struct drm_i915_private *i915) } } -void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m, +void intel_dmc_print_error_state(struct drm_printer *p, struct drm_i915_private *i915) { struct intel_dmc *dmc = i915_to_dmc(i915); @@ -1185,13 +1192,13 @@ void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m, if (!HAS_DMC(i915)) return; - i915_error_printf(m, "DMC initialized: %s\n", str_yes_no(dmc)); - i915_error_printf(m, "DMC loaded: %s\n", - str_yes_no(intel_dmc_has_payload(i915))); + drm_printf(p, "DMC initialized: %s\n", str_yes_no(dmc)); + drm_printf(p, "DMC loaded: %s\n", + str_yes_no(intel_dmc_has_payload(i915))); if (dmc) - i915_error_printf(m, "DMC fw version: %d.%d\n", - DMC_VERSION_MAJOR(dmc->version), - DMC_VERSION_MINOR(dmc->version)); + drm_printf(p, "DMC fw version: %d.%d\n", + DMC_VERSION_MAJOR(dmc->version), + DMC_VERSION_MINOR(dmc->version)); } static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index fd607afff2ef..54cff6002e31 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -8,9 +8,9 @@ #include <linux/types.h> -struct drm_i915_error_state_buf; -struct drm_i915_private; enum pipe; +struct drm_i915_private; +struct drm_printer; void intel_dmc_init(struct drm_i915_private *i915); void intel_dmc_load_program(struct drm_i915_private *i915); @@ -22,7 +22,7 @@ void intel_dmc_suspend(struct drm_i915_private *i915); void intel_dmc_resume(struct drm_i915_private *i915); bool intel_dmc_has_payload(struct drm_i915_private *i915); void intel_dmc_debugfs_register(struct drm_i915_private *i915); -void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m, +void intel_dmc_print_error_state(struct drm_printer *p, struct drm_i915_private *i915); void assert_dmc_loaded(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index e05e25cd4a94..3903f6ead6e6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -48,6 +48,7 @@ #include "i915_drv.h" #include "i915_irq.h" #include "i915_reg.h" +#include "intel_alpm.h" #include "intel_atomic.h" #include "intel_audio.h" #include "intel_backlight.h" @@ -68,6 +69,7 @@ #include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_drrs.h" +#include "intel_encoder.h" #include "intel_fifo_underrun.h" #include "intel_hdcp.h" #include "intel_hdmi.h" @@ -75,6 +77,7 @@ #include "intel_hotplug_irq.h" #include "intel_lspcon.h" #include "intel_lvds.h" +#include "intel_modeset_lock.h" #include "intel_panel.h" #include "intel_pch_display.h" #include "intel_pps.h" @@ -329,7 +332,7 @@ static int intel_dp_common_len_rate_limit(const struct intel_dp *intel_dp, intel_dp->num_common_rates, max_rate); } -static int intel_dp_common_rate(struct intel_dp *intel_dp, int index) +int intel_dp_common_rate(struct intel_dp *intel_dp, int index) { if (drm_WARN_ON(&dp_to_i915(intel_dp)->drm, index < 0 || index >= intel_dp->num_common_rates)) @@ -344,7 +347,7 @@ int intel_dp_max_common_rate(struct intel_dp *intel_dp) return intel_dp_common_rate(intel_dp, intel_dp->num_common_rates - 1); } -static int intel_dp_max_source_lane_count(struct intel_digital_port *dig_port) +int intel_dp_max_source_lane_count(struct intel_digital_port *dig_port) { int vbt_max_lanes = intel_bios_dp_max_lane_count(dig_port->base.devdata); int max_lanes = dig_port->max_lanes; @@ -370,19 +373,39 @@ int intel_dp_max_common_lane_count(struct intel_dp *intel_dp) return min3(source_max, sink_max, lane_max); } +static int forced_lane_count(struct intel_dp *intel_dp) +{ + return clamp(intel_dp->link.force_lane_count, 1, intel_dp_max_common_lane_count(intel_dp)); +} + int intel_dp_max_lane_count(struct intel_dp *intel_dp) { - switch (intel_dp->max_link_lane_count) { + int lane_count; + + if (intel_dp->link.force_lane_count) + lane_count = forced_lane_count(intel_dp); + else + lane_count = intel_dp->link.max_lane_count; + + switch (lane_count) { case 1: case 2: case 4: - return intel_dp->max_link_lane_count; + return lane_count; default: - MISSING_CASE(intel_dp->max_link_lane_count); + MISSING_CASE(lane_count); return 1; } } +static int intel_dp_min_lane_count(struct intel_dp *intel_dp) +{ + if (intel_dp->link.force_lane_count) + return forced_lane_count(intel_dp); + + return 1; +} + /* * The required data bandwidth for a mode with given pixel clock and bpp. This * is the required net bandwidth independent of the data bandwidth efficiency. @@ -436,12 +459,16 @@ int intel_dp_max_link_data_rate(struct intel_dp *intel_dp, return max_rate; } -bool intel_dp_has_bigjoiner(struct intel_dp *intel_dp) +bool intel_dp_has_joiner(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_encoder *encoder = &intel_dig_port->base; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + /* eDP MSO is not compatible with joiner */ + if (intel_dp->mso_link_count) + return false; + return DISPLAY_VER(dev_priv) >= 12 || (DISPLAY_VER(dev_priv) == 11 && encoder->port != PORT_A); @@ -477,6 +504,9 @@ static int mtl_max_source_rate(struct intel_dp *intel_dp) if (intel_encoder_is_c10phy(encoder)) return 810000; + if (DISPLAY_VER_FULL(to_i915(encoder->base.dev)) == IP_VER(14, 1)) + return 1350000; + return 2000000; } @@ -601,7 +631,7 @@ static int intersect_rates(const int *source_rates, int source_len, } /* return index of rate in rates array, or -1 if not found */ -static int intel_dp_rate_index(const int *rates, int len, int rate) +int intel_dp_rate_index(const int *rates, int len, int rate) { int i; @@ -641,7 +671,7 @@ static bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate, * boot-up. */ if (link_rate == 0 || - link_rate > intel_dp->max_link_rate) + link_rate > intel_dp->link.max_rate) return false; if (lane_count == 0 || @@ -651,78 +681,6 @@ static bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate, return true; } -static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp, - int link_rate, - u8 lane_count) -{ - /* FIXME figure out what we actually want here */ - const struct drm_display_mode *fixed_mode = - intel_panel_preferred_fixed_mode(intel_dp->attached_connector); - int mode_rate, max_rate; - - mode_rate = intel_dp_link_required(fixed_mode->clock, 18); - max_rate = intel_dp_max_link_data_rate(intel_dp, link_rate, lane_count); - if (mode_rate > max_rate) - return false; - - return true; -} - -int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, - int link_rate, u8 lane_count) -{ - struct drm_i915_private *i915 = dp_to_i915(intel_dp); - int index; - - /* - * TODO: Enable fallback on MST links once MST link compute can handle - * the fallback params. - */ - if (intel_dp->is_mst) { - drm_err(&i915->drm, "Link Training Unsuccessful\n"); - return -1; - } - - if (intel_dp_is_edp(intel_dp) && !intel_dp->use_max_params) { - drm_dbg_kms(&i915->drm, - "Retrying Link training for eDP with max parameters\n"); - intel_dp->use_max_params = true; - return 0; - } - - index = intel_dp_rate_index(intel_dp->common_rates, - intel_dp->num_common_rates, - link_rate); - if (index > 0) { - if (intel_dp_is_edp(intel_dp) && - !intel_dp_can_link_train_fallback_for_edp(intel_dp, - intel_dp_common_rate(intel_dp, index - 1), - lane_count)) { - drm_dbg_kms(&i915->drm, - "Retrying Link training for eDP with same parameters\n"); - return 0; - } - intel_dp->max_link_rate = intel_dp_common_rate(intel_dp, index - 1); - intel_dp->max_link_lane_count = lane_count; - } else if (lane_count > 1) { - if (intel_dp_is_edp(intel_dp) && - !intel_dp_can_link_train_fallback_for_edp(intel_dp, - intel_dp_max_common_rate(intel_dp), - lane_count >> 1)) { - drm_dbg_kms(&i915->drm, - "Retrying Link training for eDP with same parameters\n"); - return 0; - } - intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); - intel_dp->max_link_lane_count = lane_count >> 1; - } else { - drm_err(&i915->drm, "Link Training Unsuccessful\n"); - return -1; - } - - return 0; -} - u32 intel_dp_mode_to_fec_clock(u32 mode_clock) { return div_u64(mul_u32_u32(mode_clock, DP_DSC_FEC_OVERHEAD_FACTOR), @@ -1204,19 +1162,39 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, return MODE_OK; } -bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, - struct intel_connector *connector, - int hdisplay, int clock) +bool intel_dp_need_joiner(struct intel_dp *intel_dp, + struct intel_connector *connector, + int hdisplay, int clock) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); - if (!intel_dp_has_bigjoiner(intel_dp)) + if (!intel_dp_has_joiner(intel_dp)) return false; return clock > i915->display.cdclk.max_dotclk_freq || hdisplay > 5120 || connector->force_bigjoiner_enable; } +bool intel_dp_has_dsc(const struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + + if (!HAS_DSC(i915)) + return false; + + if (connector->mst_port && !HAS_DSC_MST(i915)) + return false; + + if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP && + connector->panel.vbt.edp.dsc_disable) + return false; + + if (!drm_dp_sink_supports_dsc(connector->dp.dsc_dpcd)) + return false; + + return true; +} + static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *_connector, struct drm_display_mode *mode) @@ -1231,7 +1209,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, u16 dsc_max_compressed_bpp = 0; u8 dsc_slice_count = 0; enum drm_mode_status status; - bool dsc = false, bigjoiner = false; + bool dsc = false, joiner = false; status = intel_cpu_transcoder_mode_valid(dev_priv, mode); if (status != MODE_OK) @@ -1252,9 +1230,9 @@ intel_dp_mode_valid(struct drm_connector *_connector, target_clock = fixed_mode->clock; } - if (intel_dp_need_bigjoiner(intel_dp, connector, - mode->hdisplay, target_clock)) { - bigjoiner = true; + if (intel_dp_need_joiner(intel_dp, connector, + mode->hdisplay, target_clock)) { + joiner = true; max_dotclk *= 2; } if (target_clock > max_dotclk) @@ -1271,8 +1249,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, mode_rate = intel_dp_link_required(target_clock, intel_dp_mode_min_output_bpp(connector, mode)); - if (HAS_DSC(dev_priv) && - drm_dp_sink_supports_dsc(connector->dp.dsc_dpcd)) { + if (intel_dp_has_dsc(connector)) { enum intel_output_format sink_format, output_format; int pipe_bpp; @@ -1301,20 +1278,20 @@ intel_dp_mode_valid(struct drm_connector *_connector, max_lanes, target_clock, mode->hdisplay, - bigjoiner, + joiner, output_format, pipe_bpp, 64); dsc_slice_count = intel_dp_dsc_get_slice_count(connector, target_clock, mode->hdisplay, - bigjoiner); + joiner); } dsc = dsc_max_compressed_bpp && dsc_slice_count; } - if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner) && !dsc) + if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) return MODE_CLOCK_HIGH; if (mode_rate > max_rate && !dsc) @@ -1324,7 +1301,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, if (status != MODE_OK) return status; - return intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner); + return intel_mode_valid_max_plane_size(dev_priv, mode, joiner); } bool intel_dp_source_supports_tps3(struct drm_i915_private *i915) @@ -1374,16 +1351,38 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) drm_dbg_kms(&i915->drm, "common rates: %s\n", str); } +static int forced_link_rate(struct intel_dp *intel_dp) +{ + int len = intel_dp_common_len_rate_limit(intel_dp, intel_dp->link.force_rate); + + if (len == 0) + return intel_dp_common_rate(intel_dp, 0); + + return intel_dp_common_rate(intel_dp, len - 1); +} + int intel_dp_max_link_rate(struct intel_dp *intel_dp) { int len; - len = intel_dp_common_len_rate_limit(intel_dp, intel_dp->max_link_rate); + if (intel_dp->link.force_rate) + return forced_link_rate(intel_dp); + + len = intel_dp_common_len_rate_limit(intel_dp, intel_dp->link.max_rate); return intel_dp_common_rate(intel_dp, len - 1); } +static int +intel_dp_min_link_rate(struct intel_dp *intel_dp) +{ + if (intel_dp->link.force_rate) + return forced_link_rate(intel_dp); + + return intel_dp_common_rate(intel_dp, 0); +} + int intel_dp_rate_select(struct intel_dp *intel_dp, int rate) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -1441,15 +1440,16 @@ bool intel_dp_supports_fec(struct intel_dp *intel_dp, drm_dp_sink_supports_fec(connector->dp.fec_capability); } -static bool intel_dp_supports_dsc(const struct intel_connector *connector, - const struct intel_crtc_state *crtc_state) +bool intel_dp_supports_dsc(const struct intel_connector *connector, + const struct intel_crtc_state *crtc_state) { + if (!intel_dp_has_dsc(connector)) + return false; + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP) && !crtc_state->fec_enable) return false; - return intel_dsc_source_support(crtc_state) && - connector->dp.dsc_decompression_aux && - drm_dp_sink_supports_dsc(connector->dp.dsc_dpcd); + return intel_dsc_source_support(crtc_state); } static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp, @@ -2015,7 +2015,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, adjusted_mode->clock, adjusted_mode->hdisplay, - pipe_config->bigjoiner_pipes); + pipe_config->joiner_pipes); dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp); dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16)); @@ -2249,7 +2249,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, intel_dp_dsc_get_slice_count(connector, adjusted_mode->crtc_clock, adjusted_mode->crtc_hdisplay, - pipe_config->bigjoiner_pipes); + pipe_config->joiner_pipes); if (!dsc_dp_slice_count) { drm_dbg_kms(&dev_priv->drm, "Compressed Slice Count not supported\n"); @@ -2263,7 +2263,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, * is greater than the maximum Cdclock and if slice count is even * then we need to use 2 VDSC instances. */ - if (pipe_config->bigjoiner_pipes || pipe_config->dsc.slice_count > 1) + if (pipe_config->joiner_pipes || pipe_config->dsc.slice_count > 1) pipe_config->dsc.dsc_split = true; ret = intel_dp_dsc_compute_params(connector, pipe_config); @@ -2353,13 +2353,14 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp, bool dsc, struct link_config_limits *limits) { - limits->min_rate = intel_dp_common_rate(intel_dp, 0); + limits->min_rate = intel_dp_min_link_rate(intel_dp); limits->max_rate = intel_dp_max_link_rate(intel_dp); /* FIXME 128b/132b SST support missing */ limits->max_rate = min(limits->max_rate, 810000); + limits->min_rate = min(limits->min_rate, limits->max_rate); - limits->min_lane_count = 1; + limits->min_lane_count = intel_dp_min_lane_count(intel_dp); limits->max_lane_count = intel_dp_max_lane_count(intel_dp); limits->pipe.min_bpp = intel_dp_min_bpp(crtc_state->output_format); @@ -2429,12 +2430,12 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, !intel_dp_supports_fec(intel_dp, connector, pipe_config)) return -EINVAL; - if (intel_dp_need_bigjoiner(intel_dp, connector, - adjusted_mode->crtc_hdisplay, - adjusted_mode->crtc_clock)) - pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); + if (intel_dp_need_joiner(intel_dp, connector, + adjusted_mode->crtc_hdisplay, + adjusted_mode->crtc_clock)) + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); - joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->bigjoiner_pipes); + joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->joiner_pipes); dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en || !intel_dp_compute_config_limits(intel_dp, pipe_config, @@ -2633,11 +2634,19 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, /* Currently only DP_AS_SDP_AVT_FIXED_VTOTAL mode supported */ as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC; as_sdp->length = 0x9; - as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL; - as_sdp->vtotal = adjusted_mode->vtotal; - as_sdp->target_rr = 0; as_sdp->duration_incr_ms = 0; as_sdp->duration_incr_ms = 0; + + if (crtc_state->cmrr.enable) { + as_sdp->mode = DP_AS_SDP_FAVT_TRR_REACHED; + as_sdp->vtotal = adjusted_mode->vtotal; + as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode); + as_sdp->target_rr_divider = true; + } else { + as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL; + as_sdp->vtotal = adjusted_mode->vtotal; + as_sdp->target_rr = 0; + } } static void intel_dp_compute_vsc_sdp(struct intel_dp *intel_dp, @@ -2660,14 +2669,6 @@ static void intel_dp_compute_vsc_sdp(struct intel_dp *intel_dp, if (intel_dp_needs_vsc_sdp(crtc_state, conn_state)) { intel_dp_compute_vsc_colorimetry(crtc_state, conn_state, vsc); - } else if (crtc_state->has_psr2) { - /* - * [PSR2 without colorimetry] - * Prepare VSC Header for SU as per eDP 1.4 spec, Table 6-11 - * 3D stereo + PSR/PSR2 + Y-coordinate. - */ - vsc->revision = 0x4; - vsc->length = 0xe; } else if (crtc_state->has_panel_replay) { /* * [Panel Replay without colorimetry info] @@ -2676,6 +2677,14 @@ static void intel_dp_compute_vsc_sdp(struct intel_dp *intel_dp, */ vsc->revision = 0x6; vsc->length = 0x10; + } else if (crtc_state->has_sel_update) { + /* + * [PSR2 without colorimetry] + * Prepare VSC Header for SU as per eDP 1.4 spec, Table 6-11 + * 3D stereo + PSR/PSR2 + Y-coordinate. + */ + vsc->revision = 0x4; + vsc->length = 0xe; } else { /* * [PSR1] @@ -2754,7 +2763,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, * FIXME all joined pipes share the same transcoder. * Need to account for that when updating M/N live. */ - if (has_seamless_m_n(connector) && !pipe_config->bigjoiner_pipes) + if (has_seamless_m_n(connector) && !pipe_config->joiner_pipes) pipe_config->update_m_n = true; if (!can_enable_drrs(connector, pipe_config, downclock_mode)) { @@ -2783,7 +2792,6 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, } static bool intel_dp_has_audio(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); @@ -2792,8 +2800,7 @@ static bool intel_dp_has_audio(struct intel_encoder *encoder, struct intel_connector *connector = to_intel_connector(conn_state->connector); - if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) && - !intel_dp_port_has_audio(i915, encoder->port)) + if (!intel_dp_port_has_audio(i915, encoder->port)) return false; if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) @@ -2852,14 +2859,14 @@ intel_dp_audio_compute_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state) { pipe_config->has_audio = - intel_dp_has_audio(encoder, pipe_config, conn_state) && + intel_dp_has_audio(encoder, conn_state) && intel_audio_compute_config(encoder, pipe_config, conn_state); pipe_config->sdp_split_enable = pipe_config->has_audio && intel_dp_is_uhbr(pipe_config); } -void intel_dp_queue_modeset_retry_work(struct intel_connector *connector) +static void intel_dp_queue_modeset_retry_work(struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(connector->base.dev); @@ -2868,6 +2875,7 @@ void intel_dp_queue_modeset_retry_work(struct intel_connector *connector) drm_connector_put(&connector->base); } +/* NOTE: @state is only valid for MST links and can be %NULL for SST. */ void intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state, struct intel_encoder *encoder, @@ -2876,6 +2884,7 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state, struct intel_connector *connector; struct intel_digital_connector_state *conn_state; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + struct drm_i915_private *i915 = dp_to_i915(intel_dp); int i; if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) { @@ -2884,6 +2893,9 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state, return; } + if (drm_WARN_ON(&i915->drm, !state)) + return; + for_each_new_intel_connector_in_state(state, connector, conn_state, i) { if (!conn_state->base.crtc) continue; @@ -2997,6 +3009,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, intel_vrr_compute_config(pipe_config, conn_state); intel_dp_compute_as_sdp(intel_dp, pipe_config); intel_psr_compute_config(intel_dp, pipe_config, conn_state); + intel_alpm_lobf_compute_config(intel_dp, pipe_config, conn_state); intel_dp_drrs_compute_config(connector, pipe_config, link_bpp_x16); intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state); intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state); @@ -3014,10 +3027,12 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, intel_dp->lane_count = lane_count; } -static void intel_dp_reset_max_link_params(struct intel_dp *intel_dp) +void intel_dp_reset_link_params(struct intel_dp *intel_dp) { - intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); - intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); + intel_dp->link.max_lane_count = intel_dp_max_common_lane_count(intel_dp); + intel_dp->link.max_rate = intel_dp_max_common_rate(intel_dp); + intel_dp->link.retrain_disabled = false; + intel_dp->link.seq_train_failures = 0; } /* Enable backlight PWM and backlight PP control. */ @@ -3352,7 +3367,7 @@ void intel_dp_sync_state(struct intel_encoder *encoder, intel_dp_tunnel_resume(intel_dp, crtc_state, dpcd_updated); if (crtc_state) - intel_dp_reset_max_link_params(intel_dp); + intel_dp_reset_link_params(intel_dp); } bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, @@ -4227,6 +4242,9 @@ static ssize_t intel_dp_as_sdp_pack(const struct drm_dp_as_sdp *as_sdp, sdp->db[3] = as_sdp->target_rr & 0xFF; sdp->db[4] = (as_sdp->target_rr >> 8) & 0x3; + if (as_sdp->target_rr_divider) + sdp->db[4] |= 0x20; + return length; } @@ -4350,7 +4368,8 @@ void intel_dp_set_infoframes(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder); + i915_reg_t reg = HSW_TVIDEO_DIP_CTL(dev_priv, + crtc_state->cpu_transcoder); u32 dip_enable = VIDEO_DIP_ENABLE_AVI_HSW | VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW | VIDEO_DIP_ENABLE_SPD_HSW | VIDEO_DIP_ENABLE_DRM_GLK; @@ -4407,6 +4426,7 @@ int intel_dp_as_sdp_unpack(struct drm_dp_as_sdp *as_sdp, as_sdp->mode = sdp->db[0] & DP_ADAPTIVE_SYNC_SDP_OPERATION_MODE; as_sdp->vtotal = (sdp->db[2] << 8) | sdp->db[1]; as_sdp->target_rr = (u64)sdp->db[3] | ((u64)sdp->db[4] & 0x3); + as_sdp->target_rr_divider = sdp->db[4] & 0x20 ? true : false; return 0; } @@ -4432,7 +4452,8 @@ static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc, vsc->length = sdp->sdp_header.HB3; if ((sdp->sdp_header.HB2 == 0x2 && sdp->sdp_header.HB3 == 0x8) || - (sdp->sdp_header.HB2 == 0x4 && sdp->sdp_header.HB3 == 0xe)) { + (sdp->sdp_header.HB2 == 0x4 && sdp->sdp_header.HB3 == 0xe) || + (sdp->sdp_header.HB2 == 0x6 && sdp->sdp_header.HB3 == 0x10)) { /* * - HB2 = 0x2, HB3 = 0x8 * VSC SDP supporting 3D stereo + PSR @@ -4440,6 +4461,8 @@ static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc, * VSC SDP supporting 3D stereo + PSR2 with Y-coordinate of * first scan line of the SU region (applies to eDP v1.4b * and higher). + * - HB2 = 0x6, HB3 = 0x10 + * VSC SDP supporting 3D stereo + Panel Replay. */ return 0; } else if (sdp->sdp_header.HB2 == 0x5 && sdp->sdp_header.HB3 == 0x13) { @@ -5017,6 +5040,8 @@ static bool intel_dp_check_mst_status(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &dig_port->base; bool link_ok = true; bool reprobe_needed = false; @@ -5062,7 +5087,10 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp) drm_dp_mst_hpd_irq_send_new_request(&intel_dp->mst_mgr); } - return link_ok && !reprobe_needed; + if (!link_ok || intel_dp->link.force_retrain) + intel_encoder_link_check_queue_work(encoder, 0); + + return !reprobe_needed; } static void @@ -5108,6 +5136,9 @@ intel_dp_needs_link_retrain(struct intel_dp *intel_dp) if (intel_psr_enabled(intel_dp)) return false; + if (intel_dp->link.force_retrain) + return true; + if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX, link_status) < 0) return false; @@ -5124,6 +5155,12 @@ intel_dp_needs_link_retrain(struct intel_dp *intel_dp) intel_dp->lane_count)) return false; + if (intel_dp->link.retrain_disabled) + return false; + + if (intel_dp->link.seq_train_failures) + return true; + /* Retrain if link not ok */ return !intel_dp_link_ok(intel_dp, link_status); } @@ -5209,12 +5246,13 @@ static bool intel_dp_is_connected(struct intel_dp *intel_dp) intel_dp->is_mst; } -int intel_dp_retrain_link(struct intel_encoder *encoder, - struct drm_modeset_acquire_ctx *ctx) +static int intel_dp_retrain_link(struct intel_encoder *encoder, + struct drm_modeset_acquire_ctx *ctx) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_crtc *crtc; + bool mst_output = false; u8 pipe_mask; int ret; @@ -5239,13 +5277,19 @@ int intel_dp_retrain_link(struct intel_encoder *encoder, if (!intel_dp_needs_link_retrain(intel_dp)) return 0; - drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] retraining link\n", - encoder->base.base.id, encoder->base.name); + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] retraining link (forced %s)\n", + encoder->base.base.id, encoder->base.name, + str_yes_no(intel_dp->link.force_retrain)); for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc, pipe_mask) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) { + mst_output = true; + break; + } + /* Suppress underruns caused by re-training */ intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); if (crtc_state->has_pch_encoder) @@ -5253,19 +5297,26 @@ int intel_dp_retrain_link(struct intel_encoder *encoder, intel_crtc_pch_transcoder(crtc), false); } + /* TODO: use a modeset for SST as well. */ + if (mst_output) { + ret = intel_modeset_commit_pipes(dev_priv, pipe_mask, ctx); + + if (ret && ret != -EDEADLK) + drm_dbg_kms(&dev_priv->drm, + "[ENCODER:%d:%s] link retraining failed: %pe\n", + encoder->base.base.id, encoder->base.name, + ERR_PTR(ret)); + + goto out; + } + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc, pipe_mask) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); - /* retrain on the MST master transcoder */ - if (DISPLAY_VER(dev_priv) >= 12 && - intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) && - !intel_dp_mst_is_master_trans(crtc_state)) - continue; - intel_dp_check_frl_training(intel_dp); intel_dp_pcon_dsc_configure(intel_dp, crtc_state); - intel_dp_start_link_train(intel_dp, crtc_state); + intel_dp_start_link_train(NULL, intel_dp, crtc_state); intel_dp_stop_link_train(intel_dp, crtc_state); break; } @@ -5283,7 +5334,37 @@ int intel_dp_retrain_link(struct intel_encoder *encoder, intel_crtc_pch_transcoder(crtc), true); } - return 0; +out: + if (ret != -EDEADLK) + intel_dp->link.force_retrain = false; + + return ret; +} + +void intel_dp_link_check(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct drm_modeset_acquire_ctx ctx; + int ret; + + intel_modeset_lock_ctx_retry(&ctx, NULL, 0, ret) + ret = intel_dp_retrain_link(encoder, &ctx); + + drm_WARN_ON(&i915->drm, ret); +} + +void intel_dp_check_link_state(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &dig_port->base; + + if (!intel_dp_is_connected(intel_dp)) + return; + + if (!intel_dp_needs_link_retrain(intel_dp)) + return; + + intel_encoder_link_check_queue_work(encoder, 0); } static int intel_dp_prep_phy_test(struct intel_dp *intel_dp, @@ -5496,9 +5577,7 @@ intel_dp_short_pulse(struct intel_dp *intel_dp) /* Handle CEC interrupts, if any */ drm_dp_cec_irq(&intel_dp->aux); - /* defer to the hotplug work for link retraining if needed */ - if (intel_dp_needs_link_retrain(intel_dp)) - return false; + intel_dp_check_link_state(intel_dp); intel_psr_short_pulse(intel_dp); @@ -5858,6 +5937,7 @@ intel_dp_detect(struct drm_connector *connector, memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance)); memset(intel_connector->dp.dsc_dpcd, 0, sizeof(intel_connector->dp.dsc_dpcd)); intel_dp->psr.sink_panel_replay_support = false; + intel_dp->psr.sink_panel_replay_su_support = false; intel_dp_mst_disconnect(intel_dp); @@ -5880,12 +5960,8 @@ intel_dp_detect(struct drm_connector *connector, intel_dp_mst_configure(intel_dp); - /* - * TODO: Reset link params when switching to MST mode, until MST - * supports link training fallback params. - */ - if (intel_dp->reset_link_params || intel_dp->is_mst) { - intel_dp_reset_max_link_params(intel_dp); + if (intel_dp->reset_link_params) { + intel_dp_reset_link_params(intel_dp); intel_dp->reset_link_params = false; } @@ -5904,12 +5980,13 @@ intel_dp_detect(struct drm_connector *connector, /* * Some external monitors do not signal loss of link synchronization * with an IRQ_HPD, so force a link status check. + * + * TODO: this probably became redundant, so remove it: the link state + * is rechecked/recovered now after modesets, where the loss of + * synchronization tends to occur. */ - if (!intel_dp_is_edp(intel_dp)) { - ret = intel_dp_retrain_link(encoder, ctx); - if (ret) - return ret; - } + if (!intel_dp_is_edp(intel_dp)) + intel_dp_check_link_state(intel_dp); /* * Clearing NACK and defer counts to get their exact values @@ -6051,11 +6128,14 @@ void intel_dp_connector_sync_state(struct intel_connector *connector, } } -void intel_dp_encoder_flush_work(struct drm_encoder *encoder) +void intel_dp_encoder_flush_work(struct drm_encoder *_encoder) { - struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); + struct intel_encoder *encoder = to_intel_encoder(_encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct intel_dp *intel_dp = &dig_port->dp; + intel_encoder_link_check_flush_work(encoder); + intel_dp_mst_encoder_cleanup(dig_port); intel_dp_tunnel_destroy(intel_dp); @@ -6361,8 +6441,8 @@ bool intel_dp_is_port_edp(struct drm_i915_private *i915, enum port port) return _intel_dp_is_port_edp(i915, devdata, port); } -static bool -has_gamut_metadata_dip(struct intel_encoder *encoder) +bool +intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); enum port port = encoder->port; @@ -6409,7 +6489,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_attach_dp_colorspace_property(connector); } - if (has_gamut_metadata_dip(&dp_to_dig_port(intel_dp)->base)) + if (intel_dp_has_gamut_metadata_dip(&dp_to_dig_port(intel_dp)->base)) drm_connector_attach_hdr_output_metadata_property(connector); if (HAS_VRR(dev_priv)) @@ -6508,6 +6588,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, */ intel_hpd_enable_detection(encoder); + intel_alpm_init_dpcd(intel_dp); + /* Cache DPCD and EDID for edp. */ has_dpcd = intel_edp_init_dpcd(intel_dp, intel_connector); @@ -6737,7 +6819,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, intel_dp_set_source_rates(intel_dp); intel_dp_set_common_rates(intel_dp); - intel_dp_reset_max_link_params(intel_dp); + intel_dp_reset_link_params(intel_dp); /* init MST on ports that can support it */ intel_dp_mst_encoder_init(dig_port, diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 106ecfde36d9..a0f990a95ecc 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -44,7 +44,6 @@ bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); int intel_dp_min_bpp(enum intel_output_format output_format); void intel_dp_init_modeset_retry_work(struct intel_connector *connector); -void intel_dp_queue_modeset_retry_work(struct intel_connector *connector); void intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state, struct intel_encoder *encoder, @@ -55,13 +54,11 @@ void intel_dp_connector_sync_state(struct intel_connector *connector, const struct intel_crtc_state *crtc_state); void intel_dp_set_link_params(struct intel_dp *intel_dp, int link_rate, int lane_count); -int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, - int link_rate, u8 lane_count); int intel_dp_get_active_pipes(struct intel_dp *intel_dp, struct drm_modeset_acquire_ctx *ctx, u8 *pipe_mask); -int intel_dp_retrain_link(struct intel_encoder *encoder, - struct drm_modeset_acquire_ctx *ctx); +void intel_dp_link_check(struct intel_encoder *encoder); +void intel_dp_check_link_state(struct intel_dp *intel_dp); void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode); void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); @@ -90,6 +87,7 @@ bool intel_dp_has_hdmi_sink(struct intel_dp *intel_dp); bool intel_dp_is_edp(struct intel_dp *intel_dp); bool intel_dp_as_sdp_supported(struct intel_dp *intel_dp); bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state); +bool intel_dp_has_dsc(const struct intel_connector *connector); int intel_dp_link_symbol_size(int rate); int intel_dp_link_symbol_clock(int rate); bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port); @@ -101,13 +99,17 @@ void intel_edp_backlight_off(const struct drm_connector_state *conn_state); void intel_edp_fixup_vbt_bpp(struct intel_encoder *encoder, int pipe_bpp); void intel_dp_mst_suspend(struct drm_i915_private *dev_priv); void intel_dp_mst_resume(struct drm_i915_private *dev_priv); +int intel_dp_max_source_lane_count(struct intel_digital_port *dig_port); int intel_dp_max_link_rate(struct intel_dp *intel_dp); int intel_dp_max_lane_count(struct intel_dp *intel_dp); int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state); int intel_dp_rate_select(struct intel_dp *intel_dp, int rate); int intel_dp_max_common_rate(struct intel_dp *intel_dp); int intel_dp_max_common_lane_count(struct intel_dp *intel_dp); +int intel_dp_common_rate(struct intel_dp *intel_dp, int index); +int intel_dp_rate_index(const int *rates, int len, int rate); void intel_dp_update_sink_caps(struct intel_dp *intel_dp); +void intel_dp_reset_link_params(struct intel_dp *intel_dp); void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, u8 *link_bw, u8 *rate_select); @@ -121,7 +123,7 @@ int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16, int intel_dp_max_link_data_rate(struct intel_dp *intel_dp, int max_dprx_rate, int max_dprx_lanes); bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner); -bool intel_dp_has_bigjoiner(struct intel_dp *intel_dp); +bool intel_dp_has_joiner(struct intel_dp *intel_dp); bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); void intel_dp_set_infoframes(struct intel_encoder *encoder, bool enable, @@ -150,9 +152,9 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, int mode_clock, int mode_hdisplay, bool bigjoiner); -bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, - struct intel_connector *connector, - int hdisplay, int clock); +bool intel_dp_need_joiner(struct intel_dp *intel_dp, + struct intel_connector *connector, + int hdisplay, int clock); static inline unsigned int intel_dp_unused_lane_mask(int lane_count) { @@ -169,6 +171,9 @@ bool intel_dp_supports_fec(struct intel_dp *intel_dp, const struct intel_connector *connector, const struct intel_crtc_state *pipe_config); +bool intel_dp_supports_dsc(const struct intel_connector *connector, + const struct intel_crtc_state *crtc_state); + u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp); void intel_ddi_update_pipe(struct intel_atomic_state *state, @@ -196,5 +201,6 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp, struct link_config_limits *limits); void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector); +bool intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder); #endif /* __INTEL_DP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f58efdc688a..8ce60d53dcde 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -40,11 +40,6 @@ #include "intel_dp.h" #include "intel_dp_aux_backlight.h" -/* TODO: - * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we - * can make people's backlights work in the mean time - */ - /* * DP AUX registers for Intel's proprietary HDR backlight interface. We define * them here since we'll likely be the only driver to ever use these. @@ -69,14 +64,14 @@ #define INTEL_EDP_HDR_GETSET_CTRL_PARAMS 0x344 # define INTEL_EDP_HDR_TCON_2084_DECODE_ENABLE BIT(0) # define INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE BIT(1) -# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) /* Pre-TGL+ */ +# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) # define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLE BIT(3) # define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4) # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLE BIT(5) /* Bit 6 is reserved */ -# define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_ENABLE BIT(7) +# define INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX BIT(7) -#define INTEL_EDP_HDR_CONTENT_LUMINANCE 0x346 /* Pre-TGL+ */ +#define INTEL_EDP_HDR_CONTENT_LUMINANCE 0x346 #define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A #define INTEL_EDP_SDR_LUMINANCE_LEVEL 0x352 #define INTEL_EDP_BRIGHTNESS_NITS_LSB 0x354 @@ -127,9 +122,6 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) if (ret != sizeof(tcon_cap)) return false; - if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) - return false; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] Detected %s HDR backlight interface version %d\n", connector->base.base.id, connector->base.name, is_intel_tcon_cap(tcon_cap) ? "Intel" : "unsupported", tcon_cap[0]); @@ -137,6 +129,9 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) if (!is_intel_tcon_cap(tcon_cap)) return false; + if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) + return false; + /* * If we don't have HDR static metadata there is no way to * runtime detect used range for nits based control. For now @@ -156,8 +151,18 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) return false; } - panel->backlight.edp.intel.sdr_uses_aux = + panel->backlight.edp.intel_cap.sdr_uses_aux = tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; + panel->backlight.edp.intel_cap.supports_2084_decode = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2084_DECODE_CAP; + panel->backlight.edp.intel_cap.supports_2020_gamut = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2020_GAMUT_CAP; + panel->backlight.edp.intel_cap.supports_segmented_backlight = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_CAP; + panel->backlight.edp.intel_cap.supports_sdp_colorimetry = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_CAP; + panel->backlight.edp.intel_cap.supports_tone_mapping = + tcon_cap[1] & INTEL_EDP_HDR_TCON_TONE_MAPPING_CAP; return true; } @@ -178,7 +183,7 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe } if (!(tmp & INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE)) { - if (!panel->backlight.edp.intel.sdr_uses_aux) { + if (!panel->backlight.edp.intel_cap.sdr_uses_aux) { u32 pwm_level = panel->backlight.pwm_funcs->get(connector, pipe); return intel_backlight_level_from_pwm(connector, pwm_level); @@ -215,13 +220,27 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, connector->base.base.id, connector->base.name); } +static bool +intel_dp_in_hdr_mode(const struct drm_connector_state *conn_state) +{ + struct hdr_output_metadata *hdr_metadata; + + if (!conn_state->hdr_output_metadata) + return false; + + hdr_metadata = conn_state->hdr_output_metadata->data; + + return hdr_metadata->hdmi_metadata_type1.eotf == HDMI_EOTF_SMPTE_ST2084; +} + static void intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = &connector->panel; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (intel_dp_in_hdr_mode(conn_state) || + panel->backlight.edp.intel_cap.sdr_uses_aux) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -231,6 +250,64 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 } static void +intel_dp_aux_write_content_luminance(struct intel_connector *connector, + struct hdr_output_metadata *hdr_metadata) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + int ret; + u8 buf[4]; + + if (!intel_dp_has_gamut_metadata_dip(connector->encoder)) + return; + + buf[0] = hdr_metadata->hdmi_metadata_type1.max_cll & 0xFF; + buf[1] = (hdr_metadata->hdmi_metadata_type1.max_cll & 0xFF00) >> 8; + buf[2] = hdr_metadata->hdmi_metadata_type1.max_fall & 0xFF; + buf[3] = (hdr_metadata->hdmi_metadata_type1.max_fall & 0xFF00) >> 8; + + ret = drm_dp_dpcd_write(&intel_dp->aux, + INTEL_EDP_HDR_CONTENT_LUMINANCE, + buf, sizeof(buf)); + if (ret < 0) + drm_dbg_kms(&i915->drm, + "Content Luminance DPCD reg write failed, err:-%d\n", + ret); +} + +static void +intel_dp_aux_fill_hdr_tcon_params(const struct drm_connector_state *conn_state, u8 *ctrl) +{ + struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct intel_panel *panel = &connector->panel; + struct drm_i915_private *i915 = to_i915(connector->base.dev); + + /* + * According to spec segmented backlight needs to be set whenever panel is in + * HDR mode. + */ + if (intel_dp_in_hdr_mode(conn_state)) { + *ctrl |= INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLE; + *ctrl |= INTEL_EDP_HDR_TCON_2084_DECODE_ENABLE; + } + + if (DISPLAY_VER(i915) < 11) + *ctrl &= ~INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE; + + if (panel->backlight.edp.intel_cap.supports_2020_gamut && + (conn_state->colorspace == DRM_MODE_COLORIMETRY_BT2020_RGB || + conn_state->colorspace == DRM_MODE_COLORIMETRY_BT2020_YCC || + conn_state->colorspace == DRM_MODE_COLORIMETRY_BT2020_CYCC)) + *ctrl |= INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE; + + if (panel->backlight.edp.intel_cap.supports_sdp_colorimetry && + intel_dp_has_gamut_metadata_dip(connector->encoder)) + *ctrl |= INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX; + else + *ctrl &= ~INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX; +} + +static void intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { @@ -238,6 +315,7 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, struct intel_panel *panel = &connector->panel; struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + struct hdr_output_metadata *hdr_metadata; int ret; u8 old_ctrl, ctrl; @@ -251,8 +329,10 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, } ctrl = old_ctrl; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (intel_dp_in_hdr_mode(conn_state) || + panel->backlight.edp.intel_cap.sdr_uses_aux) { ctrl |= INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; + intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -262,10 +342,17 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, ctrl &= ~INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; } + intel_dp_aux_fill_hdr_tcon_params(conn_state, &ctrl); + if (ctrl != old_ctrl && drm_dp_dpcd_writeb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl) != 1) drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to configure DPCD brightness controls\n", connector->base.base.id, connector->base.name); + + if (intel_dp_in_hdr_mode(conn_state)) { + hdr_metadata = conn_state->hdr_output_metadata->data; + intel_dp_aux_write_content_luminance(connector, hdr_metadata); + } } static void @@ -275,7 +362,7 @@ intel_dp_aux_hdr_disable_backlight(const struct drm_connector_state *conn_state, struct intel_panel *panel = &connector->panel; /* Nothing to do for AUX based backlight controls */ - if (panel->backlight.edp.intel.sdr_uses_aux) + if (panel->backlight.edp.intel_cap.sdr_uses_aux) return; /* Note we want the actual pwm_level to be 0, regardless of pwm_min */ @@ -287,6 +374,29 @@ static const char *dpcd_vs_pwm_str(bool aux) return aux ? "DPCD" : "PWM"; } +static void +intel_dp_aux_write_panel_luminance_override(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_panel *panel = &connector->panel; + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + int ret; + u8 buf[4] = {}; + + buf[0] = panel->backlight.min & 0xFF; + buf[1] = (panel->backlight.min & 0xFF00) >> 8; + buf[2] = panel->backlight.max & 0xFF; + buf[3] = (panel->backlight.max & 0xFF00) >> 8; + + ret = drm_dp_dpcd_write(&intel_dp->aux, + INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE, + buf, sizeof(buf)); + if (ret < 0) + drm_dbg_kms(&i915->drm, + "Panel Luminance DPCD reg write failed, err:-%d\n", + ret); +} + static int intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pipe) { @@ -298,9 +408,9 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] SDR backlight is controlled through %s\n", connector->base.base.id, connector->base.name, - dpcd_vs_pwm_str(panel->backlight.edp.intel.sdr_uses_aux)); + dpcd_vs_pwm_str(panel->backlight.edp.intel_cap.sdr_uses_aux)); - if (!panel->backlight.edp.intel.sdr_uses_aux) { + if (!panel->backlight.edp.intel_cap.sdr_uses_aux) { ret = panel->backlight.pwm_funcs->setup(connector, pipe); if (ret < 0) { drm_err(&i915->drm, @@ -318,11 +428,12 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi panel->backlight.min = 0; } + intel_dp_aux_write_panel_luminance_override(connector); + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] Using AUX HDR interface for backlight control (range %d..%d)\n", connector->base.base.id, connector->base.name, panel->backlight.min, panel->backlight.max); - panel->backlight.level = intel_dp_aux_hdr_get_backlight(connector, pipe); panel->backlight.enabled = panel->backlight.level != 0; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h b/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h index e642445364d2..4e109e81409b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h @@ -23,12 +23,17 @@ #define _DPA_AUX_CH_CTL 0x64010 #define _DPB_AUX_CH_CTL 0x64110 -#define _XELPDP_USBC1_AUX_CH_CTL 0x16f210 -#define _XELPDP_USBC2_AUX_CH_CTL 0x16f410 #define DP_AUX_CH_CTL(aux_ch) _MMIO_PORT(aux_ch, _DPA_AUX_CH_CTL, \ _DPB_AUX_CH_CTL) #define VLV_DP_AUX_CH_CTL(aux_ch) _MMIO(VLV_DISPLAY_BASE + \ _PORT(aux_ch, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL)) + +#define _PCH_DPB_AUX_CH_CTL 0xe4110 +#define _PCH_DPC_AUX_CH_CTL 0xe4210 +#define PCH_DP_AUX_CH_CTL(aux_ch) _MMIO_PORT((aux_ch) - AUX_CH_B, _PCH_DPB_AUX_CH_CTL, _PCH_DPC_AUX_CH_CTL) + +#define _XELPDP_USBC1_AUX_CH_CTL 0x16f210 +#define _XELPDP_USBC2_AUX_CH_CTL 0x16f410 #define _XELPDP_DP_AUX_CH_CTL(aux_ch) \ _MMIO(_PICK_EVEN_2RANGES(aux_ch, AUX_CH_USBC1, \ _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL, \ @@ -72,12 +77,17 @@ #define _DPA_AUX_CH_DATA1 0x64014 #define _DPB_AUX_CH_DATA1 0x64114 -#define _XELPDP_USBC1_AUX_CH_DATA1 0x16f214 -#define _XELPDP_USBC2_AUX_CH_DATA1 0x16f414 #define DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PORT(aux_ch, _DPA_AUX_CH_DATA1, \ _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */ #define VLV_DP_AUX_CH_DATA(aux_ch, i) _MMIO(VLV_DISPLAY_BASE + _PORT(aux_ch, _DPA_AUX_CH_DATA1, \ _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */ + +#define _PCH_DPB_AUX_CH_DATA1 0xe4114 +#define _PCH_DPC_AUX_CH_DATA1 0xe4214 +#define PCH_DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PORT((aux_ch) - AUX_CH_B, _PCH_DPB_AUX_CH_DATA1, _PCH_DPC_AUX_CH_DATA1) + (i) * 4) /* 5 registers */ + +#define _XELPDP_USBC1_AUX_CH_DATA1 0x16f214 +#define _XELPDP_USBC2_AUX_CH_DATA1 0x16f414 #define _XELPDP_DP_AUX_CH_DATA(aux_ch, i) \ _MMIO(_PICK_EVEN_2RANGES(aux_ch, AUX_CH_USBC1, \ _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1, \ diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 92b03073acdd..2edffe62f360 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -687,15 +687,16 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, bool *hdcp2_capable) { struct drm_i915_private *i915 = to_i915(connector->base.dev); - struct drm_dp_aux *aux = &connector->port->aux; + struct drm_dp_aux *aux; u8 bcaps; int ret; *hdcp_capable = false; *hdcp2_capable = false; - if (!intel_encoder_is_mst(connector->encoder)) + if (!connector->mst_port) return -EINVAL; + aux = &connector->port->aux; ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); if (ret) drm_dbg_kms(&i915->drm, diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 947575140059..1bc4ef84ff3b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -25,6 +25,9 @@ #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dp_link_training.h" +#include "intel_encoder.h" +#include "intel_hotplug.h" +#include "intel_panel.h" #define LT_MSG_PREFIX "[CONNECTOR:%d:%s][ENCODER:%d:%s][%s] " #define LT_MSG_ARGS(_intel_dp, _dp_phy) (_intel_dp)->attached_connector->base.base.id, \ @@ -1091,28 +1094,129 @@ out: return ret; } -static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp, +static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp, + int link_rate, + u8 lane_count) +{ + /* FIXME figure out what we actually want here */ + const struct drm_display_mode *fixed_mode = + intel_panel_preferred_fixed_mode(intel_dp->attached_connector); + int mode_rate, max_rate; + + mode_rate = intel_dp_link_required(fixed_mode->clock, 18); + max_rate = intel_dp_max_link_data_rate(intel_dp, link_rate, lane_count); + if (mode_rate > max_rate) + return false; + + return true; +} + +static int reduce_link_rate(struct intel_dp *intel_dp, int current_rate) +{ + int rate_index; + int new_rate; + + if (intel_dp->link.force_rate) + return -1; + + rate_index = intel_dp_rate_index(intel_dp->common_rates, + intel_dp->num_common_rates, + current_rate); + + if (rate_index <= 0) + return -1; + + new_rate = intel_dp_common_rate(intel_dp, rate_index - 1); + + /* TODO: Make switching from UHBR to non-UHBR rates work. */ + if (drm_dp_is_uhbr_rate(current_rate) != drm_dp_is_uhbr_rate(new_rate)) + return -1; + + return new_rate; +} + +static int reduce_lane_count(struct intel_dp *intel_dp, int current_lane_count) +{ + if (intel_dp->link.force_lane_count) + return -1; + + if (current_lane_count == 1) + return -1; + + return current_lane_count >> 1; +} + +static int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + int new_link_rate; + int new_lane_count; + + if (intel_dp_is_edp(intel_dp) && !intel_dp->use_max_params) { + lt_dbg(intel_dp, DP_PHY_DPRX, + "Retrying Link training for eDP with max parameters\n"); + intel_dp->use_max_params = true; + return 0; + } + + new_lane_count = crtc_state->lane_count; + new_link_rate = reduce_link_rate(intel_dp, crtc_state->port_clock); + if (new_link_rate < 0) { + new_lane_count = reduce_lane_count(intel_dp, crtc_state->lane_count); + new_link_rate = intel_dp_max_common_rate(intel_dp); + } + + if (new_lane_count < 0) + return -1; + + if (intel_dp_is_edp(intel_dp) && + !intel_dp_can_link_train_fallback_for_edp(intel_dp, new_link_rate, new_lane_count)) { + lt_dbg(intel_dp, DP_PHY_DPRX, + "Retrying Link training for eDP with same parameters\n"); + return 0; + } + + lt_dbg(intel_dp, DP_PHY_DPRX, + "Reducing link parameters from %dx%d to %dx%d\n", + crtc_state->lane_count, crtc_state->port_clock, + new_lane_count, new_link_rate); + + intel_dp->link.max_rate = new_link_rate; + intel_dp->link.max_lane_count = new_lane_count; + + return 0; +} + +/* NOTE: @state is only valid for MST links and can be %NULL for SST. */ +static bool intel_dp_schedule_fallback_link_training(struct intel_atomic_state *state, + struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { - struct intel_connector *intel_connector = intel_dp->attached_connector; + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; if (!intel_digital_port_connected(&dp_to_dig_port(intel_dp)->base)) { lt_dbg(intel_dp, DP_PHY_DPRX, "Link Training failed on disconnected sink.\n"); - return; + return true; } if (intel_dp->hobl_active) { lt_dbg(intel_dp, DP_PHY_DPRX, "Link Training failed with HOBL active, not enabling it from now on\n"); intel_dp->hobl_failed = true; - } else if (intel_dp_get_link_train_fallback_values(intel_dp, - crtc_state->port_clock, - crtc_state->lane_count)) { - return; + } else if (intel_dp_get_link_train_fallback_values(intel_dp, crtc_state)) { + return false; } + if (drm_WARN_ON(&i915->drm, + intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) && + !state)) + return false; + /* Schedule a Hotplug Uevent to userspace to start modeset */ - intel_dp_queue_modeset_retry_work(intel_connector); + intel_dp_queue_modeset_retry_for_link(state, encoder, crtc_state); + + return true; } /* Perform the link training on all LTTPRs and the DPRX on a link. */ @@ -1359,6 +1463,7 @@ intel_dp_128b132b_link_train(struct intel_dp *intel_dp, /** * intel_dp_start_link_train - start link training + * @state: Atomic state * @intel_dp: DP struct * @crtc_state: state for CRTC attached to the encoder * @@ -1366,11 +1471,16 @@ intel_dp_128b132b_link_train(struct intel_dp *intel_dp, * retraining with reduced link rate/lane parameters if the link training * fails. * After calling this function intel_dp_stop_link_train() must be called. + * + * NOTE: @state is only valid for MST links and can be %NULL for SST. */ -void intel_dp_start_link_train(struct intel_dp *intel_dp, +void intel_dp_start_link_train(struct intel_atomic_state *state, + struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &dig_port->base; bool passed; /* @@ -1379,6 +1489,11 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp, */ int lttpr_count = intel_dp_init_lttpr_and_dprx_caps(intel_dp); + if (drm_WARN_ON(&i915->drm, + intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) && + !state)) + return; + if (lttpr_count < 0) /* Still continue with enabling the port and link training. */ lttpr_count = 0; @@ -1390,6 +1505,17 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp, else passed = intel_dp_link_train_all_phys(intel_dp, crtc_state, lttpr_count); + if (intel_dp->link.force_train_failure) { + intel_dp->link.force_train_failure--; + lt_dbg(intel_dp, DP_PHY_DPRX, "Forcing link training failure\n"); + } else if (passed) { + intel_dp->link.seq_train_failures = 0; + intel_encoder_link_check_queue_work(encoder, 2000); + return; + } + + intel_dp->link.seq_train_failures++; + /* * Ignore the link failure in CI * @@ -1402,13 +1528,25 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp, * For test cases which rely on the link training or processing of HPDs * ignore_long_hpd flag can unset from the testcase. */ - if (!passed && i915->display.hotplug.ignore_long_hpd) { + if (i915->display.hotplug.ignore_long_hpd) { lt_dbg(intel_dp, DP_PHY_DPRX, "Ignore the link failure\n"); return; } + if (intel_dp->link.seq_train_failures < 2) { + intel_encoder_link_check_queue_work(encoder, 0); + return; + } + + if (intel_dp_schedule_fallback_link_training(state, intel_dp, crtc_state)) + return; + + intel_dp->link.retrain_disabled = true; + if (!passed) - intel_dp_schedule_fallback_link_training(intel_dp, crtc_state); + lt_err(intel_dp, DP_PHY_DPRX, "Can't reduce link training parameters after failure\n"); + else + lt_dbg(intel_dp, DP_PHY_DPRX, "Can't reduce link training parameters after forced failure\n"); } void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp, @@ -1430,3 +1568,381 @@ void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp, lt_dbg(intel_dp, DP_PHY_DPRX, "DP2.0 SDP CRC16 for 128b/132b enabled\n"); } + +static struct intel_dp *intel_connector_to_intel_dp(struct intel_connector *connector) +{ + if (connector->mst_port) + return connector->mst_port; + else + return enc_to_intel_dp(intel_attached_encoder(connector)); +} + +static int i915_dp_force_link_rate_show(struct seq_file *m, void *data) +{ + struct intel_connector *connector = to_intel_connector(m->private); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int current_rate = -1; + int force_rate; + int err; + int i; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + if (intel_dp->link_trained) + current_rate = intel_dp->link_rate; + force_rate = intel_dp->link.force_rate; + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + seq_printf(m, "%sauto%s", + force_rate == 0 ? "[" : "", + force_rate == 0 ? "]" : ""); + + for (i = 0; i < intel_dp->num_source_rates; i++) + seq_printf(m, " %s%d%s%s", + intel_dp->source_rates[i] == force_rate ? "[" : "", + intel_dp->source_rates[i], + intel_dp->source_rates[i] == current_rate ? "*" : "", + intel_dp->source_rates[i] == force_rate ? "]" : ""); + + seq_putc(m, '\n'); + + return 0; +} + +static int parse_link_rate(struct intel_dp *intel_dp, const char __user *ubuf, size_t len) +{ + char *kbuf; + const char *p; + int rate; + int ret = 0; + + kbuf = memdup_user_nul(ubuf, len); + if (IS_ERR(kbuf)) + return PTR_ERR(kbuf); + + p = strim(kbuf); + + if (!strcmp(p, "auto")) { + rate = 0; + } else { + ret = kstrtoint(p, 0, &rate); + if (ret < 0) + goto out_free; + + if (intel_dp_rate_index(intel_dp->source_rates, + intel_dp->num_source_rates, + rate) < 0) + ret = -EINVAL; + } + +out_free: + kfree(kbuf); + + return ret < 0 ? ret : rate; +} + +static ssize_t i915_dp_force_link_rate_write(struct file *file, + const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct intel_connector *connector = to_intel_connector(m->private); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int rate; + int err; + + rate = parse_link_rate(intel_dp, ubuf, len); + if (rate < 0) + return rate; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + intel_dp_reset_link_params(intel_dp); + intel_dp->link.force_rate = rate; + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + *offp += len; + + return len; +} +DEFINE_SHOW_STORE_ATTRIBUTE(i915_dp_force_link_rate); + +static int i915_dp_force_lane_count_show(struct seq_file *m, void *data) +{ + struct intel_connector *connector = to_intel_connector(m->private); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int current_lane_count = -1; + int force_lane_count; + int err; + int i; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + if (intel_dp->link_trained) + current_lane_count = intel_dp->lane_count; + force_lane_count = intel_dp->link.force_lane_count; + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + seq_printf(m, "%sauto%s", + force_lane_count == 0 ? "[" : "", + force_lane_count == 0 ? "]" : ""); + + for (i = 1; i <= 4; i <<= 1) + seq_printf(m, " %s%d%s%s", + i == force_lane_count ? "[" : "", + i, + i == current_lane_count ? "*" : "", + i == force_lane_count ? "]" : ""); + + seq_putc(m, '\n'); + + return 0; +} + +static int parse_lane_count(const char __user *ubuf, size_t len) +{ + char *kbuf; + const char *p; + int lane_count; + int ret = 0; + + kbuf = memdup_user_nul(ubuf, len); + if (IS_ERR(kbuf)) + return PTR_ERR(kbuf); + + p = strim(kbuf); + + if (!strcmp(p, "auto")) { + lane_count = 0; + } else { + ret = kstrtoint(p, 0, &lane_count); + if (ret < 0) + goto out_free; + + switch (lane_count) { + case 1: + case 2: + case 4: + break; + default: + ret = -EINVAL; + } + } + +out_free: + kfree(kbuf); + + return ret < 0 ? ret : lane_count; +} + +static ssize_t i915_dp_force_lane_count_write(struct file *file, + const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct intel_connector *connector = to_intel_connector(m->private); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int lane_count; + int err; + + lane_count = parse_lane_count(ubuf, len); + if (lane_count < 0) + return lane_count; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + intel_dp_reset_link_params(intel_dp); + intel_dp->link.force_lane_count = lane_count; + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + *offp += len; + + return len; +} +DEFINE_SHOW_STORE_ATTRIBUTE(i915_dp_force_lane_count); + +static int i915_dp_max_link_rate_show(void *data, u64 *val) +{ + struct intel_connector *connector = to_intel_connector(data); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int err; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + *val = intel_dp->link.max_rate; + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(i915_dp_max_link_rate_fops, i915_dp_max_link_rate_show, NULL, "%llu\n"); + +static int i915_dp_max_lane_count_show(void *data, u64 *val) +{ + struct intel_connector *connector = to_intel_connector(data); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int err; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + *val = intel_dp->link.max_lane_count; + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(i915_dp_max_lane_count_fops, i915_dp_max_lane_count_show, NULL, "%llu\n"); + +static int i915_dp_force_link_training_failure_show(void *data, u64 *val) +{ + struct intel_connector *connector = to_intel_connector(data); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int err; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + *val = intel_dp->link.force_train_failure; + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + return 0; +} + +static int i915_dp_force_link_training_failure_write(void *data, u64 val) +{ + struct intel_connector *connector = to_intel_connector(data); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int err; + + if (val > 2) + return -EINVAL; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + intel_dp->link.force_train_failure = val; + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(i915_dp_force_link_training_failure_fops, + i915_dp_force_link_training_failure_show, + i915_dp_force_link_training_failure_write, "%llu\n"); + +static int i915_dp_force_link_retrain_show(void *data, u64 *val) +{ + struct intel_connector *connector = to_intel_connector(data); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int err; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + *val = intel_dp->link.force_retrain; + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + return 0; +} + +static int i915_dp_force_link_retrain_write(void *data, u64 val) +{ + struct intel_connector *connector = to_intel_connector(data); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int err; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + intel_dp->link.force_retrain = val; + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + intel_hpd_trigger_irq(dp_to_dig_port(intel_dp)); + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(i915_dp_force_link_retrain_fops, + i915_dp_force_link_retrain_show, + i915_dp_force_link_retrain_write, "%llu\n"); + +static int i915_dp_link_retrain_disabled_show(struct seq_file *m, void *data) +{ + struct intel_connector *connector = to_intel_connector(m->private); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector); + int err; + + err = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (err) + return err; + + seq_printf(m, "%s\n", str_yes_no(intel_dp->link.retrain_disabled)); + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(i915_dp_link_retrain_disabled); + +void intel_dp_link_training_debugfs_add(struct intel_connector *connector) +{ + struct dentry *root = connector->base.debugfs_entry; + + if (connector->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort && + connector->base.connector_type != DRM_MODE_CONNECTOR_eDP) + return; + + debugfs_create_file("i915_dp_force_link_rate", 0644, root, + connector, &i915_dp_force_link_rate_fops); + + debugfs_create_file("i915_dp_force_lane_count", 0644, root, + connector, &i915_dp_force_lane_count_fops); + + debugfs_create_file("i915_dp_max_link_rate", 0444, root, + connector, &i915_dp_max_link_rate_fops); + + debugfs_create_file("i915_dp_max_lane_count", 0444, root, + connector, &i915_dp_max_lane_count_fops); + + debugfs_create_file("i915_dp_force_link_training_failure", 0644, root, + connector, &i915_dp_force_link_training_failure_fops); + + debugfs_create_file("i915_dp_force_link_retrain", 0644, root, + connector, &i915_dp_force_link_retrain_fops); + + debugfs_create_file("i915_dp_link_retrain_disabled", 0444, root, + connector, &i915_dp_link_retrain_disabled_fops); +} diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h b/drivers/gpu/drm/i915/display/intel_dp_link_training.h index 19836a8a4f90..42e7fc6cb171 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h @@ -8,6 +8,8 @@ #include <drm/display/drm_dp_helper.h> +struct intel_atomic_state; +struct intel_connector; struct intel_crtc_state; struct intel_dp; @@ -25,7 +27,8 @@ void intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, void intel_dp_set_signal_levels(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state, enum drm_dp_phy dp_phy); -void intel_dp_start_link_train(struct intel_dp *intel_dp, +void intel_dp_start_link_train(struct intel_atomic_state *state, + struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); void intel_dp_stop_link_train(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); @@ -42,4 +45,7 @@ static inline u8 intel_dp_training_pattern_symbol(u8 pattern) void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); + +void intel_dp_link_training_debugfs_add(struct intel_connector *connector); + #endif /* __INTEL_DP_LINK_TRAINING_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 715d2f59f565..27ce5c3f5951 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -105,7 +105,7 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state, dsc_slice_count = intel_dp_dsc_get_slice_count(connector, adjusted_mode->clock, adjusted_mode->hdisplay, - crtc_state->bigjoiner_pipes); + crtc_state->joiner_pipes); } overhead = drm_dp_bw_overhead(crtc_state->lane_count, @@ -207,6 +207,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, int remote_bw_overhead; int link_bpp_x16; int remote_tu; + fixed20_12 pbn; drm_dbg_kms(&i915->drm, "Trying bpp %d\n", bpp); @@ -237,11 +238,29 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, * crtc_state->dp_m_n.tu), provided that the driver doesn't * enable SSC on the corresponding link. */ - crtc_state->pbn = intel_dp_mst_calc_pbn(adjusted_mode->crtc_clock, - link_bpp_x16, - remote_bw_overhead); + pbn.full = dfixed_const(intel_dp_mst_calc_pbn(adjusted_mode->crtc_clock, + link_bpp_x16, + remote_bw_overhead)); + remote_tu = DIV_ROUND_UP(pbn.full, mst_state->pbn_div.full); - remote_tu = DIV_ROUND_UP(dfixed_const(crtc_state->pbn), mst_state->pbn_div.full); + /* + * Aligning the TUs ensures that symbols consisting of multiple + * (4) symbol cycles don't get split between two consecutive + * MTPs, as required by Bspec. + * TODO: remove the alignment restriction for 128b/132b links + * on some platforms, where Bspec allows this. + */ + remote_tu = ALIGN(remote_tu, 4 / crtc_state->lane_count); + + /* + * Also align PBNs accordingly, since MST core will derive its + * own copy of TU from the PBN in drm_dp_atomic_find_time_slots(). + * The above comment about the difference between the PBN + * allocated for the whole path and the TUs allocated for the + * first branch device's link also applies here. + */ + pbn.full = remote_tu * mst_state->pbn_div.full; + crtc_state->pbn = dfixed_trunc(pbn); drm_WARN_ON(&i915->drm, remote_tu < crtc_state->dp_m_n.tu); crtc_state->dp_m_n.tu = remote_tu; @@ -349,6 +368,8 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder, if (max_bpp > sink_max_bpp) max_bpp = sink_max_bpp; + crtc_state->pipe_bpp = max_bpp; + max_compressed_bpp = intel_dp_dsc_sink_max_compressed_bpp(connector, crtc_state, max_bpp / 3); @@ -400,18 +421,6 @@ static int intel_dp_mst_update_slots(struct intel_encoder *encoder, return 0; } -static bool -intel_dp_mst_dsc_source_support(const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - - /* - * FIXME: Enabling DSC on ICL results in blank screen and FIFO pipe / - * transcoder underruns, re-enable DSC after fixing this issue. - */ - return DISPLAY_VER(i915) >= 12 && intel_dsc_source_support(crtc_state); -} - static int mode_hblank_period_ns(const struct drm_display_mode *mode) { return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(mode->htotal - mode->hdisplay, @@ -456,7 +465,7 @@ adjust_limits_for_dsc_hblank_expansion_quirk(const struct intel_connector *conne return true; if (!dsc) { - if (intel_dp_mst_dsc_source_support(crtc_state)) { + if (intel_dp_supports_dsc(connector, crtc_state)) { drm_dbg_kms(&i915->drm, "[CRTC:%d:%s][CONNECTOR:%d:%s] DSC needed by hblank expansion quirk\n", crtc->base.base.id, crtc->base.name, @@ -567,16 +576,16 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; - if (intel_dp_need_bigjoiner(intel_dp, connector, - adjusted_mode->crtc_hdisplay, - adjusted_mode->crtc_clock)) - pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); + if (intel_dp_need_joiner(intel_dp, connector, + adjusted_mode->crtc_hdisplay, + adjusted_mode->crtc_clock)) + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->has_pch_encoder = false; - joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->bigjoiner_pipes); + joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->joiner_pipes); dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en || !intel_dp_mst_compute_config_limits(intel_dp, @@ -602,7 +611,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, str_yes_no(ret), str_yes_no(joiner_needs_dsc), str_yes_no(intel_dp->force_dsc_en)); - if (!intel_dp_mst_dsc_source_support(pipe_config)) + if (!intel_dp_supports_dsc(connector, pipe_config)) return -EINVAL; if (!intel_dp_mst_compute_config_limits(intel_dp, @@ -962,6 +971,9 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state, drm_dbg_kms(&i915->drm, "active links %d\n", intel_dp->active_mst_links); + if (intel_dp->active_mst_links == 1) + intel_dp->link_trained = false; + intel_hdcp_disable(intel_mst->connector); intel_dp_sink_disable_decompression(state, connector, old_crtc_state); @@ -1009,7 +1021,8 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, clear_act_sent(encoder, old_crtc_state); - intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder), + intel_de_rmw(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, old_crtc_state->cpu_transcoder), TRANS_DDI_DP_VC_PAYLOAD_ALLOC, 0); wait_for_act_sent(encoder, old_crtc_state); @@ -1230,7 +1243,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, clear_act_sent(encoder, pipe_config); - intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(trans), 0, + intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, trans), 0, TRANS_DDI_DP_VC_PAYLOAD_ALLOC); drm_dbg_kms(&dev_priv->drm, "active links %d\n", @@ -1375,7 +1388,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq; int max_rate, mode_rate, max_lanes, max_link_clock; int ret; - bool dsc = false, bigjoiner = false; + bool dsc = false, joiner = false; u16 dsc_max_compressed_bpp = 0; u8 dsc_slice_count = 0; int target_clock = mode->clock; @@ -1418,9 +1431,9 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, * corresponding link capabilities of the sink) in case the * stream is uncompressed for it by the last branch device. */ - if (intel_dp_need_bigjoiner(intel_dp, intel_connector, - mode->hdisplay, target_clock)) { - bigjoiner = true; + if (intel_dp_need_joiner(intel_dp, intel_connector, + mode->hdisplay, target_clock)) { + joiner = true; max_dotclk *= 2; } @@ -1434,8 +1447,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, return 0; } - if (HAS_DSC_MST(dev_priv) && - drm_dp_sink_supports_dsc(intel_connector->dp.dsc_dpcd)) { + if (intel_dp_has_dsc(intel_connector)) { /* * TBD pass the connector BPC, * for now U8_MAX so that max BPC on that platform would be picked @@ -1449,20 +1461,20 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, max_lanes, target_clock, mode->hdisplay, - bigjoiner, + joiner, INTEL_OUTPUT_FORMAT_RGB, pipe_bpp, 64); dsc_slice_count = intel_dp_dsc_get_slice_count(intel_connector, target_clock, mode->hdisplay, - bigjoiner); + joiner); } dsc = dsc_max_compressed_bpp && dsc_slice_count; } - if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner) && !dsc) { + if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) { *status = MODE_CLOCK_HIGH; return 0; } @@ -1472,7 +1484,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, return 0; } - *status = intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner); + *status = intel_mode_valid_max_plane_size(dev_priv, mode, joiner); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index a981f45facb3..d67d5e2fd570 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -398,12 +398,13 @@ void i9xx_dpll_get_hw_state(struct intel_crtc *crtc, if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A) tmp = dev_priv->display.state.chv_dpll_md[crtc->pipe]; else - tmp = intel_de_read(dev_priv, DPLL_MD(crtc->pipe)); + tmp = intel_de_read(dev_priv, + DPLL_MD(dev_priv, crtc->pipe)); hw_state->dpll_md = tmp; } - hw_state->dpll = intel_de_read(dev_priv, DPLL(crtc->pipe)); + hw_state->dpll = intel_de_read(dev_priv, DPLL(dev_priv, crtc->pipe)); if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) { hw_state->fp0 = intel_de_read(dev_priv, FP0(crtc->pipe)); @@ -1842,28 +1843,30 @@ void i9xx_enable_pll(const struct intel_crtc_state *crtc_state) * the P1/P2 dividers. Otherwise the DPLL will keep using the old * dividers, even though the register value does change. */ - intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll & ~DPLL_VGA_MODE_DIS); - intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), + hw_state->dpll & ~DPLL_VGA_MODE_DIS); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), hw_state->dpll); /* Wait for the clocks to stabilize. */ - intel_de_posting_read(dev_priv, DPLL(pipe)); + intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe)); udelay(150); if (DISPLAY_VER(dev_priv) >= 4) { - intel_de_write(dev_priv, DPLL_MD(pipe), hw_state->dpll_md); + intel_de_write(dev_priv, DPLL_MD(dev_priv, pipe), + hw_state->dpll_md); } else { /* The pixel multiplier can only be updated once the * DPLL is enabled and the clocks are stable. * * So write it again. */ - intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), hw_state->dpll); } /* We do this three times for luck */ for (i = 0; i < 3; i++) { - intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll); - intel_de_posting_read(dev_priv, DPLL(pipe)); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), hw_state->dpll); + intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe)); udelay(150); /* wait for warmup */ } } @@ -1991,11 +1994,11 @@ static void _vlv_enable_pll(const struct intel_crtc_state *crtc_state) const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; enum pipe pipe = crtc->pipe; - intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll); - intel_de_posting_read(dev_priv, DPLL(pipe)); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), hw_state->dpll); + intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe)); udelay(150); - if (intel_de_wait_for_set(dev_priv, DPLL(pipe), DPLL_LOCK_VLV, 1)) + if (intel_de_wait_for_set(dev_priv, DPLL(dev_priv, pipe), DPLL_LOCK_VLV, 1)) drm_err(&dev_priv->drm, "DPLL %d failed to lock\n", pipe); } @@ -2012,7 +2015,7 @@ void vlv_enable_pll(const struct intel_crtc_state *crtc_state) assert_pps_unlocked(dev_priv, pipe); /* Enable Refclk */ - intel_de_write(dev_priv, DPLL(pipe), + intel_de_write(dev_priv, DPLL(dev_priv, pipe), hw_state->dpll & ~(DPLL_VCO_ENABLE | DPLL_EXT_BUFFER_ENABLE_VLV)); if (hw_state->dpll & DPLL_VCO_ENABLE) { @@ -2020,8 +2023,8 @@ void vlv_enable_pll(const struct intel_crtc_state *crtc_state) _vlv_enable_pll(crtc_state); } - intel_de_write(dev_priv, DPLL_MD(pipe), hw_state->dpll_md); - intel_de_posting_read(dev_priv, DPLL_MD(pipe)); + intel_de_write(dev_priv, DPLL_MD(dev_priv, pipe), hw_state->dpll_md); + intel_de_posting_read(dev_priv, DPLL_MD(dev_priv, pipe)); } static void chv_prepare_pll(const struct intel_crtc_state *crtc_state) @@ -2138,10 +2141,10 @@ static void _chv_enable_pll(const struct intel_crtc_state *crtc_state) udelay(1); /* Enable PLL */ - intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), hw_state->dpll); /* Check PLL is locked */ - if (intel_de_wait_for_set(dev_priv, DPLL(pipe), DPLL_LOCK_VLV, 1)) + if (intel_de_wait_for_set(dev_priv, DPLL(dev_priv, pipe), DPLL_LOCK_VLV, 1)) drm_err(&dev_priv->drm, "PLL %d failed to lock\n", pipe); } @@ -2158,7 +2161,7 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state) assert_pps_unlocked(dev_priv, pipe); /* Enable Refclk and SSC */ - intel_de_write(dev_priv, DPLL(pipe), + intel_de_write(dev_priv, DPLL(dev_priv, pipe), hw_state->dpll & ~DPLL_VCO_ENABLE); if (hw_state->dpll & DPLL_VCO_ENABLE) { @@ -2174,7 +2177,8 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state) * the value from DPLLBMD to either pipe B or C. */ intel_de_write(dev_priv, CBR4_VLV, CBR_DPLLBMD_PIPE(pipe)); - intel_de_write(dev_priv, DPLL_MD(PIPE_B), hw_state->dpll_md); + intel_de_write(dev_priv, DPLL_MD(dev_priv, PIPE_B), + hw_state->dpll_md); intel_de_write(dev_priv, CBR4_VLV, 0); dev_priv->display.state.chv_dpll_md[pipe] = hw_state->dpll_md; @@ -2183,11 +2187,12 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state) * We should always have it disabled. */ drm_WARN_ON(&dev_priv->drm, - (intel_de_read(dev_priv, DPLL(PIPE_B)) & + (intel_de_read(dev_priv, DPLL(dev_priv, PIPE_B)) & DPLL_VGA_MODE_DIS) == 0); } else { - intel_de_write(dev_priv, DPLL_MD(pipe), hw_state->dpll_md); - intel_de_posting_read(dev_priv, DPLL_MD(pipe)); + intel_de_write(dev_priv, DPLL_MD(dev_priv, pipe), + hw_state->dpll_md); + intel_de_posting_read(dev_priv, DPLL_MD(dev_priv, pipe)); } } @@ -2241,8 +2246,8 @@ void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) if (pipe != PIPE_A) val |= DPLL_INTEGRATED_CRI_CLK_VLV; - intel_de_write(dev_priv, DPLL(pipe), val); - intel_de_posting_read(dev_priv, DPLL(pipe)); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), val); + intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe)); } void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) @@ -2259,8 +2264,8 @@ void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) if (pipe != PIPE_A) val |= DPLL_INTEGRATED_CRI_CLK_VLV; - intel_de_write(dev_priv, DPLL(pipe), val); - intel_de_posting_read(dev_priv, DPLL(pipe)); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), val); + intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe)); vlv_dpio_get(dev_priv); @@ -2285,8 +2290,8 @@ void i9xx_disable_pll(const struct intel_crtc_state *crtc_state) /* Make sure the pipe isn't still relying on us */ assert_transcoder_disabled(dev_priv, crtc_state->cpu_transcoder); - intel_de_write(dev_priv, DPLL(pipe), DPLL_VGA_MODE_DIS); - intel_de_posting_read(dev_priv, DPLL(pipe)); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), DPLL_VGA_MODE_DIS); + intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe)); } @@ -2312,7 +2317,7 @@ static void assert_pll(struct drm_i915_private *dev_priv, { bool cur_state; - cur_state = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE; + cur_state = intel_de_read(dev_priv, DPLL(dev_priv, pipe)) & DPLL_VCO_ENABLE; I915_STATE_WARN(dev_priv, cur_state != state, "PLL state assertion failure (expected %s, current %s)\n", str_on_off(state), str_on_off(cur_state)); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index f09e513ce05b..36baed75b89a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -264,6 +264,7 @@ struct intel_cx0pll_state { struct intel_c20pll_state c20; }; bool ssc_enabled; + bool use_c10; }; struct intel_dpll_hw_state { diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index b29bceff73f2..73a1918e2537 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -121,7 +121,8 @@ static void dpt_cleanup(struct i915_address_space *vm) i915_gem_object_put(dpt->obj); } -struct i915_vma *intel_dpt_pin(struct i915_address_space *vm) +struct i915_vma *intel_dpt_pin_to_ggtt(struct i915_address_space *vm, + unsigned int alignment) { struct drm_i915_private *i915 = vm->i915; struct i915_dpt *dpt = i915_vm_to_dpt(vm); @@ -143,8 +144,8 @@ struct i915_vma *intel_dpt_pin(struct i915_address_space *vm) if (err) continue; - vma = i915_gem_object_ggtt_pin_ww(dpt->obj, &ww, NULL, 0, 4096, - pin_flags); + vma = i915_gem_object_ggtt_pin_ww(dpt->obj, &ww, NULL, 0, + alignment, pin_flags); if (IS_ERR(vma)) { err = PTR_ERR(vma); continue; @@ -172,7 +173,7 @@ struct i915_vma *intel_dpt_pin(struct i915_address_space *vm) return err ? ERR_PTR(err) : vma; } -void intel_dpt_unpin(struct i915_address_space *vm) +void intel_dpt_unpin_from_ggtt(struct i915_address_space *vm) { struct i915_dpt *dpt = i915_vm_to_dpt(vm); diff --git a/drivers/gpu/drm/i915/display/intel_dpt.h b/drivers/gpu/drm/i915/display/intel_dpt.h index e18a9f767b11..ff18a525bfbe 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.h +++ b/drivers/gpu/drm/i915/display/intel_dpt.h @@ -13,8 +13,9 @@ struct i915_vma; struct intel_framebuffer; void intel_dpt_destroy(struct i915_address_space *vm); -struct i915_vma *intel_dpt_pin(struct i915_address_space *vm); -void intel_dpt_unpin(struct i915_address_space *vm); +struct i915_vma *intel_dpt_pin_to_ggtt(struct i915_address_space *vm, + unsigned int alignment); +void intel_dpt_unpin_from_ggtt(struct i915_address_space *vm); void intel_dpt_suspend(struct drm_i915_private *i915); void intel_dpt_resume(struct drm_i915_private *i915); struct i915_address_space * diff --git a/drivers/gpu/drm/i915/display/intel_dpt_common.c b/drivers/gpu/drm/i915/display/intel_dpt_common.c index cdba47165c04..573f72068899 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt_common.c +++ b/drivers/gpu/drm/i915/display/intel_dpt_common.c @@ -7,6 +7,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_dpt_common.h" +#include "skl_universal_plane_regs.h" void intel_dpt_configure(struct intel_crtc *crtc) { diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 597f8bd6aa1a..3ca29afa5422 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -85,7 +85,7 @@ intel_drrs_set_refresh_rate_pipeconf(struct intel_crtc *crtc, else bit = TRANSCONF_REFRESH_RATE_ALT_ILK; - intel_de_rmw(dev_priv, TRANSCONF(cpu_transcoder), + intel_de_rmw(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), bit, refresh_rate == DRRS_REFRESH_RATE_LOW ? bit : 0); } @@ -135,7 +135,7 @@ static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *c frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, - crtc_state->bigjoiner_pipes) + crtc_state->joiner_pipes) frontbuffer_bits |= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); return frontbuffer_bits; @@ -157,7 +157,7 @@ void intel_drrs_activate(const struct intel_crtc_state *crtc_state) if (!crtc_state->hw.active) return; - if (intel_crtc_is_bigjoiner_slave(crtc_state)) + if (intel_crtc_is_joiner_secondary(crtc_state)) return; mutex_lock(&crtc->drrs.mutex); @@ -189,7 +189,7 @@ void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state) if (!old_crtc_state->hw.active) return; - if (intel_crtc_is_bigjoiner_slave(old_crtc_state)) + if (intel_crtc_is_joiner_secondary(old_crtc_state)) return; mutex_lock(&crtc->drrs.mutex); diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 4baaa92ceaec..5180b9722046 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -6,7 +6,6 @@ #include "i915_drv.h" #include "i915_irq.h" -#include "i915_reg.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_types.h" @@ -19,16 +18,8 @@ #define CACHELINE_BYTES 64 -enum dsb_id { - INVALID_DSB = -1, - DSB1, - DSB2, - DSB3, - MAX_DSB_PER_PIPE -}; - struct intel_dsb { - enum dsb_id id; + enum intel_dsb_id id; struct intel_dsb_buffer dsb_buf; struct intel_crtc *crtc; @@ -121,9 +112,9 @@ static void intel_dsb_dump(struct intel_dsb *dsb) } static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe, - enum dsb_id id) + enum intel_dsb_id dsb_id) { - return intel_de_read_fw(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY; + return intel_de_read_fw(i915, DSB_CTRL(pipe, dsb_id)) & DSB_STATUS_BUSY; } static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw) @@ -328,14 +319,10 @@ static int intel_dsb_dewake_scanline(const struct intel_crtc_state *crtc_state) unsigned int latency = skl_watermark_max_latency(i915, 0); int vblank_start; - if (crtc_state->vrr.enable) { + if (crtc_state->vrr.enable) vblank_start = intel_vrr_vmin_vblank_start(crtc_state); - } else { - vblank_start = adjusted_mode->crtc_vblank_start; - - if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) - vblank_start = DIV_ROUND_UP(vblank_start, 2); - } + else + vblank_start = intel_mode_vblank_start(adjusted_mode); return max(0, vblank_start - intel_usecs_to_scanlines(adjusted_mode, latency)); } @@ -448,6 +435,7 @@ void intel_dsb_wait(struct intel_dsb *dsb) /** * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer. * @crtc_state: the CRTC state + * @dsb_id: the DSB engine to use * @max_cmds: number of commands we need to fit into command buffer * * This function prepare the command buffer which is used to store dsb @@ -457,6 +445,7 @@ void intel_dsb_wait(struct intel_dsb *dsb) * DSB context, NULL on failure */ struct intel_dsb *intel_dsb_prepare(const struct intel_crtc_state *crtc_state, + enum intel_dsb_id dsb_id, unsigned int max_cmds) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -486,7 +475,7 @@ struct intel_dsb *intel_dsb_prepare(const struct intel_crtc_state *crtc_state, intel_runtime_pm_put(&i915->runtime_pm, wakeref); - dsb->id = DSB1; + dsb->id = dsb_id; dsb->crtc = crtc; dsb->size = size / 4; /* in dwords */ dsb->free_pos = 0; @@ -501,7 +490,7 @@ out_put_rpm: out: drm_info_once(&i915->drm, "[CRTC:%d:%s] DSB %d queue setup failed, will fallback to MMIO for display HW programming\n", - crtc->base.base.id, crtc->base.name, DSB1); + crtc->base.base.id, crtc->base.name, dsb_id); return NULL; } diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index 16d80f434356..36fdb130af6e 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -14,7 +14,16 @@ struct intel_crtc; struct intel_crtc_state; struct intel_dsb; +enum intel_dsb_id { + INTEL_DSB_0, + INTEL_DSB_1, + INTEL_DSB_2, + + I915_MAX_DSBS, +}; + struct intel_dsb *intel_dsb_prepare(const struct intel_crtc_state *crtc_state, + enum intel_dsb_id dsb_id, unsigned int max_cmds); void intel_dsb_finish(struct intel_dsb *dsb); void intel_dsb_cleanup(struct intel_dsb *dsb); diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index a5d7fc8418c9..072ef1d62bda 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -353,14 +353,14 @@ static void icl_native_gpio_set_value(struct drm_i915_private *dev_priv, case MIPI_AVDD_EN_2: index = gpio == MIPI_AVDD_EN_1 ? 0 : 1; - intel_de_rmw(dev_priv, PP_CONTROL(index), PANEL_POWER_ON, + intel_de_rmw(dev_priv, PP_CONTROL(dev_priv, index), PANEL_POWER_ON, value ? PANEL_POWER_ON : 0); break; case MIPI_BKLT_EN_1: case MIPI_BKLT_EN_2: index = gpio == MIPI_BKLT_EN_1 ? 0 : 1; - intel_de_rmw(dev_priv, PP_CONTROL(index), EDP_BLC_ENABLE, + intel_de_rmw(dev_priv, PP_CONTROL(dev_priv, index), EDP_BLC_ENABLE, value ? EDP_BLC_ENABLE : 0); break; case MIPI_AVEE_EN_1: @@ -751,7 +751,7 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id) struct intel_connector *connector = intel_dsi->attached_connector; struct mipi_config *mipi_config = connector->panel.vbt.dsi.config; struct mipi_pps_data *pps = connector->panel.vbt.dsi.pps; - struct drm_display_mode *mode = connector->panel.vbt.lfp_lvds_vbt_mode; + struct drm_display_mode *mode = connector->panel.vbt.lfp_vbt_mode; u16 burst_mode_ratio; enum port port; diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 1840f5b59229..091824334f26 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -456,13 +456,14 @@ static bool intel_dvo_init_dev(struct drm_i915_private *dev_priv, * the device. */ for_each_pipe(dev_priv, pipe) - dpll[pipe] = intel_de_rmw(dev_priv, DPLL(pipe), 0, DPLL_DVO_2X_MODE); + dpll[pipe] = intel_de_rmw(dev_priv, DPLL(dev_priv, pipe), 0, + DPLL_DVO_2X_MODE); ret = dvo->dev_ops->init(&intel_dvo->dev, i2c); /* restore the DVO 2x clock state to original */ for_each_pipe(dev_priv, pipe) { - intel_de_write(dev_priv, DPLL(pipe), dpll[pipe]); + intel_de_write(dev_priv, DPLL(dev_priv, pipe), dpll[pipe]); } intel_gmbus_force_bit(i2c, false); diff --git a/drivers/gpu/drm/i915/display/intel_encoder.c b/drivers/gpu/drm/i915/display/intel_encoder.c new file mode 100644 index 000000000000..dee55f56960f --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_encoder.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2024 Intel Corporation + */ + +#include <linux/workqueue.h> + +#include "i915_drv.h" + +#include "intel_display_types.h" +#include "intel_encoder.h" + +static void intel_encoder_link_check_work_fn(struct work_struct *work) +{ + struct intel_encoder *encoder = + container_of(work, typeof(*encoder), link_check_work.work); + + encoder->link_check(encoder); +} + +void intel_encoder_link_check_init(struct intel_encoder *encoder, + void (*callback)(struct intel_encoder *encoder)) +{ + INIT_DELAYED_WORK(&encoder->link_check_work, intel_encoder_link_check_work_fn); + encoder->link_check = callback; +} + +void intel_encoder_link_check_flush_work(struct intel_encoder *encoder) +{ + cancel_delayed_work_sync(&encoder->link_check_work); +} + +void intel_encoder_link_check_queue_work(struct intel_encoder *encoder, int delay_ms) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + mod_delayed_work(i915->unordered_wq, + &encoder->link_check_work, msecs_to_jiffies(delay_ms)); +} diff --git a/drivers/gpu/drm/i915/display/intel_encoder.h b/drivers/gpu/drm/i915/display/intel_encoder.h new file mode 100644 index 000000000000..2cda054e2b15 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_encoder.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __INTEL_ENCODER_H__ +#define __INTEL_ENCODER_H__ + +struct intel_encoder; + +void intel_encoder_link_check_init(struct intel_encoder *encoder, + void (*callback)(struct intel_encoder *encoder)); +void intel_encoder_link_check_queue_work(struct intel_encoder *encoder, int delay_ms); +void intel_encoder_link_check_flush_work(struct intel_encoder *encoder); + +#endif /* __INTEL_ENCODER_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 86b443433e8b..8069abf91c5e 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -9,6 +9,7 @@ #include <linux/dma-fence.h> #include <linux/dma-resv.h> +#include "gem/i915_gem_object.h" #include "i915_drv.h" #include "intel_display.h" #include "intel_display_types.h" @@ -805,8 +806,23 @@ unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, { struct drm_i915_private *dev_priv = to_i915(fb->dev); - if (intel_fb_uses_dpt(fb)) + if (intel_fb_uses_dpt(fb)) { + /* AUX_DIST needs only 4K alignment */ + if (intel_fb_is_ccs_aux_plane(fb, color_plane)) + return 512 * 4096; + + /* + * FIXME ADL sees GGTT/DMAR faults with async + * flips unless we align to 16k at least. + * Figure out what's going on here... + */ + if (IS_ALDERLAKE_P(dev_priv) && + !intel_fb_is_ccs_modifier(fb->modifier) && + HAS_ASYNC_FLIPS(dev_priv)) + return 512 * 16 * 1024; + return 512 * 4096; + } /* AUX_DIST needs only 4K alignment */ if (intel_fb_is_ccs_aux_plane(fb, color_plane)) @@ -1030,7 +1046,7 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *i915, int color_plane, unsigned int pitch, unsigned int rotation, - u32 alignment) + unsigned int alignment) { unsigned int cpp = fb->format->cpp[color_plane]; u32 offset, offset_aligned; @@ -1087,8 +1103,8 @@ u32 intel_plane_compute_aligned_offset(int *x, int *y, struct drm_i915_private *i915 = to_i915(intel_plane->base.dev); const struct drm_framebuffer *fb = state->hw.fb; unsigned int rotation = state->hw.rotation; - int pitch = state->view.color_plane[color_plane].mapping_stride; - u32 alignment; + unsigned int pitch = state->view.color_plane[color_plane].mapping_stride; + unsigned int alignment; if (intel_plane->id == PLANE_CURSOR) alignment = intel_cursor_alignment(i915); @@ -1105,8 +1121,7 @@ static int intel_fb_offset_to_xy(int *x, int *y, int color_plane) { struct drm_i915_private *i915 = to_i915(fb->dev); - unsigned int height; - u32 alignment, unused; + unsigned int height, alignment, unused; if (DISPLAY_VER(i915) >= 12 && !intel_fb_needs_pot_stride_remap(to_intel_framebuffer(fb)) && @@ -1493,8 +1508,8 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p check_array_bounds(i915, view->gtt.remapped.plane, color_plane); if (view->gtt.remapped.plane_alignment) { - unsigned int aligned_offset = ALIGN(gtt_offset, - view->gtt.remapped.plane_alignment); + u32 aligned_offset = ALIGN(gtt_offset, + view->gtt.remapped.plane_alignment); size += aligned_offset - gtt_offset; gtt_offset = aligned_offset; @@ -1780,16 +1795,16 @@ u32 intel_fb_max_stride(struct drm_i915_private *dev_priv, return 128 * 1024; } -static u32 +static unsigned int intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane) { struct drm_i915_private *dev_priv = to_i915(fb->dev); - u32 tile_width; + unsigned int tile_width; if (is_surface_linear(fb, color_plane)) { - u32 max_stride = intel_plane_fb_max_stride(dev_priv, - fb->format->format, - fb->modifier); + unsigned int max_stride = intel_plane_fb_max_stride(dev_priv, + fb->format->format, + fb->modifier); /* * To make remapping with linear generally feasible @@ -2046,7 +2061,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb, drm_helper_mode_fill_fb_struct(&dev_priv->drm, fb, mode_cmd); for (i = 0; i < fb->format->num_planes; i++) { - u32 stride_alignment; + unsigned int stride_alignment; if (mode_cmd->handles[i] != mode_cmd->handles[0]) { drm_dbg_kms(&dev_priv->drm, "bad plane %d handle\n", @@ -2063,7 +2078,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb, } if (intel_fb_is_gen12_ccs_aux_plane(fb, i)) { - int ccs_aux_stride = gen12_ccs_aux_stride(intel_fb, i); + unsigned int ccs_aux_stride = gen12_ccs_aux_stride(intel_fb, i); if (fb->pitches[i] != ccs_aux_stride) { drm_dbg_kms(&dev_priv->drm, diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c index b6df9baf481b..1acc11fa19f4 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c @@ -11,24 +11,24 @@ #include "gem/i915_gem_object.h" #include "i915_drv.h" +#include "intel_atomic_plane.h" #include "intel_display_types.h" #include "intel_dpt.h" #include "intel_fb.h" #include "intel_fb_pin.h" static struct i915_vma * -intel_pin_fb_obj_dpt(struct drm_framebuffer *fb, - const struct i915_gtt_view *view, - bool uses_fence, - unsigned long *out_flags, - struct i915_address_space *vm) +intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, + const struct i915_gtt_view *view, + unsigned int alignment, + unsigned long *out_flags, + struct i915_address_space *vm) { struct drm_device *dev = fb->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct i915_gem_ww_ctx ww; struct i915_vma *vma; - u32 alignment; int ret; /* @@ -41,8 +41,6 @@ intel_pin_fb_obj_dpt(struct drm_framebuffer *fb, if (WARN_ON(!i915_gem_object_is_framebuffer(obj))) return ERR_PTR(-EINVAL); - alignment = 4096 * 512; - atomic_inc(&dev_priv->gpu_error.pending_fb_pin); for_i915_gem_ww(&ww, ret, true) { @@ -104,20 +102,20 @@ err: } struct i915_vma * -intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, - bool phys_cursor, - const struct i915_gtt_view *view, - bool uses_fence, - unsigned long *out_flags) +intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, + bool phys_cursor, + const struct i915_gtt_view *view, + bool uses_fence, + unsigned long *out_flags) { struct drm_device *dev = fb->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_object *obj = intel_fb_obj(fb); intel_wakeref_t wakeref; struct i915_gem_ww_ctx ww; + unsigned int alignment; struct i915_vma *vma; unsigned int pinctl; - u32 alignment; int ret; if (drm_WARN_ON(dev, !i915_gem_object_is_framebuffer(obj))) @@ -228,7 +226,7 @@ err: return vma; } -void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags) +void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags) { if (flags & PLANE_HAS_FENCE) i915_vma_unpin_fence(vma); @@ -239,18 +237,15 @@ void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags) int intel_plane_pin_fb(struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - struct drm_framebuffer *fb = plane_state->hw.fb; + const struct intel_framebuffer *fb = + to_intel_framebuffer(plane_state->hw.fb); struct i915_vma *vma; - bool phys_cursor = - plane->id == PLANE_CURSOR && - DISPLAY_INFO(dev_priv)->cursor_needs_physical; - - if (!intel_fb_uses_dpt(fb)) { - vma = intel_pin_and_fence_fb_obj(fb, phys_cursor, - &plane_state->view.gtt, - intel_plane_uses_fence(plane_state), - &plane_state->flags); + + if (!intel_fb_uses_dpt(&fb->base)) { + vma = intel_fb_pin_to_ggtt(&fb->base, intel_plane_needs_physical(plane), + &plane_state->view.gtt, + intel_plane_uses_fence(plane_state), + &plane_state->flags); if (IS_ERR(vma)) return PTR_ERR(vma); @@ -262,22 +257,23 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state) * will trigger might_sleep() even if it won't actually sleep, * which is the case when the fb has already been pinned. */ - if (phys_cursor) + if (intel_plane_needs_physical(plane)) plane_state->phys_dma_addr = - i915_gem_object_get_dma_address(intel_fb_obj(fb), 0); + i915_gem_object_get_dma_address(intel_fb_obj(&fb->base), 0); } else { - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + unsigned int alignment = intel_surf_alignment(&fb->base, 0); - vma = intel_dpt_pin(intel_fb->dpt_vm); + vma = intel_dpt_pin_to_ggtt(fb->dpt_vm, alignment / 512); if (IS_ERR(vma)) return PTR_ERR(vma); plane_state->ggtt_vma = vma; - vma = intel_pin_fb_obj_dpt(fb, &plane_state->view.gtt, false, - &plane_state->flags, intel_fb->dpt_vm); + vma = intel_fb_pin_to_dpt(&fb->base, &plane_state->view.gtt, + alignment, &plane_state->flags, + fb->dpt_vm); if (IS_ERR(vma)) { - intel_dpt_unpin(intel_fb->dpt_vm); + intel_dpt_unpin_from_ggtt(fb->dpt_vm); plane_state->ggtt_vma = NULL; return PTR_ERR(vma); } @@ -292,22 +288,21 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state) void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state) { - struct drm_framebuffer *fb = old_plane_state->hw.fb; + const struct intel_framebuffer *fb = + to_intel_framebuffer(old_plane_state->hw.fb); struct i915_vma *vma; - if (!intel_fb_uses_dpt(fb)) { + if (!intel_fb_uses_dpt(&fb->base)) { vma = fetch_and_zero(&old_plane_state->ggtt_vma); if (vma) - intel_unpin_fb_vma(vma, old_plane_state->flags); + intel_fb_unpin_vma(vma, old_plane_state->flags); } else { - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - vma = fetch_and_zero(&old_plane_state->dpt_vma); if (vma) - intel_unpin_fb_vma(vma, old_plane_state->flags); + intel_fb_unpin_vma(vma, old_plane_state->flags); vma = fetch_and_zero(&old_plane_state->ggtt_vma); if (vma) - intel_dpt_unpin(intel_fb->dpt_vm); + intel_dpt_unpin_from_ggtt(fb->dpt_vm); } } diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.h b/drivers/gpu/drm/i915/display/intel_fb_pin.h index de0efaa25905..3f8245edcd15 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.h +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.h @@ -14,13 +14,13 @@ struct intel_plane_state; struct i915_gtt_view; struct i915_vma * -intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, - bool phys_cursor, - const struct i915_gtt_view *view, - bool uses_fence, - unsigned long *out_flags); +intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, + bool phys_cursor, + const struct i915_gtt_view *view, + bool uses_fence, + unsigned long *out_flags); -void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags); +void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags); int intel_plane_pin_fb(struct intel_plane_state *plane_state); void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 151dcd0c45b6..67116c9f1464 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -43,11 +43,14 @@ #include <drm/drm_blend.h> #include <drm/drm_fourcc.h> +#include "gem/i915_gem_stolen.h" +#include "gt/intel_gt_types.h" #include "i915_drv.h" #include "i915_reg.h" #include "i915_utils.h" #include "i915_vgpu.h" #include "i915_vma.h" +#include "i9xx_plane_regs.h" #include "intel_cdclk.h" #include "intel_de.h" #include "intel_display_device.h" @@ -326,8 +329,8 @@ static void i8xx_fbc_nuke(struct intel_fbc *fbc) enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane; struct drm_i915_private *dev_priv = fbc->i915; - intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), - intel_de_read_fw(dev_priv, DSPADDR(i9xx_plane))); + intel_de_write_fw(dev_priv, DSPADDR(dev_priv, i9xx_plane), + intel_de_read_fw(dev_priv, DSPADDR(dev_priv, i9xx_plane))); } static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) @@ -363,8 +366,8 @@ static void i965_fbc_nuke(struct intel_fbc *fbc) enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane; struct drm_i915_private *dev_priv = fbc->i915; - intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), - intel_de_read_fw(dev_priv, DSPSURF(i9xx_plane))); + intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane), + intel_de_read_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane))); } static const struct intel_fbc_funcs i965_fbc_funcs = { @@ -1234,6 +1237,12 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } + /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */ + if (i915_vtd_active(i915) && (IS_SKYLAKE(i915) || IS_BROXTON(i915))) { + plane_state->no_fbc_reason = "VT-d enabled"; + return 0; + } + crtc_state = intel_atomic_get_new_crtc_state(state, crtc); if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { @@ -1251,7 +1260,8 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, * Recommendation is to keep this combination disabled * Bspec: 50422 HSD: 14010260002 */ - if (IS_DISPLAY_VER(i915, 12, 14) && crtc_state->has_psr2) { + if (IS_DISPLAY_VER(i915, 12, 14) && crtc_state->has_sel_update && + !crtc_state->has_panel_replay) { plane_state->no_fbc_reason = "PSR2 enabled"; return 0; } @@ -1259,7 +1269,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, /* Wa_14016291713 */ if ((IS_DISPLAY_VER(i915, 12, 13) || IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_C0)) && - crtc_state->has_psr) { + crtc_state->has_psr && !crtc_state->has_panel_replay) { plane_state->no_fbc_reason = "PSR1 enabled (Wa_14016291713)"; return 0; } @@ -1818,19 +1828,6 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *i915) return 0; } -static bool need_fbc_vtd_wa(struct drm_i915_private *i915) -{ - /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */ - if (i915_vtd_active(i915) && - (IS_SKYLAKE(i915) || IS_BROXTON(i915))) { - drm_info(&i915->drm, - "Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n"); - return true; - } - - return false; -} - void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane) { plane->fbc = fbc; @@ -1876,9 +1873,6 @@ void intel_fbc_init(struct drm_i915_private *i915) { enum intel_fbc_id fbc_id; - if (need_fbc_vtd_wa(i915)) - DISPLAY_RUNTIME_INFO(i915)->fbc_mask = 0; - i915->display.params.enable_fbc = intel_sanitize_fbc_option(i915); drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n", i915->display.params.enable_fbc); diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index bda702c2cab8..37ae176bfeb0 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -44,6 +44,7 @@ #include <drm/drm_gem_framebuffer_helper.h> #include "gem/i915_gem_mman.h" +#include "gem/i915_gem_object.h" #include "i915_drv.h" #include "intel_display_types.h" @@ -146,7 +147,7 @@ static void intel_fbdev_fb_destroy(struct fb_info *info) * the info->screen_base mmaping. Leaking the VMA is simpler than * trying to rectify all the possible error paths leading here. */ - intel_unpin_fb_vma(ifbdev->vma, ifbdev->vma_flags); + intel_fb_unpin_vma(ifbdev->vma, ifbdev->vma_flags); drm_framebuffer_remove(&ifbdev->fb->base); drm_client_release(&fb_helper->client); @@ -175,7 +176,7 @@ static int intelfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct intel_fbdev *ifbdev = to_intel_fbdev(helper); - struct intel_framebuffer *intel_fb = ifbdev->fb; + struct intel_framebuffer *fb = ifbdev->fb; struct drm_device *dev = helper->dev; struct drm_i915_private *dev_priv = to_i915(dev); const struct i915_gtt_view view = { @@ -195,30 +196,30 @@ static int intelfb_create(struct drm_fb_helper *helper, if (ret) return ret; - if (intel_fb && - (sizes->fb_width > intel_fb->base.width || - sizes->fb_height > intel_fb->base.height)) { + ifbdev->fb = NULL; + + if (fb && + (sizes->fb_width > fb->base.width || + sizes->fb_height > fb->base.height)) { drm_dbg_kms(&dev_priv->drm, "BIOS fb too small (%dx%d), we require (%dx%d)," " releasing it\n", - intel_fb->base.width, intel_fb->base.height, + fb->base.width, fb->base.height, sizes->fb_width, sizes->fb_height); - drm_framebuffer_put(&intel_fb->base); - intel_fb = ifbdev->fb = NULL; + drm_framebuffer_put(&fb->base); + fb = NULL; } - if (!intel_fb || drm_WARN_ON(dev, !intel_fb_obj(&intel_fb->base))) { - struct drm_framebuffer *fb; + if (!fb || drm_WARN_ON(dev, !intel_fb_obj(&fb->base))) { drm_dbg_kms(&dev_priv->drm, "no BIOS fb, allocating a new one\n"); fb = intel_fbdev_fb_alloc(helper, sizes); if (IS_ERR(fb)) return PTR_ERR(fb); - intel_fb = ifbdev->fb = to_intel_framebuffer(fb); } else { drm_dbg_kms(&dev_priv->drm, "re-using BIOS fb\n"); prealloc = true; - sizes->fb_width = intel_fb->base.width; - sizes->fb_height = intel_fb->base.height; + sizes->fb_width = fb->base.width; + sizes->fb_height = fb->base.height; } wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); @@ -227,8 +228,8 @@ static int intelfb_create(struct drm_fb_helper *helper, * This also validates that any existing fb inherited from the * BIOS is suitable for own access. */ - vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, false, - &view, false, &flags); + vma = intel_fb_pin_to_ggtt(&fb->base, false, + &view, false, &flags); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_unlock; @@ -241,11 +242,11 @@ static int intelfb_create(struct drm_fb_helper *helper, goto out_unpin; } - ifbdev->helper.fb = &ifbdev->fb->base; + ifbdev->helper.fb = &fb->base; info->fbops = &intelfb_ops; - obj = intel_fb_obj(&intel_fb->base); + obj = intel_fb_obj(&fb->base); ret = intel_fbdev_fb_fill_info(dev_priv, info, obj, vma); if (ret) @@ -263,8 +264,9 @@ static int intelfb_create(struct drm_fb_helper *helper, /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ drm_dbg_kms(&dev_priv->drm, "allocated %dx%d fb: 0x%08x\n", - ifbdev->fb->base.width, ifbdev->fb->base.height, + fb->base.width, fb->base.height, i915_ggtt_offset(vma)); + ifbdev->fb = fb; ifbdev->vma = vma; ifbdev->vma_flags = flags; @@ -273,7 +275,7 @@ static int intelfb_create(struct drm_fb_helper *helper, return 0; out_unpin: - intel_unpin_fb_vma(vma, flags); + intel_fb_unpin_vma(vma, flags); out_unlock: intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); return ret; diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c index 0665f943f65f..497525ef9668 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c @@ -11,8 +11,8 @@ #include "intel_display_types.h" #include "intel_fbdev_fb.h" -struct drm_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) +struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) { struct drm_framebuffer *fb; struct drm_device *dev = helper->dev; @@ -63,7 +63,7 @@ struct drm_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, fb = intel_framebuffer_create(obj, &mode_cmd); i915_gem_object_put(obj); - return fb; + return to_intel_framebuffer(fb); } int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info, diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.h b/drivers/gpu/drm/i915/display/intel_fbdev_fb.h index a395b2c65d33..4832fe688fbf 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fbdev_fb.h @@ -13,8 +13,8 @@ struct drm_i915_private; struct fb_info; struct i915_vma; -struct drm_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes); +struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes); int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info, struct drm_i915_gem_object *obj, struct i915_vma *vma); diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index 295a0f24ebbf..d33befd7994d 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -34,7 +34,8 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv, * so pipe->transcoder cast is fine here. */ enum transcoder cpu_transcoder = (enum transcoder)pipe; - cur_state = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)) & TRANS_DDI_FUNC_ENABLE; + cur_state = intel_de_read(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)) & TRANS_DDI_FUNC_ENABLE; } else { cur_state = intel_de_read(dev_priv, FDI_TX_CTL(pipe)) & FDI_TX_ENABLE; } @@ -514,7 +515,7 @@ static void ilk_fdi_link_train(struct intel_crtc *crtc, * detection works. */ intel_de_write(dev_priv, FDI_RX_TUSIZE1(pipe), - intel_de_read(dev_priv, PIPE_DATA_M1(pipe)) & TU_SIZE_MASK); + intel_de_read(dev_priv, PIPE_DATA_M1(dev_priv, pipe)) & TU_SIZE_MASK); /* FDI needs bits from pipe first */ assert_transcoder_enabled(dev_priv, crtc_state->cpu_transcoder); @@ -616,7 +617,7 @@ static void gen6_fdi_link_train(struct intel_crtc *crtc, * detection works. */ intel_de_write(dev_priv, FDI_RX_TUSIZE1(pipe), - intel_de_read(dev_priv, PIPE_DATA_M1(pipe)) & TU_SIZE_MASK); + intel_de_read(dev_priv, PIPE_DATA_M1(dev_priv, pipe)) & TU_SIZE_MASK); /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit for train result */ @@ -754,7 +755,7 @@ static void ivb_manual_fdi_link_train(struct intel_crtc *crtc, * detection works. */ intel_de_write(dev_priv, FDI_RX_TUSIZE1(pipe), - intel_de_read(dev_priv, PIPE_DATA_M1(pipe)) & TU_SIZE_MASK); + intel_de_read(dev_priv, PIPE_DATA_M1(dev_priv, pipe)) & TU_SIZE_MASK); /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit for train result */ @@ -1034,7 +1035,7 @@ void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state) temp = intel_de_read(dev_priv, reg); temp &= ~(FDI_DP_PORT_WIDTH_MASK | (0x7 << 16)); temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes); - temp |= (intel_de_read(dev_priv, TRANSCONF(pipe)) & TRANSCONF_BPC_MASK) << 11; + temp |= (intel_de_read(dev_priv, TRANSCONF(dev_priv, pipe)) & TRANSCONF_BPC_MASK) << 11; intel_de_write(dev_priv, reg, temp | FDI_RX_PLL_ENABLE); intel_de_posting_read(dev_priv, reg); @@ -1090,7 +1091,7 @@ void ilk_fdi_disable(struct intel_crtc *crtc) reg = FDI_RX_CTL(pipe); temp = intel_de_read(dev_priv, reg); temp &= ~(0x7 << 16); - temp |= (intel_de_read(dev_priv, TRANSCONF(pipe)) & TRANSCONF_BPC_MASK) << 11; + temp |= (intel_de_read(dev_priv, TRANSCONF(dev_priv, pipe)) & TRANSCONF_BPC_MASK) << 11; intel_de_write(dev_priv, reg, temp & ~FDI_RX_ENABLE); intel_de_posting_read(dev_priv, reg); @@ -1116,7 +1117,7 @@ void ilk_fdi_disable(struct intel_crtc *crtc) } /* BPC in FDI rx is consistent with that in TRANSCONF */ temp &= ~(0x07 << 16); - temp |= (intel_de_read(dev_priv, TRANSCONF(pipe)) & TRANSCONF_BPC_MASK) << 11; + temp |= (intel_de_read(dev_priv, TRANSCONF(dev_priv, pipe)) & TRANSCONF_BPC_MASK) << 11; intel_de_write(dev_priv, reg, temp); intel_de_posting_read(dev_priv, reg); diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c index 09a7fa6c0c37..e5e4ca7cc499 100644 --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c @@ -94,7 +94,7 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev) static void i9xx_check_fifo_underruns(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - i915_reg_t reg = PIPESTAT(crtc->pipe); + i915_reg_t reg = PIPESTAT(dev_priv, crtc->pipe); u32 enable_mask; lockdep_assert_held(&dev_priv->irq_lock); @@ -115,7 +115,7 @@ static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, bool enable, bool old) { struct drm_i915_private *dev_priv = to_i915(dev); - i915_reg_t reg = PIPESTAT(pipe); + i915_reg_t reg = PIPESTAT(dev_priv, pipe); lockdep_assert_held(&dev_priv->irq_lock); @@ -209,7 +209,8 @@ static void bdw_set_fifo_underrun_reporting(struct drm_device *dev, if (enable) { if (DISPLAY_VER(dev_priv) >= 11) - intel_de_write(dev_priv, ICL_PIPESTATUS(pipe), + intel_de_write(dev_priv, + ICL_PIPESTATUS(dev_priv, pipe), icl_pipe_status_underrun_mask(dev_priv)); bdw_enable_pipe_irq(dev_priv, pipe, mask); @@ -418,9 +419,11 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, * the underrun was caused by the downstream port. */ if (DISPLAY_VER(dev_priv) >= 11) { - underruns = intel_de_read(dev_priv, ICL_PIPESTATUS(pipe)) & + underruns = intel_de_read(dev_priv, + ICL_PIPESTATUS(dev_priv, pipe)) & icl_pipe_status_underrun_mask(dev_priv); - intel_de_write(dev_priv, ICL_PIPESTATUS(pipe), underruns); + intel_de_write(dev_priv, ICL_PIPESTATUS(dev_priv, pipe), + underruns); } if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) { diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c index 2ea37c0414a9..4923c340a0b6 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c @@ -65,6 +65,7 @@ #include "intel_fbc.h" #include "intel_frontbuffer.h" #include "intel_psr.h" +#include "intel_tdf.h" /** * frontbuffer_flush - flush frontbuffer @@ -93,6 +94,7 @@ static void frontbuffer_flush(struct drm_i915_private *i915, trace_intel_frontbuffer_flush(i915, frontbuffer_bits, origin); might_sleep(); + intel_td_flush(i915); intel_drrs_flush(i915, frontbuffer_bits); intel_psr_flush(i915, frontbuffer_bits, origin); intel_fbc_flush(i915, frontbuffer_bits, origin); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index d5ed4c7dfbc0..3ebe035f382e 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -13,7 +13,7 @@ #include <linux/random.h> #include <drm/display/drm_hdcp_helper.h> -#include <drm/i915_component.h> +#include <drm/intel/i915_component.h> #include "i915_drv.h" #include "i915_reg.h" @@ -30,6 +30,29 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 +/* WA: 16022217614 */ +static void +intel_hdcp_disable_hdcp_line_rekeying(struct intel_encoder *encoder, + struct intel_hdcp *hdcp) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + /* Here we assume HDMI is in TMDS mode of operation */ + if (encoder->type != INTEL_OUTPUT_HDMI) + return; + + if (DISPLAY_VER(dev_priv) >= 14) { + if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_D0, STEP_FOREVER)) + intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(hdcp->cpu_transcoder), + 0, HDCP_LINE_REKEY_DISABLE); + else if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 1), STEP_B0, STEP_FOREVER) || + IS_DISPLAY_IP_STEP(dev_priv, IP_VER(20, 0), STEP_B0, STEP_FOREVER)) + intel_de_rmw(dev_priv, + TRANS_DDI_FUNC_CTL(dev_priv, hdcp->cpu_transcoder), + 0, TRANS_DDI_HDCP_LINE_REKEY_DISABLE); + } +} + static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { @@ -2005,6 +2028,8 @@ static int _intel_hdcp2_enable(struct intel_atomic_state *state, connector->base.base.id, connector->base.name, hdcp->content_type); + intel_hdcp_disable_hdcp_line_rekeying(connector->encoder, hdcp); + ret = hdcp2_authenticate_and_encrypt(state, connector); if (ret) { drm_dbg_kms(&i915->drm, "HDCP2 Type%d Enabling Failed. (%d)\n", diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c index 35823e1f65d6..16afeb8a3a8d 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c @@ -3,7 +3,7 @@ * Copyright 2023, Intel Corporation. */ -#include <drm/i915_hdcp_interface.h> +#include <drm/intel/i915_hdcp_interface.h> #include "gem/i915_gem_region.h" #include "gt/intel_gt.h" diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c index 240b00849f3d..6548e71b4c49 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c @@ -4,7 +4,7 @@ */ #include <linux/err.h> -#include <drm/i915_hdcp_interface.h> +#include <drm/intel/i915_hdcp_interface.h> #include "i915_drv.h" #include "intel_hdcp_gsc_message.h" diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 5f6deceaf8ba..19498ee455fa 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -38,7 +38,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> -#include <drm/intel_lpe_audio.h> +#include <drm/intel/intel_lpe_audio.h> #include "g4x_hdmi.h" #include "i915_drv.h" @@ -83,7 +83,7 @@ assert_hdmi_transcoder_func_disabled(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { drm_WARN(&dev_priv->drm, - intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)) & + intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)) & TRANS_DDI_FUNC_ENABLE, "HDMI transcoder function enabled, expecting disabled\n"); } @@ -165,21 +165,21 @@ hsw_dip_data_reg(struct drm_i915_private *dev_priv, { switch (type) { case HDMI_PACKET_TYPE_GAMUT_METADATA: - return HSW_TVIDEO_DIP_GMP_DATA(cpu_transcoder, i); + return HSW_TVIDEO_DIP_GMP_DATA(dev_priv, cpu_transcoder, i); case DP_SDP_VSC: - return HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder, i); + return HSW_TVIDEO_DIP_VSC_DATA(dev_priv, cpu_transcoder, i); case DP_SDP_ADAPTIVE_SYNC: - return ADL_TVIDEO_DIP_AS_SDP_DATA(cpu_transcoder, i); + return ADL_TVIDEO_DIP_AS_SDP_DATA(dev_priv, cpu_transcoder, i); case DP_SDP_PPS: - return ICL_VIDEO_DIP_PPS_DATA(cpu_transcoder, i); + return ICL_VIDEO_DIP_PPS_DATA(dev_priv, cpu_transcoder, i); case HDMI_INFOFRAME_TYPE_AVI: - return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder, i); + return HSW_TVIDEO_DIP_AVI_DATA(dev_priv, cpu_transcoder, i); case HDMI_INFOFRAME_TYPE_SPD: - return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder, i); + return HSW_TVIDEO_DIP_SPD_DATA(dev_priv, cpu_transcoder, i); case HDMI_INFOFRAME_TYPE_VENDOR: - return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i); + return HSW_TVIDEO_DIP_VS_DATA(dev_priv, cpu_transcoder, i); case HDMI_INFOFRAME_TYPE_DRM: - return GLK_TVIDEO_DIP_DRM_DATA(cpu_transcoder, i); + return GLK_TVIDEO_DIP_DRM_DATA(dev_priv, cpu_transcoder, i); default: MISSING_CASE(type); return INVALID_MMIO_REG; @@ -507,7 +507,7 @@ void hsw_write_infoframe(struct intel_encoder *encoder, const u32 *data = frame; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder); + i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(dev_priv, cpu_transcoder); int data_size; int i; u32 val = intel_de_read(dev_priv, ctl_reg); @@ -532,7 +532,8 @@ void hsw_write_infoframe(struct intel_encoder *encoder, 0); /* Wa_14013475917 */ - if (!(IS_DISPLAY_VER(dev_priv, 13, 14) && crtc_state->has_psr && type == DP_SDP_VSC)) + if (!(IS_DISPLAY_VER(dev_priv, 13, 14) && crtc_state->has_psr && + !crtc_state->has_panel_replay && type == DP_SDP_VSC)) val |= hsw_infoframe_enable(type); if (type == DP_SDP_VSC) @@ -561,7 +562,7 @@ static u32 hsw_infoframes_enabled(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 val = intel_de_read(dev_priv, - HSW_TVIDEO_DIP_CTL(pipe_config->cpu_transcoder)); + HSW_TVIDEO_DIP_CTL(dev_priv, pipe_config->cpu_transcoder)); u32 mask; mask = (VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_AVI_HSW | @@ -985,7 +986,7 @@ static bool intel_hdmi_set_gcp_infoframe(struct intel_encoder *encoder, return false; if (HAS_DDI(dev_priv)) - reg = HSW_TVIDEO_DIP_GCP(crtc_state->cpu_transcoder); + reg = HSW_TVIDEO_DIP_GCP(dev_priv, crtc_state->cpu_transcoder); else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) reg = VLV_TVIDEO_DIP_GCP(crtc->pipe); else if (HAS_PCH_SPLIT(dev_priv)) @@ -1010,7 +1011,7 @@ void intel_hdmi_read_gcp_infoframe(struct intel_encoder *encoder, return; if (HAS_DDI(dev_priv)) - reg = HSW_TVIDEO_DIP_GCP(crtc_state->cpu_transcoder); + reg = HSW_TVIDEO_DIP_GCP(dev_priv, crtc_state->cpu_transcoder); else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) reg = VLV_TVIDEO_DIP_GCP(crtc->pipe); else if (HAS_PCH_SPLIT(dev_priv)) @@ -1215,7 +1216,8 @@ static void hsw_set_infoframes(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder); + i915_reg_t reg = HSW_TVIDEO_DIP_CTL(dev_priv, + crtc_state->cpu_transcoder); u32 val = intel_de_read(dev_priv, reg); assert_hdmi_transcoder_func_disabled(dev_priv, @@ -1474,7 +1476,8 @@ static int kbl_repositioning_enc_en_signal(struct intel_connector *connector, int ret; for (;;) { - scanline = intel_de_read(dev_priv, PIPEDSL(crtc->pipe)); + scanline = intel_de_read(dev_priv, + PIPEDSL(dev_priv, crtc->pipe)); if (scanline > 100 && scanline < 200) break; usleep_range(25, 50); @@ -1783,7 +1786,9 @@ static int intel_hdmi_source_max_tmds_clock(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); int max_tmds_clock, vbt_max_tmds_clock; - if (DISPLAY_VER(dev_priv) >= 10) + if (DISPLAY_VER(dev_priv) >= 13 || IS_ALDERLAKE_S(dev_priv)) + max_tmds_clock = 600000; + else if (DISPLAY_VER(dev_priv) >= 10) max_tmds_clock = 594000; else if (DISPLAY_VER(dev_priv) >= 8 || IS_HASWELL(dev_priv)) max_tmds_clock = 300000; diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c index d270bb7b9462..a1f07ee69a86 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c @@ -186,7 +186,8 @@ void i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, lockdep_assert_held(&dev_priv->irq_lock); drm_WARN_ON(&dev_priv->drm, bits & ~mask); - intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits); + intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN(dev_priv), mask, + bits); } /** @@ -434,18 +435,21 @@ u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv) * bits can itself generate a new hotplug interrupt :( */ for (i = 0; i < 10; i++) { - u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask; + u32 tmp = intel_uncore_read(&dev_priv->uncore, + PORT_HOTPLUG_STAT(dev_priv)) & hotplug_status_mask; if (tmp == 0) return hotplug_status; hotplug_status |= tmp; - intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status); + intel_uncore_write(&dev_priv->uncore, + PORT_HOTPLUG_STAT(dev_priv), + hotplug_status); } drm_WARN_ONCE(&dev_priv->drm, 1, "PORT_HOTPLUG_STAT did not clear (0x%08x)\n", - intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); + intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT(dev_priv))); return hotplug_status; } diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c index 93e6cac9a4ed..f11626176fe2 100644 --- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c @@ -68,7 +68,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> -#include <drm/intel_lpe_audio.h> +#include <drm/intel/intel_lpe_audio.h> #include "i915_drv.h" #include "i915_irq.h" diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 1d048fa98561..8b26354d6e53 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -641,7 +641,7 @@ u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, if (lspcon->hdr_supported) { tmp = intel_de_read(dev_priv, - HSW_TVIDEO_DIP_CTL(pipe_config->cpu_transcoder)); + HSW_TVIDEO_DIP_CTL(dev_priv, pipe_config->cpu_transcoder)); mask = VIDEO_DIP_ENABLE_GMP_HSW; if (tmp & mask) diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 8b8959073466..9f018503d4fd 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -148,7 +148,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, /* gen2/3 store dither state in pfit control, needs to match */ if (DISPLAY_VER(dev_priv) < 4) { - tmp = intel_de_read(dev_priv, PFIT_CONTROL); + tmp = intel_de_read(dev_priv, PFIT_CONTROL(dev_priv)); crtc_state->gmch_pfit.control |= tmp & PFIT_PANEL_8TO6_DITHER_ENABLE; } @@ -161,18 +161,19 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv, { u32 val; - pps->powerdown_on_reset = intel_de_read(dev_priv, PP_CONTROL(0)) & PANEL_POWER_RESET; + pps->powerdown_on_reset = intel_de_read(dev_priv, + PP_CONTROL(dev_priv, 0)) & PANEL_POWER_RESET; - val = intel_de_read(dev_priv, PP_ON_DELAYS(0)); + val = intel_de_read(dev_priv, PP_ON_DELAYS(dev_priv, 0)); pps->port = REG_FIELD_GET(PANEL_PORT_SELECT_MASK, val); pps->t1_t2 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, val); pps->t5 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, val); - val = intel_de_read(dev_priv, PP_OFF_DELAYS(0)); + val = intel_de_read(dev_priv, PP_OFF_DELAYS(dev_priv, 0)); pps->t3 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, val); pps->tx = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, val); - val = intel_de_read(dev_priv, PP_DIVISOR(0)); + val = intel_de_read(dev_priv, PP_DIVISOR(dev_priv, 0)); pps->divider = REG_FIELD_GET(PP_REFERENCE_DIVIDER_MASK, val); val = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, val); /* @@ -209,23 +210,23 @@ static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv, { u32 val; - val = intel_de_read(dev_priv, PP_CONTROL(0)); + val = intel_de_read(dev_priv, PP_CONTROL(dev_priv, 0)); drm_WARN_ON(&dev_priv->drm, (val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS); if (pps->powerdown_on_reset) val |= PANEL_POWER_RESET; - intel_de_write(dev_priv, PP_CONTROL(0), val); + intel_de_write(dev_priv, PP_CONTROL(dev_priv, 0), val); - intel_de_write(dev_priv, PP_ON_DELAYS(0), + intel_de_write(dev_priv, PP_ON_DELAYS(dev_priv, 0), REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, pps->port) | REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, pps->t1_t2) | REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, pps->t5)); - intel_de_write(dev_priv, PP_OFF_DELAYS(0), + intel_de_write(dev_priv, PP_OFF_DELAYS(dev_priv, 0), REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, pps->t3) | REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, pps->tx)); - intel_de_write(dev_priv, PP_DIVISOR(0), + intel_de_write(dev_priv, PP_DIVISOR(dev_priv, 0), REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, pps->divider) | REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(pps->t4, 1000) + 1)); } @@ -321,10 +322,10 @@ static void intel_enable_lvds(struct intel_atomic_state *state, intel_de_rmw(dev_priv, lvds_encoder->reg, 0, LVDS_PORT_EN); - intel_de_rmw(dev_priv, PP_CONTROL(0), 0, PANEL_POWER_ON); + intel_de_rmw(dev_priv, PP_CONTROL(dev_priv, 0), 0, PANEL_POWER_ON); intel_de_posting_read(dev_priv, lvds_encoder->reg); - if (intel_de_wait_for_set(dev_priv, PP_STATUS(0), PP_ON, 5000)) + if (intel_de_wait_for_set(dev_priv, PP_STATUS(dev_priv, 0), PP_ON, 5000)) drm_err(&dev_priv->drm, "timed out waiting for panel to power on\n"); @@ -339,8 +340,8 @@ static void intel_disable_lvds(struct intel_atomic_state *state, struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - intel_de_rmw(dev_priv, PP_CONTROL(0), PANEL_POWER_ON, 0); - if (intel_de_wait_for_clear(dev_priv, PP_STATUS(0), PP_ON, 1000)) + intel_de_rmw(dev_priv, PP_CONTROL(dev_priv, 0), PANEL_POWER_ON, 0); + if (intel_de_wait_for_clear(dev_priv, PP_STATUS(dev_priv, 0), PP_ON, 1000)) drm_err(&dev_priv->drm, "timed out waiting for panel to power off\n"); @@ -379,7 +380,7 @@ static void intel_lvds_shutdown(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (intel_de_wait_for_clear(dev_priv, PP_STATUS(0), PP_CYCLE_DELAY_ACTIVE, 5000)) + if (intel_de_wait_for_clear(dev_priv, PP_STATUS(dev_priv, 0), PP_CYCLE_DELAY_ACTIVE, 5000)) drm_err(&dev_priv->drm, "timed out waiting for panel power cycle delay\n"); } diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index caeca3a8442c..7602cb30ebf1 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -68,7 +68,7 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc, /* Everything's already locked, -EDEADLK can't happen. */ for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, BIT(pipe) | - intel_crtc_bigjoiner_slave_pipes(crtc_state)) { + intel_crtc_joiner_secondary_pipes(crtc_state)) { struct intel_crtc_state *temp_crtc_state = intel_atomic_get_crtc_state(state, temp_crtc); int ret; @@ -189,7 +189,7 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc) /* * Return all the pipes using a transcoder in @transcoder_mask. - * For bigjoiner configs return only the bigjoiner master. + * For joiner configs return only the joiner primary. */ static u8 get_transcoder_pipes(struct drm_i915_private *i915, u8 transcoder_mask) @@ -204,7 +204,7 @@ static u8 get_transcoder_pipes(struct drm_i915_private *i915, if (temp_crtc_state->cpu_transcoder == INVALID_TRANSCODER) continue; - if (intel_crtc_is_bigjoiner_slave(temp_crtc_state)) + if (intel_crtc_is_joiner_secondary(temp_crtc_state)) continue; if (transcoder_mask & BIT(temp_crtc_state->cpu_transcoder)) @@ -216,7 +216,7 @@ static u8 get_transcoder_pipes(struct drm_i915_private *i915, /* * Return the port sync master and slave pipes linked to @crtc. - * For bigjoiner configs return only the bigjoiner master pipes. + * For joiner configs return only the joiner primary pipes. */ static void get_portsync_pipes(struct intel_crtc *crtc, u8 *master_pipe_mask, u8 *slave_pipes_mask) @@ -248,16 +248,16 @@ static void get_portsync_pipes(struct intel_crtc *crtc, *slave_pipes_mask = get_transcoder_pipes(i915, master_crtc_state->sync_mode_slaves_mask); } -static u8 get_bigjoiner_slave_pipes(struct drm_i915_private *i915, u8 master_pipes_mask) +static u8 get_joiner_secondary_pipes(struct drm_i915_private *i915, u8 primary_pipes_mask) { - struct intel_crtc *master_crtc; + struct intel_crtc *primary_crtc; u8 pipes = 0; - for_each_intel_crtc_in_pipe_mask(&i915->drm, master_crtc, master_pipes_mask) { - struct intel_crtc_state *master_crtc_state = - to_intel_crtc_state(master_crtc->base.state); + for_each_intel_crtc_in_pipe_mask(&i915->drm, primary_crtc, primary_pipes_mask) { + struct intel_crtc_state *primary_crtc_state = + to_intel_crtc_state(primary_crtc->base.state); - pipes |= intel_crtc_bigjoiner_slave_pipes(master_crtc_state); + pipes |= intel_crtc_joiner_secondary_pipes(primary_crtc_state); } return pipes; @@ -269,21 +269,21 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc, struct drm_i915_private *i915 = to_i915(crtc->base.dev); u8 portsync_master_mask; u8 portsync_slaves_mask; - u8 bigjoiner_slaves_mask; + u8 joiner_secondaries_mask; struct intel_crtc *temp_crtc; /* TODO: Add support for MST */ get_portsync_pipes(crtc, &portsync_master_mask, &portsync_slaves_mask); - bigjoiner_slaves_mask = get_bigjoiner_slave_pipes(i915, - portsync_master_mask | - portsync_slaves_mask); + joiner_secondaries_mask = get_joiner_secondary_pipes(i915, + portsync_master_mask | + portsync_slaves_mask); drm_WARN_ON(&i915->drm, portsync_master_mask & portsync_slaves_mask || - portsync_master_mask & bigjoiner_slaves_mask || - portsync_slaves_mask & bigjoiner_slaves_mask); + portsync_master_mask & joiner_secondaries_mask || + portsync_slaves_mask & joiner_secondaries_mask); - for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, bigjoiner_slaves_mask) + for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, joiner_secondaries_mask) intel_crtc_disable_noatomic_begin(temp_crtc, ctx); for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, portsync_slaves_mask) @@ -293,7 +293,7 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc, intel_crtc_disable_noatomic_begin(temp_crtc, ctx); for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, - bigjoiner_slaves_mask | + joiner_secondaries_mask | portsync_slaves_mask | portsync_master_mask) intel_crtc_disable_noatomic_complete(temp_crtc); @@ -326,7 +326,7 @@ static void intel_modeset_update_connector_atomic_state(struct drm_i915_private static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state) { - if (intel_crtc_is_bigjoiner_slave(crtc_state)) + if (intel_crtc_is_joiner_secondary(crtc_state)) return; crtc_state->uapi.enable = crtc_state->hw.enable; @@ -474,7 +474,7 @@ static bool intel_sanitize_crtc(struct intel_crtc *crtc, } if (!crtc_state->hw.active || - intel_crtc_is_bigjoiner_slave(crtc_state)) + intel_crtc_is_joiner_secondary(crtc_state)) return false; needs_link_reset = intel_crtc_needs_link_reset(crtc); @@ -728,19 +728,19 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915) encoder->base.crtc = &crtc->base; intel_encoder_get_config(encoder, crtc_state); - /* read out to slave crtc as well for bigjoiner */ - if (crtc_state->bigjoiner_pipes) { - struct intel_crtc *slave_crtc; + /* read out to secondary crtc as well for joiner */ + if (crtc_state->joiner_pipes) { + struct intel_crtc *secondary_crtc; - /* encoder should read be linked to bigjoiner master */ - WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state)); + /* encoder should read be linked to joiner primary */ + WARN_ON(intel_crtc_is_joiner_secondary(crtc_state)); - for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, - intel_crtc_bigjoiner_slave_pipes(crtc_state)) { - struct intel_crtc_state *slave_crtc_state; + for_each_intel_crtc_in_pipe_mask(&i915->drm, secondary_crtc, + intel_crtc_joiner_secondary_pipes(crtc_state)) { + struct intel_crtc_state *secondary_crtc_state; - slave_crtc_state = to_intel_crtc_state(slave_crtc->base.state); - intel_encoder_get_config(encoder, slave_crtc_state); + secondary_crtc_state = to_intel_crtc_state(secondary_crtc->base.state); + intel_encoder_get_config(encoder, secondary_crtc_state); } } diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c index 076298a8d405..3491db5cad31 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c @@ -166,7 +166,7 @@ verify_crtc_state(struct intel_atomic_state *state, const struct intel_crtc_state *sw_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); struct intel_crtc_state *hw_crtc_state; - struct intel_crtc *master_crtc; + struct intel_crtc *primary_crtc; struct intel_encoder *encoder; hw_crtc_state = intel_crtc_state_alloc(crtc); @@ -193,9 +193,9 @@ verify_crtc_state(struct intel_atomic_state *state, "transitional active state does not match atomic hw state (expected %i, found %i)\n", sw_crtc_state->hw.active, crtc->active); - master_crtc = intel_master_crtc(sw_crtc_state); + primary_crtc = intel_primary_crtc(sw_crtc_state); - for_each_encoder_on_crtc(dev, &master_crtc->base, encoder) { + for_each_encoder_on_crtc(dev, &primary_crtc->base, encoder) { enum pipe pipe; bool active; @@ -205,7 +205,7 @@ verify_crtc_state(struct intel_atomic_state *state, encoder->base.base.id, active, sw_crtc_state->hw.active); - I915_STATE_WARN(i915, active && master_crtc->pipe != pipe, + I915_STATE_WARN(i915, active && primary_crtc->pipe != pipe, "Encoder connected to wrong pipe %c\n", pipe_name(pipe)); diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 1c2099ed5514..06b1122ec13e 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -943,17 +943,19 @@ static void update_pfit_vscale_ratio(struct intel_overlay *overlay) * line with the intel documentation for the i965 */ if (DISPLAY_VER(dev_priv) >= 4) { - u32 tmp = intel_de_read(dev_priv, PFIT_PGM_RATIOS); + u32 tmp = intel_de_read(dev_priv, PFIT_PGM_RATIOS(dev_priv)); /* on i965 use the PGM reg to read out the autoscaler values */ ratio = REG_FIELD_GET(PFIT_VERT_SCALE_MASK_965, tmp); } else { u32 tmp; - if (intel_de_read(dev_priv, PFIT_CONTROL) & PFIT_VERT_AUTO_SCALE) - tmp = intel_de_read(dev_priv, PFIT_AUTO_RATIOS); + if (intel_de_read(dev_priv, PFIT_CONTROL(dev_priv)) & PFIT_VERT_AUTO_SCALE) + tmp = intel_de_read(dev_priv, + PFIT_AUTO_RATIOS(dev_priv)); else - tmp = intel_de_read(dev_priv, PFIT_PGM_RATIOS); + tmp = intel_de_read(dev_priv, + PFIT_PGM_RATIOS(dev_priv)); ratio = REG_FIELD_GET(PFIT_VERT_SCALE_MASK, tmp); } @@ -1485,15 +1487,14 @@ intel_overlay_capture_error_state(struct drm_i915_private *dev_priv) } void -intel_overlay_print_error_state(struct drm_i915_error_state_buf *m, +intel_overlay_print_error_state(struct drm_printer *p, struct intel_overlay_error_state *error) { - i915_error_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n", - error->dovsta, error->isr); - i915_error_printf(m, " Register file at 0x%08lx:\n", - error->base); + drm_printf(p, "Overlay, status: 0x%08x, interrupt: 0x%08x\n", + error->dovsta, error->isr); + drm_printf(p, " Register file at 0x%08lx:\n", error->base); -#define P(x) i915_error_printf(m, " " #x ": 0x%08x\n", error->regs.x) +#define P(x) drm_printf(p, " " #x ": 0x%08x\n", error->regs.x) P(OBUF_0Y); P(OBUF_1Y); P(OBUF_0U); diff --git a/drivers/gpu/drm/i915/display/intel_overlay.h b/drivers/gpu/drm/i915/display/intel_overlay.h index c3f68fce6f08..f28a09c062d0 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.h +++ b/drivers/gpu/drm/i915/display/intel_overlay.h @@ -8,8 +8,8 @@ struct drm_device; struct drm_file; -struct drm_i915_error_state_buf; struct drm_i915_private; +struct drm_printer; struct intel_overlay; struct intel_overlay_error_state; @@ -24,7 +24,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data, void intel_overlay_reset(struct drm_i915_private *dev_priv); struct intel_overlay_error_state * intel_overlay_capture_error_state(struct drm_i915_private *dev_priv); -void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e, +void intel_overlay_print_error_state(struct drm_printer *p, struct intel_overlay_error_state *error); #else static inline void intel_overlay_setup(struct drm_i915_private *dev_priv) @@ -55,7 +55,7 @@ intel_overlay_capture_error_state(struct drm_i915_private *dev_priv) { return NULL; } -static inline void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e, +static inline void intel_overlay_print_error_state(struct drm_printer *p, struct intel_overlay_error_state *error) { } diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 6f4ff6a89c32..71454ddef20f 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -352,7 +352,7 @@ void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector) struct drm_i915_private *i915 = to_i915(connector->base.dev); const struct drm_display_mode *mode; - mode = connector->panel.vbt.lfp_lvds_vbt_mode; + mode = connector->panel.vbt.lfp_vbt_mode; if (!mode) return; diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 826e38a9e6a4..0d48b9bec29c 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -224,20 +224,20 @@ static void ilk_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_s enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; intel_de_write(dev_priv, PCH_TRANS_HTOTAL(pch_transcoder), - intel_de_read(dev_priv, TRANS_HTOTAL(cpu_transcoder))); + intel_de_read(dev_priv, TRANS_HTOTAL(dev_priv, cpu_transcoder))); intel_de_write(dev_priv, PCH_TRANS_HBLANK(pch_transcoder), - intel_de_read(dev_priv, TRANS_HBLANK(cpu_transcoder))); + intel_de_read(dev_priv, TRANS_HBLANK(dev_priv, cpu_transcoder))); intel_de_write(dev_priv, PCH_TRANS_HSYNC(pch_transcoder), - intel_de_read(dev_priv, TRANS_HSYNC(cpu_transcoder))); + intel_de_read(dev_priv, TRANS_HSYNC(dev_priv, cpu_transcoder))); intel_de_write(dev_priv, PCH_TRANS_VTOTAL(pch_transcoder), - intel_de_read(dev_priv, TRANS_VTOTAL(cpu_transcoder))); + intel_de_read(dev_priv, TRANS_VTOTAL(dev_priv, cpu_transcoder))); intel_de_write(dev_priv, PCH_TRANS_VBLANK(pch_transcoder), - intel_de_read(dev_priv, TRANS_VBLANK(cpu_transcoder))); + intel_de_read(dev_priv, TRANS_VBLANK(dev_priv, cpu_transcoder))); intel_de_write(dev_priv, PCH_TRANS_VSYNC(pch_transcoder), - intel_de_read(dev_priv, TRANS_VSYNC(cpu_transcoder))); + intel_de_read(dev_priv, TRANS_VSYNC(dev_priv, cpu_transcoder))); intel_de_write(dev_priv, PCH_TRANS_VSYNCSHIFT(pch_transcoder), - intel_de_read(dev_priv, TRANS_VSYNCSHIFT(cpu_transcoder))); + intel_de_read(dev_priv, TRANS_VSYNCSHIFT(dev_priv, cpu_transcoder))); } static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) @@ -271,7 +271,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) reg = PCH_TRANSCONF(pipe); val = intel_de_read(dev_priv, reg); - pipeconf_val = intel_de_read(dev_priv, TRANSCONF(pipe)); + pipeconf_val = intel_de_read(dev_priv, TRANSCONF(dev_priv, pipe)); if (HAS_PCH_IBX(dev_priv)) { /* Configure frame start delay to match the CPU */ @@ -413,7 +413,7 @@ void ilk_pch_enable(struct intel_atomic_state *state, intel_crtc_has_dp_encoder(crtc_state)) { const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - u32 bpc = (intel_de_read(dev_priv, TRANSCONF(pipe)) & TRANSCONF_BPC_MASK) >> 5; + u32 bpc = (intel_de_read(dev_priv, TRANSCONF(dev_priv, pipe)) & TRANSCONF_BPC_MASK) >> 5; i915_reg_t reg = TRANS_DP_CTL(pipe); enum port port; @@ -557,7 +557,8 @@ static void lpt_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val); val = TRANS_ENABLE; - pipeconf_val = intel_de_read(dev_priv, TRANSCONF(cpu_transcoder)); + pipeconf_val = intel_de_read(dev_priv, + TRANSCONF(dev_priv, cpu_transcoder)); if ((pipeconf_val & TRANSCONF_INTERLACE_MASK_HSW) == TRANSCONF_INTERLACE_IF_ID_ILK) val |= TRANS_INTERLACE_INTERLACED; diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c index 5a468ed6e26c..82ceede0b2b1 100644 --- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c @@ -34,6 +34,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_pipe_crc.h" +#include "intel_pipe_crc_regs.h" static const char * const pipe_crc_sources[] = { [INTEL_PIPE_CRC_SOURCE_NONE] = "none", @@ -167,7 +168,7 @@ static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, * - DisplayPort scrambling: used for EMI reduction */ if (need_stable_symbols) { - u32 tmp = intel_de_read(dev_priv, PORT_DFT2_G4X); + u32 tmp = intel_de_read(dev_priv, PORT_DFT2_G4X(dev_priv)); tmp |= DC_BALANCE_RESET_VLV; switch (pipe) { @@ -183,7 +184,7 @@ static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, default: return -EINVAL; } - intel_de_write(dev_priv, PORT_DFT2_G4X, tmp); + intel_de_write(dev_priv, PORT_DFT2_G4X(dev_priv), tmp); } return 0; @@ -229,7 +230,7 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, static void vlv_undo_pipe_scramble_reset(struct drm_i915_private *dev_priv, enum pipe pipe) { - u32 tmp = intel_de_read(dev_priv, PORT_DFT2_G4X); + u32 tmp = intel_de_read(dev_priv, PORT_DFT2_G4X(dev_priv)); switch (pipe) { case PIPE_A: @@ -246,7 +247,7 @@ static void vlv_undo_pipe_scramble_reset(struct drm_i915_private *dev_priv, } if (!(tmp & PIPE_SCRAMBLE_RESET_MASK)) tmp &= ~DC_BALANCE_RESET_VLV; - intel_de_write(dev_priv, PORT_DFT2_G4X, tmp); + intel_de_write(dev_priv, PORT_DFT2_G4X(dev_priv), tmp); } static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, @@ -608,8 +609,8 @@ int intel_crtc_set_crc_source(struct drm_crtc *_crtc, const char *source_name) goto out; pipe_crc->source = source; - intel_de_write(dev_priv, PIPE_CRC_CTL(pipe), val); - intel_de_posting_read(dev_priv, PIPE_CRC_CTL(pipe)); + intel_de_write(dev_priv, PIPE_CRC_CTL(dev_priv, pipe), val); + intel_de_posting_read(dev_priv, PIPE_CRC_CTL(dev_priv, pipe)); if (!source) { if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) @@ -643,8 +644,8 @@ void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc) /* Don't need pipe_crc->lock here, IRQs are not generated. */ pipe_crc->skipped = 0; - intel_de_write(dev_priv, PIPE_CRC_CTL(pipe), val); - intel_de_posting_read(dev_priv, PIPE_CRC_CTL(pipe)); + intel_de_write(dev_priv, PIPE_CRC_CTL(dev_priv, pipe), val); + intel_de_posting_read(dev_priv, PIPE_CRC_CTL(dev_priv, pipe)); } void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc) @@ -658,7 +659,7 @@ void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc) pipe_crc->skipped = INT_MIN; spin_unlock_irq(&pipe_crc->lock); - intel_de_write(dev_priv, PIPE_CRC_CTL(pipe), 0); - intel_de_posting_read(dev_priv, PIPE_CRC_CTL(pipe)); + intel_de_write(dev_priv, PIPE_CRC_CTL(dev_priv, pipe), 0); + intel_de_posting_read(dev_priv, PIPE_CRC_CTL(dev_priv, pipe)); intel_synchronize_irq(dev_priv); } diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc_regs.h b/drivers/gpu/drm/i915/display/intel_pipe_crc_regs.h new file mode 100644 index 000000000000..4e65f51d34e6 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc_regs.h @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __INTEL_PIPE_CRC_REGS_H__ +#define __INTEL_PIPE_CRC_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define _PIPE_CRC_CTL_A 0x60050 +#define PIPE_CRC_CTL(dev_priv, pipe) _MMIO_TRANS2((dev_priv), (pipe), _PIPE_CRC_CTL_A) +#define PIPE_CRC_ENABLE REG_BIT(31) +/* skl+ source selection */ +#define PIPE_CRC_SOURCE_MASK_SKL REG_GENMASK(30, 28) +#define PIPE_CRC_SOURCE_PLANE_1_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 0) +#define PIPE_CRC_SOURCE_PLANE_2_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 2) +#define PIPE_CRC_SOURCE_DMUX_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 4) +#define PIPE_CRC_SOURCE_PLANE_3_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 6) +#define PIPE_CRC_SOURCE_PLANE_4_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 7) +#define PIPE_CRC_SOURCE_PLANE_5_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 5) +#define PIPE_CRC_SOURCE_PLANE_6_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 3) +#define PIPE_CRC_SOURCE_PLANE_7_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 1) +/* ivb+ source selection */ +#define PIPE_CRC_SOURCE_MASK_IVB REG_GENMASK(30, 29) +#define PIPE_CRC_SOURCE_PRIMARY_IVB REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_IVB, 0) +#define PIPE_CRC_SOURCE_SPRITE_IVB REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_IVB, 1) +#define PIPE_CRC_SOURCE_PF_IVB REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_IVB, 2) +/* ilk+ source selection */ +#define PIPE_CRC_SOURCE_MASK_ILK REG_GENMASK(30, 28) +#define PIPE_CRC_SOURCE_PRIMARY_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 0) +#define PIPE_CRC_SOURCE_SPRITE_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 1) +#define PIPE_CRC_SOURCE_PIPE_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 2) +/* embedded DP port on the north display block */ +#define PIPE_CRC_SOURCE_PORT_A_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 4) +#define PIPE_CRC_SOURCE_FDI_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 5) +/* vlv source selection */ +#define PIPE_CRC_SOURCE_MASK_VLV REG_GENMASK(30, 27) +#define PIPE_CRC_SOURCE_PIPE_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 0) +#define PIPE_CRC_SOURCE_HDMIB_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 1) +#define PIPE_CRC_SOURCE_HDMIC_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 2) +/* with DP port the pipe source is invalid */ +#define PIPE_CRC_SOURCE_DP_D_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 3) +#define PIPE_CRC_SOURCE_DP_B_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 6) +#define PIPE_CRC_SOURCE_DP_C_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 7) +/* gen3+ source selection */ +#define PIPE_CRC_SOURCE_MASK_I9XX REG_GENMASK(30, 28) +#define PIPE_CRC_SOURCE_PIPE_I9XX REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 0) +#define PIPE_CRC_SOURCE_SDVOB_I9XX REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 1) +#define PIPE_CRC_SOURCE_SDVOC_I9XX REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 2) +/* with DP/TV port the pipe source is invalid */ +#define PIPE_CRC_SOURCE_DP_D_G4X REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 3) +#define PIPE_CRC_SOURCE_TV_PRE REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 4) +#define PIPE_CRC_SOURCE_TV_POST REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 5) +#define PIPE_CRC_SOURCE_DP_B_G4X REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 6) +#define PIPE_CRC_SOURCE_DP_C_G4X REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 7) +/* gen2 doesn't have source selection bits */ +#define PIPE_CRC_INCLUDE_BORDER_I8XX REG_BIT(30) +#define PIPE_CRC_EXP_RED_MASK REG_BIT(22, 0) /* pre-ivb */ +#define PIPE_CRC_EXP_1_MASK_IVB REG_BIT(22, 0) /* ivb */ + +#define _PIPE_CRC_EXP_GREEN_A 0x60054 +#define PIPE_CRC_EXP_GREEN(dev_priv, pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_EXP_GREEN_A) +#define PIPE_CRC_EXP_GREEN_MASK REG_BIT(22, 0) /* pre-ivb */ + +#define _PIPE_CRC_EXP_BLUE_A 0x60058 +#define PIPE_CRC_EXP_BLUE(dev_priv, pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_EXP_BLUE_A) +#define PIPE_CRC_EXP_BLUE_MASK REG_BIT(22, 0) /* pre-ivb */ + +#define _PIPE_CRC_EXP_RES1_A_I915 0x6005c /* i915+ */ +#define PIPE_CRC_EXP_RES1_I915(dev_priv, pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_EXP_RES1_A_I915) +#define PIPE_CRC_EXP_RES1_MASK REG_BIT(22, 0) /* pre-ivb */ + +#define _PIPE_CRC_EXP_RES2_A_G4X 0x60080 /* g4x+ */ +#define PIPE_CRC_EXP_RES2_G4X(dev_priv, pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_EXP_RES2_A_G4X) +#define PIPE_CRC_EXP_RES2_MASK REG_BIT(22, 0) /* pre-ivb */ + +#define _PIPE_CRC_RES_RED_A 0x60060 +#define PIPE_CRC_RES_RED(dev_priv, pipe) _MMIO_TRANS2((dev_priv), (pipe), _PIPE_CRC_RES_RED_A) + +#define _PIPE_CRC_RES_GREEN_A 0x60064 +#define PIPE_CRC_RES_GREEN(dev_priv, pipe) _MMIO_TRANS2((dev_priv), (pipe), _PIPE_CRC_RES_GREEN_A) + +#define _PIPE_CRC_RES_BLUE_A 0x60068 +#define PIPE_CRC_RES_BLUE(dev_priv, pipe) _MMIO_TRANS2((dev_priv), (pipe), _PIPE_CRC_RES_BLUE_A) + +#define _PIPE_CRC_RES_RES1_A_I915 0x6006c /* i915+ */ +#define PIPE_CRC_RES_RES1_I915(dev_priv, pipe) _MMIO_TRANS2((dev_priv), (pipe), _PIPE_CRC_RES_RES1_A_I915) + +#define _PIPE_CRC_RES_RES2_A_G4X 0x60080 /* g4x+ */ +#define PIPE_CRC_RES_RES2_G4X(dev_priv, pipe) _MMIO_TRANS2((dev_priv), (pipe), _PIPE_CRC_RES_RES2_A_G4X) + +/* ivb */ +#define _PIPE_CRC_EXP_2_A_IVB 0x60054 +#define _PIPE_CRC_EXP_2_B_IVB 0x61054 +#define PIPE_CRC_EXP_2_IVB(pipe) _MMIO_PIPE(pipe, _PIPE_CRC_EXP_2_A_IVB, _PIPE_CRC_EXP_2_B_IVB) +#define PIPE_CRC_EXP_2_MASK_IVB REG_BIT(22, 0) /* ivb */ + +/* ivb */ +#define _PIPE_CRC_EXP_3_A_IVB 0x60058 +#define _PIPE_CRC_EXP_3_B_IVB 0x61058 +#define PIPE_CRC_EXP_3_IVB(pipe) _MMIO_PIPE(pipe, _PIPE_CRC_EXP_3_A_IVB, _PIPE_CRC_EXP_3_B_IVB) +#define PIPE_CRC_EXP_3_MASK_IVB REG_BIT(22, 0) /* ivb */ + +/* ivb */ +#define _PIPE_CRC_EXP_4_A_IVB 0x6005c +#define _PIPE_CRC_EXP_4_B_IVB 0x6105c +#define PIPE_CRC_EXP_4_IVB(pipe) _MMIO_PIPE(pipe, _PIPE_CRC_EXP_2_A_IVB, _PIPE_CRC_EXP_2_B_IVB) +#define PIPE_CRC_EXP_4_MASK_IVB REG_BIT(22, 0) /* ivb */ + +/* ivb */ +#define _PIPE_CRC_EXP_5_A_IVB 0x60060 +#define _PIPE_CRC_EXP_5_B_IVB 0x61060 +#define PIPE_CRC_EXP_5_IVB(pipe) _MMIO_PIPE(pipe, _PIPE_CRC_EXP_2_A_IVB, _PIPE_CRC_EXP_2_B_IVB) +#define PIPE_CRC_EXP_5_MASK_IVB REG_BIT(22, 0) /* ivb */ + +/* ivb */ +#define _PIPE_CRC_RES_1_A_IVB 0x60064 +#define _PIPE_CRC_RES_1_B_IVB 0x61064 +#define PIPE_CRC_RES_1_IVB(pipe) _MMIO_PIPE((pipe), _PIPE_CRC_RES_1_A_IVB, _PIPE_CRC_RES_1_B_IVB) + +/* ivb */ +#define _PIPE_CRC_RES_2_A_IVB 0x60068 +#define _PIPE_CRC_RES_2_B_IVB 0x61068 +#define PIPE_CRC_RES_2_IVB(pipe) _MMIO_PIPE((pipe), _PIPE_CRC_RES_2_A_IVB, _PIPE_CRC_RES_2_B_IVB) + +/* ivb */ +#define _PIPE_CRC_RES_3_A_IVB 0x6006c +#define _PIPE_CRC_RES_3_B_IVB 0x6106c +#define PIPE_CRC_RES_3_IVB(pipe) _MMIO_PIPE((pipe), _PIPE_CRC_RES_3_A_IVB, _PIPE_CRC_RES_3_B_IVB) + +/* ivb */ +#define _PIPE_CRC_RES_4_A_IVB 0x60070 +#define _PIPE_CRC_RES_4_B_IVB 0x61070 +#define PIPE_CRC_RES_4_IVB(pipe) _MMIO_PIPE((pipe), _PIPE_CRC_RES_4_A_IVB, _PIPE_CRC_RES_4_B_IVB) + +/* ivb */ +#define _PIPE_CRC_RES_5_A_IVB 0x60074 +#define _PIPE_CRC_RES_5_B_IVB 0x61074 +#define PIPE_CRC_RES_5_IVB(pipe) _MMIO_PIPE((pipe), _PIPE_CRC_RES_5_A_IVB, _PIPE_CRC_RES_5_B_IVB) + +/* hsw+ */ +#define _PIPE_CRC_EXP_A_HSW 0x60054 +#define _PIPE_CRC_EXP_B_HSW 0x61054 +#define PIPE_CRC_EXP_HSW(pipe) _MMIO_PIPE((pipe), _PIPE_CRC_EXP_A_HSW, _PIPE_CRC_EXP_B_HSW) + +/* hsw+ */ +#define _PIPE_CRC_RES_A_HSW 0x60064 +#define _PIPE_CRC_RES_B_HSW 0x61064 +#define PIPE_CRC_RES_HSW(pipe) _MMIO_PIPE((pipe), _PIPE_CRC_RES_A_HSW, _PIPE_CRC_RES_B_HSW) + +#endif /* __INTEL_PIPE_CRC_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 0ccbf9a85914..42306bc4ba86 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -119,7 +119,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) else DP |= DP_PIPE_SEL(pipe); - pll_enabled = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE; + pll_enabled = intel_de_read(dev_priv, DPLL(dev_priv, pipe)) & DPLL_VCO_ENABLE; /* * The DPLL for the pipe must be enabled for this to work. @@ -272,12 +272,12 @@ typedef bool (*pps_check)(struct drm_i915_private *dev_priv, int pps_idx); static bool pps_has_pp_on(struct drm_i915_private *dev_priv, int pps_idx) { - return intel_de_read(dev_priv, PP_STATUS(pps_idx)) & PP_ON; + return intel_de_read(dev_priv, PP_STATUS(dev_priv, pps_idx)) & PP_ON; } static bool pps_has_vdd_on(struct drm_i915_private *dev_priv, int pps_idx) { - return intel_de_read(dev_priv, PP_CONTROL(pps_idx)) & EDP_FORCE_VDD; + return intel_de_read(dev_priv, PP_CONTROL(dev_priv, pps_idx)) & EDP_FORCE_VDD; } static bool pps_any(struct drm_i915_private *dev_priv, int pps_idx) @@ -292,7 +292,7 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv, enum pipe pipe; for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) { - u32 port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(pipe)) & + u32 port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(dev_priv, pipe)) & PANEL_PORT_SELECT_MASK; if (port_sel != PANEL_PORT_SELECT_VLV(port)) @@ -491,17 +491,17 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp, else pps_idx = intel_dp->pps.pps_idx; - regs->pp_ctrl = PP_CONTROL(pps_idx); - regs->pp_stat = PP_STATUS(pps_idx); - regs->pp_on = PP_ON_DELAYS(pps_idx); - regs->pp_off = PP_OFF_DELAYS(pps_idx); + regs->pp_ctrl = PP_CONTROL(dev_priv, pps_idx); + regs->pp_stat = PP_STATUS(dev_priv, pps_idx); + regs->pp_on = PP_ON_DELAYS(dev_priv, pps_idx); + regs->pp_off = PP_OFF_DELAYS(dev_priv, pps_idx); /* Cycle delay moved from PP_DIVISOR to PP_CONTROL */ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) || INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) regs->pp_div = INVALID_MMIO_REG; else - regs->pp_div = PP_DIVISOR(pps_idx); + regs->pp_div = PP_DIVISOR(dev_priv, pps_idx); } static i915_reg_t @@ -1111,7 +1111,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); enum pipe pipe = intel_dp->pps.pps_pipe; - i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe); + i915_reg_t pp_on_reg = PP_ON_DELAYS(dev_priv, pipe); drm_WARN_ON(&dev_priv->drm, intel_dp->pps.active_pipe != INVALID_PIPE); @@ -1656,7 +1656,7 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv) pps_num = intel_num_pps(dev_priv); for (pps_idx = 0; pps_idx < pps_num; pps_idx++) - intel_de_rmw(dev_priv, PP_CONTROL(pps_idx), + intel_de_rmw(dev_priv, PP_CONTROL(dev_priv, pps_idx), PANEL_UNLOCK_MASK, PANEL_UNLOCK_REGS); } @@ -1714,8 +1714,8 @@ void assert_pps_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) if (HAS_PCH_SPLIT(dev_priv)) { u32 port_sel; - pp_reg = PP_CONTROL(0); - port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK; + pp_reg = PP_CONTROL(dev_priv, 0); + port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(dev_priv, 0)) & PANEL_PORT_SELECT_MASK; switch (port_sel) { case PANEL_PORT_SELECT_LVDS: @@ -1736,13 +1736,13 @@ void assert_pps_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) } } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { /* presumably write lock depends on pipe, not port select */ - pp_reg = PP_CONTROL(pipe); + pp_reg = PP_CONTROL(dev_priv, pipe); panel_pipe = pipe; } else { u32 port_sel; - pp_reg = PP_CONTROL(0); - port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK; + pp_reg = PP_CONTROL(dev_priv, 0); + port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(dev_priv, 0)) & PANEL_PORT_SELECT_MASK; drm_WARN_ON(&dev_priv->drm, port_sel != PANEL_PORT_SELECT_LVDS); diff --git a/drivers/gpu/drm/i915/display/intel_pps_regs.h b/drivers/gpu/drm/i915/display/intel_pps_regs.h index 60edd2a27100..8f9dbfab9523 100644 --- a/drivers/gpu/drm/i915/display/intel_pps_regs.h +++ b/drivers/gpu/drm/i915/display/intel_pps_regs.h @@ -6,6 +6,7 @@ #ifndef __INTEL_PPS_REGS_H__ #define __INTEL_PPS_REGS_H__ +#include "intel_display_conversion.h" #include "intel_display_reg_defs.h" /* Panel power sequencing */ @@ -13,12 +14,11 @@ #define VLV_PPS_BASE (VLV_DISPLAY_BASE + PPS_BASE) #define PCH_PPS_BASE 0xC7200 -#define _MMIO_PPS(pps_idx, reg) _MMIO(dev_priv->display.pps.mmio_base - \ - PPS_BASE + (reg) + \ - (pps_idx) * 0x100) +#define _MMIO_PPS(dev_priv, pps_idx, reg) \ + _MMIO(__to_intel_display(dev_priv)->pps.mmio_base - PPS_BASE + (reg) + (pps_idx) * 0x100) #define _PP_STATUS 0x61200 -#define PP_STATUS(pps_idx) _MMIO_PPS(pps_idx, _PP_STATUS) +#define PP_STATUS(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_STATUS) #define PP_ON REG_BIT(31) /* * Indicates that all dependencies of the panel are on: @@ -45,7 +45,7 @@ #define PP_SEQUENCE_STATE_RESET REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0xf) #define _PP_CONTROL 0x61204 -#define PP_CONTROL(pps_idx) _MMIO_PPS(pps_idx, _PP_CONTROL) +#define PP_CONTROL(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_CONTROL) #define PANEL_UNLOCK_MASK REG_GENMASK(31, 16) #define PANEL_UNLOCK_REGS REG_FIELD_PREP(PANEL_UNLOCK_MASK, 0xabcd) #define BXT_POWER_CYCLE_DELAY_MASK REG_GENMASK(8, 4) @@ -55,7 +55,7 @@ #define PANEL_POWER_ON REG_BIT(0) #define _PP_ON_DELAYS 0x61208 -#define PP_ON_DELAYS(pps_idx) _MMIO_PPS(pps_idx, _PP_ON_DELAYS) +#define PP_ON_DELAYS(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_ON_DELAYS) #define PANEL_PORT_SELECT_MASK REG_GENMASK(31, 30) #define PANEL_PORT_SELECT_LVDS REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 0) #define PANEL_PORT_SELECT_DPA REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 1) @@ -66,12 +66,12 @@ #define PANEL_LIGHT_ON_DELAY_MASK REG_GENMASK(12, 0) #define _PP_OFF_DELAYS 0x6120C -#define PP_OFF_DELAYS(pps_idx) _MMIO_PPS(pps_idx, _PP_OFF_DELAYS) +#define PP_OFF_DELAYS(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_OFF_DELAYS) #define PANEL_POWER_DOWN_DELAY_MASK REG_GENMASK(28, 16) #define PANEL_LIGHT_OFF_DELAY_MASK REG_GENMASK(12, 0) #define _PP_DIVISOR 0x61210 -#define PP_DIVISOR(pps_idx) _MMIO_PPS(pps_idx, _PP_DIVISOR) +#define PP_DIVISOR(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_DIVISOR) #define PP_REFERENCE_DIVIDER_MASK REG_GENMASK(31, 8) #define PANEL_POWER_CYCLE_DELAY_MASK REG_GENMASK(4, 0) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index f5b33335a9ae..a9d9383e4ee5 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -27,8 +27,10 @@ #include "i915_drv.h" #include "i915_reg.h" +#include "intel_alpm.h" #include "intel_atomic.h" #include "intel_crtc.h" +#include "intel_cursor_regs.h" #include "intel_ddi.h" #include "intel_de.h" #include "intel_display_types.h" @@ -233,6 +235,26 @@ static bool psr2_global_enabled(struct intel_dp *intel_dp) } } +static bool psr2_su_region_et_global_enabled(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + if (i915->display.params.enable_psr != -1) + return false; + + return true; +} + +static bool panel_replay_global_enabled(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + if ((i915->display.params.enable_psr != -1) || + (intel_dp->psr.debug & I915_PSR_DEBUG_PANEL_REPLAY_DISABLE)) + return false; + return true; +} + static u32 psr_irq_psr_error_bit_get(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -269,7 +291,7 @@ static i915_reg_t psr_ctl_reg(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { if (DISPLAY_VER(dev_priv) >= 8) - return EDP_PSR_CTL(cpu_transcoder); + return EDP_PSR_CTL(dev_priv, cpu_transcoder); else return HSW_SRD_CTL; } @@ -278,7 +300,7 @@ static i915_reg_t psr_debug_reg(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { if (DISPLAY_VER(dev_priv) >= 8) - return EDP_PSR_DEBUG(cpu_transcoder); + return EDP_PSR_DEBUG(dev_priv, cpu_transcoder); else return HSW_SRD_DEBUG; } @@ -287,7 +309,7 @@ static i915_reg_t psr_perf_cnt_reg(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { if (DISPLAY_VER(dev_priv) >= 8) - return EDP_PSR_PERF_CNT(cpu_transcoder); + return EDP_PSR_PERF_CNT(dev_priv, cpu_transcoder); else return HSW_SRD_PERF_CNT; } @@ -296,7 +318,7 @@ static i915_reg_t psr_status_reg(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { if (DISPLAY_VER(dev_priv) >= 8) - return EDP_PSR_STATUS(cpu_transcoder); + return EDP_PSR_STATUS(dev_priv, cpu_transcoder); else return HSW_SRD_STATUS; } @@ -305,7 +327,7 @@ static i915_reg_t psr_imr_reg(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { if (DISPLAY_VER(dev_priv) >= 12) - return TRANS_PSR_IMR(cpu_transcoder); + return TRANS_PSR_IMR(dev_priv, cpu_transcoder); else return EDP_PSR_IMR; } @@ -314,7 +336,7 @@ static i915_reg_t psr_iir_reg(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { if (DISPLAY_VER(dev_priv) >= 12) - return TRANS_PSR_IIR(cpu_transcoder); + return TRANS_PSR_IIR(dev_priv, cpu_transcoder); else return EDP_PSR_IIR; } @@ -323,7 +345,7 @@ static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { if (DISPLAY_VER(dev_priv) >= 8) - return EDP_PSR_AUX_CTL(cpu_transcoder); + return EDP_PSR_AUX_CTL(dev_priv, cpu_transcoder); else return HSW_SRD_AUX_CTL; } @@ -332,7 +354,7 @@ static i915_reg_t psr_aux_data_reg(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder, int i) { if (DISPLAY_VER(dev_priv) >= 8) - return EDP_PSR_AUX_DATA(cpu_transcoder, i); + return EDP_PSR_AUX_DATA(dev_priv, cpu_transcoder, i); else return HSW_SRD_AUX_DATA(i); } @@ -356,12 +378,12 @@ static void psr_irq_control(struct intel_dp *intel_dp) } static void psr_event_print(struct drm_i915_private *i915, - u32 val, bool psr2_enabled) + u32 val, bool sel_update_enabled) { drm_dbg_kms(&i915->drm, "PSR exit events: 0x%x\n", val); if (val & PSR_EVENT_PSR2_WD_TIMER_EXPIRE) drm_dbg_kms(&i915->drm, "\tPSR2 watchdog timer expired\n"); - if ((val & PSR_EVENT_PSR2_DISABLED) && psr2_enabled) + if ((val & PSR_EVENT_PSR2_DISABLED) && sel_update_enabled) drm_dbg_kms(&i915->drm, "\tPSR2 disabled\n"); if (val & PSR_EVENT_SU_DIRTY_FIFO_UNDERRUN) drm_dbg_kms(&i915->drm, "\tSU dirty FIFO underrun\n"); @@ -389,7 +411,7 @@ static void psr_event_print(struct drm_i915_private *i915, drm_dbg_kms(&i915->drm, "\tVBI enabled\n"); if (val & PSR_EVENT_LPSP_MODE_EXIT) drm_dbg_kms(&i915->drm, "\tLPSP mode exited\n"); - if ((val & PSR_EVENT_PSR_DISABLE) && !psr2_enabled) + if ((val & PSR_EVENT_PSR_DISABLE) && !sel_update_enabled) drm_dbg_kms(&i915->drm, "\tPSR disabled\n"); } @@ -415,9 +437,11 @@ void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir) if (DISPLAY_VER(dev_priv) >= 9) { u32 val; - val = intel_de_rmw(dev_priv, PSR_EVENT(cpu_transcoder), 0, 0); + val = intel_de_rmw(dev_priv, + PSR_EVENT(dev_priv, cpu_transcoder), + 0, 0); - psr_event_print(dev_priv, val, intel_dp->psr.psr2_enabled); + psr_event_print(dev_priv, val, intel_dp->psr.sel_update_enabled); } } @@ -442,16 +466,6 @@ void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir) } } -static bool intel_dp_get_alpm_status(struct intel_dp *intel_dp) -{ - u8 alpm_caps = 0; - - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_RECEIVER_ALPM_CAP, - &alpm_caps) != 1) - return false; - return alpm_caps & DP_ALPM_CAP; -} - static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -466,6 +480,40 @@ static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp) return val; } +static u8 intel_dp_get_su_capability(struct intel_dp *intel_dp) +{ + u8 su_capability = 0; + + if (intel_dp->psr.sink_panel_replay_su_support) + drm_dp_dpcd_readb(&intel_dp->aux, + DP_PANEL_PANEL_REPLAY_CAPABILITY, + &su_capability); + else + su_capability = intel_dp->psr_dpcd[1]; + + return su_capability; +} + +static unsigned int +intel_dp_get_su_x_granularity_offset(struct intel_dp *intel_dp) +{ + return intel_dp->psr.sink_panel_replay_su_support ? + DP_PANEL_PANEL_REPLAY_X_GRANULARITY : + DP_PSR2_SU_X_GRANULARITY; +} + +static unsigned int +intel_dp_get_su_y_granularity_offset(struct intel_dp *intel_dp) +{ + return intel_dp->psr.sink_panel_replay_su_support ? + DP_PANEL_PANEL_REPLAY_Y_GRANULARITY : + DP_PSR2_SU_Y_GRANULARITY; +} + +/* + * Note: Bits related to granularity are same in panel replay and psr + * registers. Rely on PSR definitions on these "common" bits. + */ static void intel_dp_get_su_granularity(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -473,18 +521,29 @@ static void intel_dp_get_su_granularity(struct intel_dp *intel_dp) u16 w; u8 y; - /* If sink don't have specific granularity requirements set legacy ones */ - if (!(intel_dp->psr_dpcd[1] & DP_PSR2_SU_GRANULARITY_REQUIRED)) { + /* + * TODO: Do we need to take into account panel supporting both PSR and + * Panel replay? + */ + + /* + * If sink don't have specific granularity requirements set legacy + * ones. + */ + if (!(intel_dp_get_su_capability(intel_dp) & + DP_PSR2_SU_GRANULARITY_REQUIRED)) { /* As PSR2 HW sends full lines, we do not care about x granularity */ w = 4; y = 4; goto exit; } - r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &w, 2); + r = drm_dp_dpcd_read(&intel_dp->aux, + intel_dp_get_su_x_granularity_offset(intel_dp), + &w, 2); if (r != 2) drm_dbg_kms(&i915->drm, - "Unable to read DP_PSR2_SU_X_GRANULARITY\n"); + "Unable to read selective update x granularity\n"); /* * Spec says that if the value read is 0 the default granularity should * be used instead. @@ -492,10 +551,12 @@ static void intel_dp_get_su_granularity(struct intel_dp *intel_dp) if (r != 2 || w == 0) w = 4; - r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_Y_GRANULARITY, &y, 1); + r = drm_dp_dpcd_read(&intel_dp->aux, + intel_dp_get_su_y_granularity_offset(intel_dp), + &y, 1); if (r != 1) { drm_dbg_kms(&i915->drm, - "Unable to read DP_PSR2_SU_Y_GRANULARITY\n"); + "Unable to read selective update y granularity\n"); y = 4; } if (y == 0) @@ -509,20 +570,16 @@ exit: static void _panel_replay_init_dpcd(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); - u8 pr_dpcd = 0; - intel_dp->psr.sink_panel_replay_support = false; - drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP, &pr_dpcd); + intel_dp->psr.sink_panel_replay_support = true; - if (!(pr_dpcd & DP_PANEL_REPLAY_SUPPORT)) { - drm_dbg_kms(&i915->drm, - "Panel replay is not supported by panel\n"); - return; - } + if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_SU_SUPPORT) + intel_dp->psr.sink_panel_replay_su_support = true; drm_dbg_kms(&i915->drm, - "Panel replay is supported by panel\n"); - intel_dp->psr.sink_panel_replay_support = true; + "Panel replay %sis supported by panel\n", + intel_dp->psr.sink_panel_replay_su_support ? + "selective_update " : ""); } static void _psr_init_dpcd(struct intel_dp *intel_dp) @@ -553,7 +610,6 @@ static void _psr_init_dpcd(struct intel_dp *intel_dp) intel_dp->psr_dpcd[0] >= DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) { bool y_req = intel_dp->psr_dpcd[1] & DP_PSR2_SU_Y_COORDINATE_REQUIRED; - bool alpm = intel_dp_get_alpm_status(intel_dp); /* * All panels that supports PSR version 03h (PSR2 + @@ -566,7 +622,8 @@ static void _psr_init_dpcd(struct intel_dp *intel_dp) * Y-coordinate requirement panels we would need to enable * GTC first. */ - intel_dp->psr.sink_psr2_support = y_req && alpm; + intel_dp->psr.sink_psr2_support = y_req && + intel_alpm_aux_wake_supported(intel_dp); drm_dbg_kms(&i915->drm, "PSR2 %ssupported\n", intel_dp->psr.sink_psr2_support ? "" : "not "); } @@ -574,15 +631,19 @@ static void _psr_init_dpcd(struct intel_dp *intel_dp) void intel_psr_init_dpcd(struct intel_dp *intel_dp) { - _panel_replay_init_dpcd(intel_dp); - drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd, sizeof(intel_dp->psr_dpcd)); + drm_dp_dpcd_readb(&intel_dp->aux, DP_PANEL_REPLAY_CAP, + &intel_dp->pr_dpcd); + + if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_SUPPORT) + _panel_replay_init_dpcd(intel_dp); if (intel_dp->psr_dpcd[0]) _psr_init_dpcd(intel_dp); - if (intel_dp->psr.sink_psr2_support) + if (intel_dp->psr.sink_psr2_support || + intel_dp->psr.sink_panel_replay_su_support) intel_dp_get_su_granularity(intel_dp); } @@ -623,68 +684,76 @@ static void hsw_psr_setup_aux(struct intel_dp *intel_dp) aux_ctl); } -static bool psr2_su_region_et_valid(struct intel_dp *intel_dp) +static bool psr2_su_region_et_valid(struct intel_dp *intel_dp, bool panel_replay) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); - if (DISPLAY_VER(i915) >= 20 && - intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_ET_SUPPORTED && - !(intel_dp->psr.debug & I915_PSR_DEBUG_SU_REGION_ET_DISABLE)) - return true; + if (DISPLAY_VER(i915) < 20 || !intel_dp_is_edp(intel_dp) || + intel_dp->psr.debug & I915_PSR_DEBUG_SU_REGION_ET_DISABLE) + return false; - return false; + return panel_replay ? + intel_dp->pr_dpcd & DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT : + intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_ET_SUPPORTED && + psr2_su_region_et_global_enabled(intel_dp); } -static unsigned int intel_psr_get_enable_sink_offset(struct intel_dp *intel_dp) +static void _panel_replay_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { - return intel_dp->psr.panel_replay_enabled ? - PANEL_REPLAY_CONFIG : DP_PSR_EN_CFG; -} + u8 val = DP_PANEL_REPLAY_ENABLE | + DP_PANEL_REPLAY_VSC_SDP_CRC_EN | + DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN | + DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN | + DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR_EN; -/* - * Note: Most of the bits are same in PANEL_REPLAY_CONFIG and DP_PSR_EN_CFG. We - * are relying on PSR definitions on these "common" bits. - */ -void intel_psr_enable_sink(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - u8 dpcd_val = DP_PSR_ENABLE; + if (crtc_state->has_sel_update) + val |= DP_PANEL_REPLAY_SU_ENABLE; - if (crtc_state->has_psr2) { - /* Enable ALPM at sink for psr2 */ - if (!crtc_state->has_panel_replay) { - drm_dp_dpcd_writeb(&intel_dp->aux, - DP_RECEIVER_ALPM_CONFIG, - DP_ALPM_ENABLE | - DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE); + if (crtc_state->enable_psr2_su_region_et) + val |= DP_PANEL_REPLAY_ENABLE_SU_REGION_ET; - if (psr2_su_region_et_valid(intel_dp)) - dpcd_val |= DP_PSR_ENABLE_SU_REGION_ET; - } + drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG, val); +} + +static void _psr_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + u8 val = DP_PSR_ENABLE; - dpcd_val |= DP_PSR_ENABLE_PSR2 | DP_PSR_IRQ_HPD_WITH_CRC_ERRORS; + if (crtc_state->has_sel_update) { + val |= DP_PSR_ENABLE_PSR2 | DP_PSR_IRQ_HPD_WITH_CRC_ERRORS; } else { if (intel_dp->psr.link_standby) - dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; + val |= DP_PSR_MAIN_LINK_ACTIVE; - if (!crtc_state->has_panel_replay && DISPLAY_VER(dev_priv) >= 8) - dpcd_val |= DP_PSR_CRC_VERIFICATION; + if (DISPLAY_VER(i915) >= 8) + val |= DP_PSR_CRC_VERIFICATION; } - if (crtc_state->has_panel_replay) - dpcd_val |= DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN | - DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN; - - if (crtc_state->req_psr2_sdp_prior_scanline) - dpcd_val |= DP_PSR_SU_REGION_SCANLINE_CAPTURE; + if (crtc_state->enable_psr2_su_region_et) + val |= DP_PANEL_REPLAY_ENABLE_SU_REGION_ET; if (intel_dp->psr.entry_setup_frames > 0) - dpcd_val |= DP_PSR_FRAME_CAPTURE; + val |= DP_PSR_FRAME_CAPTURE; - drm_dp_dpcd_writeb(&intel_dp->aux, - intel_psr_get_enable_sink_offset(intel_dp), - dpcd_val); + drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val); +} + +void intel_psr_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + /* Enable ALPM at sink for psr2 */ + if (!crtc_state->has_panel_replay && crtc_state->has_sel_update) + drm_dp_dpcd_writeb(&intel_dp->aux, + DP_RECEIVER_ALPM_CONFIG, + DP_ALPM_ENABLE | + DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE); + + crtc_state->has_panel_replay ? + _panel_replay_enable_sink(intel_dp, crtc_state) : + _psr_enable_sink(intel_dp, crtc_state); if (intel_dp_is_edp(intel_dp)) drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); @@ -814,8 +883,8 @@ static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp) static int psr2_block_count_lines(struct intel_dp *intel_dp) { - return intel_dp->psr.alpm_parameters.io_wake_lines < 9 && - intel_dp->psr.alpm_parameters.fast_wake_lines < 9 ? 8 : 12; + return intel_dp->alpm_parameters.io_wake_lines < 9 && + intel_dp->alpm_parameters.fast_wake_lines < 9 ? 8 : 12; } static int psr2_block_count(struct intel_dp *intel_dp) @@ -842,7 +911,8 @@ static void dg2_activate_panel_replay(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - intel_de_rmw(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), + intel_de_rmw(dev_priv, + PSR2_MAN_TRK_CTL(dev_priv, intel_dp->psr.transcoder), 0, ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME); intel_de_rmw(dev_priv, TRANS_DP2_CTL(intel_dp->psr.transcoder), 0, @@ -852,7 +922,6 @@ static void dg2_activate_panel_replay(struct intel_dp *intel_dp) static void hsw_activate_psr2(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_psr *psr = &intel_dp->psr; enum transcoder cpu_transcoder = intel_dp->psr.transcoder; u32 val = EDP_PSR2_ENABLE; u32 psr_val = 0; @@ -869,7 +938,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= intel_psr2_get_tp_time(intel_dp); - if (DISPLAY_VER(dev_priv) >= 12) { + if (DISPLAY_VER(dev_priv) >= 12 && DISPLAY_VER(dev_priv) < 20) { if (psr2_block_count(intel_dp) > 2) val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_3; else @@ -894,18 +963,20 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) */ int tmp; - tmp = map[psr->alpm_parameters.io_wake_lines - + tmp = map[intel_dp->alpm_parameters.io_wake_lines - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES]; val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(tmp + TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES); - tmp = map[psr->alpm_parameters.fast_wake_lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES]; + tmp = map[intel_dp->alpm_parameters.fast_wake_lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES]; val |= TGL_EDP_PSR2_FAST_WAKE(tmp + TGL_EDP_PSR2_FAST_WAKE_MIN_LINES); + } else if (DISPLAY_VER(dev_priv) >= 20) { + val |= LNL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines); } else if (DISPLAY_VER(dev_priv) >= 12) { - val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines); - val |= TGL_EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines); + val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines); + val |= TGL_EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines); } else if (DISPLAY_VER(dev_priv) >= 9) { - val |= EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines); - val |= EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines); + val |= EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines); + val |= EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines); } if (intel_dp->psr.req_psr2_sdp_prior_scanline) @@ -917,13 +988,15 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) if (intel_dp->psr.psr2_sel_fetch_enabled) { u32 tmp; - tmp = intel_de_read(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder)); + tmp = intel_de_read(dev_priv, + PSR2_MAN_TRK_CTL(dev_priv, cpu_transcoder)); drm_WARN_ON(&dev_priv->drm, !(tmp & PSR2_MAN_TRK_CTL_ENABLE)); } else if (HAS_PSR2_SEL_FETCH(dev_priv)) { - intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder), 0); + intel_de_write(dev_priv, + PSR2_MAN_TRK_CTL(dev_priv, cpu_transcoder), 0); } - if (psr2_su_region_et_valid(intel_dp)) + if (intel_dp->psr.su_region_et_enabled) val |= LNL_EDP_PSR2_SU_REGION_ET_ENABLE; /* @@ -932,7 +1005,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) */ intel_de_write(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder), psr_val); - intel_de_write(dev_priv, EDP_PSR2_CTL(cpu_transcoder), val); + intel_de_write(dev_priv, EDP_PSR2_CTL(dev_priv, cpu_transcoder), val); } static bool @@ -963,7 +1036,7 @@ static void psr2_program_idle_frames(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); enum transcoder cpu_transcoder = intel_dp->psr.transcoder; - intel_de_rmw(dev_priv, EDP_PSR2_CTL(cpu_transcoder), + intel_de_rmw(dev_priv, EDP_PSR2_CTL(dev_priv, cpu_transcoder), EDP_PSR2_IDLE_FRAMES_MASK, EDP_PSR2_IDLE_FRAMES(idle_frames)); } @@ -1088,9 +1161,6 @@ static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp, return false; } - if (psr2_su_region_et_valid(intel_dp)) - crtc_state->enable_psr2_su_region_et = true; - return crtc_state->enable_psr2_sel_fetch = true; } @@ -1161,237 +1231,6 @@ static bool _compute_psr2_sdp_prior_scanline_indication(struct intel_dp *intel_d return true; } -/* - * See Bspec: 71632 for the table - * - * Silence_period = tSilence,Min + ((tSilence,Max - tSilence,Min) / 2) - * - * Half cycle duration: - * - * Link rates 1.62 - 4.32 and tLFPS_Cycle = 70 ns - * FLOOR( (Link Rate * tLFPS_Cycle) / (2 * 10) ) - * - * Link rates 5.4 - 8.1 - * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ] = 10 - * LFPS Period chosen is the mid-point of the min:max values from the table - * FLOOR( LFPS Period in Symbol clocks / - * (2 * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ]) ) - */ -static bool _lnl_get_silence_period_and_lfps_half_cycle(int link_rate, - int *silence_period, - int *lfps_half_cycle) -{ - switch (link_rate) { - case 162000: - *silence_period = 20; - *lfps_half_cycle = 5; - break; - case 216000: - *silence_period = 27; - *lfps_half_cycle = 7; - break; - case 243000: - *silence_period = 31; - *lfps_half_cycle = 8; - break; - case 270000: - *silence_period = 34; - *lfps_half_cycle = 9; - break; - case 324000: - *silence_period = 41; - *lfps_half_cycle = 11; - break; - case 432000: - *silence_period = 56; - *lfps_half_cycle = 15; - break; - case 540000: - *silence_period = 69; - *lfps_half_cycle = 12; - break; - case 648000: - *silence_period = 84; - *lfps_half_cycle = 15; - break; - case 675000: - *silence_period = 87; - *lfps_half_cycle = 15; - break; - case 810000: - *silence_period = 104; - *lfps_half_cycle = 19; - break; - default: - *silence_period = *lfps_half_cycle = -1; - return false; - } - return true; -} - -/* - * AUX-Less Wake Time = CEILING( ((PHY P2 to P0) + tLFPS_Period, Max+ - * tSilence, Max+ tPHY Establishment + tCDS) / tline) - * For the "PHY P2 to P0" latency see the PHY Power Control page - * (PHY P2 to P0) : https://gfxspecs.intel.com/Predator/Home/Index/68965 - * : 12 us - * The tLFPS_Period, Max term is 800ns - * The tSilence, Max term is 180ns - * The tPHY Establishment (a.k.a. t1) term is 50us - * The tCDS term is 1 or 2 times t2 - * t2 = Number ML_PHY_LOCK * tML_PHY_LOCK - * Number ML_PHY_LOCK = ( 7 + CEILING( 6.5us / tML_PHY_LOCK ) + 1) - * Rounding up the 6.5us padding to the next ML_PHY_LOCK boundary and - * adding the "+ 1" term ensures all ML_PHY_LOCK sequences that start - * within the CDS period complete within the CDS period regardless of - * entry into the period - * tML_PHY_LOCK = TPS4 Length * ( 10 / (Link Rate in MHz) ) - * TPS4 Length = 252 Symbols - */ -static int _lnl_compute_aux_less_wake_time(int port_clock) -{ - int tphy2_p2_to_p0 = 12 * 1000; - int tlfps_period_max = 800; - int tsilence_max = 180; - int t1 = 50 * 1000; - int tps4 = 252; - int tml_phy_lock = 1000 * 1000 * tps4 * 10 / port_clock; - int num_ml_phy_lock = 7 + DIV_ROUND_UP(6500, tml_phy_lock) + 1; - int t2 = num_ml_phy_lock * tml_phy_lock; - int tcds = 1 * t2; - - return DIV_ROUND_UP(tphy2_p2_to_p0 + tlfps_period_max + tsilence_max + - t1 + tcds, 1000); -} - -static int _lnl_compute_aux_less_alpm_params(struct intel_dp *intel_dp, - struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *i915 = dp_to_i915(intel_dp); - int aux_less_wake_time, aux_less_wake_lines, silence_period, - lfps_half_cycle; - - aux_less_wake_time = - _lnl_compute_aux_less_wake_time(crtc_state->port_clock); - aux_less_wake_lines = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, - aux_less_wake_time); - - if (!_lnl_get_silence_period_and_lfps_half_cycle(crtc_state->port_clock, - &silence_period, - &lfps_half_cycle)) - return false; - - if (aux_less_wake_lines > ALPM_CTL_AUX_LESS_WAKE_TIME_MASK || - silence_period > PORT_ALPM_CTL_SILENCE_PERIOD_MASK || - lfps_half_cycle > PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION_MASK) - return false; - - if (i915->display.params.psr_safest_params) - aux_less_wake_lines = ALPM_CTL_AUX_LESS_WAKE_TIME_MASK; - - intel_dp->psr.alpm_parameters.fast_wake_lines = aux_less_wake_lines; - intel_dp->psr.alpm_parameters.silence_period_sym_clocks = silence_period; - intel_dp->psr.alpm_parameters.lfps_half_cycle_num_of_syms = lfps_half_cycle; - - return true; -} - -static bool _lnl_compute_alpm_params(struct intel_dp *intel_dp, - struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *i915 = dp_to_i915(intel_dp); - int check_entry_lines; - - if (DISPLAY_VER(i915) < 20) - return true; - - /* ALPM Entry Check = 2 + CEILING( 5us /tline ) */ - check_entry_lines = 2 + - intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 5); - - if (check_entry_lines > 15) - return false; - - if (!_lnl_compute_aux_less_alpm_params(intel_dp, crtc_state)) - return false; - - if (i915->display.params.psr_safest_params) - check_entry_lines = 15; - - intel_dp->psr.alpm_parameters.check_entry_lines = check_entry_lines; - - return true; -} - -/* - * IO wake time for DISPLAY_VER < 12 is not directly mentioned in Bspec. There - * are 50 us io wake time and 32 us fast wake time. Clearly preharge pulses are - * not (improperly) included in 32 us fast wake time. 50 us - 32 us = 18 us. - */ -static int skl_io_buffer_wake_time(void) -{ - return 18; -} - -static int tgl_io_buffer_wake_time(void) -{ - return 10; -} - -static int io_buffer_wake_time(const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - - if (DISPLAY_VER(i915) >= 12) - return tgl_io_buffer_wake_time(); - else - return skl_io_buffer_wake_time(); -} - -static bool _compute_alpm_params(struct intel_dp *intel_dp, - struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *i915 = dp_to_i915(intel_dp); - int io_wake_lines, io_wake_time, fast_wake_lines, fast_wake_time; - int tfw_exit_latency = 20; /* eDP spec */ - int phy_wake = 4; /* eDP spec */ - int preamble = 8; /* eDP spec */ - int precharge = intel_dp_aux_fw_sync_len() - preamble; - u8 max_wake_lines; - - io_wake_time = max(precharge, io_buffer_wake_time(crtc_state)) + - preamble + phy_wake + tfw_exit_latency; - fast_wake_time = precharge + preamble + phy_wake + - tfw_exit_latency; - - if (DISPLAY_VER(i915) >= 12) - /* TODO: Check how we can use ALPM_CTL fast wake extended field */ - max_wake_lines = 12; - else - max_wake_lines = 8; - - io_wake_lines = intel_usecs_to_scanlines( - &crtc_state->hw.adjusted_mode, io_wake_time); - fast_wake_lines = intel_usecs_to_scanlines( - &crtc_state->hw.adjusted_mode, fast_wake_time); - - if (io_wake_lines > max_wake_lines || - fast_wake_lines > max_wake_lines) - return false; - - if (!_lnl_compute_alpm_params(intel_dp, crtc_state)) - return false; - - if (i915->display.params.psr_safest_params) - io_wake_lines = fast_wake_lines = max_wake_lines; - - /* According to Bspec lower limit should be set as 7 lines. */ - intel_dp->psr.alpm_parameters.io_wake_lines = max(io_wake_lines, 7); - intel_dp->psr.alpm_parameters.fast_wake_lines = max(fast_wake_lines, 7); - - return true; -} - static int intel_psr_entry_setup_frames(struct intel_dp *intel_dp, const struct drm_display_mode *adjusted_mode) { @@ -1425,6 +1264,31 @@ static int intel_psr_entry_setup_frames(struct intel_dp *intel_dp, return entry_setup_frames; } +static bool wake_lines_fit_into_vblank(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + int vblank = crtc_state->hw.adjusted_mode.crtc_vblank_end - + crtc_state->hw.adjusted_mode.crtc_vblank_start; + int wake_lines; + + if (crtc_state->has_panel_replay) + wake_lines = intel_dp->alpm_parameters.aux_less_wake_lines; + else + wake_lines = DISPLAY_VER(i915) < 20 ? + psr2_block_count_lines(intel_dp) : + intel_dp->alpm_parameters.io_wake_lines; + + if (crtc_state->req_psr2_sdp_prior_scanline) + vblank -= 1; + + /* Vblank >= PSR2_CTL Block Count Number maximum line count */ + if (vblank < wake_lines) + return false; + + return true; +} + static bool intel_psr2_config_valid(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state) { @@ -1461,11 +1325,6 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } - if (!psr2_global_enabled(intel_dp)) { - drm_dbg_kms(&dev_priv->drm, "PSR2 disabled by flag\n"); - return false; - } - /* * DSC and PSR2 cannot be enabled simultaneously. If a requested * resolution requires DSC to be enabled, priority is given to DSC @@ -1478,12 +1337,6 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } - if (crtc_state->crc_enabled) { - drm_dbg_kms(&dev_priv->drm, - "PSR2 not enabled because it would inhibit pipe CRC calculation\n"); - return false; - } - if (DISPLAY_VER(dev_priv) >= 12) { psr_max_h = 5120; psr_max_v = 3200; @@ -1519,45 +1372,73 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } - if (!_compute_alpm_params(intel_dp, crtc_state)) { + if (!intel_alpm_compute_params(intel_dp, crtc_state)) { drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, Unable to use long enough wake times\n"); return false; } /* Vblank >= PSR2_CTL Block Count Number maximum line count */ - if (crtc_state->hw.adjusted_mode.crtc_vblank_end - - crtc_state->hw.adjusted_mode.crtc_vblank_start < - psr2_block_count_lines(intel_dp)) { + if (!wake_lines_fit_into_vblank(intel_dp, crtc_state)) { drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, too short vblank time\n"); return false; } - if (HAS_PSR2_SEL_FETCH(dev_priv)) { - if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) && - !HAS_PSR_HW_TRACKING(dev_priv)) { - drm_dbg_kms(&dev_priv->drm, - "PSR2 not enabled, selective fetch not valid and no HW tracking available\n"); - return false; - } - } - - if (!psr2_granularity_check(intel_dp, crtc_state)) { - drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, SU granularity not compatible\n"); - goto unsupported; - } - if (!crtc_state->enable_psr2_sel_fetch && (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v)) { drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, resolution %dx%d > max supported %dx%d\n", crtc_hdisplay, crtc_vdisplay, psr_max_h, psr_max_v); - goto unsupported; + return false; } tgl_dc3co_exitline_compute_config(intel_dp, crtc_state); + + if (psr2_su_region_et_valid(intel_dp, crtc_state->has_panel_replay)) + crtc_state->enable_psr2_su_region_et = true; + + return true; +} + +static bool intel_sel_update_config_valid(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + + if (HAS_PSR2_SEL_FETCH(dev_priv) && + !intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) && + !HAS_PSR_HW_TRACKING(dev_priv)) { + drm_dbg_kms(&dev_priv->drm, + "Selective update not enabled, selective fetch not valid and no HW tracking available\n"); + goto unsupported; + } + + if (!psr2_global_enabled(intel_dp)) { + drm_dbg_kms(&dev_priv->drm, "Selective update disabled by flag\n"); + goto unsupported; + } + + if (!crtc_state->has_panel_replay && !intel_psr2_config_valid(intel_dp, crtc_state)) + goto unsupported; + + if (crtc_state->has_panel_replay && (DISPLAY_VER(dev_priv) < 14 || + !intel_dp->psr.sink_panel_replay_su_support)) + goto unsupported; + + if (crtc_state->crc_enabled) { + drm_dbg_kms(&dev_priv->drm, + "Selective update not enabled because it would inhibit pipe CRC calculation\n"); + goto unsupported; + } + + if (!psr2_granularity_check(intel_dp, crtc_state)) { + drm_dbg_kms(&dev_priv->drm, + "Selective update not enabled, SU granularity not compatible\n"); + goto unsupported; + } + return true; unsupported: @@ -1595,6 +1476,21 @@ static bool _psr_compute_config(struct intel_dp *intel_dp, return true; } +static bool _panel_replay_compute_config(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + if (!CAN_PANEL_REPLAY(intel_dp)) + return false; + + if (!panel_replay_global_enabled(intel_dp)) { + drm_dbg_kms(&i915->drm, "Panel Replay disabled by flag\n"); + return false; + } + + return true; +} + void intel_psr_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state) @@ -1620,18 +1516,17 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, } /* - * FIXME figure out what is wrong with PSR+bigjoiner and + * FIXME figure out what is wrong with PSR+joiner and * fix it. Presumably something related to the fact that * PSR is a transcoder level feature. */ - if (crtc_state->bigjoiner_pipes) { + if (crtc_state->joiner_pipes) { drm_dbg_kms(&dev_priv->drm, - "PSR disabled due to bigjoiner\n"); + "PSR disabled due to joiner\n"); return; } - if (CAN_PANEL_REPLAY(intel_dp)) - crtc_state->has_panel_replay = true; + crtc_state->has_panel_replay = _panel_replay_compute_config(intel_dp); crtc_state->has_psr = crtc_state->has_panel_replay ? true : _psr_compute_config(intel_dp, crtc_state); @@ -1639,7 +1534,7 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, if (!crtc_state->has_psr) return; - crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state); + crtc_state->has_sel_update = intel_sel_update_config_valid(intel_dp, crtc_state); } void intel_psr_get_config(struct intel_encoder *encoder, @@ -1672,20 +1567,24 @@ void intel_psr_get_config(struct intel_encoder *encoder, pipe_config->has_psr = true; } - pipe_config->has_psr2 = intel_dp->psr.psr2_enabled; + pipe_config->has_sel_update = intel_dp->psr.sel_update_enabled; pipe_config->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_VSC); - if (!intel_dp->psr.psr2_enabled) + if (!intel_dp->psr.sel_update_enabled) goto unlock; if (HAS_PSR2_SEL_FETCH(dev_priv)) { - val = intel_de_read(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder)); + val = intel_de_read(dev_priv, + PSR2_MAN_TRK_CTL(dev_priv, cpu_transcoder)); if (val & PSR2_MAN_TRK_CTL_ENABLE) pipe_config->enable_psr2_sel_fetch = true; } + pipe_config->enable_psr2_su_region_et = intel_dp->psr.su_region_et_enabled; + if (DISPLAY_VER(dev_priv) >= 12) { - val = intel_de_read(dev_priv, TRANS_EXITLINE(cpu_transcoder)); + val = intel_de_read(dev_priv, + TRANS_EXITLINE(dev_priv, cpu_transcoder)); pipe_config->dc3co_exitline = REG_FIELD_GET(EXITLINE_MASK, val); } unlock: @@ -1699,7 +1598,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp) drm_WARN_ON(&dev_priv->drm, transcoder_has_psr2(dev_priv, cpu_transcoder) && - intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder)) & EDP_PSR2_ENABLE); + intel_de_read(dev_priv, EDP_PSR2_CTL(dev_priv, cpu_transcoder)) & EDP_PSR2_ENABLE); drm_WARN_ON(&dev_priv->drm, intel_de_read(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder)) & EDP_PSR_ENABLE); @@ -1711,7 +1610,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp) /* psr1, psr2 and panel-replay are mutually exclusive.*/ if (intel_dp->psr.panel_replay_enabled) dg2_activate_panel_replay(intel_dp); - else if (intel_dp->psr.psr2_enabled) + else if (intel_dp->psr.sel_update_enabled) hsw_activate_psr2(intel_dp); else hsw_activate_psr1(intel_dp); @@ -1763,51 +1662,6 @@ static void wm_optimization_wa(struct intel_dp *intel_dp, wa_16013835468_bit_get(intel_dp), 0); } -static void lnl_alpm_configure(struct intel_dp *intel_dp) -{ - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - enum transcoder cpu_transcoder = intel_dp->psr.transcoder; - struct intel_psr *psr = &intel_dp->psr; - u32 alpm_ctl; - - if (DISPLAY_VER(dev_priv) < 20 || (!intel_dp->psr.psr2_enabled && - !intel_dp_is_edp(intel_dp))) - return; - - /* - * Panel Replay on eDP is always using ALPM aux less. I.e. no need to - * check panel support at this point. - */ - if (intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) { - alpm_ctl = ALPM_CTL_ALPM_ENABLE | - ALPM_CTL_ALPM_AUX_LESS_ENABLE | - ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS; - - intel_de_write(dev_priv, PORT_ALPM_CTL(cpu_transcoder), - PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE | - PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) | - PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) | - PORT_ALPM_CTL_SILENCE_PERIOD( - psr->alpm_parameters.silence_period_sym_clocks)); - - intel_de_write(dev_priv, PORT_ALPM_LFPS_CTL(cpu_transcoder), - PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(10) | - PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION( - psr->alpm_parameters.lfps_half_cycle_num_of_syms) | - PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION( - psr->alpm_parameters.lfps_half_cycle_num_of_syms) | - PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION( - psr->alpm_parameters.lfps_half_cycle_num_of_syms)); - } else { - alpm_ctl = ALPM_CTL_EXTENDED_FAST_WAKE_ENABLE | - ALPM_CTL_EXTENDED_FAST_WAKE_TIME(psr->alpm_parameters.fast_wake_lines); - } - - alpm_ctl |= ALPM_CTL_ALPM_ENTRY_CHECK(psr->alpm_parameters.check_entry_lines); - - intel_de_write(dev_priv, ALPM_CTL(cpu_transcoder), alpm_ctl); -} - static void intel_psr_enable_source(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -1877,7 +1731,9 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, * transcoder, EXITLINE will need to be unset when disabling PSR */ if (intel_dp->psr.dc3co_exitline) - intel_de_rmw(dev_priv, TRANS_EXITLINE(cpu_transcoder), EXITLINE_MASK, + intel_de_rmw(dev_priv, + TRANS_EXITLINE(dev_priv, cpu_transcoder), + EXITLINE_MASK, intel_dp->psr.dc3co_exitline << EXITLINE_SHIFT | EXITLINE_ENABLE); if (HAS_PSR_HW_TRACKING(dev_priv) && HAS_PSR2_SEL_FETCH(dev_priv)) @@ -1886,7 +1742,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, IGNORE_PSR2_HW_TRACKING : 0); if (intel_dp_is_edp(intel_dp)) - lnl_alpm_configure(intel_dp); + intel_alpm_configure(intel_dp, crtc_state); /* * Wa_16013835468 @@ -1894,7 +1750,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, */ wm_optimization_wa(intel_dp, crtc_state); - if (intel_dp->psr.psr2_enabled) { + if (intel_dp->psr.sel_update_enabled) { if (DISPLAY_VER(dev_priv) == 9) intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder), 0, PSR2_VSC_ENABLE_PROG_HEADER | @@ -1905,15 +1761,18 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, * All supported adlp panels have 1-based X granularity, this may * cause issues if non-supported panels are used. */ - if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0) || - IS_ALDERLAKE_P(dev_priv)) + if (!intel_dp->psr.panel_replay_enabled && + (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0) || + IS_ALDERLAKE_P(dev_priv))) intel_de_rmw(dev_priv, hsw_chicken_trans_reg(dev_priv, cpu_transcoder), 0, ADLP_1_BASED_X_GRANULARITY); /* Wa_16012604467:adlp,mtl[a0,b0] */ - if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0)) + if (!intel_dp->psr.panel_replay_enabled && + IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0)) intel_de_rmw(dev_priv, - MTL_CLKGATE_DIS_TRANS(cpu_transcoder), 0, + MTL_CLKGATE_DIS_TRANS(dev_priv, cpu_transcoder), + 0, MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS); else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, 0, @@ -1960,7 +1819,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp, drm_WARN_ON(&dev_priv->drm, intel_dp->psr.enabled); - intel_dp->psr.psr2_enabled = crtc_state->has_psr2; + intel_dp->psr.sel_update_enabled = crtc_state->has_sel_update; intel_dp->psr.panel_replay_enabled = crtc_state->has_panel_replay; intel_dp->psr.busy_frontbuffer_bits = 0; intel_dp->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; @@ -1970,6 +1829,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp, intel_dp->psr.dc3co_exit_delay = val; intel_dp->psr.dc3co_exitline = crtc_state->dc3co_exitline; intel_dp->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch; + intel_dp->psr.su_region_et_enabled = crtc_state->enable_psr2_su_region_et; intel_dp->psr.psr2_sel_fetch_cff_enabled = false; intel_dp->psr.req_psr2_sdp_prior_scanline = crtc_state->req_psr2_sdp_prior_scanline; @@ -1981,7 +1841,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp, drm_dbg_kms(&dev_priv->drm, "Enabling Panel Replay\n"); } else { drm_dbg_kms(&dev_priv->drm, "Enabling PSR%s\n", - intel_dp->psr.psr2_enabled ? "2" : "1"); + intel_dp->psr.sel_update_enabled ? "2" : "1"); /* * Panel replay has to be enabled before link training: doing it @@ -2008,7 +1868,8 @@ static void intel_psr_exit(struct intel_dp *intel_dp) if (!intel_dp->psr.active) { if (transcoder_has_psr2(dev_priv, cpu_transcoder)) { - val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder)); + val = intel_de_read(dev_priv, + EDP_PSR2_CTL(dev_priv, cpu_transcoder)); drm_WARN_ON(&dev_priv->drm, val & EDP_PSR2_ENABLE); } @@ -2021,10 +1882,11 @@ static void intel_psr_exit(struct intel_dp *intel_dp) if (intel_dp->psr.panel_replay_enabled) { intel_de_rmw(dev_priv, TRANS_DP2_CTL(intel_dp->psr.transcoder), TRANS_DP2_PANEL_REPLAY_ENABLE, 0); - } else if (intel_dp->psr.psr2_enabled) { + } else if (intel_dp->psr.sel_update_enabled) { tgl_disallow_dc3co_on_psr2_exit(intel_dp); - val = intel_de_rmw(dev_priv, EDP_PSR2_CTL(cpu_transcoder), + val = intel_de_rmw(dev_priv, + EDP_PSR2_CTL(dev_priv, cpu_transcoder), EDP_PSR2_ENABLE, 0); drm_WARN_ON(&dev_priv->drm, !(val & EDP_PSR2_ENABLE)); @@ -2044,8 +1906,9 @@ static void intel_psr_wait_exit_locked(struct intel_dp *intel_dp) i915_reg_t psr_status; u32 psr_status_mask; - if (intel_dp->psr.psr2_enabled) { - psr_status = EDP_PSR2_STATUS(cpu_transcoder); + if (intel_dp_is_edp(intel_dp) && (intel_dp->psr.sel_update_enabled || + intel_dp->psr.panel_replay_enabled)) { + psr_status = EDP_PSR2_STATUS(dev_priv, cpu_transcoder); psr_status_mask = EDP_PSR2_STATUS_STATE_MASK; } else { psr_status = psr_status_reg(dev_priv, cpu_transcoder); @@ -2072,7 +1935,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) drm_dbg_kms(&dev_priv->drm, "Disabling Panel Replay\n"); else drm_dbg_kms(&dev_priv->drm, "Disabling PSR%s\n", - intel_dp->psr.psr2_enabled ? "2" : "1"); + intel_dp->psr.sel_update_enabled ? "2" : "1"); intel_psr_exit(intel_dp); intel_psr_wait_exit_locked(intel_dp); @@ -2085,11 +1948,12 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, wa_16013835468_bit_get(intel_dp), 0); - if (intel_dp->psr.psr2_enabled) { + if (intel_dp->psr.sel_update_enabled) { /* Wa_16012604467:adlp,mtl[a0,b0] */ - if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0)) + if (!intel_dp->psr.panel_replay_enabled && + IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0)) intel_de_rmw(dev_priv, - MTL_CLKGATE_DIS_TRANS(cpu_transcoder), + MTL_CLKGATE_DIS_TRANS(dev_priv, cpu_transcoder), MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS, 0); else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, @@ -2101,26 +1965,29 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) /* Panel Replay on eDP is always using ALPM aux less. */ if (intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) { - intel_de_rmw(dev_priv, ALPM_CTL(cpu_transcoder), + intel_de_rmw(dev_priv, ALPM_CTL(dev_priv, cpu_transcoder), ALPM_CTL_ALPM_ENABLE | ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0); - intel_de_rmw(dev_priv, PORT_ALPM_CTL(cpu_transcoder), + intel_de_rmw(dev_priv, + PORT_ALPM_CTL(dev_priv, cpu_transcoder), PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0); } /* Disable PSR on Sink */ - drm_dp_dpcd_writeb(&intel_dp->aux, - intel_psr_get_enable_sink_offset(intel_dp), 0); + if (!intel_dp->psr.panel_replay_enabled) { + drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); - if (!intel_dp->psr.panel_replay_enabled && - intel_dp->psr.psr2_enabled) - drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, 0); + if (intel_dp->psr.sel_update_enabled) + drm_dp_dpcd_writeb(&intel_dp->aux, + DP_RECEIVER_ALPM_CONFIG, 0); + } intel_dp->psr.enabled = false; intel_dp->psr.panel_replay_enabled = false; - intel_dp->psr.psr2_enabled = false; + intel_dp->psr.sel_update_enabled = false; intel_dp->psr.psr2_sel_fetch_enabled = false; + intel_dp->psr.su_region_et_enabled = false; intel_dp->psr.psr2_sel_fetch_cff_enabled = false; } @@ -2244,7 +2111,7 @@ static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp) if (intel_dp->psr.psr2_sel_fetch_enabled) intel_de_write(dev_priv, - PSR2_MAN_TRK_CTL(cpu_transcoder), + PSR2_MAN_TRK_CTL(dev_priv, cpu_transcoder), man_trk_ctl_enable_bit_get(dev_priv) | man_trk_ctl_partial_frame_bit_get(dev_priv) | man_trk_ctl_single_full_frame_bit_get(dev_priv) | @@ -2263,7 +2130,7 @@ static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp) * but testing proved that it works for up display 13, for newer * than that testing will be needed. */ - intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0); + intel_de_write(dev_priv, CURSURFLIVE(dev_priv, intel_dp->psr.pipe), 0); } void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state) @@ -2286,7 +2153,7 @@ void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_st break; } - intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder), + intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(dev_priv, cpu_transcoder), crtc_state->psr2_man_track_ctl); if (!crtc_state->enable_psr2_su_region_et) @@ -2332,19 +2199,14 @@ exit: crtc_state->psr2_man_track_ctl = val; } -static u32 -psr2_pipe_srcsz_early_tpt_calc(struct intel_crtc_state *crtc_state, - bool full_update, bool cursor_in_su_area) +static u32 psr2_pipe_srcsz_early_tpt_calc(struct intel_crtc_state *crtc_state, + bool full_update) { int width, height; if (!crtc_state->enable_psr2_su_region_et || full_update) return 0; - if (!cursor_in_su_area) - return PIPESRC_WIDTH(0) | - PIPESRC_HEIGHT(drm_rect_height(&crtc_state->pipe_src)); - width = drm_rect_width(&crtc_state->psr2_su_area); height = drm_rect_height(&crtc_state->psr2_su_area); @@ -2484,7 +2346,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, crtc_state->psr2_su_area.x1 = 0; crtc_state->psr2_su_area.y1 = -1; - crtc_state->psr2_su_area.x2 = INT_MAX; + crtc_state->psr2_su_area.x2 = drm_rect_width(&crtc_state->pipe_src); crtc_state->psr2_su_area.y2 = -1; /* @@ -2573,8 +2435,9 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, goto skip_sel_fetch_set_loop; /* Wa_14014971492 */ - if ((IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0) || - IS_ALDERLAKE_P(dev_priv) || IS_TIGERLAKE(dev_priv)) && + if (!crtc_state->has_panel_replay && + ((IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0) || + IS_ALDERLAKE_P(dev_priv) || IS_TIGERLAKE(dev_priv))) && crtc_state->splitter.enable) crtc_state->psr2_su_area.y1 = 0; @@ -2652,8 +2515,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, skip_sel_fetch_set_loop: psr2_man_trk_ctl_calc(crtc_state, full_update); crtc_state->pipe_srcsz_early_tpt = - psr2_pipe_srcsz_early_tpt_calc(crtc_state, full_update, - cursor_in_su_area); + psr2_pipe_srcsz_early_tpt_calc(crtc_state, full_update); return 0; } @@ -2683,12 +2545,15 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state, * - PSR disabled in new state * - All planes will go inactive * - Changing between PSR versions + * - Region Early Transport changing * - Display WA #1136: skl, bxt */ needs_to_disable |= intel_crtc_needs_modeset(new_crtc_state); needs_to_disable |= !new_crtc_state->has_psr; needs_to_disable |= !new_crtc_state->active_planes; - needs_to_disable |= new_crtc_state->has_psr2 != psr->psr2_enabled; + needs_to_disable |= new_crtc_state->has_sel_update != psr->sel_update_enabled; + needs_to_disable |= new_crtc_state->enable_psr2_su_region_et != + psr->su_region_et_enabled; needs_to_disable |= DISPLAY_VER(i915) < 11 && new_crtc_state->wm_level_disabled; @@ -2761,7 +2626,7 @@ static int _psr2_ready_for_pipe_update_locked(struct intel_dp *intel_dp) * EDP_PSR2_STATUS_STATE_DEEP_SLEEP to be cleared. */ return intel_de_wait_for_clear(dev_priv, - EDP_PSR2_STATUS(cpu_transcoder), + EDP_PSR2_STATUS(dev_priv, cpu_transcoder), EDP_PSR2_STATUS_STATE_DEEP_SLEEP, 50); } @@ -2781,6 +2646,13 @@ static int _psr1_ready_for_pipe_update_locked(struct intel_dp *intel_dp) EDP_PSR_STATUS_STATE_MASK, 50); } +static int _panel_replay_ready_for_pipe_update_locked(struct intel_dp *intel_dp) +{ + return intel_dp_is_edp(intel_dp) ? + _psr2_ready_for_pipe_update_locked(intel_dp) : + _psr1_ready_for_pipe_update_locked(intel_dp); +} + /** * intel_psr_wait_for_idle_locked - wait for PSR be ready for a pipe update * @new_crtc_state: new CRTC state @@ -2806,7 +2678,9 @@ void intel_psr_wait_for_idle_locked(const struct intel_crtc_state *new_crtc_stat if (!intel_dp->psr.enabled) continue; - if (intel_dp->psr.psr2_enabled) + if (intel_dp->psr.panel_replay_enabled) + ret = _panel_replay_ready_for_pipe_update_locked(intel_dp); + else if (intel_dp->psr.sel_update_enabled) ret = _psr2_ready_for_pipe_update_locked(intel_dp); else ret = _psr1_ready_for_pipe_update_locked(intel_dp); @@ -2827,8 +2701,9 @@ static bool __psr_wait_for_idle_locked(struct intel_dp *intel_dp) if (!intel_dp->psr.enabled) return false; - if (intel_dp->psr.psr2_enabled) { - reg = EDP_PSR2_STATUS(cpu_transcoder); + if (intel_dp_is_edp(intel_dp) && (intel_dp->psr.sel_update_enabled || + intel_dp->psr.panel_replay_enabled)) { + reg = EDP_PSR2_STATUS(dev_priv, cpu_transcoder); mask = EDP_PSR2_STATUS_STATE_MASK; } else { reg = psr_status_reg(dev_priv, cpu_transcoder); @@ -2914,10 +2789,14 @@ int intel_psr_debug_set(struct intel_dp *intel_dp, u64 val) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); const u32 mode = val & I915_PSR_DEBUG_MODE_MASK; - u32 old_mode; + const u32 disable_bits = val & (I915_PSR_DEBUG_SU_REGION_ET_DISABLE | + I915_PSR_DEBUG_PANEL_REPLAY_DISABLE); + u32 old_mode, old_disable_bits; int ret; - if (val & ~(I915_PSR_DEBUG_IRQ | I915_PSR_DEBUG_MODE_MASK) || + if (val & ~(I915_PSR_DEBUG_IRQ | I915_PSR_DEBUG_SU_REGION_ET_DISABLE | + I915_PSR_DEBUG_PANEL_REPLAY_DISABLE | + I915_PSR_DEBUG_MODE_MASK) || mode > I915_PSR_DEBUG_ENABLE_SEL_FETCH) { drm_dbg_kms(&dev_priv->drm, "Invalid debug mask %llx\n", val); return -EINVAL; @@ -2928,6 +2807,10 @@ int intel_psr_debug_set(struct intel_dp *intel_dp, u64 val) return ret; old_mode = intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK; + old_disable_bits = intel_dp->psr.debug & + (I915_PSR_DEBUG_SU_REGION_ET_DISABLE | + I915_PSR_DEBUG_PANEL_REPLAY_DISABLE); + intel_dp->psr.debug = val; /* @@ -2939,7 +2822,7 @@ int intel_psr_debug_set(struct intel_dp *intel_dp, u64 val) mutex_unlock(&intel_dp->psr.lock); - if (old_mode != mode) + if (old_mode != mode || old_disable_bits != disable_bits) ret = intel_psr_fastset_force(dev_priv); return ret; @@ -3000,15 +2883,20 @@ static void _psr_invalidate_handle(struct intel_dp *intel_dp) if (intel_dp->psr.psr2_sel_fetch_cff_enabled) { /* Send one update otherwise lag is observed in screen */ - intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0); + intel_de_write(dev_priv, + CURSURFLIVE(dev_priv, intel_dp->psr.pipe), + 0); return; } val = man_trk_ctl_enable_bit_get(dev_priv) | man_trk_ctl_partial_frame_bit_get(dev_priv) | man_trk_ctl_continuos_full_frame(dev_priv); - intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder), val); - intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0); + intel_de_write(dev_priv, + PSR2_MAN_TRK_CTL(dev_priv, cpu_transcoder), + val); + intel_de_write(dev_priv, + CURSURFLIVE(dev_priv, intel_dp->psr.pipe), 0); intel_dp->psr.psr2_sel_fetch_cff_enabled = true; } else { intel_psr_exit(intel_dp); @@ -3068,7 +2956,7 @@ tgl_dc3co_flush_locked(struct intel_dp *intel_dp, unsigned int frontbuffer_bits, { struct drm_i915_private *i915 = dp_to_i915(intel_dp); - if (!intel_dp->psr.dc3co_exitline || !intel_dp->psr.psr2_enabled || + if (!intel_dp->psr.dc3co_exitline || !intel_dp->psr.sel_update_enabled || !intel_dp->psr.active) return; @@ -3105,9 +2993,12 @@ static void _psr_flush_handle(struct intel_dp *intel_dp) * SU configuration in case update is sent for any reason after * sff bit gets cleared by the HW on next vblank. */ - intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder), + intel_de_write(dev_priv, + PSR2_MAN_TRK_CTL(dev_priv, cpu_transcoder), val); - intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0); + intel_de_write(dev_priv, + CURSURFLIVE(dev_priv, intel_dp->psr.pipe), + 0); intel_dp->psr.psr2_sel_fetch_cff_enabled = false; } } else { @@ -3219,9 +3110,6 @@ void intel_psr_init(struct intel_dp *intel_dp) else intel_dp->psr.source_support = true; - /* Disable early transport for now */ - intel_dp->psr.debug |= I915_PSR_DEBUG_SU_REGION_ET_DISABLE; - /* Set link_standby x link_off defaults */ if (DISPLAY_VER(dev_priv) < 12) /* For new platforms up to TGL let's respect VBT back again */ @@ -3266,7 +3154,7 @@ static void psr_alpm_check(struct intel_dp *intel_dp) u8 val; int r; - if (!psr->psr2_enabled) + if (!psr->sel_update_enabled) return; r = drm_dp_dpcd_readb(aux, DP_RECEIVER_ALPM_STATUS, &val); @@ -3446,7 +3334,8 @@ psr_source_status(struct intel_dp *intel_dp, struct seq_file *m) const char *status = "unknown"; u32 val, status_val; - if (intel_dp->psr.psr2_enabled) { + if (intel_dp_is_edp(intel_dp) && (intel_dp->psr.sel_update_enabled || + intel_dp->psr.panel_replay_enabled)) { static const char * const live_status[] = { "IDLE", "CAPTURE", @@ -3460,7 +3349,8 @@ psr_source_status(struct intel_dp *intel_dp, struct seq_file *m) "BUF_ON", "TG_ON" }; - val = intel_de_read(dev_priv, EDP_PSR2_STATUS(cpu_transcoder)); + val = intel_de_read(dev_priv, + EDP_PSR2_STATUS(dev_priv, cpu_transcoder)); status_val = REG_FIELD_GET(EDP_PSR2_STATUS_STATE_MASK, val); if (status_val < ARRAY_SIZE(live_status)) status = live_status[status_val]; @@ -3484,22 +3374,66 @@ psr_source_status(struct intel_dp *intel_dp, struct seq_file *m) seq_printf(m, "Source PSR/PanelReplay status: %s [0x%08x]\n", status, val); } -static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) +static void intel_psr_sink_capability(struct intel_dp *intel_dp, + struct seq_file *m) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - enum transcoder cpu_transcoder = intel_dp->psr.transcoder; struct intel_psr *psr = &intel_dp->psr; - intel_wakeref_t wakeref; - const char *status; - bool enabled; - u32 val; seq_printf(m, "Sink support: PSR = %s", str_yes_no(psr->sink_support)); if (psr->sink_support) seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]); - seq_printf(m, ", Panel Replay = %s\n", str_yes_no(psr->sink_panel_replay_support)); + if (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_ET_SUPPORTED) + seq_printf(m, " (Early Transport)"); + seq_printf(m, ", Panel Replay = %s", str_yes_no(psr->sink_panel_replay_support)); + seq_printf(m, ", Panel Replay Selective Update = %s", + str_yes_no(psr->sink_panel_replay_su_support)); + if (intel_dp->pr_dpcd & DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT) + seq_printf(m, " (Early Transport)"); + seq_printf(m, "\n"); +} + +static void intel_psr_print_mode(struct intel_dp *intel_dp, + struct seq_file *m) +{ + struct intel_psr *psr = &intel_dp->psr; + const char *status, *mode, *region_et; + + if (psr->enabled) + status = " enabled"; + else + status = "disabled"; + + if (psr->panel_replay_enabled && psr->sel_update_enabled) + mode = "Panel Replay Selective Update"; + else if (psr->panel_replay_enabled) + mode = "Panel Replay"; + else if (psr->sel_update_enabled) + mode = "PSR2"; + else if (psr->enabled) + mode = "PSR1"; + else + mode = ""; + + if (psr->su_region_et_enabled) + region_et = " (Early Transport)"; + else + region_et = ""; + + seq_printf(m, "PSR mode: %s%s%s\n", mode, status, region_et); +} + +static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + enum transcoder cpu_transcoder = intel_dp->psr.transcoder; + struct intel_psr *psr = &intel_dp->psr; + intel_wakeref_t wakeref; + bool enabled; + u32 val, psr2_ctl; + + intel_psr_sink_capability(intel_dp, m); if (!(psr->sink_support || psr->sink_panel_replay_support)) return 0; @@ -3507,13 +3441,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); mutex_lock(&psr->lock); - if (psr->panel_replay_enabled) - status = "Panel Replay Enabled"; - else if (psr->enabled) - status = psr->psr2_enabled ? "PSR2 enabled" : "PSR1 enabled"; - else - status = "disabled"; - seq_printf(m, "PSR mode: %s\n", status); + intel_psr_print_mode(intel_dp, m); if (!psr->enabled) { seq_printf(m, "PSR sink not reliable: %s\n", @@ -3524,9 +3452,16 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) if (psr->panel_replay_enabled) { val = intel_de_read(dev_priv, TRANS_DP2_CTL(cpu_transcoder)); + + if (intel_dp_is_edp(intel_dp)) + psr2_ctl = intel_de_read(dev_priv, + EDP_PSR2_CTL(dev_priv, + cpu_transcoder)); + enabled = val & TRANS_DP2_PANEL_REPLAY_ENABLE; - } else if (psr->psr2_enabled) { - val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder)); + } else if (psr->sel_update_enabled) { + val = intel_de_read(dev_priv, + EDP_PSR2_CTL(dev_priv, cpu_transcoder)); enabled = val & EDP_PSR2_ENABLE; } else { val = intel_de_read(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder)); @@ -3534,6 +3469,9 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) } seq_printf(m, "Source PSR/PanelReplay ctl: %s [0x%08x]\n", str_enabled_disabled(enabled), val); + if (psr->panel_replay_enabled && intel_dp_is_edp(intel_dp)) + seq_printf(m, "PSR2_CTL: 0x%08x\n", + psr2_ctl); psr_source_status(intel_dp, m); seq_printf(m, "Busy frontbuffer bits: 0x%08x\n", psr->busy_frontbuffer_bits); @@ -3551,7 +3489,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) seq_printf(m, "Last exit at: %lld\n", psr->last_exit); } - if (psr->psr2_enabled) { + if (psr->sel_update_enabled) { u32 su_frames_val[3]; int frame; @@ -3560,7 +3498,8 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) * frame boundary between register reads */ for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame += 3) { - val = intel_de_read(dev_priv, PSR2_SU_STATUS(cpu_transcoder, frame)); + val = intel_de_read(dev_priv, + PSR2_SU_STATUS(dev_priv, cpu_transcoder, frame)); su_frames_val[frame / 3] = val; } @@ -3694,16 +3633,9 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data) "reserved", "sink internal error", }; - static const char * const panel_replay_status[] = { - "Sink device frame is locked to the Source device", - "Sink device is coasting, using the VTotal target", - "Sink device is governing the frame rate (frame rate unlock is granted)", - "Sink device in the process of re-locking with the Source device", - }; const char *str; int ret; u8 status, error_status; - u32 idx; if (!(CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp))) { seq_puts(m, "PSR/Panel-Replay Unsupported\n"); @@ -3717,16 +3649,11 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data) if (ret) return ret; - str = "unknown"; - if (intel_dp->psr.panel_replay_enabled) { - idx = (status & DP_SINK_FRAME_LOCKED_MASK) >> DP_SINK_FRAME_LOCKED_SHIFT; - if (idx < ARRAY_SIZE(panel_replay_status)) - str = panel_replay_status[idx]; - } else if (intel_dp->psr.enabled) { - idx = status & DP_PSR_SINK_STATE_MASK; - if (idx < ARRAY_SIZE(sink_status)) - str = sink_status[idx]; - } + status &= DP_PSR_SINK_STATE_MASK; + if (status < ARRAY_SIZE(sink_status)) + str = sink_status[status]; + else + str = "unknown"; seq_printf(m, "Sink %s status: 0x%x [%s]\n", psr_mode_str(intel_dp), status, str); diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h index ebc22999572c..642bb15fb547 100644 --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h @@ -9,7 +9,7 @@ #include "intel_display_reg_defs.h" #include "intel_dp_aux_regs.h" -#define TRANS_EXITLINE(trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_EXITLINE_A) +#define TRANS_EXITLINE(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_EXITLINE_A) #define EXITLINE_ENABLE REG_BIT(31) #define EXITLINE_MASK REG_GENMASK(12, 0) #define EXITLINE_SHIFT 0 @@ -23,7 +23,7 @@ #define HSW_SRD_CTL _MMIO(0x64800) #define _SRD_CTL_A 0x60800 #define _SRD_CTL_EDP 0x6f800 -#define EDP_PSR_CTL(tran) _MMIO_TRANS2(dev_priv, tran, _SRD_CTL_A) +#define EDP_PSR_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _SRD_CTL_A) #define EDP_PSR_ENABLE REG_BIT(31) #define BDW_PSR_SINGLE_FRAME REG_BIT(30) #define EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK REG_BIT(29) /* SW can't modify */ @@ -66,8 +66,8 @@ #define EDP_PSR_IIR _MMIO(0x64838) #define _PSR_IMR_A 0x60814 #define _PSR_IIR_A 0x60818 -#define TRANS_PSR_IMR(tran) _MMIO_TRANS2(dev_priv, tran, _PSR_IMR_A) -#define TRANS_PSR_IIR(tran) _MMIO_TRANS2(dev_priv, tran, _PSR_IIR_A) +#define TRANS_PSR_IMR(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PSR_IMR_A) +#define TRANS_PSR_IIR(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PSR_IIR_A) #define _EDP_PSR_TRANS_SHIFT(trans) ((trans) == TRANSCODER_EDP ? \ 0 : ((trans) - TRANSCODER_A + 1) * 8) #define TGL_PSR_MASK REG_GENMASK(2, 0) @@ -86,7 +86,7 @@ #define HSW_SRD_AUX_CTL _MMIO(0x64810) #define _SRD_AUX_CTL_A 0x60810 #define _SRD_AUX_CTL_EDP 0x6f810 -#define EDP_PSR_AUX_CTL(tran) _MMIO_TRANS2(dev_priv, tran, _SRD_AUX_CTL_A) +#define EDP_PSR_AUX_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _SRD_AUX_CTL_A) #define EDP_PSR_AUX_CTL_TIME_OUT_MASK DP_AUX_CH_CTL_TIME_OUT_MASK #define EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK DP_AUX_CH_CTL_MESSAGE_SIZE_MASK #define EDP_PSR_AUX_CTL_PRECHARGE_2US_MASK DP_AUX_CH_CTL_PRECHARGE_2US_MASK @@ -96,12 +96,12 @@ #define HSW_SRD_AUX_DATA(i) _MMIO(0x64814 + (i) * 4) /* 5 registers */ #define _SRD_AUX_DATA_A 0x60814 #define _SRD_AUX_DATA_EDP 0x6f814 -#define EDP_PSR_AUX_DATA(tran, i) _MMIO_TRANS2(dev_priv, tran, _SRD_AUX_DATA_A + (i) * 4) /* 5 registers */ +#define EDP_PSR_AUX_DATA(dev_priv, tran, i) _MMIO_TRANS2(dev_priv, tran, _SRD_AUX_DATA_A + (i) * 4) /* 5 registers */ #define HSW_SRD_STATUS _MMIO(0x64840) #define _SRD_STATUS_A 0x60840 #define _SRD_STATUS_EDP 0x6f840 -#define EDP_PSR_STATUS(tran) _MMIO_TRANS2(dev_priv, tran, _SRD_STATUS_A) +#define EDP_PSR_STATUS(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _SRD_STATUS_A) #define EDP_PSR_STATUS_STATE_MASK REG_GENMASK(31, 29) #define EDP_PSR_STATUS_STATE_IDLE REG_FIELD_PREP(EDP_PSR_STATUS_STATE_MASK, 0) #define EDP_PSR_STATUS_STATE_SRDONACK REG_FIELD_PREP(EDP_PSR_STATUS_STATE_MASK, 1) @@ -126,14 +126,14 @@ #define HSW_SRD_PERF_CNT _MMIO(0x64844) #define _SRD_PERF_CNT_A 0x60844 #define _SRD_PERF_CNT_EDP 0x6f844 -#define EDP_PSR_PERF_CNT(tran) _MMIO_TRANS2(dev_priv, tran, _SRD_PERF_CNT_A) +#define EDP_PSR_PERF_CNT(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _SRD_PERF_CNT_A) #define EDP_PSR_PERF_CNT_MASK REG_GENMASK(23, 0) /* PSR_MASK on SKL+ */ #define HSW_SRD_DEBUG _MMIO(0x64860) #define _SRD_DEBUG_A 0x60860 #define _SRD_DEBUG_EDP 0x6f860 -#define EDP_PSR_DEBUG(tran) _MMIO_TRANS2(dev_priv, tran, _SRD_DEBUG_A) +#define EDP_PSR_DEBUG(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _SRD_DEBUG_A) #define EDP_PSR_DEBUG_MASK_MAX_SLEEP REG_BIT(28) #define EDP_PSR_DEBUG_MASK_LPSP REG_BIT(27) #define EDP_PSR_DEBUG_MASK_MEMUP REG_BIT(26) @@ -153,7 +153,7 @@ #define _PSR2_CTL_A 0x60900 #define _PSR2_CTL_EDP 0x6f900 -#define EDP_PSR2_CTL(tran) _MMIO_TRANS2(dev_priv, tran, _PSR2_CTL_A) +#define EDP_PSR2_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PSR2_CTL_A) #define EDP_PSR2_ENABLE REG_BIT(31) #define EDP_SU_TRACK_ENABLE REG_BIT(30) /* up to adl-p */ #define TGL_EDP_PSR2_BLOCK_COUNT_MASK REG_BIT(28) @@ -172,6 +172,10 @@ #define TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES 5 #define TGL_EDP_PSR2_IO_BUFFER_WAKE(lines) REG_FIELD_PREP(TGL_EDP_PSR2_IO_BUFFER_WAKE_MASK, \ (lines) - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES) +#define LNL_EDP_PSR2_IO_BUFFER_WAKE_MASK REG_GENMASK(18, 13) +#define LNL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES 5 +#define LNL_EDP_PSR2_IO_BUFFER_WAKE(lines) REG_FIELD_PREP(LNL_EDP_PSR2_IO_BUFFER_WAKE_MASK, \ + (lines) - LNL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES) #define EDP_PSR2_FAST_WAKE_MASK REG_GENMASK(12, 11) #define EDP_PSR2_FAST_WAKE_MAX_LINES 8 #define EDP_PSR2_FAST_WAKE(lines) REG_FIELD_PREP(EDP_PSR2_FAST_WAKE_MASK, \ @@ -195,7 +199,7 @@ #define _PSR_EVENT_TRANS_C 0x62848 #define _PSR_EVENT_TRANS_D 0x63848 #define _PSR_EVENT_TRANS_EDP 0x6f848 -#define PSR_EVENT(tran) _MMIO_TRANS2(dev_priv, tran, _PSR_EVENT_TRANS_A) +#define PSR_EVENT(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PSR_EVENT_TRANS_A) #define PSR_EVENT_PSR2_WD_TIMER_EXPIRE REG_BIT(17) #define PSR_EVENT_PSR2_DISABLED REG_BIT(16) #define PSR_EVENT_SU_DIRTY_FIFO_UNDERRUN REG_BIT(15) @@ -215,21 +219,21 @@ #define _PSR2_STATUS_A 0x60940 #define _PSR2_STATUS_EDP 0x6f940 -#define EDP_PSR2_STATUS(tran) _MMIO_TRANS2(dev_priv, tran, _PSR2_STATUS_A) +#define EDP_PSR2_STATUS(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PSR2_STATUS_A) #define EDP_PSR2_STATUS_STATE_MASK REG_GENMASK(31, 28) #define EDP_PSR2_STATUS_STATE_DEEP_SLEEP REG_FIELD_PREP(EDP_PSR2_STATUS_STATE_MASK, 0x8) #define _PSR2_SU_STATUS_A 0x60914 #define _PSR2_SU_STATUS_EDP 0x6f914 -#define _PSR2_SU_STATUS(tran, index) _MMIO_TRANS2(dev_priv, tran, _PSR2_SU_STATUS_A + (index) * 4) -#define PSR2_SU_STATUS(tran, frame) (_PSR2_SU_STATUS(tran, (frame) / 3)) +#define _PSR2_SU_STATUS(dev_priv, tran, index) _MMIO_TRANS2(dev_priv, tran, _PSR2_SU_STATUS_A + (index) * 4) +#define PSR2_SU_STATUS(dev_priv, tran, frame) (_PSR2_SU_STATUS(dev_priv, tran, (frame) / 3)) #define PSR2_SU_STATUS_SHIFT(frame) (((frame) % 3) * 10) #define PSR2_SU_STATUS_MASK(frame) (0x3ff << PSR2_SU_STATUS_SHIFT(frame)) #define PSR2_SU_STATUS_FRAMES 8 #define _PSR2_MAN_TRK_CTL_A 0x60910 #define _PSR2_MAN_TRK_CTL_EDP 0x6f910 -#define PSR2_MAN_TRK_CTL(tran) _MMIO_TRANS2(dev_priv, tran, _PSR2_MAN_TRK_CTL_A) +#define PSR2_MAN_TRK_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PSR2_MAN_TRK_CTL_A) #define PSR2_MAN_TRK_CTL_ENABLE REG_BIT(31) #define PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK REG_GENMASK(30, 21) #define PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val) @@ -248,56 +252,11 @@ /* PSR2 Early transport */ #define _PIPE_SRCSZ_ERLY_TPT_A 0x70074 - -#define PIPE_SRCSZ_ERLY_TPT(trans) _MMIO_TRANS2(dev_priv, trans, _PIPE_SRCSZ_ERLY_TPT_A) - -#define _SEL_FETCH_PLANE_BASE_1_A 0x70890 -#define _SEL_FETCH_PLANE_BASE_2_A 0x708B0 -#define _SEL_FETCH_PLANE_BASE_3_A 0x708D0 -#define _SEL_FETCH_PLANE_BASE_4_A 0x708F0 -#define _SEL_FETCH_PLANE_BASE_5_A 0x70920 -#define _SEL_FETCH_PLANE_BASE_6_A 0x70940 -#define _SEL_FETCH_PLANE_BASE_7_A 0x70960 -#define _SEL_FETCH_PLANE_BASE_CUR_A 0x70880 -#define _SEL_FETCH_PLANE_BASE_1_B 0x71890 - -#define _SEL_FETCH_PLANE_BASE_A(plane) _PICK(plane, \ - _SEL_FETCH_PLANE_BASE_1_A, \ - _SEL_FETCH_PLANE_BASE_2_A, \ - _SEL_FETCH_PLANE_BASE_3_A, \ - _SEL_FETCH_PLANE_BASE_4_A, \ - _SEL_FETCH_PLANE_BASE_5_A, \ - _SEL_FETCH_PLANE_BASE_6_A, \ - _SEL_FETCH_PLANE_BASE_7_A, \ - _SEL_FETCH_PLANE_BASE_CUR_A) -#define _SEL_FETCH_PLANE_BASE_1(pipe) _PIPE(pipe, _SEL_FETCH_PLANE_BASE_1_A, _SEL_FETCH_PLANE_BASE_1_B) -#define _SEL_FETCH_PLANE_BASE(pipe, plane) (_SEL_FETCH_PLANE_BASE_1(pipe) - \ - _SEL_FETCH_PLANE_BASE_1_A + \ - _SEL_FETCH_PLANE_BASE_A(plane)) - -#define _SEL_FETCH_PLANE_CTL_1_A 0x70890 -#define PLANE_SEL_FETCH_CTL(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ - _SEL_FETCH_PLANE_CTL_1_A - \ - _SEL_FETCH_PLANE_BASE_1_A) -#define PLANE_SEL_FETCH_CTL_ENABLE REG_BIT(31) - -#define _SEL_FETCH_PLANE_POS_1_A 0x70894 -#define PLANE_SEL_FETCH_POS(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ - _SEL_FETCH_PLANE_POS_1_A - \ - _SEL_FETCH_PLANE_BASE_1_A) - -#define _SEL_FETCH_PLANE_SIZE_1_A 0x70898 -#define PLANE_SEL_FETCH_SIZE(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ - _SEL_FETCH_PLANE_SIZE_1_A - \ - _SEL_FETCH_PLANE_BASE_1_A) - -#define _SEL_FETCH_PLANE_OFFSET_1_A 0x7089C -#define PLANE_SEL_FETCH_OFFSET(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ - _SEL_FETCH_PLANE_OFFSET_1_A - \ - _SEL_FETCH_PLANE_BASE_1_A) +#define _PIPE_SRCSZ_ERLY_TPT_B 0x71074 +#define PIPE_SRCSZ_ERLY_TPT(pipe) _MMIO_PIPE((pipe), _PIPE_SRCSZ_ERLY_TPT_A, _PIPE_SRCSZ_ERLY_TPT_B) #define _ALPM_CTL_A 0x60950 -#define ALPM_CTL(tran) _MMIO_TRANS2(dev_priv, tran, _ALPM_CTL_A) +#define ALPM_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _ALPM_CTL_A) #define ALPM_CTL_ALPM_ENABLE REG_BIT(31) #define ALPM_CTL_ALPM_AUX_LESS_ENABLE REG_BIT(30) #define ALPM_CTL_LOBF_ENABLE REG_BIT(29) @@ -321,7 +280,7 @@ #define ALPM_CTL_AUX_LESS_WAKE_TIME(val) REG_FIELD_PREP(ALPM_CTL_AUX_LESS_WAKE_TIME_MASK, val) #define _ALPM_CTL2_A 0x60954 -#define ALPM_CTL2(tran) _MMIO_TRANS2(dev_priv, tran, _ALPM_CTL2_A) +#define ALPM_CTL2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _ALPM_CTL2_A) #define ALPM_CTL2_SWITCH_TO_ACTIVE_LATENCY_MASK REG_GENMASK(28, 24) #define ALPM_CTL2_SWITCH_TO_ACTIVE_LATENCY(val) REG_FIELD_PREP(ALPM_CTL2_SWITCH_TO_ACTIVE_LATENCY_MASK, val) #define ALPM_CTL2_AUX_LESS_WAKE_TIME_EXTENSION_MASK REG_GENMASK(19, 16) @@ -335,7 +294,8 @@ #define ALPM_CTL2_NUMBER_AUX_LESS_ML_PHY_SLEEP_SEQUENCES(val) REG_FIELD_PREP(ALPM_CTL2_NUMBER_AUX_LESS_ML_PHY_SLEEP_SEQUENCES_MASK, val) #define _PORT_ALPM_CTL_A 0x16fa2c -#define PORT_ALPM_CTL(tran) _MMIO_TRANS2(dev_priv, tran, _PORT_ALPM_CTL_A) +#define _PORT_ALPM_CTL_B 0x16fc2c +#define PORT_ALPM_CTL(dev_priv, port) _MMIO_PORT(port, _PORT_ALPM_CTL_A, _PORT_ALPM_CTL_B) #define PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE REG_BIT(31) #define PORT_ALPM_CTL_MAX_PHY_SWING_SETUP_MASK REG_GENMASK(23, 20) #define PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(val) REG_FIELD_PREP(PORT_ALPM_CTL_MAX_PHY_SWING_SETUP_MASK, val) @@ -345,7 +305,8 @@ #define PORT_ALPM_CTL_SILENCE_PERIOD(val) REG_FIELD_PREP(PORT_ALPM_CTL_SILENCE_PERIOD_MASK, val) #define _PORT_ALPM_LFPS_CTL_A 0x16fa30 -#define PORT_ALPM_LFPS_CTL(tran) _MMIO_TRANS2(dev_priv, tran, _PORT_ALPM_LFPS_CTL_A) +#define _PORT_ALPM_LFPS_CTL_B 0x16fc30 +#define PORT_ALPM_LFPS_CTL(dev_priv, port) _MMIO_PORT(port, _PORT_ALPM_LFPS_CTL_A, _PORT_ALPM_LFPS_CTL_B) #define PORT_ALPM_LFPS_CTL_LFPS_START_POLARITY REG_BIT(31) #define PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT_MASK REG_GENMASK(27, 24) #define PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT_MIN 7 diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 36a253a19c74..e1c907f601da 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -39,7 +39,6 @@ #include <drm/drm_rect.h> #include "i915_drv.h" -#include "i915_reg.h" #include "i9xx_plane.h" #include "intel_atomic_plane.h" #include "intel_de.h" diff --git a/drivers/gpu/drm/i915/display/intel_sprite_regs.h b/drivers/gpu/drm/i915/display/intel_sprite_regs.h index bb67705652b2..73021e3ced6d 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite_regs.h +++ b/drivers/gpu/drm/i915/display/intel_sprite_regs.h @@ -6,7 +6,10 @@ #include "intel_display_reg_defs.h" +/* g4x/ilk/snb video sprite */ #define _DVSACNTR 0x72180 +#define _DVSBCNTR 0x73180 +#define DVSCNTR(pipe) _MMIO_PIPE(pipe, _DVSACNTR, _DVSBCNTR) #define DVS_ENABLE REG_BIT(31) #define DVS_PIPE_GAMMA_ENABLE REG_BIT(30) #define DVS_YUV_RANGE_CORRECTION_DISABLE REG_BIT(27) @@ -28,31 +31,67 @@ #define DVS_TRICKLE_FEED_DISABLE REG_BIT(14) #define DVS_TILED REG_BIT(10) #define DVS_DEST_KEY REG_BIT(2) + #define _DVSALINOFF 0x72184 +#define _DVSBLINOFF 0x73184 +#define DVSLINOFF(pipe) _MMIO_PIPE(pipe, _DVSALINOFF, _DVSBLINOFF) + #define _DVSASTRIDE 0x72188 +#define _DVSBSTRIDE 0x73188 +#define DVSSTRIDE(pipe) _MMIO_PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE) + #define _DVSAPOS 0x7218c +#define _DVSBPOS 0x7318c +#define DVSPOS(pipe) _MMIO_PIPE(pipe, _DVSAPOS, _DVSBPOS) #define DVS_POS_Y_MASK REG_GENMASK(31, 16) #define DVS_POS_Y(y) REG_FIELD_PREP(DVS_POS_Y_MASK, (y)) #define DVS_POS_X_MASK REG_GENMASK(15, 0) #define DVS_POS_X(x) REG_FIELD_PREP(DVS_POS_X_MASK, (x)) + #define _DVSASIZE 0x72190 +#define _DVSBSIZE 0x73190 +#define DVSSIZE(pipe) _MMIO_PIPE(pipe, _DVSASIZE, _DVSBSIZE) #define DVS_HEIGHT_MASK REG_GENMASK(31, 16) #define DVS_HEIGHT(h) REG_FIELD_PREP(DVS_HEIGHT_MASK, (h)) #define DVS_WIDTH_MASK REG_GENMASK(15, 0) #define DVS_WIDTH(w) REG_FIELD_PREP(DVS_WIDTH_MASK, (w)) + #define _DVSAKEYVAL 0x72194 +#define _DVSBKEYVAL 0x73194 +#define DVSKEYVAL(pipe) _MMIO_PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL) + #define _DVSAKEYMSK 0x72198 +#define _DVSBKEYMSK 0x73198 +#define DVSKEYMSK(pipe) _MMIO_PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK) + #define _DVSASURF 0x7219c +#define _DVSBSURF 0x7319c +#define DVSSURF(pipe) _MMIO_PIPE(pipe, _DVSASURF, _DVSBSURF) #define DVS_ADDR_MASK REG_GENMASK(31, 12) + #define _DVSAKEYMAXVAL 0x721a0 +#define _DVSBKEYMAXVAL 0x731a0 +#define DVSKEYMAX(pipe) _MMIO_PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL) + #define _DVSATILEOFF 0x721a4 +#define _DVSBTILEOFF 0x731a4 +#define DVSTILEOFF(pipe) _MMIO_PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF) #define DVS_OFFSET_Y_MASK REG_GENMASK(31, 16) #define DVS_OFFSET_Y(y) REG_FIELD_PREP(DVS_OFFSET_Y_MASK, (y)) #define DVS_OFFSET_X_MASK REG_GENMASK(15, 0) #define DVS_OFFSET_X(x) REG_FIELD_PREP(DVS_OFFSET_X_MASK, (x)) + #define _DVSASURFLIVE 0x721ac +#define _DVSBSURFLIVE 0x731ac +#define DVSSURFLIVE(pipe) _MMIO_PIPE(pipe, _DVSASURFLIVE, _DVSBSURFLIVE) + #define _DVSAGAMC_G4X 0x721e0 /* g4x */ +#define _DVSBGAMC_G4X 0x731e0 /* g4x */ +#define DVSGAMC_G4X(pipe, i) _MMIO(_PIPE(pipe, _DVSAGAMC_G4X, _DVSBGAMC_G4X) + (5 - (i)) * 4) /* 6 x u0.8 */ + #define _DVSASCALE 0x72204 +#define _DVSBSCALE 0x73204 +#define DVSSCALE(pipe) _MMIO_PIPE(pipe, _DVSASCALE, _DVSBSCALE) #define DVS_SCALE_ENABLE REG_BIT(31) #define DVS_FILTER_MASK REG_GENMASK(30, 29) #define DVS_FILTER_MEDIUM REG_FIELD_PREP(DVS_FILTER_MASK, 0) @@ -64,42 +103,19 @@ #define DVS_SRC_WIDTH(w) REG_FIELD_PREP(DVS_SRC_WIDTH_MASK, (w)) #define DVS_SRC_HEIGHT_MASK REG_GENMASK(10, 0) #define DVS_SRC_HEIGHT(h) REG_FIELD_PREP(DVS_SRC_HEIGHT_MASK, (h)) -#define _DVSAGAMC_ILK 0x72300 /* ilk/snb */ -#define _DVSAGAMCMAX_ILK 0x72340 /* ilk/snb */ -#define _DVSBCNTR 0x73180 -#define _DVSBLINOFF 0x73184 -#define _DVSBSTRIDE 0x73188 -#define _DVSBPOS 0x7318c -#define _DVSBSIZE 0x73190 -#define _DVSBKEYVAL 0x73194 -#define _DVSBKEYMSK 0x73198 -#define _DVSBSURF 0x7319c -#define _DVSBKEYMAXVAL 0x731a0 -#define _DVSBTILEOFF 0x731a4 -#define _DVSBSURFLIVE 0x731ac -#define _DVSBGAMC_G4X 0x731e0 /* g4x */ -#define _DVSBSCALE 0x73204 +#define _DVSAGAMC_ILK 0x72300 /* ilk/snb */ #define _DVSBGAMC_ILK 0x73300 /* ilk/snb */ -#define _DVSBGAMCMAX_ILK 0x73340 /* ilk/snb */ - -#define DVSCNTR(pipe) _MMIO_PIPE(pipe, _DVSACNTR, _DVSBCNTR) -#define DVSLINOFF(pipe) _MMIO_PIPE(pipe, _DVSALINOFF, _DVSBLINOFF) -#define DVSSTRIDE(pipe) _MMIO_PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE) -#define DVSPOS(pipe) _MMIO_PIPE(pipe, _DVSAPOS, _DVSBPOS) -#define DVSSURF(pipe) _MMIO_PIPE(pipe, _DVSASURF, _DVSBSURF) -#define DVSKEYMAX(pipe) _MMIO_PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL) -#define DVSSIZE(pipe) _MMIO_PIPE(pipe, _DVSASIZE, _DVSBSIZE) -#define DVSSCALE(pipe) _MMIO_PIPE(pipe, _DVSASCALE, _DVSBSCALE) -#define DVSTILEOFF(pipe) _MMIO_PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF) -#define DVSKEYVAL(pipe) _MMIO_PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL) -#define DVSKEYMSK(pipe) _MMIO_PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK) -#define DVSSURFLIVE(pipe) _MMIO_PIPE(pipe, _DVSASURFLIVE, _DVSBSURFLIVE) -#define DVSGAMC_G4X(pipe, i) _MMIO(_PIPE(pipe, _DVSAGAMC_G4X, _DVSBGAMC_G4X) + (5 - (i)) * 4) /* 6 x u0.8 */ #define DVSGAMC_ILK(pipe, i) _MMIO(_PIPE(pipe, _DVSAGAMC_ILK, _DVSBGAMC_ILK) + (i) * 4) /* 16 x u0.10 */ + +#define _DVSAGAMCMAX_ILK 0x72340 /* ilk/snb */ +#define _DVSBGAMCMAX_ILK 0x73340 /* ilk/snb */ #define DVSGAMCMAX_ILK(pipe, i) _MMIO(_PIPE(pipe, _DVSAGAMCMAX_ILK, _DVSBGAMCMAX_ILK) + (i) * 4) /* 3 x u1.10 */ +/* ivb/hsw/bdw sprite */ #define _SPRA_CTL 0x70280 +#define _SPRB_CTL 0x71280 +#define SPRCTL(pipe) _MMIO_PIPE(pipe, _SPRA_CTL, _SPRB_CTL) #define SPRITE_ENABLE REG_BIT(31) #define SPRITE_PIPE_GAMMA_ENABLE REG_BIT(30) #define SPRITE_YUV_RANGE_CORRECTION_DISABLE REG_BIT(28) @@ -125,31 +141,67 @@ #define SPRITE_PLANE_GAMMA_DISABLE REG_BIT(13) #define SPRITE_TILED REG_BIT(10) #define SPRITE_DEST_KEY REG_BIT(2) -#define _SPRA_LINOFF 0x70284 + +#define _SPRA_LINOFF 0x70284 /* ivb */ +#define _SPRB_LINOFF 0x71284 /* ivb */ +#define SPRLINOFF(pipe) _MMIO_PIPE(pipe, _SPRA_LINOFF, _SPRB_LINOFF) + #define _SPRA_STRIDE 0x70288 +#define _SPRB_STRIDE 0x71288 +#define SPRSTRIDE(pipe) _MMIO_PIPE(pipe, _SPRA_STRIDE, _SPRB_STRIDE) + #define _SPRA_POS 0x7028c +#define _SPRB_POS 0x7128c +#define SPRPOS(pipe) _MMIO_PIPE(pipe, _SPRA_POS, _SPRB_POS) #define SPRITE_POS_Y_MASK REG_GENMASK(31, 16) #define SPRITE_POS_Y(y) REG_FIELD_PREP(SPRITE_POS_Y_MASK, (y)) #define SPRITE_POS_X_MASK REG_GENMASK(15, 0) #define SPRITE_POS_X(x) REG_FIELD_PREP(SPRITE_POS_X_MASK, (x)) + #define _SPRA_SIZE 0x70290 +#define _SPRB_SIZE 0x71290 +#define SPRSIZE(pipe) _MMIO_PIPE(pipe, _SPRA_SIZE, _SPRB_SIZE) #define SPRITE_HEIGHT_MASK REG_GENMASK(31, 16) #define SPRITE_HEIGHT(h) REG_FIELD_PREP(SPRITE_HEIGHT_MASK, (h)) #define SPRITE_WIDTH_MASK REG_GENMASK(15, 0) #define SPRITE_WIDTH(w) REG_FIELD_PREP(SPRITE_WIDTH_MASK, (w)) + #define _SPRA_KEYVAL 0x70294 +#define _SPRB_KEYVAL 0x71294 +#define SPRKEYVAL(pipe) _MMIO_PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL) + #define _SPRA_KEYMSK 0x70298 +#define _SPRB_KEYMSK 0x71298 +#define SPRKEYMSK(pipe) _MMIO_PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK) + #define _SPRA_SURF 0x7029c +#define _SPRB_SURF 0x7129c +#define SPRSURF(pipe) _MMIO_PIPE(pipe, _SPRA_SURF, _SPRB_SURF) #define SPRITE_ADDR_MASK REG_GENMASK(31, 12) + #define _SPRA_KEYMAX 0x702a0 -#define _SPRA_TILEOFF 0x702a4 +#define _SPRB_KEYMAX 0x712a0 +#define SPRKEYMAX(pipe) _MMIO_PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX) + +#define _SPRA_TILEOFF 0x702a4 /* ivb */ +#define _SPRB_TILEOFF 0x712a4 /* ivb */ +#define SPRTILEOFF(pipe) _MMIO_PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF) #define SPRITE_OFFSET_Y_MASK REG_GENMASK(31, 16) #define SPRITE_OFFSET_Y(y) REG_FIELD_PREP(SPRITE_OFFSET_Y_MASK, (y)) #define SPRITE_OFFSET_X_MASK REG_GENMASK(15, 0) #define SPRITE_OFFSET_X(x) REG_FIELD_PREP(SPRITE_OFFSET_X_MASK, (x)) -#define _SPRA_OFFSET 0x702a4 + +#define _SPRA_OFFSET 0x702a4 /* hsw/bdw */ +#define _SPRB_OFFSET 0x712a4 /* hsw/bdw */ +#define SPROFFSET(pipe) _MMIO_PIPE(pipe, _SPRA_OFFSET, _SPRB_OFFSET) + #define _SPRA_SURFLIVE 0x702ac -#define _SPRA_SCALE 0x70304 +#define _SPRB_SURFLIVE 0x712ac +#define SPRSURFLIVE(pipe) _MMIO_PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE) + +#define _SPRA_SCALE 0x70304 /* ivb */ +#define _SPRB_SCALE 0x71304 /* ivb */ +#define SPRSCALE(pipe) _MMIO_PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE) #define SPRITE_SCALE_ENABLE REG_BIT(31) #define SPRITE_FILTER_MASK REG_GENMASK(30, 29) #define SPRITE_FILTER_MEDIUM REG_FIELD_PREP(SPRITE_FILTER_MASK, 0) @@ -161,45 +213,28 @@ #define SPRITE_SRC_WIDTH(w) REG_FIELD_PREP(SPRITE_SRC_WIDTH_MASK, (w)) #define SPRITE_SRC_HEIGHT_MASK REG_GENMASK(10, 0) #define SPRITE_SRC_HEIGHT(h) REG_FIELD_PREP(SPRITE_SRC_HEIGHT_MASK, (h)) -#define _SPRA_GAMC 0x70400 -#define _SPRA_GAMC16 0x70440 -#define _SPRA_GAMC17 0x7044c -#define _SPRB_CTL 0x71280 -#define _SPRB_LINOFF 0x71284 -#define _SPRB_STRIDE 0x71288 -#define _SPRB_POS 0x7128c -#define _SPRB_SIZE 0x71290 -#define _SPRB_KEYVAL 0x71294 -#define _SPRB_KEYMSK 0x71298 -#define _SPRB_SURF 0x7129c -#define _SPRB_KEYMAX 0x712a0 -#define _SPRB_TILEOFF 0x712a4 -#define _SPRB_OFFSET 0x712a4 -#define _SPRB_SURFLIVE 0x712ac -#define _SPRB_SCALE 0x71304 +#define _SPRA_GAMC 0x70400 #define _SPRB_GAMC 0x71400 -#define _SPRB_GAMC16 0x71440 -#define _SPRB_GAMC17 0x7144c - -#define SPRCTL(pipe) _MMIO_PIPE(pipe, _SPRA_CTL, _SPRB_CTL) -#define SPRLINOFF(pipe) _MMIO_PIPE(pipe, _SPRA_LINOFF, _SPRB_LINOFF) -#define SPRSTRIDE(pipe) _MMIO_PIPE(pipe, _SPRA_STRIDE, _SPRB_STRIDE) -#define SPRPOS(pipe) _MMIO_PIPE(pipe, _SPRA_POS, _SPRB_POS) -#define SPRSIZE(pipe) _MMIO_PIPE(pipe, _SPRA_SIZE, _SPRB_SIZE) -#define SPRKEYVAL(pipe) _MMIO_PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL) -#define SPRKEYMSK(pipe) _MMIO_PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK) -#define SPRSURF(pipe) _MMIO_PIPE(pipe, _SPRA_SURF, _SPRB_SURF) -#define SPRKEYMAX(pipe) _MMIO_PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX) -#define SPRTILEOFF(pipe) _MMIO_PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF) -#define SPROFFSET(pipe) _MMIO_PIPE(pipe, _SPRA_OFFSET, _SPRB_OFFSET) -#define SPRSCALE(pipe) _MMIO_PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE) #define SPRGAMC(pipe, i) _MMIO(_PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC) + (i) * 4) /* 16 x u0.10 */ + +#define _SPRA_GAMC16 0x70440 +#define _SPRB_GAMC16 0x71440 #define SPRGAMC16(pipe, i) _MMIO(_PIPE(pipe, _SPRA_GAMC16, _SPRB_GAMC16) + (i) * 4) /* 3 x u1.10 */ + +#define _SPRA_GAMC17 0x7044c +#define _SPRB_GAMC17 0x7144c #define SPRGAMC17(pipe, i) _MMIO(_PIPE(pipe, _SPRA_GAMC17, _SPRB_GAMC17) + (i) * 4) /* 3 x u2.10 */ -#define SPRSURFLIVE(pipe) _MMIO_PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE) + +/* vlv/chv sprite */ +#define _VLV_SPR(pipe, plane_id, reg_a, reg_b) \ + _PIPE((pipe) * 2 + (plane_id) - PLANE_SPRITE0, (reg_a), (reg_b)) +#define _MMIO_VLV_SPR(pipe, plane_id, reg_a, reg_b) \ + _MMIO(_VLV_SPR((pipe), (plane_id), (reg_a), (reg_b))) #define _SPACNTR (VLV_DISPLAY_BASE + 0x72180) +#define _SPBCNTR (VLV_DISPLAY_BASE + 0x72280) +#define SPCNTR(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACNTR, _SPBCNTR) #define SP_ENABLE REG_BIT(31) #define SP_PIPE_GAMMA_ENABLE REG_BIT(30) #define SP_FORMAT_MASK REG_GENMASK(29, 26) @@ -225,80 +260,85 @@ #define SP_ROTATE_180 REG_BIT(15) #define SP_TILED REG_BIT(10) #define SP_MIRROR REG_BIT(8) /* CHV pipe B */ + #define _SPALINOFF (VLV_DISPLAY_BASE + 0x72184) +#define _SPBLINOFF (VLV_DISPLAY_BASE + 0x72284) +#define SPLINOFF(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPALINOFF, _SPBLINOFF) + #define _SPASTRIDE (VLV_DISPLAY_BASE + 0x72188) +#define _SPBSTRIDE (VLV_DISPLAY_BASE + 0x72288) +#define SPSTRIDE(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPASTRIDE, _SPBSTRIDE) + #define _SPAPOS (VLV_DISPLAY_BASE + 0x7218c) +#define _SPBPOS (VLV_DISPLAY_BASE + 0x7228c) +#define SPPOS(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAPOS, _SPBPOS) #define SP_POS_Y_MASK REG_GENMASK(31, 16) #define SP_POS_Y(y) REG_FIELD_PREP(SP_POS_Y_MASK, (y)) #define SP_POS_X_MASK REG_GENMASK(15, 0) #define SP_POS_X(x) REG_FIELD_PREP(SP_POS_X_MASK, (x)) + #define _SPASIZE (VLV_DISPLAY_BASE + 0x72190) +#define _SPBSIZE (VLV_DISPLAY_BASE + 0x72290) +#define SPSIZE(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPASIZE, _SPBSIZE) #define SP_HEIGHT_MASK REG_GENMASK(31, 16) #define SP_HEIGHT(h) REG_FIELD_PREP(SP_HEIGHT_MASK, (h)) #define SP_WIDTH_MASK REG_GENMASK(15, 0) #define SP_WIDTH(w) REG_FIELD_PREP(SP_WIDTH_MASK, (w)) + #define _SPAKEYMINVAL (VLV_DISPLAY_BASE + 0x72194) +#define _SPBKEYMINVAL (VLV_DISPLAY_BASE + 0x72294) +#define SPKEYMINVAL(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAKEYMINVAL, _SPBKEYMINVAL) + #define _SPAKEYMSK (VLV_DISPLAY_BASE + 0x72198) +#define _SPBKEYMSK (VLV_DISPLAY_BASE + 0x72298) +#define SPKEYMSK(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAKEYMSK, _SPBKEYMSK) + #define _SPASURF (VLV_DISPLAY_BASE + 0x7219c) +#define _SPBSURF (VLV_DISPLAY_BASE + 0x7229c) +#define SPSURF(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPASURF, _SPBSURF) #define SP_ADDR_MASK REG_GENMASK(31, 12) + #define _SPAKEYMAXVAL (VLV_DISPLAY_BASE + 0x721a0) +#define _SPBKEYMAXVAL (VLV_DISPLAY_BASE + 0x722a0) +#define SPKEYMAXVAL(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAKEYMAXVAL, _SPBKEYMAXVAL) + #define _SPATILEOFF (VLV_DISPLAY_BASE + 0x721a4) +#define _SPBTILEOFF (VLV_DISPLAY_BASE + 0x722a4) +#define SPTILEOFF(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPATILEOFF, _SPBTILEOFF) #define SP_OFFSET_Y_MASK REG_GENMASK(31, 16) #define SP_OFFSET_Y(y) REG_FIELD_PREP(SP_OFFSET_Y_MASK, (y)) #define SP_OFFSET_X_MASK REG_GENMASK(15, 0) #define SP_OFFSET_X(x) REG_FIELD_PREP(SP_OFFSET_X_MASK, (x)) + #define _SPACONSTALPHA (VLV_DISPLAY_BASE + 0x721a8) +#define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8) +#define SPCONSTALPHA(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACONSTALPHA, _SPBCONSTALPHA) #define SP_CONST_ALPHA_ENABLE REG_BIT(31) #define SP_CONST_ALPHA_MASK REG_GENMASK(7, 0) #define SP_CONST_ALPHA(alpha) REG_FIELD_PREP(SP_CONST_ALPHA_MASK, (alpha)) + #define _SPASURFLIVE (VLV_DISPLAY_BASE + 0x721ac) +#define _SPBSURFLIVE (VLV_DISPLAY_BASE + 0x722ac) +#define SPSURFLIVE(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPASURFLIVE, _SPBSURFLIVE) + #define _SPACLRC0 (VLV_DISPLAY_BASE + 0x721d0) +#define _SPBCLRC0 (VLV_DISPLAY_BASE + 0x722d0) +#define SPCLRC0(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACLRC0, _SPBCLRC0) #define SP_CONTRAST_MASK REG_GENMASK(26, 18) #define SP_CONTRAST(x) REG_FIELD_PREP(SP_CONTRAST_MASK, (x)) /* u3.6 */ #define SP_BRIGHTNESS_MASK REG_GENMASK(7, 0) #define SP_BRIGHTNESS(x) REG_FIELD_PREP(SP_BRIGHTNESS_MASK, (x)) /* s8 */ + #define _SPACLRC1 (VLV_DISPLAY_BASE + 0x721d4) +#define _SPBCLRC1 (VLV_DISPLAY_BASE + 0x722d4) +#define SPCLRC1(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACLRC1, _SPBCLRC1) #define SP_SH_SIN_MASK REG_GENMASK(26, 16) #define SP_SH_SIN(x) REG_FIELD_PREP(SP_SH_SIN_MASK, (x)) /* s4.7 */ #define SP_SH_COS_MASK REG_GENMASK(9, 0) #define SP_SH_COS(x) REG_FIELD_PREP(SP_SH_COS_MASK, (x)) /* u3.7 */ -#define _SPAGAMC (VLV_DISPLAY_BASE + 0x721e0) -#define _SPBCNTR (VLV_DISPLAY_BASE + 0x72280) -#define _SPBLINOFF (VLV_DISPLAY_BASE + 0x72284) -#define _SPBSTRIDE (VLV_DISPLAY_BASE + 0x72288) -#define _SPBPOS (VLV_DISPLAY_BASE + 0x7228c) -#define _SPBSIZE (VLV_DISPLAY_BASE + 0x72290) -#define _SPBKEYMINVAL (VLV_DISPLAY_BASE + 0x72294) -#define _SPBKEYMSK (VLV_DISPLAY_BASE + 0x72298) -#define _SPBSURF (VLV_DISPLAY_BASE + 0x7229c) -#define _SPBKEYMAXVAL (VLV_DISPLAY_BASE + 0x722a0) -#define _SPBTILEOFF (VLV_DISPLAY_BASE + 0x722a4) -#define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8) -#define _SPBSURFLIVE (VLV_DISPLAY_BASE + 0x722ac) -#define _SPBCLRC0 (VLV_DISPLAY_BASE + 0x722d0) -#define _SPBCLRC1 (VLV_DISPLAY_BASE + 0x722d4) +#define _SPAGAMC (VLV_DISPLAY_BASE + 0x721e0) #define _SPBGAMC (VLV_DISPLAY_BASE + 0x722e0) - -#define _VLV_SPR(pipe, plane_id, reg_a, reg_b) \ - _PIPE((pipe) * 2 + (plane_id) - PLANE_SPRITE0, (reg_a), (reg_b)) -#define _MMIO_VLV_SPR(pipe, plane_id, reg_a, reg_b) \ - _MMIO(_VLV_SPR((pipe), (plane_id), (reg_a), (reg_b))) - -#define SPCNTR(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACNTR, _SPBCNTR) -#define SPLINOFF(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPALINOFF, _SPBLINOFF) -#define SPSTRIDE(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPASTRIDE, _SPBSTRIDE) -#define SPPOS(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAPOS, _SPBPOS) -#define SPSIZE(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPASIZE, _SPBSIZE) -#define SPKEYMINVAL(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAKEYMINVAL, _SPBKEYMINVAL) -#define SPKEYMSK(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAKEYMSK, _SPBKEYMSK) -#define SPSURF(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPASURF, _SPBSURF) -#define SPKEYMAXVAL(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAKEYMAXVAL, _SPBKEYMAXVAL) -#define SPTILEOFF(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPATILEOFF, _SPBTILEOFF) -#define SPCONSTALPHA(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACONSTALPHA, _SPBCONSTALPHA) -#define SPSURFLIVE(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPASURFLIVE, _SPBSURFLIVE) -#define SPCLRC0(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACLRC0, _SPBCLRC0) -#define SPCLRC1(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACLRC1, _SPBCLRC1) #define SPGAMC(pipe, plane_id, i) _MMIO(_VLV_SPR((pipe), (plane_id), _SPAGAMC, _SPBGAMC) + (5 - (i)) * 4) /* 6 x u0.10 */ /* diff --git a/drivers/gpu/drm/i915/display/intel_sprite_uapi.c b/drivers/gpu/drm/i915/display/intel_sprite_uapi.c index a76b48ebc2d3..4853c4806004 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite_uapi.c +++ b/drivers/gpu/drm/i915/display/intel_sprite_uapi.c @@ -74,7 +74,7 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, * pipe simultaneously. */ if (DISPLAY_VER(dev_priv) >= 9 && - to_intel_plane(plane)->id >= PLANE_SPRITE1 && + to_intel_plane(plane)->id >= PLANE_3 && set->flags & I915_SET_COLORKEY_DESTINATION) return -EINVAL; diff --git a/drivers/gpu/drm/i915/display/intel_tdf.h b/drivers/gpu/drm/i915/display/intel_tdf.h new file mode 100644 index 000000000000..353cde21f6c2 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_tdf.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __INTEL_TDF_H__ +#define __INTEL_TDF_H__ + +/* + * TDF (Transient-Data-Flush) is needed for Xe2+ where special L3:XD caching can + * be enabled through various PAT index modes. Idea is to use this caching mode + * when for example rendering onto the display surface, with the promise that + * KMD will ensure transient cache entries are always flushed by the time we do + * the display flip, since display engine is never coherent with CPU/GPU caches. + */ + +struct drm_i915_private; + +#ifdef I915 +static inline void intel_td_flush(struct drm_i915_private *i915) {} +#else +void intel_td_flush(struct drm_i915_private *i915); +#endif + +#endif diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index baf7354cb6e2..e5db54b1c632 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -5,6 +5,7 @@ #include "i915_drv.h" #include "i915_reg.h" +#include "intel_color.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_types.h" @@ -89,9 +90,7 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc) htotal = mode->crtc_htotal; hsync_start = mode->crtc_hsync_start; - vbl_start = mode->crtc_vblank_start; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vbl_start = DIV_ROUND_UP(vbl_start, 2); + vbl_start = intel_mode_vblank_start(mode); /* Convert to pixel count */ vbl_start *= htotal; @@ -104,7 +103,8 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc) * we get a low value that's stable across two reads of the high * register. */ - frame = intel_de_read64_2x32(dev_priv, PIPEFRAMEPIXEL(pipe), PIPEFRAME(pipe)); + frame = intel_de_read64_2x32(dev_priv, PIPEFRAMEPIXEL(dev_priv, pipe), + PIPEFRAME(dev_priv, pipe)); pixel = frame & PIPE_PIXEL_MASK; frame = (frame >> PIPE_FRAME_LOW_SHIFT) & 0xffffff; @@ -126,14 +126,13 @@ u32 g4x_get_vblank_counter(struct drm_crtc *crtc) if (!vblank->max_vblank_count) return 0; - return intel_de_read(dev_priv, PIPE_FRMCOUNT_G4X(pipe)); + return intel_de_read(dev_priv, PIPE_FRMCOUNT_G4X(dev_priv, pipe)); } static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); const struct drm_display_mode *mode = &vblank->hwmode; u32 htotal = mode->crtc_htotal; u32 clock = mode->crtc_clock; @@ -178,8 +177,7 @@ static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) */ static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) { - struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); const struct drm_display_mode *mode = &vblank->hwmode; u32 vblank_start = mode->crtc_vblank_start; u32 vtotal = mode->crtc_vtotal; @@ -192,6 +190,44 @@ static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) return scanline; } +static int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + /* + * The scanline counter increments at the leading edge of hsync. + * + * On most platforms it starts counting from vtotal-1 on the + * first active line. That means the scanline counter value is + * always one less than what we would expect. Ie. just after + * start of vblank, which also occurs at start of hsync (on the + * last active line), the scanline counter will read vblank_start-1. + * + * On gen2 the scanline counter starts counting from 1 instead + * of vtotal-1, so we have to subtract one. + * + * On HSW+ the behaviour of the scanline counter depends on the output + * type. For DP ports it behaves like most other platforms, but on HDMI + * there's an extra 1 line difference. So we need to add two instead of + * one to the value. + * + * On VLV/CHV DSI the scanline counter would appear to increment + * approx. 1/3 of a scanline before start of vblank. Unfortunately + * that means we can't tell whether we're in vblank or not while + * we're on that particular line. We must still set scanline_offset + * to 1 so that the vblank timestamps come out correct when we query + * the scanline counter from within the vblank interrupt handler. + * However if queried just before the start of vblank we'll get an + * answer that's slightly in the future. + */ + if (DISPLAY_VER(i915) == 2) + return -1; + else if (HAS_DDI(i915) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + return 2; + else + return 1; +} + /* * intel_de_read_fw(), only for fast reads of display block, no need for * forcewake etc. @@ -200,25 +236,20 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - const struct drm_display_mode *mode; - struct drm_vblank_crtc *vblank; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); + const struct drm_display_mode *mode = &vblank->hwmode; enum pipe pipe = crtc->pipe; int position, vtotal; if (!crtc->active) return 0; - vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - mode = &vblank->hwmode; - if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) return __intel_get_crtc_scanline_from_timestamp(crtc); - vtotal = mode->crtc_vtotal; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vtotal /= 2; + vtotal = intel_mode_vtotal(mode); - position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; + position = intel_de_read_fw(dev_priv, PIPEDSL(dev_priv, pipe)) & PIPEDSL_LINE_MASK; /* * On HSW, the DSL reg (0x70000) appears to return 0 if we @@ -237,7 +268,8 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) for (i = 0; i < 100; i++) { udelay(1); - temp = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; + temp = intel_de_read_fw(dev_priv, + PIPEDSL(dev_priv, pipe)) & PIPEDSL_LINE_MASK; if (temp != position) { position = temp; break; @@ -249,19 +281,14 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) * See update_scanline_offset() for the details on the * scanline_offset adjustment. */ - return (position + crtc->scanline_offset) % vtotal; + return (position + vtotal + crtc->scanline_offset) % vtotal; } int intel_crtc_scanline_to_hw(struct intel_crtc *crtc, int scanline) { - const struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + const struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); const struct drm_display_mode *mode = &vblank->hwmode; - int vtotal; - - vtotal = mode->crtc_vtotal; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vtotal /= 2; + int vtotal = intel_mode_vtotal(mode); return (scanline + vtotal - crtc->scanline_offset) % vtotal; } @@ -318,15 +345,9 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, htotal = mode->crtc_htotal; hsync_start = mode->crtc_hsync_start; - vtotal = mode->crtc_vtotal; - vbl_start = mode->crtc_vblank_start; - vbl_end = mode->crtc_vblank_end; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - vbl_start = DIV_ROUND_UP(vbl_start, 2); - vbl_end /= 2; - vtotal /= 2; - } + vtotal = intel_mode_vtotal(mode); + vbl_start = intel_mode_vblank_start(mode); + vbl_end = intel_mode_vblank_end(mode); /* * Enter vblank critical section, as we will do multiple @@ -366,7 +387,7 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, * We can split this into vertical and horizontal * scanout position. */ - position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; + position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(dev_priv, pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; /* convert to pixel counts */ vbl_start *= htotal; @@ -455,7 +476,7 @@ int intel_get_crtc_scanline(struct intel_crtc *crtc) static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, enum pipe pipe) { - i915_reg_t reg = PIPEDSL(pipe); + i915_reg_t reg = PIPEDSL(dev_priv, pipe); u32 line1, line2; line1 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; @@ -487,53 +508,6 @@ void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) wait_for_pipe_scanline_moving(crtc, true); } -static int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - - /* - * The scanline counter increments at the leading edge of hsync. - * - * On most platforms it starts counting from vtotal-1 on the - * first active line. That means the scanline counter value is - * always one less than what we would expect. Ie. just after - * start of vblank, which also occurs at start of hsync (on the - * last active line), the scanline counter will read vblank_start-1. - * - * On gen2 the scanline counter starts counting from 1 instead - * of vtotal-1, so we have to subtract one (or rather add vtotal-1 - * to keep the value positive), instead of adding one. - * - * On HSW+ the behaviour of the scanline counter depends on the output - * type. For DP ports it behaves like most other platforms, but on HDMI - * there's an extra 1 line difference. So we need to add two instead of - * one to the value. - * - * On VLV/CHV DSI the scanline counter would appear to increment - * approx. 1/3 of a scanline before start of vblank. Unfortunately - * that means we can't tell whether we're in vblank or not while - * we're on that particular line. We must still set scanline_offset - * to 1 so that the vblank timestamps come out correct when we query - * the scanline counter from within the vblank interrupt handler. - * However if queried just before the start of vblank we'll get an - * answer that's slightly in the future. - */ - if (DISPLAY_VER(i915) == 2) { - int vtotal; - - vtotal = adjusted_mode->crtc_vtotal; - if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) - vtotal /= 2; - - return vtotal - 1; - } else if (HAS_DDI(i915) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { - return 2; - } else { - return 1; - } -} - void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, bool vrr_enable) { @@ -583,7 +557,7 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, spin_unlock_irqrestore(&i915->drm.vblank_time_lock, irqflags); } -static int intel_mode_vblank_start(const struct drm_display_mode *mode) +int intel_mode_vblank_start(const struct drm_display_mode *mode) { int vblank_start = mode->crtc_vblank_start; @@ -593,6 +567,26 @@ static int intel_mode_vblank_start(const struct drm_display_mode *mode) return vblank_start; } +int intel_mode_vblank_end(const struct drm_display_mode *mode) +{ + int vblank_end = mode->crtc_vblank_end; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vblank_end /= 2; + + return vblank_end; +} + +int intel_mode_vtotal(const struct drm_display_mode *mode) +{ + int vtotal = mode->crtc_vtotal; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vtotal /= 2; + + return vtotal; +} + void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state, struct intel_vblank_evade_ctx *evade) @@ -646,7 +640,8 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, * DSB execution waits for the transcoder's undelayed vblank, * hence we must kick off the commit before that. */ - if (new_crtc_state->dsb || new_crtc_state->update_m_n || new_crtc_state->update_lrr) + if (intel_color_uses_dsb(new_crtc_state) || + new_crtc_state->update_m_n || new_crtc_state->update_lrr) evade->min -= adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay; } diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h index ec6c3da3eeac..b51ae2c1039e 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.h +++ b/drivers/gpu/drm/i915/display/intel_vblank.h @@ -10,6 +10,7 @@ #include <linux/types.h> struct drm_crtc; +struct drm_display_mode; struct intel_crtc; struct intel_crtc_state; @@ -19,6 +20,10 @@ struct intel_vblank_evade_ctx { bool need_vlv_dsi_wa; }; +int intel_mode_vblank_start(const struct drm_display_mode *mode); +int intel_mode_vblank_end(const struct drm_display_mode *mode); +int intel_mode_vtotal(const struct drm_display_mode *mode); + void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state, struct intel_vblank_evade_ctx *evade); diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index 228702c0e492..1af8407e2081 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -39,6 +39,50 @@ #include "intel_bios.h" +/* EDID derived structures */ +struct bdb_edid_pnp_id { + u16 mfg_name; + u16 product_code; + u32 serial; + u8 mfg_week; + u8 mfg_year; +} __packed; + +struct bdb_edid_product_name { + char name[13]; +} __packed; + +struct bdb_edid_dtd { + u16 clock; /**< In 10khz */ + u8 hactive_lo; + u8 hblank_lo; + u8 hblank_hi:4; + u8 hactive_hi:4; + u8 vactive_lo; + u8 vblank_lo; + u8 vblank_hi:4; + u8 vactive_hi:4; + u8 hsync_off_lo; + u8 hsync_pulse_width_lo; + u8 vsync_pulse_width_lo:4; + u8 vsync_off_lo:4; + u8 vsync_pulse_width_hi:2; + u8 vsync_off_hi:2; + u8 hsync_pulse_width_hi:2; + u8 hsync_off_hi:2; + u8 himage_lo; + u8 vimage_lo; + u8 vimage_hi:4; + u8 himage_hi:4; + u8 h_border; + u8 v_border; + u8 rsvd1:3; + u8 digital:2; + u8 vsync_positive:1; + u8 hsync_positive:1; + u8 non_interlaced:1; +} __packed; + /** * struct vbt_header - VBT Header structure * @signature: VBT signature, always starts with "$VBT" @@ -97,40 +141,56 @@ struct bdb_header { enum bdb_block_id { BDB_GENERAL_FEATURES = 1, BDB_GENERAL_DEFINITIONS = 2, - BDB_OLD_TOGGLE_LIST = 3, + BDB_DISPLAY_TOGGLE = 3, BDB_MODE_SUPPORT_LIST = 4, BDB_GENERIC_MODE_TABLE = 5, - BDB_EXT_MMIO_REGS = 6, - BDB_SWF_IO = 7, - BDB_SWF_MMIO = 8, - BDB_PSR = 9, + BDB_EXT_MMIO_REGS = 6, /* VBIOS only */ + BDB_SWF_IO = 7, /* VBIOS only */ + BDB_SWF_MMIO = 8, /* VBIOS only */ + BDB_DOT_CLOCK_OVERRIDE_ALM = 9, + BDB_PSR = 9, /* 165+ */ BDB_MODE_REMOVAL_TABLE = 10, BDB_CHILD_DEVICE_TABLE = 11, BDB_DRIVER_FEATURES = 12, BDB_DRIVER_PERSISTENCE = 13, - BDB_EXT_TABLE_PTRS = 14, + BDB_EXT_TABLE_PTRS = 14, /* VBIOS only */ BDB_DOT_CLOCK_OVERRIDE = 15, - BDB_DISPLAY_SELECT = 16, + BDB_DISPLAY_SELECT_OLD = 16, + BDB_SV_TEST_FUNCTIONS = 17, BDB_DRIVER_ROTATION = 18, - BDB_DISPLAY_REMOVE = 19, + BDB_DISPLAY_REMOVE_OLD = 19, BDB_OEM_CUSTOM = 20, BDB_EFP_LIST = 21, /* workarounds for VGA hsync/vsync */ BDB_SDVO_LVDS_OPTIONS = 22, - BDB_SDVO_PANEL_DTDS = 23, - BDB_SDVO_LVDS_PNP_IDS = 24, - BDB_SDVO_LVDS_POWER_SEQ = 25, + BDB_SDVO_LVDS_DTD = 23, + BDB_SDVO_LVDS_PNP_ID = 24, + BDB_SDVO_LVDS_PPS = 25, BDB_TV_OPTIONS = 26, BDB_EDP = 27, - BDB_LVDS_OPTIONS = 40, - BDB_LVDS_LFP_DATA_PTRS = 41, - BDB_LVDS_LFP_DATA = 42, - BDB_LVDS_BACKLIGHT = 43, + BDB_EFP_DTD = 28, /* 161+ */ + BDB_DISPLAY_SELECT_IVB = 29, /* 164+ */ + BDB_DISPLAY_REMOVE_IVB = 30, /* 164+ */ + BDB_DISPLAY_SELECT_HSW = 31, /* 166+ */ + BDB_DISPLAY_REMOVE_HSW = 32, /* 166+ */ + BDB_LFP_OPTIONS = 40, + BDB_LFP_DATA_PTRS = 41, + BDB_LFP_DATA = 42, + BDB_LFP_BACKLIGHT = 43, BDB_LFP_POWER = 44, - BDB_MIPI_CONFIG = 52, - BDB_MIPI_SEQUENCE = 53, - BDB_COMPRESSION_PARAMETERS = 56, - BDB_GENERIC_DTD = 58, - BDB_SKIP = 254, /* VBIOS private block, ignore */ + BDB_EDP_BFI = 45, /* 160+ */ + BDB_CHROMATICITY = 46, /* 169+ */ + BDB_MIPI = 50, /* 170-172 */ + BDB_FIXED_SET_MODE = 51, /* 172+ */ + BDB_MIPI_CONFIG = 52, /* 175+ */ + BDB_MIPI_SEQUENCE = 53, /* 177+ */ + BDB_RGB_PALETTE = 54, /* 180+ */ + BDB_COMPRESSION_PARAMETERS_OLD = 55, /* 198-212 */ + BDB_COMPRESSION_PARAMETERS = 56, /* 213+ */ + BDB_VSWING_PREEMPH = 57, /* 218+ */ + BDB_GENERIC_DTD = 58, /* 229+ */ + BDB_INT15_HOOK = 252, /* VBIOS only */ + BDB_PRD_TABLE = 253, + BDB_SKIP = 254, /* VBIOS only */ }; /* @@ -198,10 +258,11 @@ struct bdb_general_features { /* Device handle */ #define DEVICE_HANDLE_CRT 0x0001 +#define DEVICE_HANDLE_TV 0x0002 /* ???-214 */ #define DEVICE_HANDLE_EFP1 0x0004 #define DEVICE_HANDLE_EFP2 0x0040 #define DEVICE_HANDLE_EFP3 0x0020 -#define DEVICE_HANDLE_EFP4 0x0010 /* 194+ */ +#define DEVICE_HANDLE_EFP4 0x0010 #define DEVICE_HANDLE_EFP5 0x0002 /* 215+ */ #define DEVICE_HANDLE_EFP6 0x0001 /* 217+ */ #define DEVICE_HANDLE_EFP7 0x0100 /* 217+ */ @@ -517,6 +578,114 @@ struct bdb_general_definitions { } __packed; /* + * Block 3 - Display Toggle Option Block + */ + +struct bdb_display_toggle { + u8 feature_bits; + u16 num_entries; /* ALM only */ + u16 list[]; /* ALM only */ +} __packed; + +/* + * Block 4 - Mode Support List + */ + +struct bdb_mode_support_list { + u8 intel_mode_number[0]; + u16 mode_list_length; +} __packed; + +/* + * Block 5 - Generic Mode Table + */ + +struct generic_mode_table { + u16 x_res; + u16 y_res; + u8 color_depths; + u8 refresh_rate[3]; + u8 reserved; + u8 text_cols; + u8 text_rows; + u8 font_height; + u16 page_size; + u8 misc; +} __packed; + +struct generic_mode_timings { + u32 dotclock_khz; + u16 hdisplay; + u16 htotal; + u16 hblank_start; + u16 hblank_end; + u16 hsync_start; + u16 hsync_end; + u16 vdisplay; + u16 vtotal; + u16 vblank_start; + u16 vblank_end; + u16 vsync_start; + u16 vsync_end; +} __packed; + +struct generic_mode_timings_alm { + struct generic_mode_timings timings; + u8 wm_8bpp; + u8 burst_8bpp; + u8 wm_16bpp; + u8 burst_16bpp; + u8 wm_32bpp; + u8 burst_32bpp; +} __packed; + +struct bdb_generic_mode_table_alm { + struct generic_mode_table table; + struct generic_mode_timings_alm timings[3]; +} __packed; + +struct bdb_generic_mode_table_mgm { + u16 mode_flag; + struct generic_mode_table table; + struct generic_mode_timings timings[3]; +} __packed; + +/* + * Block 6 - Extended MMIO Register Table, VBIOS only + * Block 7 - IO Software Flag Table, VBIOS only + * Block 8 - MMIO SWF Register Table, VBIOS only + */ +struct bdb_reg_table { + u16 table_id; + u8 data_access_size; + /* + * offset,value tuples: + * data_access_size==0xce -> u8,u8 + * data_access_size==0x02 -> u32,u32 + */ + /* u16 table_end_marker; */ +} __packed; + +/* + * Block 9 - Undocumented table (ALM only) + */ + +struct dot_clock_override_entry_gen2 { + u32 dotclock; + u8 n; + u8 m1; + u8 m2; + u8 p1:5; + u8 p1_div_by_2:1; + u8 reserved:1; + u8 p2_div_by_4:1; +} __packed; + +struct bdb_dot_clock_override_alm { + struct dot_clock_override_entry_gen2 t[0]; +} __packed; + +/* * Block 9 - SRD Feature Block */ @@ -544,6 +713,29 @@ struct bdb_psr { } __packed; /* + * Block 10 - Mode Removal Table + */ + +struct mode_removal_table { + u16 x_res; + u16 y_res; + u8 bpp; + u16 refresh_rate; + u8 removal_flags; + u16 panel_flags; +} __packed; + +struct bdb_mode_removal { + u8 row_size; /* 8 or 10 bytes */ + /* + * VBT spec says this is always 20 entries, + * but ALM seems to have only 15 entries. + */ + struct mode_removal_table modes[]; + /* u16 terminator; 0x0000 */ +} __packed; + +/* * Block 12 - Driver Features Data Block */ @@ -622,6 +814,139 @@ struct bdb_driver_features { } __packed; /* + * Block 13 - Driver Persistent Algorithm + */ + +struct bdb_driver_persistence { + u16 hotkey_persistent_algorithm:1; + u16 lid_switch_persistent_algorithm:1; + u16 power_management_persistent_algorithm:1; + u16 hotkey_persistent_on_mds_twin:1; + u16 hotkey_persistent_on_refresh_rate:1; + u16 hotkey_persistent_on_restore_pipe:1; + u16 hotkey_persistent_on_mode:1; + u16 edid_persistent_on_mode:1; + u16 dvo_hotplug_persistent_on_mode:1; + u16 docking_persistent_algorithm:1; + u16 rsvd:6; + u8 persistent_max_config; +} __packed; + +/* + * Block 15 - Dot Clock Override Table + */ + +struct dot_clock_override_entry_gen3 { + u32 dotclock; + u8 n; + u8 m1; + u8 m2; + u8 p1; + u8 p2; +} __packed; + +struct bdb_dot_clock_override { + u8 row_size; /* 8 == gen2, 9 == gen3+ */ + u8 num_rows; + struct dot_clock_override_entry_gen3 table[]; /* or _gen2 */ +} __packed; + +/* + * Block 16 - Toggle List Block (pre-HSW) + */ + +struct toggle_list_entry_old { + u8 display_select_pipe_a; + u8 display_select_pipe_b; + u8 caps; +} __packed; + +struct toggle_list_table_old { + u16 num_entries; + u8 entry_size; + struct toggle_list_entry_old list[]; +} __packed; + +struct bdb_display_select_old { + /* each table has variable size! */ + struct toggle_list_table_old tables[4]; +} __packed; + +/* + * Block 17 - SV Test Functions + */ + +struct bdb_sv_test_functions { + u8 sv_bits[8]; +} __packed; + +/* + * Block 18 - Driver Rotation + */ + +struct bdb_driver_rotation { + u8 rotation_enable; + u8 rotation_flags_1; + u16 rotation_flags_2; + u32 rotation_flags_3; + u32 rotation_flags_4; +} __packed; + +/* + * Block 19 - Display Configuration Removal Table (pre-IVB) + */ + +struct display_remove_entry_old { + u8 display_select_pipe_a; + u8 display_select_pipe_b; +} __packed; + +struct bdb_display_remove_old { + u8 num_entries; + u8 entry_size; + struct display_remove_entry_old table[]; +} __packed; + +/* + * Block 20 - OEM Customizable Modes + */ + +struct oem_mode { + u8 enable_in_vbios:1; + u8 enable_in_os:1; + u8 enable_in_gop:1; /* 207+ */ + u8 reserved:5; + u8 display_flags; /* ???-216 */ + u16 x_res; + u16 y_res; + u8 color_depth; + u8 refresh_rate; + struct bdb_edid_dtd dtd; + u16 display_flags_2; /* 217+ */ +} __packed; + +struct bdb_oem_custom { + u8 num_entries; + u8 entry_size; + struct oem_mode modes[]; +} __packed; + +/* + * Block 21 - EFP List + */ + +struct efp_entry { + u16 mfg_name; + u16 product_code; +} __packed; + +struct bdb_efp_list { + u8 num_entries; + u8 entry_size; + struct efp_entry efp[]; +} __packed; + +/* * Block 22 - SDVO LVDS General Options */ @@ -642,42 +967,47 @@ struct bdb_sdvo_lvds_options { } __packed; /* - * Block 23 - SDVO LVDS Panel DTDs + * Block 23 - SDVO LVDS DTD */ -struct lvds_dvo_timing { - u16 clock; /**< In 10khz */ - u8 hactive_lo; - u8 hblank_lo; - u8 hblank_hi:4; - u8 hactive_hi:4; - u8 vactive_lo; - u8 vblank_lo; - u8 vblank_hi:4; - u8 vactive_hi:4; - u8 hsync_off_lo; - u8 hsync_pulse_width_lo; - u8 vsync_pulse_width_lo:4; - u8 vsync_off_lo:4; - u8 vsync_pulse_width_hi:2; - u8 vsync_off_hi:2; - u8 hsync_pulse_width_hi:2; - u8 hsync_off_hi:2; - u8 himage_lo; - u8 vimage_lo; - u8 vimage_hi:4; - u8 himage_hi:4; - u8 h_border; - u8 v_border; - u8 rsvd1:3; - u8 digital:2; - u8 vsync_positive:1; - u8 hsync_positive:1; - u8 non_interlaced:1; +struct bdb_sdvo_lvds_dtd { + struct bdb_edid_dtd dtd[4]; } __packed; -struct bdb_sdvo_panel_dtds { - struct lvds_dvo_timing dtds[4]; +/* + * Block 24 - SDVO LVDS PnP ID + */ + +struct bdb_sdvo_lvds_pnp_id { + struct bdb_edid_pnp_id pnp_id[4]; +} __packed; + +/* + * Block 25 - SDVO LVDS PPS + */ + +struct sdvo_lvds_pps { + u16 t0; /* power on */ + u16 t1; /* backlight on */ + u16 t2; /* backlight off */ + u16 t3; /* power off */ + u16 t4; /* power cycle */ +} __packed; + +struct bdb_sdvo_lvds_pps { + struct sdvo_lvds_pps pps[4]; +} __packed; + +/* + * Block 26 - TV Options Block + */ + +struct bdb_tv_options { + u16 underscan_overscan_hdtv_component:2; + u16 rsvd1:10; + u16 underscan_overscan_hdtv_dvi:2; + u16 add_modes_to_avoid_overscan_issue:1; + u16 d_connector_support:1; } __packed; /* @@ -749,13 +1079,88 @@ struct bdb_edp { struct edp_apical_params apical_params[16]; /* 203+ */ u16 edp_fast_link_training_rate[16]; /* 224+ */ u16 edp_max_port_link_rate[16]; /* 244+ */ + u16 edp_dsc_disable; /* 251+ */ +} __packed; + +/* + * Block 28 - EFP DTD Block + */ + +struct bdb_efp_dtd { + struct bdb_edid_dtd dtd[3]; +} __packed; + +/* + * Block 29 - Toggle List Block (IVB) + */ + +struct toggle_list_entry_ivb { + u8 display_select; +} __packed; + +struct toggle_list_table_ivb { + u16 num_entries; + u8 entry_size; + struct toggle_list_entry_ivb list[]; +} __packed; + +struct bdb_display_select_ivb { + /* each table has variable size! */ + struct toggle_list_table_ivb tables[4]; +} __packed; + +/* + * Block 30 - Display Configuration Removal Table (IVB) + */ + +struct display_remove_entry_ivb { + u8 display_select; +} __packed; + +struct bdb_display_remove_ivb { + u8 num_entries; + u8 entry_size; + struct display_remove_entry_ivb table[]; +} __packed; + +/* + * Block 31 - Toggle List Block (HSW+) + */ + +struct toggle_list_entry_hsw { + u16 display_select; +} __packed; + +struct toggle_list_table_hsw { + u16 num_entries; + u8 entry_size; + struct toggle_list_entry_hsw list[]; +} __packed; + +struct bdb_display_select_hsw { + /* each table has variable size! */ + struct toggle_list_table_hsw tables[4]; +} __packed; + +/* + * Block 32 - Display Configuration Removal Table (HSW+) + */ + +struct display_remove_entry_hsw { + u16 display_select; +} __packed; + +struct bdb_display_remove_hsw { + u8 num_entries; + u8 entry_size; + struct display_remove_entry_hsw table[]; } __packed; /* * Block 40 - LFP Data Block */ -struct bdb_lvds_options { +struct bdb_lfp_options { u8 panel_type; u8 panel_type2; /* 212+ */ /* LVDS capabilities, stored in a dword */ @@ -788,22 +1193,22 @@ struct bdb_lvds_options { /* * Block 41 - LFP Data Table Pointers */ -struct lvds_lfp_data_ptr_table { +struct lfp_data_ptr_table { u16 offset; /* offsets are from start of bdb */ u8 table_size; } __packed; /* LFP pointer table contains entries to the struct below */ -struct lvds_lfp_data_ptr { - struct lvds_lfp_data_ptr_table fp_timing; - struct lvds_lfp_data_ptr_table dvo_timing; - struct lvds_lfp_data_ptr_table panel_pnp_id; +struct lfp_data_ptr { + struct lfp_data_ptr_table fp_timing; + struct lfp_data_ptr_table dvo_timing; + struct lfp_data_ptr_table panel_pnp_id; } __packed; -struct bdb_lvds_lfp_data_ptrs { - u8 lvds_entries; - struct lvds_lfp_data_ptr ptr[16]; - struct lvds_lfp_data_ptr_table panel_name; /* (156-163?)+ */ +struct bdb_lfp_data_ptrs { + u8 num_entries; + struct lfp_data_ptr ptr[16]; + struct lfp_data_ptr_table panel_name; /* (156-163?)+ */ } __packed; /* @@ -811,7 +1216,7 @@ struct bdb_lvds_lfp_data_ptrs { */ /* LFP data has 3 blocks per entry */ -struct lvds_fp_timing { +struct fp_timing { u16 x_res; u16 y_res; u32 lvds_reg; @@ -827,46 +1232,34 @@ struct lvds_fp_timing { u16 terminator; } __packed; -struct lvds_pnp_id { - u16 mfg_name; - u16 product_code; - u32 serial; - u8 mfg_week; - u8 mfg_year; -} __packed; - /* * For reference only. fp_timing has variable size so * the data must be accessed using the data table pointers. * Do not use this directly! */ -struct lvds_lfp_data_entry { - struct lvds_fp_timing fp_timing; - struct lvds_dvo_timing dvo_timing; - struct lvds_pnp_id pnp_id; +struct lfp_data_entry { + struct fp_timing fp_timing; + struct bdb_edid_dtd dvo_timing; + struct bdb_edid_pnp_id pnp_id; } __packed; -struct bdb_lvds_lfp_data { - struct lvds_lfp_data_entry data[16]; +struct bdb_lfp_data { + struct lfp_data_entry data[16]; } __packed; -struct lvds_lfp_panel_name { - u8 name[13]; -} __packed; - -struct lvds_lfp_black_border { +struct lfp_black_border { u8 top; /* 227+ */ u8 bottom; /* 227+ */ u8 left; /* 238+ */ u8 right; /* 238+ */ } __packed; -struct bdb_lvds_lfp_data_tail { - struct lvds_lfp_panel_name panel_name[16]; /* (156-163?)+ */ +struct bdb_lfp_data_tail { + struct bdb_edid_product_name panel_name[16]; /* (156-163?)+ */ u16 scaling_enable; /* 187+ */ u8 seamless_drrs_min_refresh_rate[16]; /* 188+ */ u8 pixel_overlap_count[16]; /* 208+ */ - struct lvds_lfp_black_border black_border[16]; /* 227+ */ + struct lfp_black_border black_border[16]; /* 227+ */ u16 dual_lfp_port_sync_enable; /* 231+ */ u16 gpu_dithering_for_banding_artifacts; /* 245+ */ } __packed; @@ -899,7 +1292,7 @@ struct lfp_brightness_level { u16 reserved; } __packed; -struct bdb_lfp_backlight_data { +struct bdb_lfp_backlight { u8 entry_size; struct lfp_backlight_data_entry data[16]; u8 level[16]; /* 162-233 */ @@ -959,6 +1352,122 @@ struct bdb_lfp_power { } __packed; /* + * Block 45 - eDP BFI Block + */ + +struct edp_bfi { + u8 enable_bfi_in_driver:1; + u8 enable_brightness_control_in_cui:1; + u8 reserved:6; + u8 brightness_percentage_when_bfi_disabled; +} __packed; + +struct bdb_edp_bfi { + u8 bfi_structure_size; + struct edp_bfi bfi[16]; +} __packed; + +/* + * Block 46 - Chromaticity For Narrow Gamut Panel Configuration Block + */ + +struct chromaticity { + u8 chromaticity_enable:1; + u8 chromaticity_from_edid_base_block:1; + u8 rsvd:6; + + u8 green_y_lo:2; + u8 green_x_lo:2; + u8 red_y_lo:2; + u8 red_x_lo:2; + u8 white_y_lo:2; + u8 white_x_lo:2; + u8 blue_y_lo:2; + u8 blue_x_lo:2; + + u8 red_x_hi; + u8 red_y_hi; + u8 green_x_hi; + u8 green_y_hi; + u8 blue_x_hi; + u8 blue_y_hi; + u8 white_x_hi; + u8 white_y_hi; +} __packed; + +struct luminance_and_gamma { + u8 luminance_enable:1; /* 211+ */ + u8 gamma_enable:1; /* 211+ */ + u8 rsvd:6; + + u16 min_luminance; /* 211+ */ + u16 max_luminance; /* 211+ */ + u16 one_percent_max_luminance; /* 211+ */ + u8 gamma; /* 211+ */ +} __packed; + +struct bdb_chromaticity { + struct chromaticity chromaticity[16]; + struct luminance_and_gamma luminance_and_gamma[16]; /* 211+ */ +} __packed; + +/* + * Block 50 - MIPI Block + */ + +struct mipi_data { + u16 panel_identifier; + u16 bridge_revision; + + u32 dithering:1; + u32 pixel_format_18bpp:1; + u32 reserved1:1; + u32 dphy_params_valid:1; + u32 reserved2:28; + + u16 port_info; + + u16 reserved3:2; + u16 num_lanes:2; + u16 reserved4:12; + + u16 virtual_channel_num:2; + u16 video_transfer_mode:2; + u16 reserved5:12; + + u32 dsi_ddr_clock; + u32 renesas_bridge_ref_clock; + u16 power_conservation; + + u32 prepare_count:5; + u32 reserved6:3; + u32 clk_zero_count:8; + u32 trail_count:5; + u32 reserved7:3; + u32 exit_zero_count:6; + u32 reserved8:2; + + u32 high_low_switch_count; + u32 lp_byte_clock; + u32 clock_lane_switch_time_counter; + u32 panel_color_depth; +} __packed; + +struct bdb_mipi { + struct mipi_data mipi[16]; +} __packed; + +/* + * Block 51 - Fixed Set Mode Table + */ + +struct bdb_fixed_set_mode { + u8 enable; + u32 x_res; + u32 y_res; +} __packed; + +/* * Block 52 - MIPI Configuration Block */ @@ -981,6 +1490,17 @@ struct bdb_mipi_sequence { } __packed; /* + * Block 55 - RGB Palette Table + */ + +struct bdb_rgb_palette { + u8 is_enabled; + u8 red[256]; + u8 blue[256]; + u8 green[256]; +} __packed; + +/* * Block 56 - Compression Parameters */ @@ -1032,6 +1552,16 @@ struct bdb_compression_parameters { } __packed; /* + * Block 57 - Vswing PreEmphasis Table + */ + +struct bdb_vswing_preemph { + u8 num_tables; + u8 num_columns; + u32 tables[]; +} __packed; + +/* * Block 58 - Generic DTD Block */ @@ -1061,4 +1591,29 @@ struct bdb_generic_dtd { struct generic_dtd_entry dtd[]; /* up to 24 DTD's */ } __packed; +/* + * Block 253 - PRD Table + */ + +struct prd_entry_old { + u8 displays_attached; + u8 display_in_pipe_a; + u8 display_in_pipe_b; +} __packed; + +struct bdb_prd_table_old { + struct prd_entry_old list[0]; /* ???-216 */ + u16 num_entries; /* ???-216 */ +} __packed; + +struct prd_entry_new { + u16 primary_display; + u16 secondary_display; +} __packed; + +struct bdb_prd_table_new { + u16 num_entries; /* 217+ */ + struct prd_entry_new list[]; /* 217+ */ +} __packed; + #endif /* _INTEL_VBT_DEFS_H_ */ diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 17d6572f9d0a..b9687b7692b8 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -10,7 +10,6 @@ #include <drm/display/drm_dsc_helper.h> #include "i915_drv.h" -#include "i915_reg.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_types.h" @@ -380,7 +379,7 @@ int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state) { int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state); - if (crtc_state->bigjoiner_pipes) + if (crtc_state->joiner_pipes) num_vdsc_instances *= 2; return num_vdsc_instances; @@ -761,11 +760,11 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state) struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dss_ctl1_val = 0; - if (crtc_state->bigjoiner_pipes && !crtc_state->dsc.compression_enable) { - if (intel_crtc_is_bigjoiner_slave(crtc_state)) - dss_ctl1_val |= UNCOMPRESSED_JOINER_SLAVE; + if (crtc_state->joiner_pipes && !crtc_state->dsc.compression_enable) { + if (intel_crtc_is_joiner_secondary(crtc_state)) + dss_ctl1_val |= UNCOMPRESSED_JOINER_SECONDARY; else - dss_ctl1_val |= UNCOMPRESSED_JOINER_MASTER; + dss_ctl1_val |= UNCOMPRESSED_JOINER_PRIMARY; intel_de_write(dev_priv, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder), dss_ctl1_val); } @@ -789,10 +788,10 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state) dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE; dss_ctl1_val |= JOINER_ENABLE; } - if (crtc_state->bigjoiner_pipes) { + if (crtc_state->joiner_pipes) { dss_ctl1_val |= BIG_JOINER_ENABLE; - if (!intel_crtc_is_bigjoiner_slave(crtc_state)) - dss_ctl1_val |= MASTER_BIG_JOINER_ENABLE; + if (!intel_crtc_is_joiner_secondary(crtc_state)) + dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE; } intel_de_write(dev_priv, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder), dss_ctl1_val); intel_de_write(dev_priv, dss_ctl2_reg(crtc, crtc_state->cpu_transcoder), dss_ctl2_val); @@ -805,7 +804,7 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state) /* Disable only if either of them is enabled */ if (old_crtc_state->dsc.compression_enable || - old_crtc_state->bigjoiner_pipes) { + old_crtc_state->joiner_pipes) { intel_de_write(dev_priv, dss_ctl1_reg(crtc, old_crtc_state->cpu_transcoder), 0); intel_de_write(dev_priv, dss_ctl2_reg(crtc, old_crtc_state->cpu_transcoder), 0); } diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h index 8b21dc8e26d5..f921ad67b587 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h @@ -32,13 +32,13 @@ _ICL_PIPE_DSS_CTL1_PB, \ _ICL_PIPE_DSS_CTL1_PC) #define BIG_JOINER_ENABLE (1 << 29) -#define MASTER_BIG_JOINER_ENABLE (1 << 28) +#define PRIMARY_BIG_JOINER_ENABLE (1 << 28) #define VGA_CENTERING_ENABLE (1 << 27) #define SPLITTER_CONFIGURATION_MASK REG_GENMASK(26, 25) #define SPLITTER_CONFIGURATION_2_SEGMENT REG_FIELD_PREP(SPLITTER_CONFIGURATION_MASK, 0) #define SPLITTER_CONFIGURATION_4_SEGMENT REG_FIELD_PREP(SPLITTER_CONFIGURATION_MASK, 1) -#define UNCOMPRESSED_JOINER_MASTER (1 << 21) -#define UNCOMPRESSED_JOINER_SLAVE (1 << 20) +#define UNCOMPRESSED_JOINER_PRIMARY (1 << 21) +#define UNCOMPRESSED_JOINER_SECONDARY (1 << 20) #define _ICL_PIPE_DSS_CTL2_PB 0x78204 #define _ICL_PIPE_DSS_CTL2_PC 0x78404 diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 894ee97b3e1b..6430da25957d 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -9,8 +9,12 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_vrr.h" +#include "intel_vrr_regs.h" #include "intel_dp.h" +#define FIXED_POINT_PRECISION 100 +#define CMRR_PRECISION_TOLERANCE 10 + bool intel_vrr_is_capable(struct intel_connector *connector) { const struct drm_display_info *info = &connector->base.display_info; @@ -106,6 +110,53 @@ int intel_vrr_vmax_vblank_start(const struct intel_crtc_state *crtc_state) return crtc_state->vrr.vmax - intel_vrr_vblank_exit_length(crtc_state); } +static bool +is_cmrr_frac_required(struct intel_crtc_state *crtc_state) +{ + int calculated_refresh_k, actual_refresh_k, pixel_clock_per_line; + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (!HAS_CMRR(i915)) + return false; + + actual_refresh_k = + drm_mode_vrefresh(adjusted_mode) * FIXED_POINT_PRECISION; + pixel_clock_per_line = + adjusted_mode->crtc_clock * 1000 / adjusted_mode->crtc_htotal; + calculated_refresh_k = + pixel_clock_per_line * FIXED_POINT_PRECISION / adjusted_mode->crtc_vtotal; + + if ((actual_refresh_k - calculated_refresh_k) < CMRR_PRECISION_TOLERANCE) + return false; + + return true; +} + +static unsigned int +cmrr_get_vtotal(struct intel_crtc_state *crtc_state, bool video_mode_required) +{ + int multiplier_m = 1, multiplier_n = 1, vtotal, desired_refresh_rate; + long long adjusted_pixel_rate; + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + + desired_refresh_rate = drm_mode_vrefresh(adjusted_mode); + + if (video_mode_required) { + multiplier_m = 1001; + multiplier_n = 1000; + } + + crtc_state->cmrr.cmrr_n = mul_u32_u32(desired_refresh_rate * adjusted_mode->crtc_htotal, + multiplier_n); + vtotal = DIV_ROUND_UP_ULL(mul_u32_u32(adjusted_mode->crtc_clock * 1000, multiplier_n), + crtc_state->cmrr.cmrr_n); + adjusted_pixel_rate = mul_u32_u32(adjusted_mode->crtc_clock * 1000, multiplier_m); + crtc_state->cmrr.cmrr_m = do_div(adjusted_pixel_rate, crtc_state->cmrr.cmrr_n); + + return vtotal; +} + void intel_vrr_compute_config(struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state) @@ -115,6 +166,7 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_dp *intel_dp = intel_attached_dp(connector); + bool is_edp = intel_dp_is_edp(intel_dp); struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; const struct drm_display_info *info = &connector->base.display_info; int vmin, vmax; @@ -123,7 +175,7 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, * FIXME all joined pipes share the same transcoder. * Need to account for that during VRR toggle/push/etc. */ - if (crtc_state->bigjoiner_pipes) + if (crtc_state->joiner_pipes) return; if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -159,6 +211,39 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1; /* + * When panel is VRR capable and userspace has + * not enabled adaptive sync mode then Fixed Average + * Vtotal mode should be enabled. + */ + if (crtc_state->uapi.vrr_enabled) { + crtc_state->vrr.enable = true; + crtc_state->mode_flags |= I915_MODE_FLAG_VRR; + } else if (is_cmrr_frac_required(crtc_state) && is_edp) { + crtc_state->vrr.enable = true; + crtc_state->cmrr.enable = true; + /* + * TODO: Compute precise target refresh rate to determine + * if video_mode_required should be true. Currently set to + * false due to uncertainty about the precise target + * refresh Rate. + */ + crtc_state->vrr.vmax = cmrr_get_vtotal(crtc_state, false); + crtc_state->vrr.vmin = crtc_state->vrr.vmax; + crtc_state->vrr.flipline = crtc_state->vrr.vmin; + crtc_state->mode_flags |= I915_MODE_FLAG_VRR; + } + + if (intel_dp_as_sdp_supported(intel_dp) && + crtc_state->vrr.enable) { + crtc_state->vrr.vsync_start = + (crtc_state->hw.adjusted_mode.crtc_vtotal - + crtc_state->hw.adjusted_mode.vsync_start); + crtc_state->vrr.vsync_end = + (crtc_state->hw.adjusted_mode.crtc_vtotal - + crtc_state->hw.adjusted_mode.vsync_end); + } + + /* * For XE_LPD+, we use guardband and pipeline override * is deprecated. */ @@ -170,19 +255,6 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start - crtc_state->framestart_delay - 1); } - - if (crtc_state->uapi.vrr_enabled) { - crtc_state->vrr.enable = true; - crtc_state->mode_flags |= I915_MODE_FLAG_VRR; - if (intel_dp_as_sdp_supported(intel_dp)) { - crtc_state->vrr.vsync_start = - (crtc_state->hw.adjusted_mode.crtc_vtotal - - crtc_state->hw.adjusted_mode.vsync_start); - crtc_state->vrr.vsync_end = - (crtc_state->hw.adjusted_mode.crtc_vtotal - - crtc_state->hw.adjusted_mode.vsync_end); - } - } } static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state) @@ -213,14 +285,30 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state) 0, PIPE_VBLANK_WITH_DELAY); if (!crtc_state->vrr.flipline) { - intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0); + intel_de_write(dev_priv, + TRANS_VRR_CTL(dev_priv, cpu_transcoder), 0); return; } - intel_de_write(dev_priv, TRANS_VRR_VMIN(cpu_transcoder), crtc_state->vrr.vmin - 1); - intel_de_write(dev_priv, TRANS_VRR_VMAX(cpu_transcoder), crtc_state->vrr.vmax - 1); - intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl(crtc_state)); - intel_de_write(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder), crtc_state->vrr.flipline - 1); + if (crtc_state->cmrr.enable) { + intel_de_write(dev_priv, TRANS_CMRR_M_HI(dev_priv, cpu_transcoder), + upper_32_bits(crtc_state->cmrr.cmrr_m)); + intel_de_write(dev_priv, TRANS_CMRR_M_LO(dev_priv, cpu_transcoder), + lower_32_bits(crtc_state->cmrr.cmrr_m)); + intel_de_write(dev_priv, TRANS_CMRR_N_HI(dev_priv, cpu_transcoder), + upper_32_bits(crtc_state->cmrr.cmrr_n)); + intel_de_write(dev_priv, TRANS_CMRR_N_LO(dev_priv, cpu_transcoder), + lower_32_bits(crtc_state->cmrr.cmrr_n)); + } + + intel_de_write(dev_priv, TRANS_VRR_VMIN(dev_priv, cpu_transcoder), + crtc_state->vrr.vmin - 1); + intel_de_write(dev_priv, TRANS_VRR_VMAX(dev_priv, cpu_transcoder), + crtc_state->vrr.vmax - 1); + intel_de_write(dev_priv, TRANS_VRR_CTL(dev_priv, cpu_transcoder), + trans_vrr_ctl(crtc_state)); + intel_de_write(dev_priv, TRANS_VRR_FLIPLINE(dev_priv, cpu_transcoder), + crtc_state->vrr.flipline - 1); } void intel_vrr_send_push(const struct intel_crtc_state *crtc_state) @@ -232,7 +320,7 @@ void intel_vrr_send_push(const struct intel_crtc_state *crtc_state) if (!crtc_state->vrr.enable) return; - intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), + intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder), TRANS_PUSH_EN | TRANS_PUSH_SEND); } @@ -245,7 +333,7 @@ bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state) if (!crtc_state->vrr.enable) return false; - return intel_de_read(dev_priv, TRANS_PUSH(cpu_transcoder)) & TRANS_PUSH_SEND; + return intel_de_read(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder)) & TRANS_PUSH_SEND; } void intel_vrr_enable(const struct intel_crtc_state *crtc_state) @@ -256,15 +344,23 @@ void intel_vrr_enable(const struct intel_crtc_state *crtc_state) if (!crtc_state->vrr.enable) return; - intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), TRANS_PUSH_EN); + intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder), + TRANS_PUSH_EN); if (HAS_AS_SDP(dev_priv)) - intel_de_write(dev_priv, TRANS_VRR_VSYNC(cpu_transcoder), + intel_de_write(dev_priv, + TRANS_VRR_VSYNC(dev_priv, cpu_transcoder), VRR_VSYNC_END(crtc_state->vrr.vsync_end) | VRR_VSYNC_START(crtc_state->vrr.vsync_start)); - intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), - VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state)); + if (crtc_state->cmrr.enable) { + intel_de_write(dev_priv, TRANS_VRR_CTL(dev_priv, cpu_transcoder), + VRR_CTL_VRR_ENABLE | VRR_CTL_CMRR_ENABLE | + trans_vrr_ctl(crtc_state)); + } else { + intel_de_write(dev_priv, TRANS_VRR_CTL(dev_priv, cpu_transcoder), + VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state)); + } } void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state) @@ -276,14 +372,16 @@ void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state) if (!old_crtc_state->vrr.enable) return; - intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), + intel_de_write(dev_priv, TRANS_VRR_CTL(dev_priv, cpu_transcoder), trans_vrr_ctl(old_crtc_state)); - intel_de_wait_for_clear(dev_priv, TRANS_VRR_STATUS(cpu_transcoder), + intel_de_wait_for_clear(dev_priv, + TRANS_VRR_STATUS(dev_priv, cpu_transcoder), VRR_STATUS_VRR_EN_LIVE, 1000); - intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), 0); + intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder), 0); if (HAS_AS_SDP(dev_priv)) - intel_de_write(dev_priv, TRANS_VRR_VSYNC(cpu_transcoder), 0); + intel_de_write(dev_priv, + TRANS_VRR_VSYNC(dev_priv, cpu_transcoder), 0); } void intel_vrr_get_config(struct intel_crtc_state *crtc_state) @@ -292,9 +390,21 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state) enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 trans_vrr_ctl, trans_vrr_vsync; - trans_vrr_ctl = intel_de_read(dev_priv, TRANS_VRR_CTL(cpu_transcoder)); + trans_vrr_ctl = intel_de_read(dev_priv, + TRANS_VRR_CTL(dev_priv, cpu_transcoder)); crtc_state->vrr.enable = trans_vrr_ctl & VRR_CTL_VRR_ENABLE; + if (HAS_CMRR(dev_priv)) + crtc_state->cmrr.enable = (trans_vrr_ctl & VRR_CTL_CMRR_ENABLE); + + if (crtc_state->cmrr.enable) { + crtc_state->cmrr.cmrr_n = + intel_de_read64_2x32(dev_priv, TRANS_CMRR_N_LO(dev_priv, cpu_transcoder), + TRANS_CMRR_N_HI(dev_priv, cpu_transcoder)); + crtc_state->cmrr.cmrr_m = + intel_de_read64_2x32(dev_priv, TRANS_CMRR_M_LO(dev_priv, cpu_transcoder), + TRANS_CMRR_M_HI(dev_priv, cpu_transcoder)); + } if (DISPLAY_VER(dev_priv) >= 13) crtc_state->vrr.guardband = @@ -305,9 +415,12 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state) REG_FIELD_GET(VRR_CTL_PIPELINE_FULL_MASK, trans_vrr_ctl); if (trans_vrr_ctl & VRR_CTL_FLIP_LINE_EN) { - crtc_state->vrr.flipline = intel_de_read(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder)) + 1; - crtc_state->vrr.vmax = intel_de_read(dev_priv, TRANS_VRR_VMAX(cpu_transcoder)) + 1; - crtc_state->vrr.vmin = intel_de_read(dev_priv, TRANS_VRR_VMIN(cpu_transcoder)) + 1; + crtc_state->vrr.flipline = intel_de_read(dev_priv, + TRANS_VRR_FLIPLINE(dev_priv, cpu_transcoder)) + 1; + crtc_state->vrr.vmax = intel_de_read(dev_priv, + TRANS_VRR_VMAX(dev_priv, cpu_transcoder)) + 1; + crtc_state->vrr.vmin = intel_de_read(dev_priv, + TRANS_VRR_VMIN(dev_priv, cpu_transcoder)) + 1; } if (crtc_state->vrr.enable) { @@ -315,7 +428,8 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state) if (HAS_AS_SDP(dev_priv)) { trans_vrr_vsync = - intel_de_read(dev_priv, TRANS_VRR_VSYNC(cpu_transcoder)); + intel_de_read(dev_priv, + TRANS_VRR_VSYNC(dev_priv, cpu_transcoder)); crtc_state->vrr.vsync_start = REG_FIELD_GET(VRR_VSYNC_START_MASK, trans_vrr_vsync); crtc_state->vrr.vsync_end = diff --git a/drivers/gpu/drm/i915/display/intel_vrr_regs.h b/drivers/gpu/drm/i915/display/intel_vrr_regs.h new file mode 100644 index 000000000000..6ed0e0dc97e7 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_vrr_regs.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __INTEL_VRR_REGS_H__ +#define __INTEL_VRR_REGS_H__ + +#include "intel_display_reg_defs.h" + +/* VRR registers */ +#define _TRANS_VRR_CTL_A 0x60420 +#define _TRANS_VRR_CTL_B 0x61420 +#define _TRANS_VRR_CTL_C 0x62420 +#define _TRANS_VRR_CTL_D 0x63420 +#define TRANS_VRR_CTL(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_CTL_A) +#define VRR_CTL_VRR_ENABLE REG_BIT(31) +#define VRR_CTL_IGN_MAX_SHIFT REG_BIT(30) +#define VRR_CTL_FLIP_LINE_EN REG_BIT(29) +#define VRR_CTL_PIPELINE_FULL_MASK REG_GENMASK(10, 3) +#define VRR_CTL_PIPELINE_FULL(x) REG_FIELD_PREP(VRR_CTL_PIPELINE_FULL_MASK, (x)) +#define VRR_CTL_PIPELINE_FULL_OVERRIDE REG_BIT(0) +#define XELPD_VRR_CTL_VRR_GUARDBAND_MASK REG_GENMASK(15, 0) +#define XELPD_VRR_CTL_VRR_GUARDBAND(x) REG_FIELD_PREP(XELPD_VRR_CTL_VRR_GUARDBAND_MASK, (x)) + +#define _TRANS_VRR_VMAX_A 0x60424 +#define _TRANS_VRR_VMAX_B 0x61424 +#define _TRANS_VRR_VMAX_C 0x62424 +#define _TRANS_VRR_VMAX_D 0x63424 +#define TRANS_VRR_VMAX(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_VMAX_A) +#define VRR_VMAX_MASK REG_GENMASK(19, 0) + +#define _TRANS_VRR_VMIN_A 0x60434 +#define _TRANS_VRR_VMIN_B 0x61434 +#define _TRANS_VRR_VMIN_C 0x62434 +#define _TRANS_VRR_VMIN_D 0x63434 +#define TRANS_VRR_VMIN(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_VMIN_A) +#define VRR_VMIN_MASK REG_GENMASK(15, 0) + +#define _TRANS_VRR_VMAXSHIFT_A 0x60428 +#define _TRANS_VRR_VMAXSHIFT_B 0x61428 +#define _TRANS_VRR_VMAXSHIFT_C 0x62428 +#define _TRANS_VRR_VMAXSHIFT_D 0x63428 +#define TRANS_VRR_VMAXSHIFT(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, \ + _TRANS_VRR_VMAXSHIFT_A) +#define VRR_VMAXSHIFT_DEC_MASK REG_GENMASK(29, 16) +#define VRR_VMAXSHIFT_DEC REG_BIT(16) +#define VRR_VMAXSHIFT_INC_MASK REG_GENMASK(12, 0) + +#define _TRANS_VRR_STATUS_A 0x6042c +#define _TRANS_VRR_STATUS_B 0x6142c +#define _TRANS_VRR_STATUS_C 0x6242c +#define _TRANS_VRR_STATUS_D 0x6342c +#define TRANS_VRR_STATUS(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_STATUS_A) +#define VRR_STATUS_VMAX_REACHED REG_BIT(31) +#define VRR_STATUS_NOFLIP_TILL_BNDR REG_BIT(30) +#define VRR_STATUS_FLIP_BEF_BNDR REG_BIT(29) +#define VRR_STATUS_NO_FLIP_FRAME REG_BIT(28) +#define VRR_STATUS_VRR_EN_LIVE REG_BIT(27) +#define VRR_STATUS_FLIPS_SERVICED REG_BIT(26) +#define VRR_STATUS_VBLANK_MASK REG_GENMASK(22, 20) +#define STATUS_FSM_IDLE REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 0) +#define STATUS_FSM_WAIT_TILL_FDB REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 1) +#define STATUS_FSM_WAIT_TILL_FS REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 2) +#define STATUS_FSM_WAIT_TILL_FLIP REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 3) +#define STATUS_FSM_PIPELINE_FILL REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 4) +#define STATUS_FSM_ACTIVE REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 5) +#define STATUS_FSM_LEGACY_VBLANK REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 6) + +#define _TRANS_VRR_VTOTAL_PREV_A 0x60480 +#define _TRANS_VRR_VTOTAL_PREV_B 0x61480 +#define _TRANS_VRR_VTOTAL_PREV_C 0x62480 +#define _TRANS_VRR_VTOTAL_PREV_D 0x63480 +#define TRANS_VRR_VTOTAL_PREV(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, \ + _TRANS_VRR_VTOTAL_PREV_A) +#define VRR_VTOTAL_FLIP_BEFR_BNDR REG_BIT(31) +#define VRR_VTOTAL_FLIP_AFTER_BNDR REG_BIT(30) +#define VRR_VTOTAL_FLIP_AFTER_DBLBUF REG_BIT(29) +#define VRR_VTOTAL_PREV_FRAME_MASK REG_GENMASK(19, 0) + +#define _TRANS_VRR_FLIPLINE_A 0x60438 +#define _TRANS_VRR_FLIPLINE_B 0x61438 +#define _TRANS_VRR_FLIPLINE_C 0x62438 +#define _TRANS_VRR_FLIPLINE_D 0x63438 +#define TRANS_VRR_FLIPLINE(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, \ + _TRANS_VRR_FLIPLINE_A) +#define VRR_FLIPLINE_MASK REG_GENMASK(19, 0) + +#define _TRANS_VRR_STATUS2_A 0x6043c +#define _TRANS_VRR_STATUS2_B 0x6143c +#define _TRANS_VRR_STATUS2_C 0x6243c +#define _TRANS_VRR_STATUS2_D 0x6343c +#define TRANS_VRR_STATUS2(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_STATUS2_A) +#define VRR_STATUS2_VERT_LN_CNT_MASK REG_GENMASK(19, 0) + +#define _TRANS_PUSH_A 0x60a70 +#define _TRANS_PUSH_B 0x61a70 +#define _TRANS_PUSH_C 0x62a70 +#define _TRANS_PUSH_D 0x63a70 +#define TRANS_PUSH(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_PUSH_A) +#define TRANS_PUSH_EN REG_BIT(31) +#define TRANS_PUSH_SEND REG_BIT(30) + +#define _TRANS_VRR_VSYNC_A 0x60078 +#define TRANS_VRR_VSYNC(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_VSYNC_A) +#define VRR_VSYNC_END_MASK REG_GENMASK(28, 16) +#define VRR_VSYNC_END(vsync_end) REG_FIELD_PREP(VRR_VSYNC_END_MASK, (vsync_end)) +#define VRR_VSYNC_START_MASK REG_GENMASK(12, 0) +#define VRR_VSYNC_START(vsync_start) REG_FIELD_PREP(VRR_VSYNC_START_MASK, (vsync_start)) + +/*CMRR Registers*/ + +#define _TRANS_CMRR_M_LO_A 0x604F0 +#define TRANS_CMRR_M_LO(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_CMRR_M_LO_A) + +#define _TRANS_CMRR_M_HI_A 0x604F4 +#define TRANS_CMRR_M_HI(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_CMRR_M_HI_A) + +#define _TRANS_CMRR_N_LO_A 0x604F8 +#define TRANS_CMRR_N_LO(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_CMRR_N_LO_A) + +#define _TRANS_CMRR_N_HI_A 0x604FC +#define TRANS_CMRR_N_HI(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_CMRR_N_HI_A) + +#define VRR_CTL_CMRR_ENABLE REG_BIT(27) + +#endif /* __INTEL_VRR_REGS__ */ diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 860574d04f88..8a66b1002a74 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -21,6 +21,7 @@ #include "intel_psr_regs.h" #include "skl_scaler.h" #include "skl_universal_plane.h" +#include "skl_universal_plane_regs.h" #include "skl_watermark.h" #include "pxp/intel_pxp.h" @@ -237,9 +238,9 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915) { if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915)) - return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3); + return BIT(PLANE_4) | BIT(PLANE_5); else - return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5); + return BIT(PLANE_6) | BIT(PLANE_7); } bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv, @@ -251,7 +252,7 @@ bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv, u8 icl_hdr_plane_mask(void) { - return BIT(PLANE_PRIMARY) | BIT(PLANE_SPRITE0) | BIT(PLANE_SPRITE1); + return BIT(PLANE_1) | BIT(PLANE_2) | BIT(PLANE_3); } bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id) @@ -461,41 +462,46 @@ static int icl_plane_max_height(const struct drm_framebuffer *fb, } static unsigned int -skl_plane_max_stride(struct intel_plane *plane, - u32 pixel_format, u64 modifier, - unsigned int rotation) +plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation, + unsigned int max_pixels, + unsigned int max_bytes) { - struct drm_i915_private *i915 = to_i915(plane->base.dev); const struct drm_format_info *info = drm_format_info(pixel_format); int cpp = info->cpp[0]; - int max_horizontal_pixels = 8192; - int max_stride_bytes; - - if (DISPLAY_VER(i915) >= 13) { - /* - * The stride in bytes must not exceed of the size - * of 128K bytes. For pixel formats of 64bpp will allow - * for a 16K pixel surface. - */ - max_stride_bytes = 131072; - if (cpp == 8) - max_horizontal_pixels = 16384; - else - max_horizontal_pixels = 65536; - } else { - /* - * "The stride in bytes must not exceed the - * of the size of 8K pixels and 32K bytes." - */ - max_stride_bytes = 32768; - } if (drm_rotation_90_or_270(rotation)) - return min(max_horizontal_pixels, max_stride_bytes / cpp); + return min(max_pixels, max_bytes / cpp); else - return min(max_horizontal_pixels * cpp, max_stride_bytes); + return min(max_pixels * cpp, max_bytes); } +static unsigned int +adl_plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation) +{ + unsigned int max_pixels = 65536; /* PLANE_OFFSET limit */ + unsigned int max_bytes = 128 * 1024; + + return plane_max_stride(plane, pixel_format, + modifier, rotation, + max_pixels, max_bytes); +} + +static unsigned int +skl_plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation) +{ + unsigned int max_pixels = 8192; /* PLANE_OFFSET limit */ + unsigned int max_bytes = 32 * 1024; + + return plane_max_stride(plane, pixel_format, + modifier, rotation, + max_pixels, max_bytes); +} /* Preoffset values for YUV to RGB Conversion */ #define PREOFF_YUV_TO_RGB_HI 0x1800 @@ -616,6 +622,66 @@ static u32 skl_plane_stride(const struct intel_plane_state *plane_state, return stride / skl_plane_stride_mult(fb, color_plane, rotation); } +static u32 skl_plane_ddb_reg_val(const struct skl_ddb_entry *entry) +{ + if (!entry->end) + return 0; + + return PLANE_BUF_END(entry->end - 1) | + PLANE_BUF_START(entry->start); +} + +static u32 skl_plane_wm_reg_val(const struct skl_wm_level *level) +{ + u32 val = 0; + + if (level->enable) + val |= PLANE_WM_EN; + if (level->ignore_lines) + val |= PLANE_WM_IGNORE_LINES; + val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks); + val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines); + + return val; +} + +static void skl_write_plane_wm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(plane->base.dev); + enum plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; + const struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; + const struct skl_ddb_entry *ddb_y = + &crtc_state->wm.skl.plane_ddb_y[plane_id]; + int level; + + for (level = 0; level < i915->display.wm.num_levels; level++) + intel_de_write_fw(i915, PLANE_WM(pipe, plane_id, level), + skl_plane_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level))); + + intel_de_write_fw(i915, PLANE_WM_TRANS(pipe, plane_id), + skl_plane_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id))); + + if (HAS_HW_SAGV_WM(i915)) { + const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; + + intel_de_write_fw(i915, PLANE_WM_SAGV(pipe, plane_id), + skl_plane_wm_reg_val(&wm->sagv.wm0)); + intel_de_write_fw(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id), + skl_plane_wm_reg_val(&wm->sagv.trans_wm)); + } + + intel_de_write_fw(i915, PLANE_BUF_CFG(pipe, plane_id), + skl_plane_ddb_reg_val(ddb)); + + if (DISPLAY_VER(i915) < 11) + intel_de_write_fw(i915, PLANE_NV12_BUF_CFG(pipe, plane_id), + skl_plane_ddb_reg_val(ddb_y)); +} + static void skl_plane_disable_arm(struct intel_plane *plane, const struct intel_crtc_state *crtc_state) @@ -639,7 +705,7 @@ static void icl_plane_disable_sel_fetch_arm(struct intel_plane *plane, if (!crtc_state->enable_psr2_sel_fetch) return; - intel_de_write_fw(i915, PLANE_SEL_FETCH_CTL(pipe, plane->id), 0); + intel_de_write_fw(i915, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0); } static void @@ -1174,6 +1240,11 @@ skl_plane_update_arm(struct intel_plane *plane, plane_ctl = plane_state->ctl | skl_plane_ctl_crtc(crtc_state); + /* see intel_plane_atomic_calc_changes() */ + if (plane->need_async_flip_toggle_wa && + crtc_state->async_flip_planes & BIT(plane->id)) + plane_ctl |= PLANE_CTL_ASYNC_FLIP; + if (DISPLAY_VER(dev_priv) >= 10) plane_color_ctl = plane_state->color_ctl | glk_plane_color_ctl_crtc(crtc_state); @@ -1231,9 +1302,13 @@ static void icl_plane_update_sel_fetch_noarm(struct intel_plane *plane, clip = &plane_state->psr2_sel_fetch_area; - val = (clip->y1 + plane_state->uapi.dst.y1) << 16; + if (crtc_state->enable_psr2_su_region_et) + y = max(0, plane_state->uapi.dst.y1 - crtc_state->psr2_su_area.y1); + else + y = (clip->y1 + plane_state->uapi.dst.y1); + val = y << 16; val |= plane_state->uapi.dst.x1; - intel_de_write_fw(i915, PLANE_SEL_FETCH_POS(pipe, plane->id), val); + intel_de_write_fw(i915, SEL_FETCH_PLANE_POS(pipe, plane->id), val); x = plane_state->view.color_plane[color_plane].x; @@ -1248,13 +1323,13 @@ static void icl_plane_update_sel_fetch_noarm(struct intel_plane *plane, val = y << 16 | x; - intel_de_write_fw(i915, PLANE_SEL_FETCH_OFFSET(pipe, plane->id), + intel_de_write_fw(i915, SEL_FETCH_PLANE_OFFSET(pipe, plane->id), val); /* Sizes are 0 based */ val = (drm_rect_height(clip) - 1) << 16; val |= (drm_rect_width(&plane_state->uapi.src) >> 16) - 1; - intel_de_write_fw(i915, PLANE_SEL_FETCH_SIZE(pipe, plane->id), val); + intel_de_write_fw(i915, SEL_FETCH_PLANE_SIZE(pipe, plane->id), val); } static void @@ -1343,8 +1418,8 @@ static void icl_plane_update_sel_fetch_arm(struct intel_plane *plane, return; if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) - intel_de_write_fw(i915, PLANE_SEL_FETCH_CTL(pipe, plane->id), - PLANE_SEL_FETCH_CTL_ENABLE); + intel_de_write_fw(i915, SEL_FETCH_PLANE_CTL(pipe, plane->id), + SEL_FETCH_PLANE_CTL_ENABLE); else icl_plane_disable_sel_fetch_arm(plane, crtc_state); } @@ -1609,7 +1684,7 @@ skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, int aux_x = plane_state->view.color_plane[ccs_plane].x; int aux_y = plane_state->view.color_plane[ccs_plane].y; u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; - u32 alignment = intel_surf_alignment(fb, ccs_plane); + unsigned int alignment = intel_surf_alignment(fb, ccs_plane); int hsub; int vsub; @@ -1629,8 +1704,7 @@ skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, plane_state, ccs_plane, aux_offset, - aux_offset - - alignment); + aux_offset - alignment); aux_x = x * hsub + aux_x % hsub; aux_y = y * vsub + aux_y % vsub; } @@ -1652,10 +1726,10 @@ int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state, struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; - const int aux_plane = skl_main_to_aux_plane(fb, 0); - const u32 aux_offset = plane_state->view.color_plane[aux_plane].offset; - const u32 alignment = intel_surf_alignment(fb, 0); - const int w = drm_rect_width(&plane_state->uapi.src) >> 16; + int aux_plane = skl_main_to_aux_plane(fb, 0); + u32 aux_offset = plane_state->view.color_plane[aux_plane].offset; + unsigned int alignment = intel_surf_alignment(fb, 0); + int w = drm_rect_width(&plane_state->uapi.src) >> 16; intel_add_fb_offsets(x, y, plane_state, 0); *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0); @@ -1702,16 +1776,16 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; - const unsigned int rotation = plane_state->hw.rotation; + unsigned int rotation = plane_state->hw.rotation; int x = plane_state->uapi.src.x1 >> 16; int y = plane_state->uapi.src.y1 >> 16; - const int w = drm_rect_width(&plane_state->uapi.src) >> 16; - const int h = drm_rect_height(&plane_state->uapi.src) >> 16; - const int min_width = intel_plane_min_width(plane, fb, 0, rotation); - const int max_width = intel_plane_max_width(plane, fb, 0, rotation); - const int max_height = intel_plane_max_height(plane, fb, 0, rotation); - const int aux_plane = skl_main_to_aux_plane(fb, 0); - const u32 alignment = intel_surf_alignment(fb, 0); + int w = drm_rect_width(&plane_state->uapi.src) >> 16; + int h = drm_rect_height(&plane_state->uapi.src) >> 16; + int min_width = intel_plane_min_width(plane, fb, 0, rotation); + int max_width = intel_plane_max_width(plane, fb, 0, rotation); + int max_height = intel_plane_max_height(plane, fb, 0, rotation); + unsigned int alignment = intel_surf_alignment(fb, 0); + int aux_plane = skl_main_to_aux_plane(fb, 0); u32 offset; int ret; @@ -1799,7 +1873,7 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) if (ccs_plane) { u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; - u32 alignment = intel_surf_alignment(fb, uv_plane); + unsigned int alignment = intel_surf_alignment(fb, uv_plane); if (offset > aux_offset) offset = intel_plane_adjust_aligned_offset(&x, &y, @@ -2029,7 +2103,7 @@ static bool skl_plane_has_fbc(struct drm_i915_private *i915, if (DISPLAY_VER(i915) >= 20) return icl_is_hdr_plane(i915, plane_id); else - return plane_id == PLANE_PRIMARY; + return plane_id == PLANE_1; } static struct intel_fbc *skl_plane_fbc(struct drm_i915_private *dev_priv, @@ -2053,7 +2127,7 @@ static bool skl_plane_has_planar(struct drm_i915_private *dev_priv, if (DISPLAY_VER(dev_priv) == 9 && pipe == PIPE_C) return false; - if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0) + if (plane_id != PLANE_1 && plane_id != PLANE_2) return false; return true; @@ -2261,8 +2335,7 @@ static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915, return pipe != PIPE_C; return pipe != PIPE_C && - (plane_id == PLANE_PRIMARY || - plane_id == PLANE_SPRITE0); + (plane_id == PLANE_1 || plane_id == PLANE_2); } static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915, @@ -2280,7 +2353,7 @@ static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915, if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) return false; - return plane_id < PLANE_SPRITE4; + return plane_id < PLANE_6; } static u8 skl_get_plane_caps(struct drm_i915_private *i915, @@ -2352,7 +2425,11 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, plane->min_cdclk = skl_plane_min_cdclk; } - plane->max_stride = skl_plane_max_stride; + if (DISPLAY_VER(dev_priv) >= 13) + plane->max_stride = adl_plane_max_stride; + else + plane->max_stride = skl_plane_max_stride; + if (DISPLAY_VER(dev_priv) >= 11) { plane->update_noarm = icl_plane_update_noarm; plane->update_arm = icl_plane_update_arm; @@ -2365,9 +2442,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, plane->get_hw_state = skl_plane_get_hw_state; plane->check_plane = skl_plane_check; - if (plane_id == PLANE_PRIMARY) { - plane->need_async_flip_disable_wa = IS_DISPLAY_VER(dev_priv, - 9, 10); + if (plane_id == PLANE_1) { + plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(dev_priv, 9, 10); plane->async_flip = skl_plane_async_flip; plane->enable_flip_done = skl_plane_enable_flip_done; plane->disable_flip_done = skl_plane_disable_flip_done; @@ -2388,7 +2464,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, else plane_funcs = &skl_plane_funcs; - if (plane_id == PLANE_PRIMARY) + if (plane_id == PLANE_1) plane_type = DRM_PLANE_TYPE_PRIMARY; else plane_type = DRM_PLANE_TYPE_OVERLAY; @@ -2482,9 +2558,9 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, drm_WARN_ON(dev, pipe != crtc->pipe); - if (crtc_state->bigjoiner_pipes) { + if (crtc_state->joiner_pipes) { drm_dbg_kms(&dev_priv->drm, - "Unsupported bigjoiner configuration for initial FB\n"); + "Unsupported joiner configuration for initial FB\n"); return; } diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.h b/drivers/gpu/drm/i915/display/skl_universal_plane.h index e92e00c01b29..541489479135 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.h +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.h @@ -12,6 +12,8 @@ struct drm_i915_private; struct intel_crtc; struct intel_initial_plane_config; struct intel_plane_state; +struct skl_ddb_entry; +struct skl_wm_level; enum pipe; enum plane_id; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h b/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h new file mode 100644 index 000000000000..4ddcd7d46bbd --- /dev/null +++ b/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h @@ -0,0 +1,442 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __SKL_UNIVERSAL_PLANE_REGS_H__ +#define __SKL_UNIVERSAL_PLANE_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define _SKL_PLANE(pipe, plane, reg_1_a, reg_1_b, reg_2_a, reg_2_b) \ + _PLANE((plane), _PIPE((pipe), (reg_1_a), (reg_1_b)), _PIPE((pipe), (reg_2_a), (reg_2_b))) +#define _SKL_PLANE_DW(pipe, plane, dw, reg_1_a, reg_1_b, reg_2_a, reg_2_b) \ + (_SKL_PLANE((pipe), (plane), (reg_1_a), (reg_1_b), (reg_2_a), (reg_2_b)) + (dw) * 4) +#define _MMIO_SKL_PLANE(pipe, plane, reg_1_a, reg_1_b, reg_2_a, reg_2_b) \ + _MMIO(_SKL_PLANE((pipe), (plane), (reg_1_a), (reg_1_b), (reg_2_a), (reg_2_b))) +#define _MMIO_SKL_PLANE_DW(pipe, plane, dw, reg_1_a, reg_1_b, reg_2_a, reg_2_b) \ + _MMIO(_SKL_PLANE_DW((pipe), (plane), (dw), (reg_1_a), (reg_1_b), (reg_2_a), (reg_2_b))) + +#define _SEL_FETCH(pipe, plane, reg_1_a, reg_1_b, reg_2_a, reg_2_b, reg_5_a, reg_5_b, reg_6_a, reg_6_b) \ + _PICK_EVEN_2RANGES((plane), PLANE_5, \ + _PIPE((pipe), (reg_1_a), (reg_1_b)), \ + _PIPE((pipe), (reg_2_a), (reg_2_b)), \ + _PIPE((pipe), (reg_5_a), (reg_5_b)), \ + _PIPE((pipe), (reg_6_a), (reg_6_b))) +#define _MMIO_SEL_FETCH(pipe, plane, reg_1_a, reg_1_b, reg_2_a, reg_2_b, reg_5_a, reg_5_b, reg_6_a, reg_6_b) \ + _MMIO(_SEL_FETCH((pipe), (plane), \ + (reg_1_a), (reg_1_b), (reg_2_a), (reg_2_b), \ + (reg_5_a), (reg_5_b), (reg_6_a), (reg_6_b))) + +#define _PLANE_CTL_1_A 0x70180 +#define _PLANE_CTL_2_A 0x70280 +#define _PLANE_CTL_1_B 0x71180 +#define _PLANE_CTL_2_B 0x71280 +#define PLANE_CTL(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_CTL_1_A, _PLANE_CTL_1_B, \ + _PLANE_CTL_2_A, _PLANE_CTL_2_B) +#define PLANE_CTL_ENABLE REG_BIT(31) +#define PLANE_CTL_ARB_SLOTS_MASK REG_GENMASK(30, 28) /* icl+ */ +#define PLANE_CTL_ARB_SLOTS(x) REG_FIELD_PREP(PLANE_CTL_ARB_SLOTS_MASK, (x)) /* icl+ */ +#define PLANE_CTL_PIPE_GAMMA_ENABLE REG_BIT(30) /* Pre-GLK */ +#define PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE REG_BIT(28) +/* + * ICL+ uses the same PLANE_CTL_FORMAT bits, but the field definition + * expanded to include bit 23 as well. However, the shift-24 based values + * correctly map to the same formats in ICL, as long as bit 23 is set to 0 + */ +#define PLANE_CTL_FORMAT_MASK_SKL REG_GENMASK(27, 24) /* pre-icl */ +#define PLANE_CTL_FORMAT_MASK_ICL REG_GENMASK(27, 23) /* icl+ */ +#define PLANE_CTL_FORMAT_YUV422 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 0) +#define PLANE_CTL_FORMAT_NV12 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 1) +#define PLANE_CTL_FORMAT_XRGB_2101010 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 2) +#define PLANE_CTL_FORMAT_P010 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 3) +#define PLANE_CTL_FORMAT_XRGB_8888 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 4) +#define PLANE_CTL_FORMAT_P012 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 5) +#define PLANE_CTL_FORMAT_XRGB_16161616F REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 6) +#define PLANE_CTL_FORMAT_P016 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 7) +#define PLANE_CTL_FORMAT_XYUV REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 8) +#define PLANE_CTL_FORMAT_INDEXED REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 12) +#define PLANE_CTL_FORMAT_RGB_565 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 14) +#define PLANE_CTL_FORMAT_Y210 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 1) +#define PLANE_CTL_FORMAT_Y212 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 3) +#define PLANE_CTL_FORMAT_Y216 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 5) +#define PLANE_CTL_FORMAT_Y410 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 7) +#define PLANE_CTL_FORMAT_Y412 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 9) +#define PLANE_CTL_FORMAT_Y416 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 11) +#define PLANE_CTL_PIPE_CSC_ENABLE REG_BIT(23) /* Pre-GLK */ +#define PLANE_CTL_KEY_ENABLE_MASK REG_GENMASK(22, 21) +#define PLANE_CTL_KEY_ENABLE_SOURCE REG_FIELD_PREP(PLANE_CTL_KEY_ENABLE_MASK, 1) +#define PLANE_CTL_KEY_ENABLE_DESTINATION REG_FIELD_PREP(PLANE_CTL_KEY_ENABLE_MASK, 2) +#define PLANE_CTL_ORDER_RGBX REG_BIT(20) +#define PLANE_CTL_YUV420_Y_PLANE REG_BIT(19) +#define PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709 REG_BIT(18) +#define PLANE_CTL_YUV422_ORDER_MASK REG_GENMASK(17, 16) +#define PLANE_CTL_YUV422_ORDER_YUYV REG_FIELD_PREP(PLANE_CTL_YUV422_ORDER_MASK, 0) +#define PLANE_CTL_YUV422_ORDER_UYVY REG_FIELD_PREP(PLANE_CTL_YUV422_ORDER_MASK, 1) +#define PLANE_CTL_YUV422_ORDER_YVYU REG_FIELD_PREP(PLANE_CTL_YUV422_ORDER_MASK, 2) +#define PLANE_CTL_YUV422_ORDER_VYUY REG_FIELD_PREP(PLANE_CTL_YUV422_ORDER_MASK, 3) +#define PLANE_CTL_RENDER_DECOMPRESSION_ENABLE REG_BIT(15) +#define PLANE_CTL_TRICKLE_FEED_DISABLE REG_BIT(14) +#define PLANE_CTL_CLEAR_COLOR_DISABLE REG_BIT(13) /* TGL+ */ +#define PLANE_CTL_PLANE_GAMMA_DISABLE REG_BIT(13) /* Pre-GLK */ +#define PLANE_CTL_TILED_MASK REG_GENMASK(12, 10) +#define PLANE_CTL_TILED_LINEAR REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 0) +#define PLANE_CTL_TILED_X REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 1) +#define PLANE_CTL_TILED_Y REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 4) +#define PLANE_CTL_TILED_YF REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 5) +#define PLANE_CTL_TILED_4 REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 5) +#define PLANE_CTL_ASYNC_FLIP REG_BIT(9) +#define PLANE_CTL_FLIP_HORIZONTAL REG_BIT(8) +#define PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE REG_BIT(4) /* TGL+ */ +#define PLANE_CTL_ALPHA_MASK REG_GENMASK(5, 4) /* Pre-GLK */ +#define PLANE_CTL_ALPHA_DISABLE REG_FIELD_PREP(PLANE_CTL_ALPHA_MASK, 0) +#define PLANE_CTL_ALPHA_SW_PREMULTIPLY REG_FIELD_PREP(PLANE_CTL_ALPHA_MASK, 2) +#define PLANE_CTL_ALPHA_HW_PREMULTIPLY REG_FIELD_PREP(PLANE_CTL_ALPHA_MASK, 3) +#define PLANE_CTL_ROTATE_MASK REG_GENMASK(1, 0) +#define PLANE_CTL_ROTATE_0 REG_FIELD_PREP(PLANE_CTL_ROTATE_MASK, 0) +#define PLANE_CTL_ROTATE_90 REG_FIELD_PREP(PLANE_CTL_ROTATE_MASK, 1) +#define PLANE_CTL_ROTATE_180 REG_FIELD_PREP(PLANE_CTL_ROTATE_MASK, 2) +#define PLANE_CTL_ROTATE_270 REG_FIELD_PREP(PLANE_CTL_ROTATE_MASK, 3) + +#define _PLANE_STRIDE_1_A 0x70188 +#define _PLANE_STRIDE_2_A 0x70288 +#define _PLANE_STRIDE_1_B 0x71188 +#define _PLANE_STRIDE_2_B 0x71288 +#define PLANE_STRIDE(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_STRIDE_1_A, _PLANE_STRIDE_1_B, \ + _PLANE_STRIDE_2_A, _PLANE_STRIDE_2_B) +#define PLANE_STRIDE__MASK REG_GENMASK(11, 0) +#define PLANE_STRIDE_(stride) REG_FIELD_PREP(PLANE_STRIDE__MASK, (stride)) + +#define _PLANE_POS_1_A 0x7018c +#define _PLANE_POS_2_A 0x7028c +#define _PLANE_POS_1_B 0x7118c +#define _PLANE_POS_2_B 0x7128c +#define PLANE_POS(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_POS_1_A, _PLANE_POS_1_B, \ + _PLANE_POS_2_A, _PLANE_POS_2_B) +#define PLANE_POS_Y_MASK REG_GENMASK(31, 16) +#define PLANE_POS_Y(y) REG_FIELD_PREP(PLANE_POS_Y_MASK, (y)) +#define PLANE_POS_X_MASK REG_GENMASK(15, 0) +#define PLANE_POS_X(x) REG_FIELD_PREP(PLANE_POS_X_MASK, (x)) + +#define _PLANE_SIZE_1_A 0x70190 +#define _PLANE_SIZE_2_A 0x70290 +#define _PLANE_SIZE_1_B 0x71190 +#define _PLANE_SIZE_2_B 0x71290 +#define PLANE_SIZE(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_SIZE_1_A, _PLANE_SIZE_1_B, \ + _PLANE_SIZE_2_A, _PLANE_SIZE_2_B) +#define PLANE_HEIGHT_MASK REG_GENMASK(31, 16) +#define PLANE_HEIGHT(h) REG_FIELD_PREP(PLANE_HEIGHT_MASK, (h)) +#define PLANE_WIDTH_MASK REG_GENMASK(15, 0) +#define PLANE_WIDTH(w) REG_FIELD_PREP(PLANE_WIDTH_MASK, (w)) + +#define _PLANE_KEYVAL_1_A 0x70194 +#define _PLANE_KEYVAL_2_A 0x70294 +#define _PLANE_KEYVAL_1_B 0x71194 +#define _PLANE_KEYVAL_2_B 0x71294 +#define PLANE_KEYVAL(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane),\ + _PLANE_KEYVAL_1_A, _PLANE_KEYVAL_1_B, \ + _PLANE_KEYVAL_2_A, _PLANE_KEYVAL_2_B) + +#define _PLANE_KEYMSK_1_A 0x70198 +#define _PLANE_KEYMSK_2_A 0x70298 +#define _PLANE_KEYMSK_1_B 0x71198 +#define _PLANE_KEYMSK_2_B 0x71298 +#define PLANE_KEYMSK(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_KEYMSK_1_A, _PLANE_KEYMSK_1_B, \ + _PLANE_KEYMSK_2_A, _PLANE_KEYMSK_2_B) +#define PLANE_KEYMSK_ALPHA_ENABLE REG_BIT(31) + +#define _PLANE_SURF_1_A 0x7019c +#define _PLANE_SURF_2_A 0x7029c +#define _PLANE_SURF_1_B 0x7119c +#define _PLANE_SURF_2_B 0x7129c +#define PLANE_SURF(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_SURF_1_A, _PLANE_SURF_1_B, \ + _PLANE_SURF_2_A, _PLANE_SURF_2_B) +#define PLANE_SURF_ADDR_MASK REG_GENMASK(31, 12) +#define PLANE_SURF_DECRYPT REG_BIT(2) + +#define _PLANE_KEYMAX_1_A 0x701a0 +#define _PLANE_KEYMAX_2_A 0x702a0 +#define _PLANE_KEYMAX_1_B 0x711a0 +#define _PLANE_KEYMAX_2_B 0x712a0 +#define PLANE_KEYMAX(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_KEYMAX_1_A, _PLANE_KEYMAX_1_B, \ + _PLANE_KEYMAX_2_A, _PLANE_KEYMAX_2_B) +#define PLANE_KEYMAX_ALPHA_MASK REG_GENMASK(31, 24) +#define PLANE_KEYMAX_ALPHA(a) REG_FIELD_PREP(PLANE_KEYMAX_ALPHA_MASK, (a)) + +#define _PLANE_OFFSET_1_A 0x701a4 +#define _PLANE_OFFSET_2_A 0x702a4 +#define _PLANE_OFFSET_1_B 0x711a4 +#define _PLANE_OFFSET_2_B 0x712a4 +#define PLANE_OFFSET(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_OFFSET_1_A, _PLANE_OFFSET_1_B, \ + _PLANE_OFFSET_2_A, _PLANE_OFFSET_2_B) +#define PLANE_OFFSET_Y_MASK REG_GENMASK(31, 16) +#define PLANE_OFFSET_Y(y) REG_FIELD_PREP(PLANE_OFFSET_Y_MASK, (y)) +#define PLANE_OFFSET_X_MASK REG_GENMASK(15, 0) +#define PLANE_OFFSET_X(x) REG_FIELD_PREP(PLANE_OFFSET_X_MASK, (x)) + +#define _PLANE_SURFLIVE_1_A 0x701ac +#define _PLANE_SURFLIVE_2_A 0x702ac +#define _PLANE_SURFLIVE_1_B 0x711ac +#define _PLANE_SURFLIVE_2_B 0x712ac +#define PLANE_SURFLIVE(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_SURFLIVE_1_A, _PLANE_SURFLIVE_1_B, \ + _PLANE_SURFLIVE_2_A, _PLANE_SURFLIVE_2_B) + +#define _PLANE_CC_VAL_1_A 0x701b4 +#define _PLANE_CC_VAL_2_A 0x702b4 +#define _PLANE_CC_VAL_1_B 0x711b4 +#define _PLANE_CC_VAL_2_B 0x712b4 +#define PLANE_CC_VAL(pipe, plane, dw) _MMIO_SKL_PLANE_DW((pipe), (plane), (dw), \ + _PLANE_CC_VAL_1_A, _PLANE_CC_VAL_1_B, \ + _PLANE_CC_VAL_2_A, _PLANE_CC_VAL_2_B) + +#define _PLANE_AUX_DIST_1_A 0x701c0 +#define _PLANE_AUX_DIST_2_A 0x702c0 +#define _PLANE_AUX_DIST_1_B 0x711c0 +#define _PLANE_AUX_DIST_2_B 0x712c0 +#define PLANE_AUX_DIST(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_AUX_DIST_1_A, _PLANE_AUX_DIST_1_B, \ + _PLANE_AUX_DIST_2_A, _PLANE_AUX_DIST_2_B) +#define PLANE_AUX_DISTANCE_MASK REG_GENMASK(31, 12) +#define PLANE_AUX_STRIDE_MASK REG_GENMASK(11, 0) +#define PLANE_AUX_STRIDE(stride) REG_FIELD_PREP(PLANE_AUX_STRIDE_MASK, (stride)) + +#define _PLANE_AUX_OFFSET_1_A 0x701c4 +#define _PLANE_AUX_OFFSET_2_A 0x702c4 +#define _PLANE_AUX_OFFSET_1_B 0x711c4 +#define _PLANE_AUX_OFFSET_2_B 0x712c4 +#define PLANE_AUX_OFFSET(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_AUX_OFFSET_1_A, _PLANE_AUX_OFFSET_1_B, \ + _PLANE_AUX_OFFSET_2_A, _PLANE_AUX_OFFSET_2_B) + +#define _PLANE_CUS_CTL_1_A 0x701c8 +#define _PLANE_CUS_CTL_2_A 0x702c8 +#define _PLANE_CUS_CTL_1_B 0x711c8 +#define _PLANE_CUS_CTL_2_B 0x712c8 +#define PLANE_CUS_CTL(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_CUS_CTL_1_A, _PLANE_CUS_CTL_1_B, \ + _PLANE_CUS_CTL_2_A, _PLANE_CUS_CTL_2_B) +#define PLANE_CUS_ENABLE REG_BIT(31) +#define PLANE_CUS_Y_PLANE_MASK REG_BIT(30) +#define PLANE_CUS_Y_PLANE_4_RKL REG_FIELD_PREP(PLANE_CUS_Y_PLANE_MASK, 0) +#define PLANE_CUS_Y_PLANE_5_RKL REG_FIELD_PREP(PLANE_CUS_Y_PLANE_MASK, 1) +#define PLANE_CUS_Y_PLANE_6_ICL REG_FIELD_PREP(PLANE_CUS_Y_PLANE_MASK, 0) +#define PLANE_CUS_Y_PLANE_7_ICL REG_FIELD_PREP(PLANE_CUS_Y_PLANE_MASK, 1) +#define PLANE_CUS_HPHASE_SIGN_NEGATIVE REG_BIT(19) +#define PLANE_CUS_HPHASE_MASK REG_GENMASK(17, 16) +#define PLANE_CUS_HPHASE_0 REG_FIELD_PREP(PLANE_CUS_HPHASE_MASK, 0) +#define PLANE_CUS_HPHASE_0_25 REG_FIELD_PREP(PLANE_CUS_HPHASE_MASK, 1) +#define PLANE_CUS_HPHASE_0_5 REG_FIELD_PREP(PLANE_CUS_HPHASE_MASK, 2) +#define PLANE_CUS_VPHASE_SIGN_NEGATIVE REG_BIT(15) +#define PLANE_CUS_VPHASE_MASK REG_GENMASK(13, 12) +#define PLANE_CUS_VPHASE_0 REG_FIELD_PREP(PLANE_CUS_VPHASE_MASK, 0) +#define PLANE_CUS_VPHASE_0_25 REG_FIELD_PREP(PLANE_CUS_VPHASE_MASK, 1) +#define PLANE_CUS_VPHASE_0_5 REG_FIELD_PREP(PLANE_CUS_VPHASE_MASK, 2) + +#define _PLANE_COLOR_CTL_1_A 0x701cc /* GLK+ */ +#define _PLANE_COLOR_CTL_2_A 0x702cc +#define _PLANE_COLOR_CTL_1_B 0x711cc +#define _PLANE_COLOR_CTL_2_B 0x712cc +#define PLANE_COLOR_CTL(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_COLOR_CTL_1_A, _PLANE_COLOR_CTL_1_B, \ + _PLANE_COLOR_CTL_2_A, _PLANE_COLOR_CTL_2_B) +#define PLANE_COLOR_PIPE_GAMMA_ENABLE REG_BIT(30) /* Pre-ICL */ +#define PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE REG_BIT(28) +#define PLANE_COLOR_PIPE_CSC_ENABLE REG_BIT(23) /* Pre-ICL */ +#define PLANE_COLOR_PLANE_CSC_ENABLE REG_BIT(21) /* ICL+ */ +#define PLANE_COLOR_INPUT_CSC_ENABLE REG_BIT(20) /* ICL+ */ +#define PLANE_COLOR_CSC_MODE_MASK REG_GENMASK(19, 17) +#define PLANE_COLOR_CSC_MODE_BYPASS REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 0) +#define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 1) +#define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 2) +#define PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 3) +#define PLANE_COLOR_CSC_MODE_RGB709_TO_RGB2020 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 4) +#define PLANE_COLOR_PLANE_GAMMA_DISABLE REG_BIT(13) +#define PLANE_COLOR_ALPHA_MASK REG_GENMASK(5, 4) +#define PLANE_COLOR_ALPHA_DISABLE REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 0) +#define PLANE_COLOR_ALPHA_SW_PREMULTIPLY REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 2) +#define PLANE_COLOR_ALPHA_HW_PREMULTIPLY REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 3) + +#define _PLANE_INPUT_CSC_RY_GY_1_A 0x701e0 +#define _PLANE_INPUT_CSC_RY_GY_2_A 0x702e0 +#define _PLANE_INPUT_CSC_RY_GY_1_B 0x711e0 +#define _PLANE_INPUT_CSC_RY_GY_2_B 0x712e0 +#define PLANE_INPUT_CSC_COEFF(pipe, plane, index) _MMIO_SKL_PLANE_DW((pipe), (plane), (index), \ + _PLANE_INPUT_CSC_RY_GY_1_A, _PLANE_INPUT_CSC_RY_GY_1_B, \ + _PLANE_INPUT_CSC_RY_GY_2_A, _PLANE_INPUT_CSC_RY_GY_2_B) + +#define _PLANE_INPUT_CSC_PREOFF_HI_1_A 0x701f8 +#define _PLANE_INPUT_CSC_PREOFF_HI_2_A 0x702f8 +#define _PLANE_INPUT_CSC_PREOFF_HI_1_B 0x711f8 +#define _PLANE_INPUT_CSC_PREOFF_HI_2_B 0x712f8 +#define PLANE_INPUT_CSC_PREOFF(pipe, plane, index) _MMIO_SKL_PLANE_DW((pipe), (plane), (index), \ + _PLANE_INPUT_CSC_PREOFF_HI_1_A, _PLANE_INPUT_CSC_PREOFF_HI_1_B, \ + _PLANE_INPUT_CSC_PREOFF_HI_2_A, _PLANE_INPUT_CSC_PREOFF_HI_2_B) + +#define _PLANE_INPUT_CSC_POSTOFF_HI_1_A 0x70204 +#define _PLANE_INPUT_CSC_POSTOFF_HI_2_A 0x70304 +#define _PLANE_INPUT_CSC_POSTOFF_HI_1_B 0x71204 +#define _PLANE_INPUT_CSC_POSTOFF_HI_2_B 0x71304 +#define PLANE_INPUT_CSC_POSTOFF(pipe, plane, index) _MMIO_SKL_PLANE_DW((pipe), (plane), (index), \ + _PLANE_INPUT_CSC_POSTOFF_HI_1_A, _PLANE_INPUT_CSC_POSTOFF_HI_1_B, \ + _PLANE_INPUT_CSC_POSTOFF_HI_2_A, _PLANE_INPUT_CSC_POSTOFF_HI_2_B) + +#define _PLANE_CSC_RY_GY_1_A 0x70210 +#define _PLANE_CSC_RY_GY_2_A 0x70310 +#define _PLANE_CSC_RY_GY_1_B 0x71210 +#define _PLANE_CSC_RY_GY_2_B 0x71310 +#define PLANE_CSC_COEFF(pipe, plane, index) _MMIO_SKL_PLANE_DW((pipe), (plane), (index), \ + _PLANE_CSC_RY_GY_1_A, _PLANE_CSC_RY_GY_1_B, \ + _PLANE_CSC_RY_GY_2_A, _PLANE_CSC_RY_GY_2_B) + +#define _PLANE_CSC_PREOFF_HI_1_A 0x70228 +#define _PLANE_CSC_PREOFF_HI_2_A 0x70328 +#define _PLANE_CSC_PREOFF_HI_1_B 0x71228 +#define _PLANE_CSC_PREOFF_HI_2_B 0x71328 +#define PLANE_CSC_PREOFF(pipe, plane, index) _MMIO_SKL_PLANE_DW((pipe), (plane), (index), \ + _PLANE_CSC_PREOFF_HI_1_A, _PLANE_CSC_PREOFF_HI_1_B, \ + _PLANE_CSC_PREOFF_HI_2_A, _PLANE_CSC_PREOFF_HI_2_B) + +#define _PLANE_CSC_POSTOFF_HI_1_A 0x70234 +#define _PLANE_CSC_POSTOFF_HI_2_A 0x70334 +#define _PLANE_CSC_POSTOFF_HI_1_B 0x71234 +#define _PLANE_CSC_POSTOFF_HI_2_B 0x71334 +#define PLANE_CSC_POSTOFF(pipe, plane, index) _MMIO_SKL_PLANE_DW((pipe), (plane), (index), \ + _PLANE_CSC_POSTOFF_HI_1_A, _PLANE_CSC_POSTOFF_HI_1_B, \ + _PLANE_CSC_POSTOFF_HI_2_A, _PLANE_CSC_POSTOFF_HI_2_B) +#define _PLANE_WM_1_A_0 0x70240 +#define _PLANE_WM_1_B_0 0x71240 +#define _PLANE_WM_2_A_0 0x70340 +#define _PLANE_WM_2_B_0 0x71340 +#define PLANE_WM(pipe, plane, level) _MMIO_SKL_PLANE_DW((pipe), (plane), (level), \ + _PLANE_WM_1_A_0, _PLANE_WM_1_B_0, \ + _PLANE_WM_2_A_0, _PLANE_WM_2_B_0) +#define PLANE_WM_EN REG_BIT(31) +#define PLANE_WM_IGNORE_LINES REG_BIT(30) +#define PLANE_WM_LINES_MASK REG_GENMASK(26, 14) +#define PLANE_WM_BLOCKS_MASK REG_GENMASK(11, 0) + +#define _PLANE_WM_SAGV_1_A 0x70258 +#define _PLANE_WM_SAGV_1_B 0x71258 +#define _PLANE_WM_SAGV_2_A 0x70358 +#define _PLANE_WM_SAGV_2_B 0x71358 +#define PLANE_WM_SAGV(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_WM_SAGV_1_A, _PLANE_WM_SAGV_1_B, \ + _PLANE_WM_SAGV_2_A, _PLANE_WM_SAGV_2_B) + +#define _PLANE_WM_SAGV_TRANS_1_A 0x7025c +#define _PLANE_WM_SAGV_TRANS_1_B 0x7125c +#define _PLANE_WM_SAGV_TRANS_2_A 0x7035c +#define _PLANE_WM_SAGV_TRANS_2_B 0x7135c +#define PLANE_WM_SAGV_TRANS(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_WM_SAGV_TRANS_1_A, _PLANE_WM_SAGV_TRANS_1_B, \ + _PLANE_WM_SAGV_TRANS_2_A, _PLANE_WM_SAGV_TRANS_2_B) + +#define _PLANE_WM_TRANS_1_A 0x70268 +#define _PLANE_WM_TRANS_1_B 0x71268 +#define _PLANE_WM_TRANS_2_A 0x70368 +#define _PLANE_WM_TRANS_2_B 0x71368 +#define PLANE_WM_TRANS(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_WM_TRANS_1_A, _PLANE_WM_TRANS_1_B, \ + _PLANE_WM_TRANS_2_A, _PLANE_WM_TRANS_2_B) + +#define _PLANE_CHICKEN_1_A 0x7026c /* tgl+ */ +#define _PLANE_CHICKEN_2_A 0x7036c +#define _PLANE_CHICKEN_1_B 0x7126c +#define _PLANE_CHICKEN_2_B 0x7136c +#define PLANE_CHICKEN(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_CHICKEN_1_A, _PLANE_CHICKEN_1_B, \ + _PLANE_CHICKEN_2_A, _PLANE_CHICKEN_2_B) +#define PLANE_CHICKEN_DISABLE_DPT REG_BIT(19) /* mtl+ */ + +#define _PLANE_NV12_BUF_CFG_1_A 0x70278 +#define _PLANE_NV12_BUF_CFG_2_A 0x70378 +#define _PLANE_NV12_BUF_CFG_1_B 0x71278 +#define _PLANE_NV12_BUF_CFG_2_B 0x71378 +#define PLANE_NV12_BUF_CFG(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_NV12_BUF_CFG_1_A, _PLANE_NV12_BUF_CFG_1_B, \ + _PLANE_NV12_BUF_CFG_2_A, _PLANE_NV12_BUF_CFG_2_B) + +#define _PLANE_BUF_CFG_1_A 0x7027c +#define _PLANE_BUF_CFG_2_A 0x7037c +#define _PLANE_BUF_CFG_1_B 0x7127c +#define _PLANE_BUF_CFG_2_B 0x7137c +#define PLANE_BUF_CFG(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_BUF_CFG_1_A, _PLANE_BUF_CFG_1_B, \ + _PLANE_BUF_CFG_2_A, _PLANE_BUF_CFG_2_B) +/* skl+: 10 bits, icl+ 11 bits, adlp+ 12 bits */ +#define PLANE_BUF_END_MASK REG_GENMASK(27, 16) +#define PLANE_BUF_END(end) REG_FIELD_PREP(PLANE_BUF_END_MASK, (end)) +#define PLANE_BUF_START_MASK REG_GENMASK(11, 0) +#define PLANE_BUF_START(start) REG_FIELD_PREP(PLANE_BUF_START_MASK, (start)) + +/* tgl+ */ +#define _SEL_FETCH_PLANE_CTL_1_A 0x70890 +#define _SEL_FETCH_PLANE_CTL_2_A 0x708b0 +#define _SEL_FETCH_PLANE_CTL_5_A 0x70920 +#define _SEL_FETCH_PLANE_CTL_6_A 0x70940 +#define _SEL_FETCH_PLANE_CTL_1_B 0x71890 +#define _SEL_FETCH_PLANE_CTL_2_B 0x718b0 +#define _SEL_FETCH_PLANE_CTL_5_B 0x71920 +#define _SEL_FETCH_PLANE_CTL_6_B 0x71940 +#define SEL_FETCH_PLANE_CTL(pipe, plane) _MMIO_SEL_FETCH((pipe), (plane),\ + _SEL_FETCH_PLANE_CTL_1_A, _SEL_FETCH_PLANE_CTL_1_B, \ + _SEL_FETCH_PLANE_CTL_2_A, _SEL_FETCH_PLANE_CTL_2_B, \ + _SEL_FETCH_PLANE_CTL_5_A, _SEL_FETCH_PLANE_CTL_5_B, \ + _SEL_FETCH_PLANE_CTL_6_A, _SEL_FETCH_PLANE_CTL_6_B) +#define SEL_FETCH_PLANE_CTL_ENABLE REG_BIT(31) + +/* tgl+ */ +#define _SEL_FETCH_PLANE_POS_1_A 0x70894 +#define _SEL_FETCH_PLANE_POS_2_A 0x708b4 +#define _SEL_FETCH_PLANE_POS_5_A 0x70924 +#define _SEL_FETCH_PLANE_POS_6_A 0x70944 +#define _SEL_FETCH_PLANE_POS_1_B 0x71894 +#define _SEL_FETCH_PLANE_POS_2_B 0x718b4 +#define _SEL_FETCH_PLANE_POS_5_B 0x71924 +#define _SEL_FETCH_PLANE_POS_6_B 0x71944 +#define SEL_FETCH_PLANE_POS(pipe, plane) _MMIO_SEL_FETCH((pipe), (plane),\ + _SEL_FETCH_PLANE_POS_1_A, _SEL_FETCH_PLANE_POS_1_B, \ + _SEL_FETCH_PLANE_POS_2_A, _SEL_FETCH_PLANE_POS_2_B, \ + _SEL_FETCH_PLANE_POS_5_A, _SEL_FETCH_PLANE_POS_5_B, \ + _SEL_FETCH_PLANE_POS_6_A, _SEL_FETCH_PLANE_POS_6_B) + +/* tgl+ */ +#define _SEL_FETCH_PLANE_SIZE_1_A 0x70898 +#define _SEL_FETCH_PLANE_SIZE_2_A 0x708b8 +#define _SEL_FETCH_PLANE_SIZE_5_A 0x70928 +#define _SEL_FETCH_PLANE_SIZE_6_A 0x70948 +#define _SEL_FETCH_PLANE_SIZE_1_B 0x71898 +#define _SEL_FETCH_PLANE_SIZE_2_B 0x718b8 +#define _SEL_FETCH_PLANE_SIZE_5_B 0x71928 +#define _SEL_FETCH_PLANE_SIZE_6_B 0x71948 +#define SEL_FETCH_PLANE_SIZE(pipe, plane) _MMIO_SEL_FETCH((pipe), (plane),\ + _SEL_FETCH_PLANE_SIZE_1_A, _SEL_FETCH_PLANE_SIZE_1_B, \ + _SEL_FETCH_PLANE_SIZE_2_A, _SEL_FETCH_PLANE_SIZE_2_B, \ + _SEL_FETCH_PLANE_SIZE_5_A, _SEL_FETCH_PLANE_SIZE_5_B, \ + _SEL_FETCH_PLANE_SIZE_6_A, _SEL_FETCH_PLANE_SIZE_6_B) + +/* tgl+ */ +#define _SEL_FETCH_PLANE_OFFSET_1_A 0x7089c +#define _SEL_FETCH_PLANE_OFFSET_2_A 0x708bc +#define _SEL_FETCH_PLANE_OFFSET_5_A 0x7092c +#define _SEL_FETCH_PLANE_OFFSET_6_A 0x7094c +#define _SEL_FETCH_PLANE_OFFSET_1_B 0x7189c +#define _SEL_FETCH_PLANE_OFFSET_2_B 0x718bc +#define _SEL_FETCH_PLANE_OFFSET_5_B 0x7192c +#define _SEL_FETCH_PLANE_OFFSET_6_B 0x7194c +#define SEL_FETCH_PLANE_OFFSET(pipe, plane) _MMIO_SEL_FETCH((pipe), (plane),\ + _SEL_FETCH_PLANE_OFFSET_1_A, _SEL_FETCH_PLANE_OFFSET_1_B, \ + _SEL_FETCH_PLANE_OFFSET_2_A, _SEL_FETCH_PLANE_OFFSET_2_B, \ + _SEL_FETCH_PLANE_OFFSET_5_A, _SEL_FETCH_PLANE_OFFSET_5_B, \ + _SEL_FETCH_PLANE_OFFSET_6_A, _SEL_FETCH_PLANE_OFFSET_6_B) + +#endif /* __SKL_UNIVERSAL_PLANE_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 7c6187b4479f..a2726364b34d 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -13,6 +13,7 @@ #include "intel_bw.h" #include "intel_cdclk.h" #include "intel_crtc.h" +#include "intel_cursor_regs.h" #include "intel_de.h" #include "intel_display.h" #include "intel_display_power.h" @@ -21,6 +22,7 @@ #include "intel_fixed.h" #include "intel_pcode.h" #include "intel_wm.h" +#include "skl_universal_plane_regs.h" #include "skl_watermark.h" #include "skl_watermark_regs.h" @@ -1394,7 +1396,7 @@ skl_total_relative_data_rate(const struct intel_crtc_state *crtc_state) return data_rate; } -static const struct skl_wm_level * +const struct skl_wm_level * skl_plane_wm_level(const struct skl_pipe_wm *pipe_wm, enum plane_id plane_id, int level) @@ -1407,7 +1409,7 @@ skl_plane_wm_level(const struct skl_pipe_wm *pipe_wm, return &wm->wm[level]; } -static const struct skl_wm_level * +const struct skl_wm_level * skl_plane_trans_wm(const struct skl_pipe_wm *pipe_wm, enum plane_id plane_id) { @@ -2363,101 +2365,6 @@ static int skl_build_pipe_wm(struct intel_atomic_state *state, return skl_wm_check_vblank(crtc_state); } -static void skl_ddb_entry_write(struct drm_i915_private *i915, - i915_reg_t reg, - const struct skl_ddb_entry *entry) -{ - if (entry->end) - intel_de_write_fw(i915, reg, - PLANE_BUF_END(entry->end - 1) | - PLANE_BUF_START(entry->start)); - else - intel_de_write_fw(i915, reg, 0); -} - -static void skl_write_wm_level(struct drm_i915_private *i915, - i915_reg_t reg, - const struct skl_wm_level *level) -{ - u32 val = 0; - - if (level->enable) - val |= PLANE_WM_EN; - if (level->ignore_lines) - val |= PLANE_WM_IGNORE_LINES; - val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks); - val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines); - - intel_de_write_fw(i915, reg, val); -} - -void skl_write_plane_wm(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *i915 = to_i915(plane->base.dev); - enum plane_id plane_id = plane->id; - enum pipe pipe = plane->pipe; - const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; - const struct skl_ddb_entry *ddb = - &crtc_state->wm.skl.plane_ddb[plane_id]; - const struct skl_ddb_entry *ddb_y = - &crtc_state->wm.skl.plane_ddb_y[plane_id]; - int level; - - for (level = 0; level < i915->display.wm.num_levels; level++) - skl_write_wm_level(i915, PLANE_WM(pipe, plane_id, level), - skl_plane_wm_level(pipe_wm, plane_id, level)); - - skl_write_wm_level(i915, PLANE_WM_TRANS(pipe, plane_id), - skl_plane_trans_wm(pipe_wm, plane_id)); - - if (HAS_HW_SAGV_WM(i915)) { - const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; - - skl_write_wm_level(i915, PLANE_WM_SAGV(pipe, plane_id), - &wm->sagv.wm0); - skl_write_wm_level(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id), - &wm->sagv.trans_wm); - } - - skl_ddb_entry_write(i915, - PLANE_BUF_CFG(pipe, plane_id), ddb); - - if (DISPLAY_VER(i915) < 11) - skl_ddb_entry_write(i915, - PLANE_NV12_BUF_CFG(pipe, plane_id), ddb_y); -} - -void skl_write_cursor_wm(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *i915 = to_i915(plane->base.dev); - enum plane_id plane_id = plane->id; - enum pipe pipe = plane->pipe; - const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; - const struct skl_ddb_entry *ddb = - &crtc_state->wm.skl.plane_ddb[plane_id]; - int level; - - for (level = 0; level < i915->display.wm.num_levels; level++) - skl_write_wm_level(i915, CUR_WM(pipe, level), - skl_plane_wm_level(pipe_wm, plane_id, level)); - - skl_write_wm_level(i915, CUR_WM_TRANS(pipe), - skl_plane_trans_wm(pipe_wm, plane_id)); - - if (HAS_HW_SAGV_WM(i915)) { - const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; - - skl_write_wm_level(i915, CUR_WM_SAGV(pipe), - &wm->sagv.wm0); - skl_write_wm_level(i915, CUR_WM_SAGV_TRANS(pipe), - &wm->sagv.trans_wm); - } - - skl_ddb_entry_write(i915, CUR_BUF_CFG(pipe), ddb); -} - static bool skl_wm_level_equals(const struct skl_wm_level *l1, const struct skl_wm_level *l2) { @@ -2522,12 +2429,14 @@ bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb, } static int -skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *new_crtc_state) +skl_ddb_add_affected_planes(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_atomic_state *state = to_intel_atomic_state(new_crtc_state->uapi.state); - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct intel_plane *plane; for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { @@ -2540,6 +2449,12 @@ skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state, &new_crtc_state->wm.skl.plane_ddb_y[plane_id])) continue; + if (new_crtc_state->do_async_flip) { + drm_dbg_kms(&i915->drm, "[PLANE:%d:%s] Can't change DDB during async flip\n", + plane->base.base.id, plane->base.name); + return -EINVAL; + } + plane_state = intel_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) return PTR_ERR(plane_state); @@ -2576,7 +2491,6 @@ skl_compute_ddb(struct intel_atomic_state *state) struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_dbuf_state *old_dbuf_state; struct intel_dbuf_state *new_dbuf_state = NULL; - const struct intel_crtc_state *old_crtc_state; struct intel_crtc_state *new_crtc_state; struct intel_crtc *crtc; int ret, i; @@ -2664,14 +2578,12 @@ skl_compute_ddb(struct intel_atomic_state *state) return ret; } - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { ret = skl_crtc_allocate_plane_ddb(state, crtc); if (ret) return ret; - ret = skl_ddb_add_affected_planes(old_crtc_state, - new_crtc_state); + ret = skl_ddb_add_affected_planes(state, crtc); if (ret) return ret; } @@ -2899,6 +2811,12 @@ static int skl_wm_add_affected_planes(struct intel_atomic_state *state, &new_crtc_state->wm.skl.optimal)) continue; + if (new_crtc_state->do_async_flip) { + drm_dbg_kms(&i915->drm, "[PLANE:%d:%s] Can't change watermarks during async flip\n", + plane->base.base.id, plane->base.name); + return -EINVAL; + } + plane_state = intel_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) return PTR_ERR(plane_state); @@ -3604,7 +3522,7 @@ static void intel_mbus_dbox_update(struct intel_atomic_state *state) for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, new_dbuf_state->active_pipes) { u32 pipe_val = val; - if (DISPLAY_VER(i915) >= 14) { + if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0)) { if (xelpdp_is_only_pipe_per_dbuf_bank(crtc->pipe, new_dbuf_state->active_pipes)) pipe_val |= MBUS_DBOX_BW_8CREDITS_MTL; diff --git a/drivers/gpu/drm/i915/display/skl_watermark.h b/drivers/gpu/drm/i915/display/skl_watermark.h index 91f92c0e706e..78b121941237 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.h +++ b/drivers/gpu/drm/i915/display/skl_watermark.h @@ -18,6 +18,8 @@ struct intel_bw_state; struct intel_crtc; struct intel_crtc_state; struct intel_plane; +struct skl_pipe_wm; +struct skl_wm_level; u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *i915); @@ -30,11 +32,6 @@ bool intel_has_sagv(struct drm_i915_private *i915); u32 skl_ddb_dbuf_slice_mask(struct drm_i915_private *i915, const struct skl_ddb_entry *entry); -void skl_write_plane_wm(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state); -void skl_write_cursor_wm(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state); - bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb, const struct skl_ddb_entry *entries, int num_entries, int ignore_idx); @@ -51,6 +48,12 @@ unsigned int skl_watermark_max_latency(struct drm_i915_private *i915, int initial_wm_level); void skl_wm_init(struct drm_i915_private *i915); +const struct skl_wm_level *skl_plane_wm_level(const struct skl_pipe_wm *pipe_wm, + enum plane_id plane_id, + int level); +const struct skl_wm_level *skl_plane_trans_wm(const struct skl_pipe_wm *pipe_wm, + enum plane_id plane_id); + struct intel_dbuf_state { struct intel_global_state base; diff --git a/drivers/gpu/drm/i915/display/skl_watermark_regs.h b/drivers/gpu/drm/i915/display/skl_watermark_regs.h index 269163fa3350..c5572fc0e847 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark_regs.h +++ b/drivers/gpu/drm/i915/display/skl_watermark_regs.h @@ -43,89 +43,6 @@ #define MBUS_TRANSLATION_THROTTLE_MIN_MASK REG_GENMASK(15, 13) #define MBUS_TRANSLATION_THROTTLE_MIN(val) REG_FIELD_PREP(MBUS_TRANSLATION_THROTTLE_MIN_MASK, val) -/* Watermark register definitions for SKL */ -#define _CUR_WM_A_0 0x70140 -#define _CUR_WM_B_0 0x71140 -#define _CUR_WM_SAGV_A 0x70158 -#define _CUR_WM_SAGV_B 0x71158 -#define _CUR_WM_SAGV_TRANS_A 0x7015C -#define _CUR_WM_SAGV_TRANS_B 0x7115C -#define _CUR_WM_TRANS_A 0x70168 -#define _CUR_WM_TRANS_B 0x71168 -#define _PLANE_WM_1_A_0 0x70240 -#define _PLANE_WM_1_B_0 0x71240 -#define _PLANE_WM_2_A_0 0x70340 -#define _PLANE_WM_2_B_0 0x71340 -#define _PLANE_WM_SAGV_1_A 0x70258 -#define _PLANE_WM_SAGV_1_B 0x71258 -#define _PLANE_WM_SAGV_2_A 0x70358 -#define _PLANE_WM_SAGV_2_B 0x71358 -#define _PLANE_WM_SAGV_TRANS_1_A 0x7025C -#define _PLANE_WM_SAGV_TRANS_1_B 0x7125C -#define _PLANE_WM_SAGV_TRANS_2_A 0x7035C -#define _PLANE_WM_SAGV_TRANS_2_B 0x7135C -#define _PLANE_WM_TRANS_1_A 0x70268 -#define _PLANE_WM_TRANS_1_B 0x71268 -#define _PLANE_WM_TRANS_2_A 0x70368 -#define _PLANE_WM_TRANS_2_B 0x71368 -#define PLANE_WM_EN (1 << 31) -#define PLANE_WM_IGNORE_LINES (1 << 30) -#define PLANE_WM_LINES_MASK REG_GENMASK(26, 14) -#define PLANE_WM_BLOCKS_MASK REG_GENMASK(11, 0) - -#define _CUR_WM_0(pipe) _PIPE(pipe, _CUR_WM_A_0, _CUR_WM_B_0) -#define CUR_WM(pipe, level) _MMIO(_CUR_WM_0(pipe) + ((4) * (level))) -#define CUR_WM_SAGV(pipe) _MMIO_PIPE(pipe, _CUR_WM_SAGV_A, _CUR_WM_SAGV_B) -#define CUR_WM_SAGV_TRANS(pipe) _MMIO_PIPE(pipe, _CUR_WM_SAGV_TRANS_A, _CUR_WM_SAGV_TRANS_B) -#define CUR_WM_TRANS(pipe) _MMIO_PIPE(pipe, _CUR_WM_TRANS_A, _CUR_WM_TRANS_B) -#define _PLANE_WM_1(pipe) _PIPE(pipe, _PLANE_WM_1_A_0, _PLANE_WM_1_B_0) -#define _PLANE_WM_2(pipe) _PIPE(pipe, _PLANE_WM_2_A_0, _PLANE_WM_2_B_0) -#define _PLANE_WM_BASE(pipe, plane) \ - _PLANE(plane, _PLANE_WM_1(pipe), _PLANE_WM_2(pipe)) -#define PLANE_WM(pipe, plane, level) \ - _MMIO(_PLANE_WM_BASE(pipe, plane) + ((4) * (level))) -#define _PLANE_WM_SAGV_1(pipe) \ - _PIPE(pipe, _PLANE_WM_SAGV_1_A, _PLANE_WM_SAGV_1_B) -#define _PLANE_WM_SAGV_2(pipe) \ - _PIPE(pipe, _PLANE_WM_SAGV_2_A, _PLANE_WM_SAGV_2_B) -#define PLANE_WM_SAGV(pipe, plane) \ - _MMIO(_PLANE(plane, _PLANE_WM_SAGV_1(pipe), _PLANE_WM_SAGV_2(pipe))) -#define _PLANE_WM_SAGV_TRANS_1(pipe) \ - _PIPE(pipe, _PLANE_WM_SAGV_TRANS_1_A, _PLANE_WM_SAGV_TRANS_1_B) -#define _PLANE_WM_SAGV_TRANS_2(pipe) \ - _PIPE(pipe, _PLANE_WM_SAGV_TRANS_2_A, _PLANE_WM_SAGV_TRANS_2_B) -#define PLANE_WM_SAGV_TRANS(pipe, plane) \ - _MMIO(_PLANE(plane, _PLANE_WM_SAGV_TRANS_1(pipe), _PLANE_WM_SAGV_TRANS_2(pipe))) -#define _PLANE_WM_TRANS_1(pipe) \ - _PIPE(pipe, _PLANE_WM_TRANS_1_A, _PLANE_WM_TRANS_1_B) -#define _PLANE_WM_TRANS_2(pipe) \ - _PIPE(pipe, _PLANE_WM_TRANS_2_A, _PLANE_WM_TRANS_2_B) -#define PLANE_WM_TRANS(pipe, plane) \ - _MMIO(_PLANE(plane, _PLANE_WM_TRANS_1(pipe), _PLANE_WM_TRANS_2(pipe))) - -#define _PLANE_BUF_CFG_1_B 0x7127c -#define _PLANE_BUF_CFG_2_B 0x7137c -#define _PLANE_BUF_CFG_1(pipe) \ - _PIPE(pipe, _PLANE_BUF_CFG_1_A, _PLANE_BUF_CFG_1_B) -#define _PLANE_BUF_CFG_2(pipe) \ - _PIPE(pipe, _PLANE_BUF_CFG_2_A, _PLANE_BUF_CFG_2_B) -#define PLANE_BUF_CFG(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_BUF_CFG_1(pipe), _PLANE_BUF_CFG_2(pipe)) - -#define _PLANE_NV12_BUF_CFG_1_B 0x71278 -#define _PLANE_NV12_BUF_CFG_2_B 0x71378 -#define _PLANE_NV12_BUF_CFG_1(pipe) \ - _PIPE(pipe, _PLANE_NV12_BUF_CFG_1_A, _PLANE_NV12_BUF_CFG_1_B) -#define _PLANE_NV12_BUF_CFG_2(pipe) \ - _PIPE(pipe, _PLANE_NV12_BUF_CFG_2_A, _PLANE_NV12_BUF_CFG_2_B) -#define PLANE_NV12_BUF_CFG(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_NV12_BUF_CFG_1(pipe), _PLANE_NV12_BUF_CFG_2(pipe)) - -/* SKL new cursor registers */ -#define _CUR_BUF_CFG_A 0x7017c -#define _CUR_BUF_CFG_B 0x7117c -#define CUR_BUF_CFG(pipe) _MMIO_PIPE(pipe, _CUR_BUF_CFG_A, _CUR_BUF_CFG_B) - /* * The below are numbered starting from "S1" on gen11/gen12, but starting * with display 13, the bspec switches to a 0-based numbering scheme diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index ee9923c7b115..eae5b5e09aa8 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -972,7 +972,8 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, */ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && port == PORT_C) - enabled = intel_de_read(display, TRANSCONF(PIPE_B)) & TRANSCONF_ENABLE; + enabled = intel_de_read(display, + TRANSCONF(dev_priv, PIPE_B)) & TRANSCONF_ENABLE; /* Try command mode if video mode not enabled */ if (!enabled) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index ad6dd7f3259b..30595b2b63e1 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -8,7 +8,7 @@ #include <linux/mutex.h> #include <drm/drm_mm.h> -#include <drm/i915_drm.h> +#include <drm/intel/i915_drm.h> #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_region.h" diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 0d0a0dc9f610..206a5e0fedf1 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -9,8 +9,8 @@ #include <linux/stop_machine.h> #include <drm/drm_managed.h> -#include <drm/i915_drm.h> -#include <drm/intel-gtt.h> +#include <drm/intel/i915_drm.h> +#include <drm/intel/intel-gtt.h> #include "display/intel_display.h" #include "gem/i915_gem_lmem.h" diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c index 866c416afb73..59eed0a0ce90 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c @@ -5,7 +5,7 @@ #include "intel_ggtt_gmch.h" -#include <drm/intel-gtt.h> +#include <drm/intel/intel-gtt.h> #include <linux/agp_backend.h> diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 626b166e67ef..a6c69a706fd7 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -4,7 +4,7 @@ */ #include <drm/drm_managed.h> -#include <drm/intel-gtt.h> +#include <drm/intel/intel-gtt.h> #include "gem/i915_gem_internal.h" #include "gem/i915_gem_lmem.h" diff --git a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c index 7c9be4fd1c8c..6e63505fe478 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c @@ -9,6 +9,7 @@ #include "intel_gt_clock_utils.h" #include "intel_gt_print.h" #include "intel_gt_regs.h" +#include "soc/intel_dram.h" static u32 read_reference_ts_freq(struct intel_uncore *uncore) { @@ -151,7 +152,7 @@ static u32 gen4_read_clock_frequency(struct intel_uncore *uncore) * * Testing on actual hardware has shown there is no /16. */ - return RUNTIME_INFO(uncore->i915)->rawclk_freq * 1000; + return DIV_ROUND_CLOSEST(i9xx_fsb_freq(uncore->i915), 4) * 1000; } static u32 read_clock_frequency(struct intel_uncore *uncore) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 4fcba42cfe34..c1ce6258e55c 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -367,7 +367,6 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p) vlv_punit_put(i915); drm_printf(p, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); - drm_printf(p, "DDR freq: %d MHz\n", i915->mem_freq); drm_printf(p, "actual GPU freq: %d MHz\n", intel_gpu_freq(rps, (freq_sts >> 8) & 0xff)); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 6161f7a3ff70..735cd23a43c6 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1025,7 +1025,7 @@ void intel_gt_set_wedged(struct intel_gt *gt) if (GEM_SHOW_DEBUG()) { struct drm_printer p = drm_dbg_printer(>->i915->drm, - DRM_UT_DRIVER, __func__); + DRM_UT_DRIVER, NULL); struct intel_engine_cs *engine; enum intel_engine_id id; diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index c9cb2a391942..fa304ea088e4 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -5,7 +5,7 @@ #include <linux/string_helpers.h> -#include <drm/i915_drm.h> +#include <drm/intel/i915_drm.h> #include "display/intel_display.h" #include "display/intel_display_irq.h" @@ -265,10 +265,10 @@ static const struct cparams { u16 c; } cparams[] = { { 1, 1333, 301, 28664 }, - { 1, 1066, 294, 24460 }, + { 1, 1067, 294, 24460 }, { 1, 800, 294, 25192 }, { 0, 1333, 276, 27605 }, - { 0, 1066, 276, 27605 }, + { 0, 1067, 276, 27605 }, { 0, 800, 231, 23784 }, }; @@ -280,15 +280,16 @@ static void gen5_rps_init(struct intel_rps *rps) u32 rgvmodectl; int c_m, i; - if (i915->fsb_freq <= 3200) + if (i915->fsb_freq <= 3200000) c_m = 0; - else if (i915->fsb_freq <= 4800) + else if (i915->fsb_freq <= 4800000) c_m = 1; else c_m = 2; for (i = 0; i < ARRAY_SIZE(cparams); i++) { - if (cparams[i].i == c_m && cparams[i].t == i915->mem_freq) { + if (cparams[i].i == c_m && + cparams[i].t == DIV_ROUND_CLOSEST(i915->mem_freq, 1000)) { rps->ips.m = cparams[i].m; rps->ips.c = cparams[i].c; break; diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c index 12eca750f7d0..5eb46700dc4e 100644 --- a/drivers/gpu/drm/i915/gt/selftest_context.c +++ b/drivers/gpu/drm/i915/gt/selftest_context.c @@ -286,7 +286,7 @@ out_engine: if (intel_engine_pm_is_awake(engine)) { struct drm_printer p = drm_dbg_printer(&engine->i915->drm, - DRM_UT_DRIVER, __func__); + DRM_UT_DRIVER, NULL); intel_engine_dump(engine, &p, "%s is still awake:%d after idle-barriers\n", diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c index a7d5465655f9..d8edd7c054c8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c @@ -5,8 +5,8 @@ #include <linux/component.h> -#include <drm/i915_component.h> -#include <drm/i915_gsc_proxy_mei_interface.h> +#include <drm/intel/i915_component.h> +#include <drm/intel/i915_gsc_proxy_mei_interface.h> #include "gt/intel_gt.h" #include "gt/intel_gt_print.h" diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 4be8cb65fb7e..2f4c9c66b40b 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -49,6 +49,7 @@ #include "i915_pvinfo.h" #include "trace.h" +#include "display/i9xx_plane_regs.h" #include "display/intel_display.h" #include "display/intel_sprite_regs.h" #include "gem/i915_gem_context.h" @@ -1314,9 +1315,9 @@ static int gen8_decode_mi_display_flip(struct parser_exec_state *s, info->async_flip = ((dword2 & GENMASK(1, 0)) == 0x1); if (info->plane == PLANE_A) { - info->ctrl_reg = DSPCNTR(info->pipe); - info->stride_reg = DSPSTRIDE(info->pipe); - info->surf_reg = DSPSURF(info->pipe); + info->ctrl_reg = DSPCNTR(dev_priv, info->pipe); + info->stride_reg = DSPSTRIDE(dev_priv, info->pipe); + info->surf_reg = DSPSURF(dev_priv, info->pipe); } else if (info->plane == PLANE_B) { info->ctrl_reg = SPRCTL(info->pipe); info->stride_reg = SPRSTRIDE(info->pipe); @@ -1380,9 +1381,9 @@ static int skl_decode_mi_display_flip(struct parser_exec_state *s, info->surf_val = (dword2 & GENMASK(31, 12)) >> 12; info->async_flip = ((dword2 & GENMASK(1, 0)) == 0x1); - info->ctrl_reg = DSPCNTR(info->pipe); - info->stride_reg = DSPSTRIDE(info->pipe); - info->surf_reg = DSPSURF(info->pipe); + info->ctrl_reg = DSPCNTR(dev_priv, info->pipe); + info->stride_reg = DSPSTRIDE(dev_priv, info->pipe); + info->surf_reg = DSPSURF(dev_priv, info->pipe); return 0; } @@ -1436,7 +1437,7 @@ static int gen8_update_plane_mmio_from_mi_display_flip( } if (info->plane == PLANE_PRIMARY) - vgpu_vreg_t(vgpu, PIPE_FLIPCOUNT_G4X(info->pipe))++; + vgpu_vreg_t(vgpu, PIPE_FLIPCOUNT_G4X(dev_priv, info->pipe))++; if (info->async_flip) intel_vgpu_trigger_virtual_event(vgpu, info->event); diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 2b7df7fcf369..c66d6d3177c8 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -37,6 +37,8 @@ #include "gvt.h" #include "display/bxt_dpio_phy_regs.h" +#include "display/i9xx_plane_regs.h" +#include "display/intel_cursor_regs.h" #include "display/intel_display.h" #include "display/intel_dpio_phy.h" #include "display/intel_sprite_regs.h" @@ -65,7 +67,7 @@ static int edp_pipe_is_enabled(struct intel_vgpu *vgpu) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - if (!(vgpu_vreg_t(vgpu, TRANSCONF(TRANSCODER_EDP)) & TRANSCONF_ENABLE)) + if (!(vgpu_vreg_t(vgpu, TRANSCONF(dev_priv, TRANSCODER_EDP)) & TRANSCONF_ENABLE)) return 0; if (!(vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP) & TRANS_DDI_FUNC_ENABLE)) @@ -81,7 +83,7 @@ int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe) pipe < PIPE_A || pipe >= I915_MAX_PIPES)) return -EINVAL; - if (vgpu_vreg_t(vgpu, TRANSCONF(pipe)) & TRANSCONF_ENABLE) + if (vgpu_vreg_t(vgpu, TRANSCONF(dev_priv, pipe)) & TRANSCONF_ENABLE) return 1; if (edp_pipe_is_enabled(vgpu) && @@ -189,20 +191,20 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) GEN8_DE_PORT_HOTPLUG(HPD_PORT_C)); for_each_pipe(dev_priv, pipe) { - vgpu_vreg_t(vgpu, TRANSCONF(pipe)) &= + vgpu_vreg_t(vgpu, TRANSCONF(dev_priv, pipe)) &= ~(TRANSCONF_ENABLE | TRANSCONF_STATE_ENABLE); - vgpu_vreg_t(vgpu, DSPCNTR(pipe)) &= ~DISP_ENABLE; + vgpu_vreg_t(vgpu, DSPCNTR(dev_priv, pipe)) &= ~DISP_ENABLE; vgpu_vreg_t(vgpu, SPRCTL(pipe)) &= ~SPRITE_ENABLE; - vgpu_vreg_t(vgpu, CURCNTR(pipe)) &= ~MCURSOR_MODE_MASK; - vgpu_vreg_t(vgpu, CURCNTR(pipe)) |= MCURSOR_MODE_DISABLE; + vgpu_vreg_t(vgpu, CURCNTR(dev_priv, pipe)) &= ~MCURSOR_MODE_MASK; + vgpu_vreg_t(vgpu, CURCNTR(dev_priv, pipe)) |= MCURSOR_MODE_DISABLE; } for (trans = TRANSCODER_A; trans <= TRANSCODER_EDP; trans++) { - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(trans)) &= + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(dev_priv, trans)) &= ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | TRANS_DDI_PORT_MASK | TRANS_DDI_FUNC_ENABLE); } - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &= + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_A)) &= ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | TRANS_DDI_PORT_MASK); @@ -250,8 +252,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) * TRANSCODER_A can be enabled. PORT_x depends on the input of * setup_virtual_dp_monitor. */ - vgpu_vreg_t(vgpu, TRANSCONF(TRANSCODER_A)) |= TRANSCONF_ENABLE; - vgpu_vreg_t(vgpu, TRANSCONF(TRANSCODER_A)) |= TRANSCONF_STATE_ENABLE; + vgpu_vreg_t(vgpu, TRANSCONF(dev_priv, TRANSCODER_A)) |= TRANSCONF_ENABLE; + vgpu_vreg_t(vgpu, TRANSCONF(dev_priv, TRANSCODER_A)) |= TRANSCONF_STATE_ENABLE; /* * Golden M/N are calculated based on: @@ -259,11 +261,11 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) * DP link clk 1620 MHz and non-constant_n. * TODO: calculate DP link symbol clk and stream clk m/n. */ - vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) = TU_SIZE(64); - vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) |= 0x5b425e; - vgpu_vreg_t(vgpu, PIPE_DATA_N1(TRANSCODER_A)) = 0x800000; - vgpu_vreg_t(vgpu, PIPE_LINK_M1(TRANSCODER_A)) = 0x3cd6e; - vgpu_vreg_t(vgpu, PIPE_LINK_N1(TRANSCODER_A)) = 0x80000; + vgpu_vreg_t(vgpu, PIPE_DATA_M1(dev_priv, TRANSCODER_A)) = TU_SIZE(64); + vgpu_vreg_t(vgpu, PIPE_DATA_M1(dev_priv, TRANSCODER_A)) |= 0x5b425e; + vgpu_vreg_t(vgpu, PIPE_DATA_N1(dev_priv, TRANSCODER_A)) = 0x800000; + vgpu_vreg_t(vgpu, PIPE_LINK_M1(dev_priv, TRANSCODER_A)) = 0x3cd6e; + vgpu_vreg_t(vgpu, PIPE_LINK_N1(dev_priv, TRANSCODER_A)) = 0x80000; /* Enable per-DDI/PORT vreg */ if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) { @@ -285,7 +287,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) (DDI_BUF_CTL_ENABLE | DDI_INIT_DISPLAY_DETECTED); vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_A)) &= ~DDI_BUF_IS_IDLE; - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)) |= + vgpu_vreg_t(vgpu, + TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_EDP)) |= (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | TRANS_DDI_FUNC_ENABLE); vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |= @@ -314,7 +317,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) DDI_BUF_CTL_ENABLE; vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) &= ~DDI_BUF_IS_IDLE; - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= + vgpu_vreg_t(vgpu, + TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_A)) |= (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | (PORT_B << TRANS_DDI_PORT_SHIFT) | TRANS_DDI_FUNC_ENABLE); @@ -344,7 +348,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) DDI_BUF_CTL_ENABLE; vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) &= ~DDI_BUF_IS_IDLE; - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= + vgpu_vreg_t(vgpu, + TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_A)) |= (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | (PORT_B << TRANS_DDI_PORT_SHIFT) | TRANS_DDI_FUNC_ENABLE); @@ -393,11 +398,11 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) * DP link clk 1620 MHz and non-constant_n. * TODO: calculate DP link symbol clk and stream clk m/n. */ - vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) = TU_SIZE(64); - vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) |= 0x5b425e; - vgpu_vreg_t(vgpu, PIPE_DATA_N1(TRANSCODER_A)) = 0x800000; - vgpu_vreg_t(vgpu, PIPE_LINK_M1(TRANSCODER_A)) = 0x3cd6e; - vgpu_vreg_t(vgpu, PIPE_LINK_N1(TRANSCODER_A)) = 0x80000; + vgpu_vreg_t(vgpu, PIPE_DATA_M1(dev_priv, TRANSCODER_A)) = TU_SIZE(64); + vgpu_vreg_t(vgpu, PIPE_DATA_M1(dev_priv, TRANSCODER_A)) |= 0x5b425e; + vgpu_vreg_t(vgpu, PIPE_DATA_N1(dev_priv, TRANSCODER_A)) = 0x800000; + vgpu_vreg_t(vgpu, PIPE_LINK_M1(dev_priv, TRANSCODER_A)) = 0x3cd6e; + vgpu_vreg_t(vgpu, PIPE_LINK_N1(dev_priv, TRANSCODER_A)) = 0x80000; } if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) { @@ -408,10 +413,10 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) vgpu_vreg_t(vgpu, DPLL_CTRL2) |= DPLL_CTRL2_DDI_SEL_OVERRIDE(PORT_B); vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIB_DETECTED; - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &= + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_A)) &= ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | TRANS_DDI_PORT_MASK); - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_A)) |= (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | (PORT_B << TRANS_DDI_PORT_SHIFT) | TRANS_DDI_FUNC_ENABLE); @@ -434,10 +439,10 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) vgpu_vreg_t(vgpu, DPLL_CTRL2) |= DPLL_CTRL2_DDI_SEL_OVERRIDE(PORT_C); vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT; - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &= + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_A)) &= ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | TRANS_DDI_PORT_MASK); - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_A)) |= (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | (PORT_C << TRANS_DDI_PORT_SHIFT) | TRANS_DDI_FUNC_ENABLE); @@ -460,10 +465,10 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) vgpu_vreg_t(vgpu, DPLL_CTRL2) |= DPLL_CTRL2_DDI_SEL_OVERRIDE(PORT_D); vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT; - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &= + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_A)) &= ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | TRANS_DDI_PORT_MASK); - vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_A)) |= (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | (PORT_D << TRANS_DDI_PORT_SHIFT) | TRANS_DDI_FUNC_ENABLE); @@ -502,13 +507,13 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) /* Disable Primary/Sprite/Cursor plane */ for_each_pipe(dev_priv, pipe) { - vgpu_vreg_t(vgpu, DSPCNTR(pipe)) &= ~DISP_ENABLE; + vgpu_vreg_t(vgpu, DSPCNTR(dev_priv, pipe)) &= ~DISP_ENABLE; vgpu_vreg_t(vgpu, SPRCTL(pipe)) &= ~SPRITE_ENABLE; - vgpu_vreg_t(vgpu, CURCNTR(pipe)) &= ~MCURSOR_MODE_MASK; - vgpu_vreg_t(vgpu, CURCNTR(pipe)) |= MCURSOR_MODE_DISABLE; + vgpu_vreg_t(vgpu, CURCNTR(dev_priv, pipe)) &= ~MCURSOR_MODE_MASK; + vgpu_vreg_t(vgpu, CURCNTR(dev_priv, pipe)) |= MCURSOR_MODE_DISABLE; } - vgpu_vreg_t(vgpu, TRANSCONF(TRANSCODER_A)) |= TRANSCONF_ENABLE; + vgpu_vreg_t(vgpu, TRANSCONF(dev_priv, TRANSCODER_A)) |= TRANSCONF_ENABLE; } static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num) @@ -645,7 +650,7 @@ static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe) } if (pipe_is_enabled(vgpu, pipe)) { - vgpu_vreg_t(vgpu, PIPE_FRMCOUNT_G4X(pipe))++; + vgpu_vreg_t(vgpu, PIPE_FRMCOUNT_G4X(dev_priv, pipe))++; intel_vgpu_trigger_virtual_event(vgpu, vblank_event[pipe]); } } diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c index 6834f9fe40cf..9efc3ca0ce82 100644 --- a/drivers/gpu/drm/i915/gvt/dmabuf.c +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c @@ -37,9 +37,10 @@ #include "gem/i915_gem_dmabuf.h" #include "i915_drv.h" -#include "i915_reg.h" #include "gvt.h" +#include "display/skl_universal_plane_regs.h" + #define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12)) static int vgpu_gem_get_pages(struct drm_i915_gem_object *obj) diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c index 4140da68aabb..c454e25b2b0f 100644 --- a/drivers/gpu/drm/i915/gvt/fb_decoder.c +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c @@ -40,7 +40,10 @@ #include "i915_pvinfo.h" #include "i915_reg.h" +#include "display/i9xx_plane_regs.h" +#include "display/intel_cursor_regs.h" #include "display/intel_sprite_regs.h" +#include "display/skl_universal_plane_regs.h" #define PRIMARY_FORMAT_NUM 16 struct pixel_format { @@ -152,7 +155,7 @@ static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe, { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - u32 stride_reg = vgpu_vreg_t(vgpu, DSPSTRIDE(pipe)) & stride_mask; + u32 stride_reg = vgpu_vreg_t(vgpu, DSPSTRIDE(dev_priv, pipe)) & stride_mask; u32 stride = stride_reg; if (GRAPHICS_VER(dev_priv) >= 9) { @@ -214,7 +217,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, if (pipe >= I915_MAX_PIPES) return -ENODEV; - val = vgpu_vreg_t(vgpu, DSPCNTR(pipe)); + val = vgpu_vreg_t(vgpu, DSPCNTR(dev_priv, pipe)); plane->enabled = !!(val & DISP_ENABLE); if (!plane->enabled) return -ENODEV; @@ -248,7 +251,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, plane->hw_format = fmt; - plane->base = vgpu_vreg_t(vgpu, DSPSURF(pipe)) & I915_GTT_PAGE_MASK; + plane->base = vgpu_vreg_t(vgpu, DSPSURF(dev_priv, pipe)) & I915_GTT_PAGE_MASK; if (!vgpu_gmadr_is_valid(vgpu, plane->base)) return -EINVAL; @@ -264,14 +267,14 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, (_PRI_PLANE_STRIDE_MASK >> 6) : _PRI_PLANE_STRIDE_MASK, plane->bpp); - plane->width = (vgpu_vreg_t(vgpu, PIPESRC(pipe)) & _PIPE_H_SRCSZ_MASK) >> + plane->width = (vgpu_vreg_t(vgpu, PIPESRC(dev_priv, pipe)) & _PIPE_H_SRCSZ_MASK) >> _PIPE_H_SRCSZ_SHIFT; plane->width += 1; - plane->height = (vgpu_vreg_t(vgpu, PIPESRC(pipe)) & - _PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT; + plane->height = (vgpu_vreg_t(vgpu, PIPESRC(dev_priv, pipe)) & + _PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT; plane->height += 1; /* raw height is one minus the real value */ - val = vgpu_vreg_t(vgpu, DSPTILEOFF(pipe)); + val = vgpu_vreg_t(vgpu, DSPTILEOFF(dev_priv, pipe)); plane->x_offset = (val & _PRI_PLANE_X_OFF_MASK) >> _PRI_PLANE_X_OFF_SHIFT; plane->y_offset = (val & _PRI_PLANE_Y_OFF_MASK) >> @@ -345,7 +348,7 @@ int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, if (pipe >= I915_MAX_PIPES) return -ENODEV; - val = vgpu_vreg_t(vgpu, CURCNTR(pipe)); + val = vgpu_vreg_t(vgpu, CURCNTR(dev_priv, pipe)); mode = val & MCURSOR_MODE_MASK; plane->enabled = (mode != MCURSOR_MODE_DISABLE); if (!plane->enabled) @@ -371,7 +374,7 @@ int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, gvt_dbg_core("alpha_plane=0x%x, alpha_force=0x%x\n", alpha_plane, alpha_force); - plane->base = vgpu_vreg_t(vgpu, CURBASE(pipe)) & I915_GTT_PAGE_MASK; + plane->base = vgpu_vreg_t(vgpu, CURBASE(dev_priv, pipe)) & I915_GTT_PAGE_MASK; if (!vgpu_gmadr_is_valid(vgpu, plane->base)) return -EINVAL; @@ -382,7 +385,7 @@ int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, return -EINVAL; } - val = vgpu_vreg_t(vgpu, CURPOS(pipe)); + val = vgpu_vreg_t(vgpu, CURPOS(dev_priv, pipe)); plane->x_pos = (val & _CURSOR_POS_X_MASK) >> _CURSOR_POS_X_SHIFT; plane->x_sign = (val & _CURSOR_SIGN_X_MASK) >> _CURSOR_SIGN_X_SHIFT; plane->y_pos = (val & _CURSOR_POS_Y_MASK) >> _CURSOR_POS_Y_SHIFT; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 22fbddbe3e23..0f09344d3c20 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -42,6 +42,8 @@ #include "i915_pvinfo.h" #include "intel_mchbar_regs.h" #include "display/bxt_dpio_phy_regs.h" +#include "display/i9xx_plane_regs.h" +#include "display/intel_cursor_regs.h" #include "display/intel_display_types.h" #include "display/intel_dmc_regs.h" #include "display/intel_dp_aux_regs.h" @@ -51,6 +53,7 @@ #include "display/intel_pps_regs.h" #include "display/intel_psr_regs.h" #include "display/intel_sprite_regs.h" +#include "display/skl_universal_plane_regs.h" #include "display/skl_watermark_regs.h" #include "display/vlv_dsi_pll_regs.h" #include "gt/intel_gt_regs.h" @@ -654,7 +657,7 @@ static void vgpu_update_refresh_rate(struct intel_vgpu *vgpu) u32 dp_br, link_m, link_n, htotal, vtotal; /* Find DDI/PORT assigned to TRANSCODER_A, expect B or D */ - port = (vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) & + port = (vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_A)) & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT; if (port != PORT_B && port != PORT_D) { gvt_dbg_dpy("vgpu-%d unsupported PORT_%c\n", vgpu->id, port_name(port)); @@ -670,12 +673,12 @@ static void vgpu_update_refresh_rate(struct intel_vgpu *vgpu) dp_br = skl_vgpu_get_dp_bitrate(vgpu, port); /* Get DP link symbol clock M/N */ - link_m = vgpu_vreg_t(vgpu, PIPE_LINK_M1(TRANSCODER_A)); - link_n = vgpu_vreg_t(vgpu, PIPE_LINK_N1(TRANSCODER_A)); + link_m = vgpu_vreg_t(vgpu, PIPE_LINK_M1(dev_priv, TRANSCODER_A)); + link_n = vgpu_vreg_t(vgpu, PIPE_LINK_N1(dev_priv, TRANSCODER_A)); /* Get H/V total from transcoder timing */ - htotal = (vgpu_vreg_t(vgpu, TRANS_HTOTAL(TRANSCODER_A)) >> TRANS_HTOTAL_SHIFT); - vtotal = (vgpu_vreg_t(vgpu, TRANS_VTOTAL(TRANSCODER_A)) >> TRANS_VTOTAL_SHIFT); + htotal = (vgpu_vreg_t(vgpu, TRANS_HTOTAL(dev_priv, TRANSCODER_A)) >> TRANS_HTOTAL_SHIFT); + vtotal = (vgpu_vreg_t(vgpu, TRANS_VTOTAL(dev_priv, TRANSCODER_A)) >> TRANS_VTOTAL_SHIFT); if (dp_br && link_n && htotal && vtotal) { u64 pixel_clk = 0; @@ -878,27 +881,28 @@ static int check_fdi_rx_train_status(struct intel_vgpu *vgpu, #define INVALID_INDEX (~0U) -static unsigned int calc_index(unsigned int offset, unsigned int start, - unsigned int next, unsigned int end, i915_reg_t i915_end) +static unsigned int calc_index(unsigned int offset, i915_reg_t _start, + i915_reg_t _next, i915_reg_t _end) { - unsigned int range = next - start; + u32 start = i915_mmio_reg_offset(_start); + u32 next = i915_mmio_reg_offset(_next); + u32 end = i915_mmio_reg_offset(_end); + u32 stride = next - start; - if (!end) - end = i915_mmio_reg_offset(i915_end); if (offset < start || offset > end) return INVALID_INDEX; offset -= start; - return offset / range; + return offset / stride; } #define FDI_RX_CTL_TO_PIPE(offset) \ - calc_index(offset, _FDI_RXA_CTL, _FDI_RXB_CTL, 0, FDI_RX_CTL(PIPE_C)) + calc_index(offset, FDI_RX_CTL(PIPE_A), FDI_RX_CTL(PIPE_B), FDI_RX_CTL(PIPE_C)) #define FDI_TX_CTL_TO_PIPE(offset) \ - calc_index(offset, _FDI_TXA_CTL, _FDI_TXB_CTL, 0, FDI_TX_CTL(PIPE_C)) + calc_index(offset, FDI_TX_CTL(PIPE_A), FDI_TX_CTL(PIPE_B), FDI_TX_CTL(PIPE_C)) #define FDI_RX_IMR_TO_PIPE(offset) \ - calc_index(offset, _FDI_RXA_IMR, _FDI_RXB_IMR, 0, FDI_RX_IMR(PIPE_C)) + calc_index(offset, FDI_RX_IMR(PIPE_A), FDI_RX_IMR(PIPE_B), FDI_RX_IMR(PIPE_C)) static int update_fdi_rx_iir_status(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) @@ -942,7 +946,7 @@ static int update_fdi_rx_iir_status(struct intel_vgpu *vgpu, } #define DP_TP_CTL_TO_PORT(offset) \ - calc_index(offset, _DP_TP_CTL_A, _DP_TP_CTL_B, 0, DP_TP_CTL(PORT_E)) + calc_index(offset, DP_TP_CTL(PORT_A), DP_TP_CTL(PORT_B), DP_TP_CTL(PORT_E)) static int dp_tp_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) @@ -1005,22 +1009,22 @@ static int south_chicken2_mmio_write(struct intel_vgpu *vgpu, return 0; } -#define DSPSURF_TO_PIPE(offset) \ - calc_index(offset, _DSPASURF, _DSPBSURF, 0, DSPSURF(PIPE_C)) +#define DSPSURF_TO_PIPE(dev_priv, offset) \ + calc_index(offset, DSPSURF(dev_priv, PIPE_A), DSPSURF(dev_priv, PIPE_B), DSPSURF(dev_priv, PIPE_C)) static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - u32 pipe = DSPSURF_TO_PIPE(offset); + u32 pipe = DSPSURF_TO_PIPE(dev_priv, offset); int event = SKL_FLIP_EVENT(pipe, PLANE_PRIMARY); write_vreg(vgpu, offset, p_data, bytes); - vgpu_vreg_t(vgpu, DSPSURFLIVE(pipe)) = vgpu_vreg(vgpu, offset); + vgpu_vreg_t(vgpu, DSPSURFLIVE(dev_priv, pipe)) = vgpu_vreg(vgpu, offset); - vgpu_vreg_t(vgpu, PIPE_FLIPCOUNT_G4X(pipe))++; + vgpu_vreg_t(vgpu, PIPE_FLIPCOUNT_G4X(dev_priv, pipe))++; - if (vgpu_vreg_t(vgpu, DSPCNTR(pipe)) & PLANE_CTL_ASYNC_FLIP) + if (vgpu_vreg_t(vgpu, DSPCNTR(dev_priv, pipe)) & PLANE_CTL_ASYNC_FLIP) intel_vgpu_trigger_virtual_event(vgpu, event); else set_bit(event, vgpu->irq.flip_done_event[pipe]); @@ -1029,7 +1033,7 @@ static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, } #define SPRSURF_TO_PIPE(offset) \ - calc_index(offset, _SPRA_SURF, _SPRB_SURF, 0, SPRSURF(PIPE_C)) + calc_index(offset, SPRSURF(PIPE_A), SPRSURF(PIPE_B), SPRSURF(PIPE_C)) static int spr_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) @@ -1059,8 +1063,8 @@ static int reg50080_mmio_write(struct intel_vgpu *vgpu, write_vreg(vgpu, offset, p_data, bytes); if (plane == PLANE_PRIMARY) { - vgpu_vreg_t(vgpu, DSPSURFLIVE(pipe)) = vgpu_vreg(vgpu, offset); - vgpu_vreg_t(vgpu, PIPE_FLIPCOUNT_G4X(pipe))++; + vgpu_vreg_t(vgpu, DSPSURFLIVE(dev_priv, pipe)) = vgpu_vreg(vgpu, offset); + vgpu_vreg_t(vgpu, PIPE_FLIPCOUNT_G4X(dev_priv, pipe))++; } else { vgpu_vreg_t(vgpu, SPRSURFLIVE(pipe)) = vgpu_vreg(vgpu, offset); } @@ -1081,13 +1085,13 @@ static int trigger_aux_channel_interrupt(struct intel_vgpu *vgpu, if (reg == i915_mmio_reg_offset(DP_AUX_CH_CTL(AUX_CH_A))) event = AUX_CHANNEL_A; - else if (reg == _PCH_DPB_AUX_CH_CTL || + else if (reg == i915_mmio_reg_offset(PCH_DP_AUX_CH_CTL(AUX_CH_B)) || reg == i915_mmio_reg_offset(DP_AUX_CH_CTL(AUX_CH_B))) event = AUX_CHANNEL_B; - else if (reg == _PCH_DPC_AUX_CH_CTL || + else if (reg == i915_mmio_reg_offset(PCH_DP_AUX_CH_CTL(AUX_CH_C)) || reg == i915_mmio_reg_offset(DP_AUX_CH_CTL(AUX_CH_C))) event = AUX_CHANNEL_C; - else if (reg == _PCH_DPD_AUX_CH_CTL || + else if (reg == i915_mmio_reg_offset(PCH_DP_AUX_CH_CTL(AUX_CH_D)) || reg == i915_mmio_reg_offset(DP_AUX_CH_CTL(AUX_CH_D))) event = AUX_CHANNEL_D; else { @@ -1151,11 +1155,6 @@ static void dp_aux_ch_ctl_link_training(struct intel_vgpu_dpcd_data *dpcd, } } -#define _REG_HSW_DP_AUX_CH_CTL(dp) \ - ((dp) ? (_PCH_DPB_AUX_CH_CTL + ((dp)-1)*0x100) : 0x64010) - -#define _REG_SKL_DP_AUX_CH_CTL(dp) (0x64010 + (dp) * 0x100) - #define OFFSET_TO_DP_AUX_PORT(offset) (((offset) & 0xF00) >> 8) #define dpy_is_valid_port(port) \ @@ -1179,12 +1178,14 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu, write_vreg(vgpu, offset, p_data, bytes); data = vgpu_vreg(vgpu, offset); - if ((GRAPHICS_VER(vgpu->gvt->gt->i915) >= 9) - && offset != _REG_SKL_DP_AUX_CH_CTL(port_index)) { + if (GRAPHICS_VER(vgpu->gvt->gt->i915) >= 9 && + offset != i915_mmio_reg_offset(DP_AUX_CH_CTL(port_index))) { /* SKL DPB/C/D aux ctl register changed */ return 0; } else if (IS_BROADWELL(vgpu->gvt->gt->i915) && - offset != _REG_HSW_DP_AUX_CH_CTL(port_index)) { + offset != i915_mmio_reg_offset(port_index ? + PCH_DP_AUX_CH_CTL(port_index) : + DP_AUX_CH_CTL(port_index))) { /* write to the data registers */ return 0; } @@ -2270,17 +2271,21 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_DFH(GEN7_HALF_SLICE_CHICKEN1, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); /* display */ - MMIO_DH(TRANSCONF(TRANSCODER_A), D_ALL, NULL, pipeconf_mmio_write); - MMIO_DH(TRANSCONF(TRANSCODER_B), D_ALL, NULL, pipeconf_mmio_write); - MMIO_DH(TRANSCONF(TRANSCODER_C), D_ALL, NULL, pipeconf_mmio_write); - MMIO_DH(TRANSCONF(TRANSCODER_EDP), D_ALL, NULL, pipeconf_mmio_write); - MMIO_DH(DSPSURF(PIPE_A), D_ALL, NULL, pri_surf_mmio_write); + MMIO_DH(TRANSCONF(dev_priv, TRANSCODER_A), D_ALL, NULL, + pipeconf_mmio_write); + MMIO_DH(TRANSCONF(dev_priv, TRANSCODER_B), D_ALL, NULL, + pipeconf_mmio_write); + MMIO_DH(TRANSCONF(dev_priv, TRANSCODER_C), D_ALL, NULL, + pipeconf_mmio_write); + MMIO_DH(TRANSCONF(dev_priv, TRANSCODER_EDP), D_ALL, NULL, + pipeconf_mmio_write); + MMIO_DH(DSPSURF(dev_priv, PIPE_A), D_ALL, NULL, pri_surf_mmio_write); MMIO_DH(REG_50080(PIPE_A, PLANE_PRIMARY), D_ALL, NULL, reg50080_mmio_write); - MMIO_DH(DSPSURF(PIPE_B), D_ALL, NULL, pri_surf_mmio_write); + MMIO_DH(DSPSURF(dev_priv, PIPE_B), D_ALL, NULL, pri_surf_mmio_write); MMIO_DH(REG_50080(PIPE_B, PLANE_PRIMARY), D_ALL, NULL, reg50080_mmio_write); - MMIO_DH(DSPSURF(PIPE_C), D_ALL, NULL, pri_surf_mmio_write); + MMIO_DH(DSPSURF(dev_priv, PIPE_C), D_ALL, NULL, pri_surf_mmio_write); MMIO_DH(REG_50080(PIPE_C, PLANE_PRIMARY), D_ALL, NULL, reg50080_mmio_write); MMIO_DH(SPRSURF(PIPE_A), D_ALL, NULL, spr_surf_mmio_write); @@ -2297,12 +2302,12 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) gmbus_mmio_write); MMIO_F(PCH_GPIO_BASE, 6 * 4, F_UNALIGN, 0, 0, D_ALL, NULL, NULL); - MMIO_F(_MMIO(_PCH_DPB_AUX_CH_CTL), 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, - dp_aux_ch_ctl_mmio_write); - MMIO_F(_MMIO(_PCH_DPC_AUX_CH_CTL), 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, - dp_aux_ch_ctl_mmio_write); - MMIO_F(_MMIO(_PCH_DPD_AUX_CH_CTL), 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, - dp_aux_ch_ctl_mmio_write); + MMIO_F(PCH_DP_AUX_CH_CTL(AUX_CH_B), 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, + dp_aux_ch_ctl_mmio_write); + MMIO_F(PCH_DP_AUX_CH_CTL(AUX_CH_C), 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, + dp_aux_ch_ctl_mmio_write); + MMIO_F(PCH_DP_AUX_CH_CTL(AUX_CH_D), 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, + dp_aux_ch_ctl_mmio_write); MMIO_DH(PCH_ADPA, D_PRE_SKL, NULL, pch_adpa_mmio_write); @@ -2339,8 +2344,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_DH(SBI_DATA, D_ALL, sbi_data_mmio_read, NULL); MMIO_DH(SBI_CTL_STAT, D_ALL, NULL, sbi_ctl_mmio_write); - MMIO_F(_MMIO(_DPA_AUX_CH_CTL), 6 * 4, 0, 0, 0, D_ALL, NULL, - dp_aux_ch_ctl_mmio_write); + MMIO_F(DP_AUX_CH_CTL(AUX_CH_A), 6 * 4, 0, 0, 0, D_ALL, NULL, + dp_aux_ch_ctl_mmio_write); MMIO_DH(DDI_BUF_CTL(PORT_A), D_ALL, NULL, ddi_buf_ctl_mmio_write); MMIO_DH(DDI_BUF_CTL(PORT_B), D_ALL, NULL, ddi_buf_ctl_mmio_write); @@ -2677,35 +2682,35 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 2), D_SKL_PLUS, NULL, NULL); MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 3), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C0(PIPE_A, 1)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C0(PIPE_A, 2)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C0(PIPE_A, 3)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C0(PIPE_A, 4)), D_SKL_PLUS, NULL, NULL); - - MMIO_DH(_MMIO(_REG_701C0(PIPE_B, 1)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C0(PIPE_B, 2)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C0(PIPE_B, 3)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C0(PIPE_B, 4)), D_SKL_PLUS, NULL, NULL); - - MMIO_DH(_MMIO(_REG_701C0(PIPE_C, 1)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C0(PIPE_C, 2)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C0(PIPE_C, 3)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C0(PIPE_C, 4)), D_SKL_PLUS, NULL, NULL); - - MMIO_DH(_MMIO(_REG_701C4(PIPE_A, 1)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C4(PIPE_A, 2)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C4(PIPE_A, 3)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C4(PIPE_A, 4)), D_SKL_PLUS, NULL, NULL); - - MMIO_DH(_MMIO(_REG_701C4(PIPE_B, 1)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C4(PIPE_B, 2)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C4(PIPE_B, 3)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C4(PIPE_B, 4)), D_SKL_PLUS, NULL, NULL); - - MMIO_DH(_MMIO(_REG_701C4(PIPE_C, 1)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C4(PIPE_C, 2)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C4(PIPE_C, 3)), D_SKL_PLUS, NULL, NULL); - MMIO_DH(_MMIO(_REG_701C4(PIPE_C, 4)), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_DIST(PIPE_A, 0), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_DIST(PIPE_A, 1), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_DIST(PIPE_A, 2), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_DIST(PIPE_A, 3), D_SKL_PLUS, NULL, NULL); + + MMIO_DH(PLANE_AUX_DIST(PIPE_B, 0), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_DIST(PIPE_B, 1), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_DIST(PIPE_B, 2), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_DIST(PIPE_B, 3), D_SKL_PLUS, NULL, NULL); + + MMIO_DH(PLANE_AUX_DIST(PIPE_C, 0), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_DIST(PIPE_C, 1), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_DIST(PIPE_C, 2), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_DIST(PIPE_C, 3), D_SKL_PLUS, NULL, NULL); + + MMIO_DH(PLANE_AUX_OFFSET(PIPE_A, 0), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_OFFSET(PIPE_A, 1), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_OFFSET(PIPE_A, 2), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_OFFSET(PIPE_A, 3), D_SKL_PLUS, NULL, NULL); + + MMIO_DH(PLANE_AUX_OFFSET(PIPE_B, 0), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_OFFSET(PIPE_B, 1), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_OFFSET(PIPE_B, 2), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_OFFSET(PIPE_B, 3), D_SKL_PLUS, NULL, NULL); + + MMIO_DH(PLANE_AUX_OFFSET(PIPE_C, 0), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_OFFSET(PIPE_C, 1), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_OFFSET(PIPE_C, 2), D_SKL_PLUS, NULL, NULL); + MMIO_DH(PLANE_AUX_OFFSET(PIPE_C, 3), D_SKL_PLUS, NULL, NULL); MMIO_DFH(BDW_SCRATCH1, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 4f74d867fe1a..38830818c120 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -1985,5 +1985,6 @@ static void __exit kvmgt_exit(void) module_init(kvmgt_init); module_exit(kvmgt_exit); +MODULE_DESCRIPTION("Intel mediated pass-through framework for KVM"); MODULE_LICENSE("GPL and additional rights"); MODULE_AUTHOR("Intel Corporation"); diff --git a/drivers/gpu/drm/i915/gvt/reg.h b/drivers/gpu/drm/i915/gvt/reg.h index d8216c63c39a..90d8eb1761a3 100644 --- a/drivers/gpu/drm/i915/gvt/reg.h +++ b/drivers/gpu/drm/i915/gvt/reg.h @@ -57,9 +57,6 @@ #define VGT_SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _PLANE_STRIDE_2_B) -#define _REG_701C0(pipe, plane) (0x701c0 + pipe * 0x1000 + (plane - 1) * 0x100) -#define _REG_701C4(pipe, plane) (0x701c4 + pipe * 0x1000 + (plane - 1) * 0x100) - #define SKL_FLIP_EVENT(pipe, plane) (PRIMARY_A_FLIP_DONE + (plane) * 3 + (pipe)) #define REG50080_FLIP_TYPE_MASK 0x3 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ee0d7d5f135d..d1d21d433766 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -305,6 +305,7 @@ struct drm_i915_private { INTEL_DRAM_LPDDR4, INTEL_DRAM_DDR5, INTEL_DRAM_LPDDR5, + INTEL_DRAM_GDDR, } type; u8 num_qgv_points; u8 num_psf_gv_points; @@ -535,7 +536,15 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_ALDERLAKE_P(i915) IS_PLATFORM(i915, INTEL_ALDERLAKE_P) #define IS_DG2(i915) IS_PLATFORM(i915, INTEL_DG2) #define IS_METEORLAKE(i915) IS_PLATFORM(i915, INTEL_METEORLAKE) -#define IS_LUNARLAKE(i915) 0 +/* + * Display code shared by i915 and Xe relies on macros like IS_LUNARLAKE, + * so we need to define these even on platforms that the i915 base driver + * doesn't support. Ensure the parameter is used in the definition to + * avoid 'unused variable' warnings when compiling the shared display code + * for i915. + */ +#define IS_LUNARLAKE(i915) (0 && i915) +#define IS_BATTLEMAGE(i915) (0 && i915) #define IS_DG2_G10(i915) \ IS_SUBPLATFORM(i915, INTEL_DG2, INTEL_SUBPLATFORM_G10) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 625b3c024540..96c6cafd5b9e 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -836,6 +836,7 @@ static void err_print_gt_engines(struct drm_i915_error_state_buf *m, static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, struct i915_gpu_coredump *error) { + struct drm_printer p = i915_error_printer(m); const struct intel_engine_coredump *ee; struct timespec64 ts; @@ -873,7 +874,7 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, err_printf(m, "IOMMU enabled?: %d\n", error->iommu); - intel_dmc_print_error_state(m, m->i915); + intel_dmc_print_error_state(&p, m->i915); err_printf(m, "RPM wakelock: %s\n", str_yes_no(error->wakelock)); err_printf(m, "PM suspended: %s\n", str_yes_no(error->suspended)); @@ -904,7 +905,7 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, } if (error->overlay) - intel_overlay_print_error_state(m, error->overlay); + intel_overlay_print_error_state(&p, error->overlay); err_print_capabilities(m, error); err_print_params(m, &error->params); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 678d632ed043..8059ac7e15fe 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1040,7 +1040,8 @@ static void i915_irq_reset(struct drm_i915_private *dev_priv) if (I915_HAS_HOTPLUG(dev_priv)) { i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0); + intel_uncore_rmw(&dev_priv->uncore, + PORT_HOTPLUG_STAT(dev_priv), 0, 0); } i9xx_pipestat_irq_reset(dev_priv); @@ -1149,7 +1150,7 @@ static void i965_irq_reset(struct drm_i915_private *dev_priv) struct intel_uncore *uncore = &dev_priv->uncore; i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0); + intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT(dev_priv), 0, 0); i9xx_pipestat_irq_reset(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 405ca17a990b..7058efa75324 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -24,7 +24,7 @@ #include <drm/drm_color_mgmt.h> #include <drm/drm_drv.h> -#include <drm/i915_pciids.h> +#include <drm/intel/i915_pciids.h> #include "display/intel_display.h" #include "display/intel_display_driver.h" @@ -797,80 +797,81 @@ __diag_pop(); * PCI ID matches, otherwise we'll use the wrong info struct above. */ static const struct pci_device_id pciidlist[] = { - INTEL_I830_IDS(&i830_info), - INTEL_I845G_IDS(&i845g_info), - INTEL_I85X_IDS(&i85x_info), - INTEL_I865G_IDS(&i865g_info), - INTEL_I915G_IDS(&i915g_info), - INTEL_I915GM_IDS(&i915gm_info), - INTEL_I945G_IDS(&i945g_info), - INTEL_I945GM_IDS(&i945gm_info), - INTEL_I965G_IDS(&i965g_info), - INTEL_G33_IDS(&g33_info), - INTEL_I965GM_IDS(&i965gm_info), - INTEL_GM45_IDS(&gm45_info), - INTEL_G45_IDS(&g45_info), - INTEL_PINEVIEW_G_IDS(&pnv_g_info), - INTEL_PINEVIEW_M_IDS(&pnv_m_info), - INTEL_IRONLAKE_D_IDS(&ilk_d_info), - INTEL_IRONLAKE_M_IDS(&ilk_m_info), - INTEL_SNB_D_GT1_IDS(&snb_d_gt1_info), - INTEL_SNB_D_GT2_IDS(&snb_d_gt2_info), - INTEL_SNB_M_GT1_IDS(&snb_m_gt1_info), - INTEL_SNB_M_GT2_IDS(&snb_m_gt2_info), - INTEL_IVB_Q_IDS(&ivb_q_info), /* must be first IVB */ - INTEL_IVB_M_GT1_IDS(&ivb_m_gt1_info), - INTEL_IVB_M_GT2_IDS(&ivb_m_gt2_info), - INTEL_IVB_D_GT1_IDS(&ivb_d_gt1_info), - INTEL_IVB_D_GT2_IDS(&ivb_d_gt2_info), - INTEL_HSW_GT1_IDS(&hsw_gt1_info), - INTEL_HSW_GT2_IDS(&hsw_gt2_info), - INTEL_HSW_GT3_IDS(&hsw_gt3_info), - INTEL_VLV_IDS(&vlv_info), - INTEL_BDW_GT1_IDS(&bdw_gt1_info), - INTEL_BDW_GT2_IDS(&bdw_gt2_info), - INTEL_BDW_GT3_IDS(&bdw_gt3_info), - INTEL_BDW_RSVD_IDS(&bdw_rsvd_info), - INTEL_CHV_IDS(&chv_info), - INTEL_SKL_GT1_IDS(&skl_gt1_info), - INTEL_SKL_GT2_IDS(&skl_gt2_info), - INTEL_SKL_GT3_IDS(&skl_gt3_info), - INTEL_SKL_GT4_IDS(&skl_gt4_info), - INTEL_BXT_IDS(&bxt_info), - INTEL_GLK_IDS(&glk_info), - INTEL_KBL_GT1_IDS(&kbl_gt1_info), - INTEL_KBL_GT2_IDS(&kbl_gt2_info), - INTEL_KBL_GT3_IDS(&kbl_gt3_info), - INTEL_KBL_GT4_IDS(&kbl_gt3_info), - INTEL_AML_KBL_GT2_IDS(&kbl_gt2_info), - INTEL_CFL_S_GT1_IDS(&cfl_gt1_info), - INTEL_CFL_S_GT2_IDS(&cfl_gt2_info), - INTEL_CFL_H_GT1_IDS(&cfl_gt1_info), - INTEL_CFL_H_GT2_IDS(&cfl_gt2_info), - INTEL_CFL_U_GT2_IDS(&cfl_gt2_info), - INTEL_CFL_U_GT3_IDS(&cfl_gt3_info), - INTEL_WHL_U_GT1_IDS(&cfl_gt1_info), - INTEL_WHL_U_GT2_IDS(&cfl_gt2_info), - INTEL_AML_CFL_GT2_IDS(&cfl_gt2_info), - INTEL_WHL_U_GT3_IDS(&cfl_gt3_info), - INTEL_CML_GT1_IDS(&cml_gt1_info), - INTEL_CML_GT2_IDS(&cml_gt2_info), - INTEL_CML_U_GT1_IDS(&cml_gt1_info), - INTEL_CML_U_GT2_IDS(&cml_gt2_info), - INTEL_ICL_11_IDS(&icl_info), - INTEL_EHL_IDS(&ehl_info), - INTEL_JSL_IDS(&jsl_info), - INTEL_TGL_12_IDS(&tgl_info), - INTEL_RKL_IDS(&rkl_info), - INTEL_ADLS_IDS(&adl_s_info), - INTEL_ADLP_IDS(&adl_p_info), - INTEL_ADLN_IDS(&adl_p_info), - INTEL_DG1_IDS(&dg1_info), - INTEL_RPLS_IDS(&adl_s_info), - INTEL_RPLP_IDS(&adl_p_info), - INTEL_DG2_IDS(&dg2_info), - INTEL_ATS_M_IDS(&ats_m_info), - INTEL_MTL_IDS(&mtl_info), + INTEL_I830_IDS(INTEL_VGA_DEVICE, &i830_info), + INTEL_I845G_IDS(INTEL_VGA_DEVICE, &i845g_info), + INTEL_I85X_IDS(INTEL_VGA_DEVICE, &i85x_info), + INTEL_I865G_IDS(INTEL_VGA_DEVICE, &i865g_info), + INTEL_I915G_IDS(INTEL_VGA_DEVICE, &i915g_info), + INTEL_I915GM_IDS(INTEL_VGA_DEVICE, &i915gm_info), + INTEL_I945G_IDS(INTEL_VGA_DEVICE, &i945g_info), + INTEL_I945GM_IDS(INTEL_VGA_DEVICE, &i945gm_info), + INTEL_I965G_IDS(INTEL_VGA_DEVICE, &i965g_info), + INTEL_G33_IDS(INTEL_VGA_DEVICE, &g33_info), + INTEL_I965GM_IDS(INTEL_VGA_DEVICE, &i965gm_info), + INTEL_GM45_IDS(INTEL_VGA_DEVICE, &gm45_info), + INTEL_G45_IDS(INTEL_VGA_DEVICE, &g45_info), + INTEL_PNV_G_IDS(INTEL_VGA_DEVICE, &pnv_g_info), + INTEL_PNV_M_IDS(INTEL_VGA_DEVICE, &pnv_m_info), + INTEL_ILK_D_IDS(INTEL_VGA_DEVICE, &ilk_d_info), + INTEL_ILK_M_IDS(INTEL_VGA_DEVICE, &ilk_m_info), + INTEL_SNB_D_GT1_IDS(INTEL_VGA_DEVICE, &snb_d_gt1_info), + INTEL_SNB_D_GT2_IDS(INTEL_VGA_DEVICE, &snb_d_gt2_info), + INTEL_SNB_M_GT1_IDS(INTEL_VGA_DEVICE, &snb_m_gt1_info), + INTEL_SNB_M_GT2_IDS(INTEL_VGA_DEVICE, &snb_m_gt2_info), + INTEL_IVB_Q_IDS(INTEL_VGA_DEVICE, &ivb_q_info), /* must be first IVB */ + INTEL_IVB_M_GT1_IDS(INTEL_VGA_DEVICE, &ivb_m_gt1_info), + INTEL_IVB_M_GT2_IDS(INTEL_VGA_DEVICE, &ivb_m_gt2_info), + INTEL_IVB_D_GT1_IDS(INTEL_VGA_DEVICE, &ivb_d_gt1_info), + INTEL_IVB_D_GT2_IDS(INTEL_VGA_DEVICE, &ivb_d_gt2_info), + INTEL_HSW_GT1_IDS(INTEL_VGA_DEVICE, &hsw_gt1_info), + INTEL_HSW_GT2_IDS(INTEL_VGA_DEVICE, &hsw_gt2_info), + INTEL_HSW_GT3_IDS(INTEL_VGA_DEVICE, &hsw_gt3_info), + INTEL_VLV_IDS(INTEL_VGA_DEVICE, &vlv_info), + INTEL_BDW_GT1_IDS(INTEL_VGA_DEVICE, &bdw_gt1_info), + INTEL_BDW_GT2_IDS(INTEL_VGA_DEVICE, &bdw_gt2_info), + INTEL_BDW_GT3_IDS(INTEL_VGA_DEVICE, &bdw_gt3_info), + INTEL_BDW_RSVD_IDS(INTEL_VGA_DEVICE, &bdw_rsvd_info), + INTEL_CHV_IDS(INTEL_VGA_DEVICE, &chv_info), + INTEL_SKL_GT1_IDS(INTEL_VGA_DEVICE, &skl_gt1_info), + INTEL_SKL_GT2_IDS(INTEL_VGA_DEVICE, &skl_gt2_info), + INTEL_SKL_GT3_IDS(INTEL_VGA_DEVICE, &skl_gt3_info), + INTEL_SKL_GT4_IDS(INTEL_VGA_DEVICE, &skl_gt4_info), + INTEL_BXT_IDS(INTEL_VGA_DEVICE, &bxt_info), + INTEL_GLK_IDS(INTEL_VGA_DEVICE, &glk_info), + INTEL_KBL_GT1_IDS(INTEL_VGA_DEVICE, &kbl_gt1_info), + INTEL_KBL_GT2_IDS(INTEL_VGA_DEVICE, &kbl_gt2_info), + INTEL_KBL_GT3_IDS(INTEL_VGA_DEVICE, &kbl_gt3_info), + INTEL_KBL_GT4_IDS(INTEL_VGA_DEVICE, &kbl_gt3_info), + INTEL_AML_KBL_GT2_IDS(INTEL_VGA_DEVICE, &kbl_gt2_info), + INTEL_CFL_S_GT1_IDS(INTEL_VGA_DEVICE, &cfl_gt1_info), + INTEL_CFL_S_GT2_IDS(INTEL_VGA_DEVICE, &cfl_gt2_info), + INTEL_CFL_H_GT1_IDS(INTEL_VGA_DEVICE, &cfl_gt1_info), + INTEL_CFL_H_GT2_IDS(INTEL_VGA_DEVICE, &cfl_gt2_info), + INTEL_CFL_U_GT2_IDS(INTEL_VGA_DEVICE, &cfl_gt2_info), + INTEL_CFL_U_GT3_IDS(INTEL_VGA_DEVICE, &cfl_gt3_info), + INTEL_WHL_U_GT1_IDS(INTEL_VGA_DEVICE, &cfl_gt1_info), + INTEL_WHL_U_GT2_IDS(INTEL_VGA_DEVICE, &cfl_gt2_info), + INTEL_AML_CFL_GT2_IDS(INTEL_VGA_DEVICE, &cfl_gt2_info), + INTEL_WHL_U_GT3_IDS(INTEL_VGA_DEVICE, &cfl_gt3_info), + INTEL_CML_GT1_IDS(INTEL_VGA_DEVICE, &cml_gt1_info), + INTEL_CML_GT2_IDS(INTEL_VGA_DEVICE, &cml_gt2_info), + INTEL_CML_U_GT1_IDS(INTEL_VGA_DEVICE, &cml_gt1_info), + INTEL_CML_U_GT2_IDS(INTEL_VGA_DEVICE, &cml_gt2_info), + INTEL_ICL_IDS(INTEL_VGA_DEVICE, &icl_info), + INTEL_EHL_IDS(INTEL_VGA_DEVICE, &ehl_info), + INTEL_JSL_IDS(INTEL_VGA_DEVICE, &jsl_info), + INTEL_TGL_IDS(INTEL_VGA_DEVICE, &tgl_info), + INTEL_RKL_IDS(INTEL_VGA_DEVICE, &rkl_info), + INTEL_ADLS_IDS(INTEL_VGA_DEVICE, &adl_s_info), + INTEL_ADLP_IDS(INTEL_VGA_DEVICE, &adl_p_info), + INTEL_ADLN_IDS(INTEL_VGA_DEVICE, &adl_p_info), + INTEL_DG1_IDS(INTEL_VGA_DEVICE, &dg1_info), + INTEL_RPLS_IDS(INTEL_VGA_DEVICE, &adl_s_info), + INTEL_RPLU_IDS(INTEL_VGA_DEVICE, &adl_p_info), + INTEL_RPLP_IDS(INTEL_VGA_DEVICE, &adl_p_info), + INTEL_DG2_IDS(INTEL_VGA_DEVICE, &dg2_info), + INTEL_ATS_M_IDS(INTEL_VGA_DEVICE, &ats_m_info), + INTEL_MTL_IDS(INTEL_VGA_DEVICE, &mtl_info), {} }; MODULE_DEVICE_TABLE(pci, pciidlist); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e22a82a5ddd7..8e4478194d11 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -668,7 +668,7 @@ #define _DPLL_A 0x6014 #define _DPLL_B 0x6018 #define _CHV_DPLL_C 0x6030 -#define DPLL(pipe) _MMIO_BASE_PIPE3(DISPLAY_MMIO_BASE(dev_priv), \ +#define DPLL(dev_priv, pipe) _MMIO_BASE_PIPE3(DISPLAY_MMIO_BASE(dev_priv), \ (pipe), _DPLL_A, _DPLL_B, _CHV_DPLL_C) #define VGA0 _MMIO(0x6000) @@ -768,7 +768,7 @@ #define _DPLL_A_MD 0x601c #define _DPLL_B_MD 0x6020 #define _CHV_DPLL_C_MD 0x603c -#define DPLL_MD(pipe) _MMIO_BASE_PIPE3(DISPLAY_MMIO_BASE(dev_priv), \ +#define DPLL_MD(dev_priv, pipe) _MMIO_BASE_PIPE3(DISPLAY_MMIO_BASE(dev_priv), \ (pipe), _DPLL_A_MD, _DPLL_B_MD, _CHV_DPLL_C_MD) /* @@ -1069,87 +1069,6 @@ * Display engine regs */ -/* Pipe A CRC regs */ -#define _PIPE_CRC_CTL_A 0x60050 -#define PIPE_CRC_ENABLE REG_BIT(31) -/* skl+ source selection */ -#define PIPE_CRC_SOURCE_MASK_SKL REG_GENMASK(30, 28) -#define PIPE_CRC_SOURCE_PLANE_1_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 0) -#define PIPE_CRC_SOURCE_PLANE_2_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 2) -#define PIPE_CRC_SOURCE_DMUX_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 4) -#define PIPE_CRC_SOURCE_PLANE_3_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 6) -#define PIPE_CRC_SOURCE_PLANE_4_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 7) -#define PIPE_CRC_SOURCE_PLANE_5_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 5) -#define PIPE_CRC_SOURCE_PLANE_6_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 3) -#define PIPE_CRC_SOURCE_PLANE_7_SKL REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_SKL, 1) -/* ivb+ source selection */ -#define PIPE_CRC_SOURCE_MASK_IVB REG_GENMASK(30, 29) -#define PIPE_CRC_SOURCE_PRIMARY_IVB REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_IVB, 0) -#define PIPE_CRC_SOURCE_SPRITE_IVB REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_IVB, 1) -#define PIPE_CRC_SOURCE_PF_IVB REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_IVB, 2) -/* ilk+ source selection */ -#define PIPE_CRC_SOURCE_MASK_ILK REG_GENMASK(30, 28) -#define PIPE_CRC_SOURCE_PRIMARY_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 0) -#define PIPE_CRC_SOURCE_SPRITE_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 1) -#define PIPE_CRC_SOURCE_PIPE_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 2) -/* embedded DP port on the north display block */ -#define PIPE_CRC_SOURCE_PORT_A_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 4) -#define PIPE_CRC_SOURCE_FDI_ILK REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_ILK, 5) -/* vlv source selection */ -#define PIPE_CRC_SOURCE_MASK_VLV REG_GENMASK(30, 27) -#define PIPE_CRC_SOURCE_PIPE_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 0) -#define PIPE_CRC_SOURCE_HDMIB_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 1) -#define PIPE_CRC_SOURCE_HDMIC_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 2) -/* with DP port the pipe source is invalid */ -#define PIPE_CRC_SOURCE_DP_D_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 3) -#define PIPE_CRC_SOURCE_DP_B_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 6) -#define PIPE_CRC_SOURCE_DP_C_VLV REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_VLV, 7) -/* gen3+ source selection */ -#define PIPE_CRC_SOURCE_MASK_I9XX REG_GENMASK(30, 28) -#define PIPE_CRC_SOURCE_PIPE_I9XX REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 0) -#define PIPE_CRC_SOURCE_SDVOB_I9XX REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 1) -#define PIPE_CRC_SOURCE_SDVOC_I9XX REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 2) -/* with DP/TV port the pipe source is invalid */ -#define PIPE_CRC_SOURCE_DP_D_G4X REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 3) -#define PIPE_CRC_SOURCE_TV_PRE REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 4) -#define PIPE_CRC_SOURCE_TV_POST REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 5) -#define PIPE_CRC_SOURCE_DP_B_G4X REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 6) -#define PIPE_CRC_SOURCE_DP_C_G4X REG_FIELD_PREP(PIPE_CRC_SOURCE_MASK_I9XX, 7) -/* gen2 doesn't have source selection bits */ -#define PIPE_CRC_INCLUDE_BORDER_I8XX REG_BIT(30) - -#define _PIPE_CRC_RES_1_A_IVB 0x60064 -#define _PIPE_CRC_RES_2_A_IVB 0x60068 -#define _PIPE_CRC_RES_3_A_IVB 0x6006c -#define _PIPE_CRC_RES_4_A_IVB 0x60070 -#define _PIPE_CRC_RES_5_A_IVB 0x60074 - -#define _PIPE_CRC_RES_RED_A 0x60060 -#define _PIPE_CRC_RES_GREEN_A 0x60064 -#define _PIPE_CRC_RES_BLUE_A 0x60068 -#define _PIPE_CRC_RES_RES1_A_I915 0x6006c -#define _PIPE_CRC_RES_RES2_A_G4X 0x60080 - -/* Pipe B CRC regs */ -#define _PIPE_CRC_RES_1_B_IVB 0x61064 -#define _PIPE_CRC_RES_2_B_IVB 0x61068 -#define _PIPE_CRC_RES_3_B_IVB 0x6106c -#define _PIPE_CRC_RES_4_B_IVB 0x61070 -#define _PIPE_CRC_RES_5_B_IVB 0x61074 - -#define PIPE_CRC_CTL(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_CTL_A) -#define PIPE_CRC_RES_1_IVB(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_RES_1_A_IVB) -#define PIPE_CRC_RES_2_IVB(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_RES_2_A_IVB) -#define PIPE_CRC_RES_3_IVB(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_RES_3_A_IVB) -#define PIPE_CRC_RES_4_IVB(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_RES_4_A_IVB) -#define PIPE_CRC_RES_5_IVB(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_RES_5_A_IVB) - -#define PIPE_CRC_RES_RED(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_RES_RED_A) -#define PIPE_CRC_RES_GREEN(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_RES_GREEN_A) -#define PIPE_CRC_RES_BLUE(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_RES_BLUE_A) -#define PIPE_CRC_RES_RES1_I915(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_RES_RES1_A_I915) -#define PIPE_CRC_RES_RES2_G4X(pipe) _MMIO_TRANS2(dev_priv, pipe, _PIPE_CRC_RES_RES2_A_G4X) - /* Pipe/transcoder A timing regs */ #define _TRANS_HTOTAL_A 0x60000 #define HTOTAL_MASK REG_GENMASK(31, 16) @@ -1217,116 +1136,16 @@ #define _TRANS_VSYNC_DSI1 0x6b814 #define _TRANS_VSYNCSHIFT_DSI1 0x6b828 -#define TRANS_HTOTAL(trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_HTOTAL_A) -#define TRANS_HBLANK(trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_HBLANK_A) -#define TRANS_HSYNC(trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_HSYNC_A) -#define TRANS_VTOTAL(trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VTOTAL_A) -#define TRANS_VBLANK(trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VBLANK_A) -#define TRANS_VSYNC(trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VSYNC_A) -#define BCLRPAT(trans) _MMIO_TRANS2(dev_priv, (trans), _BCLRPAT_A) -#define TRANS_VSYNCSHIFT(trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VSYNCSHIFT_A) -#define PIPESRC(pipe) _MMIO_TRANS2(dev_priv, (pipe), _PIPEASRC) -#define TRANS_MULT(trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_MULT_A) - -/* VRR registers */ -#define _TRANS_VRR_CTL_A 0x60420 -#define _TRANS_VRR_CTL_B 0x61420 -#define _TRANS_VRR_CTL_C 0x62420 -#define _TRANS_VRR_CTL_D 0x63420 -#define TRANS_VRR_CTL(trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_CTL_A) -#define VRR_CTL_VRR_ENABLE REG_BIT(31) -#define VRR_CTL_IGN_MAX_SHIFT REG_BIT(30) -#define VRR_CTL_FLIP_LINE_EN REG_BIT(29) -#define VRR_CTL_PIPELINE_FULL_MASK REG_GENMASK(10, 3) -#define VRR_CTL_PIPELINE_FULL(x) REG_FIELD_PREP(VRR_CTL_PIPELINE_FULL_MASK, (x)) -#define VRR_CTL_PIPELINE_FULL_OVERRIDE REG_BIT(0) -#define XELPD_VRR_CTL_VRR_GUARDBAND_MASK REG_GENMASK(15, 0) -#define XELPD_VRR_CTL_VRR_GUARDBAND(x) REG_FIELD_PREP(XELPD_VRR_CTL_VRR_GUARDBAND_MASK, (x)) - -#define _TRANS_VRR_VMAX_A 0x60424 -#define _TRANS_VRR_VMAX_B 0x61424 -#define _TRANS_VRR_VMAX_C 0x62424 -#define _TRANS_VRR_VMAX_D 0x63424 -#define TRANS_VRR_VMAX(trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_VMAX_A) -#define VRR_VMAX_MASK REG_GENMASK(19, 0) - -#define _TRANS_VRR_VMIN_A 0x60434 -#define _TRANS_VRR_VMIN_B 0x61434 -#define _TRANS_VRR_VMIN_C 0x62434 -#define _TRANS_VRR_VMIN_D 0x63434 -#define TRANS_VRR_VMIN(trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_VMIN_A) -#define VRR_VMIN_MASK REG_GENMASK(15, 0) - -#define _TRANS_VRR_VMAXSHIFT_A 0x60428 -#define _TRANS_VRR_VMAXSHIFT_B 0x61428 -#define _TRANS_VRR_VMAXSHIFT_C 0x62428 -#define _TRANS_VRR_VMAXSHIFT_D 0x63428 -#define TRANS_VRR_VMAXSHIFT(trans) _MMIO_TRANS2(dev_priv, trans, \ - _TRANS_VRR_VMAXSHIFT_A) -#define VRR_VMAXSHIFT_DEC_MASK REG_GENMASK(29, 16) -#define VRR_VMAXSHIFT_DEC REG_BIT(16) -#define VRR_VMAXSHIFT_INC_MASK REG_GENMASK(12, 0) - -#define _TRANS_VRR_STATUS_A 0x6042C -#define _TRANS_VRR_STATUS_B 0x6142C -#define _TRANS_VRR_STATUS_C 0x6242C -#define _TRANS_VRR_STATUS_D 0x6342C -#define TRANS_VRR_STATUS(trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_STATUS_A) -#define VRR_STATUS_VMAX_REACHED REG_BIT(31) -#define VRR_STATUS_NOFLIP_TILL_BNDR REG_BIT(30) -#define VRR_STATUS_FLIP_BEF_BNDR REG_BIT(29) -#define VRR_STATUS_NO_FLIP_FRAME REG_BIT(28) -#define VRR_STATUS_VRR_EN_LIVE REG_BIT(27) -#define VRR_STATUS_FLIPS_SERVICED REG_BIT(26) -#define VRR_STATUS_VBLANK_MASK REG_GENMASK(22, 20) -#define STATUS_FSM_IDLE REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 0) -#define STATUS_FSM_WAIT_TILL_FDB REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 1) -#define STATUS_FSM_WAIT_TILL_FS REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 2) -#define STATUS_FSM_WAIT_TILL_FLIP REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 3) -#define STATUS_FSM_PIPELINE_FILL REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 4) -#define STATUS_FSM_ACTIVE REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 5) -#define STATUS_FSM_LEGACY_VBLANK REG_FIELD_PREP(VRR_STATUS_VBLANK_MASK, 6) - -#define _TRANS_VRR_VTOTAL_PREV_A 0x60480 -#define _TRANS_VRR_VTOTAL_PREV_B 0x61480 -#define _TRANS_VRR_VTOTAL_PREV_C 0x62480 -#define _TRANS_VRR_VTOTAL_PREV_D 0x63480 -#define TRANS_VRR_VTOTAL_PREV(trans) _MMIO_TRANS2(dev_priv, trans, \ - _TRANS_VRR_VTOTAL_PREV_A) -#define VRR_VTOTAL_FLIP_BEFR_BNDR REG_BIT(31) -#define VRR_VTOTAL_FLIP_AFTER_BNDR REG_BIT(30) -#define VRR_VTOTAL_FLIP_AFTER_DBLBUF REG_BIT(29) -#define VRR_VTOTAL_PREV_FRAME_MASK REG_GENMASK(19, 0) - -#define _TRANS_VRR_FLIPLINE_A 0x60438 -#define _TRANS_VRR_FLIPLINE_B 0x61438 -#define _TRANS_VRR_FLIPLINE_C 0x62438 -#define _TRANS_VRR_FLIPLINE_D 0x63438 -#define TRANS_VRR_FLIPLINE(trans) _MMIO_TRANS2(dev_priv, trans, \ - _TRANS_VRR_FLIPLINE_A) -#define VRR_FLIPLINE_MASK REG_GENMASK(19, 0) - -#define _TRANS_VRR_STATUS2_A 0x6043C -#define _TRANS_VRR_STATUS2_B 0x6143C -#define _TRANS_VRR_STATUS2_C 0x6243C -#define _TRANS_VRR_STATUS2_D 0x6343C -#define TRANS_VRR_STATUS2(trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_STATUS2_A) -#define VRR_STATUS2_VERT_LN_CNT_MASK REG_GENMASK(19, 0) - -#define _TRANS_PUSH_A 0x60A70 -#define _TRANS_PUSH_B 0x61A70 -#define _TRANS_PUSH_C 0x62A70 -#define _TRANS_PUSH_D 0x63A70 -#define TRANS_PUSH(trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_PUSH_A) -#define TRANS_PUSH_EN REG_BIT(31) -#define TRANS_PUSH_SEND REG_BIT(30) - -#define _TRANS_VRR_VSYNC_A 0x60078 -#define TRANS_VRR_VSYNC(trans) _MMIO_TRANS2(dev_priv, trans, _TRANS_VRR_VSYNC_A) -#define VRR_VSYNC_END_MASK REG_GENMASK(28, 16) -#define VRR_VSYNC_END(vsync_end) REG_FIELD_PREP(VRR_VSYNC_END_MASK, (vsync_end)) -#define VRR_VSYNC_START_MASK REG_GENMASK(12, 0) -#define VRR_VSYNC_START(vsync_start) REG_FIELD_PREP(VRR_VSYNC_START_MASK, (vsync_start)) +#define TRANS_HTOTAL(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_HTOTAL_A) +#define TRANS_HBLANK(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_HBLANK_A) +#define TRANS_HSYNC(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_HSYNC_A) +#define TRANS_VTOTAL(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VTOTAL_A) +#define TRANS_VBLANK(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VBLANK_A) +#define TRANS_VSYNC(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VSYNC_A) +#define BCLRPAT(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _BCLRPAT_A) +#define TRANS_VSYNCSHIFT(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_VSYNCSHIFT_A) +#define PIPESRC(dev_priv, pipe) _MMIO_TRANS2(dev_priv, (pipe), _PIPEASRC) +#define TRANS_MULT(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_MULT_A) /* VGA port control */ #define ADPA _MMIO(0x61100) @@ -1378,7 +1197,7 @@ /* Hotplug control (945+ only) */ -#define PORT_HOTPLUG_EN _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61110) +#define PORT_HOTPLUG_EN(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61110) #define PORTB_HOTPLUG_INT_EN (1 << 29) #define PORTC_HOTPLUG_INT_EN (1 << 28) #define PORTD_HOTPLUG_INT_EN (1 << 27) @@ -1408,7 +1227,7 @@ #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) -#define PORT_HOTPLUG_STAT _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61114) +#define PORT_HOTPLUG_STAT(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61114) /* HDMI/DP bits are g4x+ */ #define PORTD_HOTPLUG_LIVE_STATUS_G4X (1 << 27) #define PORTC_HOTPLUG_LIVE_STATUS_G4X (1 << 28) @@ -1479,7 +1298,7 @@ #define PORT_DFT_I9XX _MMIO(0x61150) #define DC_BALANCE_RESET (1 << 25) -#define PORT_DFT2_G4X _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61154) +#define PORT_DFT2_G4X(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61154) #define DC_BALANCE_RESET_VLV (1 << 31) #define PIPE_SCRAMBLE_RESET_MASK ((1 << 14) | (0x3 << 0)) #define PIPE_C_SCRAMBLE_RESET REG_BIT(14) /* chv */ @@ -1588,7 +1407,7 @@ #define VIDEO_DIP_ENABLE_AS_ADL REG_BIT(23) /* Panel fitting */ -#define PFIT_CONTROL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61230) +#define PFIT_CONTROL(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61230) #define PFIT_ENABLE REG_BIT(31) #define PFIT_PIPE_MASK REG_GENMASK(30, 29) /* 965+ */ #define PFIT_PIPE(pipe) REG_FIELD_PREP(PFIT_PIPE_MASK, (pipe)) @@ -1609,7 +1428,7 @@ #define PFIT_HORIZ_AUTO_SCALE REG_BIT(5) /* pre-965 */ #define PFIT_PANEL_8TO6_DITHER_ENABLE REG_BIT(3) /* pre-965 */ -#define PFIT_PGM_RATIOS _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61234) +#define PFIT_PGM_RATIOS(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61234) #define PFIT_VERT_SCALE_MASK REG_GENMASK(31, 20) /* pre-965 */ #define PFIT_VERT_SCALE(x) REG_FIELD_PREP(PFIT_VERT_SCALE_MASK, (x)) #define PFIT_HORIZ_SCALE_MASK REG_GENMASK(15, 4) /* pre-965 */ @@ -1617,7 +1436,7 @@ #define PFIT_VERT_SCALE_MASK_965 REG_GENMASK(28, 16) /* 965+ */ #define PFIT_HORIZ_SCALE_MASK_965 REG_GENMASK(12, 0) /* 965+ */ -#define PFIT_AUTO_RATIOS _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61238) +#define PFIT_AUTO_RATIOS(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61238) #define PCH_GTC_CTL _MMIO(0xe7000) #define PCH_GTC_ENABLE (1 << 31) @@ -1762,8 +1581,6 @@ #define PIPE_LINK_M_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_LINK_M_G4X, _PIPEB_LINK_M_G4X) #define PIPE_LINK_N_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_LINK_N_G4X, _PIPEB_LINK_N_G4X) -/* Display & cursor control */ - /* Pipe A */ #define _PIPEADSL 0x70000 #define PIPEDSL_CURR_FIELD REG_BIT(31) /* ctg+ */ @@ -1878,18 +1695,14 @@ #define PIPESTAT_INT_ENABLE_MASK 0x7fff0000 #define PIPESTAT_INT_STATUS_MASK 0x0000ffff -#define TRANSCONF(trans) _MMIO_PIPE2(dev_priv, (trans), _TRANSACONF) -#define PIPEDSL(pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEADSL) -#define PIPEFRAME(pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEAFRAMEHIGH) -#define PIPEFRAMEPIXEL(pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEAFRAMEPIXEL) -#define PIPESTAT(pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEASTAT) - -#define _PIPEAGCMAX 0x70010 -#define _PIPEBGCMAX 0x71010 -#define PIPEGCMAX(pipe, i) _MMIO_PIPE2(dev_priv, pipe, _PIPEAGCMAX + (i) * 4) /* u1.16 */ +#define TRANSCONF(dev_priv, trans) _MMIO_PIPE2(dev_priv, (trans), _TRANSACONF) +#define PIPEDSL(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEADSL) +#define PIPEFRAME(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEAFRAMEHIGH) +#define PIPEFRAMEPIXEL(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEAFRAMEPIXEL) +#define PIPESTAT(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEASTAT) #define _PIPE_ARB_CTL_A 0x70028 /* icl+ */ -#define PIPE_ARB_CTL(pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPE_ARB_CTL_A) +#define PIPE_ARB_CTL(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPE_ARB_CTL_A) #define PIPE_ARB_USE_PROG_SLOTS REG_BIT(13) #define _PIPE_MISC_A 0x70030 @@ -1933,7 +1746,7 @@ #define PIPE_MISC2(pipe) _MMIO_PIPE(pipe, _PIPE_MISC2_A, _PIPE_MISC2_B) #define _ICL_PIPE_A_STATUS 0x70058 -#define ICL_PIPESTATUS(pipe) _MMIO_PIPE2(dev_priv, pipe, _ICL_PIPE_A_STATUS) +#define ICL_PIPESTATUS(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _ICL_PIPE_A_STATUS) #define PIPE_STATUS_UNDERRUN REG_BIT(31) #define PIPE_STATUS_SOFT_UNDERRUN_XELPD REG_BIT(28) #define PIPE_STATUS_HARD_UNDERRUN_XELPD REG_BIT(27) @@ -1990,7 +1803,7 @@ #define SPRITEA_INVALID_GTT_STATUS REG_BIT(1) #define PLANEA_INVALID_GTT_STATUS REG_BIT(0) -#define DSPARB _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70030) +#define DSPARB(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70030) #define DSPARB_CSTART_MASK (0x7f << 7) #define DSPARB_CSTART_SHIFT 7 #define DSPARB_BSTART_MASK (0x7f) @@ -2025,7 +1838,7 @@ #define DSPARB_SPRITEF_MASK_VLV (0xff << 8) /* pnv/gen4/g4x/vlv/chv */ -#define DSPFW1 _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70034) +#define DSPFW1(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70034) #define DSPFW_SR_SHIFT 23 #define DSPFW_SR_MASK (0x1ff << 23) #define DSPFW_CURSORB_SHIFT 16 @@ -2036,7 +1849,7 @@ #define DSPFW_PLANEA_SHIFT 0 #define DSPFW_PLANEA_MASK (0x7f << 0) #define DSPFW_PLANEA_MASK_VLV (0xff << 0) /* vlv/chv */ -#define DSPFW2 _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70038) +#define DSPFW2(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70038) #define DSPFW_FBC_SR_EN (1 << 31) /* g4x */ #define DSPFW_FBC_SR_SHIFT 28 #define DSPFW_FBC_SR_MASK (0x7 << 28) /* g4x */ @@ -2052,7 +1865,7 @@ #define DSPFW_SPRITEA_SHIFT 0 #define DSPFW_SPRITEA_MASK (0x7f << 0) /* g4x */ #define DSPFW_SPRITEA_MASK_VLV (0xff << 0) /* vlv/chv */ -#define DSPFW3 _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x7003c) +#define DSPFW3(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x7003c) #define DSPFW_HPLL_SR_EN (1 << 31) #define PINEVIEW_SELF_REFRESH_EN (1 << 30) #define DSPFW_CURSOR_SR_SHIFT 24 @@ -2263,146 +2076,10 @@ /* GM45+ just has to be different */ #define _PIPEA_FRMCOUNT_G4X 0x70040 #define _PIPEA_FLIPCOUNT_G4X 0x70044 -#define PIPE_FRMCOUNT_G4X(pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEA_FRMCOUNT_G4X) -#define PIPE_FLIPCOUNT_G4X(pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEA_FLIPCOUNT_G4X) - -/* Cursor A & B regs */ -#define _CURACNTR 0x70080 -/* Old style CUR*CNTR flags (desktop 8xx) */ -#define CURSOR_ENABLE REG_BIT(31) -#define CURSOR_PIPE_GAMMA_ENABLE REG_BIT(30) -#define CURSOR_STRIDE_MASK REG_GENMASK(29, 28) -#define CURSOR_STRIDE(stride) REG_FIELD_PREP(CURSOR_STRIDE_MASK, ffs(stride) - 9) /* 256,512,1k,2k */ -#define CURSOR_FORMAT_MASK REG_GENMASK(26, 24) -#define CURSOR_FORMAT_2C REG_FIELD_PREP(CURSOR_FORMAT_MASK, 0) -#define CURSOR_FORMAT_3C REG_FIELD_PREP(CURSOR_FORMAT_MASK, 1) -#define CURSOR_FORMAT_4C REG_FIELD_PREP(CURSOR_FORMAT_MASK, 2) -#define CURSOR_FORMAT_ARGB REG_FIELD_PREP(CURSOR_FORMAT_MASK, 4) -#define CURSOR_FORMAT_XRGB REG_FIELD_PREP(CURSOR_FORMAT_MASK, 5) -/* New style CUR*CNTR flags */ -#define MCURSOR_ARB_SLOTS_MASK REG_GENMASK(30, 28) /* icl+ */ -#define MCURSOR_ARB_SLOTS(x) REG_FIELD_PREP(MCURSOR_ARB_SLOTS_MASK, (x)) /* icl+ */ -#define MCURSOR_PIPE_SEL_MASK REG_GENMASK(29, 28) -#define MCURSOR_PIPE_SEL(pipe) REG_FIELD_PREP(MCURSOR_PIPE_SEL_MASK, (pipe)) -#define MCURSOR_PIPE_GAMMA_ENABLE REG_BIT(26) -#define MCURSOR_PIPE_CSC_ENABLE REG_BIT(24) /* ilk+ */ -#define MCURSOR_ROTATE_180 REG_BIT(15) -#define MCURSOR_TRICKLE_FEED_DISABLE REG_BIT(14) -#define MCURSOR_MODE_MASK 0x27 -#define MCURSOR_MODE_DISABLE 0x00 -#define MCURSOR_MODE_128_32B_AX 0x02 -#define MCURSOR_MODE_256_32B_AX 0x03 -#define MCURSOR_MODE_64_2B 0x04 -#define MCURSOR_MODE_64_32B_AX 0x07 -#define MCURSOR_MODE_128_ARGB_AX (0x20 | MCURSOR_MODE_128_32B_AX) -#define MCURSOR_MODE_256_ARGB_AX (0x20 | MCURSOR_MODE_256_32B_AX) -#define MCURSOR_MODE_64_ARGB_AX (0x20 | MCURSOR_MODE_64_32B_AX) -#define _CURABASE 0x70084 -#define _CURAPOS 0x70088 -#define _CURAPOS_ERLY_TPT 0x7008c -#define CURSOR_POS_Y_SIGN REG_BIT(31) -#define CURSOR_POS_Y_MASK REG_GENMASK(30, 16) -#define CURSOR_POS_Y(y) REG_FIELD_PREP(CURSOR_POS_Y_MASK, (y)) -#define CURSOR_POS_X_SIGN REG_BIT(15) -#define CURSOR_POS_X_MASK REG_GENMASK(14, 0) -#define CURSOR_POS_X(x) REG_FIELD_PREP(CURSOR_POS_X_MASK, (x)) -#define _CURASIZE 0x700a0 /* 845/865 */ -#define CURSOR_HEIGHT_MASK REG_GENMASK(21, 12) -#define CURSOR_HEIGHT(h) REG_FIELD_PREP(CURSOR_HEIGHT_MASK, (h)) -#define CURSOR_WIDTH_MASK REG_GENMASK(9, 0) -#define CURSOR_WIDTH(w) REG_FIELD_PREP(CURSOR_WIDTH_MASK, (w)) -#define _CUR_FBC_CTL_A 0x700a0 /* ivb+ */ -#define CUR_FBC_EN REG_BIT(31) -#define CUR_FBC_HEIGHT_MASK REG_GENMASK(7, 0) -#define CUR_FBC_HEIGHT(h) REG_FIELD_PREP(CUR_FBC_HEIGHT_MASK, (h)) -#define _CUR_CHICKEN_A 0x700a4 /* mtl+ */ -#define _CURASURFLIVE 0x700ac /* g4x+ */ -#define _CURBCNTR 0x700c0 -#define _CURBBASE 0x700c4 -#define _CURBPOS 0x700c8 - -#define _CURBCNTR_IVB 0x71080 -#define _CURBBASE_IVB 0x71084 -#define _CURBPOS_IVB 0x71088 - -#define CURCNTR(pipe) _MMIO_CURSOR2(dev_priv, pipe, _CURACNTR) -#define CURBASE(pipe) _MMIO_CURSOR2(dev_priv, pipe, _CURABASE) -#define CURPOS(pipe) _MMIO_CURSOR2(dev_priv, pipe, _CURAPOS) -#define CURPOS_ERLY_TPT(pipe) _MMIO_CURSOR2(dev_priv, pipe, _CURAPOS_ERLY_TPT) -#define CURSIZE(pipe) _MMIO_CURSOR2(dev_priv, pipe, _CURASIZE) -#define CUR_FBC_CTL(pipe) _MMIO_CURSOR2(dev_priv, pipe, _CUR_FBC_CTL_A) -#define CUR_CHICKEN(pipe) _MMIO_CURSOR2(dev_priv, pipe, _CUR_CHICKEN_A) -#define CURSURFLIVE(pipe) _MMIO_CURSOR2(dev_priv, pipe, _CURASURFLIVE) - -/* Display A control */ -#define _DSPAADDR_VLV 0x7017C /* vlv/chv */ -#define _DSPACNTR 0x70180 -#define DISP_ENABLE REG_BIT(31) -#define DISP_PIPE_GAMMA_ENABLE REG_BIT(30) -#define DISP_FORMAT_MASK REG_GENMASK(29, 26) -#define DISP_FORMAT_8BPP REG_FIELD_PREP(DISP_FORMAT_MASK, 2) -#define DISP_FORMAT_BGRA555 REG_FIELD_PREP(DISP_FORMAT_MASK, 3) -#define DISP_FORMAT_BGRX555 REG_FIELD_PREP(DISP_FORMAT_MASK, 4) -#define DISP_FORMAT_BGRX565 REG_FIELD_PREP(DISP_FORMAT_MASK, 5) -#define DISP_FORMAT_BGRX888 REG_FIELD_PREP(DISP_FORMAT_MASK, 6) -#define DISP_FORMAT_BGRA888 REG_FIELD_PREP(DISP_FORMAT_MASK, 7) -#define DISP_FORMAT_RGBX101010 REG_FIELD_PREP(DISP_FORMAT_MASK, 8) -#define DISP_FORMAT_RGBA101010 REG_FIELD_PREP(DISP_FORMAT_MASK, 9) -#define DISP_FORMAT_BGRX101010 REG_FIELD_PREP(DISP_FORMAT_MASK, 10) -#define DISP_FORMAT_BGRA101010 REG_FIELD_PREP(DISP_FORMAT_MASK, 11) -#define DISP_FORMAT_RGBX161616 REG_FIELD_PREP(DISP_FORMAT_MASK, 12) -#define DISP_FORMAT_RGBX888 REG_FIELD_PREP(DISP_FORMAT_MASK, 14) -#define DISP_FORMAT_RGBA888 REG_FIELD_PREP(DISP_FORMAT_MASK, 15) -#define DISP_STEREO_ENABLE REG_BIT(25) -#define DISP_PIPE_CSC_ENABLE REG_BIT(24) /* ilk+ */ -#define DISP_PIPE_SEL_MASK REG_GENMASK(25, 24) -#define DISP_PIPE_SEL(pipe) REG_FIELD_PREP(DISP_PIPE_SEL_MASK, (pipe)) -#define DISP_SRC_KEY_ENABLE REG_BIT(22) -#define DISP_LINE_DOUBLE REG_BIT(20) -#define DISP_STEREO_POLARITY_SECOND REG_BIT(18) -#define DISP_ALPHA_PREMULTIPLY REG_BIT(16) /* CHV pipe B */ -#define DISP_ROTATE_180 REG_BIT(15) -#define DISP_TRICKLE_FEED_DISABLE REG_BIT(14) /* g4x+ */ -#define DISP_TILED REG_BIT(10) -#define DISP_ASYNC_FLIP REG_BIT(9) /* g4x+ */ -#define DISP_MIRROR REG_BIT(8) /* CHV pipe B */ -#define _DSPAADDR 0x70184 -#define _DSPASTRIDE 0x70188 -#define _DSPAPOS 0x7018C /* reserved */ -#define DISP_POS_Y_MASK REG_GENMASK(31, 16) -#define DISP_POS_Y(y) REG_FIELD_PREP(DISP_POS_Y_MASK, (y)) -#define DISP_POS_X_MASK REG_GENMASK(15, 0) -#define DISP_POS_X(x) REG_FIELD_PREP(DISP_POS_X_MASK, (x)) -#define _DSPASIZE 0x70190 -#define DISP_HEIGHT_MASK REG_GENMASK(31, 16) -#define DISP_HEIGHT(h) REG_FIELD_PREP(DISP_HEIGHT_MASK, (h)) -#define DISP_WIDTH_MASK REG_GENMASK(15, 0) -#define DISP_WIDTH(w) REG_FIELD_PREP(DISP_WIDTH_MASK, (w)) -#define _DSPASURF 0x7019C /* 965+ only */ -#define DISP_ADDR_MASK REG_GENMASK(31, 12) -#define _DSPATILEOFF 0x701A4 /* 965+ only */ -#define DISP_OFFSET_Y_MASK REG_GENMASK(31, 16) -#define DISP_OFFSET_Y(y) REG_FIELD_PREP(DISP_OFFSET_Y_MASK, (y)) -#define DISP_OFFSET_X_MASK REG_GENMASK(15, 0) -#define DISP_OFFSET_X(x) REG_FIELD_PREP(DISP_OFFSET_X_MASK, (x)) -#define _DSPAOFFSET 0x701A4 /* HSW */ -#define _DSPASURFLIVE 0x701AC -#define _DSPAGAMC 0x701E0 - -#define DSPADDR_VLV(plane) _MMIO_PIPE2(dev_priv, plane, _DSPAADDR_VLV) -#define DSPCNTR(plane) _MMIO_PIPE2(dev_priv, plane, _DSPACNTR) -#define DSPADDR(plane) _MMIO_PIPE2(dev_priv, plane, _DSPAADDR) -#define DSPSTRIDE(plane) _MMIO_PIPE2(dev_priv, plane, _DSPASTRIDE) -#define DSPPOS(plane) _MMIO_PIPE2(dev_priv, plane, _DSPAPOS) -#define DSPSIZE(plane) _MMIO_PIPE2(dev_priv, plane, _DSPASIZE) -#define DSPSURF(plane) _MMIO_PIPE2(dev_priv, plane, _DSPASURF) -#define DSPTILEOFF(plane) _MMIO_PIPE2(dev_priv, plane, _DSPATILEOFF) -#define DSPLINOFF(plane) DSPADDR(plane) -#define DSPOFFSET(plane) _MMIO_PIPE2(dev_priv, plane, _DSPAOFFSET) -#define DSPSURFLIVE(plane) _MMIO_PIPE2(dev_priv, plane, _DSPASURFLIVE) -#define DSPGAMC(plane, i) _MMIO_PIPE2(dev_priv, plane, _DSPAGAMC + (5 - (i)) * 4) /* plane C only, 6 x u0.8 */ - -/* CHV pipe B blender and primary plane */ +#define PIPE_FRMCOUNT_G4X(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEA_FRMCOUNT_G4X) +#define PIPE_FLIPCOUNT_G4X(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _PIPEA_FLIPCOUNT_G4X) + +/* CHV pipe B blender */ #define _CHV_BLEND_A 0x60a00 #define CHV_BLEND_MASK REG_GENMASK(31, 30) #define CHV_BLEND_LEGACY REG_FIELD_PREP(CHV_BLEND_MASK, 0) @@ -2412,26 +2089,9 @@ #define CHV_CANVAS_RED_MASK REG_GENMASK(29, 20) #define CHV_CANVAS_GREEN_MASK REG_GENMASK(19, 10) #define CHV_CANVAS_BLUE_MASK REG_GENMASK(9, 0) -#define _PRIMPOS_A 0x60a08 -#define PRIM_POS_Y_MASK REG_GENMASK(31, 16) -#define PRIM_POS_Y(y) REG_FIELD_PREP(PRIM_POS_Y_MASK, (y)) -#define PRIM_POS_X_MASK REG_GENMASK(15, 0) -#define PRIM_POS_X(x) REG_FIELD_PREP(PRIM_POS_X_MASK, (x)) -#define _PRIMSIZE_A 0x60a0c -#define PRIM_HEIGHT_MASK REG_GENMASK(31, 16) -#define PRIM_HEIGHT(h) REG_FIELD_PREP(PRIM_HEIGHT_MASK, (h)) -#define PRIM_WIDTH_MASK REG_GENMASK(15, 0) -#define PRIM_WIDTH(w) REG_FIELD_PREP(PRIM_WIDTH_MASK, (w)) -#define _PRIMCNSTALPHA_A 0x60a10 -#define PRIM_CONST_ALPHA_ENABLE REG_BIT(31) -#define PRIM_CONST_ALPHA_MASK REG_GENMASK(7, 0) -#define PRIM_CONST_ALPHA(alpha) REG_FIELD_PREP(PRIM_CONST_ALPHA_MASK, (alpha)) - -#define CHV_BLEND(pipe) _MMIO_TRANS2(dev_priv, pipe, _CHV_BLEND_A) -#define CHV_CANVAS(pipe) _MMIO_TRANS2(dev_priv, pipe, _CHV_CANVAS_A) -#define PRIMPOS(plane) _MMIO_TRANS2(dev_priv, plane, _PRIMPOS_A) -#define PRIMSIZE(plane) _MMIO_TRANS2(dev_priv, plane, _PRIMSIZE_A) -#define PRIMCNSTALPHA(plane) _MMIO_TRANS2(dev_priv, plane, _PRIMCNSTALPHA_A) + +#define CHV_BLEND(dev_priv, pipe) _MMIO_TRANS2(dev_priv, pipe, _CHV_BLEND_A) +#define CHV_CANVAS(dev_priv, pipe) _MMIO_TRANS2(dev_priv, pipe, _CHV_CANVAS_A) /* Display/Sprite base address macros */ #define DISP_BASEADDR_MASK (0xfffff000) @@ -2449,390 +2109,15 @@ * [10:1f] all * [30:32] all */ -#define SWF0(i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70410 + (i) * 4) -#define SWF1(i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x71410 + (i) * 4) -#define SWF3(i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x72414 + (i) * 4) +#define SWF0(dev_priv, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70410 + (i) * 4) +#define SWF1(dev_priv, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x71410 + (i) * 4) +#define SWF3(dev_priv, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x72414 + (i) * 4) #define SWF_ILK(i) _MMIO(0x4F000 + (i) * 4) -/* Pipe B */ -#define _PIPEBDSL (DISPLAY_MMIO_BASE(dev_priv) + 0x71000) -#define _TRANSBCONF (DISPLAY_MMIO_BASE(dev_priv) + 0x71008) -#define _PIPEBSTAT (DISPLAY_MMIO_BASE(dev_priv) + 0x71024) -#define _PIPEBFRAMEHIGH 0x71040 -#define _PIPEBFRAMEPIXEL 0x71044 -#define _PIPEB_FRMCOUNT_G4X (DISPLAY_MMIO_BASE(dev_priv) + 0x71040) -#define _PIPEB_FLIPCOUNT_G4X (DISPLAY_MMIO_BASE(dev_priv) + 0x71044) - - -/* Display B control */ -#define _DSPBCNTR (DISPLAY_MMIO_BASE(dev_priv) + 0x71180) -#define DISP_ALPHA_TRANS_ENABLE REG_BIT(15) -#define DISP_SPRITE_ABOVE_OVERLAY REG_BIT(0) -#define _DSPBADDR (DISPLAY_MMIO_BASE(dev_priv) + 0x71184) -#define _DSPBSTRIDE (DISPLAY_MMIO_BASE(dev_priv) + 0x71188) -#define _DSPBPOS (DISPLAY_MMIO_BASE(dev_priv) + 0x7118C) -#define _DSPBSIZE (DISPLAY_MMIO_BASE(dev_priv) + 0x71190) -#define _DSPBSURF (DISPLAY_MMIO_BASE(dev_priv) + 0x7119C) -#define _DSPBTILEOFF (DISPLAY_MMIO_BASE(dev_priv) + 0x711A4) -#define _DSPBOFFSET (DISPLAY_MMIO_BASE(dev_priv) + 0x711A4) -#define _DSPBSURFLIVE (DISPLAY_MMIO_BASE(dev_priv) + 0x711AC) - /* ICL DSI 0 and 1 */ #define _PIPEDSI0CONF 0x7b008 #define _PIPEDSI1CONF 0x7b808 -/* Skylake plane registers */ - -#define _PLANE_CTL_1_A 0x70180 -#define _PLANE_CTL_2_A 0x70280 -#define _PLANE_CTL_3_A 0x70380 -#define PLANE_CTL_ENABLE REG_BIT(31) -#define PLANE_CTL_ARB_SLOTS_MASK REG_GENMASK(30, 28) /* icl+ */ -#define PLANE_CTL_ARB_SLOTS(x) REG_FIELD_PREP(PLANE_CTL_ARB_SLOTS_MASK, (x)) /* icl+ */ -#define PLANE_CTL_PIPE_GAMMA_ENABLE REG_BIT(30) /* Pre-GLK */ -#define PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE REG_BIT(28) -/* - * ICL+ uses the same PLANE_CTL_FORMAT bits, but the field definition - * expanded to include bit 23 as well. However, the shift-24 based values - * correctly map to the same formats in ICL, as long as bit 23 is set to 0 - */ -#define PLANE_CTL_FORMAT_MASK_SKL REG_GENMASK(27, 24) /* pre-icl */ -#define PLANE_CTL_FORMAT_MASK_ICL REG_GENMASK(27, 23) /* icl+ */ -#define PLANE_CTL_FORMAT_YUV422 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 0) -#define PLANE_CTL_FORMAT_NV12 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 1) -#define PLANE_CTL_FORMAT_XRGB_2101010 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 2) -#define PLANE_CTL_FORMAT_P010 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 3) -#define PLANE_CTL_FORMAT_XRGB_8888 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 4) -#define PLANE_CTL_FORMAT_P012 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 5) -#define PLANE_CTL_FORMAT_XRGB_16161616F REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 6) -#define PLANE_CTL_FORMAT_P016 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 7) -#define PLANE_CTL_FORMAT_XYUV REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 8) -#define PLANE_CTL_FORMAT_INDEXED REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 12) -#define PLANE_CTL_FORMAT_RGB_565 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_SKL, 14) -#define PLANE_CTL_FORMAT_Y210 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 1) -#define PLANE_CTL_FORMAT_Y212 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 3) -#define PLANE_CTL_FORMAT_Y216 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 5) -#define PLANE_CTL_FORMAT_Y410 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 7) -#define PLANE_CTL_FORMAT_Y412 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 9) -#define PLANE_CTL_FORMAT_Y416 REG_FIELD_PREP(PLANE_CTL_FORMAT_MASK_ICL, 11) -#define PLANE_CTL_PIPE_CSC_ENABLE REG_BIT(23) /* Pre-GLK */ -#define PLANE_CTL_KEY_ENABLE_MASK REG_GENMASK(22, 21) -#define PLANE_CTL_KEY_ENABLE_SOURCE REG_FIELD_PREP(PLANE_CTL_KEY_ENABLE_MASK, 1) -#define PLANE_CTL_KEY_ENABLE_DESTINATION REG_FIELD_PREP(PLANE_CTL_KEY_ENABLE_MASK, 2) -#define PLANE_CTL_ORDER_RGBX REG_BIT(20) -#define PLANE_CTL_YUV420_Y_PLANE REG_BIT(19) -#define PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709 REG_BIT(18) -#define PLANE_CTL_YUV422_ORDER_MASK REG_GENMASK(17, 16) -#define PLANE_CTL_YUV422_ORDER_YUYV REG_FIELD_PREP(PLANE_CTL_YUV422_ORDER_MASK, 0) -#define PLANE_CTL_YUV422_ORDER_UYVY REG_FIELD_PREP(PLANE_CTL_YUV422_ORDER_MASK, 1) -#define PLANE_CTL_YUV422_ORDER_YVYU REG_FIELD_PREP(PLANE_CTL_YUV422_ORDER_MASK, 2) -#define PLANE_CTL_YUV422_ORDER_VYUY REG_FIELD_PREP(PLANE_CTL_YUV422_ORDER_MASK, 3) -#define PLANE_CTL_RENDER_DECOMPRESSION_ENABLE REG_BIT(15) -#define PLANE_CTL_TRICKLE_FEED_DISABLE REG_BIT(14) -#define PLANE_CTL_CLEAR_COLOR_DISABLE REG_BIT(13) /* TGL+ */ -#define PLANE_CTL_PLANE_GAMMA_DISABLE REG_BIT(13) /* Pre-GLK */ -#define PLANE_CTL_TILED_MASK REG_GENMASK(12, 10) -#define PLANE_CTL_TILED_LINEAR REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 0) -#define PLANE_CTL_TILED_X REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 1) -#define PLANE_CTL_TILED_Y REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 4) -#define PLANE_CTL_TILED_YF REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 5) -#define PLANE_CTL_TILED_4 REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 5) -#define PLANE_CTL_ASYNC_FLIP REG_BIT(9) -#define PLANE_CTL_FLIP_HORIZONTAL REG_BIT(8) -#define PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE REG_BIT(4) /* TGL+ */ -#define PLANE_CTL_ALPHA_MASK REG_GENMASK(5, 4) /* Pre-GLK */ -#define PLANE_CTL_ALPHA_DISABLE REG_FIELD_PREP(PLANE_CTL_ALPHA_MASK, 0) -#define PLANE_CTL_ALPHA_SW_PREMULTIPLY REG_FIELD_PREP(PLANE_CTL_ALPHA_MASK, 2) -#define PLANE_CTL_ALPHA_HW_PREMULTIPLY REG_FIELD_PREP(PLANE_CTL_ALPHA_MASK, 3) -#define PLANE_CTL_ROTATE_MASK REG_GENMASK(1, 0) -#define PLANE_CTL_ROTATE_0 REG_FIELD_PREP(PLANE_CTL_ROTATE_MASK, 0) -#define PLANE_CTL_ROTATE_90 REG_FIELD_PREP(PLANE_CTL_ROTATE_MASK, 1) -#define PLANE_CTL_ROTATE_180 REG_FIELD_PREP(PLANE_CTL_ROTATE_MASK, 2) -#define PLANE_CTL_ROTATE_270 REG_FIELD_PREP(PLANE_CTL_ROTATE_MASK, 3) -#define _PLANE_STRIDE_1_A 0x70188 -#define _PLANE_STRIDE_2_A 0x70288 -#define _PLANE_STRIDE_3_A 0x70388 -#define PLANE_STRIDE__MASK REG_GENMASK(11, 0) -#define PLANE_STRIDE_(stride) REG_FIELD_PREP(PLANE_STRIDE__MASK, (stride)) -#define _PLANE_POS_1_A 0x7018c -#define _PLANE_POS_2_A 0x7028c -#define _PLANE_POS_3_A 0x7038c -#define PLANE_POS_Y_MASK REG_GENMASK(31, 16) -#define PLANE_POS_Y(y) REG_FIELD_PREP(PLANE_POS_Y_MASK, (y)) -#define PLANE_POS_X_MASK REG_GENMASK(15, 0) -#define PLANE_POS_X(x) REG_FIELD_PREP(PLANE_POS_X_MASK, (x)) -#define _PLANE_SIZE_1_A 0x70190 -#define _PLANE_SIZE_2_A 0x70290 -#define _PLANE_SIZE_3_A 0x70390 -#define PLANE_HEIGHT_MASK REG_GENMASK(31, 16) -#define PLANE_HEIGHT(h) REG_FIELD_PREP(PLANE_HEIGHT_MASK, (h)) -#define PLANE_WIDTH_MASK REG_GENMASK(15, 0) -#define PLANE_WIDTH(w) REG_FIELD_PREP(PLANE_WIDTH_MASK, (w)) -#define _PLANE_SURF_1_A 0x7019c -#define _PLANE_SURF_2_A 0x7029c -#define _PLANE_SURF_3_A 0x7039c -#define PLANE_SURF_ADDR_MASK REG_GENMASK(31, 12) -#define PLANE_SURF_DECRYPT REG_BIT(2) -#define _PLANE_OFFSET_1_A 0x701a4 -#define _PLANE_OFFSET_2_A 0x702a4 -#define _PLANE_OFFSET_3_A 0x703a4 -#define PLANE_OFFSET_Y_MASK REG_GENMASK(31, 16) -#define PLANE_OFFSET_Y(y) REG_FIELD_PREP(PLANE_OFFSET_Y_MASK, (y)) -#define PLANE_OFFSET_X_MASK REG_GENMASK(15, 0) -#define PLANE_OFFSET_X(x) REG_FIELD_PREP(PLANE_OFFSET_X_MASK, (x)) -#define _PLANE_KEYVAL_1_A 0x70194 -#define _PLANE_KEYVAL_2_A 0x70294 -#define _PLANE_KEYMSK_1_A 0x70198 -#define _PLANE_KEYMSK_2_A 0x70298 -#define PLANE_KEYMSK_ALPHA_ENABLE REG_BIT(31) -#define _PLANE_KEYMAX_1_A 0x701a0 -#define _PLANE_KEYMAX_2_A 0x702a0 -#define PLANE_KEYMAX_ALPHA_MASK REG_GENMASK(31, 24) -#define PLANE_KEYMAX_ALPHA(a) REG_FIELD_PREP(PLANE_KEYMAX_ALPHA_MASK, (a)) -#define _PLANE_SURFLIVE_1_A 0x701ac -#define _PLANE_SURFLIVE_2_A 0x702ac -#define _PLANE_CC_VAL_1_A 0x701b4 -#define _PLANE_CC_VAL_2_A 0x702b4 -#define _PLANE_AUX_DIST_1_A 0x701c0 -#define PLANE_AUX_DISTANCE_MASK REG_GENMASK(31, 12) -#define PLANE_AUX_STRIDE_MASK REG_GENMASK(11, 0) -#define PLANE_AUX_STRIDE(stride) REG_FIELD_PREP(PLANE_AUX_STRIDE_MASK, (stride)) -#define _PLANE_AUX_DIST_2_A 0x702c0 -#define _PLANE_AUX_OFFSET_1_A 0x701c4 -#define _PLANE_AUX_OFFSET_2_A 0x702c4 -#define _PLANE_CUS_CTL_1_A 0x701c8 -#define _PLANE_CUS_CTL_2_A 0x702c8 -#define PLANE_CUS_ENABLE REG_BIT(31) -#define PLANE_CUS_Y_PLANE_MASK REG_BIT(30) -#define PLANE_CUS_Y_PLANE_4_RKL REG_FIELD_PREP(PLANE_CUS_Y_PLANE_MASK, 0) -#define PLANE_CUS_Y_PLANE_5_RKL REG_FIELD_PREP(PLANE_CUS_Y_PLANE_MASK, 1) -#define PLANE_CUS_Y_PLANE_6_ICL REG_FIELD_PREP(PLANE_CUS_Y_PLANE_MASK, 0) -#define PLANE_CUS_Y_PLANE_7_ICL REG_FIELD_PREP(PLANE_CUS_Y_PLANE_MASK, 1) -#define PLANE_CUS_HPHASE_SIGN_NEGATIVE REG_BIT(19) -#define PLANE_CUS_HPHASE_MASK REG_GENMASK(17, 16) -#define PLANE_CUS_HPHASE_0 REG_FIELD_PREP(PLANE_CUS_HPHASE_MASK, 0) -#define PLANE_CUS_HPHASE_0_25 REG_FIELD_PREP(PLANE_CUS_HPHASE_MASK, 1) -#define PLANE_CUS_HPHASE_0_5 REG_FIELD_PREP(PLANE_CUS_HPHASE_MASK, 2) -#define PLANE_CUS_VPHASE_SIGN_NEGATIVE REG_BIT(15) -#define PLANE_CUS_VPHASE_MASK REG_GENMASK(13, 12) -#define PLANE_CUS_VPHASE_0 REG_FIELD_PREP(PLANE_CUS_VPHASE_MASK, 0) -#define PLANE_CUS_VPHASE_0_25 REG_FIELD_PREP(PLANE_CUS_VPHASE_MASK, 1) -#define PLANE_CUS_VPHASE_0_5 REG_FIELD_PREP(PLANE_CUS_VPHASE_MASK, 2) -#define _PLANE_COLOR_CTL_1_A 0x701CC /* GLK+ */ -#define _PLANE_COLOR_CTL_2_A 0x702CC /* GLK+ */ -#define _PLANE_COLOR_CTL_3_A 0x703CC /* GLK+ */ -#define PLANE_COLOR_PIPE_GAMMA_ENABLE REG_BIT(30) /* Pre-ICL */ -#define PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE REG_BIT(28) -#define PLANE_COLOR_PIPE_CSC_ENABLE REG_BIT(23) /* Pre-ICL */ -#define PLANE_COLOR_PLANE_CSC_ENABLE REG_BIT(21) /* ICL+ */ -#define PLANE_COLOR_INPUT_CSC_ENABLE REG_BIT(20) /* ICL+ */ -#define PLANE_COLOR_CSC_MODE_MASK REG_GENMASK(19, 17) -#define PLANE_COLOR_CSC_MODE_BYPASS REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 0) -#define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 1) -#define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 2) -#define PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 3) -#define PLANE_COLOR_CSC_MODE_RGB709_TO_RGB2020 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 4) -#define PLANE_COLOR_PLANE_GAMMA_DISABLE REG_BIT(13) -#define PLANE_COLOR_ALPHA_MASK REG_GENMASK(5, 4) -#define PLANE_COLOR_ALPHA_DISABLE REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 0) -#define PLANE_COLOR_ALPHA_SW_PREMULTIPLY REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 2) -#define PLANE_COLOR_ALPHA_HW_PREMULTIPLY REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 3) -#define _PLANE_CHICKEN_1_A 0x7026C /* tgl+ */ -#define _PLANE_CHICKEN_2_A 0x7036C /* tgl+ */ -#define PLANE_CHICKEN_DISABLE_DPT REG_BIT(19) /* mtl+ */ -#define _PLANE_BUF_CFG_1_A 0x7027c -#define _PLANE_BUF_CFG_2_A 0x7037c -/* skl+: 10 bits, icl+ 11 bits, adlp+ 12 bits */ -#define PLANE_BUF_END_MASK REG_GENMASK(27, 16) -#define PLANE_BUF_END(end) REG_FIELD_PREP(PLANE_BUF_END_MASK, (end)) -#define PLANE_BUF_START_MASK REG_GENMASK(11, 0) -#define PLANE_BUF_START(start) REG_FIELD_PREP(PLANE_BUF_START_MASK, (start)) -#define _PLANE_NV12_BUF_CFG_1_A 0x70278 -#define _PLANE_NV12_BUF_CFG_2_A 0x70378 - -#define _PLANE_CC_VAL_1_B 0x711b4 -#define _PLANE_CC_VAL_2_B 0x712b4 -#define _PLANE_CC_VAL_1(pipe, dw) (_PIPE(pipe, _PLANE_CC_VAL_1_A, _PLANE_CC_VAL_1_B) + (dw) * 4) -#define _PLANE_CC_VAL_2(pipe, dw) (_PIPE(pipe, _PLANE_CC_VAL_2_A, _PLANE_CC_VAL_2_B) + (dw) * 4) -#define PLANE_CC_VAL(pipe, plane, dw) \ - _MMIO_PLANE((plane), _PLANE_CC_VAL_1((pipe), (dw)), _PLANE_CC_VAL_2((pipe), (dw))) - -/* Input CSC Register Definitions */ -#define _PLANE_INPUT_CSC_RY_GY_1_A 0x701E0 -#define _PLANE_INPUT_CSC_RY_GY_2_A 0x702E0 - -#define _PLANE_INPUT_CSC_RY_GY_1_B 0x711E0 -#define _PLANE_INPUT_CSC_RY_GY_2_B 0x712E0 - -#define _PLANE_INPUT_CSC_RY_GY_1(pipe) \ - _PIPE(pipe, _PLANE_INPUT_CSC_RY_GY_1_A, \ - _PLANE_INPUT_CSC_RY_GY_1_B) -#define _PLANE_INPUT_CSC_RY_GY_2(pipe) \ - _PIPE(pipe, _PLANE_INPUT_CSC_RY_GY_2_A, \ - _PLANE_INPUT_CSC_RY_GY_2_B) - -#define PLANE_INPUT_CSC_COEFF(pipe, plane, index) \ - _MMIO_PLANE(plane, _PLANE_INPUT_CSC_RY_GY_1(pipe) + (index) * 4, \ - _PLANE_INPUT_CSC_RY_GY_2(pipe) + (index) * 4) - -#define _PLANE_INPUT_CSC_PREOFF_HI_1_A 0x701F8 -#define _PLANE_INPUT_CSC_PREOFF_HI_2_A 0x702F8 - -#define _PLANE_INPUT_CSC_PREOFF_HI_1_B 0x711F8 -#define _PLANE_INPUT_CSC_PREOFF_HI_2_B 0x712F8 - -#define _PLANE_INPUT_CSC_PREOFF_HI_1(pipe) \ - _PIPE(pipe, _PLANE_INPUT_CSC_PREOFF_HI_1_A, \ - _PLANE_INPUT_CSC_PREOFF_HI_1_B) -#define _PLANE_INPUT_CSC_PREOFF_HI_2(pipe) \ - _PIPE(pipe, _PLANE_INPUT_CSC_PREOFF_HI_2_A, \ - _PLANE_INPUT_CSC_PREOFF_HI_2_B) -#define PLANE_INPUT_CSC_PREOFF(pipe, plane, index) \ - _MMIO_PLANE(plane, _PLANE_INPUT_CSC_PREOFF_HI_1(pipe) + (index) * 4, \ - _PLANE_INPUT_CSC_PREOFF_HI_2(pipe) + (index) * 4) - -#define _PLANE_INPUT_CSC_POSTOFF_HI_1_A 0x70204 -#define _PLANE_INPUT_CSC_POSTOFF_HI_2_A 0x70304 - -#define _PLANE_INPUT_CSC_POSTOFF_HI_1_B 0x71204 -#define _PLANE_INPUT_CSC_POSTOFF_HI_2_B 0x71304 - -#define _PLANE_INPUT_CSC_POSTOFF_HI_1(pipe) \ - _PIPE(pipe, _PLANE_INPUT_CSC_POSTOFF_HI_1_A, \ - _PLANE_INPUT_CSC_POSTOFF_HI_1_B) -#define _PLANE_INPUT_CSC_POSTOFF_HI_2(pipe) \ - _PIPE(pipe, _PLANE_INPUT_CSC_POSTOFF_HI_2_A, \ - _PLANE_INPUT_CSC_POSTOFF_HI_2_B) -#define PLANE_INPUT_CSC_POSTOFF(pipe, plane, index) \ - _MMIO_PLANE(plane, _PLANE_INPUT_CSC_POSTOFF_HI_1(pipe) + (index) * 4, \ - _PLANE_INPUT_CSC_POSTOFF_HI_2(pipe) + (index) * 4) - -#define _PLANE_CTL_1_B 0x71180 -#define _PLANE_CTL_2_B 0x71280 -#define _PLANE_CTL_3_B 0x71380 -#define _PLANE_CTL_1(pipe) _PIPE(pipe, _PLANE_CTL_1_A, _PLANE_CTL_1_B) -#define _PLANE_CTL_2(pipe) _PIPE(pipe, _PLANE_CTL_2_A, _PLANE_CTL_2_B) -#define _PLANE_CTL_3(pipe) _PIPE(pipe, _PLANE_CTL_3_A, _PLANE_CTL_3_B) -#define PLANE_CTL(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_CTL_1(pipe), _PLANE_CTL_2(pipe)) - -#define _PLANE_STRIDE_1_B 0x71188 -#define _PLANE_STRIDE_2_B 0x71288 -#define _PLANE_STRIDE_3_B 0x71388 -#define _PLANE_STRIDE_1(pipe) \ - _PIPE(pipe, _PLANE_STRIDE_1_A, _PLANE_STRIDE_1_B) -#define _PLANE_STRIDE_2(pipe) \ - _PIPE(pipe, _PLANE_STRIDE_2_A, _PLANE_STRIDE_2_B) -#define _PLANE_STRIDE_3(pipe) \ - _PIPE(pipe, _PLANE_STRIDE_3_A, _PLANE_STRIDE_3_B) -#define PLANE_STRIDE(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_STRIDE_1(pipe), _PLANE_STRIDE_2(pipe)) - -#define _PLANE_POS_1_B 0x7118c -#define _PLANE_POS_2_B 0x7128c -#define _PLANE_POS_3_B 0x7138c -#define _PLANE_POS_1(pipe) _PIPE(pipe, _PLANE_POS_1_A, _PLANE_POS_1_B) -#define _PLANE_POS_2(pipe) _PIPE(pipe, _PLANE_POS_2_A, _PLANE_POS_2_B) -#define _PLANE_POS_3(pipe) _PIPE(pipe, _PLANE_POS_3_A, _PLANE_POS_3_B) -#define PLANE_POS(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_POS_1(pipe), _PLANE_POS_2(pipe)) - -#define _PLANE_SIZE_1_B 0x71190 -#define _PLANE_SIZE_2_B 0x71290 -#define _PLANE_SIZE_3_B 0x71390 -#define _PLANE_SIZE_1(pipe) _PIPE(pipe, _PLANE_SIZE_1_A, _PLANE_SIZE_1_B) -#define _PLANE_SIZE_2(pipe) _PIPE(pipe, _PLANE_SIZE_2_A, _PLANE_SIZE_2_B) -#define _PLANE_SIZE_3(pipe) _PIPE(pipe, _PLANE_SIZE_3_A, _PLANE_SIZE_3_B) -#define PLANE_SIZE(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_SIZE_1(pipe), _PLANE_SIZE_2(pipe)) - -#define _PLANE_SURF_1_B 0x7119c -#define _PLANE_SURF_2_B 0x7129c -#define _PLANE_SURF_3_B 0x7139c -#define _PLANE_SURF_1(pipe) _PIPE(pipe, _PLANE_SURF_1_A, _PLANE_SURF_1_B) -#define _PLANE_SURF_2(pipe) _PIPE(pipe, _PLANE_SURF_2_A, _PLANE_SURF_2_B) -#define _PLANE_SURF_3(pipe) _PIPE(pipe, _PLANE_SURF_3_A, _PLANE_SURF_3_B) -#define PLANE_SURF(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_SURF_1(pipe), _PLANE_SURF_2(pipe)) - -#define _PLANE_OFFSET_1_B 0x711a4 -#define _PLANE_OFFSET_2_B 0x712a4 -#define _PLANE_OFFSET_1(pipe) _PIPE(pipe, _PLANE_OFFSET_1_A, _PLANE_OFFSET_1_B) -#define _PLANE_OFFSET_2(pipe) _PIPE(pipe, _PLANE_OFFSET_2_A, _PLANE_OFFSET_2_B) -#define PLANE_OFFSET(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_OFFSET_1(pipe), _PLANE_OFFSET_2(pipe)) - -#define _PLANE_KEYVAL_1_B 0x71194 -#define _PLANE_KEYVAL_2_B 0x71294 -#define _PLANE_KEYVAL_1(pipe) _PIPE(pipe, _PLANE_KEYVAL_1_A, _PLANE_KEYVAL_1_B) -#define _PLANE_KEYVAL_2(pipe) _PIPE(pipe, _PLANE_KEYVAL_2_A, _PLANE_KEYVAL_2_B) -#define PLANE_KEYVAL(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_KEYVAL_1(pipe), _PLANE_KEYVAL_2(pipe)) - -#define _PLANE_KEYMSK_1_B 0x71198 -#define _PLANE_KEYMSK_2_B 0x71298 -#define _PLANE_KEYMSK_1(pipe) _PIPE(pipe, _PLANE_KEYMSK_1_A, _PLANE_KEYMSK_1_B) -#define _PLANE_KEYMSK_2(pipe) _PIPE(pipe, _PLANE_KEYMSK_2_A, _PLANE_KEYMSK_2_B) -#define PLANE_KEYMSK(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_KEYMSK_1(pipe), _PLANE_KEYMSK_2(pipe)) - -#define _PLANE_KEYMAX_1_B 0x711a0 -#define _PLANE_KEYMAX_2_B 0x712a0 -#define _PLANE_KEYMAX_1(pipe) _PIPE(pipe, _PLANE_KEYMAX_1_A, _PLANE_KEYMAX_1_B) -#define _PLANE_KEYMAX_2(pipe) _PIPE(pipe, _PLANE_KEYMAX_2_A, _PLANE_KEYMAX_2_B) -#define PLANE_KEYMAX(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_KEYMAX_1(pipe), _PLANE_KEYMAX_2(pipe)) - -#define _PLANE_SURFLIVE_1_B 0x711ac -#define _PLANE_SURFLIVE_2_B 0x712ac -#define _PLANE_SURFLIVE_1(pipe) _PIPE(pipe, _PLANE_SURFLIVE_1_A, _PLANE_SURFLIVE_1_B) -#define _PLANE_SURFLIVE_2(pipe) _PIPE(pipe, _PLANE_SURFLIVE_2_A, _PLANE_SURFLIVE_2_B) -#define PLANE_SURFLIVE(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_SURFLIVE_1(pipe), _PLANE_SURFLIVE_2(pipe)) - -#define _PLANE_CHICKEN_1_B 0x7126c -#define _PLANE_CHICKEN_2_B 0x7136c -#define _PLANE_CHICKEN_1(pipe) _PIPE(pipe, _PLANE_CHICKEN_1_A, _PLANE_CHICKEN_1_B) -#define _PLANE_CHICKEN_2(pipe) _PIPE(pipe, _PLANE_CHICKEN_2_A, _PLANE_CHICKEN_2_B) -#define PLANE_CHICKEN(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_CHICKEN_1(pipe), _PLANE_CHICKEN_2(pipe)) - -#define _PLANE_AUX_DIST_1_B 0x711c0 -#define _PLANE_AUX_DIST_2_B 0x712c0 -#define _PLANE_AUX_DIST_1(pipe) \ - _PIPE(pipe, _PLANE_AUX_DIST_1_A, _PLANE_AUX_DIST_1_B) -#define _PLANE_AUX_DIST_2(pipe) \ - _PIPE(pipe, _PLANE_AUX_DIST_2_A, _PLANE_AUX_DIST_2_B) -#define PLANE_AUX_DIST(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_AUX_DIST_1(pipe), _PLANE_AUX_DIST_2(pipe)) - -#define _PLANE_AUX_OFFSET_1_B 0x711c4 -#define _PLANE_AUX_OFFSET_2_B 0x712c4 -#define _PLANE_AUX_OFFSET_1(pipe) \ - _PIPE(pipe, _PLANE_AUX_OFFSET_1_A, _PLANE_AUX_OFFSET_1_B) -#define _PLANE_AUX_OFFSET_2(pipe) \ - _PIPE(pipe, _PLANE_AUX_OFFSET_2_A, _PLANE_AUX_OFFSET_2_B) -#define PLANE_AUX_OFFSET(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_AUX_OFFSET_1(pipe), _PLANE_AUX_OFFSET_2(pipe)) - -#define _PLANE_CUS_CTL_1_B 0x711c8 -#define _PLANE_CUS_CTL_2_B 0x712c8 -#define _PLANE_CUS_CTL_1(pipe) \ - _PIPE(pipe, _PLANE_CUS_CTL_1_A, _PLANE_CUS_CTL_1_B) -#define _PLANE_CUS_CTL_2(pipe) \ - _PIPE(pipe, _PLANE_CUS_CTL_2_A, _PLANE_CUS_CTL_2_B) -#define PLANE_CUS_CTL(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_CUS_CTL_1(pipe), _PLANE_CUS_CTL_2(pipe)) - -#define _PLANE_COLOR_CTL_1_B 0x711CC -#define _PLANE_COLOR_CTL_2_B 0x712CC -#define _PLANE_COLOR_CTL_3_B 0x713CC -#define _PLANE_COLOR_CTL_1(pipe) \ - _PIPE(pipe, _PLANE_COLOR_CTL_1_A, _PLANE_COLOR_CTL_1_B) -#define _PLANE_COLOR_CTL_2(pipe) \ - _PIPE(pipe, _PLANE_COLOR_CTL_2_A, _PLANE_COLOR_CTL_2_B) -#define PLANE_COLOR_CTL(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_COLOR_CTL_1(pipe), _PLANE_COLOR_CTL_2(pipe)) /* VBIOS regs */ #define VGACNTRL _MMIO(0x71400) @@ -2890,14 +2175,14 @@ #define _PIPEB_LINK_M2 0x61048 #define _PIPEB_LINK_N2 0x6104c -#define PIPE_DATA_M1(tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_M1) -#define PIPE_DATA_N1(tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_N1) -#define PIPE_DATA_M2(tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_M2) -#define PIPE_DATA_N2(tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_N2) -#define PIPE_LINK_M1(tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_M1) -#define PIPE_LINK_N1(tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_N1) -#define PIPE_LINK_M2(tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_M2) -#define PIPE_LINK_N2(tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_N2) +#define PIPE_DATA_M1(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_M1) +#define PIPE_DATA_N1(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_N1) +#define PIPE_DATA_M2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_M2) +#define PIPE_DATA_N2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_DATA_N2) +#define PIPE_LINK_M1(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_M1) +#define PIPE_LINK_N1(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_N1) +#define PIPE_LINK_M2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_M2) +#define PIPE_LINK_N2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _PIPEA_LINK_N2) /* CPU panel fitter */ /* IVB+ has 3 fitters, 0 is 7x5 capable, the other two only 3x3 */ @@ -3449,6 +2734,7 @@ #define CHICKEN_MISC_2 _MMIO(0x42084) #define CHICKEN_MISC_DISABLE_DPT REG_BIT(30) /* adl,dg2 */ +#define BMG_DARB_HALF_BLK_END_BURST REG_BIT(27) #define KBL_ARB_FILL_SPARE_14 REG_BIT(14) #define KBL_ARB_FILL_SPARE_13 REG_BIT(13) #define GLK_CL2_PWR_DOWN REG_BIT(12) @@ -3519,6 +2805,7 @@ #define DP_FEC_BS_JITTER_WA REG_BIT(15) #define PSR2_VSC_ENABLE_PROG_HEADER REG_BIT(12) #define DP_DSC_INSERT_SF_AT_EOL_WA REG_BIT(4) +#define HDCP_LINE_REKEY_DISABLE REG_BIT(0) #define DISP_ARB_CTL _MMIO(0x45000) #define DISP_FBC_MEMORY_WAKE REG_BIT(31) @@ -3984,25 +3271,25 @@ #define _ICL_VIDEO_DIP_PPS_ECC_A 0x603D4 #define _ICL_VIDEO_DIP_PPS_ECC_B 0x613D4 -#define HSW_TVIDEO_DIP_CTL(trans) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_CTL_A) -#define HSW_TVIDEO_DIP_GCP(trans) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_GCP_A) -#define HSW_TVIDEO_DIP_AVI_DATA(trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_AVI_DATA_A + (i) * 4) -#define HSW_TVIDEO_DIP_VS_DATA(trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_VS_DATA_A + (i) * 4) -#define HSW_TVIDEO_DIP_SPD_DATA(trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_SPD_DATA_A + (i) * 4) -#define HSW_TVIDEO_DIP_GMP_DATA(trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_GMP_DATA_A + (i) * 4) -#define HSW_TVIDEO_DIP_VSC_DATA(trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_VSC_DATA_A + (i) * 4) -#define GLK_TVIDEO_DIP_DRM_DATA(trans, i) _MMIO_TRANS2(dev_priv, trans, _GLK_VIDEO_DIP_DRM_DATA_A + (i) * 4) -#define ICL_VIDEO_DIP_PPS_DATA(trans, i) _MMIO_TRANS2(dev_priv, trans, _ICL_VIDEO_DIP_PPS_DATA_A + (i) * 4) -#define ICL_VIDEO_DIP_PPS_ECC(trans, i) _MMIO_TRANS2(dev_priv, trans, _ICL_VIDEO_DIP_PPS_ECC_A + (i) * 4) +#define HSW_TVIDEO_DIP_CTL(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_CTL_A) +#define HSW_TVIDEO_DIP_GCP(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_GCP_A) +#define HSW_TVIDEO_DIP_AVI_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_AVI_DATA_A + (i) * 4) +#define HSW_TVIDEO_DIP_VS_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_VS_DATA_A + (i) * 4) +#define HSW_TVIDEO_DIP_SPD_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_SPD_DATA_A + (i) * 4) +#define HSW_TVIDEO_DIP_GMP_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_GMP_DATA_A + (i) * 4) +#define HSW_TVIDEO_DIP_VSC_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _HSW_VIDEO_DIP_VSC_DATA_A + (i) * 4) +#define GLK_TVIDEO_DIP_DRM_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _GLK_VIDEO_DIP_DRM_DATA_A + (i) * 4) +#define ICL_VIDEO_DIP_PPS_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _ICL_VIDEO_DIP_PPS_DATA_A + (i) * 4) +#define ICL_VIDEO_DIP_PPS_ECC(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans, _ICL_VIDEO_DIP_PPS_ECC_A + (i) * 4) /*ADLP and later: */ -#define ADL_TVIDEO_DIP_AS_SDP_DATA(trans, i) _MMIO_TRANS2(dev_priv, trans,\ +#define ADL_TVIDEO_DIP_AS_SDP_DATA(dev_priv, trans, i) _MMIO_TRANS2(dev_priv, trans,\ _ADL_VIDEO_DIP_AS_DATA_A + (i) * 4) #define _HSW_STEREO_3D_CTL_A 0x70020 #define S3D_ENABLE (1 << 31) #define _HSW_STEREO_3D_CTL_B 0x71020 -#define HSW_STEREO_3D_CTL(trans) _MMIO_PIPE2(dev_priv, trans, _HSW_STEREO_3D_CTL_A) +#define HSW_STEREO_3D_CTL(dev_priv, trans) _MMIO_PIPE2(dev_priv, trans, _HSW_STEREO_3D_CTL_A) #define _PCH_TRANS_HTOTAL_B 0xe1000 #define _PCH_TRANS_HBLANK_B 0xe1004 @@ -4108,35 +3395,9 @@ #define CNP_PWM_CGE_GATING_DISABLE (1 << 13) #define PCH_LP_PARTITION_LEVEL_DISABLE (1 << 12) -#define _PCH_DP_B 0xe4100 -#define PCH_DP_B _MMIO(_PCH_DP_B) -#define _PCH_DPB_AUX_CH_CTL 0xe4110 -#define _PCH_DPB_AUX_CH_DATA1 0xe4114 -#define _PCH_DPB_AUX_CH_DATA2 0xe4118 -#define _PCH_DPB_AUX_CH_DATA3 0xe411c -#define _PCH_DPB_AUX_CH_DATA4 0xe4120 -#define _PCH_DPB_AUX_CH_DATA5 0xe4124 - -#define _PCH_DP_C 0xe4200 -#define PCH_DP_C _MMIO(_PCH_DP_C) -#define _PCH_DPC_AUX_CH_CTL 0xe4210 -#define _PCH_DPC_AUX_CH_DATA1 0xe4214 -#define _PCH_DPC_AUX_CH_DATA2 0xe4218 -#define _PCH_DPC_AUX_CH_DATA3 0xe421c -#define _PCH_DPC_AUX_CH_DATA4 0xe4220 -#define _PCH_DPC_AUX_CH_DATA5 0xe4224 - -#define _PCH_DP_D 0xe4300 -#define PCH_DP_D _MMIO(_PCH_DP_D) -#define _PCH_DPD_AUX_CH_CTL 0xe4310 -#define _PCH_DPD_AUX_CH_DATA1 0xe4314 -#define _PCH_DPD_AUX_CH_DATA2 0xe4318 -#define _PCH_DPD_AUX_CH_DATA3 0xe431c -#define _PCH_DPD_AUX_CH_DATA4 0xe4320 -#define _PCH_DPD_AUX_CH_DATA5 0xe4324 - -#define PCH_DP_AUX_CH_CTL(aux_ch) _MMIO_PORT((aux_ch) - AUX_CH_B, _PCH_DPB_AUX_CH_CTL, _PCH_DPC_AUX_CH_CTL) -#define PCH_DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PORT((aux_ch) - AUX_CH_B, _PCH_DPB_AUX_CH_DATA1, _PCH_DPC_AUX_CH_DATA1) + (i) * 4) /* 5 registers */ +#define PCH_DP_B _MMIO(0xe4100) +#define PCH_DP_C _MMIO(0xe4200) +#define PCH_DP_D _MMIO(0xe4300) /* CPT */ #define _TRANS_DP_CTL_A 0xe0300 @@ -4488,7 +3749,7 @@ enum skl_power_gate { #define _TRANS_DDI_FUNC_CTL_EDP 0x6F400 #define _TRANS_DDI_FUNC_CTL_DSI0 0x6b400 #define _TRANS_DDI_FUNC_CTL_DSI1 0x6bc00 -#define TRANS_DDI_FUNC_CTL(tran) _MMIO_TRANS2(dev_priv, tran, _TRANS_DDI_FUNC_CTL_A) +#define TRANS_DDI_FUNC_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _TRANS_DDI_FUNC_CTL_A) #define TRANS_DDI_FUNC_ENABLE (1 << 31) /* Those bits are ignored by pipe EDP since it can only connect to DDI A */ @@ -4520,6 +3781,7 @@ enum skl_power_gate { #define TRANS_DDI_EDP_INPUT_B_ONOFF (5 << 12) #define TRANS_DDI_EDP_INPUT_C_ONOFF (6 << 12) #define TRANS_DDI_EDP_INPUT_D_ONOFF (7 << 12) +#define TRANS_DDI_HDCP_LINE_REKEY_DISABLE REG_BIT(12) #define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(11, 10) #define TRANS_DDI_MST_TRANSPORT_SELECT(trans) \ REG_FIELD_PREP(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, trans) @@ -4543,7 +3805,7 @@ enum skl_power_gate { #define _TRANS_DDI_FUNC_CTL2_EDP 0x6f404 #define _TRANS_DDI_FUNC_CTL2_DSI0 0x6b404 #define _TRANS_DDI_FUNC_CTL2_DSI1 0x6bc04 -#define TRANS_DDI_FUNC_CTL2(tran) _MMIO_TRANS2(dev_priv, tran, _TRANS_DDI_FUNC_CTL2_A) +#define TRANS_DDI_FUNC_CTL2(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _TRANS_DDI_FUNC_CTL2_A) #define PORT_SYNC_MODE_ENABLE REG_BIT(4) #define PORT_SYNC_MODE_MASTER_SELECT_MASK REG_GENMASK(2, 0) #define PORT_SYNC_MODE_MASTER_SELECT(x) REG_FIELD_PREP(PORT_SYNC_MODE_MASTER_SELECT_MASK, (x)) @@ -4556,7 +3818,7 @@ enum skl_power_gate { #define _DP_TP_CTL_B 0x64140 #define _TGL_DP_TP_CTL_A 0x60540 #define DP_TP_CTL(port) _MMIO_PORT(port, _DP_TP_CTL_A, _DP_TP_CTL_B) -#define TGL_DP_TP_CTL(tran) _MMIO_TRANS2(dev_priv, (tran), _TGL_DP_TP_CTL_A) +#define TGL_DP_TP_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, (tran), _TGL_DP_TP_CTL_A) #define DP_TP_CTL_ENABLE (1 << 31) #define DP_TP_CTL_FEC_ENABLE (1 << 30) #define DP_TP_CTL_MODE_SST (0 << 27) @@ -4582,7 +3844,7 @@ enum skl_power_gate { #define _DP_TP_STATUS_B 0x64144 #define _TGL_DP_TP_STATUS_A 0x60544 #define DP_TP_STATUS(port) _MMIO_PORT(port, _DP_TP_STATUS_A, _DP_TP_STATUS_B) -#define TGL_DP_TP_STATUS(tran) _MMIO_TRANS2(dev_priv, (tran), _TGL_DP_TP_STATUS_A) +#define TGL_DP_TP_STATUS(dev_priv, tran) _MMIO_TRANS2(dev_priv, (tran), _TGL_DP_TP_STATUS_A) #define DP_TP_STATUS_FEC_ENABLE_LIVE (1 << 28) #define DP_TP_STATUS_IDLE_DONE (1 << 25) #define DP_TP_STATUS_ACT_SENT (1 << 24) @@ -4763,14 +4025,14 @@ enum skl_power_gate { #define _TRANSB_MSA_MISC 0x61410 #define _TRANSC_MSA_MISC 0x62410 #define _TRANS_EDP_MSA_MISC 0x6f410 -#define TRANS_MSA_MISC(tran) _MMIO_TRANS2(dev_priv, tran, _TRANSA_MSA_MISC) +#define TRANS_MSA_MISC(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _TRANSA_MSA_MISC) /* See DP_MSA_MISC_* for the bit definitions */ #define _TRANS_A_SET_CONTEXT_LATENCY 0x6007C #define _TRANS_B_SET_CONTEXT_LATENCY 0x6107C #define _TRANS_C_SET_CONTEXT_LATENCY 0x6207C #define _TRANS_D_SET_CONTEXT_LATENCY 0x6307C -#define TRANS_SET_CONTEXT_LATENCY(tran) _MMIO_TRANS2(dev_priv, tran, _TRANS_A_SET_CONTEXT_LATENCY) +#define TRANS_SET_CONTEXT_LATENCY(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _TRANS_A_SET_CONTEXT_LATENCY) #define TRANS_SET_CONTEXT_LATENCY_MASK REG_GENMASK(15, 0) #define TRANS_SET_CONTEXT_LATENCY_VALUE(x) REG_FIELD_PREP(TRANS_SET_CONTEXT_LATENCY_MASK, (x)) @@ -5148,51 +4410,6 @@ enum skl_power_gate { #define WM_DBG_DISALLOW_MAXFIFO (1 << 1) #define WM_DBG_DISALLOW_SPRITE (1 << 2) -#define _MMIO_PLANE_GAMC(plane, i, a, b) _MMIO(_PIPE(plane, a, b) + (i) * 4) - -/* Plane CSC Registers */ -#define _PLANE_CSC_RY_GY_1_A 0x70210 -#define _PLANE_CSC_RY_GY_2_A 0x70310 - -#define _PLANE_CSC_RY_GY_1_B 0x71210 -#define _PLANE_CSC_RY_GY_2_B 0x71310 - -#define _PLANE_CSC_RY_GY_1(pipe) _PIPE(pipe, _PLANE_CSC_RY_GY_1_A, \ - _PLANE_CSC_RY_GY_1_B) -#define _PLANE_CSC_RY_GY_2(pipe) _PIPE(pipe, _PLANE_CSC_RY_GY_2_A, \ - _PLANE_CSC_RY_GY_2_B) -#define PLANE_CSC_COEFF(pipe, plane, index) _MMIO_PLANE(plane, \ - _PLANE_CSC_RY_GY_1(pipe) + (index) * 4, \ - _PLANE_CSC_RY_GY_2(pipe) + (index) * 4) - -#define _PLANE_CSC_PREOFF_HI_1_A 0x70228 -#define _PLANE_CSC_PREOFF_HI_2_A 0x70328 - -#define _PLANE_CSC_PREOFF_HI_1_B 0x71228 -#define _PLANE_CSC_PREOFF_HI_2_B 0x71328 - -#define _PLANE_CSC_PREOFF_HI_1(pipe) _PIPE(pipe, _PLANE_CSC_PREOFF_HI_1_A, \ - _PLANE_CSC_PREOFF_HI_1_B) -#define _PLANE_CSC_PREOFF_HI_2(pipe) _PIPE(pipe, _PLANE_CSC_PREOFF_HI_2_A, \ - _PLANE_CSC_PREOFF_HI_2_B) -#define PLANE_CSC_PREOFF(pipe, plane, index) _MMIO_PLANE(plane, _PLANE_CSC_PREOFF_HI_1(pipe) + \ - (index) * 4, _PLANE_CSC_PREOFF_HI_2(pipe) + \ - (index) * 4) - -#define _PLANE_CSC_POSTOFF_HI_1_A 0x70234 -#define _PLANE_CSC_POSTOFF_HI_2_A 0x70334 - -#define _PLANE_CSC_POSTOFF_HI_1_B 0x71234 -#define _PLANE_CSC_POSTOFF_HI_2_B 0x71334 - -#define _PLANE_CSC_POSTOFF_HI_1(pipe) _PIPE(pipe, _PLANE_CSC_POSTOFF_HI_1_A, \ - _PLANE_CSC_POSTOFF_HI_1_B) -#define _PLANE_CSC_POSTOFF_HI_2(pipe) _PIPE(pipe, _PLANE_CSC_POSTOFF_HI_2_A, \ - _PLANE_CSC_POSTOFF_HI_2_B) -#define PLANE_CSC_POSTOFF(pipe, plane, index) _MMIO_PLANE(plane, _PLANE_CSC_POSTOFF_HI_1(pipe) + \ - (index) * 4, _PLANE_CSC_POSTOFF_HI_2(pipe) + \ - (index) * 4) - /* Gen4+ Timestamp and Pipe Frame time stamp registers */ #define GEN4_TIMESTAMP _MMIO(0x2358) #define ILK_TIMESTAMP_HI _MMIO(0x70070) @@ -5297,7 +4514,7 @@ enum skl_power_gate { #define _MTL_CLKGATE_DIS_TRANS_A 0x604E8 #define _MTL_CLKGATE_DIS_TRANS_B 0x614E8 -#define MTL_CLKGATE_DIS_TRANS(trans) _MMIO_TRANS2(dev_priv, trans, _MTL_CLKGATE_DIS_TRANS_A) +#define MTL_CLKGATE_DIS_TRANS(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _MTL_CLKGATE_DIS_TRANS_A) #define MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS REG_BIT(7) #define MTL_MEM_SS_INFO_GLOBAL _MMIO(0x45700) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 81def10eb58f..f8373a461f17 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -40,21 +40,28 @@ static void intel_save_swf(struct drm_i915_private *dev_priv) /* Scratch space */ if (GRAPHICS_VER(dev_priv) == 2 && IS_MOBILE(dev_priv)) { for (i = 0; i < 7; i++) { - dev_priv->regfile.saveSWF0[i] = intel_de_read(dev_priv, SWF0(i)); - dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv, SWF1(i)); + dev_priv->regfile.saveSWF0[i] = intel_de_read(dev_priv, + SWF0(dev_priv, i)); + dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv, + SWF1(dev_priv, i)); } for (i = 0; i < 3; i++) - dev_priv->regfile.saveSWF3[i] = intel_de_read(dev_priv, SWF3(i)); + dev_priv->regfile.saveSWF3[i] = intel_de_read(dev_priv, + SWF3(dev_priv, i)); } else if (GRAPHICS_VER(dev_priv) == 2) { for (i = 0; i < 7; i++) - dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv, SWF1(i)); + dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv, + SWF1(dev_priv, i)); } else if (HAS_GMCH(dev_priv)) { for (i = 0; i < 16; i++) { - dev_priv->regfile.saveSWF0[i] = intel_de_read(dev_priv, SWF0(i)); - dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv, SWF1(i)); + dev_priv->regfile.saveSWF0[i] = intel_de_read(dev_priv, + SWF0(dev_priv, i)); + dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv, + SWF1(dev_priv, i)); } for (i = 0; i < 3; i++) - dev_priv->regfile.saveSWF3[i] = intel_de_read(dev_priv, SWF3(i)); + dev_priv->regfile.saveSWF3[i] = intel_de_read(dev_priv, + SWF3(dev_priv, i)); } } @@ -65,21 +72,28 @@ static void intel_restore_swf(struct drm_i915_private *dev_priv) /* Scratch space */ if (GRAPHICS_VER(dev_priv) == 2 && IS_MOBILE(dev_priv)) { for (i = 0; i < 7; i++) { - intel_de_write(dev_priv, SWF0(i), dev_priv->regfile.saveSWF0[i]); - intel_de_write(dev_priv, SWF1(i), dev_priv->regfile.saveSWF1[i]); + intel_de_write(dev_priv, SWF0(dev_priv, i), + dev_priv->regfile.saveSWF0[i]); + intel_de_write(dev_priv, SWF1(dev_priv, i), + dev_priv->regfile.saveSWF1[i]); } for (i = 0; i < 3; i++) - intel_de_write(dev_priv, SWF3(i), dev_priv->regfile.saveSWF3[i]); + intel_de_write(dev_priv, SWF3(dev_priv, i), + dev_priv->regfile.saveSWF3[i]); } else if (GRAPHICS_VER(dev_priv) == 2) { for (i = 0; i < 7; i++) - intel_de_write(dev_priv, SWF1(i), dev_priv->regfile.saveSWF1[i]); + intel_de_write(dev_priv, SWF1(dev_priv, i), + dev_priv->regfile.saveSWF1[i]); } else if (HAS_GMCH(dev_priv)) { for (i = 0; i < 16; i++) { - intel_de_write(dev_priv, SWF0(i), dev_priv->regfile.saveSWF0[i]); - intel_de_write(dev_priv, SWF1(i), dev_priv->regfile.saveSWF1[i]); + intel_de_write(dev_priv, SWF0(dev_priv, i), + dev_priv->regfile.saveSWF0[i]); + intel_de_write(dev_priv, SWF1(dev_priv, i), + dev_priv->regfile.saveSWF1[i]); } for (i = 0; i < 3; i++) - intel_de_write(dev_priv, SWF3(i), dev_priv->regfile.saveSWF3[i]); + intel_de_write(dev_priv, SWF3(dev_priv, i), + dev_priv->regfile.saveSWF3[i]); } } @@ -92,7 +106,8 @@ void i915_save_display(struct drm_i915_private *dev_priv) /* Display arbitration control */ if (GRAPHICS_VER(dev_priv) <= 4) - dev_priv->regfile.saveDSPARB = intel_de_read(dev_priv, DSPARB); + dev_priv->regfile.saveDSPARB = intel_de_read(dev_priv, + DSPARB(dev_priv)); if (GRAPHICS_VER(dev_priv) == 4) pci_read_config_word(pdev, GCDGMBUS, @@ -116,7 +131,8 @@ void i915_restore_display(struct drm_i915_private *dev_priv) /* Display arbitration */ if (GRAPHICS_VER(dev_priv) <= 4) - intel_de_write(dev_priv, DSPARB, dev_priv->regfile.saveDSPARB); + intel_de_write(dev_priv, DSPARB(dev_priv), + dev_priv->regfile.saveDSPARB); intel_vga_redisable(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 1dc5281b2ade..26c4dbda076e 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -25,11 +25,8 @@ * */ -#include "display/intel_de.h" +#include "display/i9xx_plane_regs.h" #include "display/intel_display.h" -#include "display/intel_display_trace.h" -#include "display/intel_fbc_regs.h" -#include "display/skl_watermark.h" #include "gt/intel_engine_regs.h" #include "gt/intel_gt.h" @@ -137,10 +134,13 @@ static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv) enum pipe pipe; for_each_pipe(dev_priv, pipe) { - intel_uncore_rmw(&dev_priv->uncore, DSPCNTR(pipe), 0, DISP_TRICKLE_FEED_DISABLE); + intel_uncore_rmw(&dev_priv->uncore, DSPCNTR(dev_priv, pipe), + 0, DISP_TRICKLE_FEED_DISABLE); - intel_uncore_rmw(&dev_priv->uncore, DSPSURF(pipe), 0, 0); - intel_uncore_posting_read(&dev_priv->uncore, DSPSURF(pipe)); + intel_uncore_rmw(&dev_priv->uncore, DSPSURF(dev_priv, pipe), + 0, 0); + intel_uncore_posting_read(&dev_priv->uncore, + DSPSURF(dev_priv, pipe)); } } diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index a0a43ea07f11..d26de37719a7 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -25,7 +25,7 @@ #include <linux/string_helpers.h> #include <drm/drm_print.h> -#include <drm/i915_pciids.h> +#include <drm/intel/i915_pciids.h> #include "gt/intel_gt_regs.h" #include "i915_drv.h" @@ -127,80 +127,80 @@ void intel_device_info_print(const struct intel_device_info *info, drm_printf(p, "rawclk rate: %u kHz\n", runtime->rawclk_freq); } -#undef INTEL_VGA_DEVICE -#define INTEL_VGA_DEVICE(id, info) (id) +#define ID(id) (id) static const u16 subplatform_ult_ids[] = { - INTEL_HSW_ULT_GT1_IDS(0), - INTEL_HSW_ULT_GT2_IDS(0), - INTEL_HSW_ULT_GT3_IDS(0), - INTEL_BDW_ULT_GT1_IDS(0), - INTEL_BDW_ULT_GT2_IDS(0), - INTEL_BDW_ULT_GT3_IDS(0), - INTEL_BDW_ULT_RSVD_IDS(0), - INTEL_SKL_ULT_GT1_IDS(0), - INTEL_SKL_ULT_GT2_IDS(0), - INTEL_SKL_ULT_GT3_IDS(0), - INTEL_KBL_ULT_GT1_IDS(0), - INTEL_KBL_ULT_GT2_IDS(0), - INTEL_KBL_ULT_GT3_IDS(0), - INTEL_CFL_U_GT2_IDS(0), - INTEL_CFL_U_GT3_IDS(0), - INTEL_WHL_U_GT1_IDS(0), - INTEL_WHL_U_GT2_IDS(0), - INTEL_WHL_U_GT3_IDS(0), - INTEL_CML_U_GT1_IDS(0), - INTEL_CML_U_GT2_IDS(0), + INTEL_HSW_ULT_GT1_IDS(ID), + INTEL_HSW_ULT_GT2_IDS(ID), + INTEL_HSW_ULT_GT3_IDS(ID), + INTEL_BDW_ULT_GT1_IDS(ID), + INTEL_BDW_ULT_GT2_IDS(ID), + INTEL_BDW_ULT_GT3_IDS(ID), + INTEL_BDW_ULT_RSVD_IDS(ID), + INTEL_SKL_ULT_GT1_IDS(ID), + INTEL_SKL_ULT_GT2_IDS(ID), + INTEL_SKL_ULT_GT3_IDS(ID), + INTEL_KBL_ULT_GT1_IDS(ID), + INTEL_KBL_ULT_GT2_IDS(ID), + INTEL_KBL_ULT_GT3_IDS(ID), + INTEL_CFL_U_GT2_IDS(ID), + INTEL_CFL_U_GT3_IDS(ID), + INTEL_WHL_U_GT1_IDS(ID), + INTEL_WHL_U_GT2_IDS(ID), + INTEL_WHL_U_GT3_IDS(ID), + INTEL_CML_U_GT1_IDS(ID), + INTEL_CML_U_GT2_IDS(ID), }; static const u16 subplatform_ulx_ids[] = { - INTEL_HSW_ULX_GT1_IDS(0), - INTEL_HSW_ULX_GT2_IDS(0), - INTEL_BDW_ULX_GT1_IDS(0), - INTEL_BDW_ULX_GT2_IDS(0), - INTEL_BDW_ULX_GT3_IDS(0), - INTEL_BDW_ULX_RSVD_IDS(0), - INTEL_SKL_ULX_GT1_IDS(0), - INTEL_SKL_ULX_GT2_IDS(0), - INTEL_KBL_ULX_GT1_IDS(0), - INTEL_KBL_ULX_GT2_IDS(0), - INTEL_AML_KBL_GT2_IDS(0), - INTEL_AML_CFL_GT2_IDS(0), + INTEL_HSW_ULX_GT1_IDS(ID), + INTEL_HSW_ULX_GT2_IDS(ID), + INTEL_BDW_ULX_GT1_IDS(ID), + INTEL_BDW_ULX_GT2_IDS(ID), + INTEL_BDW_ULX_GT3_IDS(ID), + INTEL_BDW_ULX_RSVD_IDS(ID), + INTEL_SKL_ULX_GT1_IDS(ID), + INTEL_SKL_ULX_GT2_IDS(ID), + INTEL_KBL_ULX_GT1_IDS(ID), + INTEL_KBL_ULX_GT2_IDS(ID), + INTEL_AML_KBL_GT2_IDS(ID), + INTEL_AML_CFL_GT2_IDS(ID), }; static const u16 subplatform_portf_ids[] = { - INTEL_ICL_PORT_F_IDS(0), + INTEL_ICL_PORT_F_IDS(ID), }; static const u16 subplatform_uy_ids[] = { - INTEL_TGL_12_GT2_IDS(0), + INTEL_TGL_GT2_IDS(ID), }; static const u16 subplatform_n_ids[] = { - INTEL_ADLN_IDS(0), + INTEL_ADLN_IDS(ID), }; static const u16 subplatform_rpl_ids[] = { - INTEL_RPLS_IDS(0), - INTEL_RPLP_IDS(0), + INTEL_RPLS_IDS(ID), + INTEL_RPLU_IDS(ID), + INTEL_RPLP_IDS(ID), }; static const u16 subplatform_rplu_ids[] = { - INTEL_RPLU_IDS(0), + INTEL_RPLU_IDS(ID), }; static const u16 subplatform_g10_ids[] = { - INTEL_DG2_G10_IDS(0), - INTEL_ATS_M150_IDS(0), + INTEL_DG2_G10_IDS(ID), + INTEL_ATS_M150_IDS(ID), }; static const u16 subplatform_g11_ids[] = { - INTEL_DG2_G11_IDS(0), - INTEL_ATS_M75_IDS(0), + INTEL_DG2_G11_IDS(ID), + INTEL_ATS_M75_IDS(ID), }; static const u16 subplatform_g12_ids[] = { - INTEL_DG2_G12_IDS(0), + INTEL_DG2_G12_IDS(ID), }; static bool find_devid(u16 id, const u16 *p, unsigned int num) diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index e1a35f70b544..955c9a33212a 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -4,9 +4,11 @@ */ #include "display/bxt_dpio_phy_regs.h" +#include "display/i9xx_plane_regs.h" #include "display/intel_audio_regs.h" #include "display/intel_backlight_regs.h" #include "display/intel_color_regs.h" +#include "display/intel_cursor_regs.h" #include "display/intel_display_types.h" #include "display/intel_dmc_regs.h" #include "display/intel_dp_aux_regs.h" @@ -16,6 +18,7 @@ #include "display/intel_lvds_regs.h" #include "display/intel_psr_regs.h" #include "display/intel_sprite_regs.h" +#include "display/skl_universal_plane_regs.h" #include "display/skl_watermark_regs.h" #include "display/vlv_dsi_pll_regs.h" #include "gt/intel_engine_regs.h" @@ -123,38 +126,38 @@ static int iterate_generic_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(_MMIO(0x650b4)); MMIO_D(_MMIO(0xc4040)); MMIO_D(DERRMR); - MMIO_D(PIPEDSL(PIPE_A)); - MMIO_D(PIPEDSL(PIPE_B)); - MMIO_D(PIPEDSL(PIPE_C)); - MMIO_D(PIPEDSL(_PIPE_EDP)); - MMIO_D(TRANSCONF(TRANSCODER_A)); - MMIO_D(TRANSCONF(TRANSCODER_B)); - MMIO_D(TRANSCONF(TRANSCODER_C)); - MMIO_D(TRANSCONF(TRANSCODER_EDP)); - MMIO_D(PIPESTAT(PIPE_A)); - MMIO_D(PIPESTAT(PIPE_B)); - MMIO_D(PIPESTAT(PIPE_C)); - MMIO_D(PIPESTAT(_PIPE_EDP)); - MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_A)); - MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_B)); - MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_C)); - MMIO_D(PIPE_FLIPCOUNT_G4X(_PIPE_EDP)); - MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_A)); - MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_B)); - MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_C)); - MMIO_D(PIPE_FRMCOUNT_G4X(_PIPE_EDP)); - MMIO_D(CURCNTR(PIPE_A)); - MMIO_D(CURCNTR(PIPE_B)); - MMIO_D(CURCNTR(PIPE_C)); - MMIO_D(CURPOS(PIPE_A)); - MMIO_D(CURPOS(PIPE_B)); - MMIO_D(CURPOS(PIPE_C)); - MMIO_D(CURBASE(PIPE_A)); - MMIO_D(CURBASE(PIPE_B)); - MMIO_D(CURBASE(PIPE_C)); - MMIO_D(CUR_FBC_CTL(PIPE_A)); - MMIO_D(CUR_FBC_CTL(PIPE_B)); - MMIO_D(CUR_FBC_CTL(PIPE_C)); + MMIO_D(PIPEDSL(dev_priv, PIPE_A)); + MMIO_D(PIPEDSL(dev_priv, PIPE_B)); + MMIO_D(PIPEDSL(dev_priv, PIPE_C)); + MMIO_D(PIPEDSL(dev_priv, _PIPE_EDP)); + MMIO_D(TRANSCONF(dev_priv, TRANSCODER_A)); + MMIO_D(TRANSCONF(dev_priv, TRANSCODER_B)); + MMIO_D(TRANSCONF(dev_priv, TRANSCODER_C)); + MMIO_D(TRANSCONF(dev_priv, TRANSCODER_EDP)); + MMIO_D(PIPESTAT(dev_priv, PIPE_A)); + MMIO_D(PIPESTAT(dev_priv, PIPE_B)); + MMIO_D(PIPESTAT(dev_priv, PIPE_C)); + MMIO_D(PIPESTAT(dev_priv, _PIPE_EDP)); + MMIO_D(PIPE_FLIPCOUNT_G4X(dev_priv, PIPE_A)); + MMIO_D(PIPE_FLIPCOUNT_G4X(dev_priv, PIPE_B)); + MMIO_D(PIPE_FLIPCOUNT_G4X(dev_priv, PIPE_C)); + MMIO_D(PIPE_FLIPCOUNT_G4X(dev_priv, _PIPE_EDP)); + MMIO_D(PIPE_FRMCOUNT_G4X(dev_priv, PIPE_A)); + MMIO_D(PIPE_FRMCOUNT_G4X(dev_priv, PIPE_B)); + MMIO_D(PIPE_FRMCOUNT_G4X(dev_priv, PIPE_C)); + MMIO_D(PIPE_FRMCOUNT_G4X(dev_priv, _PIPE_EDP)); + MMIO_D(CURCNTR(dev_priv, PIPE_A)); + MMIO_D(CURCNTR(dev_priv, PIPE_B)); + MMIO_D(CURCNTR(dev_priv, PIPE_C)); + MMIO_D(CURPOS(dev_priv, PIPE_A)); + MMIO_D(CURPOS(dev_priv, PIPE_B)); + MMIO_D(CURPOS(dev_priv, PIPE_C)); + MMIO_D(CURBASE(dev_priv, PIPE_A)); + MMIO_D(CURBASE(dev_priv, PIPE_B)); + MMIO_D(CURBASE(dev_priv, PIPE_C)); + MMIO_D(CUR_FBC_CTL(dev_priv, PIPE_A)); + MMIO_D(CUR_FBC_CTL(dev_priv, PIPE_B)); + MMIO_D(CUR_FBC_CTL(dev_priv, PIPE_C)); MMIO_D(_MMIO(0x700ac)); MMIO_D(_MMIO(0x710ac)); MMIO_D(_MMIO(0x720ac)); @@ -162,32 +165,32 @@ static int iterate_generic_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(_MMIO(0x70094)); MMIO_D(_MMIO(0x70098)); MMIO_D(_MMIO(0x7009c)); - MMIO_D(DSPCNTR(PIPE_A)); - MMIO_D(DSPADDR(PIPE_A)); - MMIO_D(DSPSTRIDE(PIPE_A)); - MMIO_D(DSPPOS(PIPE_A)); - MMIO_D(DSPSIZE(PIPE_A)); - MMIO_D(DSPSURF(PIPE_A)); - MMIO_D(DSPOFFSET(PIPE_A)); - MMIO_D(DSPSURFLIVE(PIPE_A)); + MMIO_D(DSPCNTR(dev_priv, PIPE_A)); + MMIO_D(DSPADDR(dev_priv, PIPE_A)); + MMIO_D(DSPSTRIDE(dev_priv, PIPE_A)); + MMIO_D(DSPPOS(dev_priv, PIPE_A)); + MMIO_D(DSPSIZE(dev_priv, PIPE_A)); + MMIO_D(DSPSURF(dev_priv, PIPE_A)); + MMIO_D(DSPOFFSET(dev_priv, PIPE_A)); + MMIO_D(DSPSURFLIVE(dev_priv, PIPE_A)); MMIO_D(REG_50080(PIPE_A, PLANE_PRIMARY)); - MMIO_D(DSPCNTR(PIPE_B)); - MMIO_D(DSPADDR(PIPE_B)); - MMIO_D(DSPSTRIDE(PIPE_B)); - MMIO_D(DSPPOS(PIPE_B)); - MMIO_D(DSPSIZE(PIPE_B)); - MMIO_D(DSPSURF(PIPE_B)); - MMIO_D(DSPOFFSET(PIPE_B)); - MMIO_D(DSPSURFLIVE(PIPE_B)); + MMIO_D(DSPCNTR(dev_priv, PIPE_B)); + MMIO_D(DSPADDR(dev_priv, PIPE_B)); + MMIO_D(DSPSTRIDE(dev_priv, PIPE_B)); + MMIO_D(DSPPOS(dev_priv, PIPE_B)); + MMIO_D(DSPSIZE(dev_priv, PIPE_B)); + MMIO_D(DSPSURF(dev_priv, PIPE_B)); + MMIO_D(DSPOFFSET(dev_priv, PIPE_B)); + MMIO_D(DSPSURFLIVE(dev_priv, PIPE_B)); MMIO_D(REG_50080(PIPE_B, PLANE_PRIMARY)); - MMIO_D(DSPCNTR(PIPE_C)); - MMIO_D(DSPADDR(PIPE_C)); - MMIO_D(DSPSTRIDE(PIPE_C)); - MMIO_D(DSPPOS(PIPE_C)); - MMIO_D(DSPSIZE(PIPE_C)); - MMIO_D(DSPSURF(PIPE_C)); - MMIO_D(DSPOFFSET(PIPE_C)); - MMIO_D(DSPSURFLIVE(PIPE_C)); + MMIO_D(DSPCNTR(dev_priv, PIPE_C)); + MMIO_D(DSPADDR(dev_priv, PIPE_C)); + MMIO_D(DSPSTRIDE(dev_priv, PIPE_C)); + MMIO_D(DSPPOS(dev_priv, PIPE_C)); + MMIO_D(DSPSIZE(dev_priv, PIPE_C)); + MMIO_D(DSPSURF(dev_priv, PIPE_C)); + MMIO_D(DSPOFFSET(dev_priv, PIPE_C)); + MMIO_D(DSPSURFLIVE(dev_priv, PIPE_C)); MMIO_D(REG_50080(PIPE_C, PLANE_PRIMARY)); MMIO_D(SPRCTL(PIPE_A)); MMIO_D(SPRLINOFF(PIPE_A)); @@ -228,73 +231,73 @@ static int iterate_generic_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(SPRSCALE(PIPE_C)); MMIO_D(SPRSURFLIVE(PIPE_C)); MMIO_D(REG_50080(PIPE_C, PLANE_SPRITE0)); - MMIO_D(TRANS_HTOTAL(TRANSCODER_A)); - MMIO_D(TRANS_HBLANK(TRANSCODER_A)); - MMIO_D(TRANS_HSYNC(TRANSCODER_A)); - MMIO_D(TRANS_VTOTAL(TRANSCODER_A)); - MMIO_D(TRANS_VBLANK(TRANSCODER_A)); - MMIO_D(TRANS_VSYNC(TRANSCODER_A)); - MMIO_D(BCLRPAT(TRANSCODER_A)); - MMIO_D(TRANS_VSYNCSHIFT(TRANSCODER_A)); - MMIO_D(PIPESRC(TRANSCODER_A)); - MMIO_D(TRANS_HTOTAL(TRANSCODER_B)); - MMIO_D(TRANS_HBLANK(TRANSCODER_B)); - MMIO_D(TRANS_HSYNC(TRANSCODER_B)); - MMIO_D(TRANS_VTOTAL(TRANSCODER_B)); - MMIO_D(TRANS_VBLANK(TRANSCODER_B)); - MMIO_D(TRANS_VSYNC(TRANSCODER_B)); - MMIO_D(BCLRPAT(TRANSCODER_B)); - MMIO_D(TRANS_VSYNCSHIFT(TRANSCODER_B)); - MMIO_D(PIPESRC(TRANSCODER_B)); - MMIO_D(TRANS_HTOTAL(TRANSCODER_C)); - MMIO_D(TRANS_HBLANK(TRANSCODER_C)); - MMIO_D(TRANS_HSYNC(TRANSCODER_C)); - MMIO_D(TRANS_VTOTAL(TRANSCODER_C)); - MMIO_D(TRANS_VBLANK(TRANSCODER_C)); - MMIO_D(TRANS_VSYNC(TRANSCODER_C)); - MMIO_D(BCLRPAT(TRANSCODER_C)); - MMIO_D(TRANS_VSYNCSHIFT(TRANSCODER_C)); - MMIO_D(PIPESRC(TRANSCODER_C)); - MMIO_D(TRANS_HTOTAL(TRANSCODER_EDP)); - MMIO_D(TRANS_HBLANK(TRANSCODER_EDP)); - MMIO_D(TRANS_HSYNC(TRANSCODER_EDP)); - MMIO_D(TRANS_VTOTAL(TRANSCODER_EDP)); - MMIO_D(TRANS_VBLANK(TRANSCODER_EDP)); - MMIO_D(TRANS_VSYNC(TRANSCODER_EDP)); - MMIO_D(BCLRPAT(TRANSCODER_EDP)); - MMIO_D(TRANS_VSYNCSHIFT(TRANSCODER_EDP)); - MMIO_D(PIPE_DATA_M1(TRANSCODER_A)); - MMIO_D(PIPE_DATA_N1(TRANSCODER_A)); - MMIO_D(PIPE_DATA_M2(TRANSCODER_A)); - MMIO_D(PIPE_DATA_N2(TRANSCODER_A)); - MMIO_D(PIPE_LINK_M1(TRANSCODER_A)); - MMIO_D(PIPE_LINK_N1(TRANSCODER_A)); - MMIO_D(PIPE_LINK_M2(TRANSCODER_A)); - MMIO_D(PIPE_LINK_N2(TRANSCODER_A)); - MMIO_D(PIPE_DATA_M1(TRANSCODER_B)); - MMIO_D(PIPE_DATA_N1(TRANSCODER_B)); - MMIO_D(PIPE_DATA_M2(TRANSCODER_B)); - MMIO_D(PIPE_DATA_N2(TRANSCODER_B)); - MMIO_D(PIPE_LINK_M1(TRANSCODER_B)); - MMIO_D(PIPE_LINK_N1(TRANSCODER_B)); - MMIO_D(PIPE_LINK_M2(TRANSCODER_B)); - MMIO_D(PIPE_LINK_N2(TRANSCODER_B)); - MMIO_D(PIPE_DATA_M1(TRANSCODER_C)); - MMIO_D(PIPE_DATA_N1(TRANSCODER_C)); - MMIO_D(PIPE_DATA_M2(TRANSCODER_C)); - MMIO_D(PIPE_DATA_N2(TRANSCODER_C)); - MMIO_D(PIPE_LINK_M1(TRANSCODER_C)); - MMIO_D(PIPE_LINK_N1(TRANSCODER_C)); - MMIO_D(PIPE_LINK_M2(TRANSCODER_C)); - MMIO_D(PIPE_LINK_N2(TRANSCODER_C)); - MMIO_D(PIPE_DATA_M1(TRANSCODER_EDP)); - MMIO_D(PIPE_DATA_N1(TRANSCODER_EDP)); - MMIO_D(PIPE_DATA_M2(TRANSCODER_EDP)); - MMIO_D(PIPE_DATA_N2(TRANSCODER_EDP)); - MMIO_D(PIPE_LINK_M1(TRANSCODER_EDP)); - MMIO_D(PIPE_LINK_N1(TRANSCODER_EDP)); - MMIO_D(PIPE_LINK_M2(TRANSCODER_EDP)); - MMIO_D(PIPE_LINK_N2(TRANSCODER_EDP)); + MMIO_D(TRANS_HTOTAL(dev_priv, TRANSCODER_A)); + MMIO_D(TRANS_HBLANK(dev_priv, TRANSCODER_A)); + MMIO_D(TRANS_HSYNC(dev_priv, TRANSCODER_A)); + MMIO_D(TRANS_VTOTAL(dev_priv, TRANSCODER_A)); + MMIO_D(TRANS_VBLANK(dev_priv, TRANSCODER_A)); + MMIO_D(TRANS_VSYNC(dev_priv, TRANSCODER_A)); + MMIO_D(BCLRPAT(dev_priv, TRANSCODER_A)); + MMIO_D(TRANS_VSYNCSHIFT(dev_priv, TRANSCODER_A)); + MMIO_D(PIPESRC(dev_priv, TRANSCODER_A)); + MMIO_D(TRANS_HTOTAL(dev_priv, TRANSCODER_B)); + MMIO_D(TRANS_HBLANK(dev_priv, TRANSCODER_B)); + MMIO_D(TRANS_HSYNC(dev_priv, TRANSCODER_B)); + MMIO_D(TRANS_VTOTAL(dev_priv, TRANSCODER_B)); + MMIO_D(TRANS_VBLANK(dev_priv, TRANSCODER_B)); + MMIO_D(TRANS_VSYNC(dev_priv, TRANSCODER_B)); + MMIO_D(BCLRPAT(dev_priv, TRANSCODER_B)); + MMIO_D(TRANS_VSYNCSHIFT(dev_priv, TRANSCODER_B)); + MMIO_D(PIPESRC(dev_priv, TRANSCODER_B)); + MMIO_D(TRANS_HTOTAL(dev_priv, TRANSCODER_C)); + MMIO_D(TRANS_HBLANK(dev_priv, TRANSCODER_C)); + MMIO_D(TRANS_HSYNC(dev_priv, TRANSCODER_C)); + MMIO_D(TRANS_VTOTAL(dev_priv, TRANSCODER_C)); + MMIO_D(TRANS_VBLANK(dev_priv, TRANSCODER_C)); + MMIO_D(TRANS_VSYNC(dev_priv, TRANSCODER_C)); + MMIO_D(BCLRPAT(dev_priv, TRANSCODER_C)); + MMIO_D(TRANS_VSYNCSHIFT(dev_priv, TRANSCODER_C)); + MMIO_D(PIPESRC(dev_priv, TRANSCODER_C)); + MMIO_D(TRANS_HTOTAL(dev_priv, TRANSCODER_EDP)); + MMIO_D(TRANS_HBLANK(dev_priv, TRANSCODER_EDP)); + MMIO_D(TRANS_HSYNC(dev_priv, TRANSCODER_EDP)); + MMIO_D(TRANS_VTOTAL(dev_priv, TRANSCODER_EDP)); + MMIO_D(TRANS_VBLANK(dev_priv, TRANSCODER_EDP)); + MMIO_D(TRANS_VSYNC(dev_priv, TRANSCODER_EDP)); + MMIO_D(BCLRPAT(dev_priv, TRANSCODER_EDP)); + MMIO_D(TRANS_VSYNCSHIFT(dev_priv, TRANSCODER_EDP)); + MMIO_D(PIPE_DATA_M1(dev_priv, TRANSCODER_A)); + MMIO_D(PIPE_DATA_N1(dev_priv, TRANSCODER_A)); + MMIO_D(PIPE_DATA_M2(dev_priv, TRANSCODER_A)); + MMIO_D(PIPE_DATA_N2(dev_priv, TRANSCODER_A)); + MMIO_D(PIPE_LINK_M1(dev_priv, TRANSCODER_A)); + MMIO_D(PIPE_LINK_N1(dev_priv, TRANSCODER_A)); + MMIO_D(PIPE_LINK_M2(dev_priv, TRANSCODER_A)); + MMIO_D(PIPE_LINK_N2(dev_priv, TRANSCODER_A)); + MMIO_D(PIPE_DATA_M1(dev_priv, TRANSCODER_B)); + MMIO_D(PIPE_DATA_N1(dev_priv, TRANSCODER_B)); + MMIO_D(PIPE_DATA_M2(dev_priv, TRANSCODER_B)); + MMIO_D(PIPE_DATA_N2(dev_priv, TRANSCODER_B)); + MMIO_D(PIPE_LINK_M1(dev_priv, TRANSCODER_B)); + MMIO_D(PIPE_LINK_N1(dev_priv, TRANSCODER_B)); + MMIO_D(PIPE_LINK_M2(dev_priv, TRANSCODER_B)); + MMIO_D(PIPE_LINK_N2(dev_priv, TRANSCODER_B)); + MMIO_D(PIPE_DATA_M1(dev_priv, TRANSCODER_C)); + MMIO_D(PIPE_DATA_N1(dev_priv, TRANSCODER_C)); + MMIO_D(PIPE_DATA_M2(dev_priv, TRANSCODER_C)); + MMIO_D(PIPE_DATA_N2(dev_priv, TRANSCODER_C)); + MMIO_D(PIPE_LINK_M1(dev_priv, TRANSCODER_C)); + MMIO_D(PIPE_LINK_N1(dev_priv, TRANSCODER_C)); + MMIO_D(PIPE_LINK_M2(dev_priv, TRANSCODER_C)); + MMIO_D(PIPE_LINK_N2(dev_priv, TRANSCODER_C)); + MMIO_D(PIPE_DATA_M1(dev_priv, TRANSCODER_EDP)); + MMIO_D(PIPE_DATA_N1(dev_priv, TRANSCODER_EDP)); + MMIO_D(PIPE_DATA_M2(dev_priv, TRANSCODER_EDP)); + MMIO_D(PIPE_DATA_N2(dev_priv, TRANSCODER_EDP)); + MMIO_D(PIPE_LINK_M1(dev_priv, TRANSCODER_EDP)); + MMIO_D(PIPE_LINK_N1(dev_priv, TRANSCODER_EDP)); + MMIO_D(PIPE_LINK_M2(dev_priv, TRANSCODER_EDP)); + MMIO_D(PIPE_LINK_N2(dev_priv, TRANSCODER_EDP)); MMIO_D(PF_CTL(PIPE_A)); MMIO_D(PF_WIN_SZ(PIPE_A)); MMIO_D(PF_WIN_POS(PIPE_A)); @@ -503,18 +506,18 @@ static int iterate_generic_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(GAMMA_MODE(PIPE_A)); MMIO_D(GAMMA_MODE(PIPE_B)); MMIO_D(GAMMA_MODE(PIPE_C)); - MMIO_D(TRANS_MULT(TRANSCODER_A)); - MMIO_D(TRANS_MULT(TRANSCODER_B)); - MMIO_D(TRANS_MULT(TRANSCODER_C)); - MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_A)); - MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_B)); - MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_C)); + MMIO_D(TRANS_MULT(dev_priv, TRANSCODER_A)); + MMIO_D(TRANS_MULT(dev_priv, TRANSCODER_B)); + MMIO_D(TRANS_MULT(dev_priv, TRANSCODER_C)); + MMIO_D(HSW_TVIDEO_DIP_CTL(dev_priv, TRANSCODER_A)); + MMIO_D(HSW_TVIDEO_DIP_CTL(dev_priv, TRANSCODER_B)); + MMIO_D(HSW_TVIDEO_DIP_CTL(dev_priv, TRANSCODER_C)); MMIO_D(SFUSE_STRAP); MMIO_D(SBI_ADDR); MMIO_D(SBI_DATA); MMIO_D(SBI_CTL_STAT); MMIO_D(PIXCLK_GATE); - MMIO_F(_MMIO(_DPA_AUX_CH_CTL), 6 * 4); + MMIO_F(DP_AUX_CH_CTL(AUX_CH_A), 6 * 4); MMIO_D(DDI_BUF_CTL(PORT_A)); MMIO_D(DDI_BUF_CTL(PORT_B)); MMIO_D(DDI_BUF_CTL(PORT_C)); @@ -885,9 +888,9 @@ static int iterate_pre_skl_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(FORCEWAKE_MT); MMIO_D(PCH_ADPA); - MMIO_F(_MMIO(_PCH_DPB_AUX_CH_CTL), 6 * 4); - MMIO_F(_MMIO(_PCH_DPC_AUX_CH_CTL), 6 * 4); - MMIO_F(_MMIO(_PCH_DPD_AUX_CH_CTL), 6 * 4); + MMIO_F(PCH_DP_AUX_CH_CTL(AUX_CH_B), 6 * 4); + MMIO_F(PCH_DP_AUX_CH_CTL(AUX_CH_C), 6 * 4); + MMIO_F(PCH_DP_AUX_CH_CTL(AUX_CH_D), 6 * 4); MMIO_F(_MMIO(0x70440), 0xc); MMIO_F(_MMIO(0x71440), 0xc); @@ -1004,36 +1007,36 @@ static int iterate_skl_plus_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(PLANE_NV12_BUF_CFG(PIPE_C, 1)); MMIO_D(PLANE_NV12_BUF_CFG(PIPE_C, 2)); MMIO_D(PLANE_NV12_BUF_CFG(PIPE_C, 3)); - MMIO_D(_MMIO(_REG_701C0(PIPE_A, 1))); - MMIO_D(_MMIO(_REG_701C0(PIPE_A, 2))); - MMIO_D(_MMIO(_REG_701C0(PIPE_A, 3))); - MMIO_D(_MMIO(_REG_701C0(PIPE_A, 4))); - MMIO_D(_MMIO(_REG_701C0(PIPE_B, 1))); - MMIO_D(_MMIO(_REG_701C0(PIPE_B, 2))); - MMIO_D(_MMIO(_REG_701C0(PIPE_B, 3))); - MMIO_D(_MMIO(_REG_701C0(PIPE_B, 4))); - MMIO_D(_MMIO(_REG_701C0(PIPE_C, 1))); - MMIO_D(_MMIO(_REG_701C0(PIPE_C, 2))); - MMIO_D(_MMIO(_REG_701C0(PIPE_C, 3))); - MMIO_D(_MMIO(_REG_701C0(PIPE_C, 4))); - MMIO_D(_MMIO(_REG_701C4(PIPE_A, 1))); - MMIO_D(_MMIO(_REG_701C4(PIPE_A, 2))); - MMIO_D(_MMIO(_REG_701C4(PIPE_A, 3))); - MMIO_D(_MMIO(_REG_701C4(PIPE_A, 4))); - MMIO_D(_MMIO(_REG_701C4(PIPE_B, 1))); - MMIO_D(_MMIO(_REG_701C4(PIPE_B, 2))); - MMIO_D(_MMIO(_REG_701C4(PIPE_B, 3))); - MMIO_D(_MMIO(_REG_701C4(PIPE_B, 4))); - MMIO_D(_MMIO(_REG_701C4(PIPE_C, 1))); - MMIO_D(_MMIO(_REG_701C4(PIPE_C, 2))); - MMIO_D(_MMIO(_REG_701C4(PIPE_C, 3))); - MMIO_D(_MMIO(_REG_701C4(PIPE_C, 4))); - MMIO_D(_MMIO(_PLANE_CTL_3_A)); - MMIO_D(_MMIO(_PLANE_CTL_3_B)); - MMIO_D(_MMIO(0x72380)); - MMIO_D(_MMIO(0x7239c)); - MMIO_D(_MMIO(_PLANE_SURF_3_A)); - MMIO_D(_MMIO(_PLANE_SURF_3_B)); + MMIO_D(PLANE_AUX_DIST(PIPE_A, 0)); + MMIO_D(PLANE_AUX_DIST(PIPE_A, 1)); + MMIO_D(PLANE_AUX_DIST(PIPE_A, 2)); + MMIO_D(PLANE_AUX_DIST(PIPE_A, 3)); + MMIO_D(PLANE_AUX_DIST(PIPE_B, 0)); + MMIO_D(PLANE_AUX_DIST(PIPE_B, 1)); + MMIO_D(PLANE_AUX_DIST(PIPE_B, 2)); + MMIO_D(PLANE_AUX_DIST(PIPE_B, 3)); + MMIO_D(PLANE_AUX_DIST(PIPE_C, 0)); + MMIO_D(PLANE_AUX_DIST(PIPE_C, 1)); + MMIO_D(PLANE_AUX_DIST(PIPE_C, 2)); + MMIO_D(PLANE_AUX_DIST(PIPE_C, 3)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_A, 0)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_A, 1)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_A, 2)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_A, 3)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_B, 0)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_B, 1)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_B, 2)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_B, 3)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_C, 0)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_C, 1)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_C, 2)); + MMIO_D(PLANE_AUX_OFFSET(PIPE_C, 3)); + MMIO_D(PLANE_CTL(PIPE_A, 2)); + MMIO_D(PLANE_CTL(PIPE_B, 2)); + MMIO_D(PLANE_CTL(PIPE_C, 2)); + MMIO_D(PLANE_SURF(PIPE_A, 2)); + MMIO_D(PLANE_SURF(PIPE_B, 2)); + MMIO_D(PLANE_SURF(PIPE_C, 2)); MMIO_D(DMC_SSP_BASE); MMIO_D(DMC_HTP_SKL); MMIO_D(DMC_LAST_WRITE); @@ -1073,15 +1076,15 @@ static int iterate_skl_plus_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(_MMIO(0x70034)); MMIO_D(_MMIO(0x71034)); MMIO_D(_MMIO(0x72034)); - MMIO_D(_MMIO(_PLANE_KEYVAL_1(PIPE_A))); - MMIO_D(_MMIO(_PLANE_KEYVAL_1(PIPE_B))); - MMIO_D(_MMIO(_PLANE_KEYVAL_1(PIPE_C))); - MMIO_D(_MMIO(_PLANE_KEYMAX_1(PIPE_A))); - MMIO_D(_MMIO(_PLANE_KEYMAX_1(PIPE_B))); - MMIO_D(_MMIO(_PLANE_KEYMAX_1(PIPE_C))); - MMIO_D(_MMIO(_PLANE_KEYMSK_1(PIPE_A))); - MMIO_D(_MMIO(_PLANE_KEYMSK_1(PIPE_B))); - MMIO_D(_MMIO(_PLANE_KEYMSK_1(PIPE_C))); + MMIO_D(PLANE_KEYVAL(PIPE_A, 0)); + MMIO_D(PLANE_KEYVAL(PIPE_B, 0)); + MMIO_D(PLANE_KEYVAL(PIPE_C, 0)); + MMIO_D(PLANE_KEYMAX(PIPE_A, 0)); + MMIO_D(PLANE_KEYMAX(PIPE_B, 0)); + MMIO_D(PLANE_KEYMAX(PIPE_C, 0)); + MMIO_D(PLANE_KEYMSK(PIPE_A, 0)); + MMIO_D(PLANE_KEYMSK(PIPE_B, 0)); + MMIO_D(PLANE_KEYMSK(PIPE_C, 0)); MMIO_D(_MMIO(0x44500)); #define CSFE_CHICKEN1_REG(base) _MMIO((base) + 0xD4) MMIO_RING_D(CSFE_CHICKEN1_REG); @@ -1232,9 +1235,9 @@ static int iterate_bxt_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(BXT_DSI_PLL_ENABLE); MMIO_D(GEN9_CLKGATE_DIS_0); MMIO_D(GEN9_CLKGATE_DIS_4); - MMIO_D(HSW_TVIDEO_DIP_GCP(TRANSCODER_A)); - MMIO_D(HSW_TVIDEO_DIP_GCP(TRANSCODER_B)); - MMIO_D(HSW_TVIDEO_DIP_GCP(TRANSCODER_C)); + MMIO_D(HSW_TVIDEO_DIP_GCP(dev_priv, TRANSCODER_A)); + MMIO_D(HSW_TVIDEO_DIP_GCP(dev_priv, TRANSCODER_B)); + MMIO_D(HSW_TVIDEO_DIP_GCP(dev_priv, TRANSCODER_C)); MMIO_D(RC6_CTX_BASE); MMIO_D(GEN8_PUSHBUS_CONTROL); MMIO_D(GEN8_PUSHBUS_ENABLE); diff --git a/drivers/gpu/drm/i915/intel_pci_config.h b/drivers/gpu/drm/i915/intel_pci_config.h index 23b8e519f333..ebe040828e20 100644 --- a/drivers/gpu/drm/i915/intel_pci_config.h +++ b/drivers/gpu/drm/i915/intel_pci_config.h @@ -31,7 +31,7 @@ static inline int intel_mmio_bar(int graphics_ver) } } -/* BSM in include/drm/i915_drm.h */ +/* BSM in include/drm/intel/i915_drm.h */ #define MCHBAR_I915 0x44 #define MCHBAR_I965 0x48 diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c index b00d6c280159..1784153f0cf8 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c @@ -5,8 +5,8 @@ #include <linux/component.h> -#include <drm/i915_pxp_tee_interface.h> -#include <drm/i915_component.h> +#include <drm/intel/i915_pxp_tee_interface.h> +#include <drm/intel/i915_component.h> #include "gem/i915_gem_lmem.h" #include "gt/intel_gt_print.h" diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index e3287f1de774..4aba47bccc63 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -43,101 +43,51 @@ static const char *intel_dram_type_str(enum intel_dram_type type) #undef DRAM_TYPE_STR -static void pnv_detect_mem_freq(struct drm_i915_private *dev_priv) +static bool pnv_is_ddr3(struct drm_i915_private *i915) +{ + return intel_uncore_read(&i915->uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3; +} + +static unsigned int pnv_mem_freq(struct drm_i915_private *dev_priv) { u32 tmp; tmp = intel_uncore_read(&dev_priv->uncore, CLKCFG); - switch (tmp & CLKCFG_FSB_MASK) { - case CLKCFG_FSB_533: - dev_priv->fsb_freq = 533; /* 133*4 */ - break; - case CLKCFG_FSB_800: - dev_priv->fsb_freq = 800; /* 200*4 */ - break; - case CLKCFG_FSB_667: - dev_priv->fsb_freq = 667; /* 167*4 */ - break; - case CLKCFG_FSB_400: - dev_priv->fsb_freq = 400; /* 100*4 */ - break; - } - switch (tmp & CLKCFG_MEM_MASK) { case CLKCFG_MEM_533: - dev_priv->mem_freq = 533; - break; + return 533333; case CLKCFG_MEM_667: - dev_priv->mem_freq = 667; - break; + return 666667; case CLKCFG_MEM_800: - dev_priv->mem_freq = 800; - break; + return 800000; } - /* detect pineview DDR3 setting */ - tmp = intel_uncore_read(&dev_priv->uncore, CSHRDDR3CTL); - dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0; + return 0; } -static void ilk_detect_mem_freq(struct drm_i915_private *dev_priv) +static unsigned int ilk_mem_freq(struct drm_i915_private *dev_priv) { - u16 ddrpll, csipll; + u16 ddrpll; ddrpll = intel_uncore_read16(&dev_priv->uncore, DDRMPLL1); switch (ddrpll & 0xff) { case 0xc: - dev_priv->mem_freq = 800; - break; + return 800000; case 0x10: - dev_priv->mem_freq = 1066; - break; + return 1066667; case 0x14: - dev_priv->mem_freq = 1333; - break; + return 1333333; case 0x18: - dev_priv->mem_freq = 1600; - break; + return 1600000; default: drm_dbg(&dev_priv->drm, "unknown memory frequency 0x%02x\n", ddrpll & 0xff); - dev_priv->mem_freq = 0; - break; - } - - csipll = intel_uncore_read16(&dev_priv->uncore, CSIPLL0); - switch (csipll & 0x3ff) { - case 0x00c: - dev_priv->fsb_freq = 3200; - break; - case 0x00e: - dev_priv->fsb_freq = 3733; - break; - case 0x010: - dev_priv->fsb_freq = 4266; - break; - case 0x012: - dev_priv->fsb_freq = 4800; - break; - case 0x014: - dev_priv->fsb_freq = 5333; - break; - case 0x016: - dev_priv->fsb_freq = 5866; - break; - case 0x018: - dev_priv->fsb_freq = 6400; - break; - default: - drm_dbg(&dev_priv->drm, "unknown fsb frequency 0x%04x\n", - csipll & 0x3ff); - dev_priv->fsb_freq = 0; - break; + return 0; } } -static void chv_detect_mem_freq(struct drm_i915_private *i915) +static unsigned int chv_mem_freq(struct drm_i915_private *i915) { u32 val; @@ -147,15 +97,13 @@ static void chv_detect_mem_freq(struct drm_i915_private *i915) switch ((val >> 2) & 0x7) { case 3: - i915->mem_freq = 2000; - break; + return 2000000; default: - i915->mem_freq = 1600; - break; + return 1600000; } } -static void vlv_detect_mem_freq(struct drm_i915_private *i915) +static unsigned int vlv_mem_freq(struct drm_i915_private *i915) { u32 val; @@ -166,30 +114,125 @@ static void vlv_detect_mem_freq(struct drm_i915_private *i915) switch ((val >> 6) & 3) { case 0: case 1: - i915->mem_freq = 800; - break; + return 800000; case 2: - i915->mem_freq = 1066; - break; + return 1066667; case 3: - i915->mem_freq = 1333; - break; + return 1333333; } + + return 0; } static void detect_mem_freq(struct drm_i915_private *i915) { if (IS_PINEVIEW(i915)) - pnv_detect_mem_freq(i915); + i915->mem_freq = pnv_mem_freq(i915); else if (GRAPHICS_VER(i915) == 5) - ilk_detect_mem_freq(i915); + i915->mem_freq = ilk_mem_freq(i915); else if (IS_CHERRYVIEW(i915)) - chv_detect_mem_freq(i915); + i915->mem_freq = chv_mem_freq(i915); else if (IS_VALLEYVIEW(i915)) - vlv_detect_mem_freq(i915); + i915->mem_freq = vlv_mem_freq(i915); + + if (IS_PINEVIEW(i915)) + i915->is_ddr3 = pnv_is_ddr3(i915); if (i915->mem_freq) - drm_dbg(&i915->drm, "DDR speed: %d MHz\n", i915->mem_freq); + drm_dbg(&i915->drm, "DDR speed: %d kHz\n", i915->mem_freq); +} + +unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) +{ + u32 fsb; + + /* + * Note that this only reads the state of the FSB + * straps, not the actual FSB frequency. Some BIOSen + * let you configure each independently. Ideally we'd + * read out the actual FSB frequency but sadly we + * don't know which registers have that information, + * and all the relevant docs have gone to bit heaven :( + */ + fsb = intel_uncore_read(&i915->uncore, CLKCFG) & CLKCFG_FSB_MASK; + + if (IS_PINEVIEW(i915) || IS_MOBILE(i915)) { + switch (fsb) { + case CLKCFG_FSB_400: + return 400000; + case CLKCFG_FSB_533: + return 533333; + case CLKCFG_FSB_667: + return 666667; + case CLKCFG_FSB_800: + return 800000; + case CLKCFG_FSB_1067: + return 1066667; + case CLKCFG_FSB_1333: + return 1333333; + default: + MISSING_CASE(fsb); + return 1333333; + } + } else { + switch (fsb) { + case CLKCFG_FSB_400_ALT: + return 400000; + case CLKCFG_FSB_533: + return 533333; + case CLKCFG_FSB_667: + return 666667; + case CLKCFG_FSB_800: + return 800000; + case CLKCFG_FSB_1067_ALT: + return 1066667; + case CLKCFG_FSB_1333_ALT: + return 1333333; + case CLKCFG_FSB_1600_ALT: + return 1600000; + default: + MISSING_CASE(fsb); + return 1333333; + } + } +} + +static unsigned int ilk_fsb_freq(struct drm_i915_private *dev_priv) +{ + u16 fsb; + + fsb = intel_uncore_read16(&dev_priv->uncore, CSIPLL0) & 0x3ff; + + switch (fsb) { + case 0x00c: + return 3200000; + case 0x00e: + return 3733333; + case 0x010: + return 4266667; + case 0x012: + return 4800000; + case 0x014: + return 5333333; + case 0x016: + return 5866667; + case 0x018: + return 6400000; + default: + drm_dbg(&dev_priv->drm, "unknown fsb frequency 0x%04x\n", fsb); + return 0; + } +} + +static void detect_fsb_freq(struct drm_i915_private *i915) +{ + if (GRAPHICS_VER(i915) == 5) + i915->fsb_freq = ilk_fsb_freq(i915); + else if (GRAPHICS_VER(i915) == 3 || GRAPHICS_VER(i915) == 4) + i915->fsb_freq = i9xx_fsb_freq(i915); + + if (i915->fsb_freq) + drm_dbg(&i915->drm, "FSB frequency: %d kHz\n", i915->fsb_freq); } static int intel_dimm_num_devices(const struct dram_dimm_info *dimm) @@ -640,6 +683,10 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915) case 5: dram_info->type = INTEL_DRAM_LPDDR3; break; + case 8: + drm_WARN_ON(&i915->drm, !IS_DGFX(i915)); + dram_info->type = INTEL_DRAM_GDDR; + break; default: MISSING_CASE(val); return -EINVAL; @@ -657,6 +704,7 @@ void intel_dram_detect(struct drm_i915_private *i915) struct dram_info *dram_info = &i915->dram_info; int ret; + detect_fsb_freq(i915); detect_mem_freq(i915); if (GRAPHICS_VER(i915) < 9 || IS_DG2(i915) || !HAS_DISPLAY(i915)) diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/soc/intel_dram.h index 4ba13c13162c..a10136eda674 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.h +++ b/drivers/gpu/drm/i915/soc/intel_dram.h @@ -10,5 +10,6 @@ struct drm_i915_private; void intel_dram_edram_detect(struct drm_i915_private *i915); void intel_dram_detect(struct drm_i915_private *i915); +unsigned int i9xx_fsb_freq(struct drm_i915_private *i915); #endif /* __INTEL_DRAM_H__ */ diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c index 40874ebfb64c..734e9f2801ea 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.c +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -8,7 +8,7 @@ #include <linux/vgaarb.h> #include <drm/drm_managed.h> -#include <drm/i915_drm.h> +#include <drm/intel/i915_drm.h> #include "i915_drv.h" #include "intel_gmch.h" diff --git a/drivers/gpu/drm/i915/soc/intel_pch.c b/drivers/gpu/drm/i915/soc/intel_pch.c index 3cad6dac06b0..542eea50093c 100644 --- a/drivers/gpu/drm/i915/soc/intel_pch.c +++ b/drivers/gpu/drm/i915/soc/intel_pch.c @@ -218,10 +218,10 @@ void intel_detect_pch(struct drm_i915_private *dev_priv) if (DISPLAY_VER(dev_priv) >= 20) { dev_priv->pch_type = PCH_LNL; return; - } else if (IS_METEORLAKE(dev_priv)) { + } else if (IS_BATTLEMAGE(dev_priv) || IS_METEORLAKE(dev_priv)) { /* * Both north display and south display are on the SoC die. - * The real PCH is uninvolved in display. + * The real PCH (if it even exists) is uninvolved in display. */ dev_priv->pch_type = PCH_MTL; return; diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c index 71d70194fcbd..793dfb1a3ed0 100644 --- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c +++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c @@ -72,7 +72,7 @@ struct imx_ldb_channel { struct device_node *child; struct i2c_adapter *ddc; int chno; - void *edid; + const struct drm_edid *drm_edid; struct drm_display_mode mode; int mode_valid; u32 bus_format; @@ -142,15 +142,15 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector) if (num_modes > 0) return num_modes; - if (!imx_ldb_ch->edid && imx_ldb_ch->ddc) - imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc); - - if (imx_ldb_ch->edid) { - drm_connector_update_edid_property(connector, - imx_ldb_ch->edid); - num_modes = drm_add_edid_modes(connector, imx_ldb_ch->edid); + if (!imx_ldb_ch->drm_edid && imx_ldb_ch->ddc) { + imx_ldb_ch->drm_edid = drm_edid_read_ddc(connector, + imx_ldb_ch->ddc); + drm_edid_connector_update(connector, imx_ldb_ch->drm_edid); } + if (imx_ldb_ch->drm_edid) + num_modes = drm_edid_connector_add_modes(connector); + if (imx_ldb_ch->mode_valid) { struct drm_display_mode *mode; @@ -553,7 +553,6 @@ static int imx_ldb_panel_ddc(struct device *dev, struct imx_ldb_channel *channel, struct device_node *child) { struct device_node *ddc_node; - const u8 *edidp; int ret; ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0); @@ -567,6 +566,7 @@ static int imx_ldb_panel_ddc(struct device *dev, } if (!channel->ddc) { + const void *edidp; int edid_len; /* if no DDC available, fallback to hardcoded EDID */ @@ -574,8 +574,8 @@ static int imx_ldb_panel_ddc(struct device *dev, edidp = of_get_property(child, "edid", &edid_len); if (edidp) { - channel->edid = kmemdup(edidp, edid_len, GFP_KERNEL); - if (!channel->edid) + channel->drm_edid = drm_edid_alloc(edidp, edid_len); + if (!channel->drm_edid) return -ENOMEM; } else if (!channel->panel) { /* fallback to display-timings node */ @@ -744,7 +744,7 @@ static void imx_ldb_remove(struct platform_device *pdev) for (i = 0; i < 2; i++) { struct imx_ldb_channel *channel = &imx_ldb->channel[i]; - kfree(channel->edid); + drm_edid_free(channel->drm_edid); i2c_put_adapter(channel->ddc); } diff --git a/drivers/gpu/drm/imx/ipuv3/imx-tve.c b/drivers/gpu/drm/imx/ipuv3/imx-tve.c index b49bddb85535..29f494bfff67 100644 --- a/drivers/gpu/drm/imx/ipuv3/imx-tve.c +++ b/drivers/gpu/drm/imx/ipuv3/imx-tve.c @@ -201,18 +201,16 @@ static int tve_setup_vga(struct imx_tve *tve) static int imx_tve_connector_get_modes(struct drm_connector *connector) { struct imx_tve *tve = con_to_tve(connector); - struct edid *edid; - int ret = 0; + const struct drm_edid *drm_edid; + int ret; if (!tve->ddc) return 0; - edid = drm_get_edid(connector, tve->ddc); - if (edid) { - drm_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - kfree(edid); - } + drm_edid = drm_edid_read_ddc(connector, tve->ddc); + drm_edid_connector_update(connector, drm_edid); + ret = drm_edid_connector_add_modes(connector); + drm_edid_free(drm_edid); return ret; } diff --git a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c index 43ddf3a9810b..36668455aee8 100644 --- a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c +++ b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c @@ -5,7 +5,7 @@ #include <drm/drm_bridge_connector.h> #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -501,7 +501,7 @@ static int imx_lcdc_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "Cannot register device\n"); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 0751235007a7..39fa291f43dd 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -31,7 +31,7 @@ #include <drm/drm_encoder.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_fb_dma_helper.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -1399,7 +1399,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) goto err_clk_notifier_unregister; } - drm_fbdev_generic_setup(drm, 32); + drm_fbdev_dma_setup(drm, 32); return 0; diff --git a/drivers/gpu/drm/loongson/Kconfig b/drivers/gpu/drm/loongson/Kconfig index 8e59753e532d..9ed463a76ae2 100644 --- a/drivers/gpu/drm/loongson/Kconfig +++ b/drivers/gpu/drm/loongson/Kconfig @@ -6,6 +6,7 @@ config DRM_LOONGSON depends on LOONGARCH || MIPS || COMPILE_TEST select DRM_KMS_HELPER select DRM_TTM + select DRM_TTM_HELPER select I2C select I2C_ALGOBIT help diff --git a/drivers/gpu/drm/loongson/lsdc_drv.c b/drivers/gpu/drm/loongson/lsdc_drv.c index d8ff60b46abe..adc7344d2f80 100644 --- a/drivers/gpu/drm/loongson/lsdc_drv.c +++ b/drivers/gpu/drm/loongson/lsdc_drv.c @@ -10,7 +10,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_ttm.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_ioctl.h> #include <drm/drm_modeset_helper.h> @@ -314,7 +314,7 @@ static int lsdc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) return ret; - drm_fbdev_generic_setup(ddev, 32); + drm_fbdev_ttm_setup(ddev, 32); return 0; } diff --git a/drivers/gpu/drm/loongson/lsdc_output_7a1000.c b/drivers/gpu/drm/loongson/lsdc_output_7a1000.c index 6fc8dd1c7d9a..600ed4fb0884 100644 --- a/drivers/gpu/drm/loongson/lsdc_output_7a1000.c +++ b/drivers/gpu/drm/loongson/lsdc_output_7a1000.c @@ -40,16 +40,15 @@ static int ls7a1000_dpi_connector_get_modes(struct drm_connector *conn) { - unsigned int num = 0; - struct edid *edid; + int num; if (conn->ddc) { - edid = drm_get_edid(conn, conn->ddc); - if (edid) { - drm_connector_update_edid_property(conn, edid); - num = drm_add_edid_modes(conn, edid); - kfree(edid); - } + const struct drm_edid *drm_edid; + + drm_edid = drm_edid_read(conn); + drm_edid_connector_update(conn, drm_edid); + num = drm_edid_connector_add_modes(conn); + drm_edid_free(drm_edid); return num; } diff --git a/drivers/gpu/drm/loongson/lsdc_output_7a2000.c b/drivers/gpu/drm/loongson/lsdc_output_7a2000.c index ce3dabec887e..2bd797a9b9ff 100644 --- a/drivers/gpu/drm/loongson/lsdc_output_7a2000.c +++ b/drivers/gpu/drm/loongson/lsdc_output_7a2000.c @@ -44,16 +44,15 @@ static int ls7a2000_connector_get_modes(struct drm_connector *connector) { - unsigned int num = 0; - struct edid *edid; + int num; if (connector->ddc) { - edid = drm_get_edid(connector, connector->ddc); - if (edid) { - drm_connector_update_edid_property(connector, edid); - num = drm_add_edid_modes(connector, edid); - kfree(edid); - } + const struct drm_edid *drm_edid; + + drm_edid = drm_edid_read(connector); + drm_edid_connector_update(connector, drm_edid); + num = drm_edid_connector_add_modes(connector); + drm_edid_free(drm_edid); return num; } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index b5f605751b0a..c0aa3e4e2219 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -15,7 +15,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem.h> #include <drm/drm_gem_framebuffer_helper.h> @@ -644,7 +644,7 @@ static int mtk_drm_bind(struct device *dev) if (ret < 0) goto err_deinit; - drm_fbdev_generic_setup(drm, 32); + drm_fbdev_dma_setup(drm, 32); return 0; diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 6e1cca97a654..0a90fe448d14 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1208,22 +1208,11 @@ mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_mode *mode) { struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); - struct drm_bridge *next_bridge; dev_dbg(hdmi->dev, "xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n", mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), !!(mode->flags & DRM_MODE_FLAG_INTERLACE), mode->clock * 1000); - next_bridge = drm_bridge_get_next_bridge(&hdmi->bridge); - if (next_bridge) { - struct drm_display_mode adjusted_mode; - - drm_mode_init(&adjusted_mode, mode); - if (!drm_bridge_chain_mode_fixup(next_bridge, mode, - &adjusted_mode)) - return MODE_BAD; - } - if (hdmi->conf) { if (hdmi->conf->cea_modes_only && !drm_match_cea_mode(mode)) return MODE_BAD; diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index 815dfe30492b..b43ac61201f3 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -534,6 +534,7 @@ int meson_plane_create(struct meson_drm *priv) struct meson_plane *meson_plane; struct drm_plane *plane; const uint64_t *format_modifiers = format_modifiers_default; + int ret; meson_plane = devm_kzalloc(priv->drm->dev, sizeof(*meson_plane), GFP_KERNEL); @@ -548,12 +549,16 @@ int meson_plane_create(struct meson_drm *priv) else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) format_modifiers = format_modifiers_afbc_g12a; - drm_universal_plane_init(priv->drm, plane, 0xFF, - &meson_plane_funcs, - supported_drm_formats, - ARRAY_SIZE(supported_drm_formats), - format_modifiers, - DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane"); + ret = drm_universal_plane_init(priv->drm, plane, 0xFF, + &meson_plane_funcs, + supported_drm_formats, + ARRAY_SIZE(supported_drm_formats), + format_modifiers, + DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane"); + if (ret) { + devm_kfree(priv->drm->dev, meson_plane); + return ret; + } drm_plane_helper_add(plane, &meson_plane_helper_funcs); diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig index 5e4d48df4854..3096944a8f0a 100644 --- a/drivers/gpu/drm/mgag200/Kconfig +++ b/drivers/gpu/drm/mgag200/Kconfig @@ -12,14 +12,12 @@ config DRM_MGAG200 of the modesetting userspace driver, and a version of mga driver that will fail on KMS enabled devices. -config DRM_MGAG200_IOBURST_WORKAROUND - bool "Disable buffer caching" - depends on DRM_MGAG200 && PREEMPT_RT && X86 +config DRM_MGAG200_DISABLE_WRITECOMBINE + bool "Disable Write Combine mapping of VRAM" + depends on DRM_MGAG200 && PREEMPT_RT help - Enable a workaround to avoid I/O bursts within the mgag200 driver at - the expense of overall display performance. - It restores the <v5.10 behavior, by mapping the framebuffer in system - RAM as Write-Combining, and flushing the cache after each write. - This is only useful on x86_64 if you want to run processes with - deterministic latency. - If unsure, say N. + The VRAM of the G200 is mapped with Write-Combine to improve + performances. This can interfere with real-time tasks; even if they + are running on other CPU cores than the graphics output. + Enable this option only if you run realtime tasks on a server with a + Matrox G200.
\ No newline at end of file diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile index 182e224c460d..d1b25f9f6586 100644 --- a/drivers/gpu/drm/mgag200/Makefile +++ b/drivers/gpu/drm/mgag200/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only mgag200-y := \ mgag200_bmc.o \ + mgag200_ddc.o \ mgag200_drv.o \ mgag200_g200.o \ mgag200_g200eh.o \ @@ -10,7 +11,7 @@ mgag200-y := \ mgag200_g200ew3.o \ mgag200_g200se.o \ mgag200_g200wb.o \ - mgag200_i2c.o \ - mgag200_mode.o + mgag200_mode.o \ + mgag200_vga.o obj-$(CONFIG_DRM_MGAG200) += mgag200.o diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c index 2ba2e3c5086a..23ef85aa7e37 100644 --- a/drivers/gpu/drm/mgag200/mgag200_bmc.c +++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c @@ -2,8 +2,18 @@ #include <linux/delay.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> +#include <drm/drm_managed.h> +#include <drm/drm_probe_helper.h> + #include "mgag200_drv.h" +static struct mgag200_bmc_connector *to_mgag200_bmc_connector(struct drm_connector *connector) +{ + return container_of(connector, struct mgag200_bmc_connector, base); +} + void mgag200_bmc_disable_vidrst(struct mga_device *mdev) { u8 tmp; @@ -97,3 +107,100 @@ void mgag200_bmc_enable_vidrst(struct mga_device *mdev) tmp &= ~0x10; WREG_DAC(MGA1064_GEN_IO_DATA, tmp); } + +static const struct drm_encoder_funcs mgag200_bmc_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +static int mgag200_bmc_connector_helper_detect_ctx(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force) +{ + struct mgag200_bmc_connector *bmc_connector = to_mgag200_bmc_connector(connector); + struct drm_connector *physical_connector = bmc_connector->physical_connector; + + /* + * Most user-space compositors cannot handle more than one connected + * connector per CRTC. Hence, we only mark the BMC as connected if the + * physical connector is disconnected. If the physical connector's status + * is connected or unknown, the BMC remains disconnected. This has no + * effect on the output of the BMC. + * + * FIXME: Remove this logic once user-space compositors can handle more + * than one connector per CRTC. The BMC should always be connected. + */ + + if (physical_connector && physical_connector->status == connector_status_disconnected) + return connector_status_connected; + + return connector_status_disconnected; +} + +static int mgag200_bmc_connector_helper_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct mga_device *mdev = to_mga_device(dev); + const struct mgag200_device_info *minfo = mdev->info; + + return drm_add_modes_noedid(connector, minfo->max_hdisplay, minfo->max_vdisplay); +} + +static const struct drm_connector_helper_funcs mgag200_bmc_connector_helper_funcs = { + .get_modes = mgag200_bmc_connector_helper_get_modes, + .detect_ctx = mgag200_bmc_connector_helper_detect_ctx, +}; + +static const struct drm_connector_funcs mgag200_bmc_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int mgag200_bmc_connector_init(struct drm_device *dev, + struct mgag200_bmc_connector *bmc_connector, + struct drm_connector *physical_connector) +{ + struct drm_connector *connector = &bmc_connector->base; + int ret; + + ret = drm_connector_init(dev, connector, &mgag200_bmc_connector_funcs, + DRM_MODE_CONNECTOR_VIRTUAL); + if (ret) + return ret; + drm_connector_helper_add(connector, &mgag200_bmc_connector_helper_funcs); + + bmc_connector->physical_connector = physical_connector; + + return 0; +} + +int mgag200_bmc_output_init(struct mga_device *mdev, struct drm_connector *physical_connector) +{ + struct drm_device *dev = &mdev->base; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder; + struct mgag200_bmc_connector *bmc_connector; + struct drm_connector *connector; + int ret; + + encoder = &mdev->output.bmc.encoder; + ret = drm_encoder_init(dev, encoder, &mgag200_bmc_encoder_funcs, + DRM_MODE_ENCODER_VIRTUAL, NULL); + if (ret) + return ret; + encoder->possible_crtcs = drm_crtc_mask(crtc); + + bmc_connector = &mdev->output.bmc.bmc_connector; + ret = mgag200_bmc_connector_init(dev, bmc_connector, physical_connector); + if (ret) + return ret; + connector = &bmc_connector->base; + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) + return ret; + + return 0; +} diff --git a/drivers/gpu/drm/mgag200/mgag200_ddc.c b/drivers/gpu/drm/mgag200/mgag200_ddc.c new file mode 100644 index 000000000000..6d81ea8931e8 --- /dev/null +++ b/drivers/gpu/drm/mgag200/mgag200_ddc.c @@ -0,0 +1,179 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ +/* + * Authors: Dave Airlie <airlied@redhat.com> + */ + +#include <linux/export.h> +#include <linux/i2c-algo-bit.h> +#include <linux/i2c.h> +#include <linux/pci.h> + +#include <drm/drm_managed.h> + +#include "mgag200_ddc.h" +#include "mgag200_drv.h" + +struct mgag200_ddc { + struct mga_device *mdev; + + int data; + int clock; + + struct i2c_algo_bit_data bit; + struct i2c_adapter adapter; +}; + +static int mga_i2c_read_gpio(struct mga_device *mdev) +{ + WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA); + return RREG8(DAC_DATA); +} + +static void mga_i2c_set_gpio(struct mga_device *mdev, int mask, int val) +{ + int tmp; + + WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL); + tmp = (RREG8(DAC_DATA) & mask) | val; + WREG_DAC(MGA1064_GEN_IO_CTL, tmp); + WREG_DAC(MGA1064_GEN_IO_DATA, 0); +} + +static inline void mga_i2c_set(struct mga_device *mdev, int mask, int state) +{ + if (state) + state = 0; + else + state = mask; + mga_i2c_set_gpio(mdev, ~mask, state); +} + +static void mgag200_ddc_algo_bit_data_setsda(void *data, int state) +{ + struct mgag200_ddc *ddc = data; + + mga_i2c_set(ddc->mdev, ddc->data, state); +} + +static void mgag200_ddc_algo_bit_data_setscl(void *data, int state) +{ + struct mgag200_ddc *ddc = data; + + mga_i2c_set(ddc->mdev, ddc->clock, state); +} + +static int mgag200_ddc_algo_bit_data_getsda(void *data) +{ + struct mgag200_ddc *ddc = data; + + return (mga_i2c_read_gpio(ddc->mdev) & ddc->data) ? 1 : 0; +} + +static int mgag200_ddc_algo_bit_data_getscl(void *data) +{ + struct mgag200_ddc *ddc = data; + + return (mga_i2c_read_gpio(ddc->mdev) & ddc->clock) ? 1 : 0; +} + +static int mgag200_ddc_algo_bit_data_pre_xfer(struct i2c_adapter *adapter) +{ + struct mgag200_ddc *ddc = i2c_get_adapdata(adapter); + struct mga_device *mdev = ddc->mdev; + + /* + * Protect access to I/O registers from concurrent modesetting + * by acquiring the I/O-register lock. + */ + mutex_lock(&mdev->rmmio_lock); + + return 0; +} + +static void mgag200_ddc_algo_bit_data_post_xfer(struct i2c_adapter *adapter) +{ + struct mgag200_ddc *ddc = i2c_get_adapdata(adapter); + struct mga_device *mdev = ddc->mdev; + + mutex_unlock(&mdev->rmmio_lock); +} + +static void mgag200_ddc_release(struct drm_device *dev, void *res) +{ + struct mgag200_ddc *ddc = res; + + i2c_del_adapter(&ddc->adapter); +} + +struct i2c_adapter *mgag200_ddc_create(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + const struct mgag200_device_info *info = mdev->info; + struct mgag200_ddc *ddc; + struct i2c_algo_bit_data *bit; + struct i2c_adapter *adapter; + int ret; + + ddc = drmm_kzalloc(dev, sizeof(*ddc), GFP_KERNEL); + if (!ddc) + return ERR_PTR(-ENOMEM); + + WREG_DAC(MGA1064_GEN_IO_CTL2, 1); + WREG_DAC(MGA1064_GEN_IO_DATA, 0xff); + WREG_DAC(MGA1064_GEN_IO_CTL, 0); + + ddc->mdev = mdev; + ddc->data = BIT(info->i2c.data_bit); + ddc->clock = BIT(info->i2c.clock_bit); + + bit = &ddc->bit; + bit->data = ddc; + bit->setsda = mgag200_ddc_algo_bit_data_setsda; + bit->setscl = mgag200_ddc_algo_bit_data_setscl; + bit->getsda = mgag200_ddc_algo_bit_data_getsda; + bit->getscl = mgag200_ddc_algo_bit_data_getscl; + bit->pre_xfer = mgag200_ddc_algo_bit_data_pre_xfer; + bit->post_xfer = mgag200_ddc_algo_bit_data_post_xfer; + bit->udelay = 10; + bit->timeout = usecs_to_jiffies(2200); + + adapter = &ddc->adapter; + adapter->owner = THIS_MODULE; + adapter->algo_data = bit; + adapter->dev.parent = dev->dev; + snprintf(adapter->name, sizeof(adapter->name), "Matrox DDC bus"); + i2c_set_adapdata(adapter, ddc); + + ret = i2c_bit_add_bus(adapter); + if (ret) + return ERR_PTR(ret); + + ret = drmm_add_action_or_reset(dev, mgag200_ddc_release, ddc); + if (ret) + return ERR_PTR(ret); + + return adapter; +} diff --git a/drivers/gpu/drm/mgag200/mgag200_ddc.h b/drivers/gpu/drm/mgag200/mgag200_ddc.h new file mode 100644 index 000000000000..fa21d197cc78 --- /dev/null +++ b/drivers/gpu/drm/mgag200/mgag200_ddc.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __MGAG200_DDC_H__ +#define __MGAG200_DDC_H__ + +struct i2c_adapter; +struct mga_device; + +struct i2c_adapter *mgag200_ddc_create(struct mga_device *mdev); + +#endif diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 573dbe256aa8..62080cf0f2da 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -12,7 +12,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_file.h> #include <drm/drm_ioctl.h> #include <drm/drm_managed.h> @@ -84,20 +84,6 @@ resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size) return offset - 65536; } -#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND) -static struct drm_gem_object *mgag200_create_object(struct drm_device *dev, size_t size) -{ - struct drm_gem_shmem_object *shmem; - - shmem = kzalloc(sizeof(*shmem), GFP_KERNEL); - if (!shmem) - return NULL; - - shmem->map_wc = true; - return &shmem->base; -} -#endif - /* * DRM driver */ @@ -113,9 +99,6 @@ static const struct drm_driver mgag200_driver = { .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, -#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND) - .gem_create_object = mgag200_create_object, -#endif DRM_GEM_SHMEM_DRIVER_OPS, }; @@ -163,12 +146,18 @@ int mgag200_device_preinit(struct mga_device *mdev) } mdev->vram_res = res; +#if defined(CONFIG_DRM_MGAG200_DISABLE_WRITECOMBINE) + mdev->vram = devm_ioremap(dev->dev, res->start, resource_size(res)); + if (!mdev->vram) + return -ENOMEM; +#else mdev->vram = devm_ioremap_wc(dev->dev, res->start, resource_size(res)); if (!mdev->vram) return -ENOMEM; /* Don't fail on errors, but performance might be reduced. */ devm_arch_phys_wc_add(dev->dev, res->start, resource_size(res)); +#endif return 0; } @@ -285,7 +274,7 @@ mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * FIXME: A 24-bit color depth does not work with 24 bpp on * G200ER. Force 32 bpp. */ - drm_fbdev_generic_setup(dev, 32); + drm_fbdev_shmem_setup(dev, 32); return 0; } diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 58a0e62eaf18..7f7dfbd0f013 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -10,9 +10,6 @@ #ifndef __MGAG200_DRV_H__ #define __MGAG200_DRV_H__ -#include <linux/i2c-algo-bit.h> -#include <linux/i2c.h> - #include <video/vga.h> #include <drm/drm_connector.h> @@ -189,11 +186,9 @@ static inline struct mgag200_crtc_state *to_mgag200_crtc_state(struct drm_crtc_s return container_of(base, struct mgag200_crtc_state, base); } -struct mga_i2c_chan { - struct i2c_adapter adapter; - struct drm_device *dev; - struct i2c_algo_bit_data bit; - int data, clock; +struct mgag200_bmc_connector { + struct drm_connector base; + struct drm_connector *physical_connector; }; enum mga_type { @@ -293,9 +288,16 @@ struct mga_device { struct drm_plane primary_plane; struct drm_crtc crtc; - struct drm_encoder encoder; - struct mga_i2c_chan i2c; - struct drm_connector connector; + struct { + struct { + struct drm_encoder encoder; + struct drm_connector connector; + } vga; + struct { + struct drm_encoder encoder; + struct mgag200_bmc_connector bmc_connector; + } bmc; + } output; }; static inline struct mga_device *to_mga_device(struct drm_device *dev) @@ -428,32 +430,18 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st .atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state, \ .atomic_destroy_state = mgag200_crtc_atomic_destroy_state -#define MGAG200_DAC_ENCODER_FUNCS \ - .destroy = drm_encoder_cleanup - -int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector); - -#define MGAG200_VGA_CONNECTOR_HELPER_FUNCS \ - .get_modes = mgag200_vga_connector_helper_get_modes - -#define MGAG200_VGA_CONNECTOR_FUNCS \ - .reset = drm_atomic_helper_connector_reset, \ - .fill_modes = drm_helper_probe_single_connector_modes, \ - .destroy = drm_connector_cleanup, \ - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, \ - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state - void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode); void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format); void mgag200_enable_display(struct mga_device *mdev); void mgag200_init_registers(struct mga_device *mdev); int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available); +/* mgag200_vga.c */ +int mgag200_vga_output_init(struct mga_device *mdev); + /* mgag200_bmc.c */ void mgag200_bmc_disable_vidrst(struct mga_device *mdev); void mgag200_bmc_enable_vidrst(struct mga_device *mdev); - - /* mgag200_i2c.c */ -int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c); +int mgag200_bmc_output_init(struct mga_device *mdev, struct drm_connector *physical_connector); #endif /* __MGAG200_DRV_H__ */ diff --git a/drivers/gpu/drm/mgag200/mgag200_g200.c b/drivers/gpu/drm/mgag200/mgag200_g200.c index bf5d7fe525a3..f874e2949840 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200.c @@ -183,26 +183,11 @@ static const struct drm_crtc_funcs mgag200_g200_crtc_funcs = { MGAG200_CRTC_FUNCS, }; -static const struct drm_encoder_funcs mgag200_g200_dac_encoder_funcs = { - MGAG200_DAC_ENCODER_FUNCS, -}; - -static const struct drm_connector_helper_funcs mgag200_g200_vga_connector_helper_funcs = { - MGAG200_VGA_CONNECTOR_HELPER_FUNCS, -}; - -static const struct drm_connector_funcs mgag200_g200_vga_connector_funcs = { - MGAG200_VGA_CONNECTOR_FUNCS, -}; - static int mgag200_g200_pipeline_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; struct drm_plane *primary_plane = &mdev->primary_plane; struct drm_crtc *crtc = &mdev->crtc; - struct drm_encoder *encoder = &mdev->encoder; - struct mga_i2c_chan *i2c = &mdev->i2c; - struct drm_connector *connector = &mdev->connector; int ret; ret = drm_universal_plane_init(dev, primary_plane, 0, @@ -230,35 +215,9 @@ static int mgag200_g200_pipeline_init(struct mga_device *mdev) drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); - encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = drm_encoder_init(dev, encoder, &mgag200_g200_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC, NULL); - if (ret) { - drm_err(dev, "drm_encoder_init() failed: %d\n", ret); - return ret; - } - - ret = mgag200_i2c_init(mdev, i2c); - if (ret) { - drm_err(dev, "failed to add DDC bus: %d\n", ret); - return ret; - } - - ret = drm_connector_init_with_ddc(dev, connector, - &mgag200_g200_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - &i2c->adapter); - if (ret) { - drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); - return ret; - } - drm_connector_helper_add(connector, &mgag200_g200_vga_connector_helper_funcs); - - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) { - drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + ret = mgag200_vga_output_init(mdev); + if (ret) return ret; - } return 0; } @@ -442,6 +401,7 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct return ERR_PTR(ret); drm_mode_config_reset(dev); + drm_kms_helper_poll_init(dev); return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c index fad62453a91d..52bf49ead5c5 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c @@ -182,26 +182,11 @@ static const struct drm_crtc_funcs mgag200_g200eh_crtc_funcs = { MGAG200_CRTC_FUNCS, }; -static const struct drm_encoder_funcs mgag200_g200eh_dac_encoder_funcs = { - MGAG200_DAC_ENCODER_FUNCS, -}; - -static const struct drm_connector_helper_funcs mgag200_g200eh_vga_connector_helper_funcs = { - MGAG200_VGA_CONNECTOR_HELPER_FUNCS, -}; - -static const struct drm_connector_funcs mgag200_g200eh_vga_connector_funcs = { - MGAG200_VGA_CONNECTOR_FUNCS, -}; - static int mgag200_g200eh_pipeline_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; struct drm_plane *primary_plane = &mdev->primary_plane; struct drm_crtc *crtc = &mdev->crtc; - struct drm_encoder *encoder = &mdev->encoder; - struct mga_i2c_chan *i2c = &mdev->i2c; - struct drm_connector *connector = &mdev->connector; int ret; ret = drm_universal_plane_init(dev, primary_plane, 0, @@ -229,35 +214,13 @@ static int mgag200_g200eh_pipeline_init(struct mga_device *mdev) drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); - encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = drm_encoder_init(dev, encoder, &mgag200_g200eh_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC, NULL); - if (ret) { - drm_err(dev, "drm_encoder_init() failed: %d\n", ret); - return ret; - } - - ret = mgag200_i2c_init(mdev, i2c); - if (ret) { - drm_err(dev, "failed to add DDC bus: %d\n", ret); - return ret; - } - - ret = drm_connector_init_with_ddc(dev, connector, - &mgag200_g200eh_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - &i2c->adapter); - if (ret) { - drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + ret = mgag200_vga_output_init(mdev); + if (ret) return ret; - } - drm_connector_helper_add(connector, &mgag200_g200eh_vga_connector_helper_funcs); - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) { - drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector); + if (ret) return ret; - } return 0; } @@ -314,6 +277,7 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru return ERR_PTR(ret); drm_mode_config_reset(dev); + drm_kms_helper_poll_init(dev); return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c index 0f7d8112cd49..e7f89b2a59fd 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c @@ -86,26 +86,11 @@ static const struct drm_crtc_funcs mgag200_g200eh3_crtc_funcs = { MGAG200_CRTC_FUNCS, }; -static const struct drm_encoder_funcs mgag200_g200eh3_dac_encoder_funcs = { - MGAG200_DAC_ENCODER_FUNCS, -}; - -static const struct drm_connector_helper_funcs mgag200_g200eh3_vga_connector_helper_funcs = { - MGAG200_VGA_CONNECTOR_HELPER_FUNCS, -}; - -static const struct drm_connector_funcs mgag200_g200eh3_vga_connector_funcs = { - MGAG200_VGA_CONNECTOR_FUNCS, -}; - static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; struct drm_plane *primary_plane = &mdev->primary_plane; struct drm_crtc *crtc = &mdev->crtc; - struct drm_encoder *encoder = &mdev->encoder; - struct mga_i2c_chan *i2c = &mdev->i2c; - struct drm_connector *connector = &mdev->connector; int ret; ret = drm_universal_plane_init(dev, primary_plane, 0, @@ -133,35 +118,13 @@ static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev) drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); - encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = drm_encoder_init(dev, encoder, &mgag200_g200eh3_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC, NULL); - if (ret) { - drm_err(dev, "drm_encoder_init() failed: %d\n", ret); - return ret; - } - - ret = mgag200_i2c_init(mdev, i2c); - if (ret) { - drm_err(dev, "failed to add DDC bus: %d\n", ret); - return ret; - } - - ret = drm_connector_init_with_ddc(dev, connector, - &mgag200_g200eh3_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - &i2c->adapter); - if (ret) { - drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + ret = mgag200_vga_output_init(mdev); + if (ret) return ret; - } - drm_connector_helper_add(connector, &mgag200_g200eh3_vga_connector_helper_funcs); - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) { - drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector); + if (ret) return ret; - } return 0; } @@ -219,6 +182,7 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, return ERR_PTR(ret); drm_mode_config_reset(dev); + drm_kms_helper_poll_init(dev); return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c index 8d4538b71047..4e8a1756138d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -225,26 +225,11 @@ static const struct drm_crtc_funcs mgag200_g200er_crtc_funcs = { MGAG200_CRTC_FUNCS, }; -static const struct drm_encoder_funcs mgag200_g200er_dac_encoder_funcs = { - MGAG200_DAC_ENCODER_FUNCS, -}; - -static const struct drm_connector_helper_funcs mgag200_g200er_vga_connector_helper_funcs = { - MGAG200_VGA_CONNECTOR_HELPER_FUNCS, -}; - -static const struct drm_connector_funcs mgag200_g200er_vga_connector_funcs = { - MGAG200_VGA_CONNECTOR_FUNCS, -}; - static int mgag200_g200er_pipeline_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; struct drm_plane *primary_plane = &mdev->primary_plane; struct drm_crtc *crtc = &mdev->crtc; - struct drm_encoder *encoder = &mdev->encoder; - struct mga_i2c_chan *i2c = &mdev->i2c; - struct drm_connector *connector = &mdev->connector; int ret; ret = drm_universal_plane_init(dev, primary_plane, 0, @@ -272,35 +257,13 @@ static int mgag200_g200er_pipeline_init(struct mga_device *mdev) drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); - encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = drm_encoder_init(dev, encoder, &mgag200_g200er_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC, NULL); - if (ret) { - drm_err(dev, "drm_encoder_init() failed: %d\n", ret); - return ret; - } - - ret = mgag200_i2c_init(mdev, i2c); - if (ret) { - drm_err(dev, "failed to add DDC bus: %d\n", ret); - return ret; - } - - ret = drm_connector_init_with_ddc(dev, connector, - &mgag200_g200er_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - &i2c->adapter); - if (ret) { - drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + ret = mgag200_vga_output_init(mdev); + if (ret) return ret; - } - drm_connector_helper_add(connector, &mgag200_g200er_vga_connector_helper_funcs); - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) { - drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector); + if (ret) return ret; - } return 0; } @@ -353,6 +316,7 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru return ERR_PTR(ret); drm_mode_config_reset(dev); + drm_kms_helper_poll_init(dev); return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c index 56e6f986bff3..d884f3cb0ec7 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -226,26 +226,11 @@ static const struct drm_crtc_funcs mgag200_g200ev_crtc_funcs = { MGAG200_CRTC_FUNCS, }; -static const struct drm_encoder_funcs mgag200_g200ev_dac_encoder_funcs = { - MGAG200_DAC_ENCODER_FUNCS, -}; - -static const struct drm_connector_helper_funcs mgag200_g200ev_vga_connector_helper_funcs = { - MGAG200_VGA_CONNECTOR_HELPER_FUNCS, -}; - -static const struct drm_connector_funcs mgag200_g200ev_vga_connector_funcs = { - MGAG200_VGA_CONNECTOR_FUNCS, -}; - static int mgag200_g200ev_pipeline_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; struct drm_plane *primary_plane = &mdev->primary_plane; struct drm_crtc *crtc = &mdev->crtc; - struct drm_encoder *encoder = &mdev->encoder; - struct mga_i2c_chan *i2c = &mdev->i2c; - struct drm_connector *connector = &mdev->connector; int ret; ret = drm_universal_plane_init(dev, primary_plane, 0, @@ -273,35 +258,13 @@ static int mgag200_g200ev_pipeline_init(struct mga_device *mdev) drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); - encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = drm_encoder_init(dev, encoder, &mgag200_g200ev_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC, NULL); - if (ret) { - drm_err(dev, "drm_encoder_init() failed: %d\n", ret); - return ret; - } - - ret = mgag200_i2c_init(mdev, i2c); - if (ret) { - drm_err(dev, "failed to add DDC bus: %d\n", ret); - return ret; - } - - ret = drm_connector_init_with_ddc(dev, connector, - &mgag200_g200ev_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - &i2c->adapter); - if (ret) { - drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + ret = mgag200_vga_output_init(mdev); + if (ret) return ret; - } - drm_connector_helper_add(connector, &mgag200_g200ev_vga_connector_helper_funcs); - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) { - drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector); + if (ret) return ret; - } return 0; } @@ -358,6 +321,7 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru return ERR_PTR(ret); drm_mode_config_reset(dev); + drm_kms_helper_poll_init(dev); return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c index 170934414d7d..839401e8b465 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c @@ -95,26 +95,11 @@ static const struct drm_crtc_funcs mgag200_g200ew3_crtc_funcs = { MGAG200_CRTC_FUNCS, }; -static const struct drm_encoder_funcs mgag200_g200ew3_dac_encoder_funcs = { - MGAG200_DAC_ENCODER_FUNCS, -}; - -static const struct drm_connector_helper_funcs mgag200_g200ew3_vga_connector_helper_funcs = { - MGAG200_VGA_CONNECTOR_HELPER_FUNCS, -}; - -static const struct drm_connector_funcs mgag200_g200ew3_vga_connector_funcs = { - MGAG200_VGA_CONNECTOR_FUNCS, -}; - static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; struct drm_plane *primary_plane = &mdev->primary_plane; struct drm_crtc *crtc = &mdev->crtc; - struct drm_encoder *encoder = &mdev->encoder; - struct mga_i2c_chan *i2c = &mdev->i2c; - struct drm_connector *connector = &mdev->connector; int ret; ret = drm_universal_plane_init(dev, primary_plane, 0, @@ -142,35 +127,13 @@ static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev) drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); - encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = drm_encoder_init(dev, encoder, &mgag200_g200ew3_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC, NULL); - if (ret) { - drm_err(dev, "drm_encoder_init() failed: %d\n", ret); - return ret; - } - - ret = mgag200_i2c_init(mdev, i2c); - if (ret) { - drm_err(dev, "failed to add DDC bus: %d\n", ret); - return ret; - } - - ret = drm_connector_init_with_ddc(dev, connector, - &mgag200_g200ew3_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - &i2c->adapter); - if (ret) { - drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + ret = mgag200_vga_output_init(mdev); + if (ret) return ret; - } - drm_connector_helper_add(connector, &mgag200_g200ew3_vga_connector_helper_funcs); - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) { - drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector); + if (ret) return ret; - } return 0; } @@ -239,6 +202,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, return ERR_PTR(ret); drm_mode_config_reset(dev); + drm_kms_helper_poll_init(dev); return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c index ff2b3c6622e7..a824bb8ad579 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c @@ -357,26 +357,11 @@ static const struct drm_crtc_funcs mgag200_g200se_crtc_funcs = { MGAG200_CRTC_FUNCS, }; -static const struct drm_encoder_funcs mgag200_g200se_dac_encoder_funcs = { - MGAG200_DAC_ENCODER_FUNCS, -}; - -static const struct drm_connector_helper_funcs mgag200_g200se_vga_connector_helper_funcs = { - MGAG200_VGA_CONNECTOR_HELPER_FUNCS, -}; - -static const struct drm_connector_funcs mgag200_g200se_vga_connector_funcs = { - MGAG200_VGA_CONNECTOR_FUNCS, -}; - static int mgag200_g200se_pipeline_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; struct drm_plane *primary_plane = &mdev->primary_plane; struct drm_crtc *crtc = &mdev->crtc; - struct drm_encoder *encoder = &mdev->encoder; - struct mga_i2c_chan *i2c = &mdev->i2c; - struct drm_connector *connector = &mdev->connector; int ret; ret = drm_universal_plane_init(dev, primary_plane, 0, @@ -404,35 +389,13 @@ static int mgag200_g200se_pipeline_init(struct mga_device *mdev) drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); - encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = drm_encoder_init(dev, encoder, &mgag200_g200se_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC, NULL); - if (ret) { - drm_err(dev, "drm_encoder_init() failed: %d\n", ret); - return ret; - } - - ret = mgag200_i2c_init(mdev, i2c); - if (ret) { - drm_err(dev, "failed to add DDC bus: %d\n", ret); - return ret; - } - - ret = drm_connector_init_with_ddc(dev, connector, - &mgag200_g200se_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - &i2c->adapter); - if (ret) { - drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + ret = mgag200_vga_output_init(mdev); + if (ret) return ret; - } - drm_connector_helper_add(connector, &mgag200_g200se_vga_connector_helper_funcs); - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) { - drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector); + if (ret) return ret; - } return 0; } @@ -558,6 +521,7 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru return ERR_PTR(ret); drm_mode_config_reset(dev); + drm_kms_helper_poll_init(dev); return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c index 9baa727ac6f9..835df0f4fc13 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c @@ -229,26 +229,11 @@ static const struct drm_crtc_funcs mgag200_g200wb_crtc_funcs = { MGAG200_CRTC_FUNCS, }; -static const struct drm_encoder_funcs mgag200_g200wb_dac_encoder_funcs = { - MGAG200_DAC_ENCODER_FUNCS, -}; - -static const struct drm_connector_helper_funcs mgag200_g200wb_vga_connector_helper_funcs = { - MGAG200_VGA_CONNECTOR_HELPER_FUNCS, -}; - -static const struct drm_connector_funcs mgag200_g200wb_vga_connector_funcs = { - MGAG200_VGA_CONNECTOR_FUNCS, -}; - static int mgag200_g200wb_pipeline_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; struct drm_plane *primary_plane = &mdev->primary_plane; struct drm_crtc *crtc = &mdev->crtc; - struct drm_encoder *encoder = &mdev->encoder; - struct mga_i2c_chan *i2c = &mdev->i2c; - struct drm_connector *connector = &mdev->connector; int ret; ret = drm_universal_plane_init(dev, primary_plane, 0, @@ -276,35 +261,13 @@ static int mgag200_g200wb_pipeline_init(struct mga_device *mdev) drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); - encoder->possible_crtcs = drm_crtc_mask(crtc); - ret = drm_encoder_init(dev, encoder, &mgag200_g200wb_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC, NULL); - if (ret) { - drm_err(dev, "drm_encoder_init() failed: %d\n", ret); - return ret; - } - - ret = mgag200_i2c_init(mdev, i2c); - if (ret) { - drm_err(dev, "failed to add DDC bus: %d\n", ret); - return ret; - } - - ret = drm_connector_init_with_ddc(dev, connector, - &mgag200_g200wb_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - &i2c->adapter); - if (ret) { - drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + ret = mgag200_vga_output_init(mdev); + if (ret) return ret; - } - drm_connector_helper_add(connector, &mgag200_g200wb_vga_connector_helper_funcs); - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) { - drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector); + if (ret) return ret; - } return 0; } @@ -363,6 +326,7 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru return ERR_PTR(ret); drm_mode_config_reset(dev); + drm_kms_helper_poll_init(dev); return mdev; } diff --git a/drivers/gpu/drm/mgag200/mgag200_i2c.c b/drivers/gpu/drm/mgag200/mgag200_i2c.c deleted file mode 100644 index 423eb302be7e..000000000000 --- a/drivers/gpu/drm/mgag200/mgag200_i2c.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - */ -/* - * Authors: Dave Airlie <airlied@redhat.com> - */ - -#include <linux/export.h> -#include <linux/i2c-algo-bit.h> -#include <linux/i2c.h> -#include <linux/pci.h> - -#include "mgag200_drv.h" - -static int mga_i2c_read_gpio(struct mga_device *mdev) -{ - WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA); - return RREG8(DAC_DATA); -} - -static void mga_i2c_set_gpio(struct mga_device *mdev, int mask, int val) -{ - int tmp; - - WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL); - tmp = (RREG8(DAC_DATA) & mask) | val; - WREG_DAC(MGA1064_GEN_IO_CTL, tmp); - WREG_DAC(MGA1064_GEN_IO_DATA, 0); -} - -static inline void mga_i2c_set(struct mga_device *mdev, int mask, int state) -{ - if (state) - state = 0; - else - state = mask; - mga_i2c_set_gpio(mdev, ~mask, state); -} - -static void mga_gpio_setsda(void *data, int state) -{ - struct mga_i2c_chan *i2c = data; - struct mga_device *mdev = to_mga_device(i2c->dev); - mga_i2c_set(mdev, i2c->data, state); -} - -static void mga_gpio_setscl(void *data, int state) -{ - struct mga_i2c_chan *i2c = data; - struct mga_device *mdev = to_mga_device(i2c->dev); - mga_i2c_set(mdev, i2c->clock, state); -} - -static int mga_gpio_getsda(void *data) -{ - struct mga_i2c_chan *i2c = data; - struct mga_device *mdev = to_mga_device(i2c->dev); - return (mga_i2c_read_gpio(mdev) & i2c->data) ? 1 : 0; -} - -static int mga_gpio_getscl(void *data) -{ - struct mga_i2c_chan *i2c = data; - struct mga_device *mdev = to_mga_device(i2c->dev); - return (mga_i2c_read_gpio(mdev) & i2c->clock) ? 1 : 0; -} - -static void mgag200_i2c_release(void *res) -{ - struct mga_i2c_chan *i2c = res; - - i2c_del_adapter(&i2c->adapter); -} - -int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c) -{ - struct drm_device *dev = &mdev->base; - const struct mgag200_device_info *info = mdev->info; - int ret; - - WREG_DAC(MGA1064_GEN_IO_CTL2, 1); - WREG_DAC(MGA1064_GEN_IO_DATA, 0xff); - WREG_DAC(MGA1064_GEN_IO_CTL, 0); - - i2c->data = BIT(info->i2c.data_bit); - i2c->clock = BIT(info->i2c.clock_bit); - i2c->adapter.owner = THIS_MODULE; - i2c->adapter.dev.parent = dev->dev; - i2c->dev = dev; - i2c_set_adapdata(&i2c->adapter, i2c); - snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "mga i2c"); - - i2c->adapter.algo_data = &i2c->bit; - - i2c->bit.udelay = 10; - i2c->bit.timeout = 2; - i2c->bit.data = i2c; - i2c->bit.setsda = mga_gpio_setsda; - i2c->bit.setscl = mga_gpio_setscl; - i2c->bit.getsda = mga_gpio_getsda; - i2c->bit.getscl = mga_gpio_getscl; - - ret = i2c_bit_add_bus(&i2c->adapter); - if (ret) - return ret; - - return devm_add_action_or_reset(dev->dev, mgag200_i2c_release, i2c); -} diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index fc54851d3384..bb6204002cb3 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -13,7 +13,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_cache.h> #include <drm/drm_damage_helper.h> #include <drm/drm_edid.h> #include <drm/drm_format_helper.h> @@ -24,6 +23,7 @@ #include <drm/drm_panic.h> #include <drm/drm_print.h> +#include "mgag200_ddc.h" #include "mgag200_drv.h" /* @@ -438,13 +438,6 @@ static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_ma iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip)); drm_fb_memcpy(&dst, fb->pitches, vmap, fb, clip); - - /* Flushing the cache greatly improves latency on x86_64 */ -#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND) - if (!vmap->is_iomem) - drm_clflush_virt_range(vmap->vaddr + clip->y1 * fb->pitches[0], - drm_rect_height(clip) * fb->pitches[0]); -#endif } /* @@ -737,32 +730,6 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st } /* - * Connector - */ - -int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector) -{ - struct mga_device *mdev = to_mga_device(connector->dev); - const struct drm_edid *drm_edid; - int count; - - /* - * Protect access to I/O registers from concurrent modesetting - * by acquiring the I/O-register lock. - */ - mutex_lock(&mdev->rmmio_lock); - - drm_edid = drm_edid_read(connector); - drm_edid_connector_update(connector, drm_edid); - count = drm_edid_connector_add_modes(connector); - drm_edid_free(drm_edid); - - mutex_unlock(&mdev->rmmio_lock); - - return count; -} - -/* * Mode config */ diff --git a/drivers/gpu/drm/mgag200/mgag200_vga.c b/drivers/gpu/drm/mgag200/mgag200_vga.c new file mode 100644 index 000000000000..60568f32736d --- /dev/null +++ b/drivers/gpu/drm/mgag200/mgag200_vga.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_probe_helper.h> + +#include "mgag200_ddc.h" +#include "mgag200_drv.h" + +static const struct drm_encoder_funcs mgag200_dac_encoder_funcs = { + .destroy = drm_encoder_cleanup +}; + +static const struct drm_connector_helper_funcs mgag200_vga_connector_helper_funcs = { + .get_modes = drm_connector_helper_get_modes, + .detect_ctx = drm_connector_helper_detect_from_ddc +}; + +static const struct drm_connector_funcs mgag200_vga_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state +}; + +int mgag200_vga_output_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + struct drm_crtc *crtc = &mdev->crtc; + struct drm_encoder *encoder; + struct drm_connector *connector; + struct i2c_adapter *ddc; + int ret; + + encoder = &mdev->output.vga.encoder; + ret = drm_encoder_init(dev, encoder, &mgag200_dac_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + if (ret) { + drm_err(dev, "drm_encoder_init() failed: %d\n", ret); + return ret; + } + encoder->possible_crtcs = drm_crtc_mask(crtc); + + ddc = mgag200_ddc_create(mdev); + if (IS_ERR(ddc)) { + ret = PTR_ERR(ddc); + drm_err(dev, "failed to add DDC bus: %d\n", ret); + return ret; + } + + connector = &mdev->output.vga.connector; + ret = drm_connector_init_with_ddc(dev, connector, + &mgag200_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, ddc); + if (ret) { + drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret); + return ret; + } + drm_connector_helper_add(connector, &mgag200_vga_connector_helper_funcs); + + connector->polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret); + return ret; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 88728a0b2c25..ac9657d7e92d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -751,7 +751,7 @@ nv50_audio_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc, struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nvif_outp *outp = &nv_encoder->outp; - if (!nv50_audio_supported(encoder) || !drm_detect_monitor_audio(nv_connector->edid)) + if (!nv50_audio_supported(encoder) || !nv_connector->base.display_info.has_audio) return; mutex_lock(&drm->audio.lock); @@ -1765,7 +1765,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta if ((disp->disp->object.oclass == GT214_DISP || disp->disp->object.oclass >= GF110_DISP) && nv_encoder->dcb->type != DCB_OUTPUT_LVDS && - drm_detect_monitor_audio(nv_connector->edid)) + nv_connector->base.display_info.has_audio) hda = true; if (!nvif_outp_acquired(outp)) @@ -1774,7 +1774,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta switch (nv_encoder->dcb->type) { case DCB_OUTPUT_TMDS: if (disp->disp->object.oclass != NV50_DISP && - drm_detect_hdmi_monitor(nv_connector->edid)) + nv_connector->base.display_info.is_hdmi) nv50_hdmi_enable(encoder, nv_crtc, nv_connector, state, mode, hda); if (nv_encoder->outp.or.link & 1) { @@ -1787,7 +1787,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta */ if (mode->clock >= 165000 && nv_encoder->dcb->duallink_possible && - !drm_detect_hdmi_monitor(nv_connector->edid)) + !nv_connector->base.display_info.is_hdmi) proto = NV507D_SOR_SET_CONTROL_PROTOCOL_DUAL_TMDS; } else { proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_B; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index 83355dbc15ee..d7c74cc43ba5 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -127,14 +127,8 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh, struct drm_display_mode *omode = &asyh->state.adjusted_mode; struct drm_display_mode *umode = &asyh->state.mode; int mode = asyc->scaler.mode; - struct edid *edid; int umode_vdisplay, omode_hdisplay, omode_vdisplay; - if (connector->edid_blob_ptr) - edid = (struct edid *)connector->edid_blob_ptr->data; - else - edid = NULL; - if (!asyc->scaler.full) { if (mode == DRM_MODE_SCALE_NONE) omode = umode; @@ -162,7 +156,7 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh, */ if ((asyc->scaler.underscan.mode == UNDERSCAN_ON || (asyc->scaler.underscan.mode == UNDERSCAN_AUTO && - drm_detect_hdmi_monitor(edid)))) { + connector->display_info.is_hdmi))) { u32 bX = asyc->scaler.underscan.hborder; u32 bY = asyc->scaler.underscan.vborder; u32 r = (asyh->view.oH << 19) / asyh->view.oW; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h index a11d16a16c3b..9e6f39912368 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h @@ -213,6 +213,12 @@ struct nvkm_gsp { struct mutex mutex;; struct idr idr; } client_id; + + /* A linked list of registry items. The registry RPC will be built from it. */ + struct list_head registry_list; + + /* The size of the registry RPC */ + size_t registry_rpc_size; }; static inline bool diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 70fb003a6666..0712d0b15170 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -898,7 +898,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, * Without this the operation can timeout and we'll fallback to a * software copy, which might take several minutes to finish. */ - nouveau_fence_wait(fence, false, false); + nouveau_fence_wait(fence, false); ret = ttm_bo_move_accel_cleanup(bo, &fence->base, evict, false, new_reg); nouveau_fence_unref(&fence); diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 7c97b2886807..66fca95c10c7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -72,7 +72,7 @@ nouveau_channel_idle(struct nouveau_channel *chan) ret = nouveau_fence_new(&fence, chan); if (!ret) { - ret = nouveau_fence_wait(fence, false, false); + ret = nouveau_fence_wait(fence, false); nouveau_fence_unref(&fence); } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 856b3ef5edb8..938832a6af15 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1034,7 +1034,7 @@ get_tmds_link_bandwidth(struct drm_connector *connector) unsigned duallink_scale = nouveau_duallink && nv_encoder->dcb->duallink_possible ? 2 : 1; - if (drm_detect_hdmi_monitor(nv_connector->edid)) { + if (nv_connector->base.display_info.is_hdmi) { info = &nv_connector->base.display_info; duallink_scale = 1; } diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c index 6fb65b01d778..6719353e2e13 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c @@ -128,7 +128,7 @@ static void nouveau_dmem_page_free(struct page *page) static void nouveau_dmem_fence_done(struct nouveau_fence **fence) { if (fence) { - nouveau_fence_wait(*fence, true, false); + nouveau_fence_wait(*fence, false); nouveau_fence_unref(fence); } else { /* diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index a947e1d5f309..a58c31089613 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -32,7 +32,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_ttm.h> #include <drm/drm_gem_ttm_helper.h> #include <drm/drm_ioctl.h> #include <drm/drm_vblank.h> @@ -846,9 +846,9 @@ static int nouveau_drm_probe(struct pci_dev *pdev, goto fail_drm_dev_init; if (nouveau_drm(drm_dev)->client.device.info.ram_size <= 32 * 1024 * 1024) - drm_fbdev_generic_setup(drm_dev, 8); + drm_fbdev_ttm_setup(drm_dev, 8); else - drm_fbdev_generic_setup(drm_dev, 32); + drm_fbdev_ttm_setup(drm_dev, 32); quirk_broken_nv_runpm(pdev); return 0; diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c index e65c0ef23bc7..a0b5f1b16e8b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_exec.c +++ b/drivers/gpu/drm/nouveau/nouveau_exec.c @@ -188,7 +188,7 @@ nouveau_exec_job_timeout(struct nouveau_job *job) return DRM_GPU_SCHED_STAT_NOMINAL; } -static struct nouveau_job_ops nouveau_exec_job_ops = { +static const struct nouveau_job_ops nouveau_exec_job_ops = { .submit = nouveau_exec_job_submit, .armed_submit = nouveau_exec_job_armed_submit, .run = nouveau_exec_job_run, diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 93f08f9479d8..ba469767a20f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -311,39 +311,11 @@ nouveau_fence_wait_legacy(struct dma_fence *f, bool intr, long wait) return timeout - t; } -static int -nouveau_fence_wait_busy(struct nouveau_fence *fence, bool intr) -{ - int ret = 0; - - while (!nouveau_fence_done(fence)) { - if (time_after_eq(jiffies, fence->timeout)) { - ret = -EBUSY; - break; - } - - __set_current_state(intr ? - TASK_INTERRUPTIBLE : - TASK_UNINTERRUPTIBLE); - - if (intr && signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - } - - __set_current_state(TASK_RUNNING); - return ret; -} - int -nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) +nouveau_fence_wait(struct nouveau_fence *fence, bool intr) { long ret; - if (!lazy) - return nouveau_fence_wait_busy(fence, intr); - ret = dma_fence_wait_timeout(&fence->base, intr, 15 * HZ); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 8bc065acfe35..1b63197b744a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -23,7 +23,7 @@ void nouveau_fence_unref(struct nouveau_fence **); int nouveau_fence_emit(struct nouveau_fence *); bool nouveau_fence_done(struct nouveau_fence *); -int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); +int nouveau_fence_wait(struct nouveau_fence *, bool intr); int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); struct nouveau_fence_chan { diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 5a887d67dc0e..2e535caa7d6e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -928,7 +928,7 @@ revalidate: } if (sync) { - if (!(ret = nouveau_fence_wait(fence, false, false))) { + if (!(ret = nouveau_fence_wait(fence, false))) { if ((ret = dma_fence_get_status(&fence->base)) == 1) ret = 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.h b/drivers/gpu/drm/nouveau/nouveau_sched.h index e1f01a23e6f6..20cd1da8db73 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sched.h +++ b/drivers/gpu/drm/nouveau/nouveau_sched.h @@ -42,7 +42,7 @@ struct nouveau_job_args { u32 count; } out_sync; - struct nouveau_job_ops *ops; + const struct nouveau_job_ops *ops; }; struct nouveau_job { @@ -73,7 +73,7 @@ struct nouveau_job { u32 count; } out_sync; - struct nouveau_job_ops { + const struct nouveau_job_ops { /* If .submit() returns without any error, it is guaranteed that * armed_submit() is called. */ diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c index ee02cd833c5e..9402fa320a7e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c +++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c @@ -1534,7 +1534,7 @@ nouveau_uvmm_bind_job_cleanup(struct nouveau_job *job) nouveau_uvmm_bind_job_put(bind_job); } -static struct nouveau_job_ops nouveau_bind_job_ops = { +static const struct nouveau_job_ops nouveau_bind_job_ops = { .submit = nouveau_uvmm_bind_job_submit, .armed_submit = nouveau_uvmm_bind_job_armed_submit, .run = nouveau_uvmm_bind_job_run, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index abe41f7a3404..cf58f9da9139 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -54,6 +54,8 @@ #include <nvrm/535.113.01/nvidia/kernel/inc/vgpu/rpc_global_enums.h> #include <linux/acpi.h> +#include <linux/ctype.h> +#include <linux/parser.h> #define GSP_MSG_MIN_SIZE GSP_PAGE_SIZE #define GSP_MSG_MAX_SIZE GSP_PAGE_MIN_SIZE * 16 @@ -1080,53 +1082,365 @@ r535_gsp_rpc_unloading_guest_driver(struct nvkm_gsp *gsp, bool suspend) return nvkm_gsp_rpc_wr(gsp, rpc, true); } +enum registry_type { + REGISTRY_TABLE_ENTRY_TYPE_DWORD = 1, /* 32-bit unsigned integer */ + REGISTRY_TABLE_ENTRY_TYPE_BINARY = 2, /* Binary blob */ + REGISTRY_TABLE_ENTRY_TYPE_STRING = 3, /* Null-terminated string */ +}; + +/* An arbitrary limit to the length of a registry key */ +#define REGISTRY_MAX_KEY_LENGTH 64 + +/** + * registry_list_entry - linked list member for a registry key/value + * @head: list_head struct + * @type: dword, binary, or string + * @klen: the length of name of the key + * @vlen: the length of the value + * @key: the key name + * @dword: the data, if REGISTRY_TABLE_ENTRY_TYPE_DWORD + * @binary: the data, if TYPE_BINARY or TYPE_STRING + * + * Every registry key/value is represented internally by this struct. + * + * Type DWORD is a simple 32-bit unsigned integer, and its value is stored in + * @dword. + * + * Types BINARY and STRING are variable-length binary blobs. The only real + * difference between BINARY and STRING is that STRING is null-terminated and + * is expected to contain only printable characters. + * + * Note: it is technically possible to have multiple keys with the same name + * but different types, but this is not useful since GSP-RM expects keys to + * have only one specific type. + */ +struct registry_list_entry { + struct list_head head; + enum registry_type type; + size_t klen; + char key[REGISTRY_MAX_KEY_LENGTH]; + size_t vlen; + u32 dword; /* TYPE_DWORD */ + u8 binary[] __counted_by(vlen); /* TYPE_BINARY or TYPE_STRING */ +}; + +/** + * add_registry -- adds a registry entry + * @gsp: gsp pointer + * @key: name of the registry key + * @type: type of data + * @data: pointer to value + * @length: size of data, in bytes + * + * Adds a registry key/value pair to the registry database. + * + * This function collects the registry information in a linked list. After + * all registry keys have been added, build_registry() is used to create the + * RPC data structure. + * + * registry_rpc_size is a running total of the size of all registry keys. + * It's used to avoid an O(n) calculation of the size when the RPC is built. + * + * Returns 0 on success, or negative error code on error. + */ +static int add_registry(struct nvkm_gsp *gsp, const char *key, + enum registry_type type, const void *data, size_t length) +{ + struct registry_list_entry *reg; + const size_t nlen = strnlen(key, REGISTRY_MAX_KEY_LENGTH) + 1; + size_t alloc_size; /* extra bytes to alloc for binary or string value */ + + if (nlen > REGISTRY_MAX_KEY_LENGTH) + return -EINVAL; + + alloc_size = (type == REGISTRY_TABLE_ENTRY_TYPE_DWORD) ? 0 : length; + + reg = kmalloc(sizeof(*reg) + alloc_size, GFP_KERNEL); + if (!reg) + return -ENOMEM; + + switch (type) { + case REGISTRY_TABLE_ENTRY_TYPE_DWORD: + reg->dword = *(const u32 *)(data); + break; + case REGISTRY_TABLE_ENTRY_TYPE_BINARY: + case REGISTRY_TABLE_ENTRY_TYPE_STRING: + memcpy(reg->binary, data, alloc_size); + break; + default: + nvkm_error(&gsp->subdev, "unrecognized registry type %u for '%s'\n", + type, key); + kfree(reg); + return -EINVAL; + } + + memcpy(reg->key, key, nlen); + reg->klen = nlen; + reg->vlen = length; + reg->type = type; + + list_add_tail(®->head, &gsp->registry_list); + gsp->registry_rpc_size += sizeof(PACKED_REGISTRY_ENTRY) + nlen + alloc_size; + + return 0; +} + +static int add_registry_num(struct nvkm_gsp *gsp, const char *key, u32 value) +{ + return add_registry(gsp, key, REGISTRY_TABLE_ENTRY_TYPE_DWORD, + &value, sizeof(u32)); +} + +static int add_registry_string(struct nvkm_gsp *gsp, const char *key, const char *value) +{ + return add_registry(gsp, key, REGISTRY_TABLE_ENTRY_TYPE_STRING, + value, strlen(value) + 1); +} + +/** + * build_registry -- create the registry RPC data + * @gsp: gsp pointer + * @registry: pointer to the RPC payload to fill + * + * After all registry key/value pairs have been added, call this function to + * build the RPC. + * + * The registry RPC looks like this: + * + * +-----------------+ + * |NvU32 size; | + * |NvU32 numEntries;| + * +-----------------+ + * +----------------------------------------+ + * |PACKED_REGISTRY_ENTRY | + * +----------------------------------------+ + * |Null-terminated key (string) for entry 0| + * +----------------------------------------+ + * |Binary/string data value for entry 0 | (only if necessary) + * +----------------------------------------+ + * + * +----------------------------------------+ + * |PACKED_REGISTRY_ENTRY | + * +----------------------------------------+ + * |Null-terminated key (string) for entry 1| + * +----------------------------------------+ + * |Binary/string data value for entry 1 | (only if necessary) + * +----------------------------------------+ + * ... (and so on, one copy for each entry) + * + * + * The 'data' field of an entry is either a 32-bit integer (for type DWORD) + * or an offset into the PACKED_REGISTRY_TABLE (for types BINARY and STRING). + * + * All memory allocated by add_registry() is released. + */ +static void build_registry(struct nvkm_gsp *gsp, PACKED_REGISTRY_TABLE *registry) +{ + struct registry_list_entry *reg, *n; + size_t str_offset; + unsigned int i = 0; + + registry->numEntries = list_count_nodes(&gsp->registry_list); + str_offset = struct_size(registry, entries, registry->numEntries); + + list_for_each_entry_safe(reg, n, &gsp->registry_list, head) { + registry->entries[i].type = reg->type; + registry->entries[i].length = reg->vlen; + + /* Append the key name to the table */ + registry->entries[i].nameOffset = str_offset; + memcpy((void *)registry + str_offset, reg->key, reg->klen); + str_offset += reg->klen; + + switch (reg->type) { + case REGISTRY_TABLE_ENTRY_TYPE_DWORD: + registry->entries[i].data = reg->dword; + break; + case REGISTRY_TABLE_ENTRY_TYPE_BINARY: + case REGISTRY_TABLE_ENTRY_TYPE_STRING: + /* If the type is binary or string, also append the value */ + memcpy((void *)registry + str_offset, reg->binary, reg->vlen); + registry->entries[i].data = str_offset; + str_offset += reg->vlen; + break; + default: + break; + } + + i++; + list_del(®->head); + kfree(reg); + } + + /* Double-check that we calculated the sizes correctly */ + WARN_ON(gsp->registry_rpc_size != str_offset); + + registry->size = gsp->registry_rpc_size; +} + +/** + * clean_registry -- clean up registry memory in case of error + * @gsp: gsp pointer + * + * Call this function to clean up all memory allocated by add_registry() + * in case of error and build_registry() is not called. + */ +static void clean_registry(struct nvkm_gsp *gsp) +{ + struct registry_list_entry *reg, *n; + + list_for_each_entry_safe(reg, n, &gsp->registry_list, head) { + list_del(®->head); + kfree(reg); + } + + gsp->registry_rpc_size = sizeof(PACKED_REGISTRY_TABLE); +} + +MODULE_PARM_DESC(NVreg_RegistryDwords, + "A semicolon-separated list of key=integer pairs of GSP-RM registry keys"); +static char *NVreg_RegistryDwords; +module_param(NVreg_RegistryDwords, charp, 0400); + /* dword only */ struct nv_gsp_registry_entries { const char *name; u32 value; }; +/** + * r535_registry_entries - required registry entries for GSP-RM + * + * This array lists registry entries that are required for GSP-RM to + * function correctly. + * + * RMSecBusResetEnable - enables PCI secondary bus reset + * RMForcePcieConfigSave - forces GSP-RM to preserve PCI configuration + * registers on any PCI reset. + */ static const struct nv_gsp_registry_entries r535_registry_entries[] = { { "RMSecBusResetEnable", 1 }, { "RMForcePcieConfigSave", 1 }, }; #define NV_GSP_REG_NUM_ENTRIES ARRAY_SIZE(r535_registry_entries) +/** + * strip - strips all characters in 'reject' from 's' + * @s: string to strip + * @reject: string of characters to remove + * + * 's' is modified. + * + * Returns the length of the new string. + */ +static size_t strip(char *s, const char *reject) +{ + char *p = s, *p2 = s; + size_t length = 0; + char c; + + do { + while ((c = *p2) && strchr(reject, c)) + p2++; + + *p++ = c = *p2++; + length++; + } while (c); + + return length; +} + +/** + * r535_gsp_rpc_set_registry - build registry RPC and call GSP-RM + * @gsp: gsp pointer + * + * The GSP-RM registry is a set of key/value pairs that configure some aspects + * of GSP-RM. The keys are strings, and the values are 32-bit integers. + * + * The registry is built from a combination of a static hard-coded list (see + * above) and entries passed on the driver's command line. + */ static int r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp) { PACKED_REGISTRY_TABLE *rpc; - char *strings; - int str_offset; - int i; - size_t rpc_size = struct_size(rpc, entries, NV_GSP_REG_NUM_ENTRIES); + unsigned int i; + int ret; - /* add strings + null terminator */ - for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) - rpc_size += strlen(r535_registry_entries[i].name) + 1; + INIT_LIST_HEAD(&gsp->registry_list); + gsp->registry_rpc_size = sizeof(PACKED_REGISTRY_TABLE); - rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_SET_REGISTRY, rpc_size); - if (IS_ERR(rpc)) - return PTR_ERR(rpc); + for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) { + ret = add_registry_num(gsp, r535_registry_entries[i].name, + r535_registry_entries[i].value); + if (ret) + goto fail; + } - rpc->numEntries = NV_GSP_REG_NUM_ENTRIES; + /* + * The NVreg_RegistryDwords parameter is a string of key=value + * pairs separated by semicolons. We need to extract and trim each + * substring, and then parse the substring to extract the key and + * value. + */ + if (NVreg_RegistryDwords) { + char *p = kstrdup(NVreg_RegistryDwords, GFP_KERNEL); + char *start, *next = p, *equal; + + if (!p) { + ret = -ENOMEM; + goto fail; + } - str_offset = offsetof(typeof(*rpc), entries[NV_GSP_REG_NUM_ENTRIES]); - strings = (char *)rpc + str_offset; - for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) { - int name_len = strlen(r535_registry_entries[i].name) + 1; - - rpc->entries[i].nameOffset = str_offset; - rpc->entries[i].type = 1; - rpc->entries[i].data = r535_registry_entries[i].value; - rpc->entries[i].length = 4; - memcpy(strings, r535_registry_entries[i].name, name_len); - strings += name_len; - str_offset += name_len; + /* Remove any whitespace from the parameter string */ + strip(p, " \t\n"); + + while ((start = strsep(&next, ";"))) { + long value; + + equal = strchr(start, '='); + if (!equal || equal == start || equal[1] == 0) { + nvkm_error(&gsp->subdev, + "ignoring invalid registry string '%s'\n", + start); + continue; + } + + /* Truncate the key=value string to just key */ + *equal = 0; + + ret = kstrtol(equal + 1, 0, &value); + if (!ret) { + ret = add_registry_num(gsp, start, value); + } else { + /* Not a number, so treat it as a string */ + ret = add_registry_string(gsp, start, equal + 1); + } + + if (ret) { + nvkm_error(&gsp->subdev, + "ignoring invalid registry key/value '%s=%s'\n", + start, equal + 1); + continue; + } + } + + kfree(p); + } + + rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_SET_REGISTRY, gsp->registry_rpc_size); + if (IS_ERR(rpc)) { + ret = PTR_ERR(rpc); + goto fail; } - rpc->size = str_offset; + + build_registry(gsp, rpc); return nvkm_gsp_rpc_wr(gsp, rpc, false); + +fail: + clean_registry(gsp); + return ret; } #if defined(CONFIG_ACPI) && defined(CONFIG_X86) diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig index 6c49270cb290..85ed92042b74 100644 --- a/drivers/gpu/drm/omapdrm/Kconfig +++ b/drivers/gpu/drm/omapdrm/Kconfig @@ -2,7 +2,7 @@ config DRM_OMAP tristate "OMAP DRM" depends on DRM && OF - depends on ARCH_OMAP2PLUS + depends on ARCH_OMAP2PLUS || COMPILE_TEST select DRM_KMS_HELPER select FB_DMAMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION select VIDEOMODE_HELPERS diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 9ea0c64c26b5..fdae677558f3 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1023,8 +1023,8 @@ struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj, if (addr) { for_each_sg(sgt->sgl, sg, count, i) { - sg_set_page(sg, phys_to_page(addr), len, - offset_in_page(addr)); + sg_set_page(sg, pfn_to_page(__phys_to_pfn(addr)), + len, offset_in_page(addr)); sg_dma_address(sg) = addr; sg_dma_len(sg) = len; diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 2ae0eb0638f3..bf4eadfe21cb 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -145,6 +145,15 @@ config DRM_PANEL_LVDS handling of power supplies or control signals. It implements automatic backlight handling if the panel is attached to a backlight controller. +config DRM_PANEL_HIMAX_HX83102 + tristate "Himax HX83102-based panels" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for panels based on the + Himax HX83102 controller. + config DRM_PANEL_HIMAX_HX83112A tristate "Himax HX83112A-based DSI panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index f0203f6e02f4..051b75b3df7b 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_DRM_PANEL_EBBG_FT8719) += panel-ebbg-ft8719.o obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o +obj-$(CONFIG_DRM_PANEL_HIMAX_HX83102) += panel-himax-hx83102.o obj-$(CONFIG_DRM_PANEL_HIMAX_HX83112A) += panel-himax-hx83112a.o obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o diff --git a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c index 662c7bcbe6e5..4692c36fe217 100644 --- a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c +++ b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c @@ -381,4 +381,5 @@ module_spi_driver(y030xx067a_driver); MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>"); +MODULE_DESCRIPTION("Asia Better Technology Ltd. Y030XX067A IPS LCD panel driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-auo-a030jtn01.c b/drivers/gpu/drm/panel/panel-auo-a030jtn01.c index 6c86ebf2cad7..77604d6a4e72 100644 --- a/drivers/gpu/drm/panel/panel-auo-a030jtn01.c +++ b/drivers/gpu/drm/panel/panel-auo-a030jtn01.c @@ -305,4 +305,5 @@ module_spi_driver(a030jtn01_driver); MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>"); +MODULE_DESCRIPTION("AU Optronics A030JTN01.0 TFT LCD panel driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c b/drivers/gpu/drm/panel/panel-boe-himax8279d.c index e225840b0d67..df746baae301 100644 --- a/drivers/gpu/drm/panel/panel-boe-himax8279d.c +++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c @@ -47,9 +47,6 @@ struct panel_info { struct gpio_desc *enable_gpio; struct gpio_desc *pp33_gpio; struct gpio_desc *pp18_gpio; - - bool prepared; - bool enabled; }; static inline struct panel_info *to_panel_info(struct drm_panel *panel) @@ -86,17 +83,12 @@ static int boe_panel_disable(struct drm_panel *panel) struct panel_info *pinfo = to_panel_info(panel); int err; - if (!pinfo->enabled) - return 0; - err = mipi_dsi_dcs_set_display_off(pinfo->link); if (err < 0) { dev_err(panel->dev, "failed to set display off: %d\n", err); return err; } - pinfo->enabled = false; - return 0; } @@ -105,9 +97,6 @@ static int boe_panel_unprepare(struct drm_panel *panel) struct panel_info *pinfo = to_panel_info(panel); int err; - if (!pinfo->prepared) - return 0; - err = mipi_dsi_dcs_set_display_off(pinfo->link); if (err < 0) dev_err(panel->dev, "failed to set display off: %d\n", err); @@ -121,8 +110,6 @@ static int boe_panel_unprepare(struct drm_panel *panel) disable_gpios(pinfo); - pinfo->prepared = false; - return 0; } @@ -131,9 +118,6 @@ static int boe_panel_prepare(struct drm_panel *panel) struct panel_info *pinfo = to_panel_info(panel); int err; - if (pinfo->prepared) - return 0; - gpiod_set_value(pinfo->pp18_gpio, 1); /* T1: 5ms - 6ms */ usleep_range(5000, 6000); @@ -180,8 +164,6 @@ static int boe_panel_prepare(struct drm_panel *panel) /* T7: 20ms - 21ms */ usleep_range(20000, 21000); - pinfo->prepared = true; - return 0; poweroff: @@ -194,9 +176,6 @@ static int boe_panel_enable(struct drm_panel *panel) struct panel_info *pinfo = to_panel_info(panel); int ret; - if (pinfo->enabled) - return 0; - usleep_range(120000, 121000); ret = mipi_dsi_dcs_set_display_on(pinfo->link); @@ -205,8 +184,6 @@ static int boe_panel_enable(struct drm_panel *panel) return ret; } - pinfo->enabled = true; - return 0; } @@ -917,14 +894,6 @@ static void panel_remove(struct mipi_dsi_device *dsi) struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi); int err; - err = boe_panel_disable(&pinfo->base); - if (err < 0) - dev_err(&dsi->dev, "failed to disable panel: %d\n", err); - - err = boe_panel_unprepare(&pinfo->base); - if (err < 0) - dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err); - err = mipi_dsi_detach(dsi); if (err < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); @@ -932,14 +901,6 @@ static void panel_remove(struct mipi_dsi_device *dsi) drm_panel_remove(&pinfo->base); } -static void panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi); - - boe_panel_disable(&pinfo->base); - boe_panel_unprepare(&pinfo->base); -} - static struct mipi_dsi_driver panel_driver = { .driver = { .name = "panel-boe-himax8279d", @@ -947,7 +908,6 @@ static struct mipi_dsi_driver panel_driver = { }, .probe = panel_probe, .remove = panel_remove, - .shutdown = panel_shutdown, }; module_mipi_dsi_driver(panel_driver); diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c index 0ffe8f8c01de..ce919a980875 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c @@ -17,6 +17,8 @@ #include <video/mipi_display.h> +struct boe_panel; + struct panel_desc { const struct drm_display_mode *modes; unsigned int bpc; @@ -32,7 +34,7 @@ struct panel_desc { unsigned long mode_flags; enum mipi_dsi_pixel_format format; - const struct panel_init_cmd *init_cmds; + int (*init)(struct boe_panel *boe); unsigned int lanes; bool discharge_on_disable; bool lp11_before_reset; @@ -50,1409 +52,1351 @@ struct boe_panel { struct regulator *avee; struct regulator *avdd; struct gpio_desc *enable_gpio; - - bool prepared; }; -enum dsi_cmd_type { - INIT_DCS_CMD, - DELAY_CMD, -}; +static int boe_tv110c9m_init(struct boe_panel *boe) +{ + struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi }; + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0xd9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x78); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x5a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x63); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x91); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x73); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x95, 0xe6); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x96, 0xf0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x66); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0xa2); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x3b); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, + 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, + 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, + 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, + 0x03, 0xfd, 0x03, 0xff); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, + 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, + 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, + 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, + 0x03, 0xfd, 0x03, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, + 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, + 0x01, 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, + 0x03, 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, + 0x03, 0xfd, 0x03, 0xff); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x21); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, + 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, + 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, + 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, + 0x03, 0xf5, 0x03, 0xe0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, + 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, + 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, + 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, + 0x03, 0xf5, 0x03, 0xe0); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, + 0x00, 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, + 0x01, 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, + 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, + 0x03, 0xf5, 0x03, 0xe0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x24); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x1c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x1c); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x1d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x1d); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x04); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x0f); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x0e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x0e); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0d); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x0c); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x08); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x1c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x1c); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x1d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x1d); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x04); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x0f); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x0e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x0e); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x0d); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x0c); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x08); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x44); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x32); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x44); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x5d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x42); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x66); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x5d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x91); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x21); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x43); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x12); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x52, 0x34); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x82, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x21); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x30); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x00, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x82); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x3c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x97, 0xc0); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x05, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x91, 0x44); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0xa9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x93, 0x1a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x94, 0x96); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x55); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0xa9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x22); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0xa9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0xa9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0xa9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0xa9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x8d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x8e, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x90); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x25); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0xe0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0xd0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xf1, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x2a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x16); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x30); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa2, 0xf3); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa3, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa4, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0xff); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x08); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0xa1); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x28); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x30); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x56); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x57); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0xa0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x86); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x7f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0xbf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x7f); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x7d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x78); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x9e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x4e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x49); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x4b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x48); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x43); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xad, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xae, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xaf, 0x44); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x54); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x4e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x4d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x4c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x41); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x47); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x53); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x3e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x51); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x3c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x3b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x45); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x55); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0x3d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x3f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x52); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x4a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x39); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x3a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x42); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x27); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x80); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x75); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x2e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x43); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x2d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x44); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x2a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x2f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x08); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xf8); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x1a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x1a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x1a); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x23); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x80); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0xe0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0xc0); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0xf0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x08); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x40); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x00, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x24); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x13); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x03, 0x96, 0x1a, 0x04, 0x04); + + mipi_dsi_msleep(&ctx, 100); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x11); + + mipi_dsi_msleep(&ctx, 200); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29); + + mipi_dsi_msleep(&ctx, 100); -struct panel_init_cmd { - enum dsi_cmd_type type; - size_t len; - const char *data; + return 0; }; -#define _INIT_DCS_CMD(...) { \ - .type = INIT_DCS_CMD, \ - .len = sizeof((char[]){__VA_ARGS__}), \ - .data = (char[]){__VA_ARGS__} } - -#define _INIT_DELAY_CMD(...) { \ - .type = DELAY_CMD,\ - .len = sizeof((char[]){__VA_ARGS__}), \ - .data = (char[]){__VA_ARGS__} } - -static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = { - _INIT_DCS_CMD(0xFF, 0x20), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x05, 0xD9), - _INIT_DCS_CMD(0x07, 0x78), - _INIT_DCS_CMD(0x08, 0x5A), - _INIT_DCS_CMD(0x0D, 0x63), - _INIT_DCS_CMD(0x0E, 0x91), - _INIT_DCS_CMD(0x0F, 0x73), - _INIT_DCS_CMD(0x95, 0xE6), - _INIT_DCS_CMD(0x96, 0xF0), - _INIT_DCS_CMD(0x30, 0x00), - _INIT_DCS_CMD(0x6D, 0x66), - _INIT_DCS_CMD(0x75, 0xA2), - _INIT_DCS_CMD(0x77, 0x3B), +static int inx_hj110iz_init(struct boe_panel *boe) +{ + struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi }; + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0xd1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0xc0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x87); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x4b); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x63); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x91); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x69); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x94, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x95, 0xf5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x96, 0xf5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x9d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x9e, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x98); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0xa2); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0xb3); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x43); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x24); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x91, 0x44); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x4c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x94, 0x86); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x96); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0xd0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x70); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xca); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x22); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x22); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x1d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x1c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x0e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x22); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x22); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x1d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x1c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x0e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x03); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x35); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0xa7); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x32); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x12); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x33); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x31); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x41, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x42, 0x42); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x77); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x77); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x45); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x45); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x14); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x21); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x43); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4f, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x21); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x70); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x32); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x88); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7c, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x3c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x97, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x10); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x55); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x55); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x23); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x55); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x27); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe9, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xea, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xeb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xee, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xef, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xf0, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x05, 0x00, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x25); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xf1, 0x10); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x32); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x32); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x80); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x46); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x32); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x80); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x32); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x32); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x32); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x0c); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6e, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0xc5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0xb0); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0xa1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0xf4); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x30); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x58); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0xa0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x86); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x31); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x0e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x31); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x62); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x62); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x62); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x7f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x89); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x67); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x62); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x06); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x89); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x4e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x3f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x3e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x3d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x3c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xad, 0x3b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xae, 0x3a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xaf, 0x39); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x38); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x27); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x54); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x43); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x02); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x18); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x06); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x80); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x78); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x18); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x1c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x44); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x1b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x44); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x98, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x9b, 0xbe); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x14); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x28); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x2a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x2f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x08); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x62); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xf8); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x1a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x1a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x1a); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x96); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x96); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x96); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6b, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x92); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x71, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x72, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x96); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x88, 0x96); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x89, 0x10); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa2, 0x3f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa3, 0x30); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa4, 0xc0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0x03); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x97, 0x3c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x98, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x99, 0x95); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x9a, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x9b, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x9c, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x9d, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x9e, 0x90); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x25); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0xd7); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0xd7); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0xcf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x5b); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x24, 0x00, 0x38, + 0x00, 0x4c, 0x00, 0x5e, 0x00, 0x6f, 0x00, 0x7e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0x8c, 0x00, 0xbe, 0x00, 0xe5, 0x01, 0x27, + 0x01, 0x58, 0x01, 0xa8, 0x01, 0xe8, 0x01, 0xea); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9e, 0x02, 0xda, + 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x62, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9c, + 0x03, 0xaa, 0x03, 0xb2); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x27, 0x00, 0x3d, + 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0x93, 0x00, 0xc5, 0x00, 0xec, 0x01, 0x2c, + 0x01, 0x5d, 0x01, 0xac, 0x01, 0xec, 0x01, 0xee); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x2b, 0x02, 0x73, 0x02, 0xa0, 0x02, 0xdb, + 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x63, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9c, + 0x03, 0xaa, 0x03, 0xb2); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x2a, 0x00, 0x40, + 0x00, 0x56, 0x00, 0x68, 0x00, 0x7a, 0x00, 0x89); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0x98, 0x00, 0xc9, 0x00, 0xf1, 0x01, 0x30, + 0x01, 0x61, 0x01, 0xb0, 0x01, 0xef, 0x01, 0xf1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x2e, 0x02, 0x76, 0x02, 0xa3, 0x02, 0xdd, + 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x66, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9c, + 0x03, 0xaa, 0x03, 0xb2); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x21); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x24, 0x00, 0x38, + 0x00, 0x4c, 0x00, 0x5e, 0x00, 0x6f, 0x00, 0x7e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00, 0x8c, 0x00, 0xbe, 0x00, 0xe5, 0x01, 0x27, + 0x01, 0x58, 0x01, 0xa8, 0x01, 0xe8, 0x01, 0xea); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9e, 0x02, 0xda, + 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x03, 0x62, 0x03, 0x77, 0x03, 0x90, 0x03, 0xac, + 0x03, 0xca, 0x03, 0xda); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x27, 0x00, 0x3d, + 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x00, 0x93, 0x00, 0xc5, 0x00, 0xec, 0x01, 0x2c, + 0x01, 0x5d, 0x01, 0xac, 0x01, 0xec, 0x01, 0xee); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x02, 0x2b, 0x02, 0x73, 0x02, 0xa0, 0x02, 0xdb, + 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x03, 0x63, 0x03, 0x77, 0x03, 0x90, 0x03, 0xac, + 0x03, 0xca, 0x03, 0xda); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x2a, 0x00, 0x40, + 0x00, 0x56, 0x00, 0x68, 0x00, 0x7a, 0x00, 0x89); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x00, 0x98, 0x00, 0xc9, 0x00, 0xf1, 0x01, 0x30, + 0x01, 0x61, 0x01, 0xb0, 0x01, 0xef, 0x01, 0xf1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x02, 0x2e, 0x02, 0x76, 0x02, 0xa3, 0x02, 0xdd, + 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0x03, 0x66, 0x03, 0x77, 0x03, 0x90, 0x03, 0xac, + 0x03, 0xca, 0x03, 0xda); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0xf0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x08); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x01); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x20); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xff, 0x10); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x03, 0xae, 0x1a, 0x04, 0x04); + + mipi_dsi_msleep(&ctx, 100); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x11); + + mipi_dsi_msleep(&ctx, 200); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29); + + mipi_dsi_msleep(&ctx, 100); - _INIT_DCS_CMD(0xB0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9), - _INIT_DCS_CMD(0xB1, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31), - _INIT_DCS_CMD(0xB2, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B), - _INIT_DCS_CMD(0xB3, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF), - - _INIT_DCS_CMD(0xB4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9), - _INIT_DCS_CMD(0xB5, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31), - _INIT_DCS_CMD(0xB6, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B), - _INIT_DCS_CMD(0xB7, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF), - _INIT_DCS_CMD(0xB8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4D, 0x00, 0x6D, 0x00, 0x89, 0x00, 0xA1, 0x00, 0xB6, 0x00, 0xC9), - _INIT_DCS_CMD(0xB9, 0x00, 0xDA, 0x01, 0x13, 0x01, 0x3C, 0x01, 0x7E, 0x01, 0xAB, 0x01, 0xF7, 0x02, 0x2F, 0x02, 0x31), - _INIT_DCS_CMD(0xBA, 0x02, 0x67, 0x02, 0xA6, 0x02, 0xD1, 0x03, 0x08, 0x03, 0x2E, 0x03, 0x5B, 0x03, 0x6B, 0x03, 0x7B), - _INIT_DCS_CMD(0xBB, 0x03, 0x8E, 0x03, 0xA2, 0x03, 0xB7, 0x03, 0xE7, 0x03, 0xFD, 0x03, 0xFF), - - _INIT_DCS_CMD(0xFF, 0x21), - _INIT_DCS_CMD(0xFB, 0x01), - - _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1), - _INIT_DCS_CMD(0xB1, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29), - _INIT_DCS_CMD(0xB2, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73), - - _INIT_DCS_CMD(0xB3, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0), - _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1), - _INIT_DCS_CMD(0xB5, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29), - _INIT_DCS_CMD(0xB6, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73), - _INIT_DCS_CMD(0xB7, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0), - - _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1), - _INIT_DCS_CMD(0xB9, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29), - _INIT_DCS_CMD(0xBA, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73), - - _INIT_DCS_CMD(0xBB, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0), - _INIT_DCS_CMD(0xFF, 0x24), - _INIT_DCS_CMD(0xFB, 0x01), - - _INIT_DCS_CMD(0x00, 0x00), - _INIT_DCS_CMD(0x01, 0x00), - - _INIT_DCS_CMD(0x02, 0x1C), - _INIT_DCS_CMD(0x03, 0x1C), - - _INIT_DCS_CMD(0x04, 0x1D), - _INIT_DCS_CMD(0x05, 0x1D), - - _INIT_DCS_CMD(0x06, 0x04), - _INIT_DCS_CMD(0x07, 0x04), - - _INIT_DCS_CMD(0x08, 0x0F), - _INIT_DCS_CMD(0x09, 0x0F), - - _INIT_DCS_CMD(0x0A, 0x0E), - _INIT_DCS_CMD(0x0B, 0x0E), - - _INIT_DCS_CMD(0x0C, 0x0D), - _INIT_DCS_CMD(0x0D, 0x0D), - - _INIT_DCS_CMD(0x0E, 0x0C), - _INIT_DCS_CMD(0x0F, 0x0C), - - _INIT_DCS_CMD(0x10, 0x08), - _INIT_DCS_CMD(0x11, 0x08), - - _INIT_DCS_CMD(0x12, 0x00), - _INIT_DCS_CMD(0x13, 0x00), - _INIT_DCS_CMD(0x14, 0x00), - _INIT_DCS_CMD(0x15, 0x00), - - _INIT_DCS_CMD(0x16, 0x00), - _INIT_DCS_CMD(0x17, 0x00), - - _INIT_DCS_CMD(0x18, 0x1C), - _INIT_DCS_CMD(0x19, 0x1C), - - _INIT_DCS_CMD(0x1A, 0x1D), - _INIT_DCS_CMD(0x1B, 0x1D), - - _INIT_DCS_CMD(0x1C, 0x04), - _INIT_DCS_CMD(0x1D, 0x04), - - _INIT_DCS_CMD(0x1E, 0x0F), - _INIT_DCS_CMD(0x1F, 0x0F), - - _INIT_DCS_CMD(0x20, 0x0E), - _INIT_DCS_CMD(0x21, 0x0E), - - _INIT_DCS_CMD(0x22, 0x0D), - _INIT_DCS_CMD(0x23, 0x0D), - - _INIT_DCS_CMD(0x24, 0x0C), - _INIT_DCS_CMD(0x25, 0x0C), - - _INIT_DCS_CMD(0x26, 0x08), - _INIT_DCS_CMD(0x27, 0x08), - - _INIT_DCS_CMD(0x28, 0x00), - _INIT_DCS_CMD(0x29, 0x00), - _INIT_DCS_CMD(0x2A, 0x00), - _INIT_DCS_CMD(0x2B, 0x00), - - _INIT_DCS_CMD(0x2D, 0x20), - _INIT_DCS_CMD(0x2F, 0x0A), - _INIT_DCS_CMD(0x30, 0x44), - _INIT_DCS_CMD(0x33, 0x0C), - _INIT_DCS_CMD(0x34, 0x32), - - _INIT_DCS_CMD(0x37, 0x44), - _INIT_DCS_CMD(0x38, 0x40), - _INIT_DCS_CMD(0x39, 0x00), - _INIT_DCS_CMD(0x3A, 0x5D), - _INIT_DCS_CMD(0x3B, 0x60), - _INIT_DCS_CMD(0x3D, 0x42), - _INIT_DCS_CMD(0x3F, 0x06), - _INIT_DCS_CMD(0x43, 0x06), - _INIT_DCS_CMD(0x47, 0x66), - _INIT_DCS_CMD(0x4A, 0x5D), - _INIT_DCS_CMD(0x4B, 0x60), - _INIT_DCS_CMD(0x4C, 0x91), - _INIT_DCS_CMD(0x4D, 0x21), - _INIT_DCS_CMD(0x4E, 0x43), - _INIT_DCS_CMD(0x51, 0x12), - _INIT_DCS_CMD(0x52, 0x34), - _INIT_DCS_CMD(0x55, 0x82, 0x02), - _INIT_DCS_CMD(0x56, 0x04), - _INIT_DCS_CMD(0x58, 0x21), - _INIT_DCS_CMD(0x59, 0x30), - _INIT_DCS_CMD(0x5A, 0x60), - _INIT_DCS_CMD(0x5B, 0x50), - _INIT_DCS_CMD(0x5E, 0x00, 0x06), - _INIT_DCS_CMD(0x5F, 0x00), - _INIT_DCS_CMD(0x65, 0x82), - _INIT_DCS_CMD(0x7E, 0x20), - _INIT_DCS_CMD(0x7F, 0x3C), - _INIT_DCS_CMD(0x82, 0x04), - _INIT_DCS_CMD(0x97, 0xC0), - - _INIT_DCS_CMD(0xB6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00), - _INIT_DCS_CMD(0x91, 0x44), - _INIT_DCS_CMD(0x92, 0xA9), - _INIT_DCS_CMD(0x93, 0x1A), - _INIT_DCS_CMD(0x94, 0x96), - _INIT_DCS_CMD(0xD7, 0x55), - _INIT_DCS_CMD(0xDA, 0x0A), - _INIT_DCS_CMD(0xDE, 0x08), - _INIT_DCS_CMD(0xDB, 0x05), - _INIT_DCS_CMD(0xDC, 0xA9), - _INIT_DCS_CMD(0xDD, 0x22), - - _INIT_DCS_CMD(0xDF, 0x05), - _INIT_DCS_CMD(0xE0, 0xA9), - _INIT_DCS_CMD(0xE1, 0x05), - _INIT_DCS_CMD(0xE2, 0xA9), - _INIT_DCS_CMD(0xE3, 0x05), - _INIT_DCS_CMD(0xE4, 0xA9), - _INIT_DCS_CMD(0xE5, 0x05), - _INIT_DCS_CMD(0xE6, 0xA9), - _INIT_DCS_CMD(0x5C, 0x00), - _INIT_DCS_CMD(0x5D, 0x00), - _INIT_DCS_CMD(0x8D, 0x00), - _INIT_DCS_CMD(0x8E, 0x00), - _INIT_DCS_CMD(0xB5, 0x90), - _INIT_DCS_CMD(0xFF, 0x25), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x05, 0x00), - _INIT_DCS_CMD(0x19, 0x07), - _INIT_DCS_CMD(0x1F, 0x60), - _INIT_DCS_CMD(0x20, 0x50), - _INIT_DCS_CMD(0x26, 0x60), - _INIT_DCS_CMD(0x27, 0x50), - _INIT_DCS_CMD(0x33, 0x60), - _INIT_DCS_CMD(0x34, 0x50), - _INIT_DCS_CMD(0x3F, 0xE0), - _INIT_DCS_CMD(0x40, 0x00), - _INIT_DCS_CMD(0x44, 0x00), - _INIT_DCS_CMD(0x45, 0x40), - _INIT_DCS_CMD(0x48, 0x60), - _INIT_DCS_CMD(0x49, 0x50), - _INIT_DCS_CMD(0x5B, 0x00), - _INIT_DCS_CMD(0x5C, 0x00), - _INIT_DCS_CMD(0x5D, 0x00), - _INIT_DCS_CMD(0x5E, 0xD0), - _INIT_DCS_CMD(0x61, 0x60), - _INIT_DCS_CMD(0x62, 0x50), - _INIT_DCS_CMD(0xF1, 0x10), - _INIT_DCS_CMD(0xFF, 0x2A), - _INIT_DCS_CMD(0xFB, 0x01), - - _INIT_DCS_CMD(0x64, 0x16), - _INIT_DCS_CMD(0x67, 0x16), - _INIT_DCS_CMD(0x6A, 0x16), - - _INIT_DCS_CMD(0x70, 0x30), - - _INIT_DCS_CMD(0xA2, 0xF3), - _INIT_DCS_CMD(0xA3, 0xFF), - _INIT_DCS_CMD(0xA4, 0xFF), - _INIT_DCS_CMD(0xA5, 0xFF), - - _INIT_DCS_CMD(0xD6, 0x08), - - _INIT_DCS_CMD(0xFF, 0x26), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x00, 0xA1), - - _INIT_DCS_CMD(0x02, 0x31), - _INIT_DCS_CMD(0x04, 0x28), - _INIT_DCS_CMD(0x06, 0x30), - _INIT_DCS_CMD(0x0C, 0x16), - _INIT_DCS_CMD(0x0D, 0x0D), - _INIT_DCS_CMD(0x0F, 0x00), - _INIT_DCS_CMD(0x11, 0x00), - _INIT_DCS_CMD(0x12, 0x50), - _INIT_DCS_CMD(0x13, 0x56), - _INIT_DCS_CMD(0x14, 0x57), - _INIT_DCS_CMD(0x15, 0x00), - _INIT_DCS_CMD(0x16, 0x10), - _INIT_DCS_CMD(0x17, 0xA0), - _INIT_DCS_CMD(0x18, 0x86), - _INIT_DCS_CMD(0x19, 0x0D), - _INIT_DCS_CMD(0x1A, 0x7F), - _INIT_DCS_CMD(0x1B, 0x0C), - _INIT_DCS_CMD(0x1C, 0xBF), - _INIT_DCS_CMD(0x22, 0x00), - _INIT_DCS_CMD(0x23, 0x00), - _INIT_DCS_CMD(0x2A, 0x0D), - _INIT_DCS_CMD(0x2B, 0x7F), - - _INIT_DCS_CMD(0x1D, 0x00), - _INIT_DCS_CMD(0x1E, 0x65), - _INIT_DCS_CMD(0x1F, 0x65), - _INIT_DCS_CMD(0x24, 0x00), - _INIT_DCS_CMD(0x25, 0x65), - _INIT_DCS_CMD(0x2F, 0x05), - _INIT_DCS_CMD(0x30, 0x65), - _INIT_DCS_CMD(0x31, 0x05), - _INIT_DCS_CMD(0x32, 0x7D), - _INIT_DCS_CMD(0x39, 0x00), - _INIT_DCS_CMD(0x3A, 0x65), - _INIT_DCS_CMD(0x20, 0x01), - _INIT_DCS_CMD(0x33, 0x11), - _INIT_DCS_CMD(0x34, 0x78), - _INIT_DCS_CMD(0x35, 0x16), - _INIT_DCS_CMD(0xC8, 0x04), - _INIT_DCS_CMD(0xC9, 0x9E), - _INIT_DCS_CMD(0xCA, 0x4E), - _INIT_DCS_CMD(0xCB, 0x00), - - _INIT_DCS_CMD(0xA9, 0x49), - _INIT_DCS_CMD(0xAA, 0x4B), - _INIT_DCS_CMD(0xAB, 0x48), - _INIT_DCS_CMD(0xAC, 0x43), - _INIT_DCS_CMD(0xAD, 0x40), - _INIT_DCS_CMD(0xAE, 0x50), - _INIT_DCS_CMD(0xAF, 0x44), - _INIT_DCS_CMD(0xB0, 0x54), - _INIT_DCS_CMD(0xB1, 0x4E), - _INIT_DCS_CMD(0xB2, 0x4D), - _INIT_DCS_CMD(0xB3, 0x4C), - _INIT_DCS_CMD(0xB4, 0x41), - _INIT_DCS_CMD(0xB5, 0x47), - _INIT_DCS_CMD(0xB6, 0x53), - _INIT_DCS_CMD(0xB7, 0x3E), - _INIT_DCS_CMD(0xB8, 0x51), - _INIT_DCS_CMD(0xB9, 0x3C), - _INIT_DCS_CMD(0xBA, 0x3B), - _INIT_DCS_CMD(0xBB, 0x46), - _INIT_DCS_CMD(0xBC, 0x45), - _INIT_DCS_CMD(0xBD, 0x55), - _INIT_DCS_CMD(0xBE, 0x3D), - _INIT_DCS_CMD(0xBF, 0x3F), - _INIT_DCS_CMD(0xC0, 0x52), - _INIT_DCS_CMD(0xC1, 0x4A), - _INIT_DCS_CMD(0xC2, 0x39), - _INIT_DCS_CMD(0xC3, 0x4F), - _INIT_DCS_CMD(0xC4, 0x3A), - _INIT_DCS_CMD(0xC5, 0x42), - _INIT_DCS_CMD(0xFF, 0x27), - _INIT_DCS_CMD(0xFB, 0x01), - - _INIT_DCS_CMD(0x56, 0x06), - _INIT_DCS_CMD(0x58, 0x80), - _INIT_DCS_CMD(0x59, 0x75), - _INIT_DCS_CMD(0x5A, 0x00), - _INIT_DCS_CMD(0x5B, 0x02), - _INIT_DCS_CMD(0x5C, 0x00), - _INIT_DCS_CMD(0x5D, 0x00), - _INIT_DCS_CMD(0x5E, 0x20), - _INIT_DCS_CMD(0x5F, 0x10), - _INIT_DCS_CMD(0x60, 0x00), - _INIT_DCS_CMD(0x61, 0x2E), - _INIT_DCS_CMD(0x62, 0x00), - _INIT_DCS_CMD(0x63, 0x01), - _INIT_DCS_CMD(0x64, 0x43), - _INIT_DCS_CMD(0x65, 0x2D), - _INIT_DCS_CMD(0x66, 0x00), - _INIT_DCS_CMD(0x67, 0x01), - _INIT_DCS_CMD(0x68, 0x44), - - _INIT_DCS_CMD(0x00, 0x00), - _INIT_DCS_CMD(0x78, 0x00), - _INIT_DCS_CMD(0xC3, 0x00), - - _INIT_DCS_CMD(0xFF, 0x2A), - _INIT_DCS_CMD(0xFB, 0x01), - - _INIT_DCS_CMD(0x22, 0x2F), - _INIT_DCS_CMD(0x23, 0x08), - - _INIT_DCS_CMD(0x24, 0x00), - _INIT_DCS_CMD(0x25, 0x65), - _INIT_DCS_CMD(0x26, 0xF8), - _INIT_DCS_CMD(0x27, 0x00), - _INIT_DCS_CMD(0x28, 0x1A), - _INIT_DCS_CMD(0x29, 0x00), - _INIT_DCS_CMD(0x2A, 0x1A), - _INIT_DCS_CMD(0x2B, 0x00), - _INIT_DCS_CMD(0x2D, 0x1A), - - _INIT_DCS_CMD(0xFF, 0x23), - _INIT_DCS_CMD(0xFB, 0x01), - - _INIT_DCS_CMD(0x00, 0x80), - _INIT_DCS_CMD(0x07, 0x00), - - _INIT_DCS_CMD(0xFF, 0xE0), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x14, 0x60), - _INIT_DCS_CMD(0x16, 0xC0), - - _INIT_DCS_CMD(0xFF, 0xF0), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x3A, 0x08), - - _INIT_DCS_CMD(0xFF, 0x10), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0xB9, 0x01), - _INIT_DCS_CMD(0xFF, 0x20), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x18, 0x40), - - _INIT_DCS_CMD(0xFF, 0x10), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0xB9, 0x02), - _INIT_DCS_CMD(0x35, 0x00), - _INIT_DCS_CMD(0x51, 0x00, 0xFF), - _INIT_DCS_CMD(0x53, 0x24), - _INIT_DCS_CMD(0x55, 0x00), - _INIT_DCS_CMD(0xBB, 0x13), - _INIT_DCS_CMD(0x3B, 0x03, 0x96, 0x1A, 0x04, 0x04), - _INIT_DELAY_CMD(100), - _INIT_DCS_CMD(0x11), - _INIT_DELAY_CMD(200), - _INIT_DCS_CMD(0x29), - _INIT_DELAY_CMD(100), - {}, + return 0; }; -static const struct panel_init_cmd inx_hj110iz_init_cmd[] = { - _INIT_DCS_CMD(0xFF, 0x20), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x05, 0xD1), - _INIT_DCS_CMD(0x06, 0xC0), - _INIT_DCS_CMD(0x07, 0x87), - _INIT_DCS_CMD(0x08, 0x4B), - - _INIT_DCS_CMD(0x0D, 0x63), - _INIT_DCS_CMD(0x0E, 0x91), - _INIT_DCS_CMD(0x0F, 0x69), - _INIT_DCS_CMD(0x94, 0x00), - _INIT_DCS_CMD(0x95, 0xF5), - _INIT_DCS_CMD(0x96, 0xF5), - _INIT_DCS_CMD(0x9D, 0x00), - _INIT_DCS_CMD(0x9E, 0x00), - _INIT_DCS_CMD(0x69, 0x98), - _INIT_DCS_CMD(0x75, 0xA2), - _INIT_DCS_CMD(0x77, 0xB3), - - _INIT_DCS_CMD(0x58, 0x43), - _INIT_DCS_CMD(0xFF, 0x24), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x91, 0x44), - _INIT_DCS_CMD(0x92, 0x4C), - _INIT_DCS_CMD(0x94, 0x86), - _INIT_DCS_CMD(0x60, 0x96), - _INIT_DCS_CMD(0x61, 0xD0), - _INIT_DCS_CMD(0x63, 0x70), - _INIT_DCS_CMD(0xC2, 0xCA), - - _INIT_DCS_CMD(0x00, 0x03), - _INIT_DCS_CMD(0x01, 0x03), - _INIT_DCS_CMD(0x02, 0x03), - _INIT_DCS_CMD(0x03, 0x29), - _INIT_DCS_CMD(0x04, 0x22), - _INIT_DCS_CMD(0x05, 0x22), - _INIT_DCS_CMD(0x06, 0x0B), - _INIT_DCS_CMD(0x07, 0x1D), - _INIT_DCS_CMD(0x08, 0x1C), - _INIT_DCS_CMD(0x09, 0x05), - _INIT_DCS_CMD(0x0A, 0x08), - _INIT_DCS_CMD(0x0B, 0x09), - _INIT_DCS_CMD(0x0C, 0x0A), - _INIT_DCS_CMD(0x0D, 0x0C), - _INIT_DCS_CMD(0x0E, 0x0D), - _INIT_DCS_CMD(0x0F, 0x0E), - _INIT_DCS_CMD(0x10, 0x0F), - _INIT_DCS_CMD(0x11, 0x10), - _INIT_DCS_CMD(0x12, 0x11), - _INIT_DCS_CMD(0x13, 0x04), - _INIT_DCS_CMD(0x14, 0x00), - _INIT_DCS_CMD(0x15, 0x03), - _INIT_DCS_CMD(0x16, 0x03), - _INIT_DCS_CMD(0x17, 0x03), - _INIT_DCS_CMD(0x18, 0x03), - _INIT_DCS_CMD(0x19, 0x29), - _INIT_DCS_CMD(0x1A, 0x22), - _INIT_DCS_CMD(0x1B, 0x22), - _INIT_DCS_CMD(0x1C, 0x0B), - _INIT_DCS_CMD(0x1D, 0x1D), - _INIT_DCS_CMD(0x1E, 0x1C), - _INIT_DCS_CMD(0x1F, 0x05), - _INIT_DCS_CMD(0x20, 0x08), - _INIT_DCS_CMD(0x21, 0x09), - _INIT_DCS_CMD(0x22, 0x0A), - _INIT_DCS_CMD(0x23, 0x0C), - _INIT_DCS_CMD(0x24, 0x0D), - _INIT_DCS_CMD(0x25, 0x0E), - _INIT_DCS_CMD(0x26, 0x0F), - _INIT_DCS_CMD(0x27, 0x10), - _INIT_DCS_CMD(0x28, 0x11), - _INIT_DCS_CMD(0x29, 0x04), - _INIT_DCS_CMD(0x2A, 0x00), - _INIT_DCS_CMD(0x2B, 0x03), - - _INIT_DCS_CMD(0x2F, 0x0A), - _INIT_DCS_CMD(0x30, 0x35), - _INIT_DCS_CMD(0x37, 0xA7), - _INIT_DCS_CMD(0x39, 0x00), - _INIT_DCS_CMD(0x3A, 0x46), - _INIT_DCS_CMD(0x3B, 0x32), - _INIT_DCS_CMD(0x3D, 0x12), - - _INIT_DCS_CMD(0x3F, 0x33), - _INIT_DCS_CMD(0x40, 0x31), - _INIT_DCS_CMD(0x41, 0x40), - _INIT_DCS_CMD(0x42, 0x42), - _INIT_DCS_CMD(0x47, 0x77), - _INIT_DCS_CMD(0x48, 0x77), - _INIT_DCS_CMD(0x4A, 0x45), - _INIT_DCS_CMD(0x4B, 0x45), - _INIT_DCS_CMD(0x4C, 0x14), - - _INIT_DCS_CMD(0x4D, 0x21), - _INIT_DCS_CMD(0x4E, 0x43), - _INIT_DCS_CMD(0x4F, 0x65), - _INIT_DCS_CMD(0x55, 0x06), - _INIT_DCS_CMD(0x56, 0x06), - _INIT_DCS_CMD(0x58, 0x21), - _INIT_DCS_CMD(0x59, 0x70), - _INIT_DCS_CMD(0x5A, 0x46), - _INIT_DCS_CMD(0x5B, 0x32), - _INIT_DCS_CMD(0x5C, 0x88), - _INIT_DCS_CMD(0x5E, 0x00, 0x00), - _INIT_DCS_CMD(0x5F, 0x00), - - _INIT_DCS_CMD(0x7A, 0xFF), - _INIT_DCS_CMD(0x7B, 0xFF), - _INIT_DCS_CMD(0x7C, 0x00), - _INIT_DCS_CMD(0x7D, 0x00), - _INIT_DCS_CMD(0x7E, 0x20), - _INIT_DCS_CMD(0x7F, 0x3C), - _INIT_DCS_CMD(0x80, 0x00), - _INIT_DCS_CMD(0x81, 0x00), - _INIT_DCS_CMD(0x82, 0x08), - _INIT_DCS_CMD(0x97, 0x02), - _INIT_DCS_CMD(0xC5, 0x10), - - _INIT_DCS_CMD(0xD7, 0x55), - _INIT_DCS_CMD(0xD8, 0x55), - _INIT_DCS_CMD(0xD9, 0x23), - _INIT_DCS_CMD(0xDA, 0x05), - _INIT_DCS_CMD(0xDB, 0x01), - _INIT_DCS_CMD(0xDC, 0x65), - _INIT_DCS_CMD(0xDD, 0x55), - _INIT_DCS_CMD(0xDE, 0x27), - _INIT_DCS_CMD(0xDF, 0x01), - _INIT_DCS_CMD(0xE0, 0x65), - _INIT_DCS_CMD(0xE1, 0x01), - _INIT_DCS_CMD(0xE2, 0x65), - _INIT_DCS_CMD(0xE3, 0x01), - _INIT_DCS_CMD(0xE4, 0x65), - _INIT_DCS_CMD(0xE5, 0x01), - _INIT_DCS_CMD(0xE6, 0x65), - _INIT_DCS_CMD(0xE7, 0x00), - _INIT_DCS_CMD(0xE8, 0x00), - _INIT_DCS_CMD(0xE9, 0x01), - _INIT_DCS_CMD(0xEA, 0x65), - _INIT_DCS_CMD(0xEB, 0x01), - _INIT_DCS_CMD(0xEE, 0x65), - _INIT_DCS_CMD(0xEF, 0x01), - _INIT_DCS_CMD(0xF0, 0x65), - _INIT_DCS_CMD(0xB6, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00), - - _INIT_DCS_CMD(0xFF, 0x25), - - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x05, 0x00), - _INIT_DCS_CMD(0xF1, 0x10), - - _INIT_DCS_CMD(0x1E, 0x00), - _INIT_DCS_CMD(0x1F, 0x46), - _INIT_DCS_CMD(0x20, 0x32), - - _INIT_DCS_CMD(0x25, 0x00), - _INIT_DCS_CMD(0x26, 0x46), - _INIT_DCS_CMD(0x27, 0x32), - - _INIT_DCS_CMD(0x3F, 0x80), - _INIT_DCS_CMD(0x40, 0x00), - _INIT_DCS_CMD(0x43, 0x00), - - _INIT_DCS_CMD(0x44, 0x46), - _INIT_DCS_CMD(0x45, 0x46), - - _INIT_DCS_CMD(0x48, 0x46), - _INIT_DCS_CMD(0x49, 0x32), - - _INIT_DCS_CMD(0x5B, 0x80), - - _INIT_DCS_CMD(0x5C, 0x00), - _INIT_DCS_CMD(0x5D, 0x46), - _INIT_DCS_CMD(0x5E, 0x32), - - _INIT_DCS_CMD(0x5F, 0x46), - _INIT_DCS_CMD(0x60, 0x32), - - _INIT_DCS_CMD(0x61, 0x46), - _INIT_DCS_CMD(0x62, 0x32), - _INIT_DCS_CMD(0x68, 0x0C), - - _INIT_DCS_CMD(0x6C, 0x0D), - _INIT_DCS_CMD(0x6E, 0x0D), - _INIT_DCS_CMD(0x78, 0x00), - _INIT_DCS_CMD(0x79, 0xC5), - _INIT_DCS_CMD(0x7A, 0x0C), - _INIT_DCS_CMD(0x7B, 0xB0), - - _INIT_DCS_CMD(0xFF, 0x26), - _INIT_DCS_CMD(0xFB, 0x01), - - _INIT_DCS_CMD(0x00, 0xA1), - _INIT_DCS_CMD(0x02, 0x31), - _INIT_DCS_CMD(0x0A, 0xF4), - _INIT_DCS_CMD(0x04, 0x50), - _INIT_DCS_CMD(0x06, 0x30), - _INIT_DCS_CMD(0x0C, 0x16), - _INIT_DCS_CMD(0x0D, 0x0D), - _INIT_DCS_CMD(0x0F, 0x00), - _INIT_DCS_CMD(0x11, 0x00), - _INIT_DCS_CMD(0x12, 0x50), - _INIT_DCS_CMD(0x13, 0x40), - _INIT_DCS_CMD(0x14, 0x58), - _INIT_DCS_CMD(0x15, 0x00), - _INIT_DCS_CMD(0x16, 0x10), - _INIT_DCS_CMD(0x17, 0xA0), - _INIT_DCS_CMD(0x18, 0x86), - _INIT_DCS_CMD(0x22, 0x00), - _INIT_DCS_CMD(0x23, 0x00), - - _INIT_DCS_CMD(0x19, 0x0E), - _INIT_DCS_CMD(0x1A, 0x31), - _INIT_DCS_CMD(0x1B, 0x0D), - _INIT_DCS_CMD(0x1C, 0x29), - _INIT_DCS_CMD(0x2A, 0x0E), - _INIT_DCS_CMD(0x2B, 0x31), - - _INIT_DCS_CMD(0x1D, 0x00), - _INIT_DCS_CMD(0x1E, 0x62), - _INIT_DCS_CMD(0x1F, 0x62), - - _INIT_DCS_CMD(0x2F, 0x06), - _INIT_DCS_CMD(0x30, 0x62), - _INIT_DCS_CMD(0x31, 0x06), - _INIT_DCS_CMD(0x32, 0x7F), - _INIT_DCS_CMD(0x33, 0x11), - _INIT_DCS_CMD(0x34, 0x89), - _INIT_DCS_CMD(0x35, 0x67), - - _INIT_DCS_CMD(0x39, 0x0B), - _INIT_DCS_CMD(0x3A, 0x62), - _INIT_DCS_CMD(0x3B, 0x06), - - _INIT_DCS_CMD(0xC8, 0x04), - _INIT_DCS_CMD(0xC9, 0x89), - _INIT_DCS_CMD(0xCA, 0x4E), - _INIT_DCS_CMD(0xCB, 0x00), - _INIT_DCS_CMD(0xA9, 0x3F), - _INIT_DCS_CMD(0xAA, 0x3E), - _INIT_DCS_CMD(0xAB, 0x3D), - _INIT_DCS_CMD(0xAC, 0x3C), - _INIT_DCS_CMD(0xAD, 0x3B), - _INIT_DCS_CMD(0xAE, 0x3A), - _INIT_DCS_CMD(0xAF, 0x39), - _INIT_DCS_CMD(0xB0, 0x38), - - _INIT_DCS_CMD(0xFF, 0x27), - _INIT_DCS_CMD(0xFB, 0x01), - - _INIT_DCS_CMD(0xD0, 0x11), - _INIT_DCS_CMD(0xD1, 0x54), - _INIT_DCS_CMD(0xDE, 0x43), - _INIT_DCS_CMD(0xDF, 0x02), - - _INIT_DCS_CMD(0xC0, 0x18), - _INIT_DCS_CMD(0xC1, 0x00), - _INIT_DCS_CMD(0xC2, 0x00), - _INIT_DCS_CMD(0x00, 0x00), - _INIT_DCS_CMD(0xC3, 0x00), - _INIT_DCS_CMD(0x56, 0x06), - - _INIT_DCS_CMD(0x58, 0x80), - _INIT_DCS_CMD(0x59, 0x78), - _INIT_DCS_CMD(0x5A, 0x00), - _INIT_DCS_CMD(0x5B, 0x18), - _INIT_DCS_CMD(0x5C, 0x00), - _INIT_DCS_CMD(0x5D, 0x01), - _INIT_DCS_CMD(0x5E, 0x20), - _INIT_DCS_CMD(0x5F, 0x10), - _INIT_DCS_CMD(0x60, 0x00), - _INIT_DCS_CMD(0x61, 0x1C), - _INIT_DCS_CMD(0x62, 0x00), - _INIT_DCS_CMD(0x63, 0x01), - _INIT_DCS_CMD(0x64, 0x44), - _INIT_DCS_CMD(0x65, 0x1B), - _INIT_DCS_CMD(0x66, 0x00), - _INIT_DCS_CMD(0x67, 0x01), - _INIT_DCS_CMD(0x68, 0x44), - - _INIT_DCS_CMD(0x98, 0x01), - _INIT_DCS_CMD(0xB4, 0x03), - _INIT_DCS_CMD(0x9B, 0xBE), - - _INIT_DCS_CMD(0xAB, 0x14), - _INIT_DCS_CMD(0xBC, 0x08), - _INIT_DCS_CMD(0xBD, 0x28), - - _INIT_DCS_CMD(0xFF, 0x2A), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x22, 0x2F), - _INIT_DCS_CMD(0x23, 0x08), - - _INIT_DCS_CMD(0x24, 0x00), - _INIT_DCS_CMD(0x25, 0x62), - _INIT_DCS_CMD(0x26, 0xF8), - _INIT_DCS_CMD(0x27, 0x00), - _INIT_DCS_CMD(0x28, 0x1A), - _INIT_DCS_CMD(0x29, 0x00), - _INIT_DCS_CMD(0x2A, 0x1A), - _INIT_DCS_CMD(0x2B, 0x00), - _INIT_DCS_CMD(0x2D, 0x1A), - - _INIT_DCS_CMD(0x64, 0x96), - _INIT_DCS_CMD(0x65, 0x10), - _INIT_DCS_CMD(0x66, 0x00), - _INIT_DCS_CMD(0x67, 0x96), - _INIT_DCS_CMD(0x68, 0x10), - _INIT_DCS_CMD(0x69, 0x00), - _INIT_DCS_CMD(0x6A, 0x96), - _INIT_DCS_CMD(0x6B, 0x10), - _INIT_DCS_CMD(0x6C, 0x00), - _INIT_DCS_CMD(0x70, 0x92), - _INIT_DCS_CMD(0x71, 0x10), - _INIT_DCS_CMD(0x72, 0x00), - _INIT_DCS_CMD(0x79, 0x96), - _INIT_DCS_CMD(0x7A, 0x10), - _INIT_DCS_CMD(0x88, 0x96), - _INIT_DCS_CMD(0x89, 0x10), - - _INIT_DCS_CMD(0xA2, 0x3F), - _INIT_DCS_CMD(0xA3, 0x30), - _INIT_DCS_CMD(0xA4, 0xC0), - _INIT_DCS_CMD(0xA5, 0x03), - - _INIT_DCS_CMD(0xE8, 0x00), - - _INIT_DCS_CMD(0x97, 0x3C), - _INIT_DCS_CMD(0x98, 0x02), - _INIT_DCS_CMD(0x99, 0x95), - _INIT_DCS_CMD(0x9A, 0x06), - _INIT_DCS_CMD(0x9B, 0x00), - _INIT_DCS_CMD(0x9C, 0x0B), - _INIT_DCS_CMD(0x9D, 0x0A), - _INIT_DCS_CMD(0x9E, 0x90), - - _INIT_DCS_CMD(0xFF, 0x25), - _INIT_DCS_CMD(0x13, 0x02), - _INIT_DCS_CMD(0x14, 0xD7), - _INIT_DCS_CMD(0xDB, 0x02), - _INIT_DCS_CMD(0xDC, 0xD7), - _INIT_DCS_CMD(0x17, 0xCF), - _INIT_DCS_CMD(0x19, 0x0F), - _INIT_DCS_CMD(0x1B, 0x5B), - - _INIT_DCS_CMD(0xFF, 0x20), - - _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x24, 0x00, 0x38, 0x00, 0x4C, 0x00, 0x5E, 0x00, 0x6F, 0x00, 0x7E), - _INIT_DCS_CMD(0xB1, 0x00, 0x8C, 0x00, 0xBE, 0x00, 0xE5, 0x01, 0x27, 0x01, 0x58, 0x01, 0xA8, 0x01, 0xE8, 0x01, 0xEA), - _INIT_DCS_CMD(0xB2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9E, 0x02, 0xDA, 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51), - _INIT_DCS_CMD(0xB3, 0x03, 0x62, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2), - - _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x27, 0x00, 0x3D, 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84), - _INIT_DCS_CMD(0xB5, 0x00, 0x93, 0x00, 0xC5, 0x00, 0xEC, 0x01, 0x2C, 0x01, 0x5D, 0x01, 0xAC, 0x01, 0xEC, 0x01, 0xEE), - _INIT_DCS_CMD(0xB6, 0x02, 0x2B, 0x02, 0x73, 0x02, 0xA0, 0x02, 0xDB, 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51), - _INIT_DCS_CMD(0xB7, 0x03, 0x63, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2), - - _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x2A, 0x00, 0x40, 0x00, 0x56, 0x00, 0x68, 0x00, 0x7A, 0x00, 0x89), - _INIT_DCS_CMD(0xB9, 0x00, 0x98, 0x00, 0xC9, 0x00, 0xF1, 0x01, 0x30, 0x01, 0x61, 0x01, 0xB0, 0x01, 0xEF, 0x01, 0xF1), - _INIT_DCS_CMD(0xBA, 0x02, 0x2E, 0x02, 0x76, 0x02, 0xA3, 0x02, 0xDD, 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53), - _INIT_DCS_CMD(0xBB, 0x03, 0x66, 0x03, 0x75, 0x03, 0x89, 0x03, 0x9C, 0x03, 0xAA, 0x03, 0xB2), - - _INIT_DCS_CMD(0xFF, 0x21), - _INIT_DCS_CMD(0xB0, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x24, 0x00, 0x38, 0x00, 0x4C, 0x00, 0x5E, 0x00, 0x6F, 0x00, 0x7E), - _INIT_DCS_CMD(0xB1, 0x00, 0x8C, 0x00, 0xBE, 0x00, 0xE5, 0x01, 0x27, 0x01, 0x58, 0x01, 0xA8, 0x01, 0xE8, 0x01, 0xEA), - _INIT_DCS_CMD(0xB2, 0x02, 0x28, 0x02, 0x71, 0x02, 0x9E, 0x02, 0xDA, 0x03, 0x00, 0x03, 0x31, 0x03, 0x40, 0x03, 0x51), - _INIT_DCS_CMD(0xB3, 0x03, 0x62, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA), - - _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x27, 0x00, 0x3D, 0x00, 0x52, 0x00, 0x64, 0x00, 0x75, 0x00, 0x84), - _INIT_DCS_CMD(0xB5, 0x00, 0x93, 0x00, 0xC5, 0x00, 0xEC, 0x01, 0x2C, 0x01, 0x5D, 0x01, 0xAC, 0x01, 0xEC, 0x01, 0xEE), - _INIT_DCS_CMD(0xB6, 0x02, 0x2B, 0x02, 0x73, 0x02, 0xA0, 0x02, 0xDB, 0x03, 0x01, 0x03, 0x31, 0x03, 0x41, 0x03, 0x51), - _INIT_DCS_CMD(0xB7, 0x03, 0x63, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA), - - _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x2A, 0x00, 0x40, 0x00, 0x56, 0x00, 0x68, 0x00, 0x7A, 0x00, 0x89), - _INIT_DCS_CMD(0xB9, 0x00, 0x98, 0x00, 0xC9, 0x00, 0xF1, 0x01, 0x30, 0x01, 0x61, 0x01, 0xB0, 0x01, 0xEF, 0x01, 0xF1), - _INIT_DCS_CMD(0xBA, 0x02, 0x2E, 0x02, 0x76, 0x02, 0xA3, 0x02, 0xDD, 0x03, 0x02, 0x03, 0x32, 0x03, 0x42, 0x03, 0x53), - _INIT_DCS_CMD(0xBB, 0x03, 0x66, 0x03, 0x77, 0x03, 0x90, 0x03, 0xAC, 0x03, 0xCA, 0x03, 0xDA), - - _INIT_DCS_CMD(0xFF, 0xF0), - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0x3A, 0x08), - - _INIT_DCS_CMD(0xFF, 0x10), - _INIT_DCS_CMD(0xB9, 0x01), - - _INIT_DCS_CMD(0xFF, 0x20), - - _INIT_DCS_CMD(0x18, 0x40), - _INIT_DCS_CMD(0xFF, 0x10), - - _INIT_DCS_CMD(0xB9, 0x02), - _INIT_DCS_CMD(0xFF, 0x10), - - _INIT_DCS_CMD(0xFB, 0x01), - _INIT_DCS_CMD(0xB0, 0x01), - _INIT_DCS_CMD(0x35, 0x00), - _INIT_DCS_CMD(0x3B, 0x03, 0xAE, 0x1A, 0x04, 0x04), - _INIT_DELAY_CMD(100), - _INIT_DCS_CMD(0x11), - _INIT_DELAY_CMD(200), - _INIT_DCS_CMD(0x29), - _INIT_DELAY_CMD(100), - {}, -}; +static int boe_init(struct boe_panel *boe) +{ + struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi }; + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0xe5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x52); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x88); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x8b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x1a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x31); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x1c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x2c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x33); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x31); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x37); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x37); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x37); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x39); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x2e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x2f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x2f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x31); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x3f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x3f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x3f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x3f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x37); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x37); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x37); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x39); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x2e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x2f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x2f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x2a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x2a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x43); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0xc0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0xa5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0xa5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x32); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x25); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x97); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x22); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa4); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x2f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x25); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x61); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x97); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb2); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcd); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xd9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe7); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf4); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x98); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x23); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa6); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x30); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xaa); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x62); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdb); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe8); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x3b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x73); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x99); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xe0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xad); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x36); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x3a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xae); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x2a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x66); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb8); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xd1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdd); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf6); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x25); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x97); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x22); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa4); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x2f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x25); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x61); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x97); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb2); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcd); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xd9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe7); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf4); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x39); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x72); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x98); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xdc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x23); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xa6); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x2c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x30); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xaa); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x62); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdb); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe8); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x24); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x3b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb7, 0x73); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x99); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xe0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x26); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbb, 0xad); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbc, 0x36); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x3a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xae); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x2a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x66); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x9e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xb8); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xd1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xdd); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xe9); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xf6); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xfa); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xfc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0xaf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0xff); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb3, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb8, 0x68); + + mipi_dsi_msleep(&ctx, 150); -static const struct panel_init_cmd boe_init_cmd[] = { - _INIT_DCS_CMD(0xB0, 0x05), - _INIT_DCS_CMD(0xB1, 0xE5), - _INIT_DCS_CMD(0xB3, 0x52), - _INIT_DCS_CMD(0xB0, 0x00), - _INIT_DCS_CMD(0xB3, 0x88), - _INIT_DCS_CMD(0xB0, 0x04), - _INIT_DCS_CMD(0xB8, 0x00), - _INIT_DCS_CMD(0xB0, 0x00), - _INIT_DCS_CMD(0xB6, 0x03), - _INIT_DCS_CMD(0xBA, 0x8B), - _INIT_DCS_CMD(0xBF, 0x1A), - _INIT_DCS_CMD(0xC0, 0x0F), - _INIT_DCS_CMD(0xC2, 0x0C), - _INIT_DCS_CMD(0xC3, 0x02), - _INIT_DCS_CMD(0xC4, 0x0C), - _INIT_DCS_CMD(0xC5, 0x02), - _INIT_DCS_CMD(0xB0, 0x01), - _INIT_DCS_CMD(0xE0, 0x26), - _INIT_DCS_CMD(0xE1, 0x26), - _INIT_DCS_CMD(0xDC, 0x00), - _INIT_DCS_CMD(0xDD, 0x00), - _INIT_DCS_CMD(0xCC, 0x26), - _INIT_DCS_CMD(0xCD, 0x26), - _INIT_DCS_CMD(0xC8, 0x00), - _INIT_DCS_CMD(0xC9, 0x00), - _INIT_DCS_CMD(0xD2, 0x03), - _INIT_DCS_CMD(0xD3, 0x03), - _INIT_DCS_CMD(0xE6, 0x04), - _INIT_DCS_CMD(0xE7, 0x04), - _INIT_DCS_CMD(0xC4, 0x09), - _INIT_DCS_CMD(0xC5, 0x09), - _INIT_DCS_CMD(0xD8, 0x0A), - _INIT_DCS_CMD(0xD9, 0x0A), - _INIT_DCS_CMD(0xC2, 0x0B), - _INIT_DCS_CMD(0xC3, 0x0B), - _INIT_DCS_CMD(0xD6, 0x0C), - _INIT_DCS_CMD(0xD7, 0x0C), - _INIT_DCS_CMD(0xC0, 0x05), - _INIT_DCS_CMD(0xC1, 0x05), - _INIT_DCS_CMD(0xD4, 0x06), - _INIT_DCS_CMD(0xD5, 0x06), - _INIT_DCS_CMD(0xCA, 0x07), - _INIT_DCS_CMD(0xCB, 0x07), - _INIT_DCS_CMD(0xDE, 0x08), - _INIT_DCS_CMD(0xDF, 0x08), - _INIT_DCS_CMD(0xB0, 0x02), - _INIT_DCS_CMD(0xC0, 0x00), - _INIT_DCS_CMD(0xC1, 0x0D), - _INIT_DCS_CMD(0xC2, 0x17), - _INIT_DCS_CMD(0xC3, 0x26), - _INIT_DCS_CMD(0xC4, 0x31), - _INIT_DCS_CMD(0xC5, 0x1C), - _INIT_DCS_CMD(0xC6, 0x2C), - _INIT_DCS_CMD(0xC7, 0x33), - _INIT_DCS_CMD(0xC8, 0x31), - _INIT_DCS_CMD(0xC9, 0x37), - _INIT_DCS_CMD(0xCA, 0x37), - _INIT_DCS_CMD(0xCB, 0x37), - _INIT_DCS_CMD(0xCC, 0x39), - _INIT_DCS_CMD(0xCD, 0x2E), - _INIT_DCS_CMD(0xCE, 0x2F), - _INIT_DCS_CMD(0xCF, 0x2F), - _INIT_DCS_CMD(0xD0, 0x07), - _INIT_DCS_CMD(0xD2, 0x00), - _INIT_DCS_CMD(0xD3, 0x0D), - _INIT_DCS_CMD(0xD4, 0x17), - _INIT_DCS_CMD(0xD5, 0x26), - _INIT_DCS_CMD(0xD6, 0x31), - _INIT_DCS_CMD(0xD7, 0x3F), - _INIT_DCS_CMD(0xD8, 0x3F), - _INIT_DCS_CMD(0xD9, 0x3F), - _INIT_DCS_CMD(0xDA, 0x3F), - _INIT_DCS_CMD(0xDB, 0x37), - _INIT_DCS_CMD(0xDC, 0x37), - _INIT_DCS_CMD(0xDD, 0x37), - _INIT_DCS_CMD(0xDE, 0x39), - _INIT_DCS_CMD(0xDF, 0x2E), - _INIT_DCS_CMD(0xE0, 0x2F), - _INIT_DCS_CMD(0xE1, 0x2F), - _INIT_DCS_CMD(0xE2, 0x07), - _INIT_DCS_CMD(0xB0, 0x03), - _INIT_DCS_CMD(0xC8, 0x0B), - _INIT_DCS_CMD(0xC9, 0x07), - _INIT_DCS_CMD(0xC3, 0x00), - _INIT_DCS_CMD(0xE7, 0x00), - _INIT_DCS_CMD(0xC5, 0x2A), - _INIT_DCS_CMD(0xDE, 0x2A), - _INIT_DCS_CMD(0xCA, 0x43), - _INIT_DCS_CMD(0xC9, 0x07), - _INIT_DCS_CMD(0xE4, 0xC0), - _INIT_DCS_CMD(0xE5, 0x0D), - _INIT_DCS_CMD(0xCB, 0x00), - _INIT_DCS_CMD(0xB0, 0x06), - _INIT_DCS_CMD(0xB8, 0xA5), - _INIT_DCS_CMD(0xC0, 0xA5), - _INIT_DCS_CMD(0xC7, 0x0F), - _INIT_DCS_CMD(0xD5, 0x32), - _INIT_DCS_CMD(0xB8, 0x00), - _INIT_DCS_CMD(0xC0, 0x00), - _INIT_DCS_CMD(0xBC, 0x00), - _INIT_DCS_CMD(0xB0, 0x07), - _INIT_DCS_CMD(0xB1, 0x00), - _INIT_DCS_CMD(0xB2, 0x02), - _INIT_DCS_CMD(0xB3, 0x0F), - _INIT_DCS_CMD(0xB4, 0x25), - _INIT_DCS_CMD(0xB5, 0x39), - _INIT_DCS_CMD(0xB6, 0x4E), - _INIT_DCS_CMD(0xB7, 0x72), - _INIT_DCS_CMD(0xB8, 0x97), - _INIT_DCS_CMD(0xB9, 0xDC), - _INIT_DCS_CMD(0xBA, 0x22), - _INIT_DCS_CMD(0xBB, 0xA4), - _INIT_DCS_CMD(0xBC, 0x2B), - _INIT_DCS_CMD(0xBD, 0x2F), - _INIT_DCS_CMD(0xBE, 0xA9), - _INIT_DCS_CMD(0xBF, 0x25), - _INIT_DCS_CMD(0xC0, 0x61), - _INIT_DCS_CMD(0xC1, 0x97), - _INIT_DCS_CMD(0xC2, 0xB2), - _INIT_DCS_CMD(0xC3, 0xCD), - _INIT_DCS_CMD(0xC4, 0xD9), - _INIT_DCS_CMD(0xC5, 0xE7), - _INIT_DCS_CMD(0xC6, 0xF4), - _INIT_DCS_CMD(0xC7, 0xFA), - _INIT_DCS_CMD(0xC8, 0xFC), - _INIT_DCS_CMD(0xC9, 0x00), - _INIT_DCS_CMD(0xCA, 0x00), - _INIT_DCS_CMD(0xCB, 0x16), - _INIT_DCS_CMD(0xCC, 0xAF), - _INIT_DCS_CMD(0xCD, 0xFF), - _INIT_DCS_CMD(0xCE, 0xFF), - _INIT_DCS_CMD(0xB0, 0x08), - _INIT_DCS_CMD(0xB1, 0x04), - _INIT_DCS_CMD(0xB2, 0x05), - _INIT_DCS_CMD(0xB3, 0x11), - _INIT_DCS_CMD(0xB4, 0x24), - _INIT_DCS_CMD(0xB5, 0x39), - _INIT_DCS_CMD(0xB6, 0x4F), - _INIT_DCS_CMD(0xB7, 0x72), - _INIT_DCS_CMD(0xB8, 0x98), - _INIT_DCS_CMD(0xB9, 0xDC), - _INIT_DCS_CMD(0xBA, 0x23), - _INIT_DCS_CMD(0xBB, 0xA6), - _INIT_DCS_CMD(0xBC, 0x2C), - _INIT_DCS_CMD(0xBD, 0x30), - _INIT_DCS_CMD(0xBE, 0xAA), - _INIT_DCS_CMD(0xBF, 0x26), - _INIT_DCS_CMD(0xC0, 0x62), - _INIT_DCS_CMD(0xC1, 0x9B), - _INIT_DCS_CMD(0xC2, 0xB5), - _INIT_DCS_CMD(0xC3, 0xCF), - _INIT_DCS_CMD(0xC4, 0xDB), - _INIT_DCS_CMD(0xC5, 0xE8), - _INIT_DCS_CMD(0xC6, 0xF5), - _INIT_DCS_CMD(0xC7, 0xFA), - _INIT_DCS_CMD(0xC8, 0xFC), - _INIT_DCS_CMD(0xC9, 0x00), - _INIT_DCS_CMD(0xCA, 0x00), - _INIT_DCS_CMD(0xCB, 0x16), - _INIT_DCS_CMD(0xCC, 0xAF), - _INIT_DCS_CMD(0xCD, 0xFF), - _INIT_DCS_CMD(0xCE, 0xFF), - _INIT_DCS_CMD(0xB0, 0x09), - _INIT_DCS_CMD(0xB1, 0x04), - _INIT_DCS_CMD(0xB2, 0x02), - _INIT_DCS_CMD(0xB3, 0x16), - _INIT_DCS_CMD(0xB4, 0x24), - _INIT_DCS_CMD(0xB5, 0x3B), - _INIT_DCS_CMD(0xB6, 0x4F), - _INIT_DCS_CMD(0xB7, 0x73), - _INIT_DCS_CMD(0xB8, 0x99), - _INIT_DCS_CMD(0xB9, 0xE0), - _INIT_DCS_CMD(0xBA, 0x26), - _INIT_DCS_CMD(0xBB, 0xAD), - _INIT_DCS_CMD(0xBC, 0x36), - _INIT_DCS_CMD(0xBD, 0x3A), - _INIT_DCS_CMD(0xBE, 0xAE), - _INIT_DCS_CMD(0xBF, 0x2A), - _INIT_DCS_CMD(0xC0, 0x66), - _INIT_DCS_CMD(0xC1, 0x9E), - _INIT_DCS_CMD(0xC2, 0xB8), - _INIT_DCS_CMD(0xC3, 0xD1), - _INIT_DCS_CMD(0xC4, 0xDD), - _INIT_DCS_CMD(0xC5, 0xE9), - _INIT_DCS_CMD(0xC6, 0xF6), - _INIT_DCS_CMD(0xC7, 0xFA), - _INIT_DCS_CMD(0xC8, 0xFC), - _INIT_DCS_CMD(0xC9, 0x00), - _INIT_DCS_CMD(0xCA, 0x00), - _INIT_DCS_CMD(0xCB, 0x16), - _INIT_DCS_CMD(0xCC, 0xAF), - _INIT_DCS_CMD(0xCD, 0xFF), - _INIT_DCS_CMD(0xCE, 0xFF), - _INIT_DCS_CMD(0xB0, 0x0A), - _INIT_DCS_CMD(0xB1, 0x00), - _INIT_DCS_CMD(0xB2, 0x02), - _INIT_DCS_CMD(0xB3, 0x0F), - _INIT_DCS_CMD(0xB4, 0x25), - _INIT_DCS_CMD(0xB5, 0x39), - _INIT_DCS_CMD(0xB6, 0x4E), - _INIT_DCS_CMD(0xB7, 0x72), - _INIT_DCS_CMD(0xB8, 0x97), - _INIT_DCS_CMD(0xB9, 0xDC), - _INIT_DCS_CMD(0xBA, 0x22), - _INIT_DCS_CMD(0xBB, 0xA4), - _INIT_DCS_CMD(0xBC, 0x2B), - _INIT_DCS_CMD(0xBD, 0x2F), - _INIT_DCS_CMD(0xBE, 0xA9), - _INIT_DCS_CMD(0xBF, 0x25), - _INIT_DCS_CMD(0xC0, 0x61), - _INIT_DCS_CMD(0xC1, 0x97), - _INIT_DCS_CMD(0xC2, 0xB2), - _INIT_DCS_CMD(0xC3, 0xCD), - _INIT_DCS_CMD(0xC4, 0xD9), - _INIT_DCS_CMD(0xC5, 0xE7), - _INIT_DCS_CMD(0xC6, 0xF4), - _INIT_DCS_CMD(0xC7, 0xFA), - _INIT_DCS_CMD(0xC8, 0xFC), - _INIT_DCS_CMD(0xC9, 0x00), - _INIT_DCS_CMD(0xCA, 0x00), - _INIT_DCS_CMD(0xCB, 0x16), - _INIT_DCS_CMD(0xCC, 0xAF), - _INIT_DCS_CMD(0xCD, 0xFF), - _INIT_DCS_CMD(0xCE, 0xFF), - _INIT_DCS_CMD(0xB0, 0x0B), - _INIT_DCS_CMD(0xB1, 0x04), - _INIT_DCS_CMD(0xB2, 0x05), - _INIT_DCS_CMD(0xB3, 0x11), - _INIT_DCS_CMD(0xB4, 0x24), - _INIT_DCS_CMD(0xB5, 0x39), - _INIT_DCS_CMD(0xB6, 0x4F), - _INIT_DCS_CMD(0xB7, 0x72), - _INIT_DCS_CMD(0xB8, 0x98), - _INIT_DCS_CMD(0xB9, 0xDC), - _INIT_DCS_CMD(0xBA, 0x23), - _INIT_DCS_CMD(0xBB, 0xA6), - _INIT_DCS_CMD(0xBC, 0x2C), - _INIT_DCS_CMD(0xBD, 0x30), - _INIT_DCS_CMD(0xBE, 0xAA), - _INIT_DCS_CMD(0xBF, 0x26), - _INIT_DCS_CMD(0xC0, 0x62), - _INIT_DCS_CMD(0xC1, 0x9B), - _INIT_DCS_CMD(0xC2, 0xB5), - _INIT_DCS_CMD(0xC3, 0xCF), - _INIT_DCS_CMD(0xC4, 0xDB), - _INIT_DCS_CMD(0xC5, 0xE8), - _INIT_DCS_CMD(0xC6, 0xF5), - _INIT_DCS_CMD(0xC7, 0xFA), - _INIT_DCS_CMD(0xC8, 0xFC), - _INIT_DCS_CMD(0xC9, 0x00), - _INIT_DCS_CMD(0xCA, 0x00), - _INIT_DCS_CMD(0xCB, 0x16), - _INIT_DCS_CMD(0xCC, 0xAF), - _INIT_DCS_CMD(0xCD, 0xFF), - _INIT_DCS_CMD(0xCE, 0xFF), - _INIT_DCS_CMD(0xB0, 0x0C), - _INIT_DCS_CMD(0xB1, 0x04), - _INIT_DCS_CMD(0xB2, 0x02), - _INIT_DCS_CMD(0xB3, 0x16), - _INIT_DCS_CMD(0xB4, 0x24), - _INIT_DCS_CMD(0xB5, 0x3B), - _INIT_DCS_CMD(0xB6, 0x4F), - _INIT_DCS_CMD(0xB7, 0x73), - _INIT_DCS_CMD(0xB8, 0x99), - _INIT_DCS_CMD(0xB9, 0xE0), - _INIT_DCS_CMD(0xBA, 0x26), - _INIT_DCS_CMD(0xBB, 0xAD), - _INIT_DCS_CMD(0xBC, 0x36), - _INIT_DCS_CMD(0xBD, 0x3A), - _INIT_DCS_CMD(0xBE, 0xAE), - _INIT_DCS_CMD(0xBF, 0x2A), - _INIT_DCS_CMD(0xC0, 0x66), - _INIT_DCS_CMD(0xC1, 0x9E), - _INIT_DCS_CMD(0xC2, 0xB8), - _INIT_DCS_CMD(0xC3, 0xD1), - _INIT_DCS_CMD(0xC4, 0xDD), - _INIT_DCS_CMD(0xC5, 0xE9), - _INIT_DCS_CMD(0xC6, 0xF6), - _INIT_DCS_CMD(0xC7, 0xFA), - _INIT_DCS_CMD(0xC8, 0xFC), - _INIT_DCS_CMD(0xC9, 0x00), - _INIT_DCS_CMD(0xCA, 0x00), - _INIT_DCS_CMD(0xCB, 0x16), - _INIT_DCS_CMD(0xCC, 0xAF), - _INIT_DCS_CMD(0xCD, 0xFF), - _INIT_DCS_CMD(0xCE, 0xFF), - _INIT_DCS_CMD(0xB0, 0x00), - _INIT_DCS_CMD(0xB3, 0x08), - _INIT_DCS_CMD(0xB0, 0x04), - _INIT_DCS_CMD(0xB8, 0x68), - _INIT_DELAY_CMD(150), - {}, + return 0; }; -static const struct panel_init_cmd auo_kd101n80_45na_init_cmd[] = { - _INIT_DELAY_CMD(24), - _INIT_DCS_CMD(0x11), - _INIT_DELAY_CMD(120), - _INIT_DCS_CMD(0x29), - _INIT_DELAY_CMD(120), - {}, -}; +static int auo_kd101n80_45na_init(struct boe_panel *boe) +{ + struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi }; -static const struct panel_init_cmd auo_b101uan08_3_init_cmd[] = { - _INIT_DELAY_CMD(24), - _INIT_DCS_CMD(0xB0, 0x01), - _INIT_DCS_CMD(0xC0, 0x48), - _INIT_DCS_CMD(0xC1, 0x48), - _INIT_DCS_CMD(0xC2, 0x47), - _INIT_DCS_CMD(0xC3, 0x47), - _INIT_DCS_CMD(0xC4, 0x46), - _INIT_DCS_CMD(0xC5, 0x46), - _INIT_DCS_CMD(0xC6, 0x45), - _INIT_DCS_CMD(0xC7, 0x45), - _INIT_DCS_CMD(0xC8, 0x64), - _INIT_DCS_CMD(0xC9, 0x64), - _INIT_DCS_CMD(0xCA, 0x4F), - _INIT_DCS_CMD(0xCB, 0x4F), - _INIT_DCS_CMD(0xCC, 0x40), - _INIT_DCS_CMD(0xCD, 0x40), - _INIT_DCS_CMD(0xCE, 0x66), - _INIT_DCS_CMD(0xCF, 0x66), - _INIT_DCS_CMD(0xD0, 0x4F), - _INIT_DCS_CMD(0xD1, 0x4F), - _INIT_DCS_CMD(0xD2, 0x41), - _INIT_DCS_CMD(0xD3, 0x41), - _INIT_DCS_CMD(0xD4, 0x48), - _INIT_DCS_CMD(0xD5, 0x48), - _INIT_DCS_CMD(0xD6, 0x47), - _INIT_DCS_CMD(0xD7, 0x47), - _INIT_DCS_CMD(0xD8, 0x46), - _INIT_DCS_CMD(0xD9, 0x46), - _INIT_DCS_CMD(0xDA, 0x45), - _INIT_DCS_CMD(0xDB, 0x45), - _INIT_DCS_CMD(0xDC, 0x64), - _INIT_DCS_CMD(0xDD, 0x64), - _INIT_DCS_CMD(0xDE, 0x4F), - _INIT_DCS_CMD(0xDF, 0x4F), - _INIT_DCS_CMD(0xE0, 0x40), - _INIT_DCS_CMD(0xE1, 0x40), - _INIT_DCS_CMD(0xE2, 0x66), - _INIT_DCS_CMD(0xE3, 0x66), - _INIT_DCS_CMD(0xE4, 0x4F), - _INIT_DCS_CMD(0xE5, 0x4F), - _INIT_DCS_CMD(0xE6, 0x41), - _INIT_DCS_CMD(0xE7, 0x41), - _INIT_DELAY_CMD(150), - {}, -}; + msleep(24); -static const struct panel_init_cmd starry_qfh032011_53g_init_cmd[] = { - _INIT_DCS_CMD(0xB0, 0x01), - _INIT_DCS_CMD(0xC3, 0x4F), - _INIT_DCS_CMD(0xC4, 0x40), - _INIT_DCS_CMD(0xC5, 0x40), - _INIT_DCS_CMD(0xC6, 0x40), - _INIT_DCS_CMD(0xC7, 0x40), - _INIT_DCS_CMD(0xC8, 0x4D), - _INIT_DCS_CMD(0xC9, 0x52), - _INIT_DCS_CMD(0xCA, 0x51), - _INIT_DCS_CMD(0xCD, 0x5D), - _INIT_DCS_CMD(0xCE, 0x5B), - _INIT_DCS_CMD(0xCF, 0x4B), - _INIT_DCS_CMD(0xD0, 0x49), - _INIT_DCS_CMD(0xD1, 0x47), - _INIT_DCS_CMD(0xD2, 0x45), - _INIT_DCS_CMD(0xD3, 0x41), - _INIT_DCS_CMD(0xD7, 0x50), - _INIT_DCS_CMD(0xD8, 0x40), - _INIT_DCS_CMD(0xD9, 0x40), - _INIT_DCS_CMD(0xDA, 0x40), - _INIT_DCS_CMD(0xDB, 0x40), - _INIT_DCS_CMD(0xDC, 0x4E), - _INIT_DCS_CMD(0xDD, 0x52), - _INIT_DCS_CMD(0xDE, 0x51), - _INIT_DCS_CMD(0xE1, 0x5E), - _INIT_DCS_CMD(0xE2, 0x5C), - _INIT_DCS_CMD(0xE3, 0x4C), - _INIT_DCS_CMD(0xE4, 0x4A), - _INIT_DCS_CMD(0xE5, 0x48), - _INIT_DCS_CMD(0xE6, 0x46), - _INIT_DCS_CMD(0xE7, 0x42), - _INIT_DCS_CMD(0xB0, 0x03), - _INIT_DCS_CMD(0xBE, 0x03), - _INIT_DCS_CMD(0xCC, 0x44), - _INIT_DCS_CMD(0xC8, 0x07), - _INIT_DCS_CMD(0xC9, 0x05), - _INIT_DCS_CMD(0xCA, 0x42), - _INIT_DCS_CMD(0xCD, 0x3E), - _INIT_DCS_CMD(0xCF, 0x60), - _INIT_DCS_CMD(0xD2, 0x04), - _INIT_DCS_CMD(0xD3, 0x04), - _INIT_DCS_CMD(0xD4, 0x01), - _INIT_DCS_CMD(0xD5, 0x00), - _INIT_DCS_CMD(0xD6, 0x03), - _INIT_DCS_CMD(0xD7, 0x04), - _INIT_DCS_CMD(0xD9, 0x01), - _INIT_DCS_CMD(0xDB, 0x01), - _INIT_DCS_CMD(0xE4, 0xF0), - _INIT_DCS_CMD(0xE5, 0x0A), - _INIT_DCS_CMD(0xB0, 0x00), - _INIT_DCS_CMD(0xCC, 0x08), - _INIT_DCS_CMD(0xC2, 0x08), - _INIT_DCS_CMD(0xC4, 0x10), - _INIT_DCS_CMD(0xB0, 0x02), - _INIT_DCS_CMD(0xC0, 0x00), - _INIT_DCS_CMD(0xC1, 0x0A), - _INIT_DCS_CMD(0xC2, 0x20), - _INIT_DCS_CMD(0xC3, 0x24), - _INIT_DCS_CMD(0xC4, 0x23), - _INIT_DCS_CMD(0xC5, 0x29), - _INIT_DCS_CMD(0xC6, 0x23), - _INIT_DCS_CMD(0xC7, 0x1C), - _INIT_DCS_CMD(0xC8, 0x19), - _INIT_DCS_CMD(0xC9, 0x17), - _INIT_DCS_CMD(0xCA, 0x17), - _INIT_DCS_CMD(0xCB, 0x18), - _INIT_DCS_CMD(0xCC, 0x1A), - _INIT_DCS_CMD(0xCD, 0x1E), - _INIT_DCS_CMD(0xCE, 0x20), - _INIT_DCS_CMD(0xCF, 0x23), - _INIT_DCS_CMD(0xD0, 0x07), - _INIT_DCS_CMD(0xD1, 0x00), - _INIT_DCS_CMD(0xD2, 0x00), - _INIT_DCS_CMD(0xD3, 0x0A), - _INIT_DCS_CMD(0xD4, 0x13), - _INIT_DCS_CMD(0xD5, 0x1C), - _INIT_DCS_CMD(0xD6, 0x1A), - _INIT_DCS_CMD(0xD7, 0x13), - _INIT_DCS_CMD(0xD8, 0x17), - _INIT_DCS_CMD(0xD9, 0x1C), - _INIT_DCS_CMD(0xDA, 0x19), - _INIT_DCS_CMD(0xDB, 0x17), - _INIT_DCS_CMD(0xDC, 0x17), - _INIT_DCS_CMD(0xDD, 0x18), - _INIT_DCS_CMD(0xDE, 0x1A), - _INIT_DCS_CMD(0xDF, 0x1E), - _INIT_DCS_CMD(0xE0, 0x20), - _INIT_DCS_CMD(0xE1, 0x23), - _INIT_DCS_CMD(0xE2, 0x07), - _INIT_DCS_CMD(0X11), - _INIT_DELAY_CMD(120), - _INIT_DCS_CMD(0X29), - _INIT_DELAY_CMD(80), - {}, -}; + mipi_dsi_dcs_write_seq_multi(&ctx, 0x11); -static const struct panel_init_cmd starry_himax83102_j02_init_cmd[] = { - _INIT_DCS_CMD(0xB9, 0x83, 0x10, 0x21, 0x55, 0x00), - _INIT_DCS_CMD(0xB1, 0x2C, 0xB5, 0xB5, 0x31, 0xF1, 0x31, 0xD7, 0x2F, 0x36, 0x36, 0x36, 0x36, 0x1A, 0x8B, 0x11, - 0x65, 0x00, 0x88, 0xFA, 0xFF, 0xFF, 0x8F, 0xFF, 0x08, 0x74, 0x33), - _INIT_DCS_CMD(0xB2, 0x00, 0x47, 0xB0, 0x80, 0x00, 0x12, 0x72, 0x3C, 0xA3, 0x03, 0x03, 0x00, 0x00, 0x88, 0xF5), - _INIT_DCS_CMD(0xB4, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x63, 0x5C, 0x63, 0x5C, 0x01, 0x9E), - _INIT_DCS_CMD(0xE9, 0xCD), - _INIT_DCS_CMD(0xBA, 0x84), - _INIT_DCS_CMD(0xE9, 0x3F), - _INIT_DCS_CMD(0xBC, 0x1B, 0x04), - _INIT_DCS_CMD(0xBE, 0x20), - _INIT_DCS_CMD(0xBF, 0xFC, 0xC4), - _INIT_DCS_CMD(0xC0, 0x36, 0x36, 0x22, 0x11, 0x22, 0xA0, 0x61, 0x08, 0xF5, 0x03), - _INIT_DCS_CMD(0xE9, 0xCC), - _INIT_DCS_CMD(0xC7, 0x80), - _INIT_DCS_CMD(0xE9, 0x3F), - _INIT_DCS_CMD(0xE9, 0xC6), - _INIT_DCS_CMD(0xC8, 0x97), - _INIT_DCS_CMD(0xE9, 0x3F), - _INIT_DCS_CMD(0xC9, 0x00, 0x1E, 0x13, 0x88, 0x01), - _INIT_DCS_CMD(0xCB, 0x08, 0x13, 0x07, 0x00, 0x0F, 0x33), - _INIT_DCS_CMD(0xCC, 0x02), - _INIT_DCS_CMD(0xE9, 0xC4), - _INIT_DCS_CMD(0xD0, 0x03), - _INIT_DCS_CMD(0xE9, 0x3F), - _INIT_DCS_CMD(0xD1, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0C, 0xFF), - _INIT_DCS_CMD(0xD2, 0x1F, 0x11, 0x1F), - _INIT_DCS_CMD(0xD3, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x37, 0x47, 0x34, 0x3B, 0x12, 0x12, 0x03, - 0x03, 0x32, 0x10, 0x10, 0x00, 0x10, 0x32, 0x10, 0x08, 0x00, 0x08, 0x32, 0x17, 0x94, 0x07, 0x94, 0x00, 0x00), - _INIT_DCS_CMD(0xD5, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x40, 0x40, 0x1A, 0x1A, - 0x1B, 0x1B, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x28, 0x29, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18), - _INIT_DCS_CMD(0xD6, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x40, 0x40, 0x19, 0x19, 0x1A, 0x1A, - 0x1B, 0x1B, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x29, 0x28, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18), - _INIT_DCS_CMD(0xD8, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, - 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0, 0xAA, 0xBA, 0xEA, 0xAA, 0xAA, 0xA0), - _INIT_DCS_CMD(0xE0, 0x00, 0x09, 0x14, 0x1E, 0x26, 0x48, 0x61, 0x67, 0x6C, 0x67, 0x7D, 0x7F, 0x80, 0x8B, 0x87, 0x8F, 0x98, 0xAB, - 0xAB, 0x55, 0x5C, 0x68, 0x73, 0x00, 0x09, 0x14, 0x1E, 0x26, 0x48, 0x61, 0x67, 0x6C, 0x67, 0x7D, 0x7F, 0x80, 0x8B, 0x87, 0x8F, 0x98, 0xAB, 0xAB, 0x55, 0x5C, 0x68, 0x73), - _INIT_DCS_CMD(0xE7, 0x0E, 0x10, 0x10, 0x21, 0x2B, 0x9A, 0x02, 0x54, 0x9A, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x05, 0x02, 0x02, 0x10), - _INIT_DCS_CMD(0xBD, 0x01), - _INIT_DCS_CMD(0xB1, 0x01, 0xBF, 0x11), - _INIT_DCS_CMD(0xCB, 0x86), - _INIT_DCS_CMD(0xD2, 0x3C, 0xFA), - _INIT_DCS_CMD(0xD3, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x01), - _INIT_DCS_CMD(0xE7, 0x02, 0x00, 0x28, 0x01, 0x7E, 0x0F, 0x7E, 0x10, 0xA0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40), - _INIT_DCS_CMD(0xBD, 0x02), - _INIT_DCS_CMD(0xD8, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0), - _INIT_DCS_CMD(0xE7, 0xFE, 0x04, 0xFE, 0x04, 0xFE, 0x04, 0x03, 0x03, 0x03, 0x26, 0x00, 0x26, 0x81, 0x02, 0x40, 0x00, 0x20, 0x9E, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00), - _INIT_DCS_CMD(0xBD, 0x03), - _INIT_DCS_CMD(0xE9, 0xC6), - _INIT_DCS_CMD(0xB4, 0x03, 0xFF, 0xF8), - _INIT_DCS_CMD(0xE9, 0x3F), - _INIT_DCS_CMD(0xD8, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8, - 0x00, 0x00, 0x00, 0x2A, 0xAA, 0xA8, 0x00, 0x00), - _INIT_DCS_CMD(0xBD, 0x00), - _INIT_DCS_CMD(0xE9, 0xC4), - _INIT_DCS_CMD(0xBA, 0x96), - _INIT_DCS_CMD(0xE9, 0x3F), - _INIT_DCS_CMD(0xBD, 0x01), - _INIT_DCS_CMD(0xE9, 0xC5), - _INIT_DCS_CMD(0xBA, 0x4F), - _INIT_DCS_CMD(0xE9, 0x3F), - _INIT_DCS_CMD(0xBD, 0x00), - _INIT_DCS_CMD(0x11), - _INIT_DELAY_CMD(120), - _INIT_DCS_CMD(0x29), - {}, -}; + mipi_dsi_msleep(&ctx, 120); -static inline struct boe_panel *to_boe_panel(struct drm_panel *panel) -{ - return container_of(panel, struct boe_panel, base); -} + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29); + + mipi_dsi_msleep(&ctx, 120); -static int boe_panel_init_dcs_cmd(struct boe_panel *boe) -{ - struct mipi_dsi_device *dsi = boe->dsi; - struct drm_panel *panel = &boe->base; - int i, err = 0; - - if (boe->desc->init_cmds) { - const struct panel_init_cmd *init_cmds = boe->desc->init_cmds; - - for (i = 0; init_cmds[i].len != 0; i++) { - const struct panel_init_cmd *cmd = &init_cmds[i]; - - switch (cmd->type) { - case DELAY_CMD: - msleep(cmd->data[0]); - err = 0; - break; - - case INIT_DCS_CMD: - err = mipi_dsi_dcs_write(dsi, cmd->data[0], - cmd->len <= 1 ? NULL : - &cmd->data[1], - cmd->len - 1); - break; - - default: - err = -EINVAL; - } - - if (err < 0) { - dev_err(panel->dev, - "failed to write command %u\n", i); - return err; - } - } - } return 0; -} +}; -static int boe_panel_enter_sleep_mode(struct boe_panel *boe) +static int auo_b101uan08_3_init(struct boe_panel *boe) { - struct mipi_dsi_device *dsi = boe->dsi; - int ret; - - dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi }; + + msleep(24); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x48); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x48); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x47); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x47); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x45); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x45); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x64); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x64); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x66); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x66); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x41); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x41); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x48); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x48); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x47); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x47); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x45); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x45); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x64); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x64); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x66); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x66); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x41); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x41); + + mipi_dsi_msleep(&ctx, 150); - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) - return ret; + return 0; +}; - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) - return ret; +static int starry_qfh032011_53g_init(struct boe_panel *boe) +{ + struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi }; + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x4f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x4d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x52); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x51); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x5d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x5b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x4b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x49); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x47); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x45); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x41); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x50); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x4e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x52); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x51); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x5e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x5c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x4c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x4a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x48); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x42); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x44); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x42); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x3e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0xf0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0x24); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0x23); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0x23); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0x1c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0x19); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x18); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x1a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x1e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x23); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd4, 0x13); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x1c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x1a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd7, 0x13); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd9, 0x1c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xda, 0x19); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdb, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdd, 0x18); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xde, 0x1a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdf, 0x1e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x20); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x23); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0X11); + + mipi_dsi_msleep(&ctx, 120); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0X29); + + mipi_dsi_msleep(&ctx, 80); return 0; +}; + +static inline struct boe_panel *to_boe_panel(struct drm_panel *panel) +{ + return container_of(panel, struct boe_panel, base); } static int boe_panel_disable(struct drm_panel *panel) { struct boe_panel *boe = to_boe_panel(panel); - int ret; + struct mipi_dsi_multi_context ctx = { .dsi = boe->dsi }; - ret = boe_panel_enter_sleep_mode(boe); - if (ret < 0) { - dev_err(panel->dev, "failed to set panel off: %d\n", ret); - return ret; - } + boe->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - msleep(150); + mipi_dsi_dcs_set_display_off_multi(&ctx); + mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); - return 0; + mipi_dsi_msleep(&ctx, 150); + + return ctx.accum_err; } static int boe_panel_unprepare(struct drm_panel *panel) { struct boe_panel *boe = to_boe_panel(panel); - if (!boe->prepared) - return 0; - if (boe->desc->discharge_on_disable) { regulator_disable(boe->avee); regulator_disable(boe->avdd); @@ -1471,8 +1415,6 @@ static int boe_panel_unprepare(struct drm_panel *panel) regulator_disable(boe->pp3300); } - boe->prepared = false; - return 0; } @@ -1481,9 +1423,6 @@ static int boe_panel_prepare(struct drm_panel *panel) struct boe_panel *boe = to_boe_panel(panel); int ret; - if (boe->prepared) - return 0; - gpiod_set_value(boe->enable_gpio, 0); usleep_range(1000, 1500); @@ -1507,7 +1446,11 @@ static int boe_panel_prepare(struct drm_panel *panel) usleep_range(10000, 11000); if (boe->desc->lp11_before_reset) { - mipi_dsi_dcs_nop(boe->dsi); + ret = mipi_dsi_dcs_nop(boe->dsi); + if (ret < 0) { + dev_err(&boe->dsi->dev, "Failed to send NOP: %d\n", ret); + goto poweroff; + } usleep_range(1000, 2000); } gpiod_set_value(boe->enable_gpio, 1); @@ -1517,24 +1460,20 @@ static int boe_panel_prepare(struct drm_panel *panel) gpiod_set_value(boe->enable_gpio, 1); usleep_range(6000, 10000); - ret = boe_panel_init_dcs_cmd(boe); - if (ret < 0) { - dev_err(panel->dev, "failed to init panel: %d\n", ret); + ret = boe->desc->init(boe); + if (ret < 0) goto poweroff; - } - - boe->prepared = true; return 0; poweroff: + gpiod_set_value(boe->enable_gpio, 0); regulator_disable(boe->avee); poweroffavdd: regulator_disable(boe->avdd); poweroff1v8: usleep_range(5000, 7000); regulator_disable(boe->pp1800); - gpiod_set_value(boe->enable_gpio, 0); return ret; } @@ -1571,7 +1510,7 @@ static const struct panel_desc boe_tv110c9m_desc = { | MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_VIDEO_BURST, - .init_cmds = boe_tv110c9m_init_cmd, + .init = boe_tv110c9m_init, }; static const struct drm_display_mode inx_hj110iz_default_mode = { @@ -1600,7 +1539,7 @@ static const struct panel_desc inx_hj110iz_desc = { | MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_VIDEO_BURST, - .init_cmds = inx_hj110iz_init_cmd, + .init = inx_hj110iz_init, }; static const struct drm_display_mode boe_tv101wum_nl6_default_mode = { @@ -1626,7 +1565,7 @@ static const struct panel_desc boe_tv101wum_nl6_desc = { .format = MIPI_DSI_FMT_RGB888, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_LPM, - .init_cmds = boe_init_cmd, + .init = boe_init, .discharge_on_disable = false, }; @@ -1653,7 +1592,7 @@ static const struct panel_desc auo_kd101n80_45na_desc = { .format = MIPI_DSI_FMT_RGB888, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_LPM, - .init_cmds = auo_kd101n80_45na_init_cmd, + .init = auo_kd101n80_45na_init, .discharge_on_disable = true, }; @@ -1681,7 +1620,7 @@ static const struct panel_desc boe_tv101wum_n53_desc = { .format = MIPI_DSI_FMT_RGB888, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_LPM, - .init_cmds = boe_init_cmd, + .init = boe_init, }; static const struct drm_display_mode auo_b101uan08_3_default_mode = { @@ -1708,7 +1647,7 @@ static const struct panel_desc auo_b101uan08_3_desc = { .format = MIPI_DSI_FMT_RGB888, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_LPM, - .init_cmds = auo_b101uan08_3_init_cmd, + .init = auo_b101uan08_3_init, .lp11_before_reset = true, }; @@ -1736,7 +1675,7 @@ static const struct panel_desc boe_tv105wum_nw0_desc = { .format = MIPI_DSI_FMT_RGB888, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_LPM, - .init_cmds = boe_init_cmd, + .init = boe_init, .lp11_before_reset = true, }; @@ -1763,35 +1702,7 @@ static const struct panel_desc starry_qfh032011_53g_desc = { .format = MIPI_DSI_FMT_RGB888, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_LPM, - .init_cmds = starry_qfh032011_53g_init_cmd, - .lp11_before_reset = true, -}; - -static const struct drm_display_mode starry_himax83102_j02_default_mode = { - .clock = 162680, - .hdisplay = 1200, - .hsync_start = 1200 + 60, - .hsync_end = 1200 + 60 + 20, - .htotal = 1200 + 60 + 20 + 40, - .vdisplay = 1920, - .vsync_start = 1920 + 116, - .vsync_end = 1920 + 116 + 8, - .vtotal = 1920 + 116 + 8 + 12, - .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, -}; - -static const struct panel_desc starry_himax83102_j02_desc = { - .modes = &starry_himax83102_j02_default_mode, - .bpc = 8, - .size = { - .width_mm = 141, - .height_mm = 226, - }, - .lanes = 4, - .format = MIPI_DSI_FMT_RGB888, - .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | - MIPI_DSI_MODE_LPM, - .init_cmds = starry_himax83102_j02_init_cmd, + .init = starry_qfh032011_53g_init, .lp11_before_reset = true, }; @@ -1922,21 +1833,11 @@ static int boe_panel_probe(struct mipi_dsi_device *dsi) return ret; } -static void boe_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct boe_panel *boe = mipi_dsi_get_drvdata(dsi); - - drm_panel_disable(&boe->base); - drm_panel_unprepare(&boe->base); -} - static void boe_panel_remove(struct mipi_dsi_device *dsi) { struct boe_panel *boe = mipi_dsi_get_drvdata(dsi); int ret; - boe_panel_shutdown(dsi); - ret = mipi_dsi_detach(dsi); if (ret < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); @@ -1970,9 +1871,6 @@ static const struct of_device_id boe_of_match[] = { { .compatible = "starry,2081101qfh032011-53g", .data = &starry_qfh032011_53g_desc }, - { .compatible = "starry,himax83102-j02", - .data = &starry_himax83102_j02_desc - }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, boe_of_match); @@ -1984,7 +1882,6 @@ static struct mipi_dsi_driver boe_panel_driver = { }, .probe = boe_panel_probe, .remove = boe_panel_remove, - .shutdown = boe_panel_shutdown, }; module_mipi_dsi_driver(boe_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 6db277efcbb7..3a574a9b46e7 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -222,11 +222,8 @@ struct edp_panel_entry { struct panel_edp { struct drm_panel base; - bool enabled; bool no_hpd; - bool prepared; - ktime_t prepared_time; ktime_t powered_on_time; ktime_t unprepared_time; @@ -395,14 +392,9 @@ static int panel_edp_disable(struct drm_panel *panel) { struct panel_edp *p = to_panel_edp(panel); - if (!p->enabled) - return 0; - if (p->desc->delay.disable) msleep(p->desc->delay.disable); - p->enabled = false; - return 0; } @@ -420,17 +412,11 @@ static int panel_edp_suspend(struct device *dev) static int panel_edp_unprepare(struct drm_panel *panel) { - struct panel_edp *p = to_panel_edp(panel); int ret; - /* Unpreparing when already unprepared is a no-op */ - if (!p->prepared) - return 0; - ret = pm_runtime_put_sync_suspend(panel->dev); if (ret < 0) return ret; - p->prepared = false; return 0; } @@ -542,21 +528,14 @@ static int panel_edp_resume(struct device *dev) static int panel_edp_prepare(struct drm_panel *panel) { - struct panel_edp *p = to_panel_edp(panel); int ret; - /* Preparing when already prepared is a no-op */ - if (p->prepared) - return 0; - ret = pm_runtime_get_sync(panel->dev); if (ret < 0) { pm_runtime_put_autosuspend(panel->dev); return ret; } - p->prepared = true; - return 0; } @@ -565,9 +544,6 @@ static int panel_edp_enable(struct drm_panel *panel) struct panel_edp *p = to_panel_edp(panel); unsigned int delay; - if (p->enabled) - return 0; - delay = p->desc->delay.enable; /* @@ -598,8 +574,6 @@ static int panel_edp_enable(struct drm_panel *panel) panel_edp_wait(p->powered_on_time, p->desc->delay.powered_on_to_enable); - p->enabled = true; - return 0; } @@ -869,7 +843,6 @@ static int panel_edp_probe(struct device *dev, const struct panel_desc *desc, if (!panel) return -ENOMEM; - panel->enabled = false; panel->prepared_time = 0; panel->desc = desc; panel->aux = aux; @@ -971,13 +944,34 @@ err_finished_ddc_init: return err; } -static void panel_edp_remove(struct device *dev) +static void panel_edp_shutdown(struct device *dev) { struct panel_edp *panel = dev_get_drvdata(dev); - drm_panel_remove(&panel->base); + /* + * NOTE: the following two calls don't really belong here. It is the + * responsibility of a correctly written DRM modeset driver to call + * drm_atomic_helper_shutdown() at shutdown time and that should + * cause the panel to be disabled / unprepared if needed. For now, + * however, we'll keep these calls due to the sheer number of + * different DRM modeset drivers used with panel-edp. The fact that + * we're calling these and _also_ the drm_atomic_helper_shutdown() + * will try to disable/unprepare means that we can get a warning about + * trying to disable/unprepare an already disabled/unprepared panel, + * but that's something we'll have to live with until we've confirmed + * that all DRM modeset drivers are properly calling + * drm_atomic_helper_shutdown(). + */ drm_panel_disable(&panel->base); drm_panel_unprepare(&panel->base); +} + +static void panel_edp_remove(struct device *dev) +{ + struct panel_edp *panel = dev_get_drvdata(dev); + + drm_panel_remove(&panel->base); + panel_edp_shutdown(dev); pm_runtime_dont_use_autosuspend(dev); pm_runtime_disable(dev); @@ -988,14 +982,6 @@ static void panel_edp_remove(struct device *dev) panel->drm_edid = NULL; } -static void panel_edp_shutdown(struct device *dev) -{ - struct panel_edp *panel = dev_get_drvdata(dev); - - drm_panel_disable(&panel->base); - drm_panel_unprepare(&panel->base); -} - static const struct display_timing auo_b101ean01_timing = { .pixelclock = { 65300000, 72500000, 75000000 }, .hactive = { 1280, 1280, 1280 }, @@ -1059,33 +1045,6 @@ static const struct panel_desc auo_b116xak01 = { }, }; -static const struct drm_display_mode auo_b133han05_mode = { - .clock = 142600, - .hdisplay = 1920, - .hsync_start = 1920 + 58, - .hsync_end = 1920 + 58 + 42, - .htotal = 1920 + 58 + 42 + 60, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 5, - .vtotal = 1080 + 3 + 5 + 54, -}; - -static const struct panel_desc auo_b133han05 = { - .modes = &auo_b133han05_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 293, - .height = 165, - }, - .delay = { - .hpd_reliable = 100, - .enable = 20, - .unprepare = 50, - }, -}; - static const struct drm_display_mode auo_b133htn01_mode = { .clock = 150660, .hdisplay = 1920, @@ -1135,33 +1094,6 @@ static const struct panel_desc auo_b133xtn01 = { }, }; -static const struct drm_display_mode auo_b140han06_mode = { - .clock = 141000, - .hdisplay = 1920, - .hsync_start = 1920 + 16, - .hsync_end = 1920 + 16 + 16, - .htotal = 1920 + 16 + 16 + 152, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 14, - .vtotal = 1080 + 3 + 14 + 19, -}; - -static const struct panel_desc auo_b140han06 = { - .modes = &auo_b140han06_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 309, - .height = 174, - }, - .delay = { - .hpd_reliable = 100, - .enable = 20, - .unprepare = 50, - }, -}; - static const struct drm_display_mode boe_nv101wxmn51_modes[] = { { .clock = 71900, @@ -1428,33 +1360,6 @@ static const struct panel_desc innolux_p120zdg_bf1 = { }, }; -static const struct drm_display_mode ivo_m133nwf4_r0_mode = { - .clock = 138778, - .hdisplay = 1920, - .hsync_start = 1920 + 24, - .hsync_end = 1920 + 24 + 48, - .htotal = 1920 + 24 + 48 + 88, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 12, - .vtotal = 1080 + 3 + 12 + 17, - .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, -}; - -static const struct panel_desc ivo_m133nwf4_r0 = { - .modes = &ivo_m133nwf4_r0_mode, - .num_modes = 1, - .bpc = 8, - .size = { - .width = 294, - .height = 165, - }, - .delay = { - .hpd_absent = 200, - .unprepare = 500, - }, -}; - static const struct drm_display_mode kingdisplay_kd116n21_30nv_a010_mode = { .clock = 81000, .hdisplay = 1366, @@ -1703,98 +1608,40 @@ static const struct panel_desc sharp_lq123p1jx31 = { }, }; -static const struct drm_display_mode sharp_lq140m1jw46_mode[] = { - { - .clock = 346500, - .hdisplay = 1920, - .hsync_start = 1920 + 48, - .hsync_end = 1920 + 48 + 32, - .htotal = 1920 + 48 + 32 + 80, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 5, - .vtotal = 1080 + 3 + 5 + 69, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, - }, { - .clock = 144370, - .hdisplay = 1920, - .hsync_start = 1920 + 48, - .hsync_end = 1920 + 48 + 32, - .htotal = 1920 + 48 + 32 + 80, - .vdisplay = 1080, - .vsync_start = 1080 + 3, - .vsync_end = 1080 + 3 + 5, - .vtotal = 1080 + 3 + 5 + 69, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, - }, -}; - -static const struct panel_desc sharp_lq140m1jw46 = { - .modes = sharp_lq140m1jw46_mode, - .num_modes = ARRAY_SIZE(sharp_lq140m1jw46_mode), - .bpc = 8, - .size = { - .width = 309, - .height = 174, - }, - .delay = { - .hpd_absent = 80, - .enable = 50, - .unprepare = 500, - }, -}; - -static const struct drm_display_mode starry_kr122ea0sra_mode = { - .clock = 147000, - .hdisplay = 1920, - .hsync_start = 1920 + 16, - .hsync_end = 1920 + 16 + 16, - .htotal = 1920 + 16 + 16 + 32, - .vdisplay = 1200, - .vsync_start = 1200 + 15, - .vsync_end = 1200 + 15 + 2, - .vtotal = 1200 + 15 + 2 + 18, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, -}; - -static const struct panel_desc starry_kr122ea0sra = { - .modes = &starry_kr122ea0sra_mode, - .num_modes = 1, - .size = { - .width = 263, - .height = 164, - }, - .delay = { - /* TODO: should be hpd-absent and no-hpd should be set? */ - .hpd_reliable = 10 + 200, - .enable = 50, - .unprepare = 10 + 500, - }, -}; - static const struct of_device_id platform_of_match[] = { { /* Must be first */ .compatible = "edp-panel", - }, { + }, + /* + * Do not add panels to the list below unless they cannot be handled by + * the generic edp-panel compatible. + * + * The only two valid reasons are: + * - Because of the panel issues (e.g. broken EDID or broken + * identification). + * - Because the eDP drivers didn't wire up the AUX bus properly. + * NOTE that, though this is a marginally valid reason, + * some justification needs to be made for why the platform can't + * wire up the AUX bus properly. + * + * In all other cases the platform should use the aux-bus and declare + * the panel using the 'edp-panel' compatible as a device on the AUX + * bus. + */ + { .compatible = "auo,b101ean01", .data = &auo_b101ean01, }, { .compatible = "auo,b116xa01", .data = &auo_b116xak01, }, { - .compatible = "auo,b133han05", - .data = &auo_b133han05, - }, { .compatible = "auo,b133htn01", .data = &auo_b133htn01, }, { .compatible = "auo,b133xtn01", .data = &auo_b133xtn01, }, { - .compatible = "auo,b140han06", - .data = &auo_b140han06, - }, { .compatible = "boe,nv101wxmn51", .data = &boe_nv101wxmn51, }, { @@ -1822,9 +1669,6 @@ static const struct of_device_id platform_of_match[] = { .compatible = "innolux,p120zdg-bf1", .data = &innolux_p120zdg_bf1, }, { - .compatible = "ivo,m133nwf4-r0", - .data = &ivo_m133nwf4_r0, - }, { .compatible = "kingdisplay,kd116n21-30nv-a010", .data = &kingdisplay_kd116n21_30nv_a010, }, { @@ -1855,12 +1699,6 @@ static const struct of_device_id platform_of_match[] = { .compatible = "sharp,lq123p1jx31", .data = &sharp_lq123p1jx31, }, { - .compatible = "sharp,lq140m1jw46", - .data = &sharp_lq140m1jw46, - }, { - .compatible = "starry,kr122ea0sra", - .data = &starry_kr122ea0sra, - }, { /* sentinel */ } }; @@ -1911,6 +1749,12 @@ static const struct panel_delay delay_200_500_e80_d50 = { .disable = 50, }; +static const struct panel_delay delay_80_500_e50 = { + .hpd_absent = 80, + .unprepare = 500, + .enable = 50, +}; + static const struct panel_delay delay_100_500_e200 = { .hpd_absent = 100, .unprepare = 500, @@ -1983,8 +1827,10 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('A', 'U', 'O', 0x1062, &delay_200_500_e50, "B120XAN01.0"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x125c, &delay_200_500_e50, "Unknown"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x145c, &delay_200_500_e50, "B116XAB01.4"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x1999, &delay_200_500_e50, "Unknown"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x1e9b, &delay_200_500_e50, "B133UAN02.1"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x1ea5, &delay_200_500_e50, "B116XAK01.6"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x203d, &delay_200_500_e50, "B140HTN02.0"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x208d, &delay_200_500_e50, "B140HTN02.1"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x235c, &delay_200_500_e50, "B116XTN02.3"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x239b, &delay_200_500_e50, "B116XAN06.1"), @@ -2005,6 +1851,8 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('B', 'O', 'E', 0x0607, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0608, &delay_200_500_e50, "NT116WHM-N11"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x0609, &delay_200_500_e50_po2e200, "NT116WHM-N21 V4.1"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x0623, &delay_200_500_e200, "NT116WHM-N21 V4.0"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0668, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x068f, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x06e5, &delay_200_500_e200, "Unknown"), @@ -2020,6 +1868,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('B', 'O', 'E', 0x0771, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0786, &delay_200_500_p2e80, "NV116WHM-T01"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0797, &delay_200_500_e200, "Unknown"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x07a8, &delay_200_500_e50_po2e200, "NT116WHM-N21"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d1, &boe_nv133fhm_n61.delay, "NV133FHM-N61"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d3, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x07f6, &delay_200_500_e200, "NT140FHM-N44"), @@ -2067,6 +1916,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('C', 'M', 'N', 0x1157, &delay_200_500_e80_d50, "N116BGE-EA2"), EDP_PANEL_ENTRY('C', 'M', 'N', 0x115b, &delay_200_500_e80_d50, "N116BCN-EB1"), EDP_PANEL_ENTRY('C', 'M', 'N', 0x115e, &delay_200_500_e80_d50, "N116BCA-EA1"), + EDP_PANEL_ENTRY('C', 'M', 'N', 0x1160, &delay_200_500_e80_d50, "N116BCJ-EAK"), EDP_PANEL_ENTRY('C', 'M', 'N', 0x1247, &delay_200_500_e80_d50, "N120ACA-EA1"), EDP_PANEL_ENTRY('C', 'M', 'N', 0x142b, &delay_200_500_e80_d50, "N140HCA-EAC"), EDP_PANEL_ENTRY('C', 'M', 'N', 0x142e, &delay_200_500_e80_d50, "N140BGA-EA4"), @@ -2094,6 +1944,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"), EDP_PANEL_ENTRY('K', 'D', 'B', 0x1118, &delay_200_500_e50, "KD116N29-30NK-A005"), EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"), + EDP_PANEL_ENTRY('K', 'D', 'B', 0x1212, &delay_200_500_e50, "KD116N0930A16"), EDP_PANEL_ENTRY('K', 'D', 'C', 0x044f, &delay_200_500_e50, "KD116N9-30NH-F3"), EDP_PANEL_ENTRY('K', 'D', 'C', 0x05f1, &delay_200_500_e80_d50, "KD116N5-30NV-G7"), @@ -2112,7 +1963,8 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('S', 'D', 'C', 0x416d, &delay_100_500_e200, "ATNA45AF01"), EDP_PANEL_ENTRY('S', 'H', 'P', 0x1511, &delay_200_500_e50, "LQ140M1JW48"), - EDP_PANEL_ENTRY('S', 'H', 'P', 0x1523, &sharp_lq140m1jw46.delay, "LQ140M1JW46"), + EDP_PANEL_ENTRY('S', 'H', 'P', 0x1523, &delay_80_500_e50, "LQ140M1JW46"), + EDP_PANEL_ENTRY('S', 'H', 'P', 0x153a, &delay_200_500_e50, "LQ140T1JH01"), EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"), EDP_PANEL_ENTRY('S', 'T', 'A', 0x0100, &delay_100_500_e200, "2081116HHD028001-51D"), diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c new file mode 100644 index 000000000000..6e4b7e4644ce --- /dev/null +++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c @@ -0,0 +1,706 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for panels based on Himax HX83102 controller, such as: + * + * - Starry 10.51" WUXGA MIPI-DSI panel + * + * Based on drivers/gpu/drm/panel/panel-himax-hx8394.c + */ + +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regulator/consumer.h> + +#include <drm/drm_connector.h> +#include <drm/drm_crtc.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> + +#include <video/mipi_display.h> + +/* Manufacturer specific DSI commands */ +#define HX83102_SETPOWER 0xb1 +#define HX83102_SETDISP 0xb2 +#define HX83102_SETCYC 0xb4 +#define HX83102_SETEXTC 0xb9 +#define HX83102_SETMIPI 0xba +#define HX83102_SETVDC 0xbc +#define HX83102_SETBANK 0xbd +#define HX83102_UNKNOWN_BE 0xbe +#define HX83102_SETPTBA 0xbf +#define HX83102_SETSTBA 0xc0 +#define HX83102_SETTCON 0xc7 +#define HX83102_SETRAMDMY 0xc8 +#define HX83102_SETPWM 0xc9 +#define HX83102_SETCLOCK 0xcb +#define HX83102_SETPANEL 0xcc +#define HX83102_SETCASCADE 0xd0 +#define HX83102_SETPCTRL 0xd1 +#define HX83102_UNKNOWN_D2 0xd2 +#define HX83102_SETGIP0 0xd3 +#define HX83102_SETGIP1 0xd5 +#define HX83102_SETGIP2 0xd6 +#define HX83102_SETGIP3 0xd8 +#define HX83102_SETGMA 0xe0 +#define HX83102_UNKNOWN_E1 0xe1 +#define HX83102_SETTP1 0xe7 +#define HX83102_SETSPCCMD 0xe9 + +struct hx83102 { + struct drm_panel base; + struct mipi_dsi_device *dsi; + + const struct hx83102_panel_desc *desc; + + enum drm_panel_orientation orientation; + struct regulator *pp1800; + struct regulator *avee; + struct regulator *avdd; + struct gpio_desc *enable_gpio; +}; + +struct hx83102_panel_desc { + const struct drm_display_mode *modes; + + /** + * @width_mm: width of the panel's active display area + * @height_mm: height of the panel's active display area + */ + struct { + unsigned int width_mm; + unsigned int height_mm; + } size; + + int (*init)(struct hx83102 *ctx); +}; + +static inline struct hx83102 *panel_to_hx83102(struct drm_panel *panel) +{ + return container_of(panel, struct hx83102, base); +} + +static void hx83102_enable_extended_cmds(struct mipi_dsi_multi_context *dsi_ctx, bool enable) +{ + if (enable) + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX83102_SETEXTC, 0x83, 0x10, 0x21, 0x55, 0x00); + else + mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX83102_SETEXTC, 0x00, 0x00, 0x00); +} + +static int starry_himax83102_j02_init(struct hx83102 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + hx83102_enable_extended_cmds(&dsi_ctx, true); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb5, 0xb5, 0x31, 0xf1, + 0x31, 0xd7, 0x2f, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11, + 0x65, 0x00, 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x74, + 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, + 0x12, 0x72, 0x3c, 0xa3, 0x03, 0x03, 0x00, 0x00, 0x88, 0xf5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x76, 0x76, 0x76, 0x76, 0x76, + 0x76, 0x63, 0x5c, 0x63, 0x5c, 0x01, 0x9e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x36, 0x36, 0x22, 0x11, 0x22, + 0xa0, 0x61, 0x08, 0xf5, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0c, + 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x1f, 0x11, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x08, 0x37, 0x47, 0x34, 0x3b, 0x12, 0x12, 0x03, 0x03, + 0x32, 0x10, 0x10, 0x00, 0x10, 0x32, 0x10, 0x08, 0x00, 0x08, 0x32, + 0x17, 0x94, 0x07, 0x94, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x40, 0x40, 0x1a, 0x1a, 0x1b, + 0x1b, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, + 0x28, 0x29, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP2, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x40, 0x40, 0x19, 0x19, 0x1a, 0x1a, 0x1b, + 0x1b, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x29, 0x28, + 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, + 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, + 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, + 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x09, 0x14, 0x1e, 0x26, 0x48, + 0x61, 0x67, 0x6c, 0x67, 0x7d, 0x7f, 0x80, 0x8b, 0x87, 0x8f, 0x98, + 0xab, 0xab, 0x55, 0x5c, 0x68, 0x73, 0x00, 0x09, 0x14, 0x1e, 0x26, + 0x48, 0x61, 0x67, 0x6c, 0x67, 0x7d, 0x7f, 0x80, 0x8b, 0x87, 0x8f, + 0x98, 0xab, 0xab, 0x55, 0x5c, 0x68, 0x73); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x0e, 0x10, 0x10, 0x21, 0x2b, 0x9a, + 0x02, 0x54, 0x9a, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x05, + 0x02, 0x02, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0xbf, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x3c, 0xfa); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x0c, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x28, 0x01, 0x7e, 0x0f, + 0x7e, 0x10, 0xa0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xbf, 0xfe, 0xaa, 0xa0, + 0xff, 0xff, 0xbf, 0xfe, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x04, 0xfe, 0x04, 0xfe, 0x04, + 0x03, 0x03, 0x03, 0x26, 0x00, 0x26, 0x81, 0x02, 0x40, 0x00, 0x20, + 0x9e, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00, + 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, + 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x2a, 0xaa, 0xa8, + 0x00, 0x00, 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + + return dsi_ctx.accum_err; +}; + +static int boe_nv110wum_init(struct hx83102 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + msleep(60); + + hx83102_enable_extended_cmds(&dsi_ctx, true); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xaf, 0xaf, 0x2b, 0xeb, 0x42, + 0xe1, 0x4d, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11, 0x65, 0x00, + 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x9a, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x12, + 0x71, 0x3c, 0xa3, 0x11, 0x00, 0x00, 0x00, 0x88, 0xf5, 0x22, 0x8f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x49, 0x49, 0x32, 0x32, 0x14, 0x32, + 0x84, 0x6e, 0x84, 0x6e, 0x01, 0x9c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0x84); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x36, 0x36, 0x22, 0x00, 0x00, 0xa0, + 0x61, 0x08, 0xf5, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x30, 0xd4, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x34); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0c, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x1f, 0x11, 0x1f, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x08, 0x04, 0x08, 0x37, 0x37, 0x64, 0x4b, 0x11, 0x11, 0x03, 0x03, 0x32, + 0x10, 0x0e, 0x00, 0x0e, 0x32, 0x10, 0x0a, 0x00, 0x0a, 0x32, 0x17, 0x98, + 0x07, 0x98, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x24, 0x24, 0x24, 0x24, 0x07, 0x06, + 0x07, 0x06, 0x05, 0x04, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00, + 0x01, 0x00, 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, + 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x05, 0x0d, 0x14, 0x1b, 0x2c, + 0x44, 0x49, 0x51, 0x4c, 0x67, 0x6c, 0x71, 0x80, 0x7d, 0x84, 0x8d, 0xa0, + 0xa0, 0x4f, 0x58, 0x64, 0x73, 0x00, 0x05, 0x0d, 0x14, 0x1b, 0x2c, 0x44, + 0x49, 0x51, 0x4c, 0x67, 0x6c, 0x71, 0x80, 0x7d, 0x84, 0x8d, 0xa0, 0xa0, + 0x4f, 0x58, 0x64, 0x73); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x1a, 0x26, 0x9e, + 0x00, 0x53, 0x9b, 0x14, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x11, 0x00, 0x00, 0x89, 0x30, 0x80, + 0x07, 0x80, 0x02, 0x58, 0x00, 0x14, 0x02, 0x58, 0x02, 0x58, 0x02, 0x00, + 0x02, 0x2c, 0x00, 0x20, 0x02, 0x02, 0x00, 0x08, 0x00, 0x0c, 0x05, 0x0e, + 0x04, 0x94, 0x18, 0x00, 0x10, 0xf0, 0x03, 0x0c, 0x20, 0x00, 0x06, 0x0b, + 0x0b, 0x33, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0, + 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0xbf, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x96); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x84); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0xf6, 0x2b, 0x34, 0x2b, 0x74, 0x3b, + 0x74, 0x6b, 0x74); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2b, 0x01, 0x7e, 0x0f, + 0x7e, 0x10, 0xa0, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x02, 0x00, 0xbb, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xaf, 0xff, 0xff, 0xfa, 0xa0, + 0xff, 0xaf, 0xff, 0xff, 0xfa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, 0x20, 0x65, + 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00, + 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00, 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00, + 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + hx83102_enable_extended_cmds(&dsi_ctx, false); + + mipi_dsi_msleep(&dsi_ctx, 50); + + return dsi_ctx.accum_err; +}; + +static int ivo_t109nw41_init(struct hx83102 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + msleep(60); + + hx83102_enable_extended_cmds(&dsi_ctx, true); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xed, 0xed, 0x0f, 0xcf, 0x42, + 0xf5, 0x39, 0x36, 0x36, 0x36, 0x36, 0x32, 0x8b, 0x11, 0x65, 0x00, 0x88, + 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0xd6, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x12, + 0x71, 0x3c, 0xa3, 0x22, 0x20, 0x00, 0x00, 0x88, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x35, 0x35, 0x43, 0x43, 0x35, 0x35, + 0x30, 0x7a, 0x30, 0x7a, 0x01, 0x9d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x34, 0x34, 0x22, 0x11, 0x22, 0xa0, + 0x31, 0x08, 0xf5, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x22); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x34); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x07, 0x06, 0x00, 0x02, 0x04, 0x2c, + 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x08, 0x08, 0x08, 0x37, 0x07, 0x64, 0x7c, 0x11, 0x11, 0x03, 0x03, 0x32, + 0x10, 0x0e, 0x00, 0x0e, 0x32, 0x17, 0x97, 0x07, 0x97, 0x32, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x25, 0x24, 0x25, 0x24, 0x18, 0x18, + 0x18, 0x18, 0x07, 0x06, 0x07, 0x06, 0x05, 0x04, 0x05, 0x04, 0x03, 0x02, + 0x03, 0x02, 0x01, 0x00, 0x01, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, + 0x1f, 0x1f, 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x04, 0x04, 0x06, 0x0a, 0x0a, 0x05, + 0x12, 0x14, 0x17, 0x13, 0x2c, 0x33, 0x39, 0x4b, 0x4c, 0x56, 0x61, 0x78, + 0x7a, 0x41, 0x50, 0x68, 0x73, 0x04, 0x04, 0x06, 0x0a, 0x0a, 0x05, 0x12, + 0x14, 0x17, 0x13, 0x2c, 0x33, 0x39, 0x4b, 0x4c, 0x56, 0x61, 0x78, 0x7a, + 0x41, 0x50, 0x68, 0x73); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x1a, 0x26, 0x9e, + 0x00, 0x4f, 0xa0, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0a, 0x02, + 0x02, 0x00, 0x33, 0x02, 0x04, 0x18, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x04, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2b, 0x01, 0x7e, 0x0f, + 0x7e, 0x10, 0xa0, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xf2); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x03, 0x07, 0x00, 0x10, 0x79); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0, + 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, 0x20, 0x6e, + 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0, + 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00); + hx83102_enable_extended_cmds(&dsi_ctx, false); + + mipi_dsi_msleep(&dsi_ctx, 60); + + return dsi_ctx.accum_err; +}; + +static const struct drm_display_mode starry_mode = { + .clock = 162680, + .hdisplay = 1200, + .hsync_start = 1200 + 60, + .hsync_end = 1200 + 60 + 20, + .htotal = 1200 + 60 + 20 + 40, + .vdisplay = 1920, + .vsync_start = 1920 + 116, + .vsync_end = 1920 + 116 + 8, + .vtotal = 1920 + 116 + 8 + 12, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct hx83102_panel_desc starry_desc = { + .modes = &starry_mode, + .size = { + .width_mm = 141, + .height_mm = 226, + }, + .init = starry_himax83102_j02_init, +}; + +static const struct drm_display_mode boe_tv110wum_default_mode = { + .clock = 167700, + .hdisplay = 1200, + .hsync_start = 1200 + 75, + .hsync_end = 1200 + 75 + 20, + .htotal = 1200 + 75 + 20 + 65, + .vdisplay = 1920, + .vsync_start = 1920 + 115, + .vsync_end = 1920 + 115 + 8, + .vtotal = 1920 + 115 + 8 + 12, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct hx83102_panel_desc boe_nv110wum_desc = { + .modes = &boe_tv110wum_default_mode, + .size = { + .width_mm = 147, + .height_mm = 235, + }, + .init = boe_nv110wum_init, +}; + +static const struct drm_display_mode ivo_t109nw41_default_mode = { + .clock = 167700, + .hdisplay = 1200, + .hsync_start = 1200 + 75, + .hsync_end = 1200 + 75 + 20, + .htotal = 1200 + 75 + 20 + 65, + .vdisplay = 1920, + .vsync_start = 1920 + 115, + .vsync_end = 1920 + 115 + 8, + .vtotal = 1920 + 115 + 8 + 12, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct hx83102_panel_desc ivo_t109nw41_desc = { + .modes = &ivo_t109nw41_default_mode, + .size = { + .width_mm = 147, + .height_mm = 235, + }, + .init = ivo_t109nw41_init, +}; + +static int hx83102_enable(struct drm_panel *panel) +{ + msleep(130); + return 0; +} + +static int hx83102_disable(struct drm_panel *panel) +{ + struct hx83102 *ctx = panel_to_hx83102(panel); + struct mipi_dsi_device *dsi = ctx->dsi; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + + mipi_dsi_msleep(&dsi_ctx, 150); + + return dsi_ctx.accum_err; +} + +static int hx83102_unprepare(struct drm_panel *panel) +{ + struct hx83102 *ctx = panel_to_hx83102(panel); + + gpiod_set_value(ctx->enable_gpio, 0); + usleep_range(1000, 2000); + regulator_disable(ctx->avee); + regulator_disable(ctx->avdd); + usleep_range(5000, 7000); + regulator_disable(ctx->pp1800); + + return 0; +} + +static int hx83102_prepare(struct drm_panel *panel) +{ + struct hx83102 *ctx = panel_to_hx83102(panel); + struct mipi_dsi_device *dsi = ctx->dsi; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + + gpiod_set_value(ctx->enable_gpio, 0); + usleep_range(1000, 1500); + + dsi_ctx.accum_err = regulator_enable(ctx->pp1800); + if (dsi_ctx.accum_err) + return dsi_ctx.accum_err; + + usleep_range(3000, 5000); + + dsi_ctx.accum_err = regulator_enable(ctx->avdd); + if (dsi_ctx.accum_err) + goto poweroff1v8; + dsi_ctx.accum_err = regulator_enable(ctx->avee); + if (dsi_ctx.accum_err) + goto poweroffavdd; + + usleep_range(10000, 11000); + + mipi_dsi_dcs_nop_multi(&dsi_ctx); + if (dsi_ctx.accum_err) + goto poweroff; + + usleep_range(1000, 2000); + + gpiod_set_value(ctx->enable_gpio, 1); + usleep_range(1000, 2000); + gpiod_set_value(ctx->enable_gpio, 0); + usleep_range(1000, 2000); + gpiod_set_value(ctx->enable_gpio, 1); + usleep_range(6000, 10000); + + dsi_ctx.accum_err = ctx->desc->init(ctx); + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + if (dsi_ctx.accum_err) + goto poweroff; + + return 0; + +poweroff: + gpiod_set_value(ctx->enable_gpio, 0); + regulator_disable(ctx->avee); +poweroffavdd: + regulator_disable(ctx->avdd); +poweroff1v8: + usleep_range(5000, 7000); + regulator_disable(ctx->pp1800); + + return dsi_ctx.accum_err; +} + +static int hx83102_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + struct hx83102 *ctx = panel_to_hx83102(panel); + const struct drm_display_mode *m = ctx->desc->modes; + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->dev, m); + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_set_name(mode); + drm_mode_probed_add(connector, mode); + + connector->display_info.width_mm = ctx->desc->size.width_mm; + connector->display_info.height_mm = ctx->desc->size.height_mm; + connector->display_info.bpc = 8; + + return 1; +} + +static enum drm_panel_orientation hx83102_get_orientation(struct drm_panel *panel) +{ + struct hx83102 *ctx = panel_to_hx83102(panel); + + return ctx->orientation; +} + +static const struct drm_panel_funcs hx83102_drm_funcs = { + .disable = hx83102_disable, + .unprepare = hx83102_unprepare, + .prepare = hx83102_prepare, + .enable = hx83102_enable, + .get_modes = hx83102_get_modes, + .get_orientation = hx83102_get_orientation, +}; + +static int hx83102_panel_add(struct hx83102 *ctx) +{ + struct device *dev = &ctx->dsi->dev; + int err; + + ctx->avdd = devm_regulator_get(dev, "avdd"); + if (IS_ERR(ctx->avdd)) + return PTR_ERR(ctx->avdd); + + ctx->avee = devm_regulator_get(dev, "avee"); + if (IS_ERR(ctx->avee)) + return PTR_ERR(ctx->avee); + + ctx->pp1800 = devm_regulator_get(dev, "pp1800"); + if (IS_ERR(ctx->pp1800)) + return PTR_ERR(ctx->pp1800); + + ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(ctx->enable_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), "Cannot get enable GPIO\n"); + + ctx->base.prepare_prev_first = true; + + drm_panel_init(&ctx->base, dev, &hx83102_drm_funcs, + DRM_MODE_CONNECTOR_DSI); + err = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation); + if (err < 0) + return dev_err_probe(dev, err, "failed to get orientation\n"); + + err = drm_panel_of_backlight(&ctx->base); + if (err) + return err; + + ctx->base.funcs = &hx83102_drm_funcs; + ctx->base.dev = &ctx->dsi->dev; + + drm_panel_add(&ctx->base); + + return 0; +} + +static int hx83102_probe(struct mipi_dsi_device *dsi) +{ + struct hx83102 *ctx; + int ret; + const struct hx83102_panel_desc *desc; + + ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + desc = of_device_get_match_data(&dsi->dev); + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_LPM; + ctx->desc = desc; + ctx->dsi = dsi; + ret = hx83102_panel_add(ctx); + if (ret < 0) + return ret; + + mipi_dsi_set_drvdata(dsi, ctx); + + ret = mipi_dsi_attach(dsi); + if (ret) + drm_panel_remove(&ctx->base); + + return ret; +} + +static void hx83102_remove(struct mipi_dsi_device *dsi) +{ + struct hx83102 *ctx = mipi_dsi_get_drvdata(dsi); + int ret; + + ret = mipi_dsi_detach(dsi); + if (ret < 0) + dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); + + if (ctx->base.dev) + drm_panel_remove(&ctx->base); +} + +static const struct of_device_id hx83102_of_match[] = { + { .compatible = "boe,nv110wum-l60", + .data = &boe_nv110wum_desc + }, + { .compatible = "ivo,t109nw41", + .data = &ivo_t109nw41_desc + }, + { .compatible = "starry,himax83102-j02", + .data = &starry_desc + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, hx83102_of_match); + +static struct mipi_dsi_driver hx83102_driver = { + .probe = hx83102_probe, + .remove = hx83102_remove, + .driver = { + .name = "panel-himax-hx83102", + .of_match_table = hx83102_of_match, + }, +}; +module_mipi_dsi_driver(hx83102_driver); + +MODULE_AUTHOR("Cong Yang <yangcong5@huaqin.corp-partner.google.com>"); +MODULE_DESCRIPTION("DRM driver for Himax HX83102 based MIPI DSI panels"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c index ff0dc08b9829..cb9f46e853de 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx8394.c +++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c @@ -370,8 +370,7 @@ static int hx8394_enable(struct drm_panel *panel) sleep_in: /* This will probably fail, but let's try orderly power off anyway. */ - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (!ret) + if (!mipi_dsi_dcs_enter_sleep_mode(dsi)) msleep(50); return ret; diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c index b933380b7eb7..775d5d5e828c 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -32,7 +32,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> @@ -651,7 +651,7 @@ static int ili9341_dbi_probe(struct spi_device *spi, struct gpio_desc *dc, spi_set_drvdata(spi, drm); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } @@ -723,7 +723,8 @@ static int ili9341_probe(struct spi_device *spi) if (!strcmp(id->name, "sf-tc240t-9370-t")) return ili9341_dpi_probe(spi, dc, reset); - else if (!strcmp(id->name, "yx240qv29")) + + if (!strcmp(id->name, "yx240qv29")) return ili9341_dbi_probe(spi, dc, reset); return -ENODEV; diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c index 267a5307041c..266a087fe14c 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c @@ -15,6 +15,8 @@ #include <video/mipi_display.h> +struct ili9882t; + /* * Use this descriptor struct to describe different panels using the * Ilitek ILI9882T display controller. @@ -34,7 +36,7 @@ struct panel_desc { unsigned long mode_flags; enum mipi_dsi_pixel_format format; - const struct panel_init_cmd *init_cmds; + int (*init)(struct ili9882t *boe); unsigned int lanes; }; @@ -52,371 +54,363 @@ struct ili9882t { struct gpio_desc *enable_gpio; }; -enum dsi_cmd_type { - INIT_DCS_CMD, - DELAY_CMD, -}; - -struct panel_init_cmd { - enum dsi_cmd_type type; - size_t len; - const char *data; -}; - -#define _INIT_DCS_CMD(...) { \ - .type = INIT_DCS_CMD, \ - .len = sizeof((char[]){__VA_ARGS__}), \ - .data = (char[]){__VA_ARGS__} } - -#define _INIT_DELAY_CMD(...) { \ - .type = DELAY_CMD,\ - .len = sizeof((char[]){__VA_ARGS__}), \ - .data = (char[]){__VA_ARGS__} } - /* ILI9882-specific commands, add new commands as you decode them */ #define ILI9882T_DCS_SWITCH_PAGE 0xFF -#define _INIT_SWITCH_PAGE_CMD(page) \ - _INIT_DCS_CMD(ILI9882T_DCS_SWITCH_PAGE, 0x98, 0x82, (page)) - -static const struct panel_init_cmd starry_ili9882t_init_cmd[] = { - _INIT_DELAY_CMD(5), - _INIT_SWITCH_PAGE_CMD(0x01), - _INIT_DCS_CMD(0x00, 0x42), - _INIT_DCS_CMD(0x01, 0x11), - _INIT_DCS_CMD(0x02, 0x00), - _INIT_DCS_CMD(0x03, 0x00), - - _INIT_DCS_CMD(0x04, 0x01), - _INIT_DCS_CMD(0x05, 0x11), - _INIT_DCS_CMD(0x06, 0x00), - _INIT_DCS_CMD(0x07, 0x00), - - _INIT_DCS_CMD(0x08, 0x80), - _INIT_DCS_CMD(0x09, 0x81), - _INIT_DCS_CMD(0x0A, 0x71), - _INIT_DCS_CMD(0x0B, 0x00), - - _INIT_DCS_CMD(0x0C, 0x00), - _INIT_DCS_CMD(0x0E, 0x1A), - - _INIT_DCS_CMD(0x24, 0x00), - _INIT_DCS_CMD(0x25, 0x00), - _INIT_DCS_CMD(0x26, 0x00), - _INIT_DCS_CMD(0x27, 0x00), - - _INIT_DCS_CMD(0x2C, 0xD4), - _INIT_DCS_CMD(0xB9, 0x40), - - _INIT_DCS_CMD(0xB0, 0x11), - - _INIT_DCS_CMD(0xE6, 0x32), - _INIT_DCS_CMD(0xD1, 0x30), - - _INIT_DCS_CMD(0xD6, 0x55), - - _INIT_DCS_CMD(0xD0, 0x01), - _INIT_DCS_CMD(0xE3, 0x93), - _INIT_DCS_CMD(0xE4, 0x00), - _INIT_DCS_CMD(0xE5, 0x80), - - _INIT_DCS_CMD(0x31, 0x07), - _INIT_DCS_CMD(0x32, 0x07), - _INIT_DCS_CMD(0x33, 0x07), - _INIT_DCS_CMD(0x34, 0x07), - _INIT_DCS_CMD(0x35, 0x07), - _INIT_DCS_CMD(0x36, 0x01), - _INIT_DCS_CMD(0x37, 0x00), - _INIT_DCS_CMD(0x38, 0x28), - _INIT_DCS_CMD(0x39, 0x29), - _INIT_DCS_CMD(0x3A, 0x11), - _INIT_DCS_CMD(0x3B, 0x13), - _INIT_DCS_CMD(0x3C, 0x15), - _INIT_DCS_CMD(0x3D, 0x17), - _INIT_DCS_CMD(0x3E, 0x09), - _INIT_DCS_CMD(0x3F, 0x0D), - _INIT_DCS_CMD(0x40, 0x02), - _INIT_DCS_CMD(0x41, 0x02), - _INIT_DCS_CMD(0x42, 0x02), - _INIT_DCS_CMD(0x43, 0x02), - _INIT_DCS_CMD(0x44, 0x02), - _INIT_DCS_CMD(0x45, 0x02), - _INIT_DCS_CMD(0x46, 0x02), - - _INIT_DCS_CMD(0x47, 0x07), - _INIT_DCS_CMD(0x48, 0x07), - _INIT_DCS_CMD(0x49, 0x07), - _INIT_DCS_CMD(0x4A, 0x07), - _INIT_DCS_CMD(0x4B, 0x07), - _INIT_DCS_CMD(0x4C, 0x01), - _INIT_DCS_CMD(0x4D, 0x00), - _INIT_DCS_CMD(0x4E, 0x28), - _INIT_DCS_CMD(0x4F, 0x29), - _INIT_DCS_CMD(0x50, 0x10), - _INIT_DCS_CMD(0x51, 0x12), - _INIT_DCS_CMD(0x52, 0x14), - _INIT_DCS_CMD(0x53, 0x16), - _INIT_DCS_CMD(0x54, 0x08), - _INIT_DCS_CMD(0x55, 0x0C), - _INIT_DCS_CMD(0x56, 0x02), - _INIT_DCS_CMD(0x57, 0x02), - _INIT_DCS_CMD(0x58, 0x02), - _INIT_DCS_CMD(0x59, 0x02), - _INIT_DCS_CMD(0x5A, 0x02), - _INIT_DCS_CMD(0x5B, 0x02), - _INIT_DCS_CMD(0x5C, 0x02), - - _INIT_DCS_CMD(0x61, 0x07), - _INIT_DCS_CMD(0x62, 0x07), - _INIT_DCS_CMD(0x63, 0x07), - _INIT_DCS_CMD(0x64, 0x07), - _INIT_DCS_CMD(0x65, 0x07), - _INIT_DCS_CMD(0x66, 0x01), - _INIT_DCS_CMD(0x67, 0x00), - _INIT_DCS_CMD(0x68, 0x28), - _INIT_DCS_CMD(0x69, 0x29), - _INIT_DCS_CMD(0x6A, 0x16), - _INIT_DCS_CMD(0x6B, 0x14), - _INIT_DCS_CMD(0x6C, 0x12), - _INIT_DCS_CMD(0x6D, 0x10), - _INIT_DCS_CMD(0x6E, 0x0C), - _INIT_DCS_CMD(0x6F, 0x08), - _INIT_DCS_CMD(0x70, 0x02), - _INIT_DCS_CMD(0x71, 0x02), - _INIT_DCS_CMD(0x72, 0x02), - _INIT_DCS_CMD(0x73, 0x02), - _INIT_DCS_CMD(0x74, 0x02), - _INIT_DCS_CMD(0x75, 0x02), - _INIT_DCS_CMD(0x76, 0x02), - - _INIT_DCS_CMD(0x77, 0x07), - _INIT_DCS_CMD(0x78, 0x07), - _INIT_DCS_CMD(0x79, 0x07), - _INIT_DCS_CMD(0x7A, 0x07), - _INIT_DCS_CMD(0x7B, 0x07), - _INIT_DCS_CMD(0x7C, 0x01), - _INIT_DCS_CMD(0x7D, 0x00), - _INIT_DCS_CMD(0x7E, 0x28), - _INIT_DCS_CMD(0x7F, 0x29), - _INIT_DCS_CMD(0x80, 0x17), - _INIT_DCS_CMD(0x81, 0x15), - _INIT_DCS_CMD(0x82, 0x13), - _INIT_DCS_CMD(0x83, 0x11), - _INIT_DCS_CMD(0x84, 0x0D), - _INIT_DCS_CMD(0x85, 0x09), - _INIT_DCS_CMD(0x86, 0x02), - _INIT_DCS_CMD(0x87, 0x07), - _INIT_DCS_CMD(0x88, 0x07), - _INIT_DCS_CMD(0x89, 0x07), - _INIT_DCS_CMD(0x8A, 0x07), - _INIT_DCS_CMD(0x8B, 0x07), - _INIT_DCS_CMD(0x8C, 0x07), - - _INIT_SWITCH_PAGE_CMD(0x02), - _INIT_DCS_CMD(0x29, 0x3A), - _INIT_DCS_CMD(0x2A, 0x3B), - - _INIT_DCS_CMD(0x06, 0x01), - _INIT_DCS_CMD(0x07, 0x01), - _INIT_DCS_CMD(0x08, 0x0C), - _INIT_DCS_CMD(0x09, 0x44), - - _INIT_DCS_CMD(0x3C, 0x0A), - _INIT_DCS_CMD(0x39, 0x11), - _INIT_DCS_CMD(0x3D, 0x00), - _INIT_DCS_CMD(0x3A, 0x0C), - _INIT_DCS_CMD(0x3B, 0x44), - - _INIT_DCS_CMD(0x53, 0x1F), - _INIT_DCS_CMD(0x5E, 0x40), - _INIT_DCS_CMD(0x84, 0x00), - - _INIT_SWITCH_PAGE_CMD(0x03), - _INIT_DCS_CMD(0x20, 0x01), - _INIT_DCS_CMD(0x21, 0x3C), - _INIT_DCS_CMD(0x22, 0xFA), - - _INIT_SWITCH_PAGE_CMD(0x0A), - _INIT_DCS_CMD(0xE0, 0x01), - _INIT_DCS_CMD(0xE2, 0x01), - _INIT_DCS_CMD(0xE5, 0x91), - _INIT_DCS_CMD(0xE6, 0x3C), - _INIT_DCS_CMD(0xE7, 0x00), - _INIT_DCS_CMD(0xE8, 0xFA), - - _INIT_SWITCH_PAGE_CMD(0x12), - _INIT_DCS_CMD(0x87, 0x2C), - - _INIT_SWITCH_PAGE_CMD(0x05), - _INIT_DCS_CMD(0x73, 0xE5), - _INIT_DCS_CMD(0x7F, 0x6B), - _INIT_DCS_CMD(0x6D, 0xA4), - _INIT_DCS_CMD(0x79, 0x54), - _INIT_DCS_CMD(0x69, 0x97), - _INIT_DCS_CMD(0x6A, 0x97), - _INIT_DCS_CMD(0xA5, 0x3F), - _INIT_DCS_CMD(0x61, 0xDA), - _INIT_DCS_CMD(0xA7, 0xF1), - _INIT_DCS_CMD(0x5F, 0x01), - _INIT_DCS_CMD(0x62, 0x3F), - _INIT_DCS_CMD(0x1D, 0x90), - _INIT_DCS_CMD(0x86, 0x87), - - _INIT_SWITCH_PAGE_CMD(0x06), - _INIT_DCS_CMD(0xC0, 0x80), - _INIT_DCS_CMD(0xC1, 0x07), - _INIT_DCS_CMD(0xCA, 0x58), - _INIT_DCS_CMD(0xCB, 0x02), - _INIT_DCS_CMD(0xCE, 0x58), - _INIT_DCS_CMD(0xCF, 0x02), - _INIT_DCS_CMD(0x67, 0x60), - _INIT_DCS_CMD(0x10, 0x00), - _INIT_DCS_CMD(0x92, 0x22), - _INIT_DCS_CMD(0xD3, 0x08), - _INIT_DCS_CMD(0xD6, 0x55), - _INIT_DCS_CMD(0xDC, 0x38), - - _INIT_SWITCH_PAGE_CMD(0x08), - _INIT_DCS_CMD(0xE0, 0x00, 0x10, 0x2A, 0x4D, 0x61, 0x56, 0x6A, 0x6E, 0x79, 0x76, 0x8F, 0x95, 0x98, 0xAE, 0xAA, 0xB2, 0xBB, 0xCE, 0xC6, 0xBD, 0xD5, 0xE2, 0xE8), - _INIT_DCS_CMD(0xE1, 0x00, 0x10, 0x2A, 0x4D, 0x61, 0x56, 0x6A, 0x6E, 0x79, 0x76, 0x8F, 0x95, 0x98, 0xAE, 0xAA, 0xB2, 0xBB, 0xCE, 0xC6, 0xBD, 0xD5, 0xE2, 0xE8), - - _INIT_SWITCH_PAGE_CMD(0x04), - _INIT_DCS_CMD(0xBA, 0x81), - - _INIT_SWITCH_PAGE_CMD(0x0C), - _INIT_DCS_CMD(0x00, 0x02), - _INIT_DCS_CMD(0x01, 0x00), - _INIT_DCS_CMD(0x02, 0x03), - _INIT_DCS_CMD(0x03, 0x01), - _INIT_DCS_CMD(0x04, 0x03), - _INIT_DCS_CMD(0x05, 0x02), - _INIT_DCS_CMD(0x06, 0x04), - _INIT_DCS_CMD(0x07, 0x03), - _INIT_DCS_CMD(0x08, 0x03), - _INIT_DCS_CMD(0x09, 0x04), - _INIT_DCS_CMD(0x0A, 0x04), - _INIT_DCS_CMD(0x0B, 0x05), - _INIT_DCS_CMD(0x0C, 0x04), - _INIT_DCS_CMD(0x0D, 0x06), - _INIT_DCS_CMD(0x0E, 0x05), - _INIT_DCS_CMD(0x0F, 0x07), - _INIT_DCS_CMD(0x10, 0x04), - _INIT_DCS_CMD(0x11, 0x08), - _INIT_DCS_CMD(0x12, 0x05), - _INIT_DCS_CMD(0x13, 0x09), - _INIT_DCS_CMD(0x14, 0x05), - _INIT_DCS_CMD(0x15, 0x0A), - _INIT_DCS_CMD(0x16, 0x06), - _INIT_DCS_CMD(0x17, 0x0B), - _INIT_DCS_CMD(0x18, 0x05), - _INIT_DCS_CMD(0x19, 0x0C), - _INIT_DCS_CMD(0x1A, 0x06), - _INIT_DCS_CMD(0x1B, 0x0D), - _INIT_DCS_CMD(0x1C, 0x06), - _INIT_DCS_CMD(0x1D, 0x0E), - _INIT_DCS_CMD(0x1E, 0x07), - _INIT_DCS_CMD(0x1F, 0x0F), - _INIT_DCS_CMD(0x20, 0x06), - _INIT_DCS_CMD(0x21, 0x10), - _INIT_DCS_CMD(0x22, 0x07), - _INIT_DCS_CMD(0x23, 0x11), - _INIT_DCS_CMD(0x24, 0x07), - _INIT_DCS_CMD(0x25, 0x12), - _INIT_DCS_CMD(0x26, 0x08), - _INIT_DCS_CMD(0x27, 0x13), - _INIT_DCS_CMD(0x28, 0x07), - _INIT_DCS_CMD(0x29, 0x14), - _INIT_DCS_CMD(0x2A, 0x08), - _INIT_DCS_CMD(0x2B, 0x15), - _INIT_DCS_CMD(0x2C, 0x08), - _INIT_DCS_CMD(0x2D, 0x16), - _INIT_DCS_CMD(0x2E, 0x09), - _INIT_DCS_CMD(0x2F, 0x17), - _INIT_DCS_CMD(0x30, 0x08), - _INIT_DCS_CMD(0x31, 0x18), - _INIT_DCS_CMD(0x32, 0x09), - _INIT_DCS_CMD(0x33, 0x19), - _INIT_DCS_CMD(0x34, 0x09), - _INIT_DCS_CMD(0x35, 0x1A), - _INIT_DCS_CMD(0x36, 0x0A), - _INIT_DCS_CMD(0x37, 0x1B), - _INIT_DCS_CMD(0x38, 0x0A), - _INIT_DCS_CMD(0x39, 0x1C), - _INIT_DCS_CMD(0x3A, 0x0A), - _INIT_DCS_CMD(0x3B, 0x1D), - _INIT_DCS_CMD(0x3C, 0x0A), - _INIT_DCS_CMD(0x3D, 0x1E), - _INIT_DCS_CMD(0x3E, 0x0A), - _INIT_DCS_CMD(0x3F, 0x1F), - - _INIT_SWITCH_PAGE_CMD(0x04), - _INIT_DCS_CMD(0xBA, 0x01), - - _INIT_SWITCH_PAGE_CMD(0x0E), - _INIT_DCS_CMD(0x02, 0x0C), - _INIT_DCS_CMD(0x20, 0x10), - _INIT_DCS_CMD(0x25, 0x16), - _INIT_DCS_CMD(0x26, 0xE0), - _INIT_DCS_CMD(0x27, 0x00), - _INIT_DCS_CMD(0x29, 0x71), - _INIT_DCS_CMD(0x2A, 0x46), - _INIT_DCS_CMD(0x2B, 0x1F), - _INIT_DCS_CMD(0x2D, 0xC7), - _INIT_DCS_CMD(0x31, 0x02), - _INIT_DCS_CMD(0x32, 0xDF), - _INIT_DCS_CMD(0x33, 0x5A), - _INIT_DCS_CMD(0x34, 0xC0), - _INIT_DCS_CMD(0x35, 0x5A), - _INIT_DCS_CMD(0x36, 0xC0), - _INIT_DCS_CMD(0x38, 0x65), - _INIT_DCS_CMD(0x80, 0x3E), - _INIT_DCS_CMD(0x81, 0xA0), - _INIT_DCS_CMD(0xB0, 0x01), - _INIT_DCS_CMD(0xB1, 0xCC), - _INIT_DCS_CMD(0xC0, 0x12), - _INIT_DCS_CMD(0xC2, 0xCC), - _INIT_DCS_CMD(0xC3, 0xCC), - _INIT_DCS_CMD(0xC4, 0xCC), - _INIT_DCS_CMD(0xC5, 0xCC), - _INIT_DCS_CMD(0xC6, 0xCC), - _INIT_DCS_CMD(0xC7, 0xCC), - _INIT_DCS_CMD(0xC8, 0xCC), - _INIT_DCS_CMD(0xC9, 0xCC), - _INIT_DCS_CMD(0x30, 0x00), - _INIT_DCS_CMD(0x00, 0x81), - _INIT_DCS_CMD(0x08, 0x02), - _INIT_DCS_CMD(0x09, 0x00), - _INIT_DCS_CMD(0x07, 0x21), - _INIT_DCS_CMD(0x04, 0x10), - - _INIT_SWITCH_PAGE_CMD(0x1E), - _INIT_DCS_CMD(0x60, 0x00), - _INIT_DCS_CMD(0x64, 0x00), - _INIT_DCS_CMD(0x6D, 0x00), - - _INIT_SWITCH_PAGE_CMD(0x0B), - _INIT_DCS_CMD(0xA6, 0x44), - _INIT_DCS_CMD(0xA7, 0xB6), - _INIT_DCS_CMD(0xA8, 0x03), - _INIT_DCS_CMD(0xA9, 0x03), - _INIT_DCS_CMD(0xAA, 0x51), - _INIT_DCS_CMD(0xAB, 0x51), - _INIT_DCS_CMD(0xAC, 0x04), - _INIT_DCS_CMD(0xBD, 0x92), - _INIT_DCS_CMD(0xBE, 0xA1), - - _INIT_SWITCH_PAGE_CMD(0x05), - _INIT_DCS_CMD(0x86, 0x87), - - _INIT_SWITCH_PAGE_CMD(0x06), - _INIT_DCS_CMD(0x92, 0x22), - - _INIT_SWITCH_PAGE_CMD(0x00), - _INIT_DCS_CMD(MIPI_DCS_EXIT_SLEEP_MODE), - _INIT_DELAY_CMD(120), - _INIT_DCS_CMD(MIPI_DCS_SET_DISPLAY_ON), - _INIT_DELAY_CMD(20), - {}, +#define ili9882t_switch_page(ctx, page) \ + mipi_dsi_dcs_write_seq_multi(ctx, ILI9882T_DCS_SWITCH_PAGE, \ + 0x98, 0x82, (page)) + +static int starry_ili9882t_init(struct ili9882t *ili) +{ + struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi }; + + usleep_range(5000, 5100); + + ili9882t_switch_page(&ctx, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x42); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x80); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x81); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x71); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x1a); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0xd4); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x40); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x11); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x32); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x30); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x93); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x80); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x28); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x13); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x15); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x41, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x42, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x46, 0x02); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x28); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x4f, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x50, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x12); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x52, 0x14); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x54, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x57, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x02); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x28); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6b, 0x14); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x12); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6e, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6f, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x71, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x72, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x74, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x76, 0x02); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7c, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x28); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x29); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0x15); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x13); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x83, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x85, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x88, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x89, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x8a, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x8b, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x8c, 0x07); + + ili9882t_switch_page(&ctx, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x3a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x3b); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x44); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x44); + + mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x1f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x40); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x00); + + ili9882t_switch_page(&ctx, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x3c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0xfa); + + ili9882t_switch_page(&ctx, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x91); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x3c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0xfa); + + ili9882t_switch_page(&ctx, 0x12); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x2c); + + ili9882t_switch_page(&ctx, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0xe5); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x6b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0xa4); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x54); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x97); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x97); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0x3f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0xda); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xf1); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x3f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x90); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87); + + ili9882t_switch_page(&ctx, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x80); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x58); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x58); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x60); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x38); + + ili9882t_switch_page(&ctx, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e, + 0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce, + 0xc6, 0xbd, 0xd5, 0xe2, 0xe8); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e, + 0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce, + 0xc6, 0xbd, 0xd5, 0xe2, 0xe8); + + ili9882t_switch_page(&ctx, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x81); + + ili9882t_switch_page(&ctx, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x0e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x11); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x12); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x13); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x07); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x14); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x15); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2e, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x17); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x08); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x18); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x19); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x09); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x1a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x1b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x1c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x1d); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x1e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x0a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x1f); + + ili9882t_switch_page(&ctx, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x01); + + ili9882t_switch_page(&ctx, 0x0e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x10); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x16); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xe0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x71); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x46); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x1f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0xc7); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0xdf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x5a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0xc0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x5a); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0xc0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x65); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x3e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0xa0); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0xcc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x12); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xcc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xcc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xcc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xcc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xcc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xcc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0xcc); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x81); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x21); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x10); + + ili9882t_switch_page(&ctx, 0x1e); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x00); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x00); + + ili9882t_switch_page(&ctx, 0x0b); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa6, 0x44); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xb6); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa8, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x03); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x51); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x51); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x04); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x92); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa1); + + ili9882t_switch_page(&ctx, 0x05); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87); + + ili9882t_switch_page(&ctx, 0x06); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22); + + ili9882t_switch_page(&ctx, 0x00); + mipi_dsi_dcs_exit_sleep_mode_multi(&ctx); + + mipi_dsi_msleep(&ctx, 120); + + mipi_dsi_dcs_set_display_on_multi(&ctx); + + mipi_dsi_msleep(&ctx, 20); + + return ctx.accum_err; }; static inline struct ili9882t *to_ili9882t(struct drm_panel *panel) @@ -424,97 +418,21 @@ static inline struct ili9882t *to_ili9882t(struct drm_panel *panel) return container_of(panel, struct ili9882t, base); } -static int ili9882t_init_dcs_cmd(struct ili9882t *ili) -{ - struct mipi_dsi_device *dsi = ili->dsi; - struct drm_panel *panel = &ili->base; - int i, err = 0; - - if (ili->desc->init_cmds) { - const struct panel_init_cmd *init_cmds = ili->desc->init_cmds; - - for (i = 0; init_cmds[i].len != 0; i++) { - const struct panel_init_cmd *cmd = &init_cmds[i]; - - switch (cmd->type) { - case DELAY_CMD: - msleep(cmd->data[0]); - err = 0; - break; - - case INIT_DCS_CMD: - err = mipi_dsi_dcs_write(dsi, cmd->data[0], - cmd->len <= 1 ? NULL : - &cmd->data[1], - cmd->len - 1); - break; - - default: - err = -EINVAL; - } - - if (err < 0) { - dev_err(panel->dev, - "failed to write command %u\n", i); - return err; - } - } - } - return 0; -} - -static int ili9882t_switch_page(struct mipi_dsi_device *dsi, u8 page) -{ - int ret; - const struct panel_init_cmd cmd = _INIT_SWITCH_PAGE_CMD(page); - - ret = mipi_dsi_dcs_write(dsi, cmd.data[0], - cmd.len <= 1 ? NULL : - &cmd.data[1], - cmd.len - 1); - if (ret) { - dev_err(&dsi->dev, - "error switching panel controller page (%d)\n", ret); - return ret; - } - - return 0; -} - -static int ili9882t_enter_sleep_mode(struct ili9882t *ili) -{ - struct mipi_dsi_device *dsi = ili->dsi; - int ret; - - dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) - return ret; - - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) - return ret; - - return 0; -} - static int ili9882t_disable(struct drm_panel *panel) { struct ili9882t *ili = to_ili9882t(panel); - struct mipi_dsi_device *dsi = ili->dsi; - int ret; + struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi }; - ili9882t_switch_page(dsi, 0x00); - ret = ili9882t_enter_sleep_mode(ili); - if (ret < 0) { - dev_err(panel->dev, "failed to set panel off: %d\n", ret); - return ret; - } + ili9882t_switch_page(&ctx, 0x00); - msleep(150); + ili->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - return 0; + mipi_dsi_dcs_set_display_off_multi(&ctx); + mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); + + mipi_dsi_msleep(&ctx, 150); + + return ctx.accum_err; } static int ili9882t_unprepare(struct drm_panel *panel) @@ -560,7 +478,11 @@ static int ili9882t_prepare(struct drm_panel *panel) usleep_range(10000, 11000); // MIPI needs to keep the LP11 state before the lcm_reset pin is pulled high - mipi_dsi_dcs_nop(ili->dsi); + ret = mipi_dsi_dcs_nop(ili->dsi); + if (ret < 0) { + dev_err(&ili->dsi->dev, "Failed to send NOP: %d\n", ret); + goto poweroff; + } usleep_range(1000, 2000); gpiod_set_value(ili->enable_gpio, 1); @@ -570,22 +492,20 @@ static int ili9882t_prepare(struct drm_panel *panel) gpiod_set_value(ili->enable_gpio, 1); usleep_range(6000, 10000); - ret = ili9882t_init_dcs_cmd(ili); - if (ret < 0) { - dev_err(panel->dev, "failed to init panel: %d\n", ret); + ret = ili->desc->init(ili); + if (ret < 0) goto poweroff; - } return 0; poweroff: + gpiod_set_value(ili->enable_gpio, 0); regulator_disable(ili->avee); poweroffavdd: regulator_disable(ili->avdd); poweroff1v8: usleep_range(5000, 7000); regulator_disable(ili->pp1800); - gpiod_set_value(ili->enable_gpio, 0); return ret; } @@ -620,7 +540,7 @@ static const struct panel_desc starry_ili9882t_desc = { .format = MIPI_DSI_FMT_RGB888, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_LPM, - .init_cmds = starry_ili9882t_init_cmd, + .init = starry_ili9882t_init, }; static int ili9882t_get_modes(struct drm_panel *panel, diff --git a/drivers/gpu/drm/panel/panel-innolux-ej030na.c b/drivers/gpu/drm/panel/panel-innolux-ej030na.c index 8fdbda59be48..f85b7a4cbb42 100644 --- a/drivers/gpu/drm/panel/panel-innolux-ej030na.c +++ b/drivers/gpu/drm/panel/panel-innolux-ej030na.c @@ -306,4 +306,5 @@ module_spi_driver(ej030na_driver); MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>"); +MODULE_DESCRIPTION("Innolux/Chimei EJ030NA TFT LCD panel driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c index 485178a99910..d95c0d4f3e35 100644 --- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c +++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c @@ -17,14 +17,7 @@ #include <drm/drm_modes.h> #include <drm/drm_panel.h> -struct panel_init_cmd { - size_t len; - const char *data; -}; - -#define _INIT_CMD(...) { \ - .len = sizeof((char[]){__VA_ARGS__}), \ - .data = (char[]){__VA_ARGS__} } +struct innolux_panel; struct panel_desc { const struct drm_display_mode *mode; @@ -36,7 +29,7 @@ struct panel_desc { unsigned long flags; enum mipi_dsi_pixel_format format; - const struct panel_init_cmd *init_cmds; + int (*init)(struct innolux_panel *innolux); unsigned int lanes; const char * const *supply_names; unsigned int num_supplies; @@ -51,9 +44,6 @@ struct innolux_panel { struct regulator_bulk_data *supplies; struct gpio_desc *enable_gpio; - - bool prepared; - bool enabled; }; static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel) @@ -61,26 +51,11 @@ static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel) return container_of(panel, struct innolux_panel, base); } -static int innolux_panel_disable(struct drm_panel *panel) -{ - struct innolux_panel *innolux = to_innolux_panel(panel); - - if (!innolux->enabled) - return 0; - - innolux->enabled = false; - - return 0; -} - static int innolux_panel_unprepare(struct drm_panel *panel) { struct innolux_panel *innolux = to_innolux_panel(panel); int err; - if (!innolux->prepared) - return 0; - err = mipi_dsi_dcs_set_display_off(innolux->link); if (err < 0) dev_err(panel->dev, "failed to set display off: %d\n", err); @@ -104,8 +79,6 @@ static int innolux_panel_unprepare(struct drm_panel *panel) if (err < 0) return err; - innolux->prepared = false; - return 0; } @@ -114,9 +87,6 @@ static int innolux_panel_prepare(struct drm_panel *panel) struct innolux_panel *innolux = to_innolux_panel(panel); int err; - if (innolux->prepared) - return 0; - gpiod_set_value_cansleep(innolux->enable_gpio, 0); err = regulator_bulk_enable(innolux->desc->num_supplies, @@ -132,32 +102,10 @@ static int innolux_panel_prepare(struct drm_panel *panel) /* p079zca: t4, p097pfg: t5 */ usleep_range(20000, 21000); - if (innolux->desc->init_cmds) { - const struct panel_init_cmd *cmds = - innolux->desc->init_cmds; - unsigned int i; - - for (i = 0; cmds[i].len != 0; i++) { - const struct panel_init_cmd *cmd = &cmds[i]; - - err = mipi_dsi_generic_write(innolux->link, cmd->data, - cmd->len); - if (err < 0) { - dev_err(panel->dev, "failed to write command %u\n", i); - goto poweroff; - } - - /* - * Included by random guessing, because without this - * (or at least, some delay), the panel sometimes - * didn't appear to pick up the command sequence. - */ - err = mipi_dsi_dcs_nop(innolux->link); - if (err < 0) { - dev_err(panel->dev, "failed to send DCS nop: %d\n", err); - goto poweroff; - } - } + if (innolux->desc->init) { + err = innolux->desc->init(innolux); + if (err < 0) + goto poweroff; } err = mipi_dsi_dcs_exit_sleep_mode(innolux->link); @@ -178,8 +126,6 @@ static int innolux_panel_prepare(struct drm_panel *panel) /* T7: 5ms */ usleep_range(5000, 6000); - innolux->prepared = true; - return 0; poweroff: @@ -189,18 +135,6 @@ poweroff: return err; } -static int innolux_panel_enable(struct drm_panel *panel) -{ - struct innolux_panel *innolux = to_innolux_panel(panel); - - if (innolux->enabled) - return 0; - - innolux->enabled = true; - - return 0; -} - static const char * const innolux_p079zca_supply_names[] = { "power", }; @@ -250,119 +184,137 @@ static const struct drm_display_mode innolux_p097pfg_mode = { .vtotal = 2048 + 100 + 2 + 18, }; +static void innolux_panel_write_multi(struct mipi_dsi_multi_context *ctx, + const void *payload, size_t size) +{ + mipi_dsi_generic_write_multi(ctx, payload, size); + + /* + * Included by random guessing, because without this + * (or at least, some delay), the panel sometimes + * didn't appear to pick up the command sequence. + */ + mipi_dsi_dcs_nop_multi(ctx); +} + +#define innolux_panel_init_cmd_multi(ctx, seq...) \ + do { \ + static const u8 d[] = { seq }; \ + innolux_panel_write_multi(ctx, d, ARRAY_SIZE(d)); \ + } while (0) + +#define innolux_panel_switch_page(ctx, page) \ + innolux_panel_init_cmd_multi(ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, (page)) + /* * Display manufacturer failed to provide init sequencing according to * https://chromium-review.googlesource.com/c/chromiumos/third_party/coreboot/+/892065/ * so the init sequence stems from a register dump of a working panel. */ -static const struct panel_init_cmd innolux_p097pfg_init_cmds[] = { - /* page 0 */ - _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x00), - _INIT_CMD(0xB1, 0xE8, 0x11), - _INIT_CMD(0xB2, 0x25, 0x02), - _INIT_CMD(0xB5, 0x08, 0x00), - _INIT_CMD(0xBC, 0x0F, 0x00), - _INIT_CMD(0xB8, 0x03, 0x06, 0x00, 0x00), - _INIT_CMD(0xBD, 0x01, 0x90, 0x14, 0x14), - _INIT_CMD(0x6F, 0x01), - _INIT_CMD(0xC0, 0x03), - _INIT_CMD(0x6F, 0x02), - _INIT_CMD(0xC1, 0x0D), - _INIT_CMD(0xD9, 0x01, 0x09, 0x70), - _INIT_CMD(0xC5, 0x12, 0x21, 0x00), - _INIT_CMD(0xBB, 0x93, 0x93), - - /* page 1 */ - _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01), - _INIT_CMD(0xB3, 0x3C, 0x3C), - _INIT_CMD(0xB4, 0x0F, 0x0F), - _INIT_CMD(0xB9, 0x45, 0x45), - _INIT_CMD(0xBA, 0x14, 0x14), - _INIT_CMD(0xCA, 0x02), - _INIT_CMD(0xCE, 0x04), - _INIT_CMD(0xC3, 0x9B, 0x9B), - _INIT_CMD(0xD8, 0xC0, 0x03), - _INIT_CMD(0xBC, 0x82, 0x01), - _INIT_CMD(0xBD, 0x9E, 0x01), - - /* page 2 */ - _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x02), - _INIT_CMD(0xB0, 0x82), - _INIT_CMD(0xD1, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x82, 0x00, 0xA5, - 0x00, 0xC1, 0x00, 0xEA, 0x01, 0x0D, 0x01, 0x40), - _INIT_CMD(0xD2, 0x01, 0x6A, 0x01, 0xA8, 0x01, 0xDC, 0x02, 0x29, - 0x02, 0x67, 0x02, 0x68, 0x02, 0xA8, 0x02, 0xF0), - _INIT_CMD(0xD3, 0x03, 0x19, 0x03, 0x49, 0x03, 0x67, 0x03, 0x8C, - 0x03, 0xA6, 0x03, 0xC7, 0x03, 0xDE, 0x03, 0xEC), - _INIT_CMD(0xD4, 0x03, 0xFF, 0x03, 0xFF), - _INIT_CMD(0xE0, 0x00, 0x00, 0x00, 0x86, 0x00, 0xC5, 0x00, 0xE5, - 0x00, 0xFF, 0x01, 0x26, 0x01, 0x45, 0x01, 0x75), - _INIT_CMD(0xE1, 0x01, 0x9C, 0x01, 0xD5, 0x02, 0x05, 0x02, 0x4D, - 0x02, 0x86, 0x02, 0x87, 0x02, 0xC3, 0x03, 0x03), - _INIT_CMD(0xE2, 0x03, 0x2A, 0x03, 0x56, 0x03, 0x72, 0x03, 0x94, - 0x03, 0xAC, 0x03, 0xCB, 0x03, 0xE0, 0x03, 0xED), - _INIT_CMD(0xE3, 0x03, 0xFF, 0x03, 0xFF), - - /* page 3 */ - _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x03), - _INIT_CMD(0xB0, 0x00, 0x00, 0x00, 0x00), - _INIT_CMD(0xB1, 0x00, 0x00, 0x00, 0x00), - _INIT_CMD(0xB2, 0x00, 0x00, 0x06, 0x04, 0x01, 0x40, 0x85), - _INIT_CMD(0xB3, 0x10, 0x07, 0xFC, 0x04, 0x01, 0x40, 0x80), - _INIT_CMD(0xB6, 0xF0, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, - 0x40, 0x80), - _INIT_CMD(0xBA, 0xC5, 0x07, 0x00, 0x04, 0x11, 0x25, 0x8C), - _INIT_CMD(0xBB, 0xC5, 0x07, 0x00, 0x03, 0x11, 0x25, 0x8C), - _INIT_CMD(0xC0, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x80, 0x80), - _INIT_CMD(0xC1, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x80, 0x80), - _INIT_CMD(0xC4, 0x00, 0x00), - _INIT_CMD(0xEF, 0x41), - - /* page 4 */ - _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x04), - _INIT_CMD(0xEC, 0x4C), - - /* page 5 */ - _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x05), - _INIT_CMD(0xB0, 0x13, 0x03, 0x03, 0x01), - _INIT_CMD(0xB1, 0x30, 0x00), - _INIT_CMD(0xB2, 0x02, 0x02, 0x00), - _INIT_CMD(0xB3, 0x82, 0x23, 0x82, 0x9D), - _INIT_CMD(0xB4, 0xC5, 0x75, 0x24, 0x57), - _INIT_CMD(0xB5, 0x00, 0xD4, 0x72, 0x11, 0x11, 0xAB, 0x0A), - _INIT_CMD(0xB6, 0x00, 0x00, 0xD5, 0x72, 0x24, 0x56), - _INIT_CMD(0xB7, 0x5C, 0xDC, 0x5C, 0x5C), - _INIT_CMD(0xB9, 0x0C, 0x00, 0x00, 0x01, 0x00), - _INIT_CMD(0xC0, 0x75, 0x11, 0x11, 0x54, 0x05), - _INIT_CMD(0xC6, 0x00, 0x00, 0x00, 0x00), - _INIT_CMD(0xD0, 0x00, 0x48, 0x08, 0x00, 0x00), - _INIT_CMD(0xD1, 0x00, 0x48, 0x09, 0x00, 0x00), - - /* page 6 */ - _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x06), - _INIT_CMD(0xB0, 0x02, 0x32, 0x32, 0x08, 0x2F), - _INIT_CMD(0xB1, 0x2E, 0x15, 0x14, 0x13, 0x12), - _INIT_CMD(0xB2, 0x11, 0x10, 0x00, 0x3D, 0x3D), - _INIT_CMD(0xB3, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D), - _INIT_CMD(0xB4, 0x3D, 0x32), - _INIT_CMD(0xB5, 0x03, 0x32, 0x32, 0x09, 0x2F), - _INIT_CMD(0xB6, 0x2E, 0x1B, 0x1A, 0x19, 0x18), - _INIT_CMD(0xB7, 0x17, 0x16, 0x01, 0x3D, 0x3D), - _INIT_CMD(0xB8, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D), - _INIT_CMD(0xB9, 0x3D, 0x32), - _INIT_CMD(0xC0, 0x01, 0x32, 0x32, 0x09, 0x2F), - _INIT_CMD(0xC1, 0x2E, 0x1A, 0x1B, 0x16, 0x17), - _INIT_CMD(0xC2, 0x18, 0x19, 0x03, 0x3D, 0x3D), - _INIT_CMD(0xC3, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D), - _INIT_CMD(0xC4, 0x3D, 0x32), - _INIT_CMD(0xC5, 0x00, 0x32, 0x32, 0x08, 0x2F), - _INIT_CMD(0xC6, 0x2E, 0x14, 0x15, 0x10, 0x11), - _INIT_CMD(0xC7, 0x12, 0x13, 0x02, 0x3D, 0x3D), - _INIT_CMD(0xC8, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D), - _INIT_CMD(0xC9, 0x3D, 0x32), - - {}, -}; +static int innolux_p097pfg_init(struct innolux_panel *innolux) +{ + struct mipi_dsi_multi_context ctx = { .dsi = innolux->link }; + + innolux_panel_switch_page(&ctx, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xb1, 0xe8, 0x11); + innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x25, 0x02); + innolux_panel_init_cmd_multi(&ctx, 0xb5, 0x08, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xbc, 0x0f, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xb8, 0x03, 0x06, 0x00, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xbd, 0x01, 0x90, 0x14, 0x14); + innolux_panel_init_cmd_multi(&ctx, 0x6f, 0x01); + innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x03); + innolux_panel_init_cmd_multi(&ctx, 0x6f, 0x02); + innolux_panel_init_cmd_multi(&ctx, 0xc1, 0x0d); + innolux_panel_init_cmd_multi(&ctx, 0xd9, 0x01, 0x09, 0x70); + innolux_panel_init_cmd_multi(&ctx, 0xc5, 0x12, 0x21, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xbb, 0x93, 0x93); + + innolux_panel_switch_page(&ctx, 0x01); + innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x3c, 0x3c); + innolux_panel_init_cmd_multi(&ctx, 0xb4, 0x0f, 0x0f); + innolux_panel_init_cmd_multi(&ctx, 0xb9, 0x45, 0x45); + innolux_panel_init_cmd_multi(&ctx, 0xba, 0x14, 0x14); + innolux_panel_init_cmd_multi(&ctx, 0xca, 0x02); + innolux_panel_init_cmd_multi(&ctx, 0xce, 0x04); + innolux_panel_init_cmd_multi(&ctx, 0xc3, 0x9b, 0x9b); + innolux_panel_init_cmd_multi(&ctx, 0xd8, 0xc0, 0x03); + innolux_panel_init_cmd_multi(&ctx, 0xbc, 0x82, 0x01); + innolux_panel_init_cmd_multi(&ctx, 0xbd, 0x9e, 0x01); + + innolux_panel_switch_page(&ctx, 0x02); + innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x82); + innolux_panel_init_cmd_multi(&ctx, 0xd1, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x82, 0x00, 0xa5, + 0x00, 0xc1, 0x00, 0xea, 0x01, 0x0d, 0x01, 0x40); + innolux_panel_init_cmd_multi(&ctx, 0xd2, 0x01, 0x6a, 0x01, 0xa8, 0x01, 0xdc, 0x02, 0x29, + 0x02, 0x67, 0x02, 0x68, 0x02, 0xa8, 0x02, 0xf0); + innolux_panel_init_cmd_multi(&ctx, 0xd3, 0x03, 0x19, 0x03, 0x49, 0x03, 0x67, 0x03, 0x8c, + 0x03, 0xa6, 0x03, 0xc7, 0x03, 0xde, 0x03, 0xec); + innolux_panel_init_cmd_multi(&ctx, 0xd4, 0x03, 0xff, 0x03, 0xff); + innolux_panel_init_cmd_multi(&ctx, 0xe0, 0x00, 0x00, 0x00, 0x86, 0x00, 0xc5, 0x00, 0xe5, + 0x00, 0xff, 0x01, 0x26, 0x01, 0x45, 0x01, 0x75); + innolux_panel_init_cmd_multi(&ctx, 0xe1, 0x01, 0x9c, 0x01, 0xd5, 0x02, 0x05, 0x02, 0x4d, + 0x02, 0x86, 0x02, 0x87, 0x02, 0xc3, 0x03, 0x03); + innolux_panel_init_cmd_multi(&ctx, 0xe2, 0x03, 0x2a, 0x03, 0x56, 0x03, 0x72, 0x03, 0x94, + 0x03, 0xac, 0x03, 0xcb, 0x03, 0xe0, 0x03, 0xed); + innolux_panel_init_cmd_multi(&ctx, 0xe3, 0x03, 0xff, 0x03, 0xff); + + innolux_panel_switch_page(&ctx, 0x03); + innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x00, 0x00, 0x00, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xb1, 0x00, 0x00, 0x00, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x00, 0x00, 0x06, 0x04, 0x01, 0x40, 0x85); + innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x10, 0x07, 0xfc, 0x04, 0x01, 0x40, 0x80); + innolux_panel_init_cmd_multi(&ctx, 0xb6, 0xf0, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x40, 0x80); + innolux_panel_init_cmd_multi(&ctx, 0xba, 0xc5, 0x07, 0x00, 0x04, 0x11, 0x25, 0x8c); + innolux_panel_init_cmd_multi(&ctx, 0xbb, 0xc5, 0x07, 0x00, 0x03, 0x11, 0x25, 0x8c); + innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x80, 0x80); + innolux_panel_init_cmd_multi(&ctx, 0xc1, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x80, 0x80); + innolux_panel_init_cmd_multi(&ctx, 0xc4, 0x00, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xef, 0x41); + + innolux_panel_switch_page(&ctx, 0x04); + innolux_panel_init_cmd_multi(&ctx, 0xec, 0x4c); + + innolux_panel_switch_page(&ctx, 0x05); + innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x13, 0x03, 0x03, 0x01); + innolux_panel_init_cmd_multi(&ctx, 0xb1, 0x30, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x02, 0x02, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x82, 0x23, 0x82, 0x9d); + innolux_panel_init_cmd_multi(&ctx, 0xb4, 0xc5, 0x75, 0x24, 0x57); + innolux_panel_init_cmd_multi(&ctx, 0xb5, 0x00, 0xd4, 0x72, 0x11, 0x11, 0xab, 0x0a); + innolux_panel_init_cmd_multi(&ctx, 0xb6, 0x00, 0x00, 0xd5, 0x72, 0x24, 0x56); + innolux_panel_init_cmd_multi(&ctx, 0xb7, 0x5c, 0xdc, 0x5c, 0x5c); + innolux_panel_init_cmd_multi(&ctx, 0xb9, 0x0c, 0x00, 0x00, 0x01, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x75, 0x11, 0x11, 0x54, 0x05); + innolux_panel_init_cmd_multi(&ctx, 0xc6, 0x00, 0x00, 0x00, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xd0, 0x00, 0x48, 0x08, 0x00, 0x00); + innolux_panel_init_cmd_multi(&ctx, 0xd1, 0x00, 0x48, 0x09, 0x00, 0x00); + + innolux_panel_switch_page(&ctx, 0x06); + innolux_panel_init_cmd_multi(&ctx, 0xb0, 0x02, 0x32, 0x32, 0x08, 0x2f); + innolux_panel_init_cmd_multi(&ctx, 0xb1, 0x2e, 0x15, 0x14, 0x13, 0x12); + innolux_panel_init_cmd_multi(&ctx, 0xb2, 0x11, 0x10, 0x00, 0x3d, 0x3d); + innolux_panel_init_cmd_multi(&ctx, 0xb3, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d); + innolux_panel_init_cmd_multi(&ctx, 0xb4, 0x3d, 0x32); + innolux_panel_init_cmd_multi(&ctx, 0xb5, 0x03, 0x32, 0x32, 0x09, 0x2f); + innolux_panel_init_cmd_multi(&ctx, 0xb6, 0x2e, 0x1b, 0x1a, 0x19, 0x18); + innolux_panel_init_cmd_multi(&ctx, 0xb7, 0x17, 0x16, 0x01, 0x3d, 0x3d); + innolux_panel_init_cmd_multi(&ctx, 0xb8, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d); + innolux_panel_init_cmd_multi(&ctx, 0xb9, 0x3d, 0x32); + innolux_panel_init_cmd_multi(&ctx, 0xc0, 0x01, 0x32, 0x32, 0x09, 0x2f); + innolux_panel_init_cmd_multi(&ctx, 0xc1, 0x2e, 0x1a, 0x1b, 0x16, 0x17); + innolux_panel_init_cmd_multi(&ctx, 0xc2, 0x18, 0x19, 0x03, 0x3d, 0x3d); + innolux_panel_init_cmd_multi(&ctx, 0xc3, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d); + innolux_panel_init_cmd_multi(&ctx, 0xc4, 0x3d, 0x32); + innolux_panel_init_cmd_multi(&ctx, 0xc5, 0x00, 0x32, 0x32, 0x08, 0x2f); + innolux_panel_init_cmd_multi(&ctx, 0xc6, 0x2e, 0x14, 0x15, 0x10, 0x11); + innolux_panel_init_cmd_multi(&ctx, 0xc7, 0x12, 0x13, 0x02, 0x3d, 0x3d); + innolux_panel_init_cmd_multi(&ctx, 0xc8, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d); + innolux_panel_init_cmd_multi(&ctx, 0xc9, 0x3d, 0x32); + + return ctx.accum_err; +} static const struct panel_desc innolux_p097pfg_panel_desc = { .mode = &innolux_p097pfg_mode, @@ -374,7 +326,7 @@ static const struct panel_desc innolux_p097pfg_panel_desc = { .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_LPM, .format = MIPI_DSI_FMT_RGB888, - .init_cmds = innolux_p097pfg_init_cmds, + .init = innolux_p097pfg_init, .lanes = 4, .supply_names = innolux_p097pfg_supply_names, .num_supplies = ARRAY_SIZE(innolux_p097pfg_supply_names), @@ -407,10 +359,8 @@ static int innolux_panel_get_modes(struct drm_panel *panel, } static const struct drm_panel_funcs innolux_panel_funcs = { - .disable = innolux_panel_disable, .unprepare = innolux_panel_unprepare, .prepare = innolux_panel_prepare, - .enable = innolux_panel_enable, .get_modes = innolux_panel_get_modes, }; @@ -510,13 +460,6 @@ static void innolux_panel_remove(struct mipi_dsi_device *dsi) struct innolux_panel *innolux = mipi_dsi_get_drvdata(dsi); int err; - err = drm_panel_unprepare(&innolux->base); - if (err < 0) - dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err); - - err = drm_panel_disable(&innolux->base); - if (err < 0) - dev_err(&dsi->dev, "failed to disable panel: %d\n", err); err = mipi_dsi_detach(dsi); if (err < 0) @@ -525,14 +468,6 @@ static void innolux_panel_remove(struct mipi_dsi_device *dsi) innolux_panel_del(innolux); } -static void innolux_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct innolux_panel *innolux = mipi_dsi_get_drvdata(dsi); - - drm_panel_unprepare(&innolux->base); - drm_panel_disable(&innolux->base); -} - static struct mipi_dsi_driver innolux_panel_driver = { .driver = { .name = "panel-innolux-p079zca", @@ -540,7 +475,6 @@ static struct mipi_dsi_driver innolux_panel_driver = { }, .probe = innolux_panel_probe, .remove = innolux_panel_remove, - .shutdown = innolux_panel_shutdown, }; module_mipi_dsi_driver(innolux_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c index f9a69f347068..b1ce186de261 100644 --- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c +++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c @@ -37,9 +37,6 @@ struct jdi_panel { struct gpio_desc *dcdc_en_gpio; struct backlight_device *backlight; - bool prepared; - bool enabled; - const struct drm_display_mode *mode; }; @@ -176,13 +173,8 @@ static int jdi_panel_disable(struct drm_panel *panel) { struct jdi_panel *jdi = to_jdi_panel(panel); - if (!jdi->enabled) - return 0; - backlight_disable(jdi->backlight); - jdi->enabled = false; - return 0; } @@ -192,9 +184,6 @@ static int jdi_panel_unprepare(struct drm_panel *panel) struct device *dev = &jdi->dsi->dev; int ret; - if (!jdi->prepared) - return 0; - jdi_panel_off(jdi); ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies); @@ -207,8 +196,6 @@ static int jdi_panel_unprepare(struct drm_panel *panel) gpiod_set_value(jdi->dcdc_en_gpio, 0); - jdi->prepared = false; - return 0; } @@ -218,9 +205,6 @@ static int jdi_panel_prepare(struct drm_panel *panel) struct device *dev = &jdi->dsi->dev; int ret; - if (jdi->prepared) - return 0; - ret = regulator_bulk_enable(ARRAY_SIZE(jdi->supplies), jdi->supplies); if (ret < 0) { dev_err(dev, "regulator enable failed, %d\n", ret); @@ -250,8 +234,6 @@ static int jdi_panel_prepare(struct drm_panel *panel) goto poweroff; } - jdi->prepared = true; - return 0; poweroff: @@ -272,13 +254,8 @@ static int jdi_panel_enable(struct drm_panel *panel) { struct jdi_panel *jdi = to_jdi_panel(panel); - if (jdi->enabled) - return 0; - backlight_enable(jdi->backlight); - jdi->enabled = true; - return 0; } @@ -475,10 +452,6 @@ static void jdi_panel_remove(struct mipi_dsi_device *dsi) struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi); int ret; - ret = jdi_panel_disable(&jdi->base); - if (ret < 0) - dev_err(&dsi->dev, "failed to disable panel: %d\n", ret); - ret = mipi_dsi_detach(dsi); if (ret < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", @@ -487,13 +460,6 @@ static void jdi_panel_remove(struct mipi_dsi_device *dsi) jdi_panel_del(jdi); } -static void jdi_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi); - - jdi_panel_disable(&jdi->base); -} - static struct mipi_dsi_driver jdi_panel_driver = { .driver = { .name = "panel-jdi-lt070me05000", @@ -501,7 +467,6 @@ static struct mipi_dsi_driver jdi_panel_driver = { }, .probe = jdi_panel_probe, .remove = jdi_panel_remove, - .shutdown = jdi_panel_shutdown, }; module_mipi_dsi_driver(jdi_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-khadas-ts050.c b/drivers/gpu/drm/panel/panel-khadas-ts050.c index c54be0cc3f08..14932cb3defc 100644 --- a/drivers/gpu/drm/panel/panel-khadas-ts050.c +++ b/drivers/gpu/drm/panel/panel-khadas-ts050.c @@ -26,9 +26,6 @@ struct khadas_ts050_panel { struct gpio_desc *reset_gpio; struct gpio_desc *enable_gpio; struct khadas_ts050_panel_data *panel_data; - - bool prepared; - bool enabled; }; struct khadas_ts050_panel_cmd { @@ -642,9 +639,6 @@ static int khadas_ts050_panel_prepare(struct drm_panel *panel) unsigned int i; int err; - if (khadas_ts050->prepared) - return 0; - gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0); err = regulator_enable(khadas_ts050->supply); @@ -708,8 +702,6 @@ static int khadas_ts050_panel_prepare(struct drm_panel *panel) usleep_range(10000, 11000); - khadas_ts050->prepared = true; - return 0; poweroff: @@ -726,11 +718,6 @@ static int khadas_ts050_panel_unprepare(struct drm_panel *panel) struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel); int err; - if (!khadas_ts050->prepared) - return 0; - - khadas_ts050->prepared = false; - err = mipi_dsi_dcs_enter_sleep_mode(khadas_ts050->link); if (err < 0) dev_err(panel->dev, "failed to enter sleep mode: %d\n", err); @@ -747,31 +734,17 @@ static int khadas_ts050_panel_unprepare(struct drm_panel *panel) return 0; } -static int khadas_ts050_panel_enable(struct drm_panel *panel) -{ - struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel); - - khadas_ts050->enabled = true; - - return 0; -} - static int khadas_ts050_panel_disable(struct drm_panel *panel) { struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel); int err; - if (!khadas_ts050->enabled) - return 0; - err = mipi_dsi_dcs_set_display_off(khadas_ts050->link); if (err < 0) dev_err(panel->dev, "failed to set display off: %d\n", err); usleep_range(10000, 11000); - khadas_ts050->enabled = false; - return 0; } @@ -815,7 +788,6 @@ static int khadas_ts050_panel_get_modes(struct drm_panel *panel, static const struct drm_panel_funcs khadas_ts050_panel_funcs = { .prepare = khadas_ts050_panel_prepare, .unprepare = khadas_ts050_panel_unprepare, - .enable = khadas_ts050_panel_enable, .disable = khadas_ts050_panel_disable, .get_modes = khadas_ts050_panel_get_modes, }; @@ -908,16 +880,6 @@ static void khadas_ts050_panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); drm_panel_remove(&khadas_ts050->base); - drm_panel_disable(&khadas_ts050->base); - drm_panel_unprepare(&khadas_ts050->base); -} - -static void khadas_ts050_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct khadas_ts050_panel *khadas_ts050 = mipi_dsi_get_drvdata(dsi); - - drm_panel_disable(&khadas_ts050->base); - drm_panel_unprepare(&khadas_ts050->base); } static struct mipi_dsi_driver khadas_ts050_panel_driver = { @@ -927,7 +889,6 @@ static struct mipi_dsi_driver khadas_ts050_panel_driver = { }, .probe = khadas_ts050_panel_probe, .remove = khadas_ts050_panel_remove, - .shutdown = khadas_ts050_panel_shutdown, }; module_mipi_dsi_driver(khadas_ts050_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c index 17f8d80cf2b3..d6b912277196 100644 --- a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c +++ b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c @@ -23,9 +23,6 @@ struct kingdisplay_panel { struct regulator *supply; struct gpio_desc *enable_gpio; - - bool prepared; - bool enabled; }; struct kingdisplay_panel_cmd { @@ -185,15 +182,10 @@ static int kingdisplay_panel_disable(struct drm_panel *panel) struct kingdisplay_panel *kingdisplay = to_kingdisplay_panel(panel); int err; - if (!kingdisplay->enabled) - return 0; - err = mipi_dsi_dcs_set_display_off(kingdisplay->link); if (err < 0) dev_err(panel->dev, "failed to set display off: %d\n", err); - kingdisplay->enabled = false; - return 0; } @@ -202,9 +194,6 @@ static int kingdisplay_panel_unprepare(struct drm_panel *panel) struct kingdisplay_panel *kingdisplay = to_kingdisplay_panel(panel); int err; - if (!kingdisplay->prepared) - return 0; - err = mipi_dsi_dcs_enter_sleep_mode(kingdisplay->link); if (err < 0) { dev_err(panel->dev, "failed to enter sleep mode: %d\n", err); @@ -220,8 +209,6 @@ static int kingdisplay_panel_unprepare(struct drm_panel *panel) if (err < 0) return err; - kingdisplay->prepared = false; - return 0; } @@ -231,9 +218,6 @@ static int kingdisplay_panel_prepare(struct drm_panel *panel) int err, regulator_err; unsigned int i; - if (kingdisplay->prepared) - return 0; - gpiod_set_value_cansleep(kingdisplay->enable_gpio, 0); err = regulator_enable(kingdisplay->supply); @@ -275,8 +259,6 @@ static int kingdisplay_panel_prepare(struct drm_panel *panel) /* T7: 10ms */ usleep_range(10000, 11000); - kingdisplay->prepared = true; - return 0; poweroff: @@ -289,18 +271,6 @@ poweroff: return err; } -static int kingdisplay_panel_enable(struct drm_panel *panel) -{ - struct kingdisplay_panel *kingdisplay = to_kingdisplay_panel(panel); - - if (kingdisplay->enabled) - return 0; - - kingdisplay->enabled = true; - - return 0; -} - static const struct drm_display_mode default_mode = { .clock = 229000, .hdisplay = 1536, @@ -341,7 +311,6 @@ static const struct drm_panel_funcs kingdisplay_panel_funcs = { .disable = kingdisplay_panel_disable, .unprepare = kingdisplay_panel_unprepare, .prepare = kingdisplay_panel_prepare, - .enable = kingdisplay_panel_enable, .get_modes = kingdisplay_panel_get_modes, }; @@ -420,14 +389,6 @@ static void kingdisplay_panel_remove(struct mipi_dsi_device *dsi) struct kingdisplay_panel *kingdisplay = mipi_dsi_get_drvdata(dsi); int err; - err = drm_panel_unprepare(&kingdisplay->base); - if (err < 0) - dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err); - - err = drm_panel_disable(&kingdisplay->base); - if (err < 0) - dev_err(&dsi->dev, "failed to disable panel: %d\n", err); - err = mipi_dsi_detach(dsi); if (err < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); @@ -435,14 +396,6 @@ static void kingdisplay_panel_remove(struct mipi_dsi_device *dsi) kingdisplay_panel_del(kingdisplay); } -static void kingdisplay_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct kingdisplay_panel *kingdisplay = mipi_dsi_get_drvdata(dsi); - - drm_panel_unprepare(&kingdisplay->base); - drm_panel_disable(&kingdisplay->base); -} - static struct mipi_dsi_driver kingdisplay_panel_driver = { .driver = { .name = "panel-kingdisplay-kd097d04", @@ -450,7 +403,6 @@ static struct mipi_dsi_driver kingdisplay_panel_driver = { }, .probe = kingdisplay_panel_probe, .remove = kingdisplay_panel_remove, - .shutdown = kingdisplay_panel_shutdown, }; module_mipi_dsi_driver(kingdisplay_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c index 1a26205701b5..292aa26a456d 100644 --- a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c +++ b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c @@ -36,7 +36,6 @@ struct ltk050h3146w { struct regulator *vci; struct regulator *iovcc; const struct ltk050h3146w_desc *panel_desc; - bool prepared; }; static const struct ltk050h3146w_cmd page1_cmds[] = { @@ -521,9 +520,6 @@ static int ltk050h3146w_unprepare(struct drm_panel *panel) struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); int ret; - if (!ctx->prepared) - return 0; - ret = mipi_dsi_dcs_set_display_off(dsi); if (ret < 0) { dev_err(ctx->dev, "failed to set display off: %d\n", ret); @@ -539,8 +535,6 @@ static int ltk050h3146w_unprepare(struct drm_panel *panel) regulator_disable(ctx->iovcc); regulator_disable(ctx->vci); - ctx->prepared = false; - return 0; } @@ -550,9 +544,6 @@ static int ltk050h3146w_prepare(struct drm_panel *panel) struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); int ret; - if (ctx->prepared) - return 0; - dev_dbg(ctx->dev, "Resetting the panel\n"); ret = regulator_enable(ctx->vci); if (ret < 0) { @@ -593,8 +584,6 @@ static int ltk050h3146w_prepare(struct drm_panel *panel) msleep(50); - ctx->prepared = true; - return 0; disable_iovcc: @@ -684,27 +673,11 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi) return 0; } -static void ltk050h3146w_shutdown(struct mipi_dsi_device *dsi) -{ - struct ltk050h3146w *ctx = mipi_dsi_get_drvdata(dsi); - int ret; - - ret = drm_panel_unprepare(&ctx->panel); - if (ret < 0) - dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); - - ret = drm_panel_disable(&ctx->panel); - if (ret < 0) - dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); -} - static void ltk050h3146w_remove(struct mipi_dsi_device *dsi) { struct ltk050h3146w *ctx = mipi_dsi_get_drvdata(dsi); int ret; - ltk050h3146w_shutdown(dsi); - ret = mipi_dsi_detach(dsi); if (ret < 0) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); @@ -736,7 +709,6 @@ static struct mipi_dsi_driver ltk050h3146w_driver = { }, .probe = ltk050h3146w_probe, .remove = ltk050h3146w_remove, - .shutdown = ltk050h3146w_shutdown, }; module_mipi_dsi_driver(ltk050h3146w_driver); diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c index a4c9a5cb9811..6b18cf00fd4a 100644 --- a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c +++ b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c @@ -40,7 +40,6 @@ struct ltk500hd1829 { struct regulator *vcc; struct regulator *iovcc; const struct ltk500hd1829_desc *panel_desc; - bool prepared; }; static const struct ltk500hd1829_cmd ltk101b4029w_init[] = { @@ -492,9 +491,6 @@ static int ltk500hd1829_unprepare(struct drm_panel *panel) struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); int ret; - if (!ctx->prepared) - return 0; - ret = mipi_dsi_dcs_set_display_off(dsi); if (ret < 0) dev_err(panel->dev, "failed to set display off: %d\n", ret); @@ -510,8 +506,6 @@ static int ltk500hd1829_unprepare(struct drm_panel *panel) regulator_disable(ctx->iovcc); regulator_disable(ctx->vcc); - ctx->prepared = false; - return 0; } @@ -522,9 +516,6 @@ static int ltk500hd1829_prepare(struct drm_panel *panel) unsigned int i; int ret; - if (ctx->prepared) - return 0; - ret = regulator_enable(ctx->vcc); if (ret < 0) { dev_err(ctx->dev, "Failed to enable vci supply: %d\n", ret); @@ -568,8 +559,6 @@ static int ltk500hd1829_prepare(struct drm_panel *panel) goto disable_iovcc; } - ctx->prepared = true; - return 0; disable_iovcc: @@ -673,27 +662,11 @@ static int ltk500hd1829_probe(struct mipi_dsi_device *dsi) return 0; } -static void ltk500hd1829_shutdown(struct mipi_dsi_device *dsi) -{ - struct ltk500hd1829 *ctx = mipi_dsi_get_drvdata(dsi); - int ret; - - ret = drm_panel_unprepare(&ctx->panel); - if (ret < 0) - dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); - - ret = drm_panel_disable(&ctx->panel); - if (ret < 0) - dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); -} - static void ltk500hd1829_remove(struct mipi_dsi_device *dsi) { struct ltk500hd1829 *ctx = mipi_dsi_get_drvdata(dsi); int ret; - ltk500hd1829_shutdown(dsi); - ret = mipi_dsi_detach(dsi); if (ret < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); @@ -721,7 +694,6 @@ static struct mipi_dsi_driver ltk500hd1829_driver = { }, .probe = ltk500hd1829_probe, .remove = ltk500hd1829_remove, - .shutdown = ltk500hd1829_shutdown, }; module_mipi_dsi_driver(ltk500hd1829_driver); diff --git a/drivers/gpu/drm/panel/panel-lg-sw43408.c b/drivers/gpu/drm/panel/panel-lg-sw43408.c index 2b3a73696dce..f3dcc39670ea 100644 --- a/drivers/gpu/drm/panel/panel-lg-sw43408.c +++ b/drivers/gpu/drm/panel/panel-lg-sw43408.c @@ -40,83 +40,83 @@ static inline struct sw43408_panel *to_panel_info(struct drm_panel *panel) static int sw43408_unprepare(struct drm_panel *panel) { - struct sw43408_panel *ctx = to_panel_info(panel); + struct sw43408_panel *sw43408 = to_panel_info(panel); + struct mipi_dsi_multi_context ctx = { .dsi = sw43408->link }; int ret; - ret = mipi_dsi_dcs_set_display_off(ctx->link); - if (ret < 0) - dev_err(panel->dev, "set_display_off cmd failed ret = %d\n", ret); + mipi_dsi_dcs_set_display_off_multi(&ctx); - ret = mipi_dsi_dcs_enter_sleep_mode(ctx->link); - if (ret < 0) - dev_err(panel->dev, "enter_sleep cmd failed ret = %d\n", ret); + mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); - msleep(100); + mipi_dsi_msleep(&ctx, 100); - gpiod_set_value(ctx->reset_gpio, 1); + gpiod_set_value(sw43408->reset_gpio, 1); + + ret = regulator_bulk_disable(ARRAY_SIZE(sw43408->supplies), sw43408->supplies); - return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); + return ret ? : ctx.accum_err; } static int sw43408_program(struct drm_panel *panel) { - struct sw43408_panel *ctx = to_panel_info(panel); + struct sw43408_panel *sw43408 = to_panel_info(panel); + struct mipi_dsi_multi_context ctx = { .dsi = sw43408->link }; struct drm_dsc_picture_parameter_set pps; - mipi_dsi_dcs_write_seq(ctx->link, MIPI_DCS_SET_GAMMA_CURVE, 0x02); + mipi_dsi_dcs_write_seq_multi(&ctx, MIPI_DCS_SET_GAMMA_CURVE, 0x02); - mipi_dsi_dcs_set_tear_on(ctx->link, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + mipi_dsi_dcs_set_tear_on_multi(&ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); - mipi_dsi_dcs_write_seq(ctx->link, 0x53, 0x0c, 0x30); - mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x00, 0x70, 0xdf, 0x00, 0x70, 0xdf); - mipi_dsi_dcs_write_seq(ctx->link, 0xf7, 0x01, 0x49, 0x0c); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x0c, 0x30); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x00, 0x70, 0xdf, 0x00, 0x70, 0xdf); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xf7, 0x01, 0x49, 0x0c); - mipi_dsi_dcs_exit_sleep_mode(ctx->link); + mipi_dsi_dcs_exit_sleep_mode_multi(&ctx); - msleep(135); + mipi_dsi_msleep(&ctx, 135); /* COMPRESSION_MODE moved after setting the PPS */ - mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xac); - mipi_dsi_dcs_write_seq(ctx->link, 0xe5, + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0xac); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x0e, 0x10); - mipi_dsi_dcs_write_seq(ctx->link, 0xb5, + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb5, 0x75, 0x60, 0x2d, 0x5d, 0x80, 0x00, 0x0a, 0x0b, 0x00, 0x05, 0x0b, 0x00, 0x80, 0x0d, 0x0e, 0x40, 0x00, 0x0c, 0x00, 0x16, 0x00, 0xb8, 0x00, 0x80, 0x0d, 0x0e, 0x40, 0x00, 0x0c, 0x00, 0x16, 0x00, 0xb8, 0x00, 0x81, 0x00, 0x03, 0x03, 0x03, 0x01, 0x01); - msleep(85); - mipi_dsi_dcs_write_seq(ctx->link, 0xcd, + mipi_dsi_msleep(&ctx, 85); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcd, 0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x16, 0x16); - mipi_dsi_dcs_write_seq(ctx->link, 0xcb, 0x80, 0x5c, 0x07, 0x03, 0x28); - mipi_dsi_dcs_write_seq(ctx->link, 0xc0, 0x02, 0x02, 0x0f); - mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x04, 0x61, 0xdb, 0x04, 0x70, 0xdb); - mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xca); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x80, 0x5c, 0x07, 0x03, 0x28); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x02, 0x02, 0x0f); + mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x04, 0x61, 0xdb, 0x04, 0x70, 0xdb); + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0xca); + + mipi_dsi_dcs_set_display_on_multi(&ctx); - mipi_dsi_dcs_set_display_on(ctx->link); + mipi_dsi_msleep(&ctx, 50); - msleep(50); + sw43408->link->mode_flags &= ~MIPI_DSI_MODE_LPM; - ctx->link->mode_flags &= ~MIPI_DSI_MODE_LPM; + drm_dsc_pps_payload_pack(&pps, sw43408->link->dsc); - drm_dsc_pps_payload_pack(&pps, ctx->link->dsc); - mipi_dsi_picture_parameter_set(ctx->link, &pps); + mipi_dsi_picture_parameter_set_multi(&ctx, &pps); - ctx->link->mode_flags |= MIPI_DSI_MODE_LPM; + sw43408->link->mode_flags |= MIPI_DSI_MODE_LPM; /* * This panel uses PPS selectors with offset: * PPS 1 if pps_identifier is 0 * PPS 2 if pps_identifier is 1 */ - mipi_dsi_compression_mode_ext(ctx->link, true, - MIPI_DSI_COMPRESSION_DSC, 1); - - return 0; + mipi_dsi_compression_mode_ext_multi(&ctx, true, + MIPI_DSI_COMPRESSION_DSC, 1); + return ctx.accum_err; } static int sw43408_prepare(struct drm_panel *panel) diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c index 1aab0c9ae52f..c5d3ead38555 100644 --- a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c +++ b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c @@ -433,6 +433,202 @@ static const struct nv3052c_reg fs035vg158_panel_regs[] = { { 0x36, 0x0a }, // bgr = 1, ss = 1, gs = 0 }; + +static const struct nv3052c_reg wl_355608_a8_panel_regs[] = { + // EXTC Command set enable, select page 1 + { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x01 }, + // Mostly unknown registers + { 0xe3, 0x00 }, + { 0x40, 0x00 }, + { 0x03, 0x40 }, + { 0x04, 0x00 }, + { 0x05, 0x03 }, + { 0x08, 0x00 }, + { 0x09, 0x07 }, + { 0x0a, 0x01 }, + { 0x0b, 0x32 }, + { 0x0c, 0x32 }, + { 0x0d, 0x0b }, + { 0x0e, 0x00 }, + { 0x23, 0xa0 }, + { 0x24, 0x0c }, + { 0x25, 0x06 }, + { 0x26, 0x14 }, + { 0x27, 0x14 }, + { 0x38, 0xcc }, // VCOM_ADJ1 + { 0x39, 0xd7 }, // VCOM_ADJ2 + { 0x3a, 0x44 }, // VCOM_ADJ3 + { 0x28, 0x40 }, + { 0x29, 0x01 }, + { 0x2a, 0xdf }, + { 0x49, 0x3c }, + { 0x91, 0x77 }, // EXTPW_CTRL2 + { 0x92, 0x77 }, // EXTPW_CTRL3 + { 0xa0, 0x55 }, + { 0xa1, 0x50 }, + { 0xa4, 0x9c }, + { 0xa7, 0x02 }, + { 0xa8, 0x01 }, + { 0xa9, 0x01 }, + { 0xaa, 0xfc }, + { 0xab, 0x28 }, + { 0xac, 0x06 }, + { 0xad, 0x06 }, + { 0xae, 0x06 }, + { 0xaf, 0x03 }, + { 0xb0, 0x08 }, + { 0xb1, 0x26 }, + { 0xb2, 0x28 }, + { 0xb3, 0x28 }, + { 0xb4, 0x33 }, + { 0xb5, 0x08 }, + { 0xb6, 0x26 }, + { 0xb7, 0x08 }, + { 0xb8, 0x26 }, + { 0xf0, 0x00 }, + { 0xf6, 0xc0 }, + // EXTC Command set enable, select page 2 + { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x02 }, + // Set gray scale voltage to adjust gamma + { 0xb0, 0x0b }, // PGAMVR0 + { 0xb1, 0x16 }, // PGAMVR1 + { 0xb2, 0x17 }, // PGAMVR2 + { 0xb3, 0x2c }, // PGAMVR3 + { 0xb4, 0x32 }, // PGAMVR4 + { 0xb5, 0x3b }, // PGAMVR5 + { 0xb6, 0x29 }, // PGAMPR0 + { 0xb7, 0x40 }, // PGAMPR1 + { 0xb8, 0x0d }, // PGAMPK0 + { 0xb9, 0x05 }, // PGAMPK1 + { 0xba, 0x12 }, // PGAMPK2 + { 0xbb, 0x10 }, // PGAMPK3 + { 0xbc, 0x12 }, // PGAMPK4 + { 0xbd, 0x15 }, // PGAMPK5 + { 0xbe, 0x19 }, // PGAMPK6 + { 0xbf, 0x0e }, // PGAMPK7 + { 0xc0, 0x16 }, // PGAMPK8 + { 0xc1, 0x0a }, // PGAMPK9 + // Set gray scale voltage to adjust gamma + { 0xd0, 0x0c }, // NGAMVR0 + { 0xd1, 0x17 }, // NGAMVR0 + { 0xd2, 0x14 }, // NGAMVR1 + { 0xd3, 0x2e }, // NGAMVR2 + { 0xd4, 0x32 }, // NGAMVR3 + { 0xd5, 0x3c }, // NGAMVR4 + { 0xd6, 0x22 }, // NGAMPR0 + { 0xd7, 0x3d }, // NGAMPR1 + { 0xd8, 0x0d }, // NGAMPK0 + { 0xd9, 0x07 }, // NGAMPK1 + { 0xda, 0x13 }, // NGAMPK2 + { 0xdb, 0x13 }, // NGAMPK3 + { 0xdc, 0x11 }, // NGAMPK4 + { 0xdd, 0x15 }, // NGAMPK5 + { 0xde, 0x19 }, // NGAMPK6 + { 0xdf, 0x10 }, // NGAMPK7 + { 0xe0, 0x17 }, // NGAMPK8 + { 0xe1, 0x0a }, // NGAMPK9 + // EXTC Command set enable, select page 3 + { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x03 }, + // Set various timing settings + { 0x00, 0x2a }, // GIP_VST_1 + { 0x01, 0x2a }, // GIP_VST_2 + { 0x02, 0x2a }, // GIP_VST_3 + { 0x03, 0x2a }, // GIP_VST_4 + { 0x04, 0x61 }, // GIP_VST_5 + { 0x05, 0x80 }, // GIP_VST_6 + { 0x06, 0xc7 }, // GIP_VST_7 + { 0x07, 0x01 }, // GIP_VST_8 + { 0x08, 0x03 }, // GIP_VST_9 + { 0x09, 0x04 }, // GIP_VST_10 + { 0x70, 0x22 }, // GIP_ECLK1 + { 0x71, 0x80 }, // GIP_ECLK2 + { 0x30, 0x2a }, // GIP_CLK_1 + { 0x31, 0x2a }, // GIP_CLK_2 + { 0x32, 0x2a }, // GIP_CLK_3 + { 0x33, 0x2a }, // GIP_CLK_4 + { 0x34, 0x61 }, // GIP_CLK_5 + { 0x35, 0xc5 }, // GIP_CLK_6 + { 0x36, 0x80 }, // GIP_CLK_7 + { 0x37, 0x23 }, // GIP_CLK_8 + { 0x40, 0x03 }, // GIP_CLKA_1 + { 0x41, 0x04 }, // GIP_CLKA_2 + { 0x42, 0x05 }, // GIP_CLKA_3 + { 0x43, 0x06 }, // GIP_CLKA_4 + { 0x44, 0x11 }, // GIP_CLKA_5 + { 0x45, 0xe8 }, // GIP_CLKA_6 + { 0x46, 0xe9 }, // GIP_CLKA_7 + { 0x47, 0x11 }, // GIP_CLKA_8 + { 0x48, 0xea }, // GIP_CLKA_9 + { 0x49, 0xeb }, // GIP_CLKA_10 + { 0x50, 0x07 }, // GIP_CLKB_1 + { 0x51, 0x08 }, // GIP_CLKB_2 + { 0x52, 0x09 }, // GIP_CLKB_3 + { 0x53, 0x0a }, // GIP_CLKB_4 + { 0x54, 0x11 }, // GIP_CLKB_5 + { 0x55, 0xec }, // GIP_CLKB_6 + { 0x56, 0xed }, // GIP_CLKB_7 + { 0x57, 0x11 }, // GIP_CLKB_8 + { 0x58, 0xef }, // GIP_CLKB_9 + { 0x59, 0xf0 }, // GIP_CLKB_10 + // Map internal GOA signals to GOA output pad + { 0xb1, 0x01 }, // PANELD2U2 + { 0xb4, 0x15 }, // PANELD2U5 + { 0xb5, 0x16 }, // PANELD2U6 + { 0xb6, 0x09 }, // PANELD2U7 + { 0xb7, 0x0f }, // PANELD2U8 + { 0xb8, 0x0d }, // PANELD2U9 + { 0xb9, 0x0b }, // PANELD2U10 + { 0xba, 0x00 }, // PANELD2U11 + { 0xc7, 0x02 }, // PANELD2U24 + { 0xca, 0x17 }, // PANELD2U27 + { 0xcb, 0x18 }, // PANELD2U28 + { 0xcc, 0x0a }, // PANELD2U29 + { 0xcd, 0x10 }, // PANELD2U30 + { 0xce, 0x0e }, // PANELD2U31 + { 0xcf, 0x0c }, // PANELD2U32 + { 0xd0, 0x00 }, // PANELD2U33 + // Map internal GOA signals to GOA output pad + { 0x81, 0x00 }, // PANELU2D2 + { 0x84, 0x15 }, // PANELU2D5 + { 0x85, 0x16 }, // PANELU2D6 + { 0x86, 0x10 }, // PANELU2D7 + { 0x87, 0x0a }, // PANELU2D8 + { 0x88, 0x0c }, // PANELU2D9 + { 0x89, 0x0e }, // PANELU2D10 + { 0x8a, 0x02 }, // PANELU2D11 + { 0x97, 0x00 }, // PANELU2D24 + { 0x9a, 0x17 }, // PANELU2D27 + { 0x9b, 0x18 }, // PANELU2D28 + { 0x9c, 0x0f }, // PANELU2D29 + { 0x9d, 0x09 }, // PANELU2D30 + { 0x9e, 0x0b }, // PANELU2D31 + { 0x9f, 0x0d }, // PANELU2D32 + { 0xa0, 0x01 }, // PANELU2D33 + // EXTC Command set enable, select page 2 + { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x02 }, + // Unknown registers + { 0x01, 0x01 }, + { 0x02, 0xda }, + { 0x03, 0xba }, + { 0x04, 0xa8 }, + { 0x05, 0x9a }, + { 0x06, 0x70 }, + { 0x07, 0xff }, + { 0x08, 0x91 }, + { 0x09, 0x90 }, + { 0x0a, 0xff }, + { 0x0b, 0x8f }, + { 0x0c, 0x60 }, + { 0x0d, 0x58 }, + { 0x0e, 0x48 }, + { 0x0f, 0x38 }, + { 0x10, 0x2b }, + // EXTC Command set enable, select page 0 + { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x00 }, + // Display Access Control + { 0x36, 0x0a }, // bgr = 1, ss = 1, gs = 0 +}; + static inline struct nv3052c *to_nv3052c(struct drm_panel *panel) { return container_of(panel, struct nv3052c, panel); @@ -670,6 +866,21 @@ static const struct drm_display_mode fs035vg158_modes[] = { }, }; +static const struct drm_display_mode wl_355608_a8_mode[] = { + { + .clock = 24000, + .hdisplay = 640, + .hsync_start = 640 + 64, + .hsync_end = 640 + 64 + 20, + .htotal = 640 + 64 + 20 + 46, + .vdisplay = 480, + .vsync_start = 480 + 21, + .vsync_end = 480 + 21 + 4, + .vtotal = 480 + 21 + 4 + 15, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, + }, +}; + static const struct nv3052c_panel_info ltk035c5444t_panel_info = { .display_modes = ltk035c5444t_modes, .num_modes = ARRAY_SIZE(ltk035c5444t_modes), @@ -692,9 +903,21 @@ static const struct nv3052c_panel_info fs035vg158_panel_info = { .panel_regs_len = ARRAY_SIZE(fs035vg158_panel_regs), }; +static const struct nv3052c_panel_info wl_355608_a8_panel_info = { + .display_modes = wl_355608_a8_mode, + .num_modes = ARRAY_SIZE(wl_355608_a8_mode), + .width_mm = 150, + .height_mm = 94, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE, + .panel_regs = wl_355608_a8_panel_regs, + .panel_regs_len = ARRAY_SIZE(wl_355608_a8_panel_regs), +}; + static const struct spi_device_id nv3052c_ids[] = { { "ltk035c5444t", }, { "fs035vg158", }, + { "wl-355608-a8", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(spi, nv3052c_ids); @@ -702,6 +925,7 @@ MODULE_DEVICE_TABLE(spi, nv3052c_ids); static const struct of_device_id nv3052c_of_match[] = { { .compatible = "leadtek,ltk035c5444t", .data = <k035c5444t_panel_info }, { .compatible = "fascontek,fs035vg158", .data = &fs035vg158_panel_info }, + { .compatible = "wl-355608-a8", .data = &wl_355608_a8_panel_info }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, nv3052c_of_match); @@ -719,4 +943,6 @@ module_spi_driver(nv3052c_driver); MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>"); +MODULE_AUTHOR("Ryan Walklin <ryan@testtoast.com"); +MODULE_DESCRIPTION("NewVision NV3052C IPS LCD panel driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c index 3886372415c2..c2abd20e0734 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c @@ -72,8 +72,6 @@ struct nt36672a_panel { struct regulator_bulk_data supplies[ARRAY_SIZE(nt36672a_regulator_names)]; struct gpio_desc *reset_gpio; - - bool prepared; }; static inline struct nt36672a_panel *to_nt36672a_panel(struct drm_panel *panel) @@ -119,9 +117,6 @@ static int nt36672a_panel_unprepare(struct drm_panel *panel) struct nt36672a_panel *pinfo = to_nt36672a_panel(panel); int ret; - if (!pinfo->prepared) - return 0; - /* send off cmds */ ret = nt36672a_send_cmds(panel, pinfo->desc->off_cmds, pinfo->desc->num_off_cmds); @@ -147,8 +142,6 @@ static int nt36672a_panel_unprepare(struct drm_panel *panel) if (ret < 0) dev_err(panel->dev, "power_off failed ret = %d\n", ret); - pinfo->prepared = false; - return ret; } @@ -179,9 +172,6 @@ static int nt36672a_panel_prepare(struct drm_panel *panel) struct nt36672a_panel *pinfo = to_nt36672a_panel(panel); int err; - if (pinfo->prepared) - return 0; - err = nt36672a_panel_power_on(pinfo); if (err < 0) goto poweroff; @@ -221,8 +211,6 @@ static int nt36672a_panel_prepare(struct drm_panel *panel) msleep(120); - pinfo->prepared = true; - return 0; poweroff: @@ -668,14 +656,6 @@ static void nt36672a_panel_remove(struct mipi_dsi_device *dsi) struct nt36672a_panel *pinfo = mipi_dsi_get_drvdata(dsi); int err; - err = drm_panel_unprepare(&pinfo->base); - if (err < 0) - dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err); - - err = drm_panel_disable(&pinfo->base); - if (err < 0) - dev_err(&dsi->dev, "failed to disable panel: %d\n", err); - err = mipi_dsi_detach(dsi); if (err < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); @@ -683,14 +663,6 @@ static void nt36672a_panel_remove(struct mipi_dsi_device *dsi) drm_panel_remove(&pinfo->base); } -static void nt36672a_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct nt36672a_panel *pinfo = mipi_dsi_get_drvdata(dsi); - - drm_panel_disable(&pinfo->base); - drm_panel_unprepare(&pinfo->base); -} - static const struct of_device_id tianma_fhd_video_of_match[] = { { .compatible = "tianma,fhd-video", .data = &tianma_fhd_video_panel_desc }, { }, @@ -704,7 +676,6 @@ static struct mipi_dsi_driver nt36672a_panel_driver = { }, .probe = nt36672a_panel_probe, .remove = nt36672a_panel_remove, - .shutdown = nt36672a_panel_shutdown, }; module_mipi_dsi_driver(nt36672a_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c index 20b7bfe4aa12..e81a70147259 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c @@ -33,7 +33,7 @@ struct panel_desc { enum mipi_dsi_pixel_format format; unsigned int lanes; const char *panel_name; - int (*init_sequence)(struct mipi_dsi_device *dsi); + void (*init_sequence)(struct mipi_dsi_multi_context *ctx); }; struct nt36672e_panel { @@ -49,295 +49,293 @@ static inline struct nt36672e_panel *to_nt36672e_panel(struct drm_panel *panel) return container_of(panel, struct nt36672e_panel, panel); } -static int nt36672e_1080x2408_60hz_init(struct mipi_dsi_device *dsi) +static void nt36672e_1080x2408_60hz_init(struct mipi_dsi_multi_context *ctx) { - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 0x02, - 0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 0xb7); - - mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x1b, 0xa0); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x01, 0x66); - mipi_dsi_dcs_write_seq(dsi, 0x06, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0x07, 0x38); - mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x83); - mipi_dsi_dcs_write_seq(dsi, 0x69, 0x91); - mipi_dsi_dcs_write_seq(dsi, 0x95, 0xd1); - mipi_dsi_dcs_write_seq(dsi, 0x96, 0xd1); - mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x64); - mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x54); - mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x64); - mipi_dsi_dcs_write_seq(dsi, 0xf5, 0x54); - mipi_dsi_dcs_write_seq(dsi, 0xf6, 0x64); - mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x54); - mipi_dsi_dcs_write_seq(dsi, 0xf8, 0x64); - mipi_dsi_dcs_write_seq(dsi, 0xf9, 0x54); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x01, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x03, 0x0c); - mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d); - mipi_dsi_dcs_write_seq(dsi, 0x08, 0x2f); - mipi_dsi_dcs_write_seq(dsi, 0x09, 0x2e); - mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x2d); - mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x2c); - mipi_dsi_dcs_write_seq(dsi, 0x11, 0x17); - mipi_dsi_dcs_write_seq(dsi, 0x12, 0x13); - mipi_dsi_dcs_write_seq(dsi, 0x13, 0x15); - mipi_dsi_dcs_write_seq(dsi, 0x15, 0x14); - mipi_dsi_dcs_write_seq(dsi, 0x16, 0x16); - mipi_dsi_dcs_write_seq(dsi, 0x17, 0x18); - mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x1d); - mipi_dsi_dcs_write_seq(dsi, 0x20, 0x2f); - mipi_dsi_dcs_write_seq(dsi, 0x21, 0x2e); - mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2d); - mipi_dsi_dcs_write_seq(dsi, 0x23, 0x2c); - mipi_dsi_dcs_write_seq(dsi, 0x29, 0x17); - mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x13); - mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x15); - mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x14); - mipi_dsi_dcs_write_seq(dsi, 0x30, 0x16); - mipi_dsi_dcs_write_seq(dsi, 0x31, 0x18); - mipi_dsi_dcs_write_seq(dsi, 0x32, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x34, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0x35, 0x1f); - mipi_dsi_dcs_write_seq(dsi, 0x36, 0x1f); - mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x14); - mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x36); - mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x36); - mipi_dsi_dcs_write_seq(dsi, 0x53, 0x36); - mipi_dsi_dcs_write_seq(dsi, 0x71, 0x30); - mipi_dsi_dcs_write_seq(dsi, 0x79, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x82); - mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x8f); - mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x80, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x81, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x82, 0x13); - mipi_dsi_dcs_write_seq(dsi, 0x84, 0x31); - mipi_dsi_dcs_write_seq(dsi, 0x85, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x86, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x87, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x90, 0x13); - mipi_dsi_dcs_write_seq(dsi, 0x92, 0x31); - mipi_dsi_dcs_write_seq(dsi, 0x93, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x94, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x95, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x9c, 0xf4); - mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xa0, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0xa2, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0xa3, 0x02); - mipi_dsi_dcs_write_seq(dsi, 0xa4, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0xc6, 0xc0); - mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xd9, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0xe9, 0x02); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x18, 0x22); - mipi_dsi_dcs_write_seq(dsi, 0x19, 0xe4); - mipi_dsi_dcs_write_seq(dsi, 0x21, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0x66, 0xd8); - mipi_dsi_dcs_write_seq(dsi, 0x68, 0x50); - mipi_dsi_dcs_write_seq(dsi, 0x69, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x0d); - mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x48); - mipi_dsi_dcs_write_seq(dsi, 0x72, 0x41); - mipi_dsi_dcs_write_seq(dsi, 0x73, 0x4a); - mipi_dsi_dcs_write_seq(dsi, 0x74, 0xd0); - mipi_dsi_dcs_write_seq(dsi, 0x77, 0x62); - mipi_dsi_dcs_write_seq(dsi, 0x79, 0x7e); - mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x03); - mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x15); - mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x84, 0x4d); - mipi_dsi_dcs_write_seq(dsi, 0xcf, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0xef, 0x20); - mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x84); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x81, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x83, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x84, 0x03); - mipi_dsi_dcs_write_seq(dsi, 0x85, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x86, 0x03); - mipi_dsi_dcs_write_seq(dsi, 0x87, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x88, 0x05); - mipi_dsi_dcs_write_seq(dsi, 0x8a, 0x1a); - mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x24); - mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x42); - mipi_dsi_dcs_write_seq(dsi, 0x8f, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0x90, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0x91, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0x9a, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0x9b, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x9c, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x9e, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x27); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x01, 0x68); - mipi_dsi_dcs_write_seq(dsi, 0x20, 0x81); - mipi_dsi_dcs_write_seq(dsi, 0x21, 0x6a); - mipi_dsi_dcs_write_seq(dsi, 0x25, 0x81); - mipi_dsi_dcs_write_seq(dsi, 0x26, 0x94); - mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x6f, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x70, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x71, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x72, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x75, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x76, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x77, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x09); - mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x67); - mipi_dsi_dcs_write_seq(dsi, 0x80, 0x23); - mipi_dsi_dcs_write_seq(dsi, 0x82, 0x09); - mipi_dsi_dcs_write_seq(dsi, 0x83, 0x67); - mipi_dsi_dcs_write_seq(dsi, 0x88, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x89, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0xa6, 0x23); - mipi_dsi_dcs_write_seq(dsi, 0xa7, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x02); - mipi_dsi_dcs_write_seq(dsi, 0xe6, 0xd3); - mipi_dsi_dcs_write_seq(dsi, 0xeb, 0x03); - mipi_dsi_dcs_write_seq(dsi, 0xec, 0x28); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x00, 0x91); - mipi_dsi_dcs_write_seq(dsi, 0x03, 0x20); - mipi_dsi_dcs_write_seq(dsi, 0x07, 0x50); - mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x70); - mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x11, 0xe0); - mipi_dsi_dcs_write_seq(dsi, 0x15, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x16, 0xa4); - mipi_dsi_dcs_write_seq(dsi, 0x19, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x78); - mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x23); - mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x36); - mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x3e); - mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x3e); - mipi_dsi_dcs_write_seq(dsi, 0x20, 0x3e); - mipi_dsi_dcs_write_seq(dsi, 0x28, 0xfd); - mipi_dsi_dcs_write_seq(dsi, 0x29, 0x12); - mipi_dsi_dcs_write_seq(dsi, 0x2a, 0xe1); - mipi_dsi_dcs_write_seq(dsi, 0x2d, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0x30, 0x49); - mipi_dsi_dcs_write_seq(dsi, 0x33, 0x96); - mipi_dsi_dcs_write_seq(dsi, 0x34, 0xff); - mipi_dsi_dcs_write_seq(dsi, 0x35, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0x36, 0xde); - mipi_dsi_dcs_write_seq(dsi, 0x37, 0xf9); - mipi_dsi_dcs_write_seq(dsi, 0x38, 0x45); - mipi_dsi_dcs_write_seq(dsi, 0x39, 0xd9); - mipi_dsi_dcs_write_seq(dsi, 0x3a, 0x49); - mipi_dsi_dcs_write_seq(dsi, 0x4a, 0xf0); - mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x09); - mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0x7f, 0xf0); - mipi_dsi_dcs_write_seq(dsi, 0x83, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x84, 0xa4); - mipi_dsi_dcs_write_seq(dsi, 0x87, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x88, 0x78); - mipi_dsi_dcs_write_seq(dsi, 0x89, 0x23); - mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x36); - mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x7d); - mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x7d); - mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x7d); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00, - 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8); - mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01, - 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e); - mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03, - 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); - mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, - 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, - 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1); - mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01, - 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36); - mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03, - 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b); - mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03, - 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, - 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1); - mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01, - 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31); - mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03, - 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); - mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, - 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x21); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00, - 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8); - mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01, - 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e); - mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03, - 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); - mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, - 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, - 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1); - mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01, - 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36); - mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03, - 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b); - mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03, - 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, - 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1); - mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01, - 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31); - mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03, - 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); - mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, - 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2c); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x61, 0x1f); - mipi_dsi_dcs_write_seq(dsi, 0x62, 0x1f); - mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x03); - mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x14); - mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x36); - mipi_dsi_dcs_write_seq(dsi, 0x6c, 0x36); - mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x36); - mipi_dsi_dcs_write_seq(dsi, 0x53, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x54, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x55, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0x56, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x58, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0x59, 0x0f); - mipi_dsi_dcs_write_seq(dsi, 0xff, 0xf0); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x00); - - mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); - mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0x51, 0xff); - mipi_dsi_dcs_write_seq(dsi, 0x53, 0x24); - mipi_dsi_dcs_write_seq(dsi, 0x55, 0x01); - - return 0; + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x10); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0xc0, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 0x02, + 0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 0xb7); + + mipi_dsi_dcs_write_seq_multi(ctx, 0xc2, 0x1b, 0xa0); + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x20); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x66); + mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x40); + mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x38); + mipi_dsi_dcs_write_seq_multi(ctx, 0x2f, 0x83); + mipi_dsi_dcs_write_seq_multi(ctx, 0x69, 0x91); + mipi_dsi_dcs_write_seq_multi(ctx, 0x95, 0xd1); + mipi_dsi_dcs_write_seq_multi(ctx, 0x96, 0xd1); + mipi_dsi_dcs_write_seq_multi(ctx, 0xf2, 0x64); + mipi_dsi_dcs_write_seq_multi(ctx, 0xf3, 0x54); + mipi_dsi_dcs_write_seq_multi(ctx, 0xf4, 0x64); + mipi_dsi_dcs_write_seq_multi(ctx, 0xf5, 0x54); + mipi_dsi_dcs_write_seq_multi(ctx, 0xf6, 0x64); + mipi_dsi_dcs_write_seq_multi(ctx, 0xf7, 0x54); + mipi_dsi_dcs_write_seq_multi(ctx, 0xf8, 0x64); + mipi_dsi_dcs_write_seq_multi(ctx, 0xf9, 0x54); + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x24); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x0c); + mipi_dsi_dcs_write_seq_multi(ctx, 0x05, 0x1d); + mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x2f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x09, 0x2e); + mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x2d); + mipi_dsi_dcs_write_seq_multi(ctx, 0x0b, 0x2c); + mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0x17); + mipi_dsi_dcs_write_seq_multi(ctx, 0x12, 0x13); + mipi_dsi_dcs_write_seq_multi(ctx, 0x13, 0x15); + mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x14); + mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0x16); + mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x18); + mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x1d); + mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x2f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x2e); + mipi_dsi_dcs_write_seq_multi(ctx, 0x22, 0x2d); + mipi_dsi_dcs_write_seq_multi(ctx, 0x23, 0x2c); + mipi_dsi_dcs_write_seq_multi(ctx, 0x29, 0x17); + mipi_dsi_dcs_write_seq_multi(ctx, 0x2a, 0x13); + mipi_dsi_dcs_write_seq_multi(ctx, 0x2b, 0x15); + mipi_dsi_dcs_write_seq_multi(ctx, 0x2f, 0x14); + mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x16); + mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x18); + mipi_dsi_dcs_write_seq_multi(ctx, 0x32, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0x10); + mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0x1f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0x1f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x4d, 0x14); + mipi_dsi_dcs_write_seq_multi(ctx, 0x4e, 0x36); + mipi_dsi_dcs_write_seq_multi(ctx, 0x4f, 0x36); + mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x36); + mipi_dsi_dcs_write_seq_multi(ctx, 0x71, 0x30); + mipi_dsi_dcs_write_seq_multi(ctx, 0x79, 0x11); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7a, 0x82); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7b, 0x8f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0x80, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0x81, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0x82, 0x13); + mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x31); + mipi_dsi_dcs_write_seq_multi(ctx, 0x85, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x86, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x90, 0x13); + mipi_dsi_dcs_write_seq_multi(ctx, 0x92, 0x31); + mipi_dsi_dcs_write_seq_multi(ctx, 0x93, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x94, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x95, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x9c, 0xf4); + mipi_dsi_dcs_write_seq_multi(ctx, 0x9d, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0xa0, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0xa2, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0xa3, 0x02); + mipi_dsi_dcs_write_seq_multi(ctx, 0xa4, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0xc6, 0xc0); + mipi_dsi_dcs_write_seq_multi(ctx, 0xc9, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0xd9, 0x80); + mipi_dsi_dcs_write_seq_multi(ctx, 0xe9, 0x02); + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x25); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x22); + mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0xe4); + mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x40); + mipi_dsi_dcs_write_seq_multi(ctx, 0x66, 0xd8); + mipi_dsi_dcs_write_seq_multi(ctx, 0x68, 0x50); + mipi_dsi_dcs_write_seq_multi(ctx, 0x69, 0x10); + mipi_dsi_dcs_write_seq_multi(ctx, 0x6b, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x6d, 0x0d); + mipi_dsi_dcs_write_seq_multi(ctx, 0x6e, 0x48); + mipi_dsi_dcs_write_seq_multi(ctx, 0x72, 0x41); + mipi_dsi_dcs_write_seq_multi(ctx, 0x73, 0x4a); + mipi_dsi_dcs_write_seq_multi(ctx, 0x74, 0xd0); + mipi_dsi_dcs_write_seq_multi(ctx, 0x77, 0x62); + mipi_dsi_dcs_write_seq_multi(ctx, 0x79, 0x7e); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x03); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x15); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7f, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x4d); + mipi_dsi_dcs_write_seq_multi(ctx, 0xcf, 0x80); + mipi_dsi_dcs_write_seq_multi(ctx, 0xd6, 0x80); + mipi_dsi_dcs_write_seq_multi(ctx, 0xd7, 0x80); + mipi_dsi_dcs_write_seq_multi(ctx, 0xef, 0x20); + mipi_dsi_dcs_write_seq_multi(ctx, 0xf0, 0x84); + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x26); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x81, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0x03); + mipi_dsi_dcs_write_seq_multi(ctx, 0x85, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x86, 0x03); + mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x05); + mipi_dsi_dcs_write_seq_multi(ctx, 0x8a, 0x1a); + mipi_dsi_dcs_write_seq_multi(ctx, 0x8b, 0x11); + mipi_dsi_dcs_write_seq_multi(ctx, 0x8c, 0x24); + mipi_dsi_dcs_write_seq_multi(ctx, 0x8e, 0x42); + mipi_dsi_dcs_write_seq_multi(ctx, 0x8f, 0x11); + mipi_dsi_dcs_write_seq_multi(ctx, 0x90, 0x11); + mipi_dsi_dcs_write_seq_multi(ctx, 0x91, 0x11); + mipi_dsi_dcs_write_seq_multi(ctx, 0x9a, 0x80); + mipi_dsi_dcs_write_seq_multi(ctx, 0x9b, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0x9c, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x9d, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x9e, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x27); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x68); + mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x81); + mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x6a); + mipi_dsi_dcs_write_seq_multi(ctx, 0x25, 0x81); + mipi_dsi_dcs_write_seq_multi(ctx, 0x26, 0x94); + mipi_dsi_dcs_write_seq_multi(ctx, 0x6e, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x6f, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x70, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x71, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x72, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x75, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x76, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x77, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7d, 0x09); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x67); + mipi_dsi_dcs_write_seq_multi(ctx, 0x80, 0x23); + mipi_dsi_dcs_write_seq_multi(ctx, 0x82, 0x09); + mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x67); + mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x89, 0x10); + mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x10); + mipi_dsi_dcs_write_seq_multi(ctx, 0xa6, 0x23); + mipi_dsi_dcs_write_seq_multi(ctx, 0xa7, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x40); + mipi_dsi_dcs_write_seq_multi(ctx, 0xe5, 0x02); + mipi_dsi_dcs_write_seq_multi(ctx, 0xe6, 0xd3); + mipi_dsi_dcs_write_seq_multi(ctx, 0xeb, 0x03); + mipi_dsi_dcs_write_seq_multi(ctx, 0xec, 0x28); + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x2a); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x00, 0x91); + mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x20); + mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x50); + mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x70); + mipi_dsi_dcs_write_seq_multi(ctx, 0x0c, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0x0d, 0x40); + mipi_dsi_dcs_write_seq_multi(ctx, 0x0f, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0xe0); + mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0xa4); + mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x1a, 0x78); + mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x23); + mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x36); + mipi_dsi_dcs_write_seq_multi(ctx, 0x1e, 0x3e); + mipi_dsi_dcs_write_seq_multi(ctx, 0x1f, 0x3e); + mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x3e); + mipi_dsi_dcs_write_seq_multi(ctx, 0x28, 0xfd); + mipi_dsi_dcs_write_seq_multi(ctx, 0x29, 0x12); + mipi_dsi_dcs_write_seq_multi(ctx, 0x2a, 0xe1); + mipi_dsi_dcs_write_seq_multi(ctx, 0x2d, 0x0a); + mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x49); + mipi_dsi_dcs_write_seq_multi(ctx, 0x33, 0x96); + mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0xff); + mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0x40); + mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0xde); + mipi_dsi_dcs_write_seq_multi(ctx, 0x37, 0xf9); + mipi_dsi_dcs_write_seq_multi(ctx, 0x38, 0x45); + mipi_dsi_dcs_write_seq_multi(ctx, 0x39, 0xd9); + mipi_dsi_dcs_write_seq_multi(ctx, 0x3a, 0x49); + mipi_dsi_dcs_write_seq_multi(ctx, 0x4a, 0xf0); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7a, 0x09); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7b, 0x40); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7f, 0xf0); + mipi_dsi_dcs_write_seq_multi(ctx, 0x83, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x84, 0xa4); + mipi_dsi_dcs_write_seq_multi(ctx, 0x87, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x88, 0x78); + mipi_dsi_dcs_write_seq_multi(ctx, 0x89, 0x23); + mipi_dsi_dcs_write_seq_multi(ctx, 0x8b, 0x36); + mipi_dsi_dcs_write_seq_multi(ctx, 0x8c, 0x7d); + mipi_dsi_dcs_write_seq_multi(ctx, 0x8d, 0x7d); + mipi_dsi_dcs_write_seq_multi(ctx, 0x8e, 0x7d); + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x20); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00, + 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01, + 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03, + 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, + 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, + 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01, + 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03, + 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03, + 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, + 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01, + 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(ctx, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03, + 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); + mipi_dsi_dcs_write_seq_multi(ctx, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, + 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x21); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00, + 0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01, + 0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03, + 0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, + 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, + 0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01, + 0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03, + 0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03, + 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00, + 0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1); + mipi_dsi_dcs_write_seq_multi(ctx, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01, + 0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq_multi(ctx, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03, + 0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a); + mipi_dsi_dcs_write_seq_multi(ctx, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03, + 0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x2c); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x61, 0x1f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x62, 0x1f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x7e, 0x03); + mipi_dsi_dcs_write_seq_multi(ctx, 0x6a, 0x14); + mipi_dsi_dcs_write_seq_multi(ctx, 0x6b, 0x36); + mipi_dsi_dcs_write_seq_multi(ctx, 0x6c, 0x36); + mipi_dsi_dcs_write_seq_multi(ctx, 0x6d, 0x36); + mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0x54, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0x55, 0x04); + mipi_dsi_dcs_write_seq_multi(ctx, 0x56, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x58, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0x59, 0x0f); + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xf0); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x5a, 0x00); + + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0x10); + mipi_dsi_dcs_write_seq_multi(ctx, 0xfb, 0x01); + mipi_dsi_dcs_write_seq_multi(ctx, 0x51, 0xff); + mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x24); + mipi_dsi_dcs_write_seq_multi(ctx, 0x55, 0x01); } static int nt36672e_power_on(struct nt36672e_panel *ctx) @@ -379,68 +377,46 @@ static int nt36672e_power_off(struct nt36672e_panel *ctx) return ret; } -static int nt36672e_on(struct nt36672e_panel *ctx) +static int nt36672e_on(struct nt36672e_panel *nt36672e) { - struct mipi_dsi_device *dsi = ctx->dsi; - const struct panel_desc *desc = ctx->desc; - int ret = 0; + struct mipi_dsi_multi_context ctx = { .dsi = nt36672e->dsi }; + const struct panel_desc *desc = nt36672e->desc; - dsi->mode_flags |= MIPI_DSI_MODE_LPM; + nt36672e->dsi->mode_flags |= MIPI_DSI_MODE_LPM; - if (desc->init_sequence) { - ret = desc->init_sequence(dsi); - if (ret < 0) { - dev_err(&dsi->dev, "panel init sequence failed: %d\n", ret); - return ret; - } - } + if (desc->init_sequence) + desc->init_sequence(&ctx); - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(&dsi->dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(120); + mipi_dsi_dcs_exit_sleep_mode_multi(&ctx); + mipi_dsi_msleep(&ctx, 120); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(&dsi->dev, "Failed to set display on: %d\n", ret); - return ret; - } - msleep(100); + mipi_dsi_dcs_set_display_on_multi(&ctx); - return 0; + mipi_dsi_msleep(&ctx, 100); + + return ctx.accum_err; } -static int nt36672e_off(struct nt36672e_panel *ctx) +static int nt36672e_off(struct nt36672e_panel *panel) { - struct mipi_dsi_device *dsi = ctx->dsi; - int ret = 0; + struct mipi_dsi_multi_context ctx = { .dsi = panel->dsi }; - dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + panel->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(&dsi->dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(20); + mipi_dsi_dcs_set_display_off_multi(&ctx); + mipi_dsi_msleep(&ctx, 20); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(&dsi->dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(60); + mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); + mipi_dsi_msleep(&ctx, 60); - return 0; + return ctx.accum_err; } static int nt36672e_panel_prepare(struct drm_panel *panel) { struct nt36672e_panel *ctx = to_nt36672e_panel(panel); struct mipi_dsi_device *dsi = ctx->dsi; - int ret = 0; + int ret; ret = nt36672e_power_on(ctx); if (ret < 0) @@ -448,7 +424,6 @@ static int nt36672e_panel_prepare(struct drm_panel *panel) ret = nt36672e_on(ctx); if (ret < 0) { - dev_err(&dsi->dev, "Failed to initialize panel: %d\n", ret); if (nt36672e_power_off(ctx)) dev_err(&dsi->dev, "power off failed\n"); return ret; @@ -461,11 +436,9 @@ static int nt36672e_panel_unprepare(struct drm_panel *panel) { struct nt36672e_panel *ctx = to_nt36672e_panel(panel); struct mipi_dsi_device *dsi = ctx->dsi; - int ret = 0; + int ret; - ret = nt36672e_off(ctx); - if (ret < 0) - dev_err(&dsi->dev, "Failed to un-initialize panel: %d\n", ret); + nt36672e_off(ctx); ret = nt36672e_power_off(ctx); if (ret < 0) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c index 059260262b5a..9fa7654e2b67 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -356,4 +356,5 @@ module_spi_driver(nt39016_driver); MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>"); MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); +MODULE_DESCRIPTION("Novatek NT39016 TFT LCD panel driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c index 4819ada69482..94ae8c8270b8 100644 --- a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c +++ b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c @@ -64,9 +64,6 @@ struct lcd_olinuxino { struct i2c_client *client; struct mutex mutex; - bool prepared; - bool enabled; - struct regulator *supply; struct gpio_desc *enable_gpio; @@ -78,30 +75,13 @@ static inline struct lcd_olinuxino *to_lcd_olinuxino(struct drm_panel *panel) return container_of(panel, struct lcd_olinuxino, panel); } -static int lcd_olinuxino_disable(struct drm_panel *panel) -{ - struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel); - - if (!lcd->enabled) - return 0; - - lcd->enabled = false; - - return 0; -} - static int lcd_olinuxino_unprepare(struct drm_panel *panel) { struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel); - if (!lcd->prepared) - return 0; - gpiod_set_value_cansleep(lcd->enable_gpio, 0); regulator_disable(lcd->supply); - lcd->prepared = false; - return 0; } @@ -110,27 +90,11 @@ static int lcd_olinuxino_prepare(struct drm_panel *panel) struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel); int ret; - if (lcd->prepared) - return 0; - ret = regulator_enable(lcd->supply); if (ret < 0) return ret; gpiod_set_value_cansleep(lcd->enable_gpio, 1); - lcd->prepared = true; - - return 0; -} - -static int lcd_olinuxino_enable(struct drm_panel *panel) -{ - struct lcd_olinuxino *lcd = to_lcd_olinuxino(panel); - - if (lcd->enabled) - return 0; - - lcd->enabled = true; return 0; } @@ -195,10 +159,8 @@ static int lcd_olinuxino_get_modes(struct drm_panel *panel, } static const struct drm_panel_funcs lcd_olinuxino_funcs = { - .disable = lcd_olinuxino_disable, .unprepare = lcd_olinuxino_unprepare, .prepare = lcd_olinuxino_prepare, - .enable = lcd_olinuxino_enable, .get_modes = lcd_olinuxino_get_modes, }; @@ -264,9 +226,6 @@ static int lcd_olinuxino_probe(struct i2c_client *client) lcd->eeprom.num_modes = 4; } - lcd->enabled = false; - lcd->prepared = false; - lcd->supply = devm_regulator_get(dev, "power"); if (IS_ERR(lcd->supply)) return PTR_ERR(lcd->supply); @@ -292,9 +251,6 @@ static void lcd_olinuxino_remove(struct i2c_client *client) struct lcd_olinuxino *panel = i2c_get_clientdata(client); drm_panel_remove(&panel->panel); - - drm_panel_disable(&panel->panel); - drm_panel_unprepare(&panel->panel); } static const struct of_device_id lcd_olinuxino_of_ids[] = { diff --git a/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c b/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c index c415dacf1816..fc87f61d4400 100644 --- a/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c +++ b/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c @@ -360,4 +360,5 @@ static struct spi_driver ota5601a_driver = { module_spi_driver(ota5601a_driver); MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>"); +MODULE_DESCRIPTION("Orisetech OTA5601A TFT LCD panel driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c index 493e0504f6f7..dbea84f51514 100644 --- a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c +++ b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c @@ -21,9 +21,6 @@ struct osd101t2587_panel { struct regulator *supply; - bool prepared; - bool enabled; - const struct drm_display_mode *default_mode; }; @@ -37,13 +34,8 @@ static int osd101t2587_panel_disable(struct drm_panel *panel) struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel); int ret; - if (!osd101t2587->enabled) - return 0; - ret = mipi_dsi_shutdown_peripheral(osd101t2587->dsi); - osd101t2587->enabled = false; - return ret; } @@ -51,11 +43,7 @@ static int osd101t2587_panel_unprepare(struct drm_panel *panel) { struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel); - if (!osd101t2587->prepared) - return 0; - regulator_disable(osd101t2587->supply); - osd101t2587->prepared = false; return 0; } @@ -63,16 +51,8 @@ static int osd101t2587_panel_unprepare(struct drm_panel *panel) static int osd101t2587_panel_prepare(struct drm_panel *panel) { struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel); - int ret; - if (osd101t2587->prepared) - return 0; - - ret = regulator_enable(osd101t2587->supply); - if (!ret) - osd101t2587->prepared = true; - - return ret; + return regulator_enable(osd101t2587->supply); } static int osd101t2587_panel_enable(struct drm_panel *panel) @@ -80,15 +60,10 @@ static int osd101t2587_panel_enable(struct drm_panel *panel) struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel); int ret; - if (osd101t2587->enabled) - return 0; - ret = mipi_dsi_turn_on_peripheral(osd101t2587->dsi); if (ret) return ret; - osd101t2587->enabled = true; - return ret; } @@ -211,11 +186,6 @@ static void osd101t2587_panel_remove(struct mipi_dsi_device *dsi) struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi); int ret; - ret = drm_panel_disable(&osd101t2587->base); - if (ret < 0) - dev_warn(&dsi->dev, "failed to disable panel: %d\n", ret); - - drm_panel_unprepare(&osd101t2587->base); drm_panel_remove(&osd101t2587->base); ret = mipi_dsi_detach(dsi); @@ -223,14 +193,6 @@ static void osd101t2587_panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); } -static void osd101t2587_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi); - - drm_panel_disable(&osd101t2587->base); - drm_panel_unprepare(&osd101t2587->base); -} - static struct mipi_dsi_driver osd101t2587_panel_driver = { .driver = { .name = "panel-osd-osd101t2587-53ts", @@ -238,7 +200,6 @@ static struct mipi_dsi_driver osd101t2587_panel_driver = { }, .probe = osd101t2587_panel_probe, .remove = osd101t2587_panel_remove, - .shutdown = osd101t2587_panel_shutdown, }; module_mipi_dsi_driver(osd101t2587_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c index 8ba6d8287938..d1c5c9bc3c56 100644 --- a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c +++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c @@ -32,9 +32,6 @@ struct wuxga_nt_panel { struct regulator *supply; - bool prepared; - bool enabled; - ktime_t earliest_wake; const struct drm_display_mode *mode; @@ -53,28 +50,16 @@ static int wuxga_nt_panel_on(struct wuxga_nt_panel *wuxga_nt) static int wuxga_nt_panel_disable(struct drm_panel *panel) { struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); - int mipi_ret, bl_ret = 0; - - if (!wuxga_nt->enabled) - return 0; - - mipi_ret = mipi_dsi_shutdown_peripheral(wuxga_nt->dsi); - wuxga_nt->enabled = false; - - return mipi_ret ? mipi_ret : bl_ret; + return mipi_dsi_shutdown_peripheral(wuxga_nt->dsi); } static int wuxga_nt_panel_unprepare(struct drm_panel *panel) { struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); - if (!wuxga_nt->prepared) - return 0; - regulator_disable(wuxga_nt->supply); wuxga_nt->earliest_wake = ktime_add_ms(ktime_get_real(), MIN_POFF_MS); - wuxga_nt->prepared = false; return 0; } @@ -85,9 +70,6 @@ static int wuxga_nt_panel_prepare(struct drm_panel *panel) int ret; s64 enablewait; - if (wuxga_nt->prepared) - return 0; - /* * If the user re-enabled the panel before the required off-time then * we need to wait the remaining period before re-enabling regulator @@ -117,8 +99,6 @@ static int wuxga_nt_panel_prepare(struct drm_panel *panel) goto poweroff; } - wuxga_nt->prepared = true; - return 0; poweroff: @@ -127,18 +107,6 @@ poweroff: return ret; } -static int wuxga_nt_panel_enable(struct drm_panel *panel) -{ - struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); - - if (wuxga_nt->enabled) - return 0; - - wuxga_nt->enabled = true; - - return 0; -} - static const struct drm_display_mode default_mode = { .clock = 164402, .hdisplay = 1920, @@ -178,7 +146,6 @@ static const struct drm_panel_funcs wuxga_nt_panel_funcs = { .disable = wuxga_nt_panel_disable, .unprepare = wuxga_nt_panel_unprepare, .prepare = wuxga_nt_panel_prepare, - .enable = wuxga_nt_panel_enable, .get_modes = wuxga_nt_panel_get_modes, }; @@ -255,10 +222,6 @@ static void wuxga_nt_panel_remove(struct mipi_dsi_device *dsi) struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi); int ret; - ret = drm_panel_disable(&wuxga_nt->base); - if (ret < 0) - dev_err(&dsi->dev, "failed to disable panel: %d\n", ret); - ret = mipi_dsi_detach(dsi); if (ret < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); @@ -266,13 +229,6 @@ static void wuxga_nt_panel_remove(struct mipi_dsi_device *dsi) wuxga_nt_panel_del(wuxga_nt); } -static void wuxga_nt_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi); - - drm_panel_disable(&wuxga_nt->base); -} - static struct mipi_dsi_driver wuxga_nt_panel_driver = { .driver = { .name = "panel-panasonic-vvx10f034n00", @@ -280,7 +236,6 @@ static struct mipi_dsi_driver wuxga_nt_panel_driver = { }, .probe = wuxga_nt_panel_probe, .remove = wuxga_nt_panel_remove, - .shutdown = wuxga_nt_panel_shutdown, }; module_mipi_dsi_driver(wuxga_nt_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c b/drivers/gpu/drm/panel/panel-raydium-rm67191.c index dbb1ed4efbed..b2029e035635 100644 --- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c +++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c @@ -205,7 +205,6 @@ struct rad_panel { unsigned int num_supplies; bool prepared; - bool enabled; }; static const struct drm_display_mode default_mode = { @@ -267,9 +266,6 @@ static int rad_panel_prepare(struct drm_panel *panel) struct rad_panel *rad = to_rad_panel(panel); int ret; - if (rad->prepared) - return 0; - ret = regulator_bulk_enable(rad->num_supplies, rad->supplies); if (ret) return ret; @@ -291,9 +287,6 @@ static int rad_panel_unprepare(struct drm_panel *panel) struct rad_panel *rad = to_rad_panel(panel); int ret; - if (!rad->prepared) - return 0; - /* * Right after asserting the reset, we need to release it, so that the * touch driver can have an active connection with the touch controller @@ -322,9 +315,6 @@ static int rad_panel_enable(struct drm_panel *panel) int color_format = color_format_from_dsi_format(dsi->format); int ret; - if (rad->enabled) - return 0; - dsi->mode_flags |= MIPI_DSI_MODE_LPM; ret = rad_panel_push_cmd_list(dsi); @@ -389,8 +379,6 @@ static int rad_panel_enable(struct drm_panel *panel) backlight_enable(rad->backlight); - rad->enabled = true; - return 0; fail: @@ -406,9 +394,6 @@ static int rad_panel_disable(struct drm_panel *panel) struct device *dev = &dsi->dev; int ret; - if (!rad->enabled) - return 0; - dsi->mode_flags |= MIPI_DSI_MODE_LPM; backlight_disable(rad->backlight); @@ -429,8 +414,6 @@ static int rad_panel_disable(struct drm_panel *panel) return ret; } - rad->enabled = false; - return 0; } @@ -629,14 +612,6 @@ static void rad_panel_remove(struct mipi_dsi_device *dsi) drm_panel_remove(&rad->panel); } -static void rad_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct rad_panel *rad = mipi_dsi_get_drvdata(dsi); - - rad_panel_disable(&rad->panel); - rad_panel_unprepare(&rad->panel); -} - static const struct of_device_id rad_of_match[] = { { .compatible = "raydium,rm67191", }, { /* sentinel */ } @@ -650,7 +625,6 @@ static struct mipi_dsi_driver rad_panel_driver = { }, .probe = rad_panel_probe, .remove = rad_panel_remove, - .shutdown = rad_panel_shutdown, }; module_mipi_dsi_driver(rad_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-raydium-rm692e5.c b/drivers/gpu/drm/panel/panel-raydium-rm692e5.c index a613ba5b816c..21d97f6b8a2f 100644 --- a/drivers/gpu/drm/panel/panel-raydium-rm692e5.c +++ b/drivers/gpu/drm/panel/panel-raydium-rm692e5.c @@ -23,7 +23,6 @@ struct rm692e5_panel { struct drm_dsc_config dsc; struct regulator_bulk_data supplies[3]; struct gpio_desc *reset_gpio; - bool prepared; }; static inline struct rm692e5_panel *to_rm692e5_panel(struct drm_panel *panel) @@ -171,9 +170,6 @@ static int rm692e5_prepare(struct drm_panel *panel) struct device *dev = &ctx->dsi->dev; int ret; - if (ctx->prepared) - return 0; - ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); if (ret < 0) { dev_err(dev, "Failed to enable regulators: %d\n", ret); @@ -213,8 +209,6 @@ static int rm692e5_prepare(struct drm_panel *panel) mipi_dsi_generic_write_seq(ctx->dsi, 0xfe, 0x00); - ctx->prepared = true; - return 0; } @@ -222,13 +216,9 @@ static int rm692e5_unprepare(struct drm_panel *panel) { struct rm692e5_panel *ctx = to_rm692e5_panel(panel); - if (!ctx->prepared) - return 0; - gpiod_set_value_cansleep(ctx->reset_gpio, 1); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - ctx->prepared = false; return 0; } diff --git a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c index a9f0d214a900..9a482a744b8c 100644 --- a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c +++ b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c @@ -25,8 +25,6 @@ struct atana33xc20_panel { struct drm_panel base; - bool prepared; - bool enabled; bool el3_was_on; bool no_hpd; @@ -143,13 +141,8 @@ static int atana33xc20_disable(struct drm_panel *panel) { struct atana33xc20_panel *p = to_atana33xc20(panel); - /* Disabling when already disabled is a no-op */ - if (!p->enabled) - return 0; - gpiod_set_value_cansleep(p->el_on3_gpio, 0); p->el_on3_off_time = ktime_get_boottime(); - p->enabled = false; /* * Keep track of the fact that EL_ON3 was on but we haven't power @@ -173,10 +166,6 @@ static int atana33xc20_enable(struct drm_panel *panel) { struct atana33xc20_panel *p = to_atana33xc20(panel); - /* Enabling when already enabled is a no-op */ - if (p->enabled) - return 0; - /* * Once EL_ON3 drops we absolutely need a power cycle before the next * enable or the backlight will never come on again. The code ensures @@ -195,20 +184,14 @@ static int atana33xc20_enable(struct drm_panel *panel) atana33xc20_wait(p->powered_on_time, 400); gpiod_set_value_cansleep(p->el_on3_gpio, 1); - p->enabled = true; return 0; } static int atana33xc20_unprepare(struct drm_panel *panel) { - struct atana33xc20_panel *p = to_atana33xc20(panel); int ret; - /* Unpreparing when already unprepared is a no-op */ - if (!p->prepared) - return 0; - /* * Purposely do a put_sync, don't use autosuspend. The panel's tcon * seems to sometimes crash when you stop giving it data and this is @@ -220,26 +203,19 @@ static int atana33xc20_unprepare(struct drm_panel *panel) ret = pm_runtime_put_sync_suspend(panel->dev); if (ret < 0) return ret; - p->prepared = false; return 0; } static int atana33xc20_prepare(struct drm_panel *panel) { - struct atana33xc20_panel *p = to_atana33xc20(panel); int ret; - /* Preparing when already prepared is a no-op */ - if (p->prepared) - return 0; - ret = pm_runtime_get_sync(panel->dev); if (ret < 0) { pm_runtime_put_autosuspend(panel->dev); return ret; } - p->prepared = true; return 0; } @@ -351,21 +327,10 @@ static void atana33xc20_remove(struct dp_aux_ep_device *aux_ep) struct atana33xc20_panel *panel = dev_get_drvdata(dev); drm_panel_remove(&panel->base); - drm_panel_disable(&panel->base); - drm_panel_unprepare(&panel->base); drm_edid_free(panel->drm_edid); } -static void atana33xc20_shutdown(struct dp_aux_ep_device *aux_ep) -{ - struct device *dev = &aux_ep->dev; - struct atana33xc20_panel *panel = dev_get_drvdata(dev); - - drm_panel_disable(&panel->base); - drm_panel_unprepare(&panel->base); -} - static const struct of_device_id atana33xc20_dt_match[] = { { .compatible = "samsung,atna33xc20", }, { /* sentinal */ } @@ -386,7 +351,6 @@ static struct dp_aux_ep_driver atana33xc20_driver = { }, .probe = atana33xc20_probe, .remove = atana33xc20_remove, - .shutdown = atana33xc20_shutdown, }; static int __init atana33xc20_init(void) diff --git a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c index 658c7c040570..8a3fe531c641 100644 --- a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c +++ b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c @@ -44,8 +44,6 @@ struct seiko_panel_desc { struct seiko_panel { struct drm_panel base; - bool prepared; - bool enabled; const struct seiko_panel_desc *desc; struct regulator *dvdd; struct regulator *avdd; @@ -122,25 +120,10 @@ static int seiko_panel_get_fixed_modes(struct seiko_panel *panel, return num; } -static int seiko_panel_disable(struct drm_panel *panel) -{ - struct seiko_panel *p = to_seiko_panel(panel); - - if (!p->enabled) - return 0; - - p->enabled = false; - - return 0; -} - static int seiko_panel_unprepare(struct drm_panel *panel) { struct seiko_panel *p = to_seiko_panel(panel); - if (!p->prepared) - return 0; - gpiod_set_value_cansleep(p->enable_gpio, 0); regulator_disable(p->avdd); @@ -150,8 +133,6 @@ static int seiko_panel_unprepare(struct drm_panel *panel) regulator_disable(p->dvdd); - p->prepared = false; - return 0; } @@ -160,9 +141,6 @@ static int seiko_panel_prepare(struct drm_panel *panel) struct seiko_panel *p = to_seiko_panel(panel); int err; - if (p->prepared) - return 0; - err = regulator_enable(p->dvdd); if (err < 0) { dev_err(panel->dev, "failed to enable dvdd: %d\n", err); @@ -180,8 +158,6 @@ static int seiko_panel_prepare(struct drm_panel *panel) gpiod_set_value_cansleep(p->enable_gpio, 1); - p->prepared = true; - return 0; disable_dvdd: @@ -189,18 +165,6 @@ disable_dvdd: return err; } -static int seiko_panel_enable(struct drm_panel *panel) -{ - struct seiko_panel *p = to_seiko_panel(panel); - - if (p->enabled) - return 0; - - p->enabled = true; - - return 0; -} - static int seiko_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector) { @@ -228,10 +192,8 @@ static int seiko_panel_get_timings(struct drm_panel *panel, } static const struct drm_panel_funcs seiko_panel_funcs = { - .disable = seiko_panel_disable, .unprepare = seiko_panel_unprepare, .prepare = seiko_panel_prepare, - .enable = seiko_panel_enable, .get_modes = seiko_panel_get_modes, .get_timings = seiko_panel_get_timings, }; @@ -246,8 +208,6 @@ static int seiko_panel_probe(struct device *dev, if (!panel) return -ENOMEM; - panel->enabled = false; - panel->prepared = false; panel->desc = desc; panel->dvdd = devm_regulator_get(dev, "dvdd"); @@ -283,14 +243,6 @@ static void seiko_panel_remove(struct platform_device *pdev) struct seiko_panel *panel = platform_get_drvdata(pdev); drm_panel_remove(&panel->base); - drm_panel_disable(&panel->base); -} - -static void seiko_panel_shutdown(struct platform_device *pdev) -{ - struct seiko_panel *panel = platform_get_drvdata(pdev); - - drm_panel_disable(&panel->base); } static const struct display_timing seiko_43wvf1g_timing = { @@ -346,7 +298,6 @@ static struct platform_driver seiko_panel_platform_driver = { }, .probe = seiko_panel_platform_probe, .remove_new = seiko_panel_remove, - .shutdown = seiko_panel_shutdown, }; module_platform_driver(seiko_panel_platform_driver); diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c index 14851408a5e1..edc9425bb143 100644 --- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c +++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c @@ -24,9 +24,6 @@ struct sharp_panel { struct regulator *supply; - bool prepared; - bool enabled; - const struct drm_display_mode *mode; }; @@ -85,26 +82,11 @@ static __maybe_unused int sharp_panel_read(struct sharp_panel *sharp, return err; } -static int sharp_panel_disable(struct drm_panel *panel) -{ - struct sharp_panel *sharp = to_sharp_panel(panel); - - if (!sharp->enabled) - return 0; - - sharp->enabled = false; - - return 0; -} - static int sharp_panel_unprepare(struct drm_panel *panel) { struct sharp_panel *sharp = to_sharp_panel(panel); int err; - if (!sharp->prepared) - return 0; - sharp_wait_frames(sharp, 4); err = mipi_dsi_dcs_set_display_off(sharp->link1); @@ -119,8 +101,6 @@ static int sharp_panel_unprepare(struct drm_panel *panel) regulator_disable(sharp->supply); - sharp->prepared = false; - return 0; } @@ -164,9 +144,6 @@ static int sharp_panel_prepare(struct drm_panel *panel) u8 format = MIPI_DCS_PIXEL_FMT_24BIT; int err; - if (sharp->prepared) - return 0; - err = regulator_enable(sharp->supply); if (err < 0) return err; @@ -235,8 +212,6 @@ static int sharp_panel_prepare(struct drm_panel *panel) goto poweroff; } - sharp->prepared = true; - /* wait for 6 frames before continuing */ sharp_wait_frames(sharp, 6); @@ -247,18 +222,6 @@ poweroff: return err; } -static int sharp_panel_enable(struct drm_panel *panel) -{ - struct sharp_panel *sharp = to_sharp_panel(panel); - - if (sharp->enabled) - return 0; - - sharp->enabled = true; - - return 0; -} - static const struct drm_display_mode default_mode = { .clock = 278000, .hdisplay = 2560, @@ -295,10 +258,8 @@ static int sharp_panel_get_modes(struct drm_panel *panel, } static const struct drm_panel_funcs sharp_panel_funcs = { - .disable = sharp_panel_disable, .unprepare = sharp_panel_unprepare, .prepare = sharp_panel_prepare, - .enable = sharp_panel_enable, .get_modes = sharp_panel_get_modes, }; @@ -396,32 +357,13 @@ static void sharp_panel_remove(struct mipi_dsi_device *dsi) struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi); int err; - /* only detach from host for the DSI-LINK2 interface */ - if (!sharp) { - mipi_dsi_detach(dsi); - return; - } - - err = drm_panel_disable(&sharp->base); - if (err < 0) - dev_err(&dsi->dev, "failed to disable panel: %d\n", err); - err = mipi_dsi_detach(dsi); if (err < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); - sharp_panel_del(sharp); -} - -static void sharp_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi); - - /* nothing to do for DSI-LINK2 */ + /* only detach from host for the DSI-LINK2 interface */ if (!sharp) - return; - - drm_panel_disable(&sharp->base); + sharp_panel_del(sharp); } static struct mipi_dsi_driver sharp_panel_driver = { @@ -431,7 +373,6 @@ static struct mipi_dsi_driver sharp_panel_driver = { }, .probe = sharp_panel_probe, .remove = sharp_panel_remove, - .shutdown = sharp_panel_shutdown, }; module_mipi_dsi_driver(sharp_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c index 855e64444daa..729cbb0d8403 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c @@ -26,8 +26,6 @@ struct sharp_nt_panel { struct regulator *supply; struct gpio_desc *reset_gpio; - - bool prepared; }; static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel) @@ -99,9 +97,6 @@ static int sharp_nt_panel_unprepare(struct drm_panel *panel) struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel); int ret; - if (!sharp_nt->prepared) - return 0; - ret = sharp_nt_panel_off(sharp_nt); if (ret < 0) { dev_err(panel->dev, "failed to set panel off: %d\n", ret); @@ -112,8 +107,6 @@ static int sharp_nt_panel_unprepare(struct drm_panel *panel) if (sharp_nt->reset_gpio) gpiod_set_value(sharp_nt->reset_gpio, 0); - sharp_nt->prepared = false; - return 0; } @@ -122,9 +115,6 @@ static int sharp_nt_panel_prepare(struct drm_panel *panel) struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel); int ret; - if (sharp_nt->prepared) - return 0; - ret = regulator_enable(sharp_nt->supply); if (ret < 0) return ret; @@ -152,8 +142,6 @@ static int sharp_nt_panel_prepare(struct drm_panel *panel) goto poweroff; } - sharp_nt->prepared = true; - return 0; poweroff: @@ -279,10 +267,6 @@ static void sharp_nt_panel_remove(struct mipi_dsi_device *dsi) struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi); int ret; - ret = drm_panel_disable(&sharp_nt->base); - if (ret < 0) - dev_err(&dsi->dev, "failed to disable panel: %d\n", ret); - ret = mipi_dsi_detach(dsi); if (ret < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); @@ -290,13 +274,6 @@ static void sharp_nt_panel_remove(struct mipi_dsi_device *dsi) sharp_nt_panel_del(sharp_nt); } -static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi); - - drm_panel_disable(&sharp_nt->base); -} - static const struct of_device_id sharp_nt_of_match[] = { { .compatible = "sharp,ls043t1le01-qhd", }, { } @@ -310,7 +287,6 @@ static struct mipi_dsi_driver sharp_nt_panel_driver = { }, .probe = sharp_nt_panel_probe, .remove = sharp_nt_panel_remove, - .shutdown = sharp_nt_panel_shutdown, }; module_mipi_dsi_driver(sharp_nt_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index dcb6d0b6ced0..8345ed891f5a 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -138,9 +138,6 @@ struct panel_desc { struct panel_simple { struct drm_panel base; - bool enabled; - - bool prepared; ktime_t unprepared_time; @@ -290,14 +287,9 @@ static int panel_simple_disable(struct drm_panel *panel) { struct panel_simple *p = to_panel_simple(panel); - if (!p->enabled) - return 0; - if (p->desc->delay.disable) msleep(p->desc->delay.disable); - p->enabled = false; - return 0; } @@ -317,18 +309,12 @@ static int panel_simple_suspend(struct device *dev) static int panel_simple_unprepare(struct drm_panel *panel) { - struct panel_simple *p = to_panel_simple(panel); int ret; - /* Unpreparing when already unprepared is a no-op */ - if (!p->prepared) - return 0; - pm_runtime_mark_last_busy(panel->dev); ret = pm_runtime_put_autosuspend(panel->dev); if (ret < 0) return ret; - p->prepared = false; return 0; } @@ -356,21 +342,14 @@ static int panel_simple_resume(struct device *dev) static int panel_simple_prepare(struct drm_panel *panel) { - struct panel_simple *p = to_panel_simple(panel); int ret; - /* Preparing when already prepared is a no-op */ - if (p->prepared) - return 0; - ret = pm_runtime_get_sync(panel->dev); if (ret < 0) { pm_runtime_put_autosuspend(panel->dev); return ret; } - p->prepared = true; - return 0; } @@ -378,14 +357,9 @@ static int panel_simple_enable(struct drm_panel *panel) { struct panel_simple *p = to_panel_simple(panel); - if (p->enabled) - return 0; - if (p->desc->delay.enable) msleep(p->desc->delay.enable); - p->enabled = true; - return 0; } @@ -609,7 +583,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) if (!panel) return -ENOMEM; - panel->enabled = false; panel->desc = desc; panel->supply = devm_regulator_get(dev, "power"); @@ -743,26 +716,39 @@ free_ddc: return err; } -static void panel_simple_remove(struct device *dev) +static void panel_simple_shutdown(struct device *dev) { struct panel_simple *panel = dev_get_drvdata(dev); - drm_panel_remove(&panel->base); + /* + * NOTE: the following two calls don't really belong here. It is the + * responsibility of a correctly written DRM modeset driver to call + * drm_atomic_helper_shutdown() at shutdown time and that should + * cause the panel to be disabled / unprepared if needed. For now, + * however, we'll keep these calls due to the sheer number of + * different DRM modeset drivers used with panel-simple. The fact that + * we're calling these and _also_ the drm_atomic_helper_shutdown() + * will try to disable/unprepare means that we can get a warning about + * trying to disable/unprepare an already disabled/unprepared panel, + * but that's something we'll have to live with until we've confirmed + * that all DRM modeset drivers are properly calling + * drm_atomic_helper_shutdown(). + */ drm_panel_disable(&panel->base); drm_panel_unprepare(&panel->base); - - pm_runtime_dont_use_autosuspend(dev); - pm_runtime_disable(dev); - if (panel->ddc) - put_device(&panel->ddc->dev); } -static void panel_simple_shutdown(struct device *dev) +static void panel_simple_remove(struct device *dev) { struct panel_simple *panel = dev_get_drvdata(dev); - drm_panel_disable(&panel->base); - drm_panel_unprepare(&panel->base); + drm_panel_remove(&panel->base); + panel_simple_shutdown(dev); + + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); + if (panel->ddc) + put_device(&panel->ddc->dev); } static const struct drm_display_mode ampire_am_1280800n3tzqw_t00h_mode = { @@ -2870,6 +2856,35 @@ static const struct panel_desc lg_lb070wv8 = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; +static const struct drm_display_mode lincolntech_lcd185_101ct_mode = { + .clock = 155127, + .hdisplay = 1920, + .hsync_start = 1920 + 128, + .hsync_end = 1920 + 128 + 20, + .htotal = 1920 + 128 + 20 + 12, + .vdisplay = 1200, + .vsync_start = 1200 + 19, + .vsync_end = 1200 + 19 + 4, + .vtotal = 1200 + 19 + 4 + 20, +}; + +static const struct panel_desc lincolntech_lcd185_101ct = { + .modes = &lincolntech_lcd185_101ct_mode, + .bpc = 8, + .num_modes = 1, + .size = { + .width = 217, + .height = 136, + }, + .delay = { + .prepare = 50, + .disable = 50, + }, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct display_timing logictechno_lt161010_2nh_timing = { .pixelclock = { 26400000, 33300000, 46800000 }, .hactive = { 800, 800, 800 }, @@ -3026,6 +3041,64 @@ static const struct panel_desc logicpd_type_28 = { .connector_type = DRM_MODE_CONNECTOR_DPI, }; +static const struct drm_display_mode microtips_mf_101hiebcaf0_c_mode = { + .clock = 150275, + .hdisplay = 1920, + .hsync_start = 1920 + 32, + .hsync_end = 1920 + 32 + 52, + .htotal = 1920 + 32 + 52 + 24, + .vdisplay = 1200, + .vsync_start = 1200 + 24, + .vsync_end = 1200 + 24 + 8, + .vtotal = 1200 + 24 + 8 + 3, +}; + +static const struct panel_desc microtips_mf_101hiebcaf0_c = { + .modes = µtips_mf_101hiebcaf0_c_mode, + .bpc = 8, + .num_modes = 1, + .size = { + .width = 217, + .height = 136, + }, + .delay = { + .prepare = 50, + .disable = 50, + }, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + +static const struct drm_display_mode microtips_mf_103hieb0ga0_mode = { + .clock = 93301, + .hdisplay = 1920, + .hsync_start = 1920 + 72, + .hsync_end = 1920 + 72 + 72, + .htotal = 1920 + 72 + 72 + 72, + .vdisplay = 720, + .vsync_start = 720 + 3, + .vsync_end = 720 + 3 + 3, + .vtotal = 720 + 3 + 3 + 2, +}; + +static const struct panel_desc microtips_mf_103hieb0ga0 = { + .modes = µtips_mf_103hieb0ga0_mode, + .bpc = 8, + .num_modes = 1, + .size = { + .width = 244, + .height = 92, + }, + .delay = { + .prepare = 50, + .disable = 50, + }, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct drm_display_mode mitsubishi_aa070mc01_mode = { .clock = 30400, .hdisplay = 800, @@ -3567,6 +3640,32 @@ static const struct panel_desc powertip_ph800480t013_idf02 = { .connector_type = DRM_MODE_CONNECTOR_DPI, }; +static const struct drm_display_mode primeview_pm070wl4_mode = { + .clock = 32000, + .hdisplay = 800, + .hsync_start = 800 + 42, + .hsync_end = 800 + 42 + 128, + .htotal = 800 + 42 + 128 + 86, + .vdisplay = 480, + .vsync_start = 480 + 10, + .vsync_end = 480 + 10 + 2, + .vtotal = 480 + 10 + 2 + 33, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, +}; + +static const struct panel_desc primeview_pm070wl4 = { + .modes = &primeview_pm070wl4_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 152, + .height = 91, + }, + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE, + .bus_format = MEDIA_BUS_FMT_RGB666_1X18, + .connector_type = DRM_MODE_CONNECTOR_DPI, +}; + static const struct drm_display_mode qd43003c0_40_mode = { .clock = 9000, .hdisplay = 480, @@ -4645,6 +4744,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "lg,lb070wv8", .data = &lg_lb070wv8, }, { + .compatible = "lincolntech,lcd185-101ct", + .data = &lincolntech_lcd185_101ct, + }, { .compatible = "logicpd,type28", .data = &logicpd_type_28, }, { @@ -4663,6 +4765,12 @@ static const struct of_device_id platform_of_match[] = { .compatible = "logictechno,lttd800480070-l6wh-rt", .data = &logictechno_lttd800480070_l6wh_rt, }, { + .compatible = "microtips,mf-101hiebcaf0", + .data = µtips_mf_101hiebcaf0_c, + }, { + .compatible = "microtips,mf-103hieb0ga0", + .data = µtips_mf_103hieb0ga0, + }, { .compatible = "mitsubishi,aa070mc01-ca1", .data = &mitsubishi_aa070mc01, }, { @@ -4726,6 +4834,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "powertip,ph800480t013-idf02", .data = &powertip_ph800480t013_idf02, }, { + .compatible = "primeview,pm070wl4", + .data = &primeview_pm070wl4, + }, { .compatible = "qiaodian,qd43003c0-40", .data = &qd43003c0_40, }, { diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c index 7d8302cca091..77b30e045a57 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c @@ -58,7 +58,6 @@ struct st7703 { struct gpio_desc *reset_gpio; struct regulator *vcc; struct regulator *iovcc; - bool prepared; struct dentry *debugfs; const struct st7703_panel_desc *desc; @@ -752,13 +751,9 @@ static int st7703_unprepare(struct drm_panel *panel) { struct st7703 *ctx = panel_to_st7703(panel); - if (!ctx->prepared) - return 0; - gpiod_set_value_cansleep(ctx->reset_gpio, 1); regulator_disable(ctx->iovcc); regulator_disable(ctx->vcc); - ctx->prepared = false; return 0; } @@ -768,9 +763,6 @@ static int st7703_prepare(struct drm_panel *panel) struct st7703 *ctx = panel_to_st7703(panel); int ret; - if (ctx->prepared) - return 0; - dev_dbg(ctx->dev, "Resetting the panel\n"); gpiod_set_value_cansleep(ctx->reset_gpio, 1); @@ -793,8 +785,6 @@ static int st7703_prepare(struct drm_panel *panel) gpiod_set_value_cansleep(ctx->reset_gpio, 0); usleep_range(15000, 20000); - ctx->prepared = true; - return 0; } @@ -854,7 +844,13 @@ static int allpixelson_set(void *data, u64 val) dev_dbg(ctx->dev, "Setting all pixels on\n"); mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON); msleep(val * 1000); - /* Reset the panel to get video back */ + + /* + * Reset the panel to get video back. NOTE: This isn't a + * particularly safe thing to do in general because it assumes + * that the screen was on to begin with, but this is just a + * debugfs file so it's not a huge deal. + */ drm_panel_disable(&ctx->panel); drm_panel_unprepare(&ctx->panel); drm_panel_prepare(&ctx->panel); @@ -941,27 +937,11 @@ static int st7703_probe(struct mipi_dsi_device *dsi) return 0; } -static void st7703_shutdown(struct mipi_dsi_device *dsi) -{ - struct st7703 *ctx = mipi_dsi_get_drvdata(dsi); - int ret; - - ret = drm_panel_unprepare(&ctx->panel); - if (ret < 0) - dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); - - ret = drm_panel_disable(&ctx->panel); - if (ret < 0) - dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); -} - static void st7703_remove(struct mipi_dsi_device *dsi) { struct st7703 *ctx = mipi_dsi_get_drvdata(dsi); int ret; - st7703_shutdown(dsi); - ret = mipi_dsi_detach(dsi); if (ret < 0) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); @@ -985,7 +965,6 @@ MODULE_DEVICE_TABLE(of, st7703_of_match); static struct mipi_dsi_driver st7703_driver = { .probe = st7703_probe, .remove = st7703_remove, - .shutdown = st7703_shutdown, .driver = { .name = DRV_NAME, .of_match_table = st7703_of_match, diff --git a/drivers/gpu/drm/panel/panel-sony-acx565akm.c b/drivers/gpu/drm/panel/panel-sony-acx565akm.c index 3d6a286056a0..73ba93ff00fe 100644 --- a/drivers/gpu/drm/panel/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/panel/panel-sony-acx565akm.c @@ -454,9 +454,6 @@ static int acx565akm_power_on(struct acx565akm_panel *lcd) static void acx565akm_power_off(struct acx565akm_panel *lcd) { - if (!lcd->enabled) - return; - acx565akm_set_display_state(lcd, 0); acx565akm_set_sleep_mode(lcd, 1); lcd->enabled = false; @@ -655,9 +652,6 @@ static void acx565akm_remove(struct spi_device *spi) if (lcd->has_bc) acx565akm_backlight_cleanup(lcd); - - drm_panel_disable(&lcd->panel); - drm_panel_unprepare(&lcd->panel); } static const struct of_device_id acx565akm_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c index d8487bc6d611..227f97f9b136 100644 --- a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c +++ b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c @@ -24,8 +24,6 @@ struct tdo_tl070wsh30_panel { struct regulator *supply; struct gpio_desc *reset_gpio; - - bool prepared; }; static inline @@ -39,9 +37,6 @@ static int tdo_tl070wsh30_panel_prepare(struct drm_panel *panel) struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = to_tdo_tl070wsh30_panel(panel); int err; - if (tdo_tl070wsh30->prepared) - return 0; - err = regulator_enable(tdo_tl070wsh30->supply); if (err < 0) return err; @@ -74,8 +69,6 @@ static int tdo_tl070wsh30_panel_prepare(struct drm_panel *panel) msleep(20); - tdo_tl070wsh30->prepared = true; - return 0; } @@ -84,9 +77,6 @@ static int tdo_tl070wsh30_panel_unprepare(struct drm_panel *panel) struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = to_tdo_tl070wsh30_panel(panel); int err; - if (!tdo_tl070wsh30->prepared) - return 0; - err = mipi_dsi_dcs_set_display_off(tdo_tl070wsh30->link); if (err < 0) dev_err(panel->dev, "failed to set display off: %d\n", err); @@ -103,8 +93,6 @@ static int tdo_tl070wsh30_panel_unprepare(struct drm_panel *panel) regulator_disable(tdo_tl070wsh30->supply); - tdo_tl070wsh30->prepared = false; - return 0; } @@ -220,16 +208,6 @@ static void tdo_tl070wsh30_panel_remove(struct mipi_dsi_device *dsi) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); drm_panel_remove(&tdo_tl070wsh30->base); - drm_panel_disable(&tdo_tl070wsh30->base); - drm_panel_unprepare(&tdo_tl070wsh30->base); -} - -static void tdo_tl070wsh30_panel_shutdown(struct mipi_dsi_device *dsi) -{ - struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = mipi_dsi_get_drvdata(dsi); - - drm_panel_disable(&tdo_tl070wsh30->base); - drm_panel_unprepare(&tdo_tl070wsh30->base); } static struct mipi_dsi_driver tdo_tl070wsh30_panel_driver = { @@ -239,7 +217,6 @@ static struct mipi_dsi_driver tdo_tl070wsh30_panel_driver = { }, .probe = tdo_tl070wsh30_panel_probe, .remove = tdo_tl070wsh30_panel_remove, - .shutdown = tdo_tl070wsh30_panel_shutdown, }; module_mipi_dsi_driver(tdo_tl070wsh30_panel_driver); diff --git a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c index 8670386498a4..22a14006765e 100644 --- a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c +++ b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c @@ -52,7 +52,6 @@ struct xpp055c272 { struct gpio_desc *reset_gpio; struct regulator *vci; struct regulator *iovcc; - bool prepared; }; static inline struct xpp055c272 *panel_to_xpp055c272(struct drm_panel *panel) @@ -136,9 +135,6 @@ static int xpp055c272_unprepare(struct drm_panel *panel) struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); int ret; - if (!ctx->prepared) - return 0; - ret = mipi_dsi_dcs_set_display_off(dsi); if (ret < 0) dev_err(ctx->dev, "failed to set display off: %d\n", ret); @@ -152,8 +148,6 @@ static int xpp055c272_unprepare(struct drm_panel *panel) regulator_disable(ctx->iovcc); regulator_disable(ctx->vci); - ctx->prepared = false; - return 0; } @@ -163,9 +157,6 @@ static int xpp055c272_prepare(struct drm_panel *panel) struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); int ret; - if (ctx->prepared) - return 0; - dev_dbg(ctx->dev, "Resetting the panel\n"); ret = regulator_enable(ctx->vci); if (ret < 0) { @@ -209,8 +200,6 @@ static int xpp055c272_prepare(struct drm_panel *panel) msleep(50); - ctx->prepared = true; - return 0; disable_iovcc: @@ -317,27 +306,11 @@ static int xpp055c272_probe(struct mipi_dsi_device *dsi) return 0; } -static void xpp055c272_shutdown(struct mipi_dsi_device *dsi) -{ - struct xpp055c272 *ctx = mipi_dsi_get_drvdata(dsi); - int ret; - - ret = drm_panel_unprepare(&ctx->panel); - if (ret < 0) - dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); - - ret = drm_panel_disable(&ctx->panel); - if (ret < 0) - dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); -} - static void xpp055c272_remove(struct mipi_dsi_device *dsi) { struct xpp055c272 *ctx = mipi_dsi_get_drvdata(dsi); int ret; - xpp055c272_shutdown(dsi); - ret = mipi_dsi_detach(dsi); if (ret < 0) dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); @@ -358,7 +331,6 @@ static struct mipi_dsi_driver xpp055c272_driver = { }, .probe = xpp055c272_probe, .remove = xpp055c272_remove, - .shutdown = xpp055c272_shutdown, }; module_mipi_dsi_driver(xpp055c272_driver); diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index ef9f6c0716d5..b43557b10ae3 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -777,6 +777,15 @@ static const struct panfrost_compatible mediatek_mt8186_data = { .pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF), }; +/* MT8188 uses the same power domains and power supplies as MT8183 */ +static const struct panfrost_compatible mediatek_mt8188_data = { + .num_supplies = ARRAY_SIZE(mediatek_mt8183_b_supplies) - 1, + .supply_names = mediatek_mt8183_b_supplies, + .num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains), + .pm_domain_names = mediatek_mt8183_pm_domains, + .pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF), +}; + static const char * const mediatek_mt8192_supplies[] = { "mali", NULL }; static const char * const mediatek_mt8192_pm_domains[] = { "core0", "core1", "core2", "core3", "core4" }; @@ -808,6 +817,7 @@ static const struct of_device_id dt_match[] = { { .compatible = "mediatek,mt8183-mali", .data = &mediatek_mt8183_data }, { .compatible = "mediatek,mt8183b-mali", .data = &mediatek_mt8183_b_data }, { .compatible = "mediatek,mt8186-mali", .data = &mediatek_mt8186_data }, + { .compatible = "mediatek,mt8188-mali", .data = &mediatek_mt8188_data }, { .compatible = "mediatek,mt8192-mali", .data = &mediatek_mt8192_data }, {} }; diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index beee5563031a..5eb3f5719fdf 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -37,7 +37,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_ttm.h> #include <drm/drm_file.h> #include <drm/drm_gem_ttm_helper.h> #include <drm/drm_module.h> @@ -118,7 +118,7 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto modeset_cleanup; - drm_fbdev_generic_setup(&qdev->ddev, 32); + drm_fbdev_ttm_setup(&qdev->ddev, 32); return 0; modeset_cleanup: diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 7b11674f5d45..03e6871b3065 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -701,7 +701,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) if (radeon_connector->use_digital && (radeon_connector->audio == RADEON_AUDIO_ENABLE)) return ATOM_ENCODER_MODE_HDMI; - else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) && + else if (connector->display_info.is_hdmi && (radeon_connector->audio == RADEON_AUDIO_AUTO)) return ATOM_ENCODER_MODE_HDMI; else if (radeon_connector->use_digital) @@ -720,7 +720,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) if (radeon_audio != 0) { if (radeon_connector->audio == RADEON_AUDIO_ENABLE) return ATOM_ENCODER_MODE_HDMI; - else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) && + else if (connector->display_info.is_hdmi && (radeon_connector->audio == RADEON_AUDIO_AUTO)) return ATOM_ENCODER_MODE_HDMI; else @@ -737,14 +737,14 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { if (radeon_audio != 0 && - drm_detect_monitor_audio(radeon_connector_edid(connector)) && + connector->display_info.has_audio && ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev)) return ATOM_ENCODER_MODE_DP_AUDIO; return ATOM_ENCODER_MODE_DP; } else if (radeon_audio != 0) { if (radeon_connector->audio == RADEON_AUDIO_ENABLE) return ATOM_ENCODER_MODE_HDMI; - else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) && + else if (connector->display_info.is_hdmi && (radeon_connector->audio == RADEON_AUDIO_AUTO)) return ATOM_ENCODER_MODE_HDMI; else @@ -755,7 +755,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) break; case DRM_MODE_CONNECTOR_eDP: if (radeon_audio != 0 && - drm_detect_monitor_audio(radeon_connector_edid(connector)) && + connector->display_info.has_audio && ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev)) return ATOM_ENCODER_MODE_DP_AUDIO; return ATOM_ENCODER_MODE_DP; diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 681119c91d94..09dda114e218 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -412,7 +412,7 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) if (enable) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - if (connector && drm_detect_monitor_audio(radeon_connector_edid(connector))) { + if (connector && connector->display_info.has_audio) { WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset, HDMI_AVI_INFO_SEND | /* enable AVI info frames */ HDMI_AVI_INFO_CONT | /* required for audio info values to be updated */ @@ -450,8 +450,7 @@ void evergreen_dp_enable(struct drm_encoder *encoder, bool enable) if (!dig || !dig->afmt) return; - if (enable && connector && - drm_detect_monitor_audio(radeon_connector_edid(connector))) { + if (enable && connector && connector->display_info.has_audio) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector; diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index 74753bb26d33..0bcd767b9f47 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -303,6 +303,7 @@ void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset, static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct cea_sad *sads; int sad_count; @@ -310,7 +311,7 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) if (!connector) return; - sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads); + sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); if (sad_count < 0) DRM_ERROR("Couldn't read SADs: %d\n", sad_count); if (sad_count <= 0) @@ -326,6 +327,7 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); u8 *sadb = NULL; int sad_count; @@ -333,8 +335,7 @@ static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) if (!connector) return; - sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), - &sadb); + sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); if (sad_count < 0) { DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); @@ -409,7 +410,7 @@ void radeon_audio_detect(struct drm_connector *connector, radeon_encoder->audio = rdev->audio.hdmi_funcs; } - if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { + if (connector->display_info.has_audio) { if (!dig->pin) dig->pin = radeon_audio_get_pin(encoder); radeon_audio_enable(rdev, dig->pin, 0xf); @@ -646,7 +647,7 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, if (!connector) return; - if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { + if (connector->display_info.has_audio) { radeon_audio_set_mute(encoder, true); radeon_audio_write_speaker_allocation(encoder); @@ -686,7 +687,7 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, if (!connector) return; - if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { + if (connector->display_info.has_audio) { radeon_audio_write_speaker_allocation(encoder); radeon_audio_write_sad_regs(encoder); radeon_audio_write_latency_fields(encoder, mode); diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index cf0114ca59a4..69693ba5949e 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -109,7 +109,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector) case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_HDMIB: if (radeon_connector->use_digital) { - if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) { + if (connector->display_info.is_hdmi) { if (connector->display_info.bpc) bpc = connector->display_info.bpc; } @@ -117,7 +117,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector) break; case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_HDMIA: - if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) { + if (connector->display_info.is_hdmi) { if (connector->display_info.bpc) bpc = connector->display_info.bpc; } @@ -126,7 +126,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector) dig_connector = radeon_connector->con_priv; if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) || - drm_detect_hdmi_monitor(radeon_connector_edid(connector))) { + connector->display_info.is_hdmi) { if (connector->display_info.bpc) bpc = connector->display_info.bpc; } @@ -150,7 +150,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector) break; } - if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) { + if (connector->display_info.is_hdmi) { /* hdmi deep color only implemented on DCE4+ */ if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) { DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n", @@ -255,21 +255,6 @@ static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, return NULL; } -struct edid *radeon_connector_edid(struct drm_connector *connector) -{ - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - struct drm_property_blob *edid_blob = connector->edid_blob_ptr; - - if (radeon_connector->edid) { - return radeon_connector->edid; - } else if (edid_blob) { - struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL); - if (edid) - radeon_connector->edid = edid; - } - return radeon_connector->edid; -} - static void radeon_connector_get_edid(struct drm_connector *connector) { struct drm_device *dev = connector->dev; @@ -1488,7 +1473,7 @@ static enum drm_mode_status radeon_dvi_mode_valid(struct drm_connector *connecto (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) || (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) return MODE_OK; - else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) { + else if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) { /* HDMI 1.3+ supports max clock of 340 Mhz */ if (mode->clock > 340000) return MODE_CLOCK_HIGH; @@ -1784,7 +1769,7 @@ static enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { return radeon_dp_mode_valid_helper(connector, mode); } else { - if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) { + if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) { /* HDMI 1.3+ supports max clock of 340 Mhz */ if (mode->clock > 340000) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 5f1d24d3120c..843383f7237f 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1722,7 +1722,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) && ((radeon_encoder->underscan_type == UNDERSCAN_ON) || ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && - drm_detect_hdmi_monitor(radeon_connector_edid(connector)) && + connector->display_info.is_hdmi && is_hdtv_mode(mode)))) { if (radeon_encoder->underscan_hborder != 0) radeon_crtc->h_border = radeon_encoder->underscan_hborder; diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 3de3dce9e89d..0f723292409e 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -386,7 +386,7 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, case DRM_MODE_CONNECTOR_HDMIB: if (radeon_connector->use_digital) { /* HDMI 1.3 supports up to 340 Mhz over single link */ - if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) { + if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) { if (pixel_clock > 340000) return true; else @@ -408,7 +408,7 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, return false; else { /* HDMI 1.3 supports up to 340 Mhz over single link */ - if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) { + if (ASIC_IS_DCE6(rdev) && connector->display_info.is_hdmi) { if (pixel_clock > 340000) return true; else diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 546381a5c918..e0a5af180801 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -701,8 +701,6 @@ extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connecto extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector); extern int radeon_get_monitor_bpc(struct drm_connector *connector); -extern struct edid *radeon_connector_edid(struct drm_connector *connector); - extern void radeon_connector_hotplug(struct drm_connector *connector); extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, struct drm_display_mode *mode); diff --git a/drivers/gpu/drm/renesas/rcar-du/Kconfig b/drivers/gpu/drm/renesas/rcar-du/Kconfig index 53c356aed5d5..c17e7c50492c 100644 --- a/drivers/gpu/drm/renesas/rcar-du/Kconfig +++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig @@ -2,7 +2,7 @@ config DRM_RCAR_DU tristate "DRM Support for R-Car Display Unit" depends on DRM && OF - depends on ARM || ARM64 + depends on ARM || ARM64 || COMPILE_TEST depends on ARCH_RENESAS || COMPILE_TEST select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c index dee530e4c8b2..fb719d9aff10 100644 --- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c @@ -20,7 +20,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> @@ -716,7 +716,7 @@ static int rcar_du_probe(struct platform_device *pdev) drm_info(&rcdu->ddev, "Device %s probed\n", dev_name(&pdev->dev)); - drm_fbdev_generic_setup(&rcdu->ddev, 32); + drm_fbdev_dma_setup(&rcdu->ddev, 32); return 0; diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c index 470d34da1d6c..e5eca8691a33 100644 --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c @@ -14,7 +14,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_probe_helper.h> @@ -149,7 +149,7 @@ static int rzg2l_du_probe(struct platform_device *pdev) drm_info(&rcdu->ddev, "Device %s probed\n", dev_name(&pdev->dev)); - drm_fbdev_generic_setup(&rcdu->ddev, 32); + drm_fbdev_dma_setup(&rcdu->ddev, 32); return 0; diff --git a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c index e83c3e52251d..890cc2f6408d 100644 --- a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c @@ -19,7 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_modeset_helper.h> #include <drm/drm_module.h> @@ -250,7 +250,7 @@ static int shmob_drm_probe(struct platform_device *pdev) if (ret < 0) goto err_modeset_cleanup; - drm_fbdev_generic_setup(ddev, 16); + drm_fbdev_dma_setup(ddev, 16); return 0; diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 1bf3e2829cd0..7df875e38517 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -74,6 +74,9 @@ config ROCKCHIP_DW_MIPI_DSI config ROCKCHIP_INNO_HDMI bool "Rockchip specific extensions for Innosilicon HDMI" + select DRM_DISPLAY_HDMI_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER + select DRM_DISPLAY_HELPER help This selects support for Rockchip SoC specific extensions for the Innosilicon HDMI driver. If you want to enable diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 4cc8ed8f4fbd..58a44af0e9ad 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -153,6 +153,11 @@ #define PX30_DSI_TURNDISABLE BIT(5) #define PX30_DSI_LCDC_SEL BIT(0) +#define RK3128_GRF_LVDS_CON0 0x0150 +#define RK3128_DSI_FORCETXSTOPMODE GENMASK(13, 10) +#define RK3128_DSI_FORCERXMODE BIT(9) +#define RK3128_DSI_TURNDISABLE BIT(8) + #define RK3288_GRF_SOC_CON6 0x025c #define RK3288_DSI0_LCDC_SEL BIT(6) #define RK3288_DSI1_LCDC_SEL BIT(9) @@ -1493,6 +1498,18 @@ static const struct rockchip_dw_dsi_chip_data px30_chip_data[] = { { /* sentinel */ } }; +static const struct rockchip_dw_dsi_chip_data rk3128_chip_data[] = { + { + .reg = 0x10110000, + .lanecfg1_grf_reg = RK3128_GRF_LVDS_CON0, + .lanecfg1 = HIWORD_UPDATE(0, RK3128_DSI_TURNDISABLE | + RK3128_DSI_FORCERXMODE | + RK3128_DSI_FORCETXSTOPMODE), + .max_data_lanes = 4, + }, + { /* sentinel */ } +}; + static const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = { { .reg = 0xff960000, @@ -1671,6 +1688,9 @@ static const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = { .compatible = "rockchip,px30-mipi-dsi", .data = &px30_chip_data, }, { + .compatible = "rockchip,rk3128-mipi-dsi", + .data = &rk3128_chip_data, + }, { .compatible = "rockchip,rk3288-mipi-dsi", .data = &rk3288_chip_data, }, { diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 3df2cfcf9998..2241e53a2946 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -22,6 +22,9 @@ #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> +#include <drm/display/drm_hdmi_helper.h> +#include <drm/display/drm_hdmi_state_helper.h> + #include "rockchip_drm_drv.h" #include "inno_hdmi.h" @@ -67,9 +70,7 @@ struct inno_hdmi { struct inno_hdmi_connector_state { struct drm_connector_state base; - unsigned int enc_out_format; unsigned int colorimetry; - bool rgb_limited_range; }; static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder) @@ -257,26 +258,29 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi) inno_hdmi_standby(hdmi); } -static void inno_hdmi_disable_frame(struct inno_hdmi *hdmi, - enum hdmi_infoframe_type type) +static int inno_hdmi_disable_frame(struct drm_connector *connector, + enum hdmi_infoframe_type type) { - struct drm_connector *connector = &hdmi->connector; + struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector); if (type != HDMI_INFOFRAME_TYPE_AVI) { drm_err(connector->dev, "Unsupported infoframe type: %u\n", type); - return; + return 0; } hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI); + + return 0; } -static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, - union hdmi_infoframe *frame, enum hdmi_infoframe_type type) +static int inno_hdmi_upload_frame(struct drm_connector *connector, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len) { - struct drm_connector *connector = &hdmi->connector; + struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector); u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE]; - ssize_t rc, i; + ssize_t i; if (type != HDMI_INFOFRAME_TYPE_AVI) { drm_err(connector->dev, @@ -284,59 +288,19 @@ static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, return 0; } - inno_hdmi_disable_frame(hdmi, type); - - rc = hdmi_infoframe_pack(frame, packed_frame, - sizeof(packed_frame)); - if (rc < 0) - return rc; + inno_hdmi_disable_frame(connector, type); - for (i = 0; i < rc; i++) + for (i = 0; i < len; i++) hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i, packed_frame[i]); return 0; } -static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, - struct drm_display_mode *mode) -{ - struct drm_connector *connector = &hdmi->connector; - struct drm_connector_state *conn_state = connector->state; - struct inno_hdmi_connector_state *inno_conn_state = - to_inno_hdmi_conn_state(conn_state); - union hdmi_infoframe frame; - int rc; - - rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, - &hdmi->connector, - mode); - if (rc) { - inno_hdmi_disable_frame(hdmi, HDMI_INFOFRAME_TYPE_AVI); - return rc; - } - - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) - frame.avi.colorspace = HDMI_COLORSPACE_YUV444; - else if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV422) - frame.avi.colorspace = HDMI_COLORSPACE_YUV422; - else - frame.avi.colorspace = HDMI_COLORSPACE_RGB; - - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) { - drm_hdmi_avi_infoframe_quant_range(&frame.avi, - connector, mode, - inno_conn_state->rgb_limited_range ? - HDMI_QUANTIZATION_RANGE_LIMITED : - HDMI_QUANTIZATION_RANGE_FULL); - } else { - frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT; - frame.avi.ycc_quantization_range = - HDMI_YCC_QUANTIZATION_RANGE_LIMITED; - } - - return inno_hdmi_upload_frame(hdmi, &frame, HDMI_INFOFRAME_TYPE_AVI); -} +static const struct drm_connector_hdmi_funcs inno_hdmi_hdmi_connector_funcs = { + .clear_infoframe = inno_hdmi_disable_frame, + .write_infoframe = inno_hdmi_upload_frame, +}; static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) { @@ -361,8 +325,8 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) v_VIDEO_INPUT_CSP(0); hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value); - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) { - if (inno_conn_state->rgb_limited_range) { + if (conn_state->hdmi.output_format == HDMI_COLORSPACE_RGB) { + if (conn_state->hdmi.is_limited_range) { csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; @@ -380,14 +344,14 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) } } else { if (inno_conn_state->colorimetry == HDMI_COLORIMETRY_ITU_601) { - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) { + if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) { csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; csc_enable = v_CSC_ENABLE; } } else { - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) { + if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) { csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; @@ -462,10 +426,20 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, } static int inno_hdmi_setup(struct inno_hdmi *hdmi, - struct drm_display_mode *mode) + struct drm_atomic_state *state) { - struct drm_display_info *display = &hdmi->connector.display_info; - unsigned long mpixelclock = mode->clock * 1000; + struct drm_connector *connector = &hdmi->connector; + struct drm_display_info *display = &connector->display_info; + struct drm_connector_state *new_conn_state; + struct drm_crtc_state *new_crtc_state; + + new_conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!new_conn_state)) + return -EINVAL; + + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + if (WARN_ON(!new_crtc_state)) + return -EINVAL; /* Mute video and audio output */ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, @@ -475,12 +449,11 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, hdmi_writeb(hdmi, HDMI_HDCP_CTRL, v_HDMI_DVI(display->is_hdmi)); - inno_hdmi_config_video_timing(hdmi, mode); + inno_hdmi_config_video_timing(hdmi, &new_crtc_state->adjusted_mode); inno_hdmi_config_video_csc(hdmi); - if (display->is_hdmi) - inno_hdmi_config_video_avi(hdmi, mode); + drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); /* * When IP controller have configured to an accurate video @@ -488,13 +461,13 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, * DCLK_LCDC, so we need to init the TMDS rate to mode pixel * clock rate, and reconfigure the DDC clock. */ - inno_hdmi_i2c_init(hdmi, mpixelclock); + inno_hdmi_i2c_init(hdmi, new_conn_state->hdmi.tmds_char_rate); /* Unmute video and audio output */ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0)); - inno_hdmi_power_up(hdmi, mpixelclock); + inno_hdmi_power_up(hdmi, new_conn_state->hdmi.tmds_char_rate); return 0; } @@ -535,18 +508,8 @@ static void inno_hdmi_encoder_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); - struct drm_connector_state *conn_state; - struct drm_crtc_state *crtc_state; - conn_state = drm_atomic_get_new_connector_state(state, &hdmi->connector); - if (WARN_ON(!conn_state)) - return; - - crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); - if (WARN_ON(!crtc_state)) - return; - - inno_hdmi_setup(hdmi, &crtc_state->adjusted_mode); + inno_hdmi_setup(hdmi, state); } static void inno_hdmi_encoder_disable(struct drm_encoder *encoder, @@ -563,7 +526,6 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); - struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); struct drm_display_mode *mode = &crtc_state->adjusted_mode; u8 vic = drm_match_cea_mode(mode); struct inno_hdmi_connector_state *inno_conn_state = @@ -580,12 +542,7 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, else inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709; - inno_conn_state->enc_out_format = HDMI_COLORSPACE_RGB; - inno_conn_state->rgb_limited_range = - drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED; - - return inno_hdmi_display_mode_valid(hdmi, - &crtc_state->adjusted_mode) == MODE_OK ? 0 : -EINVAL; + return 0; } static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = { @@ -629,12 +586,6 @@ inno_hdmi_connector_mode_valid(struct drm_connector *connector, return inno_hdmi_display_mode_valid(hdmi, mode); } -static void inno_hdmi_connector_destroy(struct drm_connector *connector) -{ - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - static void inno_hdmi_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state) @@ -660,10 +611,9 @@ static void inno_hdmi_connector_reset(struct drm_connector *connector) return; __drm_atomic_helper_connector_reset(connector, &inno_conn_state->base); + __drm_atomic_helper_connector_hdmi_reset(connector, connector->state); inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709; - inno_conn_state->enc_out_format = HDMI_COLORSPACE_RGB; - inno_conn_state->rgb_limited_range = false; } static struct drm_connector_state * @@ -689,13 +639,13 @@ inno_hdmi_connector_duplicate_state(struct drm_connector *connector) static const struct drm_connector_funcs inno_hdmi_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .detect = inno_hdmi_connector_detect, - .destroy = inno_hdmi_connector_destroy, .reset = inno_hdmi_connector_reset, .atomic_duplicate_state = inno_hdmi_connector_duplicate_state, .atomic_destroy_state = inno_hdmi_connector_destroy_state, }; static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = { + .atomic_check = drm_atomic_helper_connector_hdmi_check, .get_modes = inno_hdmi_connector_get_modes, .mode_valid = inno_hdmi_connector_mode_valid, }; @@ -723,10 +673,14 @@ static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) drm_connector_helper_add(&hdmi->connector, &inno_hdmi_connector_helper_funcs); - drm_connector_init_with_ddc(drm, &hdmi->connector, - &inno_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA, - hdmi->ddc); + drmm_connector_hdmi_init(drm, &hdmi->connector, + "Rockchip", "Inno HDMI", + &inno_hdmi_connector_funcs, + &inno_hdmi_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA, + hdmi->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); drm_connector_attach_encoder(&hdmi->connector, encoder); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index ab55d7132550..44d769d9234d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -18,7 +18,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> @@ -191,7 +191,7 @@ static int rockchip_drm_bind(struct device *dev) if (ret) goto err_kms_helper_poll_fini; - drm_fbdev_generic_setup(drm_dev, 0); + drm_fbdev_dma_setup(drm_dev, 0); return 0; err_kms_helper_poll_fini: diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 62ebbdb16253..9873172e3fd3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -2344,7 +2344,7 @@ static void vop2_setup_layer_mixer(struct vop2_video_port *vp) port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1)); else - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8); layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index ebd943b9e357..6f51bcf774e2 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -23,7 +23,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_edid.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -2029,7 +2029,7 @@ struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap) if (ret) return ERR_PTR(dev_err_probe(dev, ret, "DRM device register failed\n")); - drm_fbdev_generic_setup(drm, 32); + drm_fbdev_shmem_setup(drm, 32); return ssd130x; } diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig index 3c7a5feff8de..75c301aadcbc 100644 --- a/drivers/gpu/drm/sti/Kconfig +++ b/drivers/gpu/drm/sti/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_STI tristate "DRM Support for STMicroelectronics SoC stiH4xx Series" - depends on OF && DRM && ARCH_STI + depends on OF && DRM && (ARCH_STI || COMPILE_TEST) select RESET_CONTROLLER select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index fd1df4ce3852..48a5d49fc131 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -7,6 +7,7 @@ #include <linux/clk.h> #include <linux/component.h> #include <linux/debugfs.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig index fa49cde43bb2..4c906d602825 100644 --- a/drivers/gpu/drm/stm/Kconfig +++ b/drivers/gpu/drm/stm/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_STM tristate "DRM Support for STMicroelectronics SoC Series" - depends on DRM && ARCH_STM32 + depends on DRM && (ARCH_STM32 || COMPILE_TEST) select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_PANEL_BRIDGE diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig index 4741d9f6544c..4037e085430e 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig @@ -18,6 +18,9 @@ if DRM_SUN4I config DRM_SUN4I_HDMI tristate "Allwinner A10/A10s/A20/A31 HDMI Controller Support" depends on ARM || COMPILE_TEST + select DRM_DISPLAY_HDMI_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER + select DRM_DISPLAY_HELPER default DRM_SUN4I help Choose this option if you have an Allwinner A10/A10s/A20/A31 diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 335fd0edb904..e89eb96d3131 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -69,7 +69,9 @@ static void sun4i_backend_disable_color_correction(struct sunxi_engine *engine) SUN4I_BACKEND_OCCTL_ENABLE, 0); } -static void sun4i_backend_commit(struct sunxi_engine *engine) +static void sun4i_backend_commit(struct sunxi_engine *engine, + struct drm_crtc *crtc, + struct drm_atomic_state *state) { DRM_DEBUG_DRIVER("Committing changes\n"); diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index c06d7cd45388..18e74047b0f5 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -91,7 +91,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc, DRM_DEBUG_DRIVER("Committing plane changes\n"); - sunxi_engine_commit(scrtc->engine); + sunxi_engine_commit(scrtc->engine, crtc, state); if (event) { crtc->state->event = NULL; diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c index 245b34adca5a..b3649449de30 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c @@ -26,6 +26,9 @@ #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> +#include <drm/display/drm_hdmi_helper.h> +#include <drm/display/drm_hdmi_state_helper.h> + #include "sun4i_backend.h" #include "sun4i_crtc.h" #include "sun4i_drv.h" @@ -37,30 +40,24 @@ #define drm_connector_to_sun4i_hdmi(c) \ container_of_const(c, struct sun4i_hdmi, connector) -static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi, - struct drm_display_mode *mode) +static int sun4i_hdmi_write_infoframe(struct drm_connector *connector, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len) { - struct hdmi_avi_infoframe frame; - u8 buffer[17]; - int i, ret; - - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, - &hdmi->connector, mode); - if (ret < 0) { - DRM_ERROR("Failed to get infoframes from mode\n"); - return ret; - } + struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); + int i; - ret = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); - if (ret < 0) { - DRM_ERROR("Failed to pack infoframes\n"); - return ret; + if (type != HDMI_INFOFRAME_TYPE_AVI) { + drm_err(connector->dev, + "Unsupported infoframe type: %u\n", type); + return 0; } - for (i = 0; i < sizeof(buffer); i++) + for (i = 0; i < len; i++) writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i)); return 0; + } static void sun4i_hdmi_disable(struct drm_encoder *encoder, @@ -83,14 +80,18 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder, { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); - struct drm_display_info *display = &hdmi->connector.display_info; + struct drm_connector *connector = &hdmi->connector; + struct drm_display_info *display = &connector->display_info; + struct drm_connector_state *conn_state = + drm_atomic_get_new_connector_state(state, connector); + unsigned long long tmds_rate = conn_state->hdmi.tmds_char_rate; unsigned int x, y; u32 val = 0; DRM_DEBUG_DRIVER("Enabling the HDMI Output\n"); - clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000); - clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000); + clk_set_rate(hdmi->mod_clk, tmds_rate); + clk_set_rate(hdmi->tmds_clk, tmds_rate); /* Set input sync enable */ writel(SUN4I_HDMI_UNKNOWN_INPUT_SYNC, @@ -143,7 +144,8 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder, clk_prepare_enable(hdmi->tmds_clk); - sun4i_hdmi_setup_avi_infoframes(hdmi, mode); + drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); + val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI); val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END); writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0)); @@ -196,7 +198,7 @@ static int sun4i_hdmi_connector_atomic_check(struct drm_connector *connector, enum drm_mode_status status; status = sun4i_hdmi_connector_clock_valid(connector, mode, - mode->clock * 1000); + conn_state->hdmi.tmds_char_rate); if (status != MODE_OK) return -EINVAL; @@ -207,8 +209,10 @@ static enum drm_mode_status sun4i_hdmi_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - return sun4i_hdmi_connector_clock_valid(connector, mode, - mode->clock * 1000); + unsigned long long rate = drm_hdmi_compute_mode_clock(mode, 8, + HDMI_COLORSPACE_RGB); + + return sun4i_hdmi_connector_clock_valid(connector, mode, rate); } static int sun4i_hdmi_get_modes(struct drm_connector *connector) @@ -258,6 +262,11 @@ static struct i2c_adapter *sun4i_hdmi_get_ddc(struct device *dev) return ddc; } +static const struct drm_connector_hdmi_funcs sun4i_hdmi_hdmi_connector_funcs = { + .tmds_char_rate_valid = sun4i_hdmi_connector_clock_valid, + .write_infoframe = sun4i_hdmi_write_infoframe, +}; + static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = { .atomic_check = sun4i_hdmi_connector_atomic_check, .mode_valid = sun4i_hdmi_connector_mode_valid, @@ -279,11 +288,16 @@ sun4i_hdmi_connector_detect(struct drm_connector *connector, bool force) return connector_status_connected; } +static void sun4i_hdmi_connector_reset(struct drm_connector *connector) +{ + drm_atomic_helper_connector_reset(connector); + __drm_atomic_helper_connector_hdmi_reset(connector, connector->state); +} + static const struct drm_connector_funcs sun4i_hdmi_connector_funcs = { .detect = sun4i_hdmi_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, - .reset = drm_atomic_helper_connector_reset, + .reset = sun4i_hdmi_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; @@ -642,10 +656,19 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, drm_connector_helper_add(&hdmi->connector, &sun4i_hdmi_connector_helper_funcs); - ret = drm_connector_init_with_ddc(drm, &hdmi->connector, - &sun4i_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA, - hdmi->ddc_i2c); + ret = drmm_connector_hdmi_init(drm, &hdmi->connector, + /* + * NOTE: Those are likely to be + * wrong, but I couldn't find the + * actual ones in the BSP. + */ + "AW", "HDMI", + &sun4i_hdmi_connector_funcs, + &sun4i_hdmi_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA, + hdmi->ddc_i2c, + BIT(HDMI_COLORSPACE_RGB), + 8); if (ret) { dev_err(dev, "Couldn't initialise the HDMI connector\n"); diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 01382860aaee..bd0fe2c6624e 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -16,6 +16,7 @@ #include <linux/platform_device.h> #include <linux/reset.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_framebuffer.h> @@ -249,10 +250,73 @@ int sun8i_mixer_drm_format_to_hw(u32 format, u32 *hw_format) return -EINVAL; } -static void sun8i_mixer_commit(struct sunxi_engine *engine) +static void sun8i_layer_enable(struct sun8i_layer *layer, bool enable) { + u32 ch_base = sun8i_channel_base(layer->mixer, layer->channel); + u32 val, reg, mask; + + if (layer->type == SUN8I_LAYER_TYPE_UI) { + val = enable ? SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN : 0; + mask = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN; + reg = SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, layer->overlay); + } else { + val = enable ? SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN : 0; + mask = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN; + reg = SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, layer->overlay); + } + + regmap_update_bits(layer->mixer->engine.regs, reg, mask, val); +} + +static void sun8i_mixer_commit(struct sunxi_engine *engine, + struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); + u32 bld_base = sun8i_blender_base(mixer); + struct drm_plane_state *plane_state; + struct drm_plane *plane; + u32 route = 0, pipe_en = 0; + DRM_DEBUG_DRIVER("Committing changes\n"); + drm_for_each_plane(plane, state->dev) { + struct sun8i_layer *layer = plane_to_sun8i_layer(plane); + bool enable; + int zpos; + + if (!(plane->possible_crtcs & drm_crtc_mask(crtc)) || layer->mixer != mixer) + continue; + + plane_state = drm_atomic_get_new_plane_state(state, plane); + if (!plane_state) + plane_state = plane->state; + + enable = plane_state->crtc && plane_state->visible; + zpos = plane_state->normalized_zpos; + + DRM_DEBUG_DRIVER(" plane %d: chan=%d ovl=%d en=%d zpos=%d\n", + plane->base.id, layer->channel, layer->overlay, + enable, zpos); + + /* + * We always update the layer enable bit, because it can clear + * spontaneously for unknown reasons. + */ + sun8i_layer_enable(layer, enable); + + if (!enable) + continue; + + /* Route layer to pipe based on zpos */ + route |= layer->channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos); + pipe_en |= SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos); + } + + regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), route); + regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), + pipe_en | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); + regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF, SUN8I_MIXER_GLOBAL_DBUFF_ENABLE); } @@ -271,7 +335,7 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm, return ERR_PTR(-ENOMEM); for (i = 0; i < mixer->cfg->vi_num; i++) { - struct sun8i_vi_layer *layer; + struct sun8i_layer *layer; layer = sun8i_vi_layer_init_one(drm, mixer, i); if (IS_ERR(layer)) { @@ -284,7 +348,7 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm, } for (i = 0; i < mixer->cfg->ui_num; i++) { - struct sun8i_ui_layer *layer; + struct sun8i_layer *layer; layer = sun8i_ui_layer_init_one(drm, mixer, i); if (IS_ERR(layer)) { diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h index 85c94884fb9a..d7898c9c9cc0 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h @@ -9,6 +9,7 @@ #include <linux/clk.h> #include <linux/regmap.h> #include <linux/reset.h> +#include <drm/drm_plane.h> #include "sunxi_engine.h" @@ -185,6 +186,25 @@ struct sun8i_mixer { struct clk *mod_clk; }; +enum { + SUN8I_LAYER_TYPE_UI, + SUN8I_LAYER_TYPE_VI, +}; + +struct sun8i_layer { + struct drm_plane plane; + struct sun8i_mixer *mixer; + int type; + int channel; + int overlay; +}; + +static inline struct sun8i_layer * +plane_to_sun8i_layer(struct drm_plane *plane) +{ + return container_of(plane, struct sun8i_layer, plane); +} + static inline struct sun8i_mixer * engine_to_sun8i_mixer(struct sunxi_engine *engine) { diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index ca75ca0835a6..b90e5edef4e8 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -24,55 +24,6 @@ #include "sun8i_ui_layer.h" #include "sun8i_ui_scaler.h" -static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel, - int overlay, bool enable, unsigned int zpos, - unsigned int old_zpos) -{ - u32 val, bld_base, ch_base; - - bld_base = sun8i_blender_base(mixer); - ch_base = sun8i_channel_base(mixer, channel); - - DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n", - enable ? "En" : "Dis", channel, overlay); - - if (enable) - val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN; - else - val = 0; - - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay), - SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val); - - if (!enable || zpos != old_zpos) { - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), - SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos), - 0); - - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_ROUTE(bld_base), - SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos), - 0); - } - - if (enable) { - val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos); - - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), - val, val); - - val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos); - - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_ROUTE(bld_base), - SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos), - val); - } -} - static void sun8i_ui_layer_update_alpha(struct sun8i_mixer *mixer, int channel, int overlay, struct drm_plane *plane) { @@ -232,7 +183,7 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane, { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); - struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane); + struct sun8i_layer *layer = plane_to_sun8i_layer(plane); struct drm_crtc *crtc = new_plane_state->crtc; struct drm_crtc_state *crtc_state; int min_scale, max_scale; @@ -259,36 +210,18 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane, true, true); } -static void sun8i_ui_layer_atomic_disable(struct drm_plane *plane, - struct drm_atomic_state *state) -{ - struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, - plane); - struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane); - unsigned int old_zpos = old_state->normalized_zpos; - struct sun8i_mixer *mixer = layer->mixer; - - sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false, 0, - old_zpos); -} static void sun8i_ui_layer_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state) { - struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, - plane); struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); - struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane); + struct sun8i_layer *layer = plane_to_sun8i_layer(plane); unsigned int zpos = new_state->normalized_zpos; - unsigned int old_zpos = old_state->normalized_zpos; struct sun8i_mixer *mixer = layer->mixer; - if (!new_state->visible) { - sun8i_ui_layer_enable(mixer, layer->channel, - layer->overlay, false, 0, old_zpos); + if (!new_state->crtc || !new_state->visible) return; - } sun8i_ui_layer_update_coord(mixer, layer->channel, layer->overlay, plane, zpos); @@ -298,13 +231,10 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane, layer->overlay, plane); sun8i_ui_layer_update_buffer(mixer, layer->channel, layer->overlay, plane); - sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, - true, zpos, old_zpos); } static const struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { .atomic_check = sun8i_ui_layer_atomic_check, - .atomic_disable = sun8i_ui_layer_atomic_disable, .atomic_update = sun8i_ui_layer_atomic_update, }; @@ -345,13 +275,13 @@ static const uint64_t sun8i_layer_modifiers[] = { DRM_FORMAT_MOD_INVALID }; -struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm, - struct sun8i_mixer *mixer, - int index) +struct sun8i_layer *sun8i_ui_layer_init_one(struct drm_device *drm, + struct sun8i_mixer *mixer, + int index) { enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY; int channel = mixer->cfg->vi_num + index; - struct sun8i_ui_layer *layer; + struct sun8i_layer *layer; unsigned int plane_cnt; int ret; @@ -390,6 +320,7 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm, drm_plane_helper_add(&layer->plane, &sun8i_ui_layer_helper_funcs); layer->mixer = mixer; + layer->type = SUN8I_LAYER_TYPE_UI; layer->channel = channel; layer->overlay = 0; diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.h b/drivers/gpu/drm/sun4i/sun8i_ui_layer.h index e3e32ee1178d..83892f6ff211 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.h +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.h @@ -47,21 +47,9 @@ #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_COMBINED ((2) << 1) struct sun8i_mixer; +struct sun8i_layer; -struct sun8i_ui_layer { - struct drm_plane plane; - struct sun8i_mixer *mixer; - int channel; - int overlay; -}; - -static inline struct sun8i_ui_layer * -plane_to_sun8i_ui_layer(struct drm_plane *plane) -{ - return container_of(plane, struct sun8i_ui_layer, plane); -} - -struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm, - struct sun8i_mixer *mixer, - int index); +struct sun8i_layer *sun8i_ui_layer_init_one(struct drm_device *drm, + struct sun8i_mixer *mixer, + int index); #endif /* _SUN8I_UI_LAYER_H_ */ diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index f9c0a56d3a14..9c09d9c08496 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -18,55 +18,6 @@ #include "sun8i_vi_layer.h" #include "sun8i_vi_scaler.h" -static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, - int overlay, bool enable, unsigned int zpos, - unsigned int old_zpos) -{ - u32 val, bld_base, ch_base; - - bld_base = sun8i_blender_base(mixer); - ch_base = sun8i_channel_base(mixer, channel); - - DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n", - enable ? "En" : "Dis", channel, overlay); - - if (enable) - val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN; - else - val = 0; - - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay), - SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val); - - if (!enable || zpos != old_zpos) { - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), - SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos), - 0); - - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_ROUTE(bld_base), - SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos), - 0); - } - - if (enable) { - val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos); - - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), - val, val); - - val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos); - - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_ROUTE(bld_base), - SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos), - val); - } -} - static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel, int overlay, struct drm_plane *plane) { @@ -366,7 +317,7 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); - struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); + struct sun8i_layer *layer = plane_to_sun8i_layer(plane); struct drm_crtc *crtc = new_plane_state->crtc; struct drm_crtc_state *crtc_state; int min_scale, max_scale; @@ -393,36 +344,17 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, true, true); } -static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane, - struct drm_atomic_state *state) -{ - struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, - plane); - struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); - unsigned int old_zpos = old_state->normalized_zpos; - struct sun8i_mixer *mixer = layer->mixer; - - sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0, - old_zpos); -} - static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state) { - struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, - plane); struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); - struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); + struct sun8i_layer *layer = plane_to_sun8i_layer(plane); unsigned int zpos = new_state->normalized_zpos; - unsigned int old_zpos = old_state->normalized_zpos; struct sun8i_mixer *mixer = layer->mixer; - if (!new_state->visible) { - sun8i_vi_layer_enable(mixer, layer->channel, - layer->overlay, false, 0, old_zpos); + if (!new_state->crtc || !new_state->visible) return; - } sun8i_vi_layer_update_coord(mixer, layer->channel, layer->overlay, plane, zpos); @@ -432,13 +364,10 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, layer->overlay, plane); sun8i_vi_layer_update_buffer(mixer, layer->channel, layer->overlay, plane); - sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, - true, zpos, old_zpos); } static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { .atomic_check = sun8i_vi_layer_atomic_check, - .atomic_disable = sun8i_vi_layer_atomic_disable, .atomic_update = sun8i_vi_layer_atomic_update, }; @@ -539,14 +468,14 @@ static const uint64_t sun8i_layer_modifiers[] = { DRM_FORMAT_MOD_INVALID }; -struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, - struct sun8i_mixer *mixer, - int index) +struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm, + struct sun8i_mixer *mixer, + int index) { enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY; u32 supported_encodings, supported_ranges; unsigned int plane_cnt, format_count; - struct sun8i_vi_layer *layer; + struct sun8i_layer *layer; const u32 *formats; int ret; @@ -613,6 +542,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs); layer->mixer = mixer; + layer->type = SUN8I_LAYER_TYPE_VI; layer->channel = index; layer->overlay = 0; diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h index 48c399e1c86d..655440cdc78f 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h @@ -52,21 +52,9 @@ #define SUN8I_MIXER_CHAN_VI_DS_M(x) ((x) << 0) struct sun8i_mixer; +struct sun8i_layer; -struct sun8i_vi_layer { - struct drm_plane plane; - struct sun8i_mixer *mixer; - int channel; - int overlay; -}; - -static inline struct sun8i_vi_layer * -plane_to_sun8i_vi_layer(struct drm_plane *plane) -{ - return container_of(plane, struct sun8i_vi_layer, plane); -} - -struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, - struct sun8i_mixer *mixer, - int index); +struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm, + struct sun8i_mixer *mixer, + int index); #endif /* _SUN8I_VI_LAYER_H_ */ diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h index ec8cf9b2bda4..ec0c4932f15c 100644 --- a/drivers/gpu/drm/sun4i/sunxi_engine.h +++ b/drivers/gpu/drm/sun4i/sunxi_engine.h @@ -7,6 +7,7 @@ #define _SUNXI_ENGINE_H_ struct drm_plane; +struct drm_crtc; struct drm_device; struct drm_crtc_state; struct drm_display_mode; @@ -59,7 +60,9 @@ struct sunxi_engine_ops { * * This function is optional. */ - void (*commit)(struct sunxi_engine *engine); + void (*commit)(struct sunxi_engine *engine, + struct drm_crtc *crtc, + struct drm_atomic_state *state); /** * @layers_init: @@ -144,12 +147,16 @@ struct sunxi_engine { /** * sunxi_engine_commit() - commit all changes of the engine * @engine: pointer to the engine + * @crtc: pointer to crtc the engine is associated with + * @state: atomic state */ static inline void -sunxi_engine_commit(struct sunxi_engine *engine) +sunxi_engine_commit(struct sunxi_engine *engine, + struct drm_crtc *crtc, + struct drm_atomic_state *state) { if (engine->ops && engine->ops->commit) - engine->ops->commit(engine); + engine->ops->commit(engine, crtc, state); } /** diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index d6183b3d7688..56dab563abd7 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \ drm_format_test.o \ drm_framebuffer_test.o \ drm_gem_shmem_test.o \ + drm_hdmi_state_helper_test.o \ drm_managed_test.o \ drm_mm_test.o \ drm_modes_test.o \ diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c index dd8fb9f8341a..9662c949d0e3 100644 --- a/drivers/gpu/drm/tests/drm_buddy_test.c +++ b/drivers/gpu/drm/tests/drm_buddy_test.c @@ -774,4 +774,5 @@ static struct kunit_suite drm_buddy_test_suite = { kunit_test_suite(drm_buddy_test_suite); MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Kunit test for drm_buddy functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c index 88f7f518ffb3..6f1457bd21d9 100644 --- a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c +++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c @@ -1056,4 +1056,5 @@ static struct kunit_suite drm_cmdline_parser_test_suite = { kunit_test_suite(drm_cmdline_parser_test_suite); MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin.com>"); +MODULE_DESCRIPTION("Kunit test for drm_cmdline_parser functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_connector_test.c b/drivers/gpu/drm/tests/drm_connector_test.c index 44f82ed2a958..2812b123a79c 100644 --- a/drivers/gpu/drm/tests/drm_connector_test.c +++ b/drivers/gpu/drm/tests/drm_connector_test.c @@ -8,16 +8,25 @@ #include <drm/drm_atomic_state_helper.h> #include <drm/drm_connector.h> #include <drm/drm_drv.h> +#include <drm/drm_edid.h> #include <drm/drm_kunit_helpers.h> +#include <drm/drm_modes.h> + +#include <drm/display/drm_hdmi_helper.h> #include <kunit/test.h> +#include "../drm_crtc_internal.h" + struct drm_connector_init_priv { struct drm_device drm; struct drm_connector connector; struct i2c_adapter ddc; }; +static const struct drm_connector_hdmi_funcs dummy_hdmi_funcs = { +}; + static const struct drm_connector_funcs dummy_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, @@ -172,6 +181,573 @@ static struct kunit_suite drmm_connector_init_test_suite = { .test_cases = drmm_connector_init_tests, }; +/* + * Test that the registration of a bog standard connector works as + * expected and doesn't report any error. + */ +static void drm_test_connector_hdmi_init_valid(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_EQ(test, ret, 0); +} + +/* + * Test that the registration of a connector without a DDC adapter + * doesn't report any error. + */ +static void drm_test_connector_hdmi_init_null_ddc(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + NULL, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_EQ(test, ret, 0); +} + +/* + * Test that the registration of an HDMI connector with a NULL vendor + * fails. + */ +static void drm_test_connector_hdmi_init_null_vendor(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + NULL, "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_LT(test, ret, 0); +} + +/* + * Test that the registration of an HDMI connector with a NULL product + * fails. + */ +static void drm_test_connector_hdmi_init_null_product(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", NULL, + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_LT(test, ret, 0); +} + +/* + * Test that the registration of a connector with a valid, shorter than + * the max length, product name succeeds, and is stored padded with 0. + */ +static void drm_test_connector_hdmi_init_product_valid(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const unsigned char expected_product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] = { + 'P', 'r', 'o', 'd', + }; + const char *product_name = "Prod"; + int ret; + + KUNIT_ASSERT_LT(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN); + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", product_name, + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_MEMEQ(test, + priv->connector.hdmi.product, + expected_product, + sizeof(priv->connector.hdmi.product)); +} + +/* + * Test that the registration of a connector with a valid, at max + * length, product name succeeds, and is stored padded without any + * trailing \0. + */ +static void drm_test_connector_hdmi_init_product_length_exact(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const unsigned char expected_product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] = { + 'P', 'r', 'o', 'd', 'u', 'c', 't', + 'P', 'r', 'o', 'd', 'u', 'c', 't', + 'P', 'r', + }; + const char *product_name = "ProductProductPr"; + int ret; + + KUNIT_ASSERT_EQ(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN); + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", product_name, + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_MEMEQ(test, + priv->connector.hdmi.product, + expected_product, + sizeof(priv->connector.hdmi.product)); +} + +/* + * Test that the registration of a connector with a product name larger + * than the maximum length fails. + */ +static void drm_test_connector_hdmi_init_product_length_too_long(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const char *product_name = "ProductProductProduct"; + int ret; + + KUNIT_ASSERT_GT(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN); + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", product_name, + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_LT(test, ret, 0); +} + +/* + * Test that the registration of a connector with a vendor name smaller + * than the maximum length succeeds, and is stored padded with zeros. + */ +static void drm_test_connector_hdmi_init_vendor_valid(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const char expected_vendor[DRM_CONNECTOR_HDMI_VENDOR_LEN] = { + 'V', 'e', 'n', 'd', + }; + const char *vendor_name = "Vend"; + int ret; + + KUNIT_ASSERT_LT(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN); + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + vendor_name, "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_MEMEQ(test, + priv->connector.hdmi.vendor, + expected_vendor, + sizeof(priv->connector.hdmi.vendor)); +} + +/* + * Test that the registration of a connector with a vendor name at the + * maximum length succeeds, and is stored padded without the trailing + * zero. + */ +static void drm_test_connector_hdmi_init_vendor_length_exact(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const char expected_vendor[DRM_CONNECTOR_HDMI_VENDOR_LEN] = { + 'V', 'e', 'n', 'd', 'o', 'r', + 'V', 'e', + }; + const char *vendor_name = "VendorVe"; + int ret; + + KUNIT_ASSERT_EQ(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN); + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + vendor_name, "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_MEMEQ(test, + priv->connector.hdmi.vendor, + expected_vendor, + sizeof(priv->connector.hdmi.vendor)); +} + +/* + * Test that the registration of a connector with a vendor name larger + * than the maximum length fails. + */ +static void drm_test_connector_hdmi_init_vendor_length_too_long(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const char *vendor_name = "VendorVendor"; + int ret; + + KUNIT_ASSERT_GT(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN); + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + vendor_name, "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_LT(test, ret, 0); +} + +/* + * Test that the registration of a connector with an invalid maximum bpc + * count fails. + */ +static void drm_test_connector_hdmi_init_bpc_invalid(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 9); + KUNIT_EXPECT_LT(test, ret, 0); +} + +/* + * Test that the registration of a connector with a null maximum bpc + * count fails. + */ +static void drm_test_connector_hdmi_init_bpc_null(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 0); + KUNIT_EXPECT_LT(test, ret, 0); +} + +/* + * Test that the registration of a connector with a maximum bpc count of + * 8 succeeds, registers the max bpc property, but doesn't register the + * HDR output metadata one. + */ +static void drm_test_connector_hdmi_init_bpc_8(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + struct drm_connector_state *state; + struct drm_connector *connector = &priv->connector; + struct drm_property *prop; + uint64_t val; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_EQ(test, ret, 0); + + prop = connector->max_bpc_property; + KUNIT_ASSERT_NOT_NULL(test, prop); + KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); + + ret = drm_object_property_get_default_value(&connector->base, prop, &val); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, val, 8); + + state = connector->state; + KUNIT_EXPECT_EQ(test, state->max_bpc, 8); + KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 8); + + prop = priv->drm.mode_config.hdr_output_metadata_property; + KUNIT_ASSERT_NOT_NULL(test, prop); + KUNIT_EXPECT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); +} + +/* + * Test that the registration of a connector with a maximum bpc count of + * 10 succeeds and registers the max bpc and HDR output metadata + * properties. + */ +static void drm_test_connector_hdmi_init_bpc_10(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + struct drm_connector_state *state; + struct drm_connector *connector = &priv->connector; + struct drm_property *prop; + uint64_t val; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 10); + KUNIT_EXPECT_EQ(test, ret, 0); + + prop = connector->max_bpc_property; + KUNIT_ASSERT_NOT_NULL(test, prop); + KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); + + ret = drm_object_property_get_default_value(&connector->base, prop, &val); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, val, 10); + + state = connector->state; + KUNIT_EXPECT_EQ(test, state->max_bpc, 10); + KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 10); + + prop = priv->drm.mode_config.hdr_output_metadata_property; + KUNIT_ASSERT_NOT_NULL(test, prop); + KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); +} + +/* + * Test that the registration of a connector with a maximum bpc count of + * 12 succeeds and registers the max bpc and HDR output metadata + * properties. + */ +static void drm_test_connector_hdmi_init_bpc_12(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + struct drm_connector_state *state; + struct drm_connector *connector = &priv->connector; + struct drm_property *prop; + uint64_t val; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 12); + KUNIT_EXPECT_EQ(test, ret, 0); + + prop = connector->max_bpc_property; + KUNIT_ASSERT_NOT_NULL(test, prop); + KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); + + ret = drm_object_property_get_default_value(&connector->base, prop, &val); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, val, 12); + + state = connector->state; + KUNIT_EXPECT_EQ(test, state->max_bpc, 12); + KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 12); + + prop = priv->drm.mode_config.hdr_output_metadata_property; + KUNIT_ASSERT_NOT_NULL(test, prop); + KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); +} + +/* + * Test that the registration of an HDMI connector with no supported + * format fails. + */ +static void drm_test_connector_hdmi_init_formats_empty(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + 0, + 8); + KUNIT_EXPECT_LT(test, ret, 0); +} + +/* + * Test that the registration of an HDMI connector not listing RGB as a + * supported format fails. + */ +static void drm_test_connector_hdmi_init_formats_no_rgb(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_YUV422), + 8); + KUNIT_EXPECT_LT(test, ret, 0); +} + +/* + * Test that the registration of an HDMI connector with an HDMI + * connector type succeeds. + */ +static void drm_test_connector_hdmi_init_type_valid(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + unsigned int connector_type = *(unsigned int *)test->param_value; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + connector_type, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_EQ(test, ret, 0); +} + +static const unsigned int drm_connector_hdmi_init_type_valid_tests[] = { + DRM_MODE_CONNECTOR_HDMIA, + DRM_MODE_CONNECTOR_HDMIB, +}; + +static void drm_connector_hdmi_init_type_desc(const unsigned int *type, char *desc) +{ + sprintf(desc, "%s", drm_get_connector_type_name(*type)); +} + +KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_valid, + drm_connector_hdmi_init_type_valid_tests, + drm_connector_hdmi_init_type_desc); + +/* + * Test that the registration of an HDMI connector with an !HDMI + * connector type fails. + */ +static void drm_test_connector_hdmi_init_type_invalid(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + unsigned int connector_type = *(unsigned int *)test->param_value; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + connector_type, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_LT(test, ret, 0); +} + +static const unsigned int drm_connector_hdmi_init_type_invalid_tests[] = { + DRM_MODE_CONNECTOR_Unknown, + DRM_MODE_CONNECTOR_VGA, + DRM_MODE_CONNECTOR_DVII, + DRM_MODE_CONNECTOR_DVID, + DRM_MODE_CONNECTOR_DVIA, + DRM_MODE_CONNECTOR_Composite, + DRM_MODE_CONNECTOR_SVIDEO, + DRM_MODE_CONNECTOR_LVDS, + DRM_MODE_CONNECTOR_Component, + DRM_MODE_CONNECTOR_9PinDIN, + DRM_MODE_CONNECTOR_DisplayPort, + DRM_MODE_CONNECTOR_TV, + DRM_MODE_CONNECTOR_eDP, + DRM_MODE_CONNECTOR_VIRTUAL, + DRM_MODE_CONNECTOR_DSI, + DRM_MODE_CONNECTOR_DPI, + DRM_MODE_CONNECTOR_WRITEBACK, + DRM_MODE_CONNECTOR_SPI, + DRM_MODE_CONNECTOR_USB, +}; + +KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_invalid, + drm_connector_hdmi_init_type_invalid_tests, + drm_connector_hdmi_init_type_desc); + +static struct kunit_case drmm_connector_hdmi_init_tests[] = { + KUNIT_CASE(drm_test_connector_hdmi_init_valid), + KUNIT_CASE(drm_test_connector_hdmi_init_bpc_8), + KUNIT_CASE(drm_test_connector_hdmi_init_bpc_10), + KUNIT_CASE(drm_test_connector_hdmi_init_bpc_12), + KUNIT_CASE(drm_test_connector_hdmi_init_bpc_invalid), + KUNIT_CASE(drm_test_connector_hdmi_init_bpc_null), + KUNIT_CASE(drm_test_connector_hdmi_init_formats_empty), + KUNIT_CASE(drm_test_connector_hdmi_init_formats_no_rgb), + KUNIT_CASE(drm_test_connector_hdmi_init_null_ddc), + KUNIT_CASE(drm_test_connector_hdmi_init_null_product), + KUNIT_CASE(drm_test_connector_hdmi_init_null_vendor), + KUNIT_CASE(drm_test_connector_hdmi_init_product_length_exact), + KUNIT_CASE(drm_test_connector_hdmi_init_product_length_too_long), + KUNIT_CASE(drm_test_connector_hdmi_init_product_valid), + KUNIT_CASE(drm_test_connector_hdmi_init_vendor_length_exact), + KUNIT_CASE(drm_test_connector_hdmi_init_vendor_length_too_long), + KUNIT_CASE(drm_test_connector_hdmi_init_vendor_valid), + KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_valid, + drm_connector_hdmi_init_type_valid_gen_params), + KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_invalid, + drm_connector_hdmi_init_type_invalid_gen_params), + { } +}; + +static struct kunit_suite drmm_connector_hdmi_init_test_suite = { + .name = "drmm_connector_hdmi_init", + .init = drm_test_connector_init, + .test_cases = drmm_connector_hdmi_init_tests, +}; + struct drm_get_tv_mode_from_name_test { const char *name; enum drm_connector_tv_mode expected_mode; @@ -235,10 +811,484 @@ static struct kunit_suite drm_get_tv_mode_from_name_test_suite = { .test_cases = drm_get_tv_mode_from_name_tests, }; +struct drm_hdmi_connector_get_broadcast_rgb_name_test { + unsigned int kind; + const char *expected_name; +}; + +#define BROADCAST_RGB_TEST(_kind, _name) \ + { \ + .kind = _kind, \ + .expected_name = _name, \ + } + +static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit *test) +{ + const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params = + test->param_value; + + KUNIT_EXPECT_STREQ(test, + drm_hdmi_connector_get_broadcast_rgb_name(params->kind), + params->expected_name); +} + +static const +struct drm_hdmi_connector_get_broadcast_rgb_name_test +drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = { + BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"), + BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"), + BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"), +}; + +static void +drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct drm_hdmi_connector_get_broadcast_rgb_name_test *t, + char *desc) +{ + sprintf(desc, "%s", t->expected_name); +} + +KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid, + drm_hdmi_connector_get_broadcast_rgb_name_valid_tests, + drm_hdmi_connector_get_broadcast_rgb_name_valid_desc); + +static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct kunit *test) +{ + KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3)); +}; + +static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] = { + KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name, + drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params), + KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid), + { } +}; + +static struct kunit_suite drm_hdmi_connector_get_broadcast_rgb_name_test_suite = { + .name = "drm_hdmi_connector_get_broadcast_rgb_name", + .test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests, +}; + +struct drm_hdmi_connector_get_output_format_name_test { + unsigned int kind; + const char *expected_name; +}; + +#define OUTPUT_FORMAT_TEST(_kind, _name) \ + { \ + .kind = _kind, \ + .expected_name = _name, \ + } + +static void drm_test_drm_hdmi_connector_get_output_format_name(struct kunit *test) +{ + const struct drm_hdmi_connector_get_output_format_name_test *params = + test->param_value; + + KUNIT_EXPECT_STREQ(test, + drm_hdmi_connector_get_output_format_name(params->kind), + params->expected_name); +} + +static const +struct drm_hdmi_connector_get_output_format_name_test +drm_hdmi_connector_get_output_format_name_valid_tests[] = { + OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_RGB, "RGB"), + OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV420, "YUV 4:2:0"), + OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV422, "YUV 4:2:2"), + OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV444, "YUV 4:4:4"), +}; + +static void +drm_hdmi_connector_get_output_format_name_valid_desc(const struct drm_hdmi_connector_get_output_format_name_test *t, + char *desc) +{ + sprintf(desc, "%s", t->expected_name); +} + +KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_output_format_name_valid, + drm_hdmi_connector_get_output_format_name_valid_tests, + drm_hdmi_connector_get_output_format_name_valid_desc); + +static void drm_test_drm_hdmi_connector_get_output_format_name_invalid(struct kunit *test) +{ + KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_output_format_name(4)); +}; + +static struct kunit_case drm_hdmi_connector_get_output_format_name_tests[] = { + KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_output_format_name, + drm_hdmi_connector_get_output_format_name_valid_gen_params), + KUNIT_CASE(drm_test_drm_hdmi_connector_get_output_format_name_invalid), + { } +}; + +static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite = { + .name = "drm_hdmi_connector_get_output_format_name", + .test_cases = drm_hdmi_connector_get_output_format_name_tests, +}; + +static void drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + struct drm_connector *connector = &priv->connector; + struct drm_property *prop; + int ret; + + ret = drmm_connector_init(&priv->drm, connector, + &dummy_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc); + KUNIT_ASSERT_EQ(test, ret, 0); + + ret = drm_connector_attach_broadcast_rgb_property(connector); + KUNIT_ASSERT_EQ(test, ret, 0); + + prop = connector->broadcast_rgb_property; + KUNIT_ASSERT_NOT_NULL(test, prop); + KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); +} + +static void drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + struct drm_connector *connector = &priv->connector; + struct drm_property *prop; + int ret; + + ret = drmm_connector_hdmi_init(&priv->drm, connector, + "Vendor", "Product", + &dummy_funcs, + &dummy_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + &priv->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_EXPECT_EQ(test, ret, 0); + + ret = drm_connector_attach_broadcast_rgb_property(connector); + KUNIT_ASSERT_EQ(test, ret, 0); + + prop = connector->broadcast_rgb_property; + KUNIT_ASSERT_NOT_NULL(test, prop); + KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); +} + +static struct kunit_case drm_connector_attach_broadcast_rgb_property_tests[] = { + KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property), + KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector), + { } +}; + +static struct kunit_suite drm_connector_attach_broadcast_rgb_property_test_suite = { + .name = "drm_connector_attach_broadcast_rgb_property", + .init = drm_test_connector_init, + .test_cases = drm_connector_attach_broadcast_rgb_property_tests, +}; + +/* + * Test that for a given mode, with 8bpc and an RGB output the TMDS + * character rate is equal to the mode pixel clock. + */ +static void drm_test_drm_hdmi_compute_mode_clock_rgb(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + unsigned long long rate; + struct drm_device *drm = &priv->drm; + + mode = drm_display_mode_from_cea_vic(drm, 16); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate); +} + +/* + * Test that for a given mode, with 10bpc and an RGB output the TMDS + * character rate is equal to 1.25 times the mode pixel clock. + */ +static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + unsigned long long rate; + struct drm_device *drm = &priv->drm; + + mode = drm_display_mode_from_cea_vic(drm, 16); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate); +} + +/* + * Test that for the VIC-1 mode, with 10bpc and an RGB output the TMDS + * character rate computation fails. + */ +static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + unsigned long long rate; + struct drm_device *drm = &priv->drm; + + mode = drm_display_mode_from_cea_vic(drm, 1); + KUNIT_ASSERT_NOT_NULL(test, mode); + + rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB); + KUNIT_EXPECT_EQ(test, rate, 0); +} + +/* + * Test that for a given mode, with 12bpc and an RGB output the TMDS + * character rate is equal to 1.5 times the mode pixel clock. + */ +static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + unsigned long long rate; + struct drm_device *drm = &priv->drm; + + mode = drm_display_mode_from_cea_vic(drm, 16); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate); +} + +/* + * Test that for the VIC-1 mode, with 12bpc and an RGB output the TMDS + * character rate computation fails. + */ +static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + unsigned long long rate; + struct drm_device *drm = &priv->drm; + + mode = drm_display_mode_from_cea_vic(drm, 1); + KUNIT_ASSERT_NOT_NULL(test, mode); + + rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB); + KUNIT_EXPECT_EQ(test, rate, 0); +} + +/* + * Test that for a mode with the pixel repetition flag, the TMDS + * character rate is indeed double the mode pixel clock. + */ +static void drm_test_drm_hdmi_compute_mode_clock_rgb_double(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + unsigned long long rate; + struct drm_device *drm = &priv->drm; + + mode = drm_display_mode_from_cea_vic(drm, 6); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) * 2, rate); +} + +/* + * Test that the TMDS character rate computation for the VIC modes + * explicitly listed in the spec as supporting YUV420 succeed and return + * half the mode pixel clock. + */ +static void drm_test_connector_hdmi_compute_mode_clock_yuv420_valid(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + struct drm_device *drm = &priv->drm; + unsigned long long rate; + unsigned int vic = *(unsigned int *)test->param_value; + + mode = drm_display_mode_from_cea_vic(drm, vic); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV420); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) / 2, rate); +} + +static const unsigned int drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[] = { + 96, 97, 101, 102, 106, 107, +}; + +static void drm_hdmi_compute_mode_clock_yuv420_vic_desc(const unsigned int *vic, char *desc) +{ + sprintf(desc, "VIC %u", *vic); +} + +KUNIT_ARRAY_PARAM(drm_hdmi_compute_mode_clock_yuv420_valid, + drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests, + drm_hdmi_compute_mode_clock_yuv420_vic_desc); + +/* + * Test that for a given mode listed supporting it and an YUV420 output + * with 10bpc, the TMDS character rate is equal to 0.625 times the mode + * pixel clock. + */ +static void drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + struct drm_device *drm = &priv->drm; + unsigned int vic = + drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0]; + unsigned long long rate; + + mode = drm_display_mode_from_cea_vic(drm, vic); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV420); + KUNIT_ASSERT_GT(test, rate, 0); + + KUNIT_EXPECT_EQ(test, mode->clock * 625, rate); +} + +/* + * Test that for a given mode listed supporting it and an YUV420 output + * with 12bpc, the TMDS character rate is equal to 0.75 times the mode + * pixel clock. + */ +static void drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + struct drm_device *drm = &priv->drm; + unsigned int vic = + drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0]; + unsigned long long rate; + + mode = drm_display_mode_from_cea_vic(drm, vic); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV420); + KUNIT_ASSERT_GT(test, rate, 0); + + KUNIT_EXPECT_EQ(test, mode->clock * 750, rate); +} + +/* + * Test that for a given mode, the computation of the TMDS character + * rate with 8bpc and a YUV422 output succeeds and returns a rate equal + * to the mode pixel clock. + */ +static void drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + struct drm_device *drm = &priv->drm; + unsigned long long rate; + + mode = drm_display_mode_from_cea_vic(drm, 16); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV422); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate); +} + +/* + * Test that for a given mode, the computation of the TMDS character + * rate with 10bpc and a YUV422 output succeeds and returns a rate equal + * to the mode pixel clock. + */ +static void drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + struct drm_device *drm = &priv->drm; + unsigned long long rate; + + mode = drm_display_mode_from_cea_vic(drm, 16); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV422); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate); +} + +/* + * Test that for a given mode, the computation of the TMDS character + * rate with 12bpc and a YUV422 output succeeds and returns a rate equal + * to the mode pixel clock. + */ +static void drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + const struct drm_display_mode *mode; + struct drm_device *drm = &priv->drm; + unsigned long long rate; + + mode = drm_display_mode_from_cea_vic(drm, 16); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV422); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate); +} + +static struct kunit_case drm_hdmi_compute_mode_clock_tests[] = { + KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb), + KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc), + KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1), + KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc), + KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1), + KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_double), + KUNIT_CASE_PARAM(drm_test_connector_hdmi_compute_mode_clock_yuv420_valid, + drm_hdmi_compute_mode_clock_yuv420_valid_gen_params), + KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc), + KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc), + KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc), + KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc), + KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc), + { } +}; + +static struct kunit_suite drm_hdmi_compute_mode_clock_test_suite = { + .name = "drm_test_connector_hdmi_compute_mode_clock", + .init = drm_test_connector_init, + .test_cases = drm_hdmi_compute_mode_clock_tests, +}; + kunit_test_suites( + &drmm_connector_hdmi_init_test_suite, &drmm_connector_init_test_suite, - &drm_get_tv_mode_from_name_test_suite + &drm_connector_attach_broadcast_rgb_property_test_suite, + &drm_get_tv_mode_from_name_test_suite, + &drm_hdmi_compute_mode_clock_test_suite, + &drm_hdmi_connector_get_broadcast_rgb_name_test_suite, + &drm_hdmi_connector_get_output_format_name_test_suite ); MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>"); +MODULE_DESCRIPTION("Kunit test for drm_modes functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c index 115034fc3421..0df2e1a54b0d 100644 --- a/drivers/gpu/drm/tests/drm_damage_helper_test.c +++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c @@ -636,4 +636,5 @@ static struct kunit_suite drm_damage_helper_test_suite = { kunit_test_suite(drm_damage_helper_test_suite); +MODULE_DESCRIPTION("Test case for drm_damage_helper functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c index d916e548fcb1..89cd9e4f4d32 100644 --- a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c +++ b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c @@ -588,4 +588,5 @@ static struct kunit_suite drm_dp_mst_helper_test_suite = { kunit_test_suite(drm_dp_mst_helper_test_suite); +MODULE_DESCRIPTION("Test cases for the DRM DP MST helpers"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_exec_test.c b/drivers/gpu/drm/tests/drm_exec_test.c index 81f928a429ba..d6c4dd1194a0 100644 --- a/drivers/gpu/drm/tests/drm_exec_test.c +++ b/drivers/gpu/drm/tests/drm_exec_test.c @@ -210,4 +210,5 @@ static struct kunit_suite drm_exec_test_suite = { kunit_test_suite(drm_exec_test_suite); MODULE_AUTHOR("AMD"); +MODULE_DESCRIPTION("Kunit test for drm_exec functions"); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/tests/drm_format_test.c b/drivers/gpu/drm/tests/drm_format_test.c index ec6996ce819a..22e2371fd66a 100644 --- a/drivers/gpu/drm/tests/drm_format_test.c +++ b/drivers/gpu/drm/tests/drm_format_test.c @@ -356,4 +356,5 @@ static struct kunit_suite drm_format_test_suite = { kunit_test_suite(drm_format_test_suite); +MODULE_DESCRIPTION("Test cases for the drm_format functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_framebuffer_test.c b/drivers/gpu/drm/tests/drm_framebuffer_test.c index f759d9f3b76e..06f03b78c9c4 100644 --- a/drivers/gpu/drm/tests/drm_framebuffer_test.c +++ b/drivers/gpu/drm/tests/drm_framebuffer_test.c @@ -379,4 +379,5 @@ static struct kunit_suite drm_framebuffer_test_suite = { kunit_test_suite(drm_framebuffer_test_suite); +MODULE_DESCRIPTION("Test cases for the drm_framebuffer functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_gem_shmem_test.c b/drivers/gpu/drm/tests/drm_gem_shmem_test.c index 91202e40cde9..c3758faa1b83 100644 --- a/drivers/gpu/drm/tests/drm_gem_shmem_test.c +++ b/drivers/gpu/drm/tests/drm_gem_shmem_test.c @@ -380,4 +380,5 @@ static struct kunit_suite drm_gem_shmem_suite = { kunit_test_suite(drm_gem_shmem_suite); +MODULE_DESCRIPTION("KUnit test suite for GEM objects backed by shmem buffers"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c new file mode 100644 index 000000000000..2d3abc71dc16 --- /dev/null +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -0,0 +1,1743 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Kunit test for drm_hdmi_state_helper functions + */ + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_atomic_uapi.h> +#include <drm/drm_drv.h> +#include <drm/drm_edid.h> +#include <drm/drm_connector.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_kunit_helpers.h> +#include <drm/drm_managed.h> +#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> + +#include <drm/display/drm_hdmi_helper.h> +#include <drm/display/drm_hdmi_state_helper.h> + +#include "../drm_crtc_internal.h" + +#include <kunit/test.h> + +#include "drm_kunit_edid.h" + +struct drm_atomic_helper_connector_hdmi_priv { + struct drm_device drm; + struct drm_plane *plane; + struct drm_crtc *crtc; + struct drm_encoder encoder; + struct drm_connector connector; + + const char *current_edid; + size_t current_edid_len; +}; + +#define connector_to_priv(c) \ + container_of_const(c, struct drm_atomic_helper_connector_hdmi_priv, connector) + +static struct drm_display_mode *find_preferred_mode(struct drm_connector *connector) +{ + struct drm_device *drm = connector->dev; + struct drm_display_mode *mode, *preferred; + + mutex_lock(&drm->mode_config.mutex); + preferred = list_first_entry(&connector->modes, struct drm_display_mode, head); + list_for_each_entry(mode, &connector->modes, head) + if (mode->type & DRM_MODE_TYPE_PREFERRED) + preferred = mode; + mutex_unlock(&drm->mode_config.mutex); + + return preferred; +} + +static int light_up_connector(struct kunit *test, + struct drm_device *drm, + struct drm_crtc *crtc, + struct drm_connector *connector, + struct drm_display_mode *mode, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_atomic_state *state; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + int ret; + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + conn_state = drm_atomic_get_connector_state(state, connector); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); + KUNIT_EXPECT_EQ(test, ret, 0); + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + ret = drm_atomic_set_mode_for_crtc(crtc_state, mode); + KUNIT_EXPECT_EQ(test, ret, 0); + + crtc_state->enable = true; + crtc_state->active = true; + + ret = drm_atomic_commit(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + return 0; +} + +static int set_connector_edid(struct kunit *test, struct drm_connector *connector, + const char *edid, size_t edid_len) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv = + connector_to_priv(connector); + struct drm_device *drm = connector->dev; + int ret; + + priv->current_edid = edid; + priv->current_edid_len = edid_len; + + mutex_lock(&drm->mode_config.mutex); + ret = connector->funcs->fill_modes(connector, 4096, 4096); + mutex_unlock(&drm->mode_config.mutex); + KUNIT_ASSERT_GT(test, ret, 0); + + return 0; +} + +static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = { +}; + +static enum drm_mode_status +reject_connector_tmds_char_rate_valid(const struct drm_connector *connector, + const struct drm_display_mode *mode, + unsigned long long tmds_rate) +{ + return MODE_BAD; +} + +static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = { + .tmds_char_rate_valid = reject_connector_tmds_char_rate_valid, +}; + +static int dummy_connector_get_modes(struct drm_connector *connector) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv = + connector_to_priv(connector); + const struct drm_edid *edid; + unsigned int num_modes; + + edid = drm_edid_alloc(priv->current_edid, priv->current_edid_len); + if (!edid) + return -EINVAL; + + drm_edid_connector_update(connector, edid); + num_modes = drm_edid_connector_add_modes(connector); + + drm_edid_free(edid); + + return num_modes; +} + +static const struct drm_connector_helper_funcs dummy_connector_helper_funcs = { + .atomic_check = drm_atomic_helper_connector_hdmi_check, + .get_modes = dummy_connector_get_modes, +}; + +static void dummy_hdmi_connector_reset(struct drm_connector *connector) +{ + drm_atomic_helper_connector_reset(connector); + __drm_atomic_helper_connector_hdmi_reset(connector, connector->state); +} + +static const struct drm_connector_funcs dummy_connector_funcs = { + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .fill_modes = drm_helper_probe_single_connector_modes, + .reset = dummy_hdmi_connector_reset, +}; + +static +struct drm_atomic_helper_connector_hdmi_priv * +drm_atomic_helper_connector_hdmi_init(struct kunit *test, + unsigned int formats, + unsigned int max_bpc) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_connector *conn; + struct drm_encoder *enc; + struct drm_device *drm; + struct device *dev; + int ret; + + dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + + priv = drm_kunit_helper_alloc_drm_device(test, dev, + struct drm_atomic_helper_connector_hdmi_priv, drm, + DRIVER_MODESET | DRIVER_ATOMIC); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + test->priv = priv; + + drm = &priv->drm; + priv->plane = drm_kunit_helper_create_primary_plane(test, drm, + NULL, + NULL, + NULL, 0, + NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->plane); + + priv->crtc = drm_kunit_helper_create_crtc(test, drm, + priv->plane, NULL, + NULL, + NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->crtc); + + enc = &priv->encoder; + ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL); + KUNIT_ASSERT_EQ(test, ret, 0); + + enc->possible_crtcs = drm_crtc_mask(priv->crtc); + + conn = &priv->connector; + ret = drmm_connector_hdmi_init(drm, conn, + "Vendor", "Product", + &dummy_connector_funcs, + &dummy_connector_hdmi_funcs, + DRM_MODE_CONNECTOR_HDMIA, + NULL, + formats, + max_bpc); + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_connector_helper_add(conn, &dummy_connector_helper_funcs); + drm_connector_attach_encoder(conn, enc); + + drm_mode_config_reset(drm); + + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_max_200mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + return priv; +} + +/* + * Test that if we change the RGB quantization property to a different + * value, we trigger a mode change on the connector's CRTC, which will + * in turn disable/enable the connector. + */ +static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *old_conn_state; + struct drm_connector_state *new_conn_state; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + conn = &priv->connector; + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + new_conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + + old_conn_state = drm_atomic_get_old_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); + + new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL; + + KUNIT_ASSERT_NE(test, + old_conn_state->hdmi.broadcast_rgb, + new_conn_state->hdmi.broadcast_rgb); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + new_conn_state = drm_atomic_get_new_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + KUNIT_EXPECT_EQ(test, new_conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_FULL); + + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed); +} + +/* + * Test that if we set the RGB quantization property to the same value, + * we don't trigger a mode change on the connector's CRTC and leave the + * connector unaffected. + */ +static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *old_conn_state; + struct drm_connector_state *new_conn_state; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + conn = &priv->connector; + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + new_conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + + old_conn_state = drm_atomic_get_old_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); + + new_conn_state->hdmi.broadcast_rgb = old_conn_state->hdmi.broadcast_rgb; + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + old_conn_state = drm_atomic_get_old_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); + + new_conn_state = drm_atomic_get_new_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + + KUNIT_EXPECT_EQ(test, + old_conn_state->hdmi.broadcast_rgb, + new_conn_state->hdmi.broadcast_rgb); + + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed); +} + +/* + * Test that for an HDMI connector, with an HDMI monitor, if the + * Broadcast RGB property is set to auto with a mode that isn't the + * VIC-1 mode, we will get a limited RGB Quantization Range. + */ +static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_atomic_state *state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + KUNIT_ASSERT_EQ(test, + conn_state->hdmi.broadcast_rgb, + DRM_HDMI_BROADCAST_RGB_AUTO); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); +} + +/* + * Test that for an HDMI connector, with an HDMI monitor, if the + * Broadcast RGB property is set to auto with a VIC-1 mode, we will get + * a full RGB Quantization Range. + */ +static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_atomic_state *state; + struct drm_display_mode *mode; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + conn = &priv->connector; + KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + mode = drm_display_mode_from_cea_vic(drm, 1); + KUNIT_ASSERT_NOT_NULL(test, mode); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, mode, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + KUNIT_ASSERT_EQ(test, + conn_state->hdmi.broadcast_rgb, + DRM_HDMI_BROADCAST_RGB_AUTO); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range); +} + +/* + * Test that for an HDMI connector, with an HDMI monitor, if the + * Broadcast RGB property is set to full with a mode that isn't the + * VIC-1 mode, we will get a full RGB Quantization Range. + */ +static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_atomic_state *state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL; + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + KUNIT_ASSERT_EQ(test, + conn_state->hdmi.broadcast_rgb, + DRM_HDMI_BROADCAST_RGB_FULL); + + KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range); +} + +/* + * Test that for an HDMI connector, with an HDMI monitor, if the + * Broadcast RGB property is set to full with a VIC-1 mode, we will get + * a full RGB Quantization Range. + */ +static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_atomic_state *state; + struct drm_display_mode *mode; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + conn = &priv->connector; + KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + mode = drm_display_mode_from_cea_vic(drm, 1); + KUNIT_ASSERT_NOT_NULL(test, mode); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, mode, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL; + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + KUNIT_ASSERT_EQ(test, + conn_state->hdmi.broadcast_rgb, + DRM_HDMI_BROADCAST_RGB_FULL); + + KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range); +} + +/* + * Test that for an HDMI connector, with an HDMI monitor, if the + * Broadcast RGB property is set to limited with a mode that isn't the + * VIC-1 mode, we will get a limited RGB Quantization Range. + */ +static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_atomic_state *state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED; + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + KUNIT_ASSERT_EQ(test, + conn_state->hdmi.broadcast_rgb, + DRM_HDMI_BROADCAST_RGB_LIMITED); + + KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); +} + +/* + * Test that for an HDMI connector, with an HDMI monitor, if the + * Broadcast RGB property is set to limited with a VIC-1 mode, we will + * get a limited RGB Quantization Range. + */ +static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_atomic_state *state; + struct drm_display_mode *mode; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + conn = &priv->connector; + KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + mode = drm_display_mode_from_cea_vic(drm, 1); + KUNIT_ASSERT_NOT_NULL(test, mode); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, mode, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED; + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + KUNIT_ASSERT_EQ(test, + conn_state->hdmi.broadcast_rgb, + DRM_HDMI_BROADCAST_RGB_LIMITED); + + KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); +} + +/* + * Test that if we change the maximum bpc property to a different value, + * we trigger a mode change on the connector's CRTC, which will in turn + * disable/enable the connector. + */ +static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *old_conn_state; + struct drm_connector_state *new_conn_state; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 10); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + new_conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + + old_conn_state = drm_atomic_get_old_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); + + new_conn_state->max_requested_bpc = 8; + + KUNIT_ASSERT_NE(test, + old_conn_state->max_requested_bpc, + new_conn_state->max_requested_bpc); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + old_conn_state = drm_atomic_get_old_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); + + new_conn_state = drm_atomic_get_new_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + + KUNIT_ASSERT_NE(test, + old_conn_state->hdmi.output_bpc, + new_conn_state->hdmi.output_bpc); + + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed); +} + +/* + * Test that if we set the output bpc property to the same value, we + * don't trigger a mode change on the connector's CRTC and leave the + * connector unaffected. + */ +static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *old_conn_state; + struct drm_connector_state *new_conn_state; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 10); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + new_conn_state = drm_atomic_get_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + + old_conn_state = drm_atomic_get_old_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); + + KUNIT_ASSERT_EQ(test, + new_conn_state->hdmi.output_bpc, + old_conn_state->hdmi.output_bpc); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + + old_conn_state = drm_atomic_get_old_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); + + new_conn_state = drm_atomic_get_new_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + + KUNIT_EXPECT_EQ(test, + old_conn_state->hdmi.output_bpc, + new_conn_state->hdmi.output_bpc); + + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed); +} + +/* + * Test that if we have an HDMI connector but a !HDMI display, we always + * output RGB with 8 bpc. + */ +static void drm_test_check_output_bpc_dvi(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_info *info; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_dvi_1080p, + ARRAY_SIZE(test_edid_dvi_1080p)); + KUNIT_ASSERT_EQ(test, ret, 0); + + info = &conn->display_info; + KUNIT_ASSERT_FALSE(test, info->is_hdmi); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); +} + +/* + * Test that when doing a commit which would use RGB 8bpc, the TMDS + * clock rate stored in the connector state is equal to the mode clock + */ +static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_max_200mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 8); + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1000); +} + +/* + * Test that when doing a commit which would use RGB 10bpc, the TMDS + * clock rate stored in the connector state is equal to 1.25 times the + * mode pixel clock + */ +static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 10); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 10); + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250); +} + +/* + * Test that when doing a commit which would use RGB 12bpc, the TMDS + * clock rate stored in the connector state is equal to 1.5 times the + * mode pixel clock + */ +static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 12); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 12); + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1500); +} + +/* + * Test that if we filter a rate through our hook, it's indeed rejected + * by the whole atomic_check logic. + * + * We do so by first doing a commit on the pipeline to make sure that it + * works, change the HDMI helpers pointer, and then try the same commit + * again to see if it fails as it should. + */ +static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_atomic_state *state; + struct drm_display_mode *preferred; + struct drm_crtc_state *crtc_state; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + conn = &priv->connector; + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_ASSERT_EQ(test, ret, 0); + + /* You shouldn't be doing that at home. */ + conn->hdmi.funcs = &reject_connector_hdmi_funcs; + + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + crtc_state->connectors_changed = true; + + ret = drm_atomic_check_only(state); + KUNIT_EXPECT_LT(test, ret, 0); +} + +/* + * Test that if: + * - We have an HDMI connector supporting RGB only + * - The chosen mode has a TMDS character rate higher than the display + * supports in RGB/12bpc + * - The chosen mode has a TMDS character rate lower than the display + * supports in RGB/10bpc. + * + * Then we will pick the latter, and the computed TMDS character rate + * will be equal to 1.25 times the mode pixel clock. + */ +static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_info *info; + struct drm_display_mode *preferred; + unsigned long long rate; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 12); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + info = &conn->display_info; + KUNIT_ASSERT_TRUE(test, info->is_hdmi); + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); + + rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_EXPECT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250); +} + +/* + * Test that if: + * - We have an HDMI connector supporting both RGB and YUV422 and up to + * 12 bpc + * - The chosen mode has a TMDS character rate higher than the display + * supports in RGB/12bpc but lower than the display supports in + * RGB/10bpc + * - The chosen mode has a TMDS character rate lower than the display + * supports in YUV422/12bpc. + * + * Then we will prefer to keep the RGB format with a lower bpc over + * picking YUV422. + */ +static void drm_test_check_max_tmds_rate_format_fallback(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_info *info; + struct drm_display_mode *preferred; + unsigned long long rate; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + info = &conn->display_info; + KUNIT_ASSERT_TRUE(test, info->is_hdmi); + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); + + rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); + + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_EXPECT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); +} + +/* + * Test that if a driver and screen supports RGB and YUV formats, and we + * try to set the VIC 1 mode, we end up with 8bpc RGB even if we could + * have had a higher bpc. + */ +static void drm_test_check_output_bpc_format_vic_1(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_info *info; + struct drm_display_mode *mode; + unsigned long long rate; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + info = &conn->display_info; + KUNIT_ASSERT_TRUE(test, info->is_hdmi); + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + mode = drm_display_mode_from_cea_vic(drm, 1); + KUNIT_ASSERT_NOT_NULL(test, mode); + + /* + * NOTE: We can't use drm_hdmi_compute_mode_clock() + * here because we're trying to get the rate of an invalid + * configuration. + * + * Thus, we have to calculate the rate by hand. + */ + rate = mode->clock * 1500; + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, mode, ctx); + KUNIT_EXPECT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); +} + +/* + * Test that if a driver supports only RGB but the screen also supports + * YUV formats, we only end up with an RGB format. + */ +static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_info *info; + struct drm_display_mode *preferred; + unsigned long long rate; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 12); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + info = &conn->display_info; + KUNIT_ASSERT_TRUE(test, info->is_hdmi); + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + /* + * We're making sure that YUV422 would be the preferred option + * here: we're always favouring higher bpc, we can't have RGB + * because the TMDS character rate exceeds the maximum supported + * by the display, and YUV422 works for that display. + * + * But since the driver only supports RGB, we should fallback to + * a lower bpc with RGB. + */ + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); + + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_EXPECT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); +} + +/* + * Test that if a screen supports only RGB but the driver also supports + * YUV formats, we only end up with an RGB format. + */ +static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_info *info; + struct drm_display_mode *preferred; + unsigned long long rate; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_max_200mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + info = &conn->display_info; + KUNIT_ASSERT_TRUE(test, info->is_hdmi); + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + /* + * We're making sure that YUV422 would be the preferred option + * here: we're always favouring higher bpc, we can't have RGB + * because the TMDS character rate exceeds the maximum supported + * by the display, and YUV422 works for that display. + * + * But since the display only supports RGB, we should fallback to + * a lower bpc with RGB. + */ + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); + + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_EXPECT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); +} + +/* + * Test that if a display supports higher bpc but the driver only + * supports 8 bpc, we only end up with 8 bpc even if we could have had a + * higher bpc. + */ +static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_info *info; + struct drm_display_mode *preferred; + unsigned long long rate; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + info = &conn->display_info; + KUNIT_ASSERT_TRUE(test, info->is_hdmi); + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + /* + * We're making sure that we have headroom on the TMDS character + * clock to actually use 12bpc. + */ + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_EXPECT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); +} + +/* + * Test that if a driver supports higher bpc but the display only + * supports 8 bpc, we only end up with 8 bpc even if we could have had a + * higher bpc. + */ +static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx *ctx; + struct drm_connector_state *conn_state; + struct drm_display_info *info; + struct drm_display_mode *preferred; + unsigned long long rate; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + ret = set_connector_edid(test, conn, + test_edid_hdmi_1080p_rgb_max_340mhz, + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_340mhz)); + KUNIT_ASSERT_EQ(test, ret, 0); + + info = &conn->display_info; + KUNIT_ASSERT_TRUE(test, info->is_hdmi); + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); + + ctx = drm_kunit_helper_acquire_ctx_alloc(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + /* + * We're making sure that we have headroom on the TMDS character + * clock to actually use 12bpc. + */ + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + drm = &priv->drm; + crtc = priv->crtc; + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); + KUNIT_EXPECT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); +} + +static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = { + KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode), + KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode_vic_1), + KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode), + KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode_vic_1), + KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode), + KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode_vic_1), + /* + * TODO: When we'll have YUV output support, we need to check + * that the limited range is always set to limited no matter + * what the value of Broadcast RGB is. + */ + KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_changed), + KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_not_changed), + KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate), + KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback), + KUNIT_CASE(drm_test_check_max_tmds_rate_format_fallback), + KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed), + KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed), + KUNIT_CASE(drm_test_check_output_bpc_dvi), + KUNIT_CASE(drm_test_check_output_bpc_format_vic_1), + KUNIT_CASE(drm_test_check_output_bpc_format_display_8bpc_only), + KUNIT_CASE(drm_test_check_output_bpc_format_display_rgb_only), + KUNIT_CASE(drm_test_check_output_bpc_format_driver_8bpc_only), + KUNIT_CASE(drm_test_check_output_bpc_format_driver_rgb_only), + KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_8bpc), + KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_10bpc), + KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_12bpc), + /* + * TODO: We should have tests to check that a change in the + * format triggers a CRTC mode change just like we do for the + * RGB Quantization and BPC. + * + * However, we don't have any way to control which format gets + * picked up aside from changing the BPC or mode which would + * already trigger a mode change. + */ + { } +}; + +static struct kunit_suite drm_atomic_helper_connector_hdmi_check_test_suite = { + .name = "drm_atomic_helper_connector_hdmi_check", + .test_cases = drm_atomic_helper_connector_hdmi_check_tests, +}; + +/* + * Test that the value of the Broadcast RGB property out of reset is set + * to auto. + */ +static void drm_test_check_broadcast_rgb_value(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_connector_state *conn_state; + struct drm_connector *conn; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + conn_state = conn->state; + KUNIT_EXPECT_EQ(test, conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_AUTO); +} + +/* + * Test that if the connector was initialised with a maximum bpc of 8, + * the value of the max_bpc and max_requested_bpc properties out of + * reset are also set to 8, and output_bpc is set to 0 and will be + * filled at atomic_check time. + */ +static void drm_test_check_bpc_8_value(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_connector_state *conn_state; + struct drm_connector *conn; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + conn_state = conn->state; + KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 8); + KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 8); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0); +} + +/* + * Test that if the connector was initialised with a maximum bpc of 10, + * the value of the max_bpc and max_requested_bpc properties out of + * reset are also set to 10, and output_bpc is set to 0 and will be + * filled at atomic_check time. + */ +static void drm_test_check_bpc_10_value(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_connector_state *conn_state; + struct drm_connector *conn; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 10); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + conn_state = conn->state; + KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 10); + KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 10); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0); +} + +/* + * Test that if the connector was initialised with a maximum bpc of 12, + * the value of the max_bpc and max_requested_bpc properties out of + * reset are also set to 12, and output_bpc is set to 0 and will be + * filled at atomic_check time. + */ +static void drm_test_check_bpc_12_value(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_connector_state *conn_state; + struct drm_connector *conn; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB), + 12); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + conn_state = conn->state; + KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 12); + KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 12); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0); +} + +/* + * Test that the value of the output format property out of reset is set + * to RGB, even if the driver supports more than that. + */ +static void drm_test_check_format_value(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_connector_state *conn_state; + struct drm_connector *conn; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 8); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + conn_state = conn->state; + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, 0); +} + +/* + * Test that the value of the output format property out of reset is set + * to 0, and will be computed at atomic_check time. + */ +static void drm_test_check_tmds_char_value(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_connector_state *conn_state; + struct drm_connector *conn; + + priv = drm_atomic_helper_connector_hdmi_init(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12); + KUNIT_ASSERT_NOT_NULL(test, priv); + + conn = &priv->connector; + conn_state = conn->state; + KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, 0); +} + +static struct kunit_case drm_atomic_helper_connector_hdmi_reset_tests[] = { + KUNIT_CASE(drm_test_check_broadcast_rgb_value), + KUNIT_CASE(drm_test_check_bpc_8_value), + KUNIT_CASE(drm_test_check_bpc_10_value), + KUNIT_CASE(drm_test_check_bpc_12_value), + KUNIT_CASE(drm_test_check_format_value), + KUNIT_CASE(drm_test_check_tmds_char_value), + { } +}; + +static struct kunit_suite drm_atomic_helper_connector_hdmi_reset_test_suite = { + .name = "drm_atomic_helper_connector_hdmi_reset", + .test_cases = drm_atomic_helper_connector_hdmi_reset_tests, +}; + +kunit_test_suites( + &drm_atomic_helper_connector_hdmi_check_test_suite, + &drm_atomic_helper_connector_hdmi_reset_test_suite, +); + +MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_kunit_edid.h b/drivers/gpu/drm/tests/drm_kunit_edid.h new file mode 100644 index 000000000000..107559900e97 --- /dev/null +++ b/drivers/gpu/drm/tests/drm_kunit_edid.h @@ -0,0 +1,484 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef DRM_KUNIT_EDID_H_ +#define DRM_KUNIT_EDID_H_ + +/* + * edid-decode (hex): + * + * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00 + * 00 21 01 03 81 a0 5a 78 0a 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 01 01 01 01 01 01 01 01 01 01 + * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c + * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73 + * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32 + * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ab + * + * ---------------- + * + * Block 0, Base EDID: + * EDID Structure Version & Revision: 1.3 + * Vendor & Product Identification: + * Manufacturer: LNX + * Model: 42 + * Made in: 2023 + * Basic Display Parameters & Features: + * Digital display + * DFP 1.x compatible TMDS + * Maximum image size: 160 cm x 90 cm + * Gamma: 2.20 + * RGB color display + * First detailed timing is the preferred timing + * Color Characteristics: + * Red : 0.0000, 0.0000 + * Green: 0.0000, 0.0000 + * Blue : 0.0000, 0.0000 + * White: 0.0000, 0.0000 + * Established Timings I & II: none + * Standard Timings: none + * Detailed Timing Descriptors: + * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm) + * Hfront 88 Hsync 44 Hback 148 Hpol P + * Vfront 4 Vsync 5 Vback 36 Vpol P + * Display Product Name: 'Test EDID' + * Display Range Limits: + * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz + * Dummy Descriptor: + * Checksum: 0xab + */ +static const unsigned char test_edid_dvi_1080p[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, + 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44, + 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, + 0x46, 0x1e, 0x46, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab +}; + +/* + * edid-decode (hex): + * + * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00 + * 00 21 01 03 81 a0 5a 78 02 00 00 00 00 00 00 00 + * 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01 + * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c + * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73 + * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32 + * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 92 + * + * 02 03 1b 81 e3 05 00 20 41 10 e2 00 4a 6d 03 0c + * 00 12 34 00 28 20 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d0 + * + * ---------------- + * + * Block 0, Base EDID: + * EDID Structure Version & Revision: 1.3 + * Vendor & Product Identification: + * Manufacturer: LNX + * Model: 42 + * Made in: 2023 + * Basic Display Parameters & Features: + * Digital display + * DFP 1.x compatible TMDS + * Maximum image size: 160 cm x 90 cm + * Gamma: 2.20 + * Monochrome or grayscale display + * First detailed timing is the preferred timing + * Color Characteristics: + * Red : 0.0000, 0.0000 + * Green: 0.0000, 0.0000 + * Blue : 0.0000, 0.0000 + * White: 0.0000, 0.0000 + * Established Timings I & II: + * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz + * Standard Timings: none + * Detailed Timing Descriptors: + * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm) + * Hfront 88 Hsync 44 Hback 148 Hpol P + * Vfront 4 Vsync 5 Vback 36 Vpol P + * Display Product Name: 'Test EDID' + * Display Range Limits: + * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz + * Dummy Descriptor: + * Extension blocks: 1 + * Checksum: 0x92 + * + * ---------------- + * + * Block 1, CTA-861 Extension Block: + * Revision: 3 + * Underscans IT Video Formats by default + * Native detailed modes: 1 + * Colorimetry Data Block: + * sRGB + * Video Data Block: + * VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz + * Video Capability Data Block: + * YCbCr quantization: No Data + * RGB quantization: Selectable (via AVI Q) + * PT scan behavior: No Data + * IT scan behavior: Always Underscanned + * CE scan behavior: Always Underscanned + * Vendor-Specific Data Block (HDMI), OUI 00-0C-03: + * Source physical address: 1.2.3.4 + * Maximum TMDS clock: 200 MHz + * Extended HDMI video details: + * Checksum: 0xd0 Unused space in Extension Block: 100 bytes + */ +static const unsigned char test_edid_hdmi_1080p_rgb_max_200mhz[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, + 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44, + 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, + 0x46, 0x00, 0x00, 0xc4, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x02, 0x03, 0x1b, 0x81, + 0xe3, 0x05, 0x00, 0x20, 0x41, 0x10, 0xe2, 0x00, 0x4a, 0x6d, 0x03, 0x0c, + 0x00, 0x12, 0x34, 0x00, 0x28, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xd0 +}; + +/* + * edid-decode (hex): + * + * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00 + * 00 21 01 03 81 a0 5a 78 02 00 00 00 00 00 00 00 + * 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01 + * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c + * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73 + * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32 + * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 92 + * + * 02 03 1b 81 e3 05 00 20 41 10 e2 00 4a 6d 03 0c + * 00 12 34 00 28 20 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d0 + * + * ---------------- + * + * Block 0, Base EDID: + * EDID Structure Version & Revision: 1.3 + * Vendor & Product Identification: + * Manufacturer: LNX + * Model: 42 + * Made in: 2023 + * Basic Display Parameters & Features: + * Digital display + * DFP 1.x compatible TMDS + * Maximum image size: 160 cm x 90 cm + * Gamma: 2.20 + * Monochrome or grayscale display + * First detailed timing is the preferred timing + * Color Characteristics: + * Red : 0.0000, 0.0000 + * Green: 0.0000, 0.0000 + * Blue : 0.0000, 0.0000 + * White: 0.0000, 0.0000 + * Established Timings I & II: + * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz + * Standard Timings: none + * Detailed Timing Descriptors: + * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm) + * Hfront 88 Hsync 44 Hback 148 Hpol P + * Vfront 4 Vsync 5 Vback 36 Vpol P + * Display Product Name: 'Test EDID' + * Display Range Limits: + * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz + * Dummy Descriptor: + * Extension blocks: 1 + * Checksum: 0x92 + * + * ---------------- + * + * Block 1, CTA-861 Extension Block: + * Revision: 3 + * Underscans IT Video Formats by default + * Native detailed modes: 1 + * Colorimetry Data Block: + * sRGB + * Video Data Block: + * VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz + * Video Capability Data Block: + * YCbCr quantization: No Data + * RGB quantization: Selectable (via AVI Q) + * PT scan behavior: No Data + * IT scan behavior: Always Underscanned + * CE scan behavior: Always Underscanned + * Vendor-Specific Data Block (HDMI), OUI 00-0C-03: + * Source physical address: 1.2.3.4 + * Maximum TMDS clock: 340 MHz + * Extended HDMI video details: + * Checksum: 0xd0 Unused space in Extension Block: 100 bytes + */ +static const unsigned char test_edid_hdmi_1080p_rgb_max_340mhz[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, + 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44, + 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, + 0x46, 0x00, 0x00, 0xc4, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x02, 0x03, 0x1b, 0x81, + 0xe3, 0x05, 0x00, 0x20, 0x41, 0x10, 0xe2, 0x00, 0x4a, 0x6d, 0x03, 0x0c, + 0x00, 0x12, 0x34, 0x00, 0x44, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xd0 +}; + +/* + * edid-decode (hex): + * + * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00 + * 00 21 01 03 81 a0 5a 78 1a 00 00 00 00 00 00 00 + * 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01 + * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c + * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73 + * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32 + * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 7a + * + * 02 03 1b b1 e3 05 00 20 41 10 e2 00 ca 6d 03 0c + * 00 12 34 78 28 20 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a8 + * + * ---------------- + * + * Block 0, Base EDID: + * EDID Structure Version & Revision: 1.3 + * Vendor & Product Identification: + * Manufacturer: LNX + * Model: 42 + * Made in: 2023 + * Basic Display Parameters & Features: + * Digital display + * DFP 1.x compatible TMDS + * Maximum image size: 160 cm x 90 cm + * Gamma: 2.20 + * Undefined display color type + * First detailed timing is the preferred timing + * Color Characteristics: + * Red : 0.0000, 0.0000 + * Green: 0.0000, 0.0000 + * Blue : 0.0000, 0.0000 + * White: 0.0000, 0.0000 + * Established Timings I & II: + * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz + * Standard Timings: none + * Detailed Timing Descriptors: + * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm) + * Hfront 88 Hsync 44 Hback 148 Hpol P + * Vfront 4 Vsync 5 Vback 36 Vpol P + * Display Product Name: 'Test EDID' + * Display Range Limits: + * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz + * Dummy Descriptor: + * Extension blocks: 1 + * Checksum: 0x7a + * + * ---------------- + * + * Block 1, CTA-861 Extension Block: + * Revision: 3 + * Underscans IT Video Formats by default + * Supports YCbCr 4:4:4 + * Supports YCbCr 4:2:2 + * Native detailed modes: 1 + * Colorimetry Data Block: + * sRGB + * Video Data Block: + * VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz + * Video Capability Data Block: + * YCbCr quantization: Selectable (via AVI YQ) + * RGB quantization: Selectable (via AVI Q) + * PT scan behavior: No Data + * IT scan behavior: Always Underscanned + * CE scan behavior: Always Underscanned + * Vendor-Specific Data Block (HDMI), OUI 00-0C-03: + * Source physical address: 1.2.3.4 + * DC_48bit + * DC_36bit + * DC_30bit + * DC_Y444 + * Maximum TMDS clock: 200 MHz + * Extended HDMI video details: + * Checksum: 0xa8 Unused space in Extension Block: 100 bytes + */ +static const unsigned char test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78, + 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, + 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44, + 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, + 0x46, 0x1e, 0x46, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7a, 0x02, 0x03, 0x1b, 0xb1, + 0xe3, 0x05, 0x00, 0x20, 0x41, 0x10, 0xe2, 0x00, 0xca, 0x6d, 0x03, 0x0c, + 0x00, 0x12, 0x34, 0x78, 0x28, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa8 +}; + +/* + * edid-decode (hex): + * + * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00 + * 00 21 01 03 81 a0 5a 78 0a 00 00 00 00 00 00 00 + * 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01 + * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c + * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73 + * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32 + * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 8a + * + * 02 03 1b b1 e3 05 00 20 41 10 e2 00 ca 6d 03 0c + * 00 12 34 78 44 20 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8c + * + * ---------------- + * + * Block 0, Base EDID: + * EDID Structure Version & Revision: 1.3 + * Vendor & Product Identification: + * Manufacturer: LNX + * Model: 42 + * Made in: 2023 + * Basic Display Parameters & Features: + * Digital display + * DFP 1.x compatible TMDS + * Maximum image size: 160 cm x 90 cm + * Gamma: 2.20 + * RGB color display + * First detailed timing is the preferred timing + * Color Characteristics: + * Red : 0.0000, 0.0000 + * Green: 0.0000, 0.0000 + * Blue : 0.0000, 0.0000 + * White: 0.0000, 0.0000 + * Established Timings I & II: + * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz + * Standard Timings: none + * Detailed Timing Descriptors: + * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm) + * Hfront 88 Hsync 44 Hback 148 Hpol P + * Vfront 4 Vsync 5 Vback 36 Vpol P + * Display Product Name: 'Test EDID' + * Display Range Limits: + * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz + * Dummy Descriptor: + * Extension blocks: 1 + * Checksum: 0x8a + * + * ---------------- + * + * Block 1, CTA-861 Extension Block: + * Revision: 3 + * Underscans IT Video Formats by default + * Supports YCbCr 4:4:4 + * Supports YCbCr 4:2:2 + * Native detailed modes: 1 + * Colorimetry Data Block: + * sRGB + * Video Data Block: + * VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz + * Video Capability Data Block: + * YCbCr quantization: Selectable (via AVI YQ) + * RGB quantization: Selectable (via AVI Q) + * PT scan behavior: No Data + * IT scan behavior: Always Underscanned + * CE scan behavior: Always Underscanned + * Vendor-Specific Data Block (HDMI), OUI 00-0C-03: + * Source physical address: 1.2.3.4 + * DC_48bit + * DC_36bit + * DC_30bit + * DC_Y444 + * Maximum TMDS clock: 340 MHz + * Extended HDMI video details: + * Checksum: 0x8c Unused space in Extension Block: 100 bytes + */ +static const unsigned char test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, + 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44, + 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, + 0x46, 0x1e, 0x46, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8a, 0x02, 0x03, 0x1b, 0xb1, + 0xe3, 0x05, 0x00, 0x20, 0x41, 0x10, 0xe2, 0x00, 0xca, 0x6d, 0x03, 0x0c, + 0x00, 0x12, 0x34, 0x78, 0x44, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x8c +}; + +#endif // DRM_KUNIT_EDID_H_ diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index d5317d13d3fc..aa62719dab0e 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -312,4 +312,5 @@ drm_kunit_helper_create_crtc(struct kunit *test, EXPORT_SYMBOL_GPL(drm_kunit_helper_create_crtc); MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>"); +MODULE_DESCRIPTION("KUnit test suite helper functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_managed_test.c b/drivers/gpu/drm/tests/drm_managed_test.c index 76eb273c9b36..d40c7ef7f9e1 100644 --- a/drivers/gpu/drm/tests/drm_managed_test.c +++ b/drivers/gpu/drm/tests/drm_managed_test.c @@ -113,4 +113,5 @@ static struct kunit_suite drm_managed_test_suite = { kunit_test_suite(drm_managed_test_suite); MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>"); +MODULE_DESCRIPTION("KUnit DRM managed test suite"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_mm_test.c b/drivers/gpu/drm/tests/drm_mm_test.c index 8497d9990b96..6174d0929020 100644 --- a/drivers/gpu/drm/tests/drm_mm_test.c +++ b/drivers/gpu/drm/tests/drm_mm_test.c @@ -356,4 +356,5 @@ static struct kunit_suite drm_mm_test_suite = { kunit_test_suite(drm_mm_test_suite); MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Test cases for the drm_mm range manager"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c index 1e9f63fbfead..7029f7a2eb4d 100644 --- a/drivers/gpu/drm/tests/drm_modes_test.c +++ b/drivers/gpu/drm/tests/drm_modes_test.c @@ -147,4 +147,5 @@ static struct kunit_suite drm_modes_analog_tv_test_suite = { kunit_test_suite(drm_modes_analog_tv_test_suite); MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>"); +MODULE_DESCRIPTION("Kunit test for drm_modes functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_plane_helper_test.c b/drivers/gpu/drm/tests/drm_plane_helper_test.c index 0f392146b233..7e975a3f4a71 100644 --- a/drivers/gpu/drm/tests/drm_plane_helper_test.c +++ b/drivers/gpu/drm/tests/drm_plane_helper_test.c @@ -315,4 +315,5 @@ static struct kunit_suite drm_plane_helper_test_suite = { kunit_test_suite(drm_plane_helper_test_suite); +MODULE_DESCRIPTION("Test cases for the drm_plane_helper functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_probe_helper_test.c b/drivers/gpu/drm/tests/drm_probe_helper_test.c index 1a2044070a6c..bc09ff38aca1 100644 --- a/drivers/gpu/drm/tests/drm_probe_helper_test.c +++ b/drivers/gpu/drm/tests/drm_probe_helper_test.c @@ -207,4 +207,5 @@ static struct kunit_suite drm_test_connector_helper_tv_get_modes_suite = { kunit_test_suite(drm_test_connector_helper_tv_get_modes_suite); MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>"); +MODULE_DESCRIPTION("Kunit test for drm_probe_helper functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_rect_test.c b/drivers/gpu/drm/tests/drm_rect_test.c index 76332cd2ead8..17e1f34b7610 100644 --- a/drivers/gpu/drm/tests/drm_rect_test.c +++ b/drivers/gpu/drm/tests/drm_rect_test.c @@ -526,4 +526,5 @@ static struct kunit_suite drm_rect_test_suite = { kunit_test_suite(drm_rect_test_suite); +MODULE_DESCRIPTION("Test cases for the drm_rect functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c index 68fed531f6a7..a5d86822c9e3 100644 --- a/drivers/gpu/drm/tidss/tidss_plane.c +++ b/drivers/gpu/drm/tidss/tidss_plane.c @@ -8,6 +8,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_crtc.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -166,6 +167,14 @@ static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = { .atomic_disable = tidss_plane_atomic_disable, }; +static const struct drm_plane_helper_funcs tidss_primary_plane_helper_funcs = { + .atomic_check = tidss_plane_atomic_check, + .atomic_update = tidss_plane_atomic_update, + .atomic_enable = tidss_plane_atomic_enable, + .atomic_disable = tidss_plane_atomic_disable, + .get_scanout_buffer = drm_fb_dma_get_scanout_buffer, +}; + static const struct drm_plane_funcs tidss_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -211,7 +220,10 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss, if (ret < 0) goto err; - drm_plane_helper_add(&tplane->plane, &tidss_plane_helper_funcs); + if (type == DRM_PLANE_TYPE_PRIMARY) + drm_plane_helper_add(&tplane->plane, &tidss_primary_plane_helper_funcs); + else + drm_plane_helper_add(&tplane->plane, &tidss_plane_helper_funcs); drm_plane_create_zpos_property(&tplane->plane, tidss->num_planes, 0, num_planes - 1); diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c index c23c9f0cf49c..31fc5d839e10 100644 --- a/drivers/gpu/drm/tiny/bochs.c +++ b/drivers/gpu/drm/tiny/bochs.c @@ -7,7 +7,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> #include <drm/drm_edid.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_ttm.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_framebuffer_helper.h> @@ -85,7 +85,7 @@ struct bochs_device { u16 yres_virtual; u32 stride; u32 bpp; - struct edid *edid; + const struct drm_edid *drm_edid; /* drm */ struct drm_device *dev; @@ -199,10 +199,10 @@ static int bochs_hw_load_edid(struct bochs_device *bochs) if (drm_edid_header_is_valid(header) != 8) return -1; - kfree(bochs->edid); - bochs->edid = drm_do_get_edid(&bochs->connector, - bochs_get_edid_block, bochs); - if (bochs->edid == NULL) + drm_edid_free(bochs->drm_edid); + bochs->drm_edid = drm_edid_read_custom(&bochs->connector, + bochs_get_edid_block, bochs); + if (!bochs->drm_edid) return -1; return 0; @@ -303,7 +303,7 @@ static void bochs_hw_fini(struct drm_device *dev) if (bochs->fb_map) iounmap(bochs->fb_map); pci_release_regions(to_pci_dev(dev->dev)); - kfree(bochs->edid); + drm_edid_free(bochs->drm_edid); } static void bochs_hw_blank(struct bochs_device *bochs, bool blank) @@ -471,12 +471,9 @@ static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = { static int bochs_connector_get_modes(struct drm_connector *connector) { - struct bochs_device *bochs = - container_of(connector, struct bochs_device, connector); - int count = 0; + int count; - if (bochs->edid) - count = drm_add_edid_modes(connector, bochs->edid); + count = drm_edid_connector_add_modes(connector); if (!count) { count = drm_add_modes_noedid(connector, 8192, 8192); @@ -507,10 +504,10 @@ static void bochs_connector_init(struct drm_device *dev) drm_connector_helper_add(connector, &bochs_connector_connector_helper_funcs); bochs_hw_load_edid(bochs); - if (bochs->edid) { + if (bochs->drm_edid) { DRM_INFO("Found EDID data blob.\n"); drm_connector_attach_edid_property(connector); - drm_connector_update_edid_property(connector, bochs->edid); + drm_edid_connector_update(&bochs->connector, bochs->drm_edid); } } @@ -670,7 +667,7 @@ static int bochs_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent if (ret) goto err_hw_fini; - drm_fbdev_generic_setup(dev, 32); + drm_fbdev_ttm_setup(dev, 32); return ret; err_hw_fini: @@ -736,4 +733,5 @@ drm_module_pci_driver_if_modeset(bochs_pci_driver, bochs_modeset); MODULE_DEVICE_TABLE(pci, bochs_pci_tbl); MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>"); +MODULE_DESCRIPTION("DRM Support for bochs dispi vga interface (qemu stdvga)"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index 4e3a152f897a..751326e3d9c3 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -31,7 +31,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_edid.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_file.h> #include <drm/drm_format_helper.h> #include <drm/drm_fourcc.h> @@ -716,7 +716,7 @@ static int cirrus_pci_probe(struct pci_dev *pdev, if (ret) return ret; - drm_fbdev_generic_setup(dev, 16); + drm_fbdev_shmem_setup(dev, 16); return 0; } @@ -760,4 +760,5 @@ static struct pci_driver cirrus_pci_driver = { drm_module_pci_driver(cirrus_pci_driver) MODULE_DEVICE_TABLE(pci, pciidlist); +MODULE_DESCRIPTION("Cirrus driver for QEMU emulated device"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index 0187539ff5ea..e0defb1d134f 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -13,7 +13,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_edid.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_file.h> #include <drm/drm_format_helper.h> #include <drm/drm_fourcc.h> @@ -699,7 +699,7 @@ static int gm12u320_usb_probe(struct usb_interface *interface, if (ret) goto err_put_device; - drm_fbdev_generic_setup(dev, 0); + drm_fbdev_shmem_setup(dev, 0); return 0; @@ -755,4 +755,5 @@ static struct usb_driver gm12u320_usb_driver = { module_usb_driver(gm12u320_usb_driver); MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); +MODULE_DESCRIPTION("GM12U320 driver for USB projectors"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c index cdc4486e059b..2e631282edeb 100644 --- a/drivers/gpu/drm/tiny/hx8357d.c +++ b/drivers/gpu/drm/tiny/hx8357d.c @@ -18,7 +18,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> @@ -256,7 +256,7 @@ static int hx8357d_probe(struct spi_device *spi) spi_set_drvdata(spi, drm); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c index bc4384d410fc..86f9d8834901 100644 --- a/drivers/gpu/drm/tiny/ili9163.c +++ b/drivers/gpu/drm/tiny/ili9163.c @@ -9,7 +9,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_mipi_dbi.h> @@ -185,7 +185,7 @@ static int ili9163_probe(struct spi_device *spi) if (ret) return ret; - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index dd8b0a181be9..b6b7a49147bf 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -20,7 +20,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_dma_helper.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -426,7 +426,7 @@ static int ili9225_probe(struct spi_device *spi) spi_set_drvdata(spi, drm); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } @@ -447,7 +447,6 @@ static void ili9225_shutdown(struct spi_device *spi) static struct spi_driver ili9225_spi_driver = { .driver = { .name = "ili9225", - .owner = THIS_MODULE, .of_match_table = ili9225_of_match, }, .id_table = ili9225_id, diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c index 47b61c3bf145..8bcada30af71 100644 --- a/drivers/gpu/drm/tiny/ili9341.c +++ b/drivers/gpu/drm/tiny/ili9341.c @@ -17,7 +17,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> @@ -218,7 +218,7 @@ static int ili9341_probe(struct spi_device *spi) spi_set_drvdata(spi, drm); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c index 938bceed5999..70d366260041 100644 --- a/drivers/gpu/drm/tiny/ili9486.c +++ b/drivers/gpu/drm/tiny/ili9486.c @@ -16,7 +16,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> @@ -247,7 +247,7 @@ static int ili9486_probe(struct spi_device *spi) spi_set_drvdata(spi, drm); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c index 01ff43c8ac3f..cdc5423990ca 100644 --- a/drivers/gpu/drm/tiny/mi0283qt.c +++ b/drivers/gpu/drm/tiny/mi0283qt.c @@ -15,7 +15,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> @@ -226,7 +226,7 @@ static int mi0283qt_probe(struct spi_device *spi) spi_set_drvdata(spi, drm); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } @@ -263,7 +263,6 @@ static const struct dev_pm_ops mi0283qt_pm_ops = { static struct spi_driver mi0283qt_spi_driver = { .driver = { .name = "mi0283qt", - .owner = THIS_MODULE, .of_match_table = mi0283qt_of_match, .pm = &mi0283qt_pm_ops, }, diff --git a/drivers/gpu/drm/tiny/ofdrm.c b/drivers/gpu/drm/tiny/ofdrm.c index ab89b7fc7bf6..35996f7eedac 100644 --- a/drivers/gpu/drm/tiny/ofdrm.c +++ b/drivers/gpu/drm/tiny/ofdrm.c @@ -11,7 +11,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -1377,7 +1377,7 @@ static int ofdrm_probe(struct platform_device *pdev) if (color_mode == 16) color_mode = odev->format->depth; // can be 15 or 16 - drm_fbdev_generic_setup(dev, color_mode); + drm_fbdev_shmem_setup(dev, color_mode); return 0; } diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c index f80a141fcf36..f753cdffe6f8 100644 --- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c +++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c @@ -16,7 +16,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> @@ -26,6 +26,49 @@ #include <video/mipi_display.h> +struct panel_mipi_dbi_format { + const char *name; + u32 fourcc; + unsigned int bpp; +}; + +static const struct panel_mipi_dbi_format panel_mipi_dbi_formats[] = { + { "r5g6b5", DRM_FORMAT_RGB565, 16 }, + { "b6x2g6x2r6x2", DRM_FORMAT_RGB888, 24 }, +}; + +static int panel_mipi_dbi_get_format(struct device *dev, u32 *formats, unsigned int *bpp) +{ + const char *format_name; + unsigned int i; + int ret; + + formats[1] = DRM_FORMAT_XRGB8888; + + ret = device_property_read_string(dev, "format", &format_name); + if (ret) { + /* Old Device Trees don't have this property */ + formats[0] = DRM_FORMAT_RGB565; + *bpp = 16; + return 0; + } + + for (i = 0; i < ARRAY_SIZE(panel_mipi_dbi_formats); i++) { + const struct panel_mipi_dbi_format *format = &panel_mipi_dbi_formats[i]; + + if (strcmp(format_name, format->name)) + continue; + + formats[0] = format->fourcc; + *bpp = format->bpp; + return 0; + } + + dev_err(dev, "Pixel format is not supported: '%s'\n", format_name); + + return -EINVAL; +} + static const u8 panel_mipi_dbi_magic[15] = { 'M', 'I', 'P', 'I', ' ', 'D', 'B', 'I', 0, 0, 0, 0, 0, 0, 0 }; @@ -276,6 +319,9 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi) struct drm_device *drm; struct mipi_dbi *dbi; struct gpio_desc *dc; + unsigned int bpp; + size_t buf_size; + u32 formats[2]; int ret; dbidev = devm_drm_dev_alloc(dev, &panel_mipi_dbi_driver, struct mipi_dbi_dev, drm); @@ -323,7 +369,14 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi) if (IS_ERR(dbidev->driver_private)) return PTR_ERR(dbidev->driver_private); - ret = mipi_dbi_dev_init(dbidev, &panel_mipi_dbi_pipe_funcs, &mode, 0); + ret = panel_mipi_dbi_get_format(dev, formats, &bpp); + if (ret) + return ret; + + buf_size = DIV_ROUND_UP(mode.hdisplay * mode.vdisplay * bpp, 8); + ret = mipi_dbi_dev_init_with_formats(dbidev, &panel_mipi_dbi_pipe_funcs, + formats, ARRAY_SIZE(formats), + &mode, 0, buf_size); if (ret) return ret; @@ -335,7 +388,7 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi) spi_set_drvdata(spi, drm); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } @@ -384,7 +437,6 @@ MODULE_DEVICE_TABLE(spi, panel_mipi_dbi_spi_id); static struct spi_driver panel_mipi_dbi_spi_driver = { .driver = { .name = "panel-mipi-dbi-spi", - .owner = THIS_MODULE, .of_match_table = panel_mipi_dbi_spi_of_match, .pm = &panel_mipi_dbi_pm_ops, }, diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 8fd6758f5725..1f78aa3d26bb 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -26,7 +26,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_dma_helper.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -1118,7 +1118,7 @@ static int repaper_probe(struct spi_device *spi) DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 1000000); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 1d8fa07572c5..d19e10289428 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -17,7 +17,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -1042,7 +1042,7 @@ static int simpledrm_probe(struct platform_device *pdev) if (color_mode == 16) color_mode = sdev->format->depth; // can be 15 or 16 - drm_fbdev_generic_setup(dev, color_mode); + drm_fbdev_shmem_setup(dev, color_mode); return 0; } diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 7336fa1ddaed..b9c6ed352182 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -16,7 +16,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_dma_helper.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> @@ -371,7 +371,7 @@ static int st7586_probe(struct spi_device *spi) spi_set_drvdata(spi, drm); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } @@ -392,7 +392,6 @@ static void st7586_shutdown(struct spi_device *spi) static struct spi_driver st7586_spi_driver = { .driver = { .name = "st7586", - .owner = THIS_MODULE, .of_match_table = st7586_of_match, }, .id_table = st7586_id, diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c index 477eb36fbb70..1676da00883d 100644 --- a/drivers/gpu/drm/tiny/st7735r.c +++ b/drivers/gpu/drm/tiny/st7735r.c @@ -18,7 +18,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> @@ -241,7 +241,7 @@ static int st7735r_probe(struct spi_device *spi) spi_set_drvdata(spi, drm); - drm_fbdev_generic_setup(drm, 0); + drm_fbdev_dma_setup(drm, 0); return 0; } diff --git a/drivers/gpu/drm/udl/Makefile b/drivers/gpu/drm/udl/Makefile index 3f6db179455d..43d69a16af18 100644 --- a/drivers/gpu/drm/udl/Makefile +++ b/drivers/gpu/drm/udl/Makefile @@ -1,4 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only -udl-y := udl_drv.o udl_modeset.o udl_main.o udl_transfer.o + +udl-y := \ + udl_drv.o \ + udl_edid.o \ + udl_main.o \ + udl_modeset.o \ + udl_transfer.o obj-$(CONFIG_DRM_UDL) := udl.o diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 1506094a8009..280a09a6e2ad 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -6,7 +6,7 @@ #include <linux/module.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_file.h> #include <drm/drm_gem_shmem_helper.h> #include <drm/drm_managed.h> @@ -117,7 +117,7 @@ static int udl_usb_probe(struct usb_interface *interface, DRM_INFO("Initialized udl on minor %d\n", udl->drm.primary->index); - drm_fbdev_generic_setup(&udl->drm, 0); + drm_fbdev_shmem_setup(&udl->drm, 0); return 0; } @@ -160,4 +160,5 @@ static struct usb_driver udl_driver = { .id_table = id_table, }; module_usb_driver(udl_driver); +MODULE_DESCRIPTION("KMS driver for the USB displaylink video adapters"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 282ebd6c02fd..1eb716d9dad5 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -49,17 +49,6 @@ struct urb_list { size_t size; }; -struct udl_connector { - struct drm_connector connector; - /* last udl_detect edid */ - struct edid *edid; -}; - -static inline struct udl_connector *to_udl_connector(struct drm_connector *connector) -{ - return container_of(connector, struct udl_connector, connector); -} - struct udl_device { struct drm_device drm; struct device *dev; @@ -68,6 +57,7 @@ struct udl_device { struct drm_plane primary_plane; struct drm_crtc crtc; struct drm_encoder encoder; + struct drm_connector connector; struct mutex gem_lock; diff --git a/drivers/gpu/drm/udl/udl_edid.c b/drivers/gpu/drm/udl/udl_edid.c new file mode 100644 index 000000000000..d67e6bf1f2ae --- /dev/null +++ b/drivers/gpu/drm/udl/udl_edid.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/string.h> + +#include <drm/drm_drv.h> +#include <drm/drm_edid.h> + +#include "udl_drv.h" +#include "udl_edid.h" + +static int udl_read_edid_block(void *data, u8 *buf, unsigned int block, size_t len) +{ + struct udl_device *udl = data; + struct drm_device *dev = &udl->drm; + struct usb_device *udev = udl_to_usb_device(udl); + u8 *read_buff; + int idx, ret; + size_t i; + + read_buff = kmalloc(2, GFP_KERNEL); + if (!read_buff) + return -ENOMEM; + + if (!drm_dev_enter(dev, &idx)) { + ret = -ENODEV; + goto err_kfree; + } + + for (i = 0; i < len; i++) { + int bval = (i + block * EDID_LENGTH) << 8; + + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x02, (0x80 | (0x02 << 5)), bval, + 0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT); + if (ret < 0) { + drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret); + goto err_drm_dev_exit; + } else if (ret < 1) { + ret = -EIO; + drm_err(dev, "Read EDID byte %zu failed\n", i); + goto err_drm_dev_exit; + } + + buf[i] = read_buff[1]; + } + + drm_dev_exit(idx); + kfree(read_buff); + + return 0; + +err_drm_dev_exit: + drm_dev_exit(idx); +err_kfree: + kfree(read_buff); + return ret; +} + +bool udl_probe_edid(struct udl_device *udl) +{ + u8 hdr[8]; + int ret; + + ret = udl_read_edid_block(udl, hdr, 0, sizeof(hdr)); + if (ret) + return false; + + /* + * The adapter sends all-zeros if no monitor has been + * connected. We consider anything else a connection. + */ + return !!memchr_inv(hdr, 0, sizeof(hdr)); +} + +const struct drm_edid *udl_edid_read(struct drm_connector *connector) +{ + struct udl_device *udl = to_udl(connector->dev); + + return drm_edid_read_custom(connector, udl_read_edid_block, udl); +} diff --git a/drivers/gpu/drm/udl/udl_edid.h b/drivers/gpu/drm/udl/udl_edid.h new file mode 100644 index 000000000000..fe15ff3752b7 --- /dev/null +++ b/drivers/gpu/drm/udl/udl_edid.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef UDL_EDID_H +#define UDL_EDID_H + +#include <linux/types.h> + +struct drm_connector; +struct drm_edid; +struct udl_device; + +bool udl_probe_edid(struct udl_device *udl); +const struct drm_edid *udl_edid_read(struct drm_connector *connector); + +#endif diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 7702359c90c2..bbb04f98886a 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -25,6 +25,7 @@ #include <drm/drm_vblank.h> #include "udl_drv.h" +#include "udl_edid.h" #include "udl_proto.h" /* @@ -415,129 +416,42 @@ static const struct drm_encoder_funcs udl_encoder_funcs = { static int udl_connector_helper_get_modes(struct drm_connector *connector) { - struct udl_connector *udl_connector = to_udl_connector(connector); + const struct drm_edid *drm_edid; + int count; - drm_connector_update_edid_property(connector, udl_connector->edid); - if (udl_connector->edid) - return drm_add_edid_modes(connector, udl_connector->edid); + drm_edid = udl_edid_read(connector); + drm_edid_connector_update(connector, drm_edid); + count = drm_edid_connector_add_modes(connector); + drm_edid_free(drm_edid); - return 0; -} - -static const struct drm_connector_helper_funcs udl_connector_helper_funcs = { - .get_modes = udl_connector_helper_get_modes, -}; - -static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) -{ - struct udl_device *udl = data; - struct drm_device *dev = &udl->drm; - struct usb_device *udev = udl_to_usb_device(udl); - u8 *read_buff; - int ret; - size_t i; - - read_buff = kmalloc(2, GFP_KERNEL); - if (!read_buff) - return -ENOMEM; - - for (i = 0; i < len; i++) { - int bval = (i + block * EDID_LENGTH) << 8; - - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - 0x02, (0x80 | (0x02 << 5)), bval, - 0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT); - if (ret < 0) { - drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret); - goto err_kfree; - } else if (ret < 1) { - ret = -EIO; - drm_err(dev, "Read EDID byte %zu failed\n", i); - goto err_kfree; - } - - buf[i] = read_buff[1]; - } - - kfree(read_buff); - - return 0; - -err_kfree: - kfree(read_buff); - return ret; + return count; } -static enum drm_connector_status udl_connector_detect(struct drm_connector *connector, bool force) +static int udl_connector_helper_detect_ctx(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force) { - struct drm_device *dev = connector->dev; - struct udl_device *udl = to_udl(dev); - struct udl_connector *udl_connector = to_udl_connector(connector); - enum drm_connector_status status = connector_status_disconnected; - int idx; + struct udl_device *udl = to_udl(connector->dev); - /* cleanup previous EDID */ - kfree(udl_connector->edid); - udl_connector->edid = NULL; + if (udl_probe_edid(udl)) + return connector_status_connected; - if (!drm_dev_enter(dev, &idx)) - return connector_status_disconnected; - - udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl); - if (udl_connector->edid) - status = connector_status_connected; - - drm_dev_exit(idx); - - return status; + return connector_status_disconnected; } -static void udl_connector_destroy(struct drm_connector *connector) -{ - struct udl_connector *udl_connector = to_udl_connector(connector); - - drm_connector_cleanup(connector); - kfree(udl_connector->edid); - kfree(udl_connector); -} +static const struct drm_connector_helper_funcs udl_connector_helper_funcs = { + .get_modes = udl_connector_helper_get_modes, + .detect_ctx = udl_connector_helper_detect_ctx, +}; static const struct drm_connector_funcs udl_connector_funcs = { .reset = drm_atomic_helper_connector_reset, - .detect = udl_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = udl_connector_destroy, + .destroy = drm_connector_cleanup, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -struct drm_connector *udl_connector_init(struct drm_device *dev) -{ - struct udl_connector *udl_connector; - struct drm_connector *connector; - int ret; - - udl_connector = kzalloc(sizeof(*udl_connector), GFP_KERNEL); - if (!udl_connector) - return ERR_PTR(-ENOMEM); - - connector = &udl_connector->connector; - ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA); - if (ret) - goto err_kfree; - - drm_connector_helper_add(connector, &udl_connector_helper_funcs); - - connector->polled = DRM_CONNECTOR_POLL_HPD | - DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; - - return connector; - -err_kfree: - kfree(udl_connector); - return ERR_PTR(ret); -} - /* * Modesetting */ @@ -607,9 +521,15 @@ int udl_modeset_init(struct drm_device *dev) return ret; encoder->possible_crtcs = drm_crtc_mask(crtc); - connector = udl_connector_init(dev); - if (IS_ERR(connector)) - return PTR_ERR(connector); + connector = &udl->connector; + ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA); + if (ret) + return ret; + drm_connector_helper_add(connector, &udl_connector_helper_funcs); + + connector->polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; + ret = drm_connector_attach_encoder(connector, encoder); if (ret) return ret; diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index 28b7ddce7747..a47f00b443d3 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -94,6 +94,9 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data, case DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE: args->value = 1; return 0; + case DRM_V3D_PARAM_MAX_PERF_COUNTERS: + args->value = v3d->max_counters; + return 0; default: DRM_DEBUG("Unknown parameter %d\n", args->param); return -EINVAL; @@ -208,6 +211,7 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = { DRM_IOCTL_DEF_DRV(V3D_PERFMON_DESTROY, v3d_perfmon_destroy_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_VALUES, v3d_perfmon_get_values_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CPU, v3d_submit_cpu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH), + DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_COUNTER, v3d_perfmon_get_counter_ioctl, DRM_RENDER_ALLOW), }; static const struct drm_driver v3d_drm_driver = { @@ -294,6 +298,13 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) v3d->cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES); WARN_ON(v3d->cores > 1); /* multicore not yet implemented */ + if (v3d->ver >= 71) + v3d->max_counters = V3D_V71_NUM_PERFCOUNTERS; + else if (v3d->ver >= 42) + v3d->max_counters = V3D_V42_NUM_PERFCOUNTERS; + else + v3d->max_counters = 0; + v3d->reset = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(v3d->reset)) { ret = PTR_ERR(v3d->reset); diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index a2c516fe6d79..099b962bdfde 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -11,6 +11,8 @@ #include <drm/drm_gem_shmem_helper.h> #include <drm/gpu_scheduler.h> +#include "v3d_performance_counters.h" + #include "uapi/drm/v3d_drm.h" struct clk; @@ -102,6 +104,11 @@ struct v3d_dev { int ver; bool single_irq_line; + /* Different revisions of V3D have different total number of performance + * counters + */ + unsigned int max_counters; + void __iomem *hub_regs; void __iomem *core_regs[3]; void __iomem *bridge_regs; @@ -345,7 +352,7 @@ struct v3d_timestamp_query { }; /* Number of perfmons required to handle all supported performance counters */ -#define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_PERFCNT_NUM, \ +#define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_MAX_COUNTERS, \ DRM_V3D_MAX_PERF_COUNTERS) struct v3d_performance_query { @@ -575,6 +582,8 @@ int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); /* v3d_sysfs.c */ int v3d_sysfs_init(struct device *dev); diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c index e1be7368b87d..b7d0b02e1a95 100644 --- a/drivers/gpu/drm/v3d/v3d_perfmon.c +++ b/drivers/gpu/drm/v3d/v3d_perfmon.c @@ -9,6 +9,192 @@ #define V3D_PERFMONID_MIN 1 #define V3D_PERFMONID_MAX U32_MAX +static const struct v3d_perf_counter_desc v3d_v42_performance_counters[] = { + {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"}, + {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"}, + {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"}, + {"FEP", "FEP-valid-quads", "[FEP] Valid quads"}, + {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"}, + {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"}, + {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"}, + {"TLB", "TLB-quads-with-zero-coverage", "[TLB] Quads with all pixels having zero coverage"}, + {"TLB", "TLB-quads-with-non-zero-coverage", "[TLB] Quads with any pixels having non-zero coverage"}, + {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"}, + {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"}, + {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"}, + {"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"}, + {"QPU", "QPU-total-idle-clk-cycles", "[QPU] Total idle clock cycles for all QPUs"}, + {"QPU", "QPU-total-active-clk-cycles-vertex-coord-shading", "[QPU] Total active clock cycles for all QPUs doing vertex/coordinate/user shading (counts only when QPU is not stalled)"}, + {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"}, + {"QPU", "QPU-total-clk-cycles-executing-valid-instr", "[QPU] Total clock cycles for all QPUs executing valid instructions"}, + {"QPU", "QPU-total-clk-cycles-waiting-TMU", "[QPU] Total clock cycles for all QPUs stalled waiting for TMUs only (counter won't increment if QPU also stalling for another reason)"}, + {"QPU", "QPU-total-clk-cycles-waiting-scoreboard", "[QPU] Total clock cycles for all QPUs stalled waiting for Scoreboard only (counter won't increment if QPU also stalling for another reason)"}, + {"QPU", "QPU-total-clk-cycles-waiting-varyings", "[QPU] Total clock cycles for all QPUs stalled waiting for Varyings only (counter won't increment if QPU also stalling for another reason)"}, + {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"}, + {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"}, + {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"}, + {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"}, + {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"}, + {"TMU", "TMU-total-text-cache-miss", "[TMU] Total texture cache misses (number of fetches from memory/L2cache)"}, + {"VPM", "VPM-total-clk-cycles-VDW-stalled", "[VPM] Total clock cycles VDW is stalled waiting for VPM access"}, + {"VPM", "VPM-total-clk-cycles-VCD-stalled", "[VPM] Total clock cycles VCD is stalled waiting for VPM access"}, + {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"}, + {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"}, + {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"}, + {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"}, + {"CORE", "cycle-count", "[CORE] Cycle counter"}, + {"QPU", "QPU-total-clk-cycles-waiting-vertex-coord-shading", "[QPU] Total stalled clock cycles for all QPUs doing vertex/coordinate/user shading"}, + {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"}, + {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"}, + {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"}, + {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"}, + {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"}, + {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"}, + {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"}, + {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"}, + {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"}, + {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"}, + {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"}, + {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"}, + {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"}, + {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"}, + {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"}, + {"TMU", "TMU-total-config-access", "[TMU] Total config accesses"}, + {"L2T", "L2T-no-id-stalled", "[L2T] No ID stall"}, + {"L2T", "L2T-command-queue-stalled", "[L2T] Command queue full stall"}, + {"L2T", "L2T-TMU-writes", "[L2T] TMU write accesses"}, + {"TMU", "TMU-active-cycles", "[TMU] Active cycles"}, + {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"}, + {"CLE", "CLE-thread-active-cycles", "[CLE] Bin or render thread active cycles"}, + {"L2T", "L2T-TMU-reads", "[L2T] TMU read accesses"}, + {"L2T", "L2T-CLE-reads", "[L2T] CLE read accesses"}, + {"L2T", "L2T-VCD-reads", "[L2T] VCD read accesses"}, + {"L2T", "L2T-TMU-config-reads", "[L2T] TMU CFG read accesses"}, + {"L2T", "L2T-SLC0-reads", "[L2T] SLC0 read accesses"}, + {"L2T", "L2T-SLC1-reads", "[L2T] SLC1 read accesses"}, + {"L2T", "L2T-SLC2-reads", "[L2T] SLC2 read accesses"}, + {"L2T", "L2T-TMU-write-miss", "[L2T] TMU write misses"}, + {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"}, + {"L2T", "L2T-CLE-read-miss", "[L2T] CLE read misses"}, + {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"}, + {"L2T", "L2T-TMU-config-read-miss", "[L2T] TMU CFG read misses"}, + {"L2T", "L2T-SLC0-read-miss", "[L2T] SLC0 read misses"}, + {"L2T", "L2T-SLC1-read-miss", "[L2T] SLC1 read misses"}, + {"L2T", "L2T-SLC2-read-miss", "[L2T] SLC2 read misses"}, + {"CORE", "core-memory-writes", "[CORE] Total memory writes"}, + {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"}, + {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"}, + {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"}, + {"CORE", "core-memory-reads", "[CORE] Total memory reads"}, + {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"}, + {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"}, + {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"}, + {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"}, + {"GMP", "GMP-memory-reads", "[GMP] Total memory reads"}, + {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"}, + {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"}, + {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"}, + {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"}, + {"TMU", "TMU-MRU-hits", "[TMU] Total MRU hits"}, + {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"}, +}; + +static const struct v3d_perf_counter_desc v3d_v71_performance_counters[] = { + {"CORE", "cycle-count", "[CORE] Cycle counter"}, + {"CORE", "core-active", "[CORE] Bin/Render/Compute active cycles"}, + {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"}, + {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"}, + {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"}, + {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"}, + {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"}, + {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"}, + {"FEP", "FEP-valid-quads", "[FEP] Valid quads"}, + {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"}, + {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"}, + {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"}, + {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"}, + {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"}, + {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"}, + {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"}, + {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"}, + {"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"}, + {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"}, + {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"}, + {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"}, + {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"}, + {"TMU", "TMU-active-cycles", "[TMU] Active cycles"}, + {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"}, + {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"}, + {"TMU", "TMU-cache-x4-active-cycles", "[TMU] Cache active cycles for x4 access"}, + {"TMU", "TMU-cache-x4-stalled-cycles", "[TMU] Cache stalled cycles for x4 access"}, + {"TMU", "TMU-total-text-quads-x4-access", "[TMU] Total texture cache x4 access"}, + {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"}, + {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"}, + {"L2T", "L2T-local", "[L2T] Local mode access"}, + {"L2T", "L2T-writeback", "[L2T] Writeback"}, + {"L2T", "L2T-zero", "[L2T] Zero"}, + {"L2T", "L2T-merge", "[L2T] Merge"}, + {"L2T", "L2T-fill", "[L2T] Fill"}, + {"L2T", "L2T-stalls-no-wid", "[L2T] Stalls because no WID available"}, + {"L2T", "L2T-stalls-no-rid", "[L2T] Stalls because no RID available"}, + {"L2T", "L2T-stalls-queue-full", "[L2T] Stalls because internal queue full"}, + {"L2T", "L2T-stalls-wrightback", "[L2T] Stalls because writeback in flight"}, + {"L2T", "L2T-stalls-mem", "[L2T] Stalls because AXI blocks read"}, + {"L2T", "L2T-stalls-fill", "[L2T] Stalls because fill pending for victim cache-line"}, + {"L2T", "L2T-hitq", "[L2T] Sent request via hit queue"}, + {"L2T", "L2T-hitq-full", "[L2T] Sent request via main queue because hit queue is full"}, + {"L2T", "L2T-stalls-read-data", "[L2T] Stalls because waiting for data from SDRAM"}, + {"L2T", "L2T-TMU-read-hits", "[L2T] TMU read hits"}, + {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"}, + {"L2T", "L2T-VCD-read-hits", "[L2T] VCD read hits"}, + {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"}, + {"L2T", "L2T-SLC-read-hits", "[L2T] SLC read hits (all slices)"}, + {"L2T", "L2T-SLC-read-miss", "[L2T] SLC read misses (all slices)"}, + {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"}, + {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"}, + {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"}, + {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"}, + {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"}, + {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"}, + {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"}, + {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"}, + {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"}, + {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"}, + {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"}, + {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"}, + {"CORE", "core-memory-writes", "[CORE] Total memory writes"}, + {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"}, + {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"}, + {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"}, + {"CORE", "core-memory-reads", "[CORE] Total memory reads"}, + {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"}, + {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"}, + {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"}, + {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"}, + {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"}, + {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"}, + {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"}, + {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"}, + {"AXI", "AXI-read-trans", "[AXI] Read transaction count"}, + {"AXI", "AXI-write-trans", "[AXI] Write transaction count"}, + {"AXI", "AXI-read-wait-cycles", "[AXI] Read total wait cycles"}, + {"AXI", "AXI-write-wait-cycles", "[AXI] Write total wait cycles"}, + {"AXI", "AXI-max-outstanding-reads", "[AXI] Maximum outstanding read transactions"}, + {"AXI", "AXI-max-outstanding-writes", "[AXI] Maximum outstanding write transactions"}, + {"QPU", "QPU-wait-bubble", "[QPU] Pipeline bubble in qcycles due all threads waiting"}, + {"QPU", "QPU-ic-miss-bubble", "[QPU] Pipeline bubble in qcycles due instruction-cache miss"}, + {"QPU", "QPU-active", "[QPU] Executed shader instruction"}, + {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"}, + {"QPU", "QPU-stalls", "[QPU] Stalled qcycles executing shader instruction"}, + {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"}, + {"QPU", "QPU-stalls-TMU", "[QPU] Stalled qcycles waiting for TMU"}, + {"QPU", "QPU-stalls-TLB", "[QPU] Stalled qcycles waiting for TLB"}, + {"QPU", "QPU-stalls-VPM", "[QPU] Stalled qcycles waiting for VPM"}, + {"QPU", "QPU-stalls-uniforms", "[QPU] Stalled qcycles waiting for uniforms"}, + {"QPU", "QPU-stalls-SFU", "[QPU] Stalled qcycles waiting for SFU"}, + {"QPU", "QPU-stalls-other", "[QPU] Stalled qcycles waiting for any other reason (vary/W/Z)"}, +}; + void v3d_perfmon_get(struct v3d_perfmon *perfmon) { if (perfmon) @@ -123,6 +309,7 @@ int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data, { struct v3d_file_priv *v3d_priv = file_priv->driver_priv; struct drm_v3d_perfmon_create *req = data; + struct v3d_dev *v3d = v3d_priv->v3d; struct v3d_perfmon *perfmon; unsigned int i; int ret; @@ -134,7 +321,7 @@ int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data, /* Make sure all counters are valid. */ for (i = 0; i < req->ncounters; i++) { - if (req->counters[i] >= V3D_PERFCNT_NUM) + if (req->counters[i] >= v3d->max_counters) return -EINVAL; } @@ -216,3 +403,42 @@ int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data, return ret; } + +int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_v3d_perfmon_get_counter *req = data; + struct v3d_dev *v3d = to_v3d_dev(dev); + const struct v3d_perf_counter_desc *counter; + + for (int i = 0; i < ARRAY_SIZE(req->reserved); i++) { + if (req->reserved[i] != 0) + return -EINVAL; + } + + /* Make sure that the counter ID is valid */ + if (req->counter >= v3d->max_counters) + return -EINVAL; + + BUILD_BUG_ON(ARRAY_SIZE(v3d_v42_performance_counters) != + V3D_V42_NUM_PERFCOUNTERS); + BUILD_BUG_ON(ARRAY_SIZE(v3d_v71_performance_counters) != + V3D_V71_NUM_PERFCOUNTERS); + BUILD_BUG_ON(V3D_MAX_COUNTERS < V3D_V42_NUM_PERFCOUNTERS); + BUILD_BUG_ON(V3D_MAX_COUNTERS < V3D_V71_NUM_PERFCOUNTERS); + BUILD_BUG_ON((V3D_MAX_COUNTERS != V3D_V42_NUM_PERFCOUNTERS) && + (V3D_MAX_COUNTERS != V3D_V71_NUM_PERFCOUNTERS)); + + if (v3d->ver >= 71) + counter = &v3d_v71_performance_counters[req->counter]; + else if (v3d->ver >= 42) + counter = &v3d_v42_performance_counters[req->counter]; + else + return -EOPNOTSUPP; + + strscpy(req->name, counter->name, sizeof(req->name)); + strscpy(req->category, counter->category, sizeof(req->category)); + strscpy(req->description, counter->description, sizeof(req->description)); + + return 0; +} diff --git a/drivers/gpu/drm/v3d/v3d_performance_counters.h b/drivers/gpu/drm/v3d/v3d_performance_counters.h new file mode 100644 index 000000000000..131b2909522a --- /dev/null +++ b/drivers/gpu/drm/v3d/v3d_performance_counters.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2024 Raspberry Pi + */ +#ifndef V3D_PERFORMANCE_COUNTERS_H +#define V3D_PERFORMANCE_COUNTERS_H + +/* Holds a description of a given performance counter. The index of performance + * counter is given by the array on v3d_performance_counter.h + */ +struct v3d_perf_counter_desc { + /* Category of the counter */ + char category[32]; + + /* Name of the counter */ + char name[64]; + + /* Description of the counter */ + char description[256]; +}; + + +#define V3D_V42_NUM_PERFCOUNTERS (87) +#define V3D_V71_NUM_PERFCOUNTERS (93) + +/* Maximum number of performance counters supported by any version of V3D */ +#define V3D_MAX_COUNTERS (93) + +#endif diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 7cd8c335cd9b..03df37a3acf5 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -490,7 +490,7 @@ v3d_write_performance_query_result(struct v3d_cpu_job *job, void *data, u32 quer struct v3d_file_priv *v3d_priv = job->base.file->driver_priv; struct v3d_dev *v3d = job->base.v3d; struct v3d_perfmon *perfmon; - u64 counter_values[V3D_PERFCNT_NUM]; + u64 counter_values[V3D_MAX_COUNTERS]; for (int i = 0; i < performance_query->nperfmons; i++) { perfmon = v3d_perfmon_find(v3d_priv, diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c b/drivers/gpu/drm/vboxvideo/vbox_drv.c index cd9e66a06596..ef36834c8673 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_drv.c +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c @@ -14,7 +14,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_ttm.h> #include <drm/drm_file.h> #include <drm/drm_ioctl.h> #include <drm/drm_managed.h> @@ -80,7 +80,7 @@ static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto err_irq_fini; - drm_fbdev_generic_setup(&vbox->ddev, 32); + drm_fbdev_ttm_setup(&vbox->ddev, 32); return 0; diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig index 91dcf8d174d6..269b5f26b2ea 100644 --- a/drivers/gpu/drm/vc4/Kconfig +++ b/drivers/gpu/drm/vc4/Kconfig @@ -10,6 +10,7 @@ config DRM_VC4 depends on COMMON_CLK depends on PM select DRM_DISPLAY_HDMI_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.c b/drivers/gpu/drm/vc4/tests/vc4_mock.c index becb3dbaa548..0731a7d85d7a 100644 --- a/drivers/gpu/drm/vc4/tests/vc4_mock.c +++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c @@ -109,16 +109,14 @@ static const struct vc4_mock_desc vc5_mock = static int __build_one_pipe(struct kunit *test, struct drm_device *drm, const struct vc4_mock_pipe_desc *pipe) { - struct vc4_dummy_plane *dummy_plane; struct drm_plane *plane; struct vc4_dummy_crtc *dummy_crtc; struct drm_crtc *crtc; unsigned int i; - dummy_plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane); + plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane); - plane = &dummy_plane->plane.base; dummy_crtc = vc4_mock_pv(test, drm, plane, pipe->data); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_crtc); diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock.h b/drivers/gpu/drm/vc4/tests/vc4_mock.h index 2d0b339bd9f3..002b6218960c 100644 --- a/drivers/gpu/drm/vc4/tests/vc4_mock.h +++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h @@ -21,13 +21,8 @@ struct drm_crtc *vc4_find_crtc_for_encoder(struct kunit *test, return NULL; } -struct vc4_dummy_plane { - struct vc4_plane plane; -}; - -struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test, - struct drm_device *drm, - enum drm_plane_type type); +struct drm_plane *vc4_dummy_plane(struct kunit *test, struct drm_device *drm, + enum drm_plane_type type); struct vc4_dummy_crtc { struct vc4_crtc crtc; diff --git a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c index 62b18f5f41db..14357db82238 100644 --- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c +++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c @@ -1,47 +1,25 @@ // SPDX-License-Identifier: GPL-2.0 -#include <drm/drm_atomic_state_helper.h> -#include <drm/drm_fourcc.h> -#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_kunit_helpers.h> #include <drm/drm_plane.h> #include <kunit/test.h> #include "vc4_mock.h" -static const struct drm_plane_helper_funcs vc4_dummy_plane_helper_funcs = { -}; - -static const struct drm_plane_funcs vc4_dummy_plane_funcs = { - .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, - .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, - .reset = drm_atomic_helper_plane_reset, -}; - -static const uint32_t vc4_dummy_plane_formats[] = { - DRM_FORMAT_XRGB8888, -}; - -struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test, - struct drm_device *drm, - enum drm_plane_type type) +struct drm_plane *vc4_dummy_plane(struct kunit *test, struct drm_device *drm, + enum drm_plane_type type) { - struct vc4_dummy_plane *dummy_plane; struct drm_plane *plane; - dummy_plane = drmm_universal_plane_alloc(drm, - struct vc4_dummy_plane, plane.base, - 0, - &vc4_dummy_plane_funcs, - vc4_dummy_plane_formats, - ARRAY_SIZE(vc4_dummy_plane_formats), - NULL, - DRM_PLANE_TYPE_PRIMARY, - NULL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane); + KUNIT_ASSERT_EQ(test, type, DRM_PLANE_TYPE_PRIMARY); - plane = &dummy_plane->plane.base; - drm_plane_helper_add(plane, &vc4_dummy_plane_helper_funcs); + plane = drm_kunit_helper_create_primary_plane(test, drm, + NULL, + NULL, + NULL, 0, + NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane); - return dummy_plane; + return plane; } diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index d30f8e8e8967..d57c4a5948c8 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -32,6 +32,7 @@ */ #include <drm/display/drm_hdmi_helper.h> +#include <drm/display/drm_hdmi_state_helper.h> #include <drm/display/drm_scdc_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> @@ -110,25 +111,6 @@ #define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) -static const char * const output_format_str[] = { - [VC4_HDMI_OUTPUT_RGB] = "RGB", - [VC4_HDMI_OUTPUT_YUV420] = "YUV 4:2:0", - [VC4_HDMI_OUTPUT_YUV422] = "YUV 4:2:2", - [VC4_HDMI_OUTPUT_YUV444] = "YUV 4:4:4", -}; - -static const char *vc4_hdmi_output_fmt_str(enum vc4_hdmi_output_format fmt) -{ - if (fmt >= ARRAY_SIZE(output_format_str)) - return "invalid"; - - return output_format_str[fmt]; -} - -static unsigned long long -vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, - unsigned int bpc, enum vc4_hdmi_output_format fmt); - static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi) { struct drm_display_info *display = &vc4_hdmi->connector.display_info; @@ -147,28 +129,13 @@ static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi) static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode, unsigned int bpc, - enum vc4_hdmi_output_format fmt) + enum hdmi_colorspace fmt) { - unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt); + unsigned long long clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt); return clock > HDMI_14_MAX_TMDS_CLK; } -static bool vc4_hdmi_is_full_range(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_state) -{ - const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - struct drm_display_info *display = &vc4_hdmi->connector.display_info; - - if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_LIMITED) - return false; - else if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_FULL) - return true; - - return !display->is_hdmi || - drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_FULL; -} - static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) { struct drm_debugfs_entry *entry = m->private; @@ -524,7 +491,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) const struct drm_display_mode *mode; list_for_each_entry(mode, &connector->probed_modes, head) { - if (vc4_hdmi_mode_needs_scrambling(mode, 8, VC4_HDMI_OUTPUT_RGB)) { + if (vc4_hdmi_mode_needs_scrambling(mode, 8, HDMI_COLORSPACE_RGB)) { drm_warn_once(drm, "The core clock cannot reach frequencies high enough to support 4k @ 60Hz."); drm_warn_once(drm, "Please change your config.txt file to add hdmi_enable_4kp60."); } @@ -539,12 +506,8 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector, { struct drm_connector_state *old_state = drm_atomic_get_old_connector_state(state, connector); - struct vc4_hdmi_connector_state *old_vc4_state = - conn_state_to_vc4_hdmi_conn_state(old_state); struct drm_connector_state *new_state = drm_atomic_get_new_connector_state(state, connector); - struct vc4_hdmi_connector_state *new_vc4_state = - conn_state_to_vc4_hdmi_conn_state(new_state); struct drm_crtc *crtc = new_state->crtc; if (!crtc) @@ -576,9 +539,7 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector, return ret; } - if (old_state->colorspace != new_state->colorspace || - old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb || - !drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) { + if (old_state->colorspace != new_state->colorspace) { struct drm_crtc_state *crtc_state; crtc_state = drm_atomic_get_crtc_state(state, crtc); @@ -588,112 +549,21 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector, crtc_state->mode_changed = true; } - return 0; -} - -static int vc4_hdmi_connector_get_property(struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val) -{ - struct drm_device *drm = connector->dev; - struct vc4_hdmi *vc4_hdmi = - connector_to_vc4_hdmi(connector); - const struct vc4_hdmi_connector_state *vc4_conn_state = - conn_state_to_vc4_hdmi_conn_state(state); - - if (property == vc4_hdmi->broadcast_rgb_property) { - *val = vc4_conn_state->broadcast_rgb; - } else { - drm_dbg(drm, "Unknown property [PROP:%d:%s]\n", - property->base.id, property->name); - return -EINVAL; - } - - return 0; -} - -static int vc4_hdmi_connector_set_property(struct drm_connector *connector, - struct drm_connector_state *state, - struct drm_property *property, - uint64_t val) -{ - struct drm_device *drm = connector->dev; - struct vc4_hdmi *vc4_hdmi = - connector_to_vc4_hdmi(connector); - struct vc4_hdmi_connector_state *vc4_conn_state = - conn_state_to_vc4_hdmi_conn_state(state); - - if (property == vc4_hdmi->broadcast_rgb_property) { - vc4_conn_state->broadcast_rgb = val; - return 0; - } - - drm_dbg(drm, "Unknown property [PROP:%d:%s]\n", - property->base.id, property->name); - return -EINVAL; + return drm_atomic_helper_connector_hdmi_check(connector, state); } static void vc4_hdmi_connector_reset(struct drm_connector *connector) { - struct vc4_hdmi_connector_state *old_state = - conn_state_to_vc4_hdmi_conn_state(connector->state); - struct vc4_hdmi_connector_state *new_state = - kzalloc(sizeof(*new_state), GFP_KERNEL); - - if (connector->state) - __drm_atomic_helper_connector_destroy_state(connector->state); - - kfree(old_state); - __drm_atomic_helper_connector_reset(connector, &new_state->base); - - if (!new_state) - return; - - new_state->base.max_bpc = 8; - new_state->base.max_requested_bpc = 8; - new_state->output_format = VC4_HDMI_OUTPUT_RGB; - new_state->broadcast_rgb = VC4_HDMI_BROADCAST_RGB_AUTO; + drm_atomic_helper_connector_reset(connector); + __drm_atomic_helper_connector_hdmi_reset(connector, connector->state); drm_atomic_helper_connector_tv_margins_reset(connector); } -static struct drm_connector_state * -vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) -{ - struct drm_connector_state *conn_state = connector->state; - struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state); - struct vc4_hdmi_connector_state *new_state; - - new_state = kzalloc(sizeof(*new_state), GFP_KERNEL); - if (!new_state) - return NULL; - - new_state->tmds_char_rate = vc4_state->tmds_char_rate; - new_state->output_bpc = vc4_state->output_bpc; - new_state->output_format = vc4_state->output_format; - new_state->broadcast_rgb = vc4_state->broadcast_rgb; - __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); - - return &new_state->base; -} - -static void vc4_hdmi_connector_destroy_state(struct drm_connector *connector, - struct drm_connector_state *state) -{ - struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(state); - - __drm_atomic_helper_connector_destroy_state(state); - kfree(vc4_state); -} - static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .reset = vc4_hdmi_connector_reset, - .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state, - .atomic_destroy_state = vc4_hdmi_connector_destroy_state, - .atomic_get_property = vc4_hdmi_connector_get_property, - .atomic_set_property = vc4_hdmi_connector_set_property, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = { @@ -702,44 +572,29 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = .atomic_check = vc4_hdmi_connector_atomic_check, }; -static const struct drm_prop_enum_list broadcast_rgb_names[] = { - { VC4_HDMI_BROADCAST_RGB_AUTO, "Automatic" }, - { VC4_HDMI_BROADCAST_RGB_FULL, "Full" }, - { VC4_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235" }, -}; - -static void -vc4_hdmi_attach_broadcast_rgb_property(struct drm_device *dev, - struct vc4_hdmi *vc4_hdmi) -{ - struct drm_property *prop = vc4_hdmi->broadcast_rgb_property; - - if (!prop) { - prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, - "Broadcast RGB", - broadcast_rgb_names, - ARRAY_SIZE(broadcast_rgb_names)); - if (!prop) - return; - - vc4_hdmi->broadcast_rgb_property = prop; - } - - drm_object_attach_property(&vc4_hdmi->connector.base, prop, - VC4_HDMI_BROADCAST_RGB_AUTO); -} +static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs; static int vc4_hdmi_connector_init(struct drm_device *dev, struct vc4_hdmi *vc4_hdmi) { struct drm_connector *connector = &vc4_hdmi->connector; struct drm_encoder *encoder = &vc4_hdmi->encoder.base; + unsigned int max_bpc = 8; int ret; - ret = drmm_connector_init(dev, connector, - &vc4_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA, - vc4_hdmi->ddc); + if (vc4_hdmi->variant->supports_hdr) + max_bpc = 12; + + ret = drmm_connector_hdmi_init(dev, connector, + "Broadcom", "Videocore", + &vc4_hdmi_connector_funcs, + &vc4_hdmi_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA, + vc4_hdmi->ddc, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + max_bpc); if (ret) return ret; @@ -763,7 +618,6 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, drm_connector_attach_colorspace_property(connector); drm_connector_attach_tv_margin_properties(connector); - drm_connector_attach_max_bpc_property(connector, 8, 12); connector->polled = (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT); @@ -772,21 +626,19 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, connector->doublescan_allowed = 0; connector->stereo_allowed = 1; - if (vc4_hdmi->variant->supports_hdr) - drm_connector_attach_hdr_output_metadata_property(connector); - - vc4_hdmi_attach_broadcast_rgb_property(dev, vc4_hdmi); + ret = drm_connector_attach_broadcast_rgb_property(connector); + if (ret) + return ret; drm_connector_attach_encoder(connector, encoder); return 0; } -static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, +static int vc4_hdmi_stop_packet(struct vc4_hdmi *vc4_hdmi, enum hdmi_infoframe_type type, bool poll) { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_device *drm = vc4_hdmi->connector.dev; u32 packet_id = type - 0x80; unsigned long flags; @@ -810,12 +662,13 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, return ret; } -static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, - union hdmi_infoframe *frame) +static int vc4_hdmi_write_infoframe(struct drm_connector *connector, + enum hdmi_infoframe_type type, + const u8 *infoframe, size_t len) { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_device *drm = vc4_hdmi->connector.dev; - u32 packet_id = frame->any.type - 0x80; + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); + struct drm_device *drm = connector->dev; + u32 packet_id = type - 0x80; const struct vc4_hdmi_register *ram_packet_start = &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START]; u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id; @@ -825,22 +678,25 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, ram_packet_start->reg); uint8_t buffer[VC4_HDMI_PACKET_STRIDE] = {}; unsigned long flags; - ssize_t len, i; + ssize_t i; int ret; int idx; if (!drm_dev_enter(drm, &idx)) - return; + return 0; + + if (len > sizeof(buffer)) { + ret = -ENOMEM; + goto out; + } + + memcpy(buffer, infoframe, len); WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & VC4_HDMI_RAM_PACKET_ENABLE), "Packet RAM has to be on to store the packet."); - len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer)); - if (len < 0) - goto out; - - ret = vc4_hdmi_stop_packet(encoder, frame->any.type, true); + ret = vc4_hdmi_stop_packet(vc4_hdmi, type, true); if (ret) { DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret); goto out; @@ -882,130 +738,7 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, out: drm_dev_exit(idx); -} - -static void vc4_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame, - enum vc4_hdmi_output_format fmt) -{ - switch (fmt) { - case VC4_HDMI_OUTPUT_RGB: - frame->colorspace = HDMI_COLORSPACE_RGB; - break; - - case VC4_HDMI_OUTPUT_YUV420: - frame->colorspace = HDMI_COLORSPACE_YUV420; - break; - - case VC4_HDMI_OUTPUT_YUV422: - frame->colorspace = HDMI_COLORSPACE_YUV422; - break; - - case VC4_HDMI_OUTPUT_YUV444: - frame->colorspace = HDMI_COLORSPACE_YUV444; - break; - - default: - break; - } -} - -static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) -{ - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_connector *connector = &vc4_hdmi->connector; - struct drm_connector_state *cstate = connector->state; - struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(cstate); - const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - union hdmi_infoframe frame; - int ret; - - lockdep_assert_held(&vc4_hdmi->mutex); - - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, - connector, mode); - if (ret < 0) { - DRM_ERROR("couldn't fill AVI infoframe\n"); - return; - } - - drm_hdmi_avi_infoframe_quant_range(&frame.avi, - connector, mode, - vc4_hdmi_is_full_range(vc4_hdmi, vc4_state) ? - HDMI_QUANTIZATION_RANGE_FULL : - HDMI_QUANTIZATION_RANGE_LIMITED); - drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate); - vc4_hdmi_avi_infoframe_colorspace(&frame.avi, vc4_state->output_format); - drm_hdmi_avi_infoframe_bars(&frame.avi, cstate); - - vc4_hdmi_write_infoframe(encoder, &frame); -} - -static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder) -{ - union hdmi_infoframe frame; - int ret; - - ret = hdmi_spd_infoframe_init(&frame.spd, "Broadcom", "Videocore"); - if (ret < 0) { - DRM_ERROR("couldn't fill SPD infoframe\n"); - return; - } - - frame.spd.sdi = HDMI_SPD_SDI_PC; - - vc4_hdmi_write_infoframe(encoder, &frame); -} - -static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder) -{ - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct hdmi_audio_infoframe *audio = &vc4_hdmi->audio.infoframe; - union hdmi_infoframe frame; - - memcpy(&frame.audio, audio, sizeof(*audio)); - - if (vc4_hdmi->packet_ram_enabled) - vc4_hdmi_write_infoframe(encoder, &frame); -} - -static void vc4_hdmi_set_hdr_infoframe(struct drm_encoder *encoder) -{ - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_connector *connector = &vc4_hdmi->connector; - struct drm_connector_state *conn_state = connector->state; - union hdmi_infoframe frame; - - lockdep_assert_held(&vc4_hdmi->mutex); - - if (!vc4_hdmi->variant->supports_hdr) - return; - - if (!conn_state->hdr_output_metadata) - return; - - if (drm_hdmi_infoframe_set_hdr_metadata(&frame.drm, conn_state)) - return; - - vc4_hdmi_write_infoframe(encoder, &frame); -} - -static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) -{ - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - - lockdep_assert_held(&vc4_hdmi->mutex); - - vc4_hdmi_set_avi_infoframe(encoder); - vc4_hdmi_set_spd_infoframe(encoder); - /* - * If audio was streaming, then we need to reenabled the audio - * infoframe here during encoder_enable. - */ - if (vc4_hdmi->audio.streaming) - vc4_hdmi_set_audio_infoframe(encoder); - - vc4_hdmi_set_hdr_infoframe(encoder); + return ret; } #define SCRAMBLING_POLLING_DELAY_MS 1000 @@ -1174,8 +907,6 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, const struct drm_display_mode *mode) { - struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(state); struct drm_device *drm = vc4_hdmi->connector.dev; unsigned long flags; u32 csc_ctl; @@ -1189,7 +920,7 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, VC4_HD_CSC_CTL_ORDER); - if (!vc4_hdmi_is_full_range(vc4_hdmi, vc4_state)) { + if (state->hdmi.is_limited_range) { /* CEA VICs other than #1 requre limited range RGB * output unless overridden by an AVI infoframe. * Apply a colorspace conversion to squash 0-255 down @@ -1412,9 +1143,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, const struct drm_display_mode *mode) { struct drm_device *drm = vc4_hdmi->connector.dev; - struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(state); - unsigned int lim_range = vc4_hdmi_is_full_range(vc4_hdmi, vc4_state) ? 0 : 1; + unsigned int lim_range = state->hdmi.is_limited_range ? 1 : 0; unsigned long flags; const u16 (*csc)[4]; u32 if_cfg = 0; @@ -1429,14 +1158,14 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - switch (vc4_state->output_format) { - case VC4_HDMI_OUTPUT_YUV444: + switch (state->hdmi.output_format) { + case HDMI_COLORSPACE_YUV444: csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc); break; - case VC4_HDMI_OUTPUT_YUV422: + case HDMI_COLORSPACE_YUV422: csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD, @@ -1453,7 +1182,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc); break; - case VC4_HDMI_OUTPUT_RGB: + case HDMI_COLORSPACE_RGB: if_xbar = 0x354021; vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_rgb[lim_range]); @@ -1542,8 +1271,6 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, const struct drm_display_mode *mode) { struct drm_device *drm = vc4_hdmi->connector.dev; - const struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(state); bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; @@ -1595,7 +1322,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); - switch (vc4_state->output_bpc) { + switch (state->hdmi.output_bpc) { case 12: gcp = 6; break; @@ -1612,7 +1339,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, * YCC422 is always 36-bit and not considered deep colour so * doesn't signal in GCP. */ - if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) { + if (state->hdmi.output_format == HDMI_COLORSPACE_YUV422) { gcp = 0; } @@ -1696,10 +1423,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, struct drm_connector *connector = &vc4_hdmi->connector; struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, connector); - struct vc4_hdmi_connector_state *vc4_conn_state = - conn_state_to_vc4_hdmi_conn_state(conn_state); const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - unsigned long tmds_char_rate = vc4_conn_state->tmds_char_rate; + unsigned long long tmds_char_rate = conn_state->hdmi.tmds_char_rate; unsigned long bvb_rate, hsm_rate; unsigned long flags; int ret; @@ -1734,7 +1459,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, */ hsm_rate = max_t(unsigned long, HSM_MIN_CLOCK_FREQ, - (tmds_char_rate / 100) * 101); + div_u64(tmds_char_rate, 100) * 101); ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); @@ -1776,7 +1501,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, } if (vc4_hdmi->variant->phy_init) - vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state); + vc4_hdmi->variant->phy_init(vc4_hdmi, conn_state); spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -1841,7 +1566,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_device *drm = connector->dev; const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; struct drm_display_info *display = &vc4_hdmi->connector.display_info; bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; @@ -1907,7 +1633,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); vc4_hdmi->packet_ram_enabled = true; - vc4_hdmi_set_infoframes(encoder); + drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); } vc4_hdmi_recenter_fifo(vc4_hdmi); @@ -1924,108 +1650,21 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(conn_state); mutex_lock(&vc4_hdmi->mutex); drm_mode_copy(&vc4_hdmi->saved_adjusted_mode, &crtc_state->adjusted_mode); - vc4_hdmi->output_bpc = vc4_state->output_bpc; - vc4_hdmi->output_format = vc4_state->output_format; + vc4_hdmi->output_bpc = conn_state->hdmi.output_bpc; + vc4_hdmi->output_format = conn_state->hdmi.output_format; mutex_unlock(&vc4_hdmi->mutex); } -static bool -vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi *vc4_hdmi, - const struct drm_display_info *info, - const struct drm_display_mode *mode, - unsigned int format, unsigned int bpc) -{ - struct drm_device *dev = vc4_hdmi->connector.dev; - u8 vic = drm_match_cea_mode(mode); - - if (vic == 1 && bpc != 8) { - drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc); - return false; - } - - if (!info->is_hdmi && - (format != VC4_HDMI_OUTPUT_RGB || bpc != 8)) { - drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n"); - return false; - } - - switch (format) { - case VC4_HDMI_OUTPUT_RGB: - drm_dbg(dev, "RGB Format, checking the constraints.\n"); - - if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) - return false; - - if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { - drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); - return false; - } - - if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { - drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); - return false; - } - - drm_dbg(dev, "RGB format supported in that configuration.\n"); - - return true; - - case VC4_HDMI_OUTPUT_YUV422: - drm_dbg(dev, "YUV422 format, checking the constraints.\n"); - - if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { - drm_dbg(dev, "Sink doesn't support YUV422.\n"); - return false; - } - - if (bpc != 12) { - drm_dbg(dev, "YUV422 only supports 12 bpc.\n"); - return false; - } - - drm_dbg(dev, "YUV422 format supported in that configuration.\n"); - - return true; - - case VC4_HDMI_OUTPUT_YUV444: - drm_dbg(dev, "YUV444 format, checking the constraints.\n"); - - if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) { - drm_dbg(dev, "Sink doesn't support YUV444.\n"); - return false; - } - - if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) { - drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); - return false; - } - - if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) { - drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); - return false; - } - - drm_dbg(dev, "YUV444 format supported in that configuration.\n"); - - return true; - } - - return false; -} - static enum drm_mode_status -vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, - const struct drm_display_mode *mode, - unsigned long long clock) +vc4_hdmi_connector_clock_valid(const struct drm_connector *connector, + const struct drm_display_mode *mode, + unsigned long long clock) { - const struct drm_connector *connector = &vc4_hdmi->connector; - const struct drm_display_info *info = &connector->display_info; + const struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); struct vc4_dev *vc4 = to_vc4_dev(connector->dev); if (clock > vc4_hdmi->variant->max_pixel_clock) @@ -2040,125 +1679,13 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, drm_mode_vrefresh(mode) >= 50) return MODE_CLOCK_HIGH; - if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000)) - return MODE_CLOCK_HIGH; - return MODE_OK; } -static unsigned long long -vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, - unsigned int bpc, - enum vc4_hdmi_output_format fmt) -{ - unsigned long long clock = mode->clock * 1000ULL; - - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - clock = clock * 2; - - if (fmt == VC4_HDMI_OUTPUT_YUV422) - bpc = 8; - - clock = clock * bpc; - do_div(clock, 8); - - return clock; -} - -static int -vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_state, - const struct drm_display_mode *mode, - unsigned int bpc, unsigned int fmt) -{ - unsigned long long clock; - - clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt); - if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, clock) != MODE_OK) - return -EINVAL; - - vc4_state->tmds_char_rate = clock; - - return 0; -} - -static int -vc4_hdmi_encoder_compute_format(const struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_state, - const struct drm_display_mode *mode, - unsigned int bpc) -{ - struct drm_device *dev = vc4_hdmi->connector.dev; - const struct drm_connector *connector = &vc4_hdmi->connector; - const struct drm_display_info *info = &connector->display_info; - unsigned int format; - - drm_dbg(dev, "Trying with an RGB output\n"); - - format = VC4_HDMI_OUTPUT_RGB; - if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) { - int ret; - - ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, - mode, bpc, format); - if (!ret) { - vc4_state->output_format = format; - return 0; - } - } - - drm_dbg(dev, "Failed, Trying with an YUV422 output\n"); - - format = VC4_HDMI_OUTPUT_YUV422; - if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) { - int ret; - - ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, - mode, bpc, format); - if (!ret) { - vc4_state->output_format = format; - return 0; - } - } - - drm_dbg(dev, "Failed. No Format Supported for that bpc count.\n"); - - return -EINVAL; -} - -static int -vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_state, - const struct drm_display_mode *mode) -{ - struct drm_device *dev = vc4_hdmi->connector.dev; - struct drm_connector_state *conn_state = &vc4_state->base; - unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12); - unsigned int bpc; - int ret; - - for (bpc = max_bpc; bpc >= 8; bpc -= 2) { - drm_dbg(dev, "Trying with a %d bpc output\n", bpc); - - ret = vc4_hdmi_encoder_compute_format(vc4_hdmi, vc4_state, - mode, bpc); - if (ret) - continue; - - vc4_state->output_bpc = bpc; - - drm_dbg(dev, - "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n", - mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), - vc4_state->output_bpc, - vc4_hdmi_output_fmt_str(vc4_state->output_format), - vc4_state->tmds_char_rate); - - break; - } - - return ret; -} +static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs = { + .tmds_char_rate_valid = vc4_hdmi_connector_clock_valid, + .write_infoframe = vc4_hdmi_write_infoframe, +}; #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL #define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL @@ -2168,16 +1695,9 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_connector *connector = &vc4_hdmi->connector; - struct drm_connector_state *old_conn_state = - drm_atomic_get_old_connector_state(conn_state->state, connector); - struct vc4_hdmi_connector_state *old_vc4_state = - conn_state_to_vc4_hdmi_conn_state(old_conn_state); - struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state); struct drm_display_mode *mode = &crtc_state->adjusted_mode; unsigned long long tmds_char_rate = mode->clock * 1000; unsigned long long tmds_bit_rate; - int ret; if (vc4_hdmi->variant->unsupported_odd_h_timings) { if (mode->flags & DRM_MODE_FLAG_DBLCLK) { @@ -2213,15 +1733,6 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, tmds_char_rate = mode->clock * 1000; } - ret = vc4_hdmi_encoder_compute_config(vc4_hdmi, vc4_state, mode); - if (ret) - return ret; - - /* vc4_hdmi_encoder_compute_config may have changed output_bpc and/or output_format */ - if (vc4_state->output_bpc != old_vc4_state->output_bpc || - vc4_state->output_format != old_vc4_state->output_format) - crtc_state->mode_changed = true; - return 0; } @@ -2230,6 +1741,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + unsigned long long rate; if (vc4_hdmi->variant->unsupported_odd_h_timings && !(mode->flags & DRM_MODE_FLAG_DBLCLK) && @@ -2237,7 +1749,8 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, (mode->hsync_end % 2) || (mode->htotal % 2))) return MODE_H_ILLEGAL; - return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, mode->clock * 1000); + rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB); + return vc4_hdmi_connector_clock_valid(&vc4_hdmi->connector, mode, rate); } static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { @@ -2429,7 +1942,6 @@ out: static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) { - struct drm_encoder *encoder = &vc4_hdmi->encoder.base; struct device *dev = &vc4_hdmi->pdev->dev; unsigned long flags; int ret; @@ -2437,7 +1949,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) lockdep_assert_held(&vc4_hdmi->mutex); vc4_hdmi->audio.streaming = false; - ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO, false); + ret = vc4_hdmi_stop_packet(vc4_hdmi, HDMI_INFOFRAME_TYPE_AUDIO, false); if (ret) dev_err(dev, "Failed to stop audio infoframe: %d\n", ret); @@ -2528,7 +2040,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, { struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); struct drm_device *drm = vc4_hdmi->connector.dev; - struct drm_encoder *encoder = &vc4_hdmi->encoder.base; + struct drm_connector *connector = &vc4_hdmi->connector; unsigned int sample_rate = params->sample_rate; unsigned int channels = params->channels; unsigned long flags; @@ -2605,8 +2117,10 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - memcpy(&vc4_hdmi->audio.infoframe, ¶ms->cea, sizeof(params->cea)); - vc4_hdmi_set_audio_infoframe(encoder); + ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, + ¶ms->cea); + if (ret) + goto out_dev_exit; out_dev_exit: drm_dev_exit(idx); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 934d5d61485a..b37f1d2c3fe5 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -10,7 +10,6 @@ struct vc4_hdmi; struct vc4_hdmi_register; -struct vc4_hdmi_connector_state; enum vc4_hdmi_phy_channel { PHY_LANE_0 = 0, @@ -76,7 +75,7 @@ struct vc4_hdmi_variant { /* Callback to initialize the PHY according to the connector state */ void (*phy_init)(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_conn_state); + struct drm_connector_state *conn_state); /* Callback to disable the PHY */ void (*phy_disable)(struct vc4_hdmi *vc4_hdmi); @@ -110,19 +109,6 @@ struct vc4_hdmi_audio { bool streaming; }; -enum vc4_hdmi_output_format { - VC4_HDMI_OUTPUT_RGB, - VC4_HDMI_OUTPUT_YUV422, - VC4_HDMI_OUTPUT_YUV444, - VC4_HDMI_OUTPUT_YUV420, -}; - -enum vc4_hdmi_broadcast_rgb { - VC4_HDMI_BROADCAST_RGB_AUTO, - VC4_HDMI_BROADCAST_RGB_FULL, - VC4_HDMI_BROADCAST_RGB_LIMITED, -}; - /* General HDMI hardware state. */ struct vc4_hdmi { struct vc4_hdmi_audio audio; @@ -135,8 +121,6 @@ struct vc4_hdmi { struct delayed_work scrambling_work; - struct drm_property *broadcast_rgb_property; - struct i2c_adapter *ddc; void __iomem *hdmicore_regs; void __iomem *hd_regs; @@ -218,16 +202,17 @@ struct vc4_hdmi { bool scdc_enabled; /** - * @output_bpc: Copy of @vc4_connector_state.output_bpc for use - * outside of KMS hooks. Protected by @mutex. + * @output_bpc: Copy of @drm_connector_state.hdmi.output_bpc for + * use outside of KMS hooks. Protected by @mutex. */ unsigned int output_bpc; /** - * @output_format: Copy of @vc4_connector_state.output_format - * for use outside of KMS hooks. Protected by @mutex. + * @output_format: Copy of + * @drm_connector_state.hdmi.output_format for use outside of + * KMS hooks. Protected by @mutex. */ - enum vc4_hdmi_output_format output_format; + enum hdmi_colorspace output_format; }; #define connector_to_vc4_hdmi(_connector) \ @@ -240,25 +225,14 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder) return container_of_const(_encoder, struct vc4_hdmi, encoder); } -struct vc4_hdmi_connector_state { - struct drm_connector_state base; - unsigned long long tmds_char_rate; - unsigned int output_bpc; - enum vc4_hdmi_output_format output_format; - enum vc4_hdmi_broadcast_rgb broadcast_rgb; -}; - -#define conn_state_to_vc4_hdmi_conn_state(_state) \ - container_of_const(_state, struct vc4_hdmi_connector_state, base) - void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_conn_state); + struct drm_connector_state *conn_state); void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_conn_state); + struct drm_connector_state *conn_state); void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c index ec24999bf96d..1f5507fc7a03 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c @@ -128,7 +128,7 @@ #define OSCILLATOR_FREQUENCY 54000000 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *conn_state) + struct drm_connector_state *conn_state) { unsigned long flags; @@ -361,11 +361,11 @@ static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi) } void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *conn_state) + struct drm_connector_state *conn_state) { const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings; const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; - unsigned long long pixel_freq = conn_state->tmds_char_rate; + unsigned long long pixel_freq = conn_state->hdmi.tmds_char_rate; unsigned long long vco_freq; unsigned char word_sel; unsigned long flags; diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index ad924a8502e9..64baf2f22d9f 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -164,11 +164,9 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector) struct drm_display_mode *mode = NULL; int count, width, height; - if (output->edid) { - count = drm_add_edid_modes(connector, output->edid); - if (count) - return count; - } + count = drm_edid_connector_add_modes(connector); + if (count) + return count; width = le32_to_cpu(output->info.r.width); height = le32_to_cpu(output->info.r.height); @@ -369,5 +367,5 @@ void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) return; for (i = 0 ; i < vgdev->num_scanouts; ++i) - kfree(vgdev->outputs[i].edid); + drm_edid_free(vgdev->outputs[i].drm_edid); } diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 188e126383c2..e5a2665e50ea 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -35,7 +35,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_file.h> #include "virtgpu_drv.h" @@ -103,7 +103,7 @@ static int virtio_gpu_probe(struct virtio_device *vdev) if (ret) goto err_deinit; - drm_fbdev_generic_setup(vdev->priv, 32); + drm_fbdev_shmem_setup(vdev->priv, 32); return 0; err_deinit: diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index bb7d86a0c6a1..64c236169db8 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -179,7 +179,7 @@ struct virtio_gpu_output { struct drm_encoder enc; struct virtio_gpu_display_one info; struct virtio_gpu_update_cursor cursor; - struct edid *edid; + const struct drm_edid *drm_edid; int cur_x; int cur_y; bool needs_modeset; diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index b1a00c0c25a7..0d3d0d09f39b 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -741,21 +741,21 @@ static void virtio_gpu_cmd_get_edid_cb(struct virtio_gpu_device *vgdev, (struct virtio_gpu_resp_edid *)vbuf->resp_buf; uint32_t scanout = le32_to_cpu(cmd->scanout); struct virtio_gpu_output *output; - struct edid *new_edid, *old_edid; + const struct drm_edid *new_edid, *old_edid; if (scanout >= vgdev->num_scanouts) return; output = vgdev->outputs + scanout; - new_edid = drm_do_get_edid(&output->conn, virtio_get_edid_block, resp); - drm_connector_update_edid_property(&output->conn, new_edid); + new_edid = drm_edid_read_custom(&output->conn, virtio_get_edid_block, resp); + drm_edid_connector_update(&output->conn, new_edid); spin_lock(&vgdev->display_info_lock); - old_edid = output->edid; - output->edid = new_edid; + old_edid = output->drm_edid; + output->drm_edid = new_edid; spin_unlock(&vgdev->display_info_lock); - kfree(old_edid); + drm_edid_free(old_edid); wake_up(&vgdev->resp_wq); } diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index dd0af086e7fa..8dc9dc13896e 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -17,7 +17,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_shmem.h> #include <drm/drm_file.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_ioctl.h> @@ -223,7 +223,7 @@ static int vkms_create(struct vkms_config *config) if (ret) goto out_devres; - drm_fbdev_generic_setup(&vkms_device->drm, 0); + drm_fbdev_shmem_setup(&vkms_device->drm, 0); return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 823d8d2da17c..50ad3105c16e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -37,7 +37,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_ttm.h> #include <drm/drm_gem_ttm_helper.h> #include <drm/drm_ioctl.h> #include <drm/drm_module.h> @@ -1679,7 +1679,7 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent) vmw_fifo_resource_inc(vmw); vmw_svga_enable(vmw); - drm_fbdev_generic_setup(&vmw->drm, 0); + drm_fbdev_ttm_setup(&vmw->drm, 0); vmw_debugfs_gem_init(vmw); vmw_debugfs_resource_managers_init(vmw); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c index 7e93a45948f7..3bfcf671fcd5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c @@ -31,7 +31,6 @@ #include "vmwgfx_bo.h" #include "vmwgfx_drv.h" #include "vmwgfx_kms.h" -#include "vmwgfx_vkms.h" #include "vmw_surface_cache.h" diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 7039008be234..20dc9759bb3c 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -192,7 +192,8 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ display/xe_dsb_buffer.o \ display/xe_fb_pin.o \ display/xe_hdcp_gsc.o \ - display/xe_plane_initial.o + display/xe_plane_initial.o \ + display/xe_tdf.o # SOC code shared with i915 xe-$(CONFIG_DRM_XE_DISPLAY) += \ @@ -202,6 +203,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ # Display code shared with i915 xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/icl_dsi.o \ + i915-display/intel_alpm.o \ i915-display/intel_atomic.o \ i915-display/intel_atomic_plane.o \ i915-display/intel_audio.o \ @@ -244,6 +246,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_dsi.o \ i915-display/intel_dsi_dcs_backlight.o \ i915-display/intel_dsi_vbt.o \ + i915-display/intel_encoder.o \ i915-display/intel_fb.o \ i915-display/intel_fbc.o \ i915-display/intel_fdi.o \ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object_types.h b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object_types.h new file mode 100644 index 000000000000..7d6bb1abab73 --- /dev/null +++ b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object_types.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2024 Intel Corporation */ + +#ifndef __I915_GEM_OBJECT_TYPES_H__ +#define __I915_GEM_OBJECT_TYPES_H__ + +#include "xe_bo.h" + +#define to_intel_bo(x) gem_to_xe_bo((x)) + +#endif diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_gem_stolen.h b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h index cb6c7598824b..cb6c7598824b 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_gem_stolen.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_gt_types.h b/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h index c15806d6c4f7..c15806d6c4f7 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_gt_types.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h index cd4632276141..2feedddf1e40 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h @@ -12,22 +12,9 @@ #include <drm/drm_drv.h> -#include "gem/i915_gem_object.h" - -#include "soc/intel_pch.h" -#include "xe_device.h" -#include "xe_bo.h" -#include "xe_pm.h" -#include "xe_step.h" -#include "i915_gem_stolen.h" -#include "i915_gpu_error.h" -#include "i915_reg_defs.h" #include "i915_utils.h" -#include "intel_gt_types.h" -#include "intel_step.h" -#include "intel_uncore.h" #include "intel_runtime_pm.h" -#include <linux/pm_runtime.h> +#include "xe_device_types.h" static inline struct drm_i915_private *to_i915(const struct drm_device *dev) { @@ -119,67 +106,15 @@ static inline struct drm_i915_private *kdev_to_i915(struct device *kdev) #define IS_RAPTORLAKE_U(xe) ((xe)->info.subplatform == XE_SUBPLATFORM_ALDERLAKE_P_RPLU) #define IS_ICL_WITH_PORT_F(xe) (xe && 0) #define HAS_FLAT_CCS(xe) (xe_device_has_flat_ccs(xe)) -#define to_intel_bo(x) gem_to_xe_bo((x)) #define HAS_128_BYTE_Y_TILING(xe) (xe || 1) -#include "intel_wakeref.h" - -static inline intel_wakeref_t intel_runtime_pm_get(struct xe_runtime_pm *pm) -{ - struct xe_device *xe = container_of(pm, struct xe_device, runtime_pm); - - return xe_pm_runtime_resume_and_get(xe); -} - -static inline intel_wakeref_t intel_runtime_pm_get_if_in_use(struct xe_runtime_pm *pm) -{ - struct xe_device *xe = container_of(pm, struct xe_device, runtime_pm); - - return xe_pm_runtime_get_if_in_use(xe); -} - -static inline intel_wakeref_t intel_runtime_pm_get_noresume(struct xe_runtime_pm *pm) -{ - struct xe_device *xe = container_of(pm, struct xe_device, runtime_pm); - - xe_pm_runtime_get_noresume(xe); - return true; -} - -static inline void intel_runtime_pm_put_unchecked(struct xe_runtime_pm *pm) -{ - struct xe_device *xe = container_of(pm, struct xe_device, runtime_pm); - - xe_pm_runtime_put(xe); -} - -static inline void intel_runtime_pm_put(struct xe_runtime_pm *pm, intel_wakeref_t wakeref) -{ - if (wakeref) - intel_runtime_pm_put_unchecked(pm); -} - -#define intel_runtime_pm_get_raw intel_runtime_pm_get -#define intel_runtime_pm_put_raw intel_runtime_pm_put -#define assert_rpm_wakelock_held(x) do { } while (0) -#define assert_rpm_raw_wakeref_held(x) do { } while (0) - -#define intel_uncore_forcewake_get(x, y) do { } while (0) -#define intel_uncore_forcewake_put(x, y) do { } while (0) - -#define intel_uncore_arm_unclaimed_mmio_detection(x) do { } while (0) - #define I915_PRIORITY_DISPLAY 0 struct i915_sched_attr { int priority; }; #define i915_gem_fence_wait_priority(fence, attr) do { (void) attr; } while (0) -#define with_intel_runtime_pm(rpm, wf) \ - for ((wf) = intel_runtime_pm_get(rpm); (wf); \ - intel_runtime_pm_put((rpm), (wf)), (wf) = 0) - #define pdev_to_i915 pdev_to_xe_device #define RUNTIME_INFO(xe) (&(xe)->info.i915_runtime) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_runtime_pm.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_runtime_pm.h index 89da3cc62f39..8c7b315aa8ac 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_runtime_pm.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/intel_runtime_pm.h @@ -3,7 +3,12 @@ * Copyright © 2023 Intel Corporation */ +#ifndef __INTEL_RUNTIME_PM_H__ +#define __INTEL_RUNTIME_PM_H__ + #include "intel_wakeref.h" +#include "xe_device_types.h" +#include "xe_pm.h" #define intel_runtime_pm xe_runtime_pm @@ -14,3 +19,49 @@ static inline void disable_rpm_wakeref_asserts(void *rpm) static inline void enable_rpm_wakeref_asserts(void *rpm) { } + +static inline intel_wakeref_t intel_runtime_pm_get(struct xe_runtime_pm *pm) +{ + struct xe_device *xe = container_of(pm, struct xe_device, runtime_pm); + + return xe_pm_runtime_resume_and_get(xe); +} + +static inline intel_wakeref_t intel_runtime_pm_get_if_in_use(struct xe_runtime_pm *pm) +{ + struct xe_device *xe = container_of(pm, struct xe_device, runtime_pm); + + return xe_pm_runtime_get_if_in_use(xe); +} + +static inline intel_wakeref_t intel_runtime_pm_get_noresume(struct xe_runtime_pm *pm) +{ + struct xe_device *xe = container_of(pm, struct xe_device, runtime_pm); + + xe_pm_runtime_get_noresume(xe); + return true; +} + +static inline void intel_runtime_pm_put_unchecked(struct xe_runtime_pm *pm) +{ + struct xe_device *xe = container_of(pm, struct xe_device, runtime_pm); + + xe_pm_runtime_put(xe); +} + +static inline void intel_runtime_pm_put(struct xe_runtime_pm *pm, intel_wakeref_t wakeref) +{ + if (wakeref) + intel_runtime_pm_put_unchecked(pm); +} + +#define intel_runtime_pm_get_raw intel_runtime_pm_get +#define intel_runtime_pm_put_raw intel_runtime_pm_put +#define assert_rpm_wakelock_held(x) do { } while (0) +#define assert_rpm_raw_wakeref_held(x) do { } while (0) + +#define with_intel_runtime_pm(rpm, wf) \ + for ((wf) = intel_runtime_pm_get(rpm); (wf); \ + intel_runtime_pm_put((rpm), (wf)), (wf) = 0) + +#endif diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h index ef79793caa72..083c4da2ea41 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h @@ -172,4 +172,9 @@ static inline void __iomem *intel_uncore_regs(struct intel_uncore *uncore) #define raw_reg_write(base, reg, value) \ writel(value, base + i915_mmio_reg_offset(reg)) +#define intel_uncore_forcewake_get(x, y) do { } while (0) +#define intel_uncore_forcewake_put(x, y) do { } while (0) + +#define intel_uncore_arm_unclaimed_mmio_detection(x) do { } while (0) + #endif /* __INTEL_UNCORE_H__ */ diff --git a/drivers/gpu/drm/xe/display/ext/i915_irq.c b/drivers/gpu/drm/xe/display/ext/i915_irq.c index bee191a4a97d..eb40f1cb44f6 100644 --- a/drivers/gpu/drm/xe/display/ext/i915_irq.c +++ b/drivers/gpu/drm/xe/display/ext/i915_irq.c @@ -3,7 +3,6 @@ * Copyright © 2023 Intel Corporation */ -#include "i915_drv.h" #include "i915_irq.h" #include "i915_reg.h" #include "intel_uncore.h" diff --git a/drivers/gpu/drm/xe/display/intel_fb_bo.c b/drivers/gpu/drm/xe/display/intel_fb_bo.c index e18521acc516..f835492f73fb 100644 --- a/drivers/gpu/drm/xe/display/intel_fb_bo.c +++ b/drivers/gpu/drm/xe/display/intel_fb_bo.c @@ -4,10 +4,11 @@ */ #include <drm/drm_modeset_helper.h> +#include <drm/ttm/ttm_bo.h> -#include "i915_drv.h" #include "intel_display_types.h" #include "intel_fb_bo.h" +#include "xe_bo.h" void intel_fb_bo_framebuffer_fini(struct xe_bo *bo) { @@ -24,7 +25,7 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb, struct xe_bo *bo, struct drm_mode_fb_cmd2 *mode_cmd) { - struct drm_i915_private *i915 = to_i915(bo->ttm.base.dev); + struct xe_device *xe = to_xe_device(bo->ttm.base.dev); int ret; xe_bo_get(bo); @@ -40,7 +41,7 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb, * mode when the boect is VM_BINDed, so we can only set * coherency with display when unbound. */ - if (XE_IOCTL_DBG(i915, !list_empty(&bo->ttm.base.gpuva.list))) { + if (XE_IOCTL_DBG(xe, !list_empty(&bo->ttm.base.gpuva.list))) { ttm_bo_unreserve(&bo->ttm); ret = -EINVAL; goto err; diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c index 9e4bcfdbc7e5..816ad13821a8 100644 --- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c +++ b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c @@ -3,22 +3,20 @@ * Copyright © 2023 Intel Corporation */ -#include "intel_fbdev_fb.h" - #include <drm/drm_fb_helper.h> +#include "intel_display_types.h" +#include "intel_fbdev_fb.h" +#include "xe_bo.h" #include "xe_gt.h" #include "xe_ttm_stolen_mgr.h" -#include "i915_drv.h" -#include "intel_display_types.h" - -struct drm_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) +struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) { struct drm_framebuffer *fb; struct drm_device *dev = helper->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct xe_device *xe = to_xe_device(dev); struct drm_mode_fb_cmd2 mode_cmd = {}; struct drm_i915_gem_object *obj; int size; @@ -39,26 +37,26 @@ struct drm_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, size = PAGE_ALIGN(size); obj = ERR_PTR(-ENODEV); - if (!IS_DGFX(dev_priv)) { - obj = xe_bo_create_pin_map(dev_priv, xe_device_get_root_tile(dev_priv), + if (!IS_DGFX(xe)) { + obj = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), NULL, size, ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT | XE_BO_FLAG_STOLEN | XE_BO_FLAG_PINNED); if (!IS_ERR(obj)) - drm_info(&dev_priv->drm, "Allocated fbdev into stolen\n"); + drm_info(&xe->drm, "Allocated fbdev into stolen\n"); else - drm_info(&dev_priv->drm, "Allocated fbdev into stolen failed: %li\n", PTR_ERR(obj)); + drm_info(&xe->drm, "Allocated fbdev into stolen failed: %li\n", PTR_ERR(obj)); } if (IS_ERR(obj)) { - obj = xe_bo_create_pin_map(dev_priv, xe_device_get_root_tile(dev_priv), NULL, size, - ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT | - XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(dev_priv)) | - XE_BO_FLAG_PINNED); + obj = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), NULL, size, + ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT | + XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) | + XE_BO_FLAG_PINNED); } if (IS_ERR(obj)) { - drm_err(&dev_priv->drm, "failed to allocate framebuffer (%pe)\n", obj); + drm_err(&xe->drm, "failed to allocate framebuffer (%pe)\n", obj); fb = ERR_PTR(-ENOMEM); goto err; } @@ -70,10 +68,11 @@ struct drm_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, } drm_gem_object_put(intel_bo_to_drm_bo(obj)); - return fb; + + return to_intel_framebuffer(fb); err: - return fb; + return ERR_CAST(fb); } int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info, diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.h b/drivers/gpu/drm/xe/display/intel_fbdev_fb.h deleted file mode 100644 index ea186772e0bb..000000000000 --- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef __INTEL_FBDEV_FB_H__ -#define __INTEL_FBDEV_FB_H__ - -struct drm_fb_helper; -struct drm_fb_helper_surface_size; -struct drm_i915_gem_object; -struct drm_i915_private; -struct fb_info; -struct i915_vma; - -struct drm_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes); -int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info, - struct drm_i915_gem_object *obj, struct i915_vma *vma); - -#endif diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index ff8863979065..78cccbe28947 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -96,9 +96,6 @@ int xe_display_create(struct xe_device *xe) xe->display.hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); - drmm_mutex_init(&xe->drm, &xe->sb_lock); - xe->enabled_irq_mask = ~0; - return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); } diff --git a/drivers/gpu/drm/xe/display/xe_dsb_buffer.c b/drivers/gpu/drm/xe/display/xe_dsb_buffer.c index 44c9fd2143cc..9e860c61f4b3 100644 --- a/drivers/gpu/drm/xe/display/xe_dsb_buffer.c +++ b/drivers/gpu/drm/xe/display/xe_dsb_buffer.c @@ -3,7 +3,6 @@ * Copyright 2023, Intel Corporation. */ -#include "i915_drv.h" #include "i915_vma.h" #include "intel_display_types.h" #include "intel_dsb_buffer.h" @@ -34,18 +33,18 @@ void intel_dsb_buffer_memset(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val, bool intel_dsb_buffer_create(struct intel_crtc *crtc, struct intel_dsb_buffer *dsb_buf, size_t size) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); - struct drm_i915_gem_object *obj; + struct xe_device *xe = to_xe_device(crtc->base.dev); + struct xe_bo *obj; struct i915_vma *vma; vma = kzalloc(sizeof(*vma), GFP_KERNEL); if (!vma) return false; - obj = xe_bo_create_pin_map(i915, xe_device_get_root_tile(i915), + obj = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), NULL, PAGE_ALIGN(size), ttm_bo_type_kernel, - XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(i915)) | + XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) | XE_BO_FLAG_GGTT); if (IS_ERR(obj)) { kfree(vma); diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 3e1ae37c4c8b..a2f417209124 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -3,17 +3,17 @@ * Copyright © 2021 Intel Corporation */ -#include "i915_drv.h" +#include <drm/ttm/ttm_bo.h> + #include "intel_display_types.h" #include "intel_dpt.h" #include "intel_fb.h" #include "intel_fb_pin.h" +#include "xe_bo.h" #include "xe_ggtt.h" #include "xe_gt.h" #include "xe_pm.h" -#include <drm/ttm/ttm_bo.h> - static void write_dpt_rotated(struct xe_bo *bo, struct iosys_map *map, u32 *dpt_ofs, u32 bo_ofs, u32 width, u32 height, u32 src_stride, u32 dst_stride) @@ -77,7 +77,7 @@ write_dpt_remapped(struct xe_bo *bo, struct iosys_map *map, u32 *dpt_ofs, *dpt_ofs = ALIGN(*dpt_ofs, 4096); } -static int __xe_pin_fb_vma_dpt(struct intel_framebuffer *fb, +static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, const struct i915_gtt_view *view, struct i915_vma *vma) { @@ -181,7 +181,7 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo } } -static int __xe_pin_fb_vma_ggtt(struct intel_framebuffer *fb, +static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, const struct i915_gtt_view *view, struct i915_vma *vma) { @@ -249,7 +249,7 @@ out: return ret; } -static struct i915_vma *__xe_pin_fb_vma(struct intel_framebuffer *fb, +static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, const struct i915_gtt_view *view) { struct drm_device *dev = fb->base.dev; @@ -333,18 +333,18 @@ static void __xe_unpin_fb_vma(struct i915_vma *vma) } struct i915_vma * -intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, - bool phys_cursor, - const struct i915_gtt_view *view, - bool uses_fence, - unsigned long *out_flags) +intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, + bool phys_cursor, + const struct i915_gtt_view *view, + bool uses_fence, + unsigned long *out_flags) { *out_flags = 0; return __xe_pin_fb_vma(to_intel_framebuffer(fb), view); } -void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags) +void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags) { __xe_unpin_fb_vma(vma); } diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index eb67ecf08db2..14b8b4278317 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -4,7 +4,7 @@ */ #include <drm/drm_print.h> -#include <drm/i915_hdcp_interface.h> +#include <drm/intel/i915_hdcp_interface.h> #include <linux/delay.h> #include "abi/gsc_command_header_abi.h" diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c index 9693c56d386b..e135b20962d9 100644 --- a/drivers/gpu/drm/xe/display/xe_plane_initial.c +++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c @@ -9,7 +9,6 @@ #include "regs/xe_gtt_defs.h" #include "xe_ggtt.h" -#include "i915_drv.h" #include "intel_atomic_plane.h" #include "intel_crtc.h" #include "intel_display.h" @@ -18,16 +17,17 @@ #include "intel_fb_pin.h" #include "intel_frontbuffer.h" #include "intel_plane_initial.h" +#include "xe_bo.h" static bool intel_reuse_initial_plane_obj(struct intel_crtc *this, const struct intel_initial_plane_config plane_configs[], struct drm_framebuffer **fb) { - struct drm_i915_private *i915 = to_i915(this->base.dev); + struct xe_device *xe = to_xe_device(this->base.dev); struct intel_crtc *crtc; - for_each_intel_crtc(&i915->drm, crtc) { + for_each_intel_crtc(&xe->drm, crtc) { struct intel_plane *plane = to_intel_plane(crtc->base.primary); const struct intel_plane_state *plane_state = @@ -134,8 +134,7 @@ static bool intel_alloc_initial_plane_obj(struct intel_crtc *crtc, struct intel_initial_plane_config *plane_config) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct xe_device *xe = to_xe_device(crtc->base.dev); struct drm_mode_fb_cmd2 mode_cmd = { 0 }; struct drm_framebuffer *fb = &plane_config->fb->base; struct xe_bo *bo; @@ -147,9 +146,9 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, case I915_FORMAT_MOD_4_TILED: break; default: - drm_dbg(&dev_priv->drm, - "Unsupported modifier for initial FB: 0x%llx\n", - fb->modifier); + drm_dbg_kms(&xe->drm, + "Unsupported modifier for initial FB: 0x%llx\n", + fb->modifier); return false; } @@ -160,13 +159,13 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, mode_cmd.modifier[0] = fb->modifier; mode_cmd.flags = DRM_MODE_FB_MODIFIERS; - bo = initial_plane_bo(dev_priv, plane_config); + bo = initial_plane_bo(xe, plane_config); if (!bo) return false; if (intel_framebuffer_init(to_intel_framebuffer(fb), bo, &mode_cmd)) { - drm_dbg_kms(&dev_priv->drm, "intel fb init failed\n"); + drm_dbg_kms(&xe->drm, "intel fb init failed\n"); goto err_bo; } /* Reference handed over to fb */ @@ -211,8 +210,8 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc, intel_fb_fill_view(to_intel_framebuffer(fb), plane_state->uapi.rotation, &plane_state->view); - vma = intel_pin_and_fence_fb_obj(fb, false, &plane_state->view.gtt, - false, &plane_state->flags); + vma = intel_fb_pin_to_ggtt(fb, false, &plane_state->view.gtt, + false, &plane_state->flags); if (IS_ERR(vma)) goto nofb; diff --git a/drivers/gpu/drm/xe/display/xe_tdf.c b/drivers/gpu/drm/xe/display/xe_tdf.c new file mode 100644 index 000000000000..2c0d4e144e09 --- /dev/null +++ b/drivers/gpu/drm/xe/display/xe_tdf.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2024 Intel Corporation + */ + +#include "xe_device.h" +#include "intel_display_types.h" +#include "intel_tdf.h" + +void intel_td_flush(struct drm_i915_private *i915) +{ + xe_device_td_flush(i915); +} diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index 6a7bbb410613..d44564bad009 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -374,6 +374,9 @@ #define XE2LPM_L3SQCREG5 XE_REG_MCR(0xb658) +#define XE2_TDF_CTRL XE_REG(0xb418) +#define TRANSIENT_FLUSH_REQUEST REG_BIT(0) + #define XEHP_MERT_MOD_CTRL XE_REG_MCR(0xcf28) #define RENDER_MOD_CTRL XE_REG_MCR(0xcf2c) #define COMP_MOD_CTRL XE_REG_MCR(0xcf30) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index e25c37ac7d14..0d57eea8f083 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -754,6 +754,55 @@ void xe_device_wmb(struct xe_device *xe) xe_mmio_write32(gt, SOFTWARE_FLAGS_SPR33, 0); } +/** + * xe_device_td_flush() - Flush transient L3 cache entries + * @xe: The device + * + * Display engine has direct access to memory and is never coherent with L3/L4 + * caches (or CPU caches), however KMD is responsible for specifically flushing + * transient L3 GPU cache entries prior to the flip sequence to ensure scanout + * can happen from such a surface without seeing corruption. + * + * Display surfaces can be tagged as transient by mapping it using one of the + * various L3:XD PAT index modes on Xe2. + * + * Note: On non-discrete xe2 platforms, like LNL, the entire L3 cache is flushed + * at the end of each submission via PIPE_CONTROL for compute/render, since SA + * Media is not coherent with L3 and we want to support render-vs-media + * usescases. For other engines like copy/blt the HW internally forces uncached + * behaviour, hence why we can skip the TDF on such platforms. + */ +void xe_device_td_flush(struct xe_device *xe) +{ + struct xe_gt *gt; + u8 id; + + if (!IS_DGFX(xe) || GRAPHICS_VER(xe) < 20) + return; + + for_each_gt(gt, xe, id) { + if (xe_gt_is_media_type(gt)) + continue; + + if (xe_force_wake_get(gt_to_fw(gt), XE_FW_GT)) + return; + + xe_mmio_write32(gt, XE2_TDF_CTRL, TRANSIENT_FLUSH_REQUEST); + /* + * FIXME: We can likely do better here with our choice of + * timeout. Currently we just assume the worst case, i.e. 150us, + * which is believed to be sufficient to cover the worst case + * scenario on current platforms if all cache entries are + * transient and need to be flushed.. + */ + if (xe_mmio_wait32(gt, XE2_TDF_CTRL, TRANSIENT_FLUSH_REQUEST, 0, + 150, NULL, false)) + xe_gt_err_once(gt, "TD flush timeout\n"); + + xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); + } +} + u32 xe_device_ccs_bytes(struct xe_device *xe, u64 size) { return xe_device_has_flat_ccs(xe) ? diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h index 3ed14072d8d1..bb07f5669dbb 100644 --- a/drivers/gpu/drm/xe/xe_device.h +++ b/drivers/gpu/drm/xe/xe_device.h @@ -161,6 +161,8 @@ void xe_device_snapshot_print(struct xe_device *xe, struct drm_printer *p); u64 xe_device_canonicalize_addr(struct xe_device *xe, u64 address); u64 xe_device_uncanonicalize_addr(struct xe_device *xe, u64 address); +void xe_device_td_flush(struct xe_device *xe); + static inline bool xe_device_wedged(struct xe_device *xe) { return atomic_read(&xe->wedged.flag); diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 185986e1d586..c37be471d11c 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -502,6 +502,7 @@ struct xe_device { INTEL_DRAM_LPDDR4, INTEL_DRAM_DDR5, INTEL_DRAM_LPDDR5, + INTEL_DRAM_GDDR, } type; u8 num_qgv_points; u8 num_psf_gv_points; @@ -516,14 +517,9 @@ struct xe_device { /* To shut up runtime pm macros.. */ struct xe_runtime_pm {} runtime_pm; - /* For pcode */ - struct mutex sb_lock; - /* only to allow build, not used functionally */ u32 irq_mask; - u32 enabled_irq_mask; - struct intel_uncore { spinlock_t lock; } uncore; diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index b01a670fecb8..8ff91fd1b7c8 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -10,7 +10,7 @@ #include <drm/drm_drv.h> #include <drm/drm_managed.h> -#include <drm/i915_drm.h> +#include <drm/intel/i915_drm.h> #include "regs/xe_gt_regs.h" #include "regs/xe_gtt_defs.h" diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.c b/drivers/gpu/drm/xe/xe_gsc_proxy.c index 6d6d1068cf23..aa812a2bc3ed 100644 --- a/drivers/gpu/drm/xe/xe_gsc_proxy.c +++ b/drivers/gpu/drm/xe/xe_gsc_proxy.c @@ -9,8 +9,8 @@ #include <linux/delay.h> #include <drm/drm_managed.h> -#include <drm/i915_component.h> -#include <drm/i915_gsc_proxy_mei_interface.h> +#include <drm/intel/i915_component.h> +#include <drm/intel/i915_gsc_proxy_mei_interface.h> #include "abi/gsc_proxy_commands_abi.h" #include "regs/xe_gsc_regs.h" diff --git a/drivers/gpu/drm/xe/xe_gt_printk.h b/drivers/gpu/drm/xe/xe_gt_printk.h index c2b004d3f48e..d6228baaff1e 100644 --- a/drivers/gpu/drm/xe/xe_gt_printk.h +++ b/drivers/gpu/drm/xe/xe_gt_printk.h @@ -13,6 +13,9 @@ #define xe_gt_printk(_gt, _level, _fmt, ...) \ drm_##_level(>_to_xe(_gt)->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) +#define xe_gt_err_once(_gt, _fmt, ...) \ + xe_gt_printk((_gt), err_once, _fmt, ##__VA_ARGS__) + #define xe_gt_err(_gt, _fmt, ...) \ xe_gt_printk((_gt), err, _fmt, ##__VA_ARGS__) diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 08583fdd7643..21a1b7d2b2a9 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -13,7 +13,7 @@ #include <drm/drm_color_mgmt.h> #include <drm/drm_drv.h> -#include <drm/xe_pciids.h> +#include <drm/intel/xe_pciids.h> #include "display/xe_display.h" #include "regs/xe_gt_regs.h" @@ -343,6 +343,7 @@ static const struct xe_device_desc lnl_desc = { static const struct xe_device_desc bmg_desc = { DGFX_FEATURES, PLATFORM(BATTLEMAGE), + .has_display = true, .require_force_probe = true, }; diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c index c9fb432d4cbd..9368acf56eaf 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c @@ -141,24 +141,18 @@ struct zynqmp_disp_layer { * struct zynqmp_disp - Display controller * @dev: Device structure * @dpsub: Display subsystem - * @blend.base: Register I/O base address for the blender - * @avbuf.base: Register I/O base address for the audio/video buffer manager - * @audio.base: Registers I/O base address for the audio mixer + * @blend: Register I/O base address for the blender + * @avbuf: Register I/O base address for the audio/video buffer manager + * @audio: Registers I/O base address for the audio mixer * @layers: Layers (planes) */ struct zynqmp_disp { struct device *dev; struct zynqmp_dpsub *dpsub; - struct { - void __iomem *base; - } blend; - struct { - void __iomem *base; - } avbuf; - struct { - void __iomem *base; - } audio; + void __iomem *blend; + void __iomem *avbuf; + void __iomem *audio; struct zynqmp_disp_layer layers[ZYNQMP_DPSUB_NUM_LAYERS]; }; @@ -410,12 +404,12 @@ static const struct zynqmp_disp_format avbuf_live_fmts[] = { static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp *disp, int reg) { - return readl(disp->avbuf.base + reg); + return readl(disp->avbuf + reg); } static void zynqmp_disp_avbuf_write(struct zynqmp_disp *disp, int reg, u32 val) { - writel(val, disp->avbuf.base + reg); + writel(val, disp->avbuf + reg); } static bool zynqmp_disp_layer_is_video(const struct zynqmp_disp_layer *layer) @@ -651,7 +645,7 @@ static void zynqmp_disp_avbuf_disable(struct zynqmp_disp *disp) static void zynqmp_disp_blend_write(struct zynqmp_disp *disp, int reg, u32 val) { - writel(val, disp->blend.base + reg); + writel(val, disp->blend + reg); } /* @@ -877,7 +871,7 @@ static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp *disp, static void zynqmp_disp_audio_write(struct zynqmp_disp *disp, int reg, u32 val) { - writel(val, disp->audio.base + reg); + writel(val, disp->audio + reg); } /** @@ -1412,21 +1406,21 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub) disp->dev = &pdev->dev; disp->dpsub = dpsub; - disp->blend.base = devm_platform_ioremap_resource_byname(pdev, "blend"); - if (IS_ERR(disp->blend.base)) { - ret = PTR_ERR(disp->blend.base); + disp->blend = devm_platform_ioremap_resource_byname(pdev, "blend"); + if (IS_ERR(disp->blend)) { + ret = PTR_ERR(disp->blend); goto error; } - disp->avbuf.base = devm_platform_ioremap_resource_byname(pdev, "av_buf"); - if (IS_ERR(disp->avbuf.base)) { - ret = PTR_ERR(disp->avbuf.base); + disp->avbuf = devm_platform_ioremap_resource_byname(pdev, "av_buf"); + if (IS_ERR(disp->avbuf)) { + ret = PTR_ERR(disp->avbuf); goto error; } - disp->audio.base = devm_platform_ioremap_resource_byname(pdev, "aud"); - if (IS_ERR(disp->audio.base)) { - ret = PTR_ERR(disp->audio.base); + disp->audio = devm_platform_ioremap_resource_byname(pdev, "aud"); + if (IS_ERR(disp->audio)) { + ret = PTR_ERR(disp->audio); goto error; } diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c index 8c2d24809014..129beac4c073 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c @@ -256,10 +256,10 @@ struct zynqmp_dp_link_config { * @fmt: format identifier string */ struct zynqmp_dp_mode { + const char *fmt; + int pclock; u8 bw_code; u8 lane_cnt; - int pclock; - const char *fmt; }; /** @@ -296,27 +296,27 @@ struct zynqmp_dp_config { * @train_set: set of training data */ struct zynqmp_dp { + struct drm_dp_aux aux; + struct drm_bridge bridge; + struct work_struct hpd_work; + + struct drm_bridge *next_bridge; struct device *dev; struct zynqmp_dpsub *dpsub; void __iomem *iomem; struct reset_control *reset; - int irq; - - struct drm_bridge bridge; - struct drm_bridge *next_bridge; - - struct zynqmp_dp_config config; - struct drm_dp_aux aux; struct phy *phy[ZYNQMP_DP_MAX_LANES]; - u8 num_lanes; - struct delayed_work hpd_work; + enum drm_connector_status status; + int irq; bool enabled; - u8 dpcd[DP_RECEIVER_CAP_SIZE]; - struct zynqmp_dp_link_config link_config; struct zynqmp_dp_mode mode; + struct zynqmp_dp_link_config link_config; + struct zynqmp_dp_config config; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; u8 train_set[ZYNQMP_DP_MAX_LANES]; + u8 num_lanes; }; static inline struct zynqmp_dp *bridge_to_dp(struct drm_bridge *bridge) @@ -606,28 +606,21 @@ static void zynqmp_dp_adjust_train(struct zynqmp_dp *dp, u8 link_status[DP_LINK_STATUS_SIZE]) { u8 *train_set = dp->train_set; - u8 voltage = 0, preemphasis = 0; u8 i; for (i = 0; i < dp->mode.lane_cnt; i++) { - u8 v = drm_dp_get_adjust_request_voltage(link_status, i); - u8 p = drm_dp_get_adjust_request_pre_emphasis(link_status, i); + u8 voltage = drm_dp_get_adjust_request_voltage(link_status, i); + u8 preemphasis = + drm_dp_get_adjust_request_pre_emphasis(link_status, i); - if (v > voltage) - voltage = v; + if (voltage >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3) + voltage |= DP_TRAIN_MAX_SWING_REACHED; - if (p > preemphasis) - preemphasis = p; - } + if (preemphasis >= DP_TRAIN_PRE_EMPH_LEVEL_2) + preemphasis |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; - if (voltage >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3) - voltage |= DP_TRAIN_MAX_SWING_REACHED; - - if (preemphasis >= DP_TRAIN_PRE_EMPH_LEVEL_2) - preemphasis |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; - - for (i = 0; i < dp->mode.lane_cnt; i++) train_set[i] = voltage | preemphasis; + } } /** @@ -1007,7 +1000,7 @@ zynqmp_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) msg->buffer, msg->size, &msg->reply); if (!ret) { - dev_dbg(dp->dev, "aux %d retries\n", i); + dev_vdbg(dp->dev, "aux %d retries\n", i); return msg->size; } @@ -1489,7 +1482,7 @@ static void zynqmp_dp_bridge_atomic_disable(struct drm_bridge *bridge, struct zynqmp_dp *dp = bridge_to_dp(bridge); dp->enabled = false; - cancel_delayed_work(&dp->hpd_work); + cancel_work(&dp->hpd_work); zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_ENABLE, 0); drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3); zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN, @@ -1655,8 +1648,7 @@ void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp) static void zynqmp_dp_hpd_work_func(struct work_struct *work) { - struct zynqmp_dp *dp = container_of(work, struct zynqmp_dp, - hpd_work.work); + struct zynqmp_dp *dp = container_of(work, struct zynqmp_dp, hpd_work); enum drm_connector_status status; status = zynqmp_dp_bridge_detect(&dp->bridge); @@ -1692,7 +1684,7 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data) zynqmp_dpsub_drm_handle_vblank(dp->dpsub); if (status & ZYNQMP_DP_INT_HPD_EVENT) - schedule_delayed_work(&dp->hpd_work, 0); + schedule_work(&dp->hpd_work); if (status & ZYNQMP_DP_INT_HPD_IRQ) { int ret; @@ -1734,7 +1726,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub) dp->dpsub = dpsub; dp->status = connector_status_disconnected; - INIT_DELAYED_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func); + INIT_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func); /* Acquire all resources (IOMEM, IRQ and PHYs). */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp"); @@ -1839,7 +1831,7 @@ void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub) zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, ZYNQMP_DP_INT_ALL); disable_irq(dp->irq); - cancel_delayed_work_sync(&dp->hpd_work); + cancel_work_sync(&dp->hpd_work); zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, 0); zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, 0xffffffff); diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c index face8d6b2a6f..f5781939de9c 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c @@ -269,6 +269,7 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev) return 0; err_disp: + drm_bridge_remove(dpsub->bridge); zynqmp_disp_remove(dpsub); err_dp: zynqmp_dp_remove(dpsub); diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h index 09ea01878f2a..b18554467e9c 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h @@ -53,6 +53,7 @@ enum zynqmp_dpsub_format { * @drm: The DRM/KMS device data * @bridge: The DP encoder bridge * @disp: The display controller + * @layers: Video and graphics layers * @dp: The DisplayPort controller * @dma_align: DMA alignment constraint (must be a power of 2) */ diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c b/drivers/gpu/drm/xlnx/zynqmp_kms.c index 43bf416b33d5..bd1368df7870 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_kms.c +++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c @@ -120,9 +120,13 @@ static void zynqmp_dpsub_plane_atomic_update(struct drm_plane *plane, zynqmp_disp_blend_set_global_alpha(dpsub->disp, true, plane->state->alpha >> 8); - /* Enable or re-enable the plane if the format has changed. */ - if (format_changed) - zynqmp_disp_layer_enable(layer); + /* + * Unconditionally enable the layer, as it may have been disabled + * previously either explicitly to reconfigure layer format, or + * implicitly after DPSUB reset during display mode change. DRM + * framework calls this callback for enabled planes only. + */ + zynqmp_disp_layer_enable(layer); } static const struct drm_plane_helper_funcs zynqmp_dpsub_plane_helper_funcs = { @@ -433,23 +437,28 @@ static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub) DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (ret) { dev_err(dpsub->dev, "failed to attach bridge to encoder\n"); - return ret; + goto err_encoder; } /* Create the connector for the chain of bridges. */ connector = drm_bridge_connector_init(&dpsub->drm->dev, encoder); if (IS_ERR(connector)) { dev_err(dpsub->dev, "failed to created connector\n"); - return PTR_ERR(connector); + ret = PTR_ERR(connector); + goto err_encoder; } ret = drm_connector_attach_encoder(connector, encoder); if (ret < 0) { dev_err(dpsub->dev, "failed to attach connector to encoder\n"); - return ret; + goto err_encoder; } return 0; + +err_encoder: + drm_encoder_cleanup(encoder); + return ret; } static void zynqmp_dpsub_drm_release(struct drm_device *drm, void *res) @@ -529,5 +538,6 @@ void zynqmp_dpsub_drm_cleanup(struct zynqmp_dpsub *dpsub) drm_dev_unregister(drm); drm_atomic_helper_shutdown(drm); + drm_encoder_cleanup(&dpsub->drm->encoder); drm_kms_helper_poll_fini(drm); } diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.h b/drivers/gpu/drm/xlnx/zynqmp_kms.h index 01be96b00e3f..cb13c6b8008e 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_kms.h +++ b/drivers/gpu/drm/xlnx/zynqmp_kms.h @@ -22,9 +22,9 @@ struct zynqmp_dpsub; /** - * struct zynqmp_dpsub - ZynqMP DisplayPort Subsystem DRM/KMS data + * struct zynqmp_dpsub_drm - ZynqMP DisplayPort Subsystem DRM/KMS data * @dpsub: Backpointer to the DisplayPort subsystem - * @drm: The DRM/KMS device + * @dev: The DRM/KMS device * @planes: The DRM planes * @crtc: The DRM CRTC * @encoder: The dummy DRM encoder diff --git a/drivers/misc/mei/gsc_proxy/mei_gsc_proxy.c b/drivers/misc/mei/gsc_proxy/mei_gsc_proxy.c index 89364bdbb129..f52fe23a6c0b 100644 --- a/drivers/misc/mei/gsc_proxy/mei_gsc_proxy.c +++ b/drivers/misc/mei/gsc_proxy/mei_gsc_proxy.c @@ -17,8 +17,8 @@ #include <linux/slab.h> #include <linux/uuid.h> #include <drm/drm_connector.h> -#include <drm/i915_component.h> -#include <drm/i915_gsc_proxy_mei_interface.h> +#include <drm/intel/i915_component.h> +#include <drm/intel/i915_gsc_proxy_mei_interface.h> /** * mei_gsc_proxy_send - Sends a proxy message to ME FW. diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c index f8759a6c9ed3..323f10620d90 100644 --- a/drivers/misc/mei/hdcp/mei_hdcp.c +++ b/drivers/misc/mei/hdcp/mei_hdcp.c @@ -23,8 +23,8 @@ #include <linux/mei_cl_bus.h> #include <linux/component.h> #include <drm/drm_connector.h> -#include <drm/i915_component.h> -#include <drm/i915_hdcp_interface.h> +#include <drm/intel/i915_component.h> +#include <drm/intel/i915_hdcp_interface.h> #include "mei_hdcp.h" diff --git a/drivers/misc/mei/pxp/mei_pxp.c b/drivers/misc/mei/pxp/mei_pxp.c index 49abc95677cd..2820d389c88e 100644 --- a/drivers/misc/mei/pxp/mei_pxp.c +++ b/drivers/misc/mei/pxp/mei_pxp.c @@ -19,8 +19,8 @@ #include <linux/mei_cl_bus.h> #include <linux/component.h> #include <drm/drm_connector.h> -#include <drm/i915_component.h> -#include <drm/i915_pxp_tee_interface.h> +#include <drm/intel/i915_component.h> +#include <drm/intel/i915_pxp_tee_interface.h> #include "mei_pxp.h" diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 73ec4460a151..523fb18a7ace 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -59,7 +59,7 @@ #include <linux/tick.h> #include <linux/timer.h> #include <linux/dmi.h> -#include <drm/i915_drm.h> +#include <drm/intel/i915_drm.h> #include <asm/msr.h> #include <asm/processor.h> #include "intel_ips.h" diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c index 806ecd32219b..5ee7e78c2cea 100644 --- a/drivers/video/fbdev/core/fb_defio.c +++ b/drivers/video/fbdev/core/fb_defio.c @@ -23,33 +23,71 @@ #include <linux/rmap.h> #include <linux/pagemap.h> -static struct page *fb_deferred_io_page(struct fb_info *info, unsigned long offs) +static struct page *fb_deferred_io_get_page(struct fb_info *info, unsigned long offs) { - void *screen_base = (void __force *) info->screen_base; - struct page *page; + struct fb_deferred_io *fbdefio = info->fbdefio; + const void *screen_buffer = info->screen_buffer; + struct page *page = NULL; - if (is_vmalloc_addr(screen_base + offs)) - page = vmalloc_to_page(screen_base + offs); - else + if (fbdefio->get_page) + return fbdefio->get_page(info, offs); + + if (is_vmalloc_addr(screen_buffer + offs)) + page = vmalloc_to_page(screen_buffer + offs); + else if (info->fix.smem_start) page = pfn_to_page((info->fix.smem_start + offs) >> PAGE_SHIFT); + if (page) + get_page(page); + return page; } +static struct fb_deferred_io_pageref *fb_deferred_io_pageref_lookup(struct fb_info *info, + unsigned long offset, + struct page *page) +{ + unsigned long pgoff = offset >> PAGE_SHIFT; + struct fb_deferred_io_pageref *pageref; + + if (fb_WARN_ON_ONCE(info, pgoff >= info->npagerefs)) + return NULL; /* incorrect allocation size */ + + /* 1:1 mapping between pageref and page offset */ + pageref = &info->pagerefs[pgoff]; + + if (pageref->page) + goto out; + + pageref->page = page; + pageref->offset = pgoff << PAGE_SHIFT; + INIT_LIST_HEAD(&pageref->list); + +out: + if (fb_WARN_ON_ONCE(info, pageref->page != page)) + return NULL; /* inconsistent state */ + return pageref; +} + +static void fb_deferred_io_pageref_clear(struct fb_deferred_io_pageref *pageref) +{ + struct page *page = pageref->page; + + if (page) + page->mapping = NULL; +} + static struct fb_deferred_io_pageref *fb_deferred_io_pageref_get(struct fb_info *info, unsigned long offset, struct page *page) { struct fb_deferred_io *fbdefio = info->fbdefio; struct list_head *pos = &fbdefio->pagereflist; - unsigned long pgoff = offset >> PAGE_SHIFT; struct fb_deferred_io_pageref *pageref, *cur; - if (WARN_ON_ONCE(pgoff >= info->npagerefs)) - return NULL; /* incorrect allocation size */ - - /* 1:1 mapping between pageref and page offset */ - pageref = &info->pagerefs[pgoff]; + pageref = fb_deferred_io_pageref_lookup(info, offset, page); + if (!pageref) + return NULL; /* * This check is to catch the case where a new process could start @@ -60,9 +98,6 @@ static struct fb_deferred_io_pageref *fb_deferred_io_pageref_get(struct fb_info if (!list_empty(&pageref->list)) goto pageref_already_added; - pageref->page = page; - pageref->offset = pgoff << PAGE_SHIFT; - if (unlikely(fbdefio->sort_pagereflist)) { /* * We loop through the list of pagerefs before adding in @@ -101,12 +136,10 @@ static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf) if (offset >= info->fix.smem_len) return VM_FAULT_SIGBUS; - page = fb_deferred_io_page(info, offset); + page = fb_deferred_io_get_page(info, offset); if (!page) return VM_FAULT_SIGBUS; - get_page(page); - if (vmf->vma->vm_file) page->mapping = vmf->vma->vm_file->f_mapping; else @@ -264,7 +297,7 @@ int fb_deferred_io_init(struct fb_info *info) { struct fb_deferred_io *fbdefio = info->fbdefio; struct fb_deferred_io_pageref *pagerefs; - unsigned long npagerefs, i; + unsigned long npagerefs; int ret; BUG_ON(!fbdefio); @@ -286,8 +319,6 @@ int fb_deferred_io_init(struct fb_info *info) ret = -ENOMEM; goto err; } - for (i = 0; i < npagerefs; ++i) - INIT_LIST_HEAD(&pagerefs[i].list); info->npagerefs = npagerefs; info->pagerefs = pagerefs; @@ -312,16 +343,13 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_open); static void fb_deferred_io_lastclose(struct fb_info *info) { - struct page *page; - int i; + unsigned long i; flush_delayed_work(&info->deferred_work); /* clear out the mapping that we setup */ - for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { - page = fb_deferred_io_page(info, i); - page->mapping = NULL; - } + for (i = 0; i < info->npagerefs; ++i) + fb_deferred_io_pageref_clear(&info->pagerefs[i]); } void fb_deferred_io_release(struct fb_info *info) |