diff mbox series

[v2,4/5] sunxi: video: v3s: Enable LCD support

Message ID 20201016171705.49609-5-m.cerveny@computer.org
State Changes Requested
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series sunxi: video: Add V3S simple-framebuffer | expand

Commit Message

Martin Cerveny Oct. 16, 2020, 5:17 p.m. UTC
Enable support for V3s LCD display with following changes:

V3s has 2x VI and 1x UI channels (use UI channel).
V3s uses PLL3 (PLL_VIDEO) for both DE2 and TCON0 pixelclock.
V3s does not support doubleclock for PLL3.
V3s supports resolution upto 1024x1024.
V3s does not support HDMI.

Signed-off-by: Martin Cerveny <m.cerveny@computer.org>
---
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h |  5 ++--
 arch/arm/include/asm/arch-sunxi/gpio.h        |  1 +
 arch/arm/mach-sunxi/Kconfig                   |  1 +
 drivers/video/sunxi/lcdc.c                    |  5 ++--
 drivers/video/sunxi/sunxi_de2.c               | 25 ++++++++++++++++---
 drivers/video/sunxi/sunxi_dw_hdmi.c           |  2 ++
 drivers/video/sunxi/sunxi_lcd.c               |  9 ++++++-
 7 files changed, 40 insertions(+), 8 deletions(-)

Comments

Maxime Ripard Oct. 19, 2020, 9:25 a.m. UTC | #1
On Fri, Oct 16, 2020 at 07:17:04PM +0200, Martin Cerveny wrote:
> Enable support for V3s LCD display with following changes:
> 
> V3s has 2x VI and 1x UI channels (use UI channel).
> V3s uses PLL3 (PLL_VIDEO) for both DE2 and TCON0 pixelclock.
> V3s does not support doubleclock for PLL3.
> V3s supports resolution upto 1024x1024.
> V3s does not support HDMI.
> 
> Signed-off-by: Martin Cerveny <m.cerveny@computer.org>
> ---
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h |  5 ++--
>  arch/arm/include/asm/arch-sunxi/gpio.h        |  1 +
>  arch/arm/mach-sunxi/Kconfig                   |  1 +
>  drivers/video/sunxi/lcdc.c                    |  5 ++--
>  drivers/video/sunxi/sunxi_de2.c               | 25 ++++++++++++++++---
>  drivers/video/sunxi/sunxi_dw_hdmi.c           |  2 ++
>  drivers/video/sunxi/sunxi_lcd.c               |  9 ++++++-
>  7 files changed, 40 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> index ee387127f3..9efe05d103 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> @@ -329,7 +329,7 @@ struct sunxi_ccm_reg {
>  #define AHB_GATE_OFFSET_DE		12
>  #define AHB_GATE_OFFSET_HDMI		11
>  #define AHB_GATE_OFFSET_TVE		9
> -#ifndef CONFIG_SUNXI_DE2
> +#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
>  #define AHB_GATE_OFFSET_LCD1		5
>  #define AHB_GATE_OFFSET_LCD0		4
>  #else
> @@ -476,7 +476,7 @@ struct sunxi_ccm_reg {
>  #define AHB_RESET_OFFSET_HDMI		11
>  #define AHB_RESET_OFFSET_HDMI2		10
>  #define AHB_RESET_OFFSET_TVE		9
> -#ifndef CONFIG_SUNXI_DE2
> +#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)

These two changes are confusing. The V3S has a DE2, so having that
condition is weird. I'd just add an elif there

>  #define AHB_RESET_OFFSET_LCD1		5
>  #define AHB_RESET_OFFSET_LCD0		4
>  #else
> @@ -510,6 +510,7 @@ struct sunxi_ccm_reg {
>  #define CCM_DE2_CTRL_PLL_MASK		(3 << 24)
>  #define CCM_DE2_CTRL_PLL6_2X		(0 << 24)
>  #define CCM_DE2_CTRL_PLL10		(1 << 24)
> +#define CCM_DE2_CTRL_PLL3_V3S		(0 << 24)
>  #define CCM_DE2_CTRL_GATE		(0x1 << 31)
>  
>  /* CCU security switch, H3 only */
> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
> index d83dfdf605..9b580fbe26 100644
> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
> @@ -181,6 +181,7 @@ enum sunxi_gpio_number {
>  #define SUN5I_GPE_SDC2		3
>  #define SUN8I_GPE_TWI2		3
>  #define SUN50I_GPE_TWI2		3
> +#define SUN8I_V3S_GPE_LCD0	3
>  
>  #define SUNXI_GPF_SDC0		2
>  #define SUNXI_GPF_UART0		4
> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> index be0822bfb7..dc0ee2cdef 100644
> --- a/arch/arm/mach-sunxi/Kconfig
> +++ b/arch/arm/mach-sunxi/Kconfig
> @@ -258,6 +258,7 @@ config MACH_SUN8I_V3S
>  	select CPU_V7_HAS_NONSEC
>  	select CPU_V7_HAS_VIRT
>  	select ARCH_SUPPORT_PSCI
> +	select SUNXI_DE2
>  	select SUNXI_GEN_SUN6I
>  	select SUNXI_DRAM_DW
>  	select SUNXI_DRAM_DW_16BIT
> diff --git a/drivers/video/sunxi/lcdc.c b/drivers/video/sunxi/lcdc.c
> index 73033c3b85..3d50f9d567 100644
> --- a/drivers/video/sunxi/lcdc.c
> +++ b/drivers/video/sunxi/lcdc.c
> @@ -244,7 +244,7 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
>  	 * not sync to higher frequencies.
>  	 */
>  	for (m = min_m; m <= max_m; m++) {
> -#ifndef CONFIG_SUNXI_DE2
> +#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
>  		n = (m * dotclock) / step;
>  
>  		if ((n >= 9) && (n <= 127)) {
> @@ -262,7 +262,7 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
>  		if (!(m & 1))
>  			continue;
>  #endif
> -
> +#ifndef CONFIG_MACH_SUN8I_V3S
>  		/* No double clock on DE2 */
>  		n = (m * dotclock) / (step * 2);
>  		if ((n >= 9) && (n <= 127)) {
> @@ -275,6 +275,7 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
>  				best_double = 1;
>  			}
>  		}
> +#endif

I'm still not seeing any indication as to where you're getting this from

>  	}
>  
>  #ifdef CONFIG_MACH_SUN6I
> diff --git a/drivers/video/sunxi/sunxi_de2.c b/drivers/video/sunxi/sunxi_de2.c
> index b657e163f0..49d41eb243 100644
> --- a/drivers/video/sunxi/sunxi_de2.c
> +++ b/drivers/video/sunxi/sunxi_de2.c
> @@ -26,12 +26,21 @@
>  
>  DECLARE_GLOBAL_DATA_PTR;
>  
> +#ifdef CONFIG_MACH_SUN8I_V3S
> +enum {
> +	/* Maximum LCD size we support */
> +	LCD_MAX_WIDTH		= 1024,
> +	LCD_MAX_HEIGHT		= 1024,
> +	LCD_MAX_LOG2_BPP	= VIDEO_BPP32,
> +};
> +#else
>  enum {
>  	/* Maximum LCD size we support */
>  	LCD_MAX_WIDTH		= 3840,
>  	LCD_MAX_HEIGHT		= 2160,
>  	LCD_MAX_LOG2_BPP	= VIDEO_BPP32,
>  };
> +#endif
>  
>  static void sunxi_de2_composer_init(void)
>  {
> @@ -47,11 +56,19 @@ static void sunxi_de2_composer_init(void)
>  	writel(reg_value, SUNXI_SRAMC_BASE + 0x04);
>  #endif
>  
> +#ifdef CONFIG_MACH_SUN8I_V3S
> +	clock_set_pll3(50000000);
> +	/* pll3 is also used for pixelclock and speed will be recomputed */
> +	/* Set DE parent to pll3 */
> +	clrsetbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_PLL_MASK,
> +			CCM_DE2_CTRL_PLL3_V3S);
> +#else
>  	clock_set_pll10(432000000);
>  
>  	/* Set DE parent to pll10 */
>  	clrsetbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_PLL_MASK,
>  			CCM_DE2_CTRL_PLL10);
> +#endif
>  
>  	/* Set ahb gating to pass */
>  	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE);
> @@ -77,7 +94,8 @@ static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
>  	struct de_ui * const de_ui_regs =
>  		(struct de_ui *)(de_mux_base +
>  				 SUNXI_DE2_MUX_CHAN_REGS +
> -				 SUNXI_DE2_MUX_CHAN_SZ * 1);
> +				 SUNXI_DE2_MUX_CHAN_SZ *
> +				 (IS_ENABLED(CONFIG_MACH_SUN8I_V3S) ? 2 : 1));

Why do you need to use two UI channels? Isn't one enough?

Maxime
Martin Cerveny Oct. 25, 2020, 9:46 a.m. UTC | #2
On Mon, 19 Oct 2020, Maxime Ripard wrote:
> On Fri, Oct 16, 2020 at 07:17:04PM +0200, Martin Cerveny wrote:
>> Enable support for V3s LCD display with following changes:
>>
>> V3s has 2x VI and 1x UI channels (use UI channel).
>> V3s uses PLL3 (PLL_VIDEO) for both DE2 and TCON0 pixelclock.
>> V3s does not support doubleclock for PLL3.
>> V3s supports resolution upto 1024x1024.
>> V3s does not support HDMI.
>>
>> Signed-off-by: Martin Cerveny <m.cerveny@computer.org>
>> ---
>>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h |  5 ++--
>>  arch/arm/include/asm/arch-sunxi/gpio.h        |  1 +
>>  arch/arm/mach-sunxi/Kconfig                   |  1 +
>>  drivers/video/sunxi/lcdc.c                    |  5 ++--
>>  drivers/video/sunxi/sunxi_de2.c               | 25 ++++++++++++++++---
>>  drivers/video/sunxi/sunxi_dw_hdmi.c           |  2 ++
>>  drivers/video/sunxi/sunxi_lcd.c               |  9 ++++++-
>>  7 files changed, 40 insertions(+), 8 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> index ee387127f3..9efe05d103 100644
>> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> @@ -329,7 +329,7 @@ struct sunxi_ccm_reg {
>>  #define AHB_GATE_OFFSET_DE		12
>>  #define AHB_GATE_OFFSET_HDMI		11
>>  #define AHB_GATE_OFFSET_TVE		9
>> -#ifndef CONFIG_SUNXI_DE2
>> +#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
>>  #define AHB_GATE_OFFSET_LCD1		5
>>  #define AHB_GATE_OFFSET_LCD0		4
>>  #else
>> @@ -476,7 +476,7 @@ struct sunxi_ccm_reg {
>>  #define AHB_RESET_OFFSET_HDMI		11
>>  #define AHB_RESET_OFFSET_HDMI2		10
>>  #define AHB_RESET_OFFSET_TVE		9
>> -#ifndef CONFIG_SUNXI_DE2
>> +#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
>
> These two changes are confusing. The V3S has a DE2, so having that
> condition is weird. I'd just add an elif there

The use of "CONFIG_SUNXI_DE2" is misleading.
The platform connectivity (AHB) depends on platform not on DE2.
Names are also weird. Should be "TCON".
AHB gating is described in platform docs and not in DE2 docs.

header:

ahb_gate1;		/* 0x64 ahb module clock gating 1 */
u32 ahb_reset1_cfg;	/* 0x2c4 AHB1 Reset 1 config */
/* ahb_gate1 offsets */
#define AHB_GATE_OFFSET_LCD0 ...
/* ahb_reset1 offsets */
#define AHB_RESET_OFFSET_LCD0

V3S datasheet:
("LCD0" (it is fixed used in drivers/video/sunxi/lcdc.c) is TCON (==TCON0) 
and does not have "LCD1" (==TCON1))

Offset: 0x0064 Register Name: BUS_CLK_GATING_REG1
Bit: 4 TCON_GATING
Offset: 0x02C4 Register Name: BUS_SOFT_RST_REG1
Bit: 4 TCON_RST

>>  #define AHB_RESET_OFFSET_LCD1		5
>>  #define AHB_RESET_OFFSET_LCD0		4
>>  #else
>> @@ -510,6 +510,7 @@ struct sunxi_ccm_reg {
>>  #define CCM_DE2_CTRL_PLL_MASK		(3 << 24)
>>  #define CCM_DE2_CTRL_PLL6_2X		(0 << 24)
>>  #define CCM_DE2_CTRL_PLL10		(1 << 24)
>> +#define CCM_DE2_CTRL_PLL3_V3S		(0 << 24)
>>  #define CCM_DE2_CTRL_GATE		(0x1 << 31)
>>
>>  /* CCU security switch, H3 only */
>> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
>> index d83dfdf605..9b580fbe26 100644
>> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
>> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
>> @@ -181,6 +181,7 @@ enum sunxi_gpio_number {
>>  #define SUN5I_GPE_SDC2		3
>>  #define SUN8I_GPE_TWI2		3
>>  #define SUN50I_GPE_TWI2		3
>> +#define SUN8I_V3S_GPE_LCD0	3
>>
>>  #define SUNXI_GPF_SDC0		2
>>  #define SUNXI_GPF_UART0		4
>> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
>> index be0822bfb7..dc0ee2cdef 100644
>> --- a/arch/arm/mach-sunxi/Kconfig
>> +++ b/arch/arm/mach-sunxi/Kconfig
>> @@ -258,6 +258,7 @@ config MACH_SUN8I_V3S
>>  	select CPU_V7_HAS_NONSEC
>>  	select CPU_V7_HAS_VIRT
>>  	select ARCH_SUPPORT_PSCI
>> +	select SUNXI_DE2
>>  	select SUNXI_GEN_SUN6I
>>  	select SUNXI_DRAM_DW
>>  	select SUNXI_DRAM_DW_16BIT
>> diff --git a/drivers/video/sunxi/lcdc.c b/drivers/video/sunxi/lcdc.c
>> index 73033c3b85..3d50f9d567 100644
>> --- a/drivers/video/sunxi/lcdc.c
>> +++ b/drivers/video/sunxi/lcdc.c
>> @@ -244,7 +244,7 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
>>  	 * not sync to higher frequencies.
>>  	 */
>>  	for (m = min_m; m <= max_m; m++) {
>> -#ifndef CONFIG_SUNXI_DE2
>> +#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
>>  		n = (m * dotclock) / step;
>>
>>  		if ((n >= 9) && (n <= 127)) {
>> @@ -262,7 +262,7 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
>>  		if (!(m & 1))
>>  			continue;
>>  #endif
>> -
>> +#ifndef CONFIG_MACH_SUN8I_V3S
>>  		/* No double clock on DE2 */
>>  		n = (m * dotclock) / (step * 2);
>>  		if ((n >= 9) && (n <= 127)) {
>> @@ -275,6 +275,7 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
>>  				best_double = 1;
>>  			}
>>  		}
>> +#endif
>
> I'm still not seeing any indication as to where you're getting this from

Again.
The use of "CONFIG_SUNXI_DE2" is misleading.
The platform PLL3 functions depends on platform not on DE2.

PLL3 on V3S platform does not support double speed.
"best_double" should not be set.

header:

u32 lcd0_ch0_clk_cfg;	/* 0x118 LCD0 CH0 module clock */
#define CCM_LCD_CH0_CTRL_PLL3		(0 << 24)
#define CCM_LCD_CH0_CTRL_PLL7		(1 << 24)
#define CCM_LCD_CH0_CTRL_PLL3_2X	(2 << 24)
#define CCM_LCD_CH0_CTRL_PLL7_2X	(3 << 24)
#define CCM_LCD_CH0_CTRL_MIPI_PLL	(4 << 24)
/* No reset bit in ch0_clk_cfg (reset is controlled through ahb_reset1) */
#define CCM_LCD_CH0_CTRL_RST		0
#define CCM_LCD_CH0_CTRL_GATE		(0x1 << 31)

V3s datasheet:

Offset: 0x0118 Register Name: TCON_CLK_REG
Bit: 31 SCLK_GATING
Bit: 26:24 CLK_SRC_SEL
    - valid values:
        000: PLL_VIDEO (PLL3)
        001: PLL_PERIPH0 (PLL6)
Bit: 3:0 CLK_DIV_RATIO_M

>>  	}
>>
>>  #ifdef CONFIG_MACH_SUN6I
>> diff --git a/drivers/video/sunxi/sunxi_de2.c b/drivers/video/sunxi/sunxi_de2.c
>> index b657e163f0..49d41eb243 100644
>> --- a/drivers/video/sunxi/sunxi_de2.c
>> +++ b/drivers/video/sunxi/sunxi_de2.c
>> @@ -26,12 +26,21 @@
>>
>>  DECLARE_GLOBAL_DATA_PTR;
>>
>> +#ifdef CONFIG_MACH_SUN8I_V3S
>> +enum {
>> +	/* Maximum LCD size we support */
>> +	LCD_MAX_WIDTH		= 1024,
>> +	LCD_MAX_HEIGHT		= 1024,
>> +	LCD_MAX_LOG2_BPP	= VIDEO_BPP32,
>> +};
>> +#else
>>  enum {
>>  	/* Maximum LCD size we support */
>>  	LCD_MAX_WIDTH		= 3840,
>>  	LCD_MAX_HEIGHT		= 2160,
>>  	LCD_MAX_LOG2_BPP	= VIDEO_BPP32,
>>  };
>> +#endif
>>
>>  static void sunxi_de2_composer_init(void)
>>  {
>> @@ -47,11 +56,19 @@ static void sunxi_de2_composer_init(void)
>>  	writel(reg_value, SUNXI_SRAMC_BASE + 0x04);
>>  #endif
>>
>> +#ifdef CONFIG_MACH_SUN8I_V3S
>> +	clock_set_pll3(50000000);
>> +	/* pll3 is also used for pixelclock and speed will be recomputed */
>> +	/* Set DE parent to pll3 */
>> +	clrsetbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_PLL_MASK,
>> +			CCM_DE2_CTRL_PLL3_V3S);
>> +#else
>>  	clock_set_pll10(432000000);
>>
>>  	/* Set DE parent to pll10 */
>>  	clrsetbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_PLL_MASK,
>>  			CCM_DE2_CTRL_PLL10);
>> +#endif
>>
>>  	/* Set ahb gating to pass */
>>  	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE);
>> @@ -77,7 +94,8 @@ static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
>>  	struct de_ui * const de_ui_regs =
>>  		(struct de_ui *)(de_mux_base +
>>  				 SUNXI_DE2_MUX_CHAN_REGS +
>> -				 SUNXI_DE2_MUX_CHAN_SZ * 1);
>> +				 SUNXI_DE2_MUX_CHAN_SZ *
>> +				 (IS_ENABLED(CONFIG_MACH_SUN8I_V3S) ? 2 : 1));
>
> Why do you need to use two UI channels? Isn't one enough?
>
> Maxime

Not "two" but I am using third (0,1,_2_) channel.
Third channel is only UI channel on V3s platform.
(first two channels are VI channels).

see:
https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/sun4i/sun8i_mixer.c#L581

Regards, M.C>
Maxime Ripard Oct. 26, 2020, 7:09 p.m. UTC | #3
On Sun, Oct 25, 2020 at 10:46:04AM +0100, Martin Cerveny wrote:
> 
> On Mon, 19 Oct 2020, Maxime Ripard wrote:
> > On Fri, Oct 16, 2020 at 07:17:04PM +0200, Martin Cerveny wrote:
> > > Enable support for V3s LCD display with following changes:
> > > 
> > > V3s has 2x VI and 1x UI channels (use UI channel).
> > > V3s uses PLL3 (PLL_VIDEO) for both DE2 and TCON0 pixelclock.
> > > V3s does not support doubleclock for PLL3.
> > > V3s supports resolution upto 1024x1024.
> > > V3s does not support HDMI.
> > > 
> > > Signed-off-by: Martin Cerveny <m.cerveny@computer.org>
> > > ---
> > >  arch/arm/include/asm/arch-sunxi/clock_sun6i.h |  5 ++--
> > >  arch/arm/include/asm/arch-sunxi/gpio.h        |  1 +
> > >  arch/arm/mach-sunxi/Kconfig                   |  1 +
> > >  drivers/video/sunxi/lcdc.c                    |  5 ++--
> > >  drivers/video/sunxi/sunxi_de2.c               | 25 ++++++++++++++++---
> > >  drivers/video/sunxi/sunxi_dw_hdmi.c           |  2 ++
> > >  drivers/video/sunxi/sunxi_lcd.c               |  9 ++++++-
> > >  7 files changed, 40 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> > > index ee387127f3..9efe05d103 100644
> > > --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> > > +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> > > @@ -329,7 +329,7 @@ struct sunxi_ccm_reg {
> > >  #define AHB_GATE_OFFSET_DE		12
> > >  #define AHB_GATE_OFFSET_HDMI		11
> > >  #define AHB_GATE_OFFSET_TVE		9
> > > -#ifndef CONFIG_SUNXI_DE2
> > > +#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
> > >  #define AHB_GATE_OFFSET_LCD1		5
> > >  #define AHB_GATE_OFFSET_LCD0		4
> > >  #else
> > > @@ -476,7 +476,7 @@ struct sunxi_ccm_reg {
> > >  #define AHB_RESET_OFFSET_HDMI		11
> > >  #define AHB_RESET_OFFSET_HDMI2		10
> > >  #define AHB_RESET_OFFSET_TVE		9
> > > -#ifndef CONFIG_SUNXI_DE2
> > > +#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
> > 
> > These two changes are confusing. The V3S has a DE2, so having that
> > condition is weird. I'd just add an elif there
> 
> The use of "CONFIG_SUNXI_DE2" is misleading.
> The platform connectivity (AHB) depends on platform not on DE2.

Feel free to fix it :)

> Names are also weird. Should be "TCON".

That one is less weird. TCON used to be called LCDC as well in the older
SoCs.

> AHB gating is described in platform docs and not in DE2 docs.
> 
> header:
> 
> ahb_gate1;		/* 0x64 ahb module clock gating 1 */
> u32 ahb_reset1_cfg;	/* 0x2c4 AHB1 Reset 1 config */
> /* ahb_gate1 offsets */
> #define AHB_GATE_OFFSET_LCD0 ...
> /* ahb_reset1 offsets */
> #define AHB_RESET_OFFSET_LCD0
> 
> V3S datasheet:
> ("LCD0" (it is fixed used in drivers/video/sunxi/lcdc.c) is TCON (==TCON0)
> and does not have "LCD1" (==TCON1))
> 
> Offset: 0x0064 Register Name: BUS_CLK_GATING_REG1
> Bit: 4 TCON_GATING
> Offset: 0x02C4 Register Name: BUS_SOFT_RST_REG1
> Bit: 4 TCON_RST
> 
> > >  #define AHB_RESET_OFFSET_LCD1		5
> > >  #define AHB_RESET_OFFSET_LCD0		4
> > >  #else
> > > @@ -510,6 +510,7 @@ struct sunxi_ccm_reg {
> > >  #define CCM_DE2_CTRL_PLL_MASK		(3 << 24)
> > >  #define CCM_DE2_CTRL_PLL6_2X		(0 << 24)
> > >  #define CCM_DE2_CTRL_PLL10		(1 << 24)
> > > +#define CCM_DE2_CTRL_PLL3_V3S		(0 << 24)
> > >  #define CCM_DE2_CTRL_GATE		(0x1 << 31)
> > > 
> > >  /* CCU security switch, H3 only */
> > > diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
> > > index d83dfdf605..9b580fbe26 100644
> > > --- a/arch/arm/include/asm/arch-sunxi/gpio.h
> > > +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
> > > @@ -181,6 +181,7 @@ enum sunxi_gpio_number {
> > >  #define SUN5I_GPE_SDC2		3
> > >  #define SUN8I_GPE_TWI2		3
> > >  #define SUN50I_GPE_TWI2		3
> > > +#define SUN8I_V3S_GPE_LCD0	3
> > > 
> > >  #define SUNXI_GPF_SDC0		2
> > >  #define SUNXI_GPF_UART0		4
> > > diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> > > index be0822bfb7..dc0ee2cdef 100644
> > > --- a/arch/arm/mach-sunxi/Kconfig
> > > +++ b/arch/arm/mach-sunxi/Kconfig
> > > @@ -258,6 +258,7 @@ config MACH_SUN8I_V3S
> > >  	select CPU_V7_HAS_NONSEC
> > >  	select CPU_V7_HAS_VIRT
> > >  	select ARCH_SUPPORT_PSCI
> > > +	select SUNXI_DE2
> > >  	select SUNXI_GEN_SUN6I
> > >  	select SUNXI_DRAM_DW
> > >  	select SUNXI_DRAM_DW_16BIT
> > > diff --git a/drivers/video/sunxi/lcdc.c b/drivers/video/sunxi/lcdc.c
> > > index 73033c3b85..3d50f9d567 100644
> > > --- a/drivers/video/sunxi/lcdc.c
> > > +++ b/drivers/video/sunxi/lcdc.c
> > > @@ -244,7 +244,7 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
> > >  	 * not sync to higher frequencies.
> > >  	 */
> > >  	for (m = min_m; m <= max_m; m++) {
> > > -#ifndef CONFIG_SUNXI_DE2
> > > +#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
> > >  		n = (m * dotclock) / step;
> > > 
> > >  		if ((n >= 9) && (n <= 127)) {
> > > @@ -262,7 +262,7 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
> > >  		if (!(m & 1))
> > >  			continue;
> > >  #endif
> > > -
> > > +#ifndef CONFIG_MACH_SUN8I_V3S
> > >  		/* No double clock on DE2 */
> > >  		n = (m * dotclock) / (step * 2);
> > >  		if ((n >= 9) && (n <= 127)) {
> > > @@ -275,6 +275,7 @@ void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
> > >  				best_double = 1;
> > >  			}
> > >  		}
> > > +#endif
> > 
> > I'm still not seeing any indication as to where you're getting this from
> 
> Again.
> The use of "CONFIG_SUNXI_DE2" is misleading.
> The platform PLL3 functions depends on platform not on DE2.
> 
> PLL3 on V3S platform does not support double speed.
> "best_double" should not be set.
> 
> header:
> 
> u32 lcd0_ch0_clk_cfg;	/* 0x118 LCD0 CH0 module clock */
> #define CCM_LCD_CH0_CTRL_PLL3		(0 << 24)
> #define CCM_LCD_CH0_CTRL_PLL7		(1 << 24)
> #define CCM_LCD_CH0_CTRL_PLL3_2X	(2 << 24)
> #define CCM_LCD_CH0_CTRL_PLL7_2X	(3 << 24)
> #define CCM_LCD_CH0_CTRL_MIPI_PLL	(4 << 24)
> /* No reset bit in ch0_clk_cfg (reset is controlled through ahb_reset1) */
> #define CCM_LCD_CH0_CTRL_RST		0
> #define CCM_LCD_CH0_CTRL_GATE		(0x1 << 31)
> 
> V3s datasheet:
> 
> Offset: 0x0118 Register Name: TCON_CLK_REG
> Bit: 31 SCLK_GATING
> Bit: 26:24 CLK_SRC_SEL
>    - valid values:
>        000: PLL_VIDEO (PLL3)
>        001: PLL_PERIPH0 (PLL6)
> Bit: 3:0 CLK_DIV_RATIO_M

Then that's your source. It should be in the commit log.

> > >  	}
> > > 
> > >  #ifdef CONFIG_MACH_SUN6I
> > > diff --git a/drivers/video/sunxi/sunxi_de2.c b/drivers/video/sunxi/sunxi_de2.c
> > > index b657e163f0..49d41eb243 100644
> > > --- a/drivers/video/sunxi/sunxi_de2.c
> > > +++ b/drivers/video/sunxi/sunxi_de2.c
> > > @@ -26,12 +26,21 @@
> > > 
> > >  DECLARE_GLOBAL_DATA_PTR;
> > > 
> > > +#ifdef CONFIG_MACH_SUN8I_V3S
> > > +enum {
> > > +	/* Maximum LCD size we support */
> > > +	LCD_MAX_WIDTH		= 1024,
> > > +	LCD_MAX_HEIGHT		= 1024,
> > > +	LCD_MAX_LOG2_BPP	= VIDEO_BPP32,
> > > +};
> > > +#else
> > >  enum {
> > >  	/* Maximum LCD size we support */
> > >  	LCD_MAX_WIDTH		= 3840,
> > >  	LCD_MAX_HEIGHT		= 2160,
> > >  	LCD_MAX_LOG2_BPP	= VIDEO_BPP32,
> > >  };
> > > +#endif
> > > 
> > >  static void sunxi_de2_composer_init(void)
> > >  {
> > > @@ -47,11 +56,19 @@ static void sunxi_de2_composer_init(void)
> > >  	writel(reg_value, SUNXI_SRAMC_BASE + 0x04);
> > >  #endif
> > > 
> > > +#ifdef CONFIG_MACH_SUN8I_V3S
> > > +	clock_set_pll3(50000000);
> > > +	/* pll3 is also used for pixelclock and speed will be recomputed */
> > > +	/* Set DE parent to pll3 */
> > > +	clrsetbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_PLL_MASK,
> > > +			CCM_DE2_CTRL_PLL3_V3S);
> > > +#else
> > >  	clock_set_pll10(432000000);
> > > 
> > >  	/* Set DE parent to pll10 */
> > >  	clrsetbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_PLL_MASK,
> > >  			CCM_DE2_CTRL_PLL10);
> > > +#endif
> > > 
> > >  	/* Set ahb gating to pass */
> > >  	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE);
> > > @@ -77,7 +94,8 @@ static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
> > >  	struct de_ui * const de_ui_regs =
> > >  		(struct de_ui *)(de_mux_base +
> > >  				 SUNXI_DE2_MUX_CHAN_REGS +
> > > -				 SUNXI_DE2_MUX_CHAN_SZ * 1);
> > > +				 SUNXI_DE2_MUX_CHAN_SZ *
> > > +				 (IS_ENABLED(CONFIG_MACH_SUN8I_V3S) ? 2 : 1));
> > 
> > Why do you need to use two UI channels? Isn't one enough?
> 
> Not "two" but I am using third (0,1,_2_) channel.
> Third channel is only UI channel on V3s platform.
> (first two channels are VI channels).
> 
> see:
> https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/sun4i/sun8i_mixer.c#L581

This should also be in the commit log

Maxime
diff mbox series

Patch

diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index ee387127f3..9efe05d103 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -329,7 +329,7 @@  struct sunxi_ccm_reg {
 #define AHB_GATE_OFFSET_DE		12
 #define AHB_GATE_OFFSET_HDMI		11
 #define AHB_GATE_OFFSET_TVE		9
-#ifndef CONFIG_SUNXI_DE2
+#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
 #define AHB_GATE_OFFSET_LCD1		5
 #define AHB_GATE_OFFSET_LCD0		4
 #else
@@ -476,7 +476,7 @@  struct sunxi_ccm_reg {
 #define AHB_RESET_OFFSET_HDMI		11
 #define AHB_RESET_OFFSET_HDMI2		10
 #define AHB_RESET_OFFSET_TVE		9
-#ifndef CONFIG_SUNXI_DE2
+#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
 #define AHB_RESET_OFFSET_LCD1		5
 #define AHB_RESET_OFFSET_LCD0		4
 #else
@@ -510,6 +510,7 @@  struct sunxi_ccm_reg {
 #define CCM_DE2_CTRL_PLL_MASK		(3 << 24)
 #define CCM_DE2_CTRL_PLL6_2X		(0 << 24)
 #define CCM_DE2_CTRL_PLL10		(1 << 24)
+#define CCM_DE2_CTRL_PLL3_V3S		(0 << 24)
 #define CCM_DE2_CTRL_GATE		(0x1 << 31)
 
 /* CCU security switch, H3 only */
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index d83dfdf605..9b580fbe26 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -181,6 +181,7 @@  enum sunxi_gpio_number {
 #define SUN5I_GPE_SDC2		3
 #define SUN8I_GPE_TWI2		3
 #define SUN50I_GPE_TWI2		3
+#define SUN8I_V3S_GPE_LCD0	3
 
 #define SUNXI_GPF_SDC0		2
 #define SUNXI_GPF_UART0		4
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index be0822bfb7..dc0ee2cdef 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -258,6 +258,7 @@  config MACH_SUN8I_V3S
 	select CPU_V7_HAS_NONSEC
 	select CPU_V7_HAS_VIRT
 	select ARCH_SUPPORT_PSCI
+	select SUNXI_DE2
 	select SUNXI_GEN_SUN6I
 	select SUNXI_DRAM_DW
 	select SUNXI_DRAM_DW_16BIT
diff --git a/drivers/video/sunxi/lcdc.c b/drivers/video/sunxi/lcdc.c
index 73033c3b85..3d50f9d567 100644
--- a/drivers/video/sunxi/lcdc.c
+++ b/drivers/video/sunxi/lcdc.c
@@ -244,7 +244,7 @@  void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
 	 * not sync to higher frequencies.
 	 */
 	for (m = min_m; m <= max_m; m++) {
-#ifndef CONFIG_SUNXI_DE2
+#if !defined(CONFIG_SUNXI_DE2) || defined(CONFIG_MACH_SUN8I_V3S)
 		n = (m * dotclock) / step;
 
 		if ((n >= 9) && (n <= 127)) {
@@ -262,7 +262,7 @@  void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
 		if (!(m & 1))
 			continue;
 #endif
-
+#ifndef CONFIG_MACH_SUN8I_V3S
 		/* No double clock on DE2 */
 		n = (m * dotclock) / (step * 2);
 		if ((n >= 9) && (n <= 127)) {
@@ -275,6 +275,7 @@  void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
 				best_double = 1;
 			}
 		}
+#endif
 	}
 
 #ifdef CONFIG_MACH_SUN6I
diff --git a/drivers/video/sunxi/sunxi_de2.c b/drivers/video/sunxi/sunxi_de2.c
index b657e163f0..49d41eb243 100644
--- a/drivers/video/sunxi/sunxi_de2.c
+++ b/drivers/video/sunxi/sunxi_de2.c
@@ -26,12 +26,21 @@ 
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifdef CONFIG_MACH_SUN8I_V3S
+enum {
+	/* Maximum LCD size we support */
+	LCD_MAX_WIDTH		= 1024,
+	LCD_MAX_HEIGHT		= 1024,
+	LCD_MAX_LOG2_BPP	= VIDEO_BPP32,
+};
+#else
 enum {
 	/* Maximum LCD size we support */
 	LCD_MAX_WIDTH		= 3840,
 	LCD_MAX_HEIGHT		= 2160,
 	LCD_MAX_LOG2_BPP	= VIDEO_BPP32,
 };
+#endif
 
 static void sunxi_de2_composer_init(void)
 {
@@ -47,11 +56,19 @@  static void sunxi_de2_composer_init(void)
 	writel(reg_value, SUNXI_SRAMC_BASE + 0x04);
 #endif
 
+#ifdef CONFIG_MACH_SUN8I_V3S
+	clock_set_pll3(50000000);
+	/* pll3 is also used for pixelclock and speed will be recomputed */
+	/* Set DE parent to pll3 */
+	clrsetbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_PLL_MASK,
+			CCM_DE2_CTRL_PLL3_V3S);
+#else
 	clock_set_pll10(432000000);
 
 	/* Set DE parent to pll10 */
 	clrsetbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_PLL_MASK,
 			CCM_DE2_CTRL_PLL10);
+#endif
 
 	/* Set ahb gating to pass */
 	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE);
@@ -77,7 +94,8 @@  static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
 	struct de_ui * const de_ui_regs =
 		(struct de_ui *)(de_mux_base +
 				 SUNXI_DE2_MUX_CHAN_REGS +
-				 SUNXI_DE2_MUX_CHAN_SZ * 1);
+				 SUNXI_DE2_MUX_CHAN_SZ *
+				 (IS_ENABLED(CONFIG_MACH_SUN8I_V3S) ? 2 : 1));
 	struct de_csc * const de_csc_regs =
 		(struct de_csc *)(de_mux_base +
 				  SUNXI_DE2_MUX_DCSC_REGS);
@@ -104,14 +122,15 @@  static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
 	for (channel = 0; channel < 4; channel++) {
 		void *ch = (void *)(de_mux_base + SUNXI_DE2_MUX_CHAN_REGS +
 				    SUNXI_DE2_MUX_CHAN_SZ * channel);
-		memset(ch, 0, (channel == 0) ?
+		memset(ch, 0, (channel == 0 ||
+			       (IS_ENABLED(CONFIG_MACH_SUN8I_V3S) && channel == 1)) ?
 			sizeof(struct de_vi) : sizeof(struct de_ui));
 	}
 	memset(de_bld_regs, 0, sizeof(struct de_bld));
 
 	writel(0x00000101, &de_bld_regs->fcolor_ctl);
 
-	writel(1, &de_bld_regs->route);
+	writel(IS_ENABLED(CONFIG_MACH_SUN8I_V3S) ? 2 : 1, &de_bld_regs->route);
 
 	writel(0, &de_bld_regs->premultiply);
 	writel(0xff000000, &de_bld_regs->bkcolor);
diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 01d4b7a11c..899fbe2f7f 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -398,6 +398,8 @@  U_BOOT_DRIVER(sunxi_dw_hdmi) = {
 	.priv_auto_alloc_size = sizeof(struct sunxi_dw_hdmi_priv),
 };
 
+#ifndef CONFIG_MACH_SUN8I_V3S
 U_BOOT_DEVICE(sunxi_dw_hdmi) = {
 	.name = "sunxi_dw_hdmi"
 };
+#endif
diff --git a/drivers/video/sunxi/sunxi_lcd.c b/drivers/video/sunxi/sunxi_lcd.c
index 49bf083a8d..2543da3feb 100644
--- a/drivers/video/sunxi/sunxi_lcd.c
+++ b/drivers/video/sunxi/sunxi_lcd.c
@@ -32,6 +32,13 @@  static void sunxi_lcdc_config_pinmux(void)
 		sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
 		sunxi_gpio_set_drv(pin, 3);
 	}
+#elif defined(CONFIG_MACH_SUN8I_V3S)
+	int pin;
+
+	for (pin = SUNXI_GPE(0); pin <= SUNXI_GPE(19); pin++)
+		sunxi_gpio_set_cfgpin(pin, SUN8I_V3S_GPE_LCD0);
+	sunxi_gpio_set_cfgpin(SUNXI_GPE(23), SUN8I_V3S_GPE_LCD0);
+	sunxi_gpio_set_cfgpin(SUNXI_GPE(24), SUN8I_V3S_GPE_LCD0);
 #endif
 }
 
@@ -145,7 +152,7 @@  U_BOOT_DRIVER(sunxi_lcd) = {
 	.priv_auto_alloc_size = sizeof(struct sunxi_lcd_priv),
 };
 
-#ifdef CONFIG_MACH_SUN50I
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I_V3S)
 U_BOOT_DEVICE(sunxi_lcd) = {
 	.name = "sunxi_lcd"
 };