| From 0e40a59f5de2cabe9d43fdd676104c22999ec0ac Mon Sep 17 00:00:00 2001 |
| From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> |
| Date: Fri, 19 Jan 2018 21:29:19 +0300 |
| Subject: [PATCH 1045/1795] drm: rcar-du: lvds: Refactor LVDS startup |
| |
| After the recent corrections to the R-Car gen2/3 LVDS startup code, already |
| similar enough at their ends rcar_lvds_enable_gen{2|3}() started asking for |
| a merge and it's becoming actually necessary with the addition of the R-Car |
| V3M (R8A77970) support -- this gen3 SoC has gen2-like LVDPLLCR layout. |
| |
| Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> |
| Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Tested-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| [Set the LVDS mode and input before turning channels on] |
| [Rebased, coding style changes] |
| Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| |
| (cherry picked from commit 871dfe7b48bdc56877826d6cf669e9eef0cf671b) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 132 +++++++++------------- |
| 1 file changed, 51 insertions(+), 81 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c |
| index 01ef0f728e94..4defa8123eb2 100644 |
| --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c |
| +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c |
| @@ -39,102 +39,37 @@ static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data) |
| iowrite32(data, lvds->mmio + reg); |
| } |
| |
| -static void rcar_du_lvdsenc_start_gen2(struct rcar_du_lvdsenc *lvds, |
| - struct rcar_du_crtc *rcrtc) |
| +static u32 rcar_lvds_lvdpllcr_gen2(unsigned int freq) |
| { |
| - const struct drm_display_mode *mode = &rcrtc->crtc.mode; |
| - unsigned int freq = mode->clock; |
| - u32 lvdcr0; |
| - u32 pllcr; |
| - |
| - /* PLL clock configuration */ |
| if (freq < 39000) |
| - pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M; |
| + return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M; |
| else if (freq < 61000) |
| - pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M; |
| + return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M; |
| else if (freq < 121000) |
| - pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M; |
| + return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M; |
| else |
| - pllcr = LVDPLLCR_PLLDLYCNT_150M; |
| - |
| - rcar_lvds_write(lvds, LVDPLLCR, pllcr); |
| - |
| - /* Select the input and set the LVDS mode. */ |
| - lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT; |
| - if (rcrtc->index == 2) |
| - lvdcr0 |= LVDCR0_DUSEL; |
| - rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| - |
| - /* Turn all the channels on. */ |
| - rcar_lvds_write(lvds, LVDCR1, |
| - LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) | |
| - LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY); |
| - |
| - /* Enable LVDS operation and turn bias circuitry on. */ |
| - lvdcr0 |= LVDCR0_BEN | LVDCR0_LVEN; |
| - rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| - |
| - /* |
| - * Turn the PLL on, wait for the startup delay, and turn the output |
| - * on. |
| - */ |
| - lvdcr0 |= LVDCR0_PLLON; |
| - rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| - |
| - usleep_range(100, 150); |
| - |
| - lvdcr0 |= LVDCR0_LVRES; |
| - rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| + return LVDPLLCR_PLLDLYCNT_150M; |
| } |
| |
| -static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds, |
| - struct rcar_du_crtc *rcrtc) |
| +static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq) |
| { |
| - const struct drm_display_mode *mode = &rcrtc->crtc.mode; |
| - unsigned int freq = mode->clock; |
| - u32 lvdcr0; |
| - u32 pllcr; |
| - |
| - /* Set the PLL clock configuration and LVDS mode. */ |
| if (freq < 42000) |
| - pllcr = LVDPLLCR_PLLDIVCNT_42M; |
| + return LVDPLLCR_PLLDIVCNT_42M; |
| else if (freq < 85000) |
| - pllcr = LVDPLLCR_PLLDIVCNT_85M; |
| + return LVDPLLCR_PLLDIVCNT_85M; |
| else if (freq < 128000) |
| - pllcr = LVDPLLCR_PLLDIVCNT_128M; |
| + return LVDPLLCR_PLLDIVCNT_128M; |
| else |
| - pllcr = LVDPLLCR_PLLDIVCNT_148M; |
| - |
| - rcar_lvds_write(lvds, LVDPLLCR, pllcr); |
| - |
| - lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT; |
| - rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| - |
| - /* Turn all the channels on. */ |
| - rcar_lvds_write(lvds, LVDCR1, |
| - LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) | |
| - LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY); |
| - |
| - /* |
| - * Turn the PLL on, set it to LVDS normal mode, wait for the startup |
| - * delay and turn the output on. |
| - */ |
| - lvdcr0 |= LVDCR0_PLLON; |
| - rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| - |
| - lvdcr0 |= LVDCR0_PWD; |
| - rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| - |
| - usleep_range(100, 150); |
| - |
| - lvdcr0 |= LVDCR0_LVRES; |
| - rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| + return LVDPLLCR_PLLDIVCNT_148M; |
| } |
| |
| static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, |
| struct rcar_du_crtc *rcrtc) |
| { |
| + const struct drm_display_mode *mode = &rcrtc->crtc.mode; |
| + u32 lvdpllcr; |
| u32 lvdhcr; |
| + u32 lvdcr0; |
| int ret; |
| |
| if (lvds->enabled) |
| @@ -165,11 +100,46 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, |
| |
| rcar_lvds_write(lvds, LVDCHCR, lvdhcr); |
| |
| - /* Perform generation-specific initialization. */ |
| + /* PLL clock configuration. */ |
| if (lvds->dev->info->gen < 3) |
| - rcar_du_lvdsenc_start_gen2(lvds, rcrtc); |
| + lvdpllcr = rcar_lvds_lvdpllcr_gen2(mode->clock); |
| else |
| - rcar_du_lvdsenc_start_gen3(lvds, rcrtc); |
| + lvdpllcr = rcar_lvds_lvdpllcr_gen3(mode->clock); |
| + rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr); |
| + |
| + /* Set the LVDS mode and select the input. */ |
| + lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT; |
| + if (rcrtc->index == 2) |
| + lvdcr0 |= LVDCR0_DUSEL; |
| + rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| + |
| + /* Turn all the channels on. */ |
| + rcar_lvds_write(lvds, LVDCR1, |
| + LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) | |
| + LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY); |
| + |
| + if (lvds->dev->info->gen < 3) { |
| + /* Enable LVDS operation and turn the bias circuitry on. */ |
| + lvdcr0 |= LVDCR0_BEN | LVDCR0_LVEN; |
| + rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| + } |
| + |
| + /* Turn the PLL on. */ |
| + lvdcr0 |= LVDCR0_PLLON; |
| + rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| + |
| + if (lvds->dev->info->gen > 2) { |
| + /* Set LVDS normal mode. */ |
| + lvdcr0 |= LVDCR0_PWD; |
| + rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| + } |
| + |
| + /* Wait for the startup delay. */ |
| + usleep_range(100, 150); |
| + |
| + /* Turn the output on. */ |
| + lvdcr0 |= LVDCR0_LVRES; |
| + rcar_lvds_write(lvds, LVDCR0, lvdcr0); |
| |
| lvds->enabled = true; |
| |
| -- |
| 2.19.0 |
| |