rcar_du_crtc.c does a soc_device_match() in
rcar_du_crtc_set_display_timing() to find out if the SoC is H3 ES1.x, and
if so, apply a workaround.

We will need another H3 ES1.x check in the following patch, so rather than
adding more soc_device_match() calls, let's add a rcar_du_device_info
entry for the ES1, and a quirk flag,
RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY, for the workaround.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen+rene...@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+rene...@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c |  8 +----
 drivers/gpu/drm/rcar-du/rcar_du_drv.c  | 48 ++++++++++++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_drv.h  |  1 +
 3 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c 
b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 3619e1ddeb62..f2d3266509cc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -10,7 +10,6 @@
 #include <linux/clk.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
-#include <linux/sys_soc.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -204,11 +203,6 @@ static void rcar_du_escr_divider(struct clk *clk, unsigned 
long target,
        }
 }
 
-static const struct soc_device_attribute rcar_du_r8a7795_es1[] = {
-       { .soc_id = "r8a7795", .revision = "ES1.*" },
-       { /* sentinel */ }
-};
-
 static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
 {
        const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
@@ -238,7 +232,7 @@ static void rcar_du_crtc_set_display_timing(struct 
rcar_du_crtc *rcrtc)
                 * no post-divider when a display PLL is present (as shown by
                 * the workaround breaking HDMI output on M3-W during testing).
                 */
-               if (soc_device_match(rcar_du_r8a7795_es1)) {
+               if (rcdu->info->quirks & RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY) {
                        target *= 2;
                        div = 1;
                }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c 
b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index c7c5217cfc1a..ea3a8cff74b7 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
+#include <linux/sys_soc.h>
 #include <linux/wait.h>
 
 #include <drm/drm_atomic_helper.h>
@@ -386,6 +387,42 @@ static const struct rcar_du_device_info 
rcar_du_r8a7795_info = {
        .dpll_mask =  BIT(2) | BIT(1),
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7795_es1_info = {
+       .gen = 3,
+       .features = RCAR_DU_FEATURE_CRTC_IRQ
+                 | RCAR_DU_FEATURE_CRTC_CLOCK
+                 | RCAR_DU_FEATURE_VSP1_SOURCE
+                 | RCAR_DU_FEATURE_INTERLACED
+                 | RCAR_DU_FEATURE_TVM_SYNC,
+       .quirks = RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY,
+       .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
+       .routes = {
+               /*
+                * R8A7795 has one RGB output, two HDMI outputs and one
+                * LVDS output.
+                */
+               [RCAR_DU_OUTPUT_DPAD0] = {
+                       .possible_crtcs = BIT(3),
+                       .port = 0,
+               },
+               [RCAR_DU_OUTPUT_HDMI0] = {
+                       .possible_crtcs = BIT(1),
+                       .port = 1,
+               },
+               [RCAR_DU_OUTPUT_HDMI1] = {
+                       .possible_crtcs = BIT(2),
+                       .port = 2,
+               },
+               [RCAR_DU_OUTPUT_LVDS0] = {
+                       .possible_crtcs = BIT(0),
+                       .port = 3,
+               },
+       },
+       .num_lvds = 1,
+       .num_rpf = 5,
+       .dpll_mask =  BIT(2) | BIT(1),
+};
+
 static const struct rcar_du_device_info rcar_du_r8a7796_info = {
        .gen = 3,
        .features = RCAR_DU_FEATURE_CRTC_IRQ
@@ -576,6 +613,11 @@ static const struct of_device_id rcar_du_of_table[] = {
 
 MODULE_DEVICE_TABLE(of, rcar_du_of_table);
 
+static const struct soc_device_attribute rcar_du_soc_table[] = {
+       { .soc_id = "r8a7795", .revision = "ES1.*", .data = 
&rcar_du_r8a7795_es1_info },
+       { /* sentinel */ }
+};
+
 const char *rcar_du_output_name(enum rcar_du_output output)
 {
        static const char * const names[] = {
@@ -667,6 +709,7 @@ static void rcar_du_shutdown(struct platform_device *pdev)
 
 static int rcar_du_probe(struct platform_device *pdev)
 {
+       const struct soc_device_attribute *soc_attr;
        struct rcar_du_device *rcdu;
        unsigned int mask;
        int ret;
@@ -681,8 +724,13 @@ static int rcar_du_probe(struct platform_device *pdev)
                return PTR_ERR(rcdu);
 
        rcdu->dev = &pdev->dev;
+
        rcdu->info = of_device_get_match_data(rcdu->dev);
 
+       soc_attr = soc_device_match(rcar_du_soc_table);
+       if (soc_attr)
+               rcdu->info = soc_attr->data;
+
        platform_set_drvdata(pdev, rcdu);
 
        /* I/O resources */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h 
b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 5cfa2bb7ad93..df87ccab146f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -34,6 +34,7 @@ struct rcar_du_device;
 #define RCAR_DU_FEATURE_NO_BLENDING    BIT(5)  /* PnMR.SPIM does not have ALP 
nor EOR bits */
 
 #define RCAR_DU_QUIRK_ALIGN_128B       BIT(0)  /* Align pitches to 128 bytes */
+#define RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY BIT(1)     /* H3 ES1 has pclk 
stability issue */
 
 enum rcar_du_output {
        RCAR_DU_OUTPUT_DPAD0,
-- 
2.34.1

Reply via email to