aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/rcar-du/rcar_du_crtc.c')
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c39
1 files changed, 26 insertions, 13 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..008e172ed43b 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;
}
@@ -251,13 +245,30 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
| DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m)
| DPLLCR_STBY;
- if (rcrtc->index == 1)
+ if (rcrtc->index == 1) {
dpllcr |= DPLLCR_PLCS1
| DPLLCR_INCS_DOTCLKIN1;
- else
- dpllcr |= DPLLCR_PLCS0
+ } else {
+ dpllcr |= DPLLCR_PLCS0_PLL
| DPLLCR_INCS_DOTCLKIN0;
+ /*
+ * On ES2.x we have a single mux controlled via bit 21,
+ * which selects between DCLKIN source (bit 21 = 0) and
+ * a PLL source (bit 21 = 1), where the PLL is always
+ * PLL1.
+ *
+ * On ES1.x we have an additional mux, controlled
+ * via bit 20, for choosing between PLL0 (bit 20 = 0)
+ * and PLL1 (bit 20 = 1). We always want to use PLL1,
+ * so on ES1.x, in addition to setting bit 21, we need
+ * to set the bit 20.
+ */
+
+ if (rcdu->info->quirks & RCAR_DU_QUIRK_H3_ES1_PLL)
+ dpllcr |= DPLLCR_PLCS0_H3ES1X_PLL1;
+ }
+
rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
escr = ESCR_DCLKSEL_DCLKIN | div;
@@ -287,10 +298,12 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
escr = params.escr;
}
- dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr);
+ if (rcdu->info->gen < 4) {
+ dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr);
- rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr);
- rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0);
+ rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr);
+ rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0);
+ }
/* Signal polarities */
dsmr = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)