summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2021-10-28 15:01:25 +1000
committerDave Airlie <airlied@redhat.com>2021-10-28 15:07:48 +1000
commitde99e6479885dfa3f64a9511a6477c2b7899e53f (patch)
tree1d7f602b8b4cc6072789247991a569f68b71354a /drivers/gpu/drm
parent970eae15600a883e4ad27dd0757b18871cc983ab (diff)
parent02d44fde976a8e9330f855fc535180727c779b9b (diff)
downloadlinux-de99e6479885dfa3f64a9511a6477c2b7899e53f.tar.gz
linux-de99e6479885dfa3f64a9511a6477c2b7899e53f.tar.bz2
linux-de99e6479885dfa3f64a9511a6477c2b7899e53f.zip
Merge tag 'drm-msm-next-2021-10-26' of https://gitlab.freedesktop.org/drm/msm into drm-next
* eDP support in DP sub-driver (for newer SoCs with native eDP output) * dpu irq handling cleanup * CRC support for making igt happy * Support for NO_CONNECTOR bridges * dsi: 14nm phy support for msm8953 * mdp5: support for msm8x53, sdm450, sdm632 * various smaller fixes and cleanups Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rob Clark <robdclark@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGsH9EwcpqGNNRJeL99NvFFjHX3SUg+nTYu0dHG5U9+QuA@mail.gmail.com
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c1
-rw-r--r--drivers/gpu/drm/msm/Kconfig2
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_debugfs.c6
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c10
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c256
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c147
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h19
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c39
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c267
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h92
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c56
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h13
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c70
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h13
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c4
-rw-r--r--drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c18
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c89
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c18
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c12
-rw-r--r--drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c8
-rw-r--r--drivers/gpu/drm/msm/dp/dp_catalog.c64
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.c294
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.h4
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c143
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.h2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_drm.c13
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.c2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_parser.c138
-rw-r--r--drivers/gpu/drm/msm/dp/dp_parser.h14
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h2
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c147
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c66
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.h1
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c25
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c4
-rw-r--r--drivers/gpu/drm/msm/edp/edp_ctrl.c5
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c38
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h6
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_bridge.c20
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_connector.c24
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy.c33
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c4
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c21
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c33
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h31
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c6
-rw-r--r--drivers/gpu/drm/msm/msm_gem_shrinker.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h7
-rw-r--r--drivers/gpu/drm/msm/msm_gpu_devfreq.c38
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h3
-rw-r--r--drivers/gpu/drm/msm/msm_submitqueue.c1
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/ttm_memory.c1
63 files changed, 1214 insertions, 1162 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index cc5b07f86346..242a5fd8b932 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -1733,7 +1733,6 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
DBG("%s", dev_name(gpu->dev));
- flush_workqueue(gpu->wq);
destroy_workqueue(gpu->wq);
etnaviv_sched_fini(gpu);
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index f5107b6ded7b..ae11061727ff 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -14,6 +14,8 @@ config DRM_MSM
select REGULATOR
select DRM_KMS_HELPER
select DRM_PANEL
+ select DRM_BRIDGE
+ select DRM_PANEL_BRIDGE
select DRM_SCHED
select SHMEM
select TMPFS
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 904535eda0c4..40577f8856d8 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -51,7 +51,6 @@ msm-y := \
disp/mdp5/mdp5_mixer.o \
disp/mdp5/mdp5_plane.o \
disp/mdp5/mdp5_smp.o \
- disp/dpu1/dpu_core_irq.o \
disp/dpu1/dpu_core_perf.o \
disp/dpu1/dpu_crtc.o \
disp/dpu1/dpu_encoder.o \
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
index c9d11d57aed6..dd593ec2bc56 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
@@ -138,7 +138,7 @@ reset_set(void *data, u64 val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(reset_fops, NULL, reset_set, "%llx\n");
+DEFINE_DEBUGFS_ATTRIBUTE(reset_fops, NULL, reset_set, "%llx\n");
void a5xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor)
@@ -154,6 +154,6 @@ void a5xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor)
ARRAY_SIZE(a5xx_debugfs_list),
minor->debugfs_root, minor);
- debugfs_create_file("reset", S_IWUGO, minor->debugfs_root, dev,
- &reset_fops);
+ debugfs_create_file_unsafe("reset", S_IWUGO, minor->debugfs_root, dev,
+ &reset_fops);
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 8b73f70766a4..71e52b2b2025 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -516,11 +516,11 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct platform_device *pdev = to_platform_device(gmu->dev);
void __iomem *pdcptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc");
- void __iomem *seqptr;
+ void __iomem *seqptr = NULL;
uint32_t pdc_address_offset;
bool pdc_in_aop = false;
- if (!pdcptr)
+ if (IS_ERR(pdcptr))
goto err;
if (adreno_is_a650(adreno_gpu) || adreno_is_a660_family(adreno_gpu))
@@ -532,7 +532,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
if (!pdc_in_aop) {
seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq");
- if (!seqptr)
+ if (IS_ERR(seqptr))
goto err;
}
@@ -891,7 +891,7 @@ static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
unsigned long gpu_freq = gmu->gpu_freqs[gmu->current_perf_index];
gpu_opp = dev_pm_opp_find_freq_exact(&gpu->pdev->dev, gpu_freq, true);
- if (IS_ERR_OR_NULL(gpu_opp))
+ if (IS_ERR(gpu_opp))
return;
gmu->freq = 0; /* so a6xx_gmu_set_freq() doesn't exit early */
@@ -905,7 +905,7 @@ static void a6xx_gmu_set_initial_bw(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
unsigned long gpu_freq = gmu->gpu_freqs[gmu->current_perf_index];
gpu_opp = dev_pm_opp_find_freq_exact(&gpu->pdev->dev, gpu_freq, true);
- if (IS_ERR_OR_NULL(gpu_opp))
+ if (IS_ERR(gpu_opp))
return;
dev_pm_opp_set_opp(&gpu->pdev->dev, gpu_opp);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
index e8f65cd8eca6..7501849ed15d 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -180,7 +180,7 @@ static int debugbus_read(struct msm_gpu *gpu, u32 block, u32 offset,
msm_readl((ptr) + ((offset) << 2))
/* read a value from the CX debug bus */
-static int cx_debugbus_read(void *__iomem cxdbg, u32 block, u32 offset,
+static int cx_debugbus_read(void __iomem *cxdbg, u32 block, u32 offset,
u32 *data)
{
u32 reg = A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX(offset) |
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
deleted file mode 100644
index d2457490930b..000000000000
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
+++ /dev/null
@@ -1,256 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
- */
-
-#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
-
-#include <linux/debugfs.h>
-#include <linux/irqdomain.h>
-#include <linux/irq.h>
-#include <linux/kthread.h>
-
-#include "dpu_core_irq.h"
-#include "dpu_trace.h"
-
-/**
- * dpu_core_irq_callback_handler - dispatch core interrupts
- * @arg: private data of callback handler
- * @irq_idx: interrupt index
- */
-static void dpu_core_irq_callback_handler(void *arg, int irq_idx)
-{
- struct dpu_kms *dpu_kms = arg;
- struct dpu_irq *irq_obj = &dpu_kms->irq_obj;
- struct dpu_irq_callback *cb;
-
- VERB("irq_idx=%d\n", irq_idx);
-
- if (list_empty(&irq_obj->irq_cb_tbl[irq_idx]))
- DRM_ERROR("no registered cb, idx:%d\n", irq_idx);
-
- atomic_inc(&irq_obj->irq_counts[irq_idx]);
-
- /*
- * Perform registered function callback
- */
- list_for_each_entry(cb, &irq_obj->irq_cb_tbl[irq_idx], list)
- if (cb->func)
- cb->func(cb->arg, irq_idx);
-}
-
-u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx, bool clear)
-{
- if (!dpu_kms->hw_intr ||
- !dpu_kms->hw_intr->ops.get_interrupt_status)
- return 0;
-
- if (irq_idx < 0) {
- DPU_ERROR("[%pS] invalid irq_idx=%d\n",
- __builtin_return_address(0), irq_idx);
- return 0;
- }
-
- return dpu_kms->hw_intr->ops.get_interrupt_status(dpu_kms->hw_intr,
- irq_idx, clear);
-}
-
-int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx,
- struct dpu_irq_callback *register_irq_cb)
-{
- unsigned long irq_flags;
-
- if (!dpu_kms->irq_obj.irq_cb_tbl) {
- DPU_ERROR("invalid params\n");
- return -EINVAL;
- }
-
- if (!register_irq_cb || !register_irq_cb->func) {
- DPU_ERROR("invalid irq_cb:%d func:%d\n",
- register_irq_cb != NULL,
- register_irq_cb ?
- register_irq_cb->func != NULL : -1);
- return -EINVAL;
- }
-
- if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
- DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
- return -EINVAL;
- }
-
- VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);
-
- irq_flags = dpu_kms->hw_intr->ops.lock(dpu_kms->hw_intr);
- trace_dpu_core_irq_register_callback(irq_idx, register_irq_cb);
- list_del_init(&register_irq_cb->list);
- list_add_tail(&register_irq_cb->list,
- &dpu_kms->irq_obj.irq_cb_tbl[irq_idx]);
- if (list_is_first(&register_irq_cb->list,
- &dpu_kms->irq_obj.irq_cb_tbl[irq_idx])) {
- int ret = dpu_kms->hw_intr->ops.enable_irq_locked(
- dpu_kms->hw_intr,
- irq_idx);
- if (ret)
- DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n",
- irq_idx);
- }
- dpu_kms->hw_intr->ops.unlock(dpu_kms->hw_intr, irq_flags);
-
- return 0;
-}
-
-int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx,
- struct dpu_irq_callback *register_irq_cb)
-{
- unsigned long irq_flags;
-
- if (!dpu_kms->irq_obj.irq_cb_tbl) {
- DPU_ERROR("invalid params\n");
- return -EINVAL;
- }
-
- if (!register_irq_cb || !register_irq_cb->func) {
- DPU_ERROR("invalid irq_cb:%d func:%d\n",
- register_irq_cb != NULL,
- register_irq_cb ?
- register_irq_cb->func != NULL : -1);
- return -EINVAL;
- }
-
- if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
- DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
- return -EINVAL;
- }
-
- VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);
-
- irq_flags = dpu_kms->hw_intr->ops.lock(dpu_kms->hw_intr);
- trace_dpu_core_irq_unregister_callback(irq_idx, register_irq_cb);
- list_del_init(&register_irq_cb->list);
- /* empty callback list but interrupt is still enabled */
- if (list_empty(&dpu_kms->irq_obj.irq_cb_tbl[irq_idx])) {
- int ret = dpu_kms->hw_intr->ops.disable_irq_locked(
- dpu_kms->hw_intr,
- irq_idx);
- if (ret)
- DPU_ERROR("Fail to disable IRQ for irq_idx:%d\n",
- irq_idx);
- VERB("irq_idx=%d ret=%d\n", irq_idx, ret);
- }
- dpu_kms->hw_intr->ops.unlock(dpu_kms->hw_intr, irq_flags);
-
- return 0;
-}
-
-static void dpu_clear_all_irqs(struct dpu_kms *dpu_kms)
-{
- if (!dpu_kms->hw_intr || !dpu_kms->hw_intr->ops.clear_all_irqs)
- return;
-
- dpu_kms->hw_intr->ops.clear_all_irqs(dpu_kms->hw_intr);
-}
-
-static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms)
-{
- if (!dpu_kms->hw_intr || !dpu_kms->hw_intr->ops.disable_all_irqs)
- return;
-
- dpu_kms->hw_intr->ops.disable_all_irqs(dpu_kms->hw_intr);
-}
-
-#ifdef CONFIG_DEBUG_FS
-static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v)
-{
- struct dpu_kms *dpu_kms = s->private;
- struct dpu_irq *irq_obj = &dpu_kms->irq_obj;
- struct dpu_irq_callback *cb;
- unsigned long irq_flags;
- int i, irq_count, cb_count;
-
- if (WARN_ON(!irq_obj->irq_cb_tbl))
- return 0;
-
- for (i = 0; i < irq_obj->total_irqs; i++) {
- irq_flags = dpu_kms->hw_intr->ops.lock(dpu_kms->hw_intr);
- cb_count = 0;
- irq_count = atomic_read(&irq_obj->irq_counts[i]);
- list_for_each_entry(cb, &irq_obj->irq_cb_tbl[i], list)
- cb_count++;
- dpu_kms->hw_intr->ops.unlock(dpu_kms->hw_intr, irq_flags);
-
- if (irq_count || cb_count)
- seq_printf(s, "idx:%d irq:%d cb:%d\n",
- i, irq_count, cb_count);
- }
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_core_irq);
-
-void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms,
- struct dentry *parent)
-{
- debugfs_create_file("core_irq", 0600, parent, dpu_kms,
- &dpu_debugfs_core_irq_fops);
-}
-#endif
-
-void dpu_core_irq_preinstall(struct dpu_kms *dpu_kms)
-{
- int i;
-
- pm_runtime_get_sync(&dpu_kms->pdev->dev);
- dpu_clear_all_irqs(dpu_kms);
- dpu_disable_all_irqs(dpu_kms);
- pm_runtime_put_sync(&dpu_kms->pdev->dev);
-
- /* Create irq callbacks for all possible irq_idx */
- dpu_kms->irq_obj.total_irqs = dpu_kms->hw_intr->total_irqs;
- dpu_kms->irq_obj.irq_cb_tbl = kcalloc(dpu_kms->irq_obj.total_irqs,
- sizeof(struct list_head), GFP_KERNEL);
- dpu_kms->irq_obj.irq_counts = kcalloc(dpu_kms->irq_obj.total_irqs,
- sizeof(atomic_t), GFP_KERNEL);
- for (i = 0; i < dpu_kms->irq_obj.total_irqs; i++) {
- INIT_LIST_HEAD(&dpu_kms->irq_obj.irq_cb_tbl[i]);
- atomic_set(&dpu_kms->irq_obj.irq_counts[i], 0);
- }
-}
-
-void dpu_core_irq_uninstall(struct dpu_kms *dpu_kms)
-{
- int i;
-
- pm_runtime_get_sync(&dpu_kms->pdev->dev);
- for (i = 0; i < dpu_kms->irq_obj.total_irqs; i++)
- if (!list_empty(&dpu_kms->irq_obj.irq_cb_tbl[i]))
- DPU_ERROR("irq_idx=%d still enabled/registered\n", i);
-
- dpu_clear_all_irqs(dpu_kms);
- dpu_disable_all_irqs(dpu_kms);
- pm_runtime_put_sync(&dpu_kms->pdev->dev);
-
- kfree(dpu_kms->irq_obj.irq_cb_tbl);
- kfree(dpu_kms->irq_obj.irq_counts);
- dpu_kms->irq_obj.irq_cb_tbl = NULL;
- dpu_kms->irq_obj.irq_counts = NULL;
- dpu_kms->irq_obj.total_irqs = 0;
-}
-
-irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms)
-{
- /*
- * Dispatch to HW driver to handle interrupt lookup that is being
- * fired. When matching interrupt is located, HW driver will call to
- * dpu_core_irq_callback_handler with the irq_idx from the lookup table.
- * dpu_core_irq_callback_handler will perform the registered function
- * callback, and do the interrupt status clearing once the registered
- * callback is finished.
- * Function will also clear the interrupt status after reading.
- */
- dpu_kms->hw_intr->ops.dispatch_irqs(
- dpu_kms->hw_intr,
- dpu_core_irq_callback_handler,
- dpu_kms);
-
- return IRQ_HANDLED;
-}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 768012243b44..967245b8cc02 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*/
@@ -70,17 +70,147 @@ static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc)
return NULL;
}
-static u32 dpu_crtc_get_vblank_counter(struct drm_crtc *crtc)
+static enum dpu_crtc_crc_source dpu_crtc_parse_crc_source(const char *src_name)
{
- struct drm_encoder *encoder;
+ if (!src_name ||
+ !strcmp(src_name, "none"))
+ return DPU_CRTC_CRC_SOURCE_NONE;
+ if (!strcmp(src_name, "auto") ||
+ !strcmp(src_name, "lm"))
+ return DPU_CRTC_CRC_SOURCE_LAYER_MIXER;
+
+ return DPU_CRTC_CRC_SOURCE_INVALID;
+}
- encoder = get_encoder_from_crtc(crtc);
+static int dpu_crtc_verify_crc_source(struct drm_crtc *crtc,
+ const char *src_name, size_t *values_cnt)
+{
+ enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name);
+ struct dpu_crtc_state *crtc_state = to_dpu_crtc_state(crtc->state);
+
+ if (source < 0) {
+ DRM_DEBUG_DRIVER("Invalid source %s for CRTC%d\n", src_name, crtc->index);
+ return -EINVAL;
+ }
+
+ if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
+ *values_cnt = crtc_state->num_mixers;
+
+ return 0;
+}
+
+static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
+{
+ enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name);
+ enum dpu_crtc_crc_source current_source;
+ struct dpu_crtc_state *crtc_state;
+ struct drm_device *drm_dev = crtc->dev;
+ struct dpu_crtc_mixer *m;
+
+ bool was_enabled;
+ bool enable = false;
+ int i, ret = 0;
+
+ if (source < 0) {
+ DRM_DEBUG_DRIVER("Invalid CRC source %s for CRTC%d\n", src_name, crtc->index);
+ return -EINVAL;
+ }
+
+ ret = drm_modeset_lock(&crtc->mutex, NULL);
+
+ if (ret)
+ return ret;
+
+ enable = (source != DPU_CRTC_CRC_SOURCE_NONE);
+ crtc_state = to_dpu_crtc_state(crtc->state);
+
+ spin_lock_irq(&drm_dev->event_lock);
+ current_source = crtc_state->crc_source;
+ spin_unlock_irq(&drm_dev->event_lock);
+
+ was_enabled = (current_source != DPU_CRTC_CRC_SOURCE_NONE);
+
+ if (!was_enabled && enable) {
+ ret = drm_crtc_vblank_get(crtc);
+
+ if (ret)
+ goto cleanup;
+
+ } else if (was_enabled && !enable) {
+ drm_crtc_vblank_put(crtc);
+ }
+
+ spin_lock_irq(&drm_dev->event_lock);
+ crtc_state->crc_source = source;
+ spin_unlock_irq(&drm_dev->event_lock);
+
+ crtc_state->crc_frame_skip_count = 0;
+
+ for (i = 0; i < crtc_state->num_mixers; ++i) {
+ m = &crtc_state->mixers[i];
+
+ if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
+ continue;
+
+ /* Calculate MISR over 1 frame */
+ m->hw_lm->ops.setup_misr(m->hw_lm, true, 1);
+ }
+
+
+cleanup:
+ drm_modeset_unlock(&crtc->mutex);
+
+ return ret;
+}
+
+static u32 dpu_crtc_get_vblank_counter(struct drm_crtc *crtc)
+{
+ struct drm_encoder *encoder = get_encoder_from_crtc(crtc);
if (!encoder) {
DRM_ERROR("no encoder found for crtc %d\n", crtc->index);
- return false;
+ return 0;
+ }
+
+ return dpu_encoder_get_vsync_count(encoder);
+}
+
+
+static int dpu_crtc_get_crc(struct drm_crtc *crtc)
+{
+ struct dpu_crtc_state *crtc_state;
+ struct dpu_crtc_mixer *m;
+ u32 crcs[CRTC_DUAL_MIXERS];
+
+ int i = 0;
+ int rc = 0;
+
+ crtc_state = to_dpu_crtc_state(crtc->state);
+
+ BUILD_BUG_ON(ARRAY_SIZE(crcs) != ARRAY_SIZE(crtc_state->mixers));
+
+ /* Skip first 2 frames in case of "uncooked" CRCs */
+ if (crtc_state->crc_frame_skip_count < 2) {
+ crtc_state->crc_frame_skip_count++;
+ return 0;
}
- return dpu_encoder_get_frame_count(encoder);
+ for (i = 0; i < crtc_state->num_mixers; ++i) {
+
+ m = &crtc_state->mixers[i];
+
+ if (!m->hw_lm || !m->hw_lm->ops.collect_misr)
+ continue;
+
+ rc = m->hw_lm->ops.collect_misr(m->hw_lm, &crcs[i]);
+