[PATCH v3 5/7] drm: rcar-du: Add quirk for H3 ES1.x pclk workaround
Tomi Valkeinen
tomi.valkeinen+renesas at ideasonboard.com
Mon Jan 23 10:47:40 UTC 2023
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+renesas at ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas at 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
More information about the dri-devel
mailing list