Skip to contentSkip to conversation

sunxi: display: Replace #ifdef-ery with helper functions

PATCH New Hans de Goede 2 participants 12 messages Aug 3, 2015 – Aug 5, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/5 sunxi: display: Replace #ifdef-ery with helper functions

All the #ifdef-ery in selecting the default and fallback monitor type is becoming unyielding and makes the code hard to read, replace it with a few helper functions.

This will also be useful with the upcoming CHIP board which has display adapter daughterboards which should be runtime detectable.

---
 drivers/video/sunxi_display.c | 90 +++++++++++++++++++++++++++----------------
 1 file changed, 56 insertions(+), 34 deletions(-)
drivers/video/sunxi_display.c +56 -34
index 269083b..3942d2f 100644
@@ -1101,6 +1101,43 @@ ulong board_get_usable_ram_top(ulong total_size)
 	return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
 }
 
+static bool sunxi_has_hdmi(void)
+{
+#ifdef CONFIG_VIDEO_HDMI
+	return true;
+#else
+	return false;
+#endif
+}
+
+static bool sunxi_has_lcd(void)
+{
+	char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
+
+	return lcd_mode[0] != 0;
+}
+
+static bool sunxi_has_vga(void)
+{
+#if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
+	return true;
+#else
+	return false;
+#endif
+}
+
+static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
+{
+	if (allow_hdmi && sunxi_has_hdmi())
+		return sunxi_monitor_dvi;
+	else if (sunxi_has_lcd())
+		return sunxi_monitor_lcd;
+	else if (sunxi_has_vga())
+		return sunxi_monitor_vga;
+	else
+		return sunxi_monitor_none;
+}
+
 void *video_hw_init(void)
 {
 	static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
@@ -1122,12 +1159,8 @@ void *video_hw_init(void)
 	hpd = video_get_option_int(options, "hpd", 1);
 	hpd_delay = video_get_option_int(options, "hpd_delay", 500);
 	edid = video_get_option_int(options, "edid", 1);
-	sunxi_display.monitor = sunxi_monitor_dvi;
-#elif defined CONFIG_VIDEO_VGA_VIA_LCD
-	sunxi_display.monitor = sunxi_monitor_vga;
-#else
-	sunxi_display.monitor = sunxi_monitor_lcd;
 #endif
+	sunxi_display.monitor = sunxi_get_default_mon(true);
 	video_get_option_string(options, "monitor", mon, sizeof(mon),
 				sunxi_get_mon_desc(sunxi_display.monitor));
 	for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
@@ -1152,16 +1185,7 @@ void *video_hw_init(void)
 				mode = &custom;
 		} else if (hpd) {
 			sunxi_hdmi_shutdown();
-			/* Fallback to lcd / vga / none */
-			if (lcd_mode[0]) {
-				sunxi_display.monitor = sunxi_monitor_lcd;
-			} else {
-#if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA
-				sunxi_display.monitor = sunxi_monitor_vga;
-#else
-				sunxi_display.monitor = sunxi_monitor_none;
-#endif
-			}
+			sunxi_display.monitor = sunxi_get_default_mon(false);
 		} /* else continue with hdmi/dvi without a cable connected */
 	}
 #endif
@@ -1171,31 +1195,29 @@ void *video_hw_init(void)
 		return NULL;
 	case sunxi_monitor_dvi:
 	case sunxi_monitor_hdmi:
-#ifdef CONFIG_VIDEO_HDMI
+		if (!sunxi_has_hdmi()) {
+			printf("HDMI/DVI not supported on this board\n");
+			sunxi_display.monitor = sunxi_monitor_none;
+			return NULL;
+		}
 		break;
-#else
-		printf("HDMI/DVI not supported on this board\n");
-		sunxi_display.monitor = sunxi_monitor_none;
-		return NULL;
-#endif
 	case sunxi_monitor_lcd:
-		if (lcd_mode[0]) {
-			sunxi_display.depth = video_get_params(&custom, lcd_mode);
-			mode = &custom;
-			break;
+		if (!sunxi_has_lcd()) {
+			printf("LCD not supported on this board\n");
+			sunxi_display.monitor = sunxi_monitor_none;
+			return NULL;
 		}
-		printf("LCD not supported on this board\n");
-		sunxi_display.monitor = sunxi_monitor_none;
-		return NULL;
+		sunxi_display.depth = video_get_params(&custom, lcd_mode);
+		mode = &custom;
+		break;
 	case sunxi_monitor_vga:
-#if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA
+		if (!sunxi_has_vga()) {
+			printf("VGA not supported on this board\n");
+			sunxi_display.monitor = sunxi_monitor_none;
+			return NULL;
+		}
 		sunxi_display.depth = 18;
 		break;
-#else
-		printf("VGA not supported on this board\n");
-		sunxi_display.monitor = sunxi_monitor_none;
-		return NULL;
-#endif
 	}
 
 	if (mode->vmode != FB_VMODE_NONINTERLACED) {
Signature · 1 line
2.4.3
#1 lore raw

PATCH 2/5 sunxi: display: Correct clk_delay calculations for lcd displays

We should only substract 2 from the vblank time when using tcon1.

---
 drivers/video/sunxi_display.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/video/sunxi_display.c +7 -4
index 3942d2f..fa4241e 100644
@@ -663,11 +663,14 @@ static void sunxi_lcdc_backlight_enable(void)
 		gpio_direction_output(pin, PWM_ON);
 }
 
-static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode)
+static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode, int tcon)
 {
 	int delay;
 
-	delay = mode->lower_margin + mode->vsync_len + mode->upper_margin - 2;
+	delay = mode->lower_margin + mode->vsync_len + mode->upper_margin;
+	if (tcon == 1)
+		delay -= 2;
+
 	return (delay > 30) ? 30 : delay;
 }
 
@@ -692,7 +695,7 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
 	clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
 			SUNXI_LCDC_CTRL_IO_MAP_TCON0);
 
-	clk_delay = sunxi_lcdc_get_clk_delay(mode);
+	clk_delay = sunxi_lcdc_get_clk_delay(mode, 0);
 	writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
 	       SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
 
@@ -770,7 +773,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
 	clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
 			SUNXI_LCDC_CTRL_IO_MAP_TCON1);
 
-	clk_delay = sunxi_lcdc_get_clk_delay(mode);
+	clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
 	writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
 	       SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
 
Signature · 1 line
2.4.3
#3 lore raw

PATCH 3/5 sunxi: display: Add a few extra register and constant defines

In reply to Hans de Goede

Add a few extra sunxi display registers and constant defines. This is a preparation patch for adding composite video out support.

---
 arch/arm/include/asm/arch-sunxi/clock_sun4i.h |  2 +-
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h |  1 +
 arch/arm/include/asm/arch-sunxi/display.h     | 45 ++++++++++++++++++++++++---
 drivers/video/sunxi_display.c                 |  8 ++---
 4 files changed, 46 insertions(+), 10 deletions(-)
arch/arm/include/asm/arch-sunxi/clock_sun4i.h +1 -1
index 01d3e28..a7e25f4 100644
@@ -291,7 +291,7 @@ struct sunxi_ccm_reg {
 #define CCM_LCD_CH0_CTRL_GATE		(0x1 << 31)
 
 #define CCM_LCD_CH1_CTRL_M(n)		((((n) - 1) & 0xf) << 0)
-/* We leave bit 11 set to 0, so sclk1 == sclk2 */
+#define CCM_LCD_CH1_CTRL_HALF_SCLK1	(1 << 11)
 #define CCM_LCD_CH1_CTRL_PLL3		(0 << 24)
 #define CCM_LCD_CH1_CTRL_PLL7		(1 << 24)
 #define CCM_LCD_CH1_CTRL_PLL3_2X	(2 << 24)
arch/arm/include/asm/arch-sunxi/clock_sun6i.h +1 -0
index 8a26b9f..06c6feb 100644
@@ -290,6 +290,7 @@ struct sunxi_ccm_reg {
 #define CCM_LCD_CH0_CTRL_GATE		(0x1 << 31)
 
 #define CCM_LCD_CH1_CTRL_M(n)		((((n) - 1) & 0xf) << 0)
+#define CCM_LCD_CH1_CTRL_HALF_SCLK1	0 /* no seperate sclk1 & 2 on sun6i */
 #define CCM_LCD_CH1_CTRL_PLL3		(0 << 24)
 #define CCM_LCD_CH1_CTRL_PLL7		(1 << 24)
 #define CCM_LCD_CH1_CTRL_PLL3_2X	(2 << 24)
arch/arm/include/asm/arch-sunxi/display.h +40 -5

90 lines not on this page · raw message

drivers/video/sunxi_display.c +4 -4
index fa4241e..74a4280 100644
@@ -791,7 +791,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
 
 	bp = mode->vsync_len + mode->upper_margin;
 	total = mode->yres + mode->lower_margin + bp;
-	writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
+	writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(2 * total) |
 	       SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
 
 	writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
@@ -944,9 +944,9 @@ static void sunxi_vga_mode_set(void)
 	writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
 	       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
 	       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
-	writel(SUNXI_TVE_GCTRL_CFG0_VGA, &tve->cfg0);
-	writel(SUNXI_TVE_GCTRL_DAC_CFG0_VGA, &tve->dac_cfg0);
-	writel(SUNXI_TVE_GCTRL_UNKNOWN1_VGA, &tve->unknown1);
+	writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
+	writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
+	writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
 }
 
 static void sunxi_vga_enable(void)
Signature · 1 line
2.4.3
#4 lore raw

PATCH 3/5 sunxi: display: Add a few extra register and constant defines

Quoted 1 line · Hans de Goede

Add a few extra sunxi display registers and constant defines.

+ "Also rename some existing defines (e.g. dropping _GCTRL) and make some more generic (e.g. dropping the 2x scaling from SUNXI_LCDC_TCON1_TIMING_V_TOTAL)."

Quoted 3 lines

This is a preparation patch for adding composite video out support.

Quoted 171 lines
---
 arch/arm/include/asm/arch-sunxi/clock_sun4i.h |  2 +-
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h |  1 +
 arch/arm/include/asm/arch-sunxi/display.h     | 45 
++++++++++++++++++++++++---
 drivers/video/sunxi_display.c                 |  8 ++---
 4 files changed, 46 insertions(+), 10 deletions(-)
arch/arm/include/asm/arch-sunxi/clock_sun4i.h +1 -1
index 01d3e28..a7e25f4 100644
@@ -291,7 +291,7 @@ struct sunxi_ccm_reg {
 #define CCM_LCD_CH0_CTRL_GATE		(0x1 << 31)
 
 #define CCM_LCD_CH1_CTRL_M(n)		((((n) - 1) & 0xf) << 0)
-/* We leave bit 11 set to 0, so sclk1 == sclk2 */
+#define CCM_LCD_CH1_CTRL_HALF_SCLK1	(1 << 11)
 #define CCM_LCD_CH1_CTRL_PLL3		(0 << 24)
 #define CCM_LCD_CH1_CTRL_PLL7		(1 << 24)
 #define CCM_LCD_CH1_CTRL_PLL3_2X	(2 << 24)
arch/arm/include/asm/arch-sunxi/clock_sun6i.h +1 -0
index 8a26b9f..06c6feb 100644
@@ -290,6 +290,7 @@ struct sunxi_ccm_reg {
 #define CCM_LCD_CH0_CTRL_GATE		(0x1 << 31)
 
 #define CCM_LCD_CH1_CTRL_M(n)		((((n) - 1) & 0xf) << 0)
+#define CCM_LCD_CH1_CTRL_HALF_SCLK1	0 /* no seperate sclk1 & 2 

on sun6i */
#define CCM_LCD_CH1_CTRL_PLL3 (0 << 24)
#define CCM_LCD_CH1_CTRL_PLL7 (1 << 24)
#define CCM_LCD_CH1_CTRL_PLL3_2X (2 << 24)

arch/arm/include/asm/arch-sunxi/display.h +10 -2
index ae95417..830ec42 100644
@@ -151,6 +151,10 @@ struct sunxi_de_be_reg {
 	u32 layer1_attr1_ctrl;		/* 0x8a4 */
 	u32 layer2_attr1_ctrl;		/* 0x8a8 */
 	u32 layer3_attr1_ctrl;		/* 0x8ac */
+	u8 res5[0x110];			/* 0x8b0 */
+	u32 output_color_ctrl;		/* 0x9c0 */
+	u8 res6[0xc];			/* 0x9c4 */
+	u32 output_color_coef[12];	/* 0x9d0 */
 };
 
 struct sunxi_lcdc_reg {
@@ -298,7 +302,7 @@ struct sunxi_tve_reg {
 	u32 cbr_level;			/* 0x10c */
 	u32 burst_phase;		/* 0x110 */
 	u32 burst_width;		/* 0x114 */
-	u8 res2[0x04];			/* 0x118 */
+	u32 unknown2;			/* 0x118 */
 	u32 sync_vbi_level;		/* 0x11c */
 	u32 white_level;		/* 0x120 */
 	u32 active_num;			/* 0x124 */
@@ -331,11 +335,14 @@ struct sunxi_tve_reg {
 #define SUNXI_DE_BE_HEIGHT(y)			(((y) - 1) << 16)
 #define SUNXI_DE_BE_MODE_ENABLE			(1 << 0)
 #define SUNXI_DE_BE_MODE_START			(1 << 1)
+#define SUNXI_DE_BE_MODE_DEFLICKER_ENABLE	(1 << 4)
 #define SUNXI_DE_BE_MODE_LAYER0_ENABLE		(1 << 8)
+#define SUNXI_DE_BE_MODE_INTERLACE_ENABLE	(1 << 28)
 #define SUNXI_DE_BE_LAYER_STRIDE(x)		((x) << 5)
 #define SUNXI_DE_BE_REG_CTRL_LOAD_REGS		(1 << 0)
 #define SUNXI_DE_BE_LAYER_ATTR0_SRC_FE0		0x00000002
 #define SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888	(0x09 << 8)
+#define SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE	1
 
 /*
  * LCDC register constants.
@@ -372,11 +379,12 @@ struct sunxi_tve_reg {
 #define SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE	(1 << 31)
 #define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(x)	((x) << 28)
 #define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(n)	(((n) & 0x1f) << 4)
+#define SUNXI_LCDC_TCON1_CTRL_INTERLACE(n)	((n) << 20)
 #define SUNXI_LCDC_TCON1_CTRL_ENABLE		(1 << 31)
 #define SUNXI_LCDC_TCON1_TIMING_H_BP(n)		(((n) - 1) 
 << 0)
 #define SUNXI_LCDC_TCON1_TIMING_H_TOTAL(n)	(((n) - 1) << 16)
 #define SUNXI_LCDC_TCON1_TIMING_V_BP(n)		(((n) - 1) 
 << 0)
-#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n)	(((n) * 2) << 16)
+#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n)	((n) << 16)
 #ifdef CONFIG_SUNXI_GEN_SUN6I

#define SUNXI_LCDC_LVDS_ANA0 0x40040320
#define SUNXI_LCDC_LVDS_ANA0_EN_MB (1 << 31)

arch/arm/include/asm/arch-sunxi/display.h +16 -3
@@ -494,9 +502,22 @@ struct sunxi_tve_reg {
  */
 #define SUNXI_TVE_GCTRL_DAC_INPUT_MASK(dac)	(0xf << (((dac) + 1) 
 * 4))
 #define SUNXI_TVE_GCTRL_DAC_INPUT(dac, sel)	((sel) << (((dac) + 
 1) * 4))
-#define SUNXI_TVE_GCTRL_CFG0_VGA		0x20000000
-#define SUNXI_TVE_GCTRL_DAC_CFG0_VGA		0x403e1ac7
-#define SUNXI_TVE_GCTRL_UNKNOWN1_VGA		0x00000000
+#define SUNXI_TVE_CFG0_VGA			0x20000000
+#define SUNXI_TVE_CFG0_PAL			0x07030001
+#define SUNXI_TVE_CFG0_NTSC			0x07030000
+#define SUNXI_TVE_DAC_CFG0_VGA			0x403e1ac7
+#define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x403f0008
+#define SUNXI_TVE_FILTER_COMPOSITE		0x00000120
+#define SUNXI_TVE_CHROMA_FREQ_PAL_M		0x21e6efe3
+#define SUNXI_TVE_CHROMA_FREQ_PAL_NC		0x21f69446
+#define SUNXI_TVE_PORCH_NUM_PAL			0x008a0018
+#define SUNXI_TVE_PORCH_NUM_NTSC		0x00760020
+#define SUNXI_TVE_LINE_NUM_PAL			0x00160271
+#define SUNXI_TVE_LINE_NUM_NTSC			0x0016020d
+#define SUNXI_TVE_BLANK_BLACK_LEVEL_PAL		0x00fc00fc
+#define SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC	0x00f0011a
+#define SUNXI_TVE_UNKNOWN1_VGA			0x00000000
+#define SUNXI_TVE_UNKNOWN1_COMPOSITE		0x18181818
 #define SUNXI_TVE_AUTO_DETECT_EN_DET_EN(dac)	(1 << ((dac) + 0))

#define SUNXI_TVE_AUTO_DETECT_EN_INT_EN(dac) (1 << ((dac) + 16))
#define SUNXI_TVE_AUTO_DETECT_INT_STATUS(dac) (1 << ((dac) + 0))

arch/arm/include/asm/arch-sunxi/display.h +14 -0
@@ -512,6 +533,20 @@ struct sunxi_tve_reg {
 #define SUNXI_TVE_CSC_REG1			0x3b6dace1
 #define SUNXI_TVE_CSC_REG2			0x0e1d13dc
 #define SUNXI_TVE_CSC_REG3			0x00108080
+#define SUNXI_TVE_COLOR_BURST_PAL_M		0x00000000
+#define SUNXI_TVE_CBR_LEVEL_PAL			0x00002828
+#define SUNXI_TVE_CBR_LEVEL_NTSC		0x0000004f
+#define SUNXI_TVE_BURST_PHASE_NTSC		0x00000000
+#define SUNXI_TVE_BURST_WIDTH_COMPOSITE		0x0016447e
+#define SUNXI_TVE_UNKNOWN2_PAL			0x0000e0e0
+#define SUNXI_TVE_UNKNOWN2_NTSC			0x0000a0a0
+#define SUNXI_TVE_SYNC_VBI_LEVEL_NTSC		0x001000f0
+#define SUNXI_TVE_ACTIVE_NUM_COMPOSITE		0x000005a0
+#define SUNXI_TVE_CHROMA_BW_GAIN_COMP		0x00000002
+#define SUNXI_TVE_NOTCH_WIDTH_COMPOSITE		0x00000101
+#define SUNXI_TVE_RESYNC_NUM_PAL		0x800d000c
+#define SUNXI_TVE_RESYNC_NUM_NTSC		0x000e000c
+#define SUNXI_TVE_SLAVE_PARA_COMPOSITE		0x00000000
 
 int sunxi_simplefb_setup(void *blob);
 
drivers/video/sunxi_display.c +4 -6
index fa4241e..74a4280 100644
@@ -791,7 +791,7 @@ static void sunxi_lcdc_tcon1_mode_set(const 
 struct ctfb_res_modes *mode,
 
 	bp = mode->vsync_len + mode->upper_margin;
 	total = mode->yres + mode->lower_margin + bp;
-	writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
+	writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(2 * total) |
 	       SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc
->tcon1_timing_v);
 
 	writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode
->vsync_len),
@@ -944,9 +944,9 @@ static void sunxi_vga_mode_set(void)
 	writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
 	       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
 	       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
-	writel(SUNXI_TVE_GCTRL_CFG0_VGA, &tve->cfg0);
-	writel(SUNXI_TVE_GCTRL_DAC_CFG0_VGA, &tve->dac_cfg0);
-	writel(SUNXI_TVE_GCTRL_UNKNOWN1_VGA, &tve->unknown1);
+	writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
+	writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
+	writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
 }
 
 static void sunxi_vga_enable(void)
#5 lore raw

PATCH 3/5 sunxi: display: Add a few extra register and constant defines

Hi,

Quoted 6 lines · Ian Campbell
Quoted 1 line · Hans de Goede

Add a few extra sunxi display registers and constant defines.

+ "Also rename some existing defines (e.g. dropping _GCTRL) and make some more generic (e.g. dropping the 2x scaling from SUNXI_LCDC_TCON1_TIMING_V_TOTAL)."

Added to the commit msg, thanks for the reviews.

Regards,

Hans

Quoted 178 lines
Quoted 4 lines

This is a preparation patch for adding composite video out support.

Quoted 171 lines
---
  arch/arm/include/asm/arch-sunxi/clock_sun4i.h |  2 +-
  arch/arm/include/asm/arch-sunxi/clock_sun6i.h |  1 +
  arch/arm/include/asm/arch-sunxi/display.h     | 45
++++++++++++++++++++++++---
  drivers/video/sunxi_display.c                 |  8 ++---
  4 files changed, 46 insertions(+), 10 deletions(-)
arch/arm/include/asm/arch-sunxi/clock_sun4i.h +1 -1
index 01d3e28..a7e25f4 100644
@@ -291,7 +291,7 @@ struct sunxi_ccm_reg {
  #define CCM_LCD_CH0_CTRL_GATE		(0x1 << 31)
 
  #define CCM_LCD_CH1_CTRL_M(n)		((((n) - 1) & 0xf) << 0)
-/* We leave bit 11 set to 0, so sclk1 == sclk2 */
+#define CCM_LCD_CH1_CTRL_HALF_SCLK1	(1 << 11)
  #define CCM_LCD_CH1_CTRL_PLL3		(0 << 24)
  #define CCM_LCD_CH1_CTRL_PLL7		(1 << 24)
  #define CCM_LCD_CH1_CTRL_PLL3_2X	(2 << 24)
arch/arm/include/asm/arch-sunxi/clock_sun6i.h +1 -0
index 8a26b9f..06c6feb 100644
@@ -290,6 +290,7 @@ struct sunxi_ccm_reg {
  #define CCM_LCD_CH0_CTRL_GATE		(0x1 << 31)
 
  #define CCM_LCD_CH1_CTRL_M(n)		((((n) - 1) & 0xf) << 0)
+#define CCM_LCD_CH1_CTRL_HALF_SCLK1	0 /* no seperate sclk1 & 2

on sun6i */
#define CCM_LCD_CH1_CTRL_PLL3 (0 << 24)
#define CCM_LCD_CH1_CTRL_PLL7 (1 << 24)
#define CCM_LCD_CH1_CTRL_PLL3_2X (2 << 24)

arch/arm/include/asm/arch-sunxi/display.h +10 -2
index ae95417..830ec42 100644
@@ -151,6 +151,10 @@ struct sunxi_de_be_reg {
  	u32 layer1_attr1_ctrl;		/* 0x8a4 */
  	u32 layer2_attr1_ctrl;		/* 0x8a8 */
  	u32 layer3_attr1_ctrl;		/* 0x8ac */
+	u8 res5[0x110];			/* 0x8b0 */
+	u32 output_color_ctrl;		/* 0x9c0 */
+	u8 res6[0xc];			/* 0x9c4 */
+	u32 output_color_coef[12];	/* 0x9d0 */
  };
 
  struct sunxi_lcdc_reg {
@@ -298,7 +302,7 @@ struct sunxi_tve_reg {
  	u32 cbr_level;			/* 0x10c */
  	u32 burst_phase;		/* 0x110 */
  	u32 burst_width;		/* 0x114 */
-	u8 res2[0x04];			/* 0x118 */
+	u32 unknown2;			/* 0x118 */
  	u32 sync_vbi_level;		/* 0x11c */
  	u32 white_level;		/* 0x120 */
  	u32 active_num;			/* 0x124 */
@@ -331,11 +335,14 @@ struct sunxi_tve_reg {
  #define SUNXI_DE_BE_HEIGHT(y)			(((y) - 1) << 16)
  #define SUNXI_DE_BE_MODE_ENABLE			(1 << 0)
  #define SUNXI_DE_BE_MODE_START			(1 << 1)
+#define SUNXI_DE_BE_MODE_DEFLICKER_ENABLE	(1 << 4)
  #define SUNXI_DE_BE_MODE_LAYER0_ENABLE		(1 << 8)
+#define SUNXI_DE_BE_MODE_INTERLACE_ENABLE	(1 << 28)
  #define SUNXI_DE_BE_LAYER_STRIDE(x)		((x) << 5)
  #define SUNXI_DE_BE_REG_CTRL_LOAD_REGS		(1 << 0)
  #define SUNXI_DE_BE_LAYER_ATTR0_SRC_FE0		0x00000002
  #define SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888	(0x09 << 8)
+#define SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE	1
 
  /*
   * LCDC register constants.
@@ -372,11 +379,12 @@ struct sunxi_tve_reg {
  #define SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE	(1 << 31)
  #define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(x)	((x) << 28)
  #define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(n)	(((n) & 0x1f) << 4)
+#define SUNXI_LCDC_TCON1_CTRL_INTERLACE(n)	((n) << 20)
  #define SUNXI_LCDC_TCON1_CTRL_ENABLE		(1 << 31)
  #define SUNXI_LCDC_TCON1_TIMING_H_BP(n)		(((n) - 1)
 << 0)
  #define SUNXI_LCDC_TCON1_TIMING_H_TOTAL(n)	(((n) - 1) << 16)
  #define SUNXI_LCDC_TCON1_TIMING_V_BP(n)		(((n) - 1)
 << 0)
-#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n)	(((n) * 2) << 16)
+#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n)	((n) << 16)
  #ifdef CONFIG_SUNXI_GEN_SUN6I
  #define SUNXI_LCDC_LVDS_ANA0			0x40040320
  #define SUNXI_LCDC_LVDS_ANA0_EN_MB		(1 << 31)
arch/arm/include/asm/arch-sunxi/display.h +16 -3
@@ -494,9 +502,22 @@ struct sunxi_tve_reg {
   */
  #define SUNXI_TVE_GCTRL_DAC_INPUT_MASK(dac)	(0xf << (((dac) + 1)
 * 4))
  #define SUNXI_TVE_GCTRL_DAC_INPUT(dac, sel)	((sel) << (((dac) +
 1) * 4))
-#define SUNXI_TVE_GCTRL_CFG0_VGA		0x20000000
-#define SUNXI_TVE_GCTRL_DAC_CFG0_VGA		0x403e1ac7
-#define SUNXI_TVE_GCTRL_UNKNOWN1_VGA		0x00000000
+#define SUNXI_TVE_CFG0_VGA			0x20000000
+#define SUNXI_TVE_CFG0_PAL			0x07030001
+#define SUNXI_TVE_CFG0_NTSC			0x07030000
+#define SUNXI_TVE_DAC_CFG0_VGA			0x403e1ac7
+#define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x403f0008
+#define SUNXI_TVE_FILTER_COMPOSITE		0x00000120
+#define SUNXI_TVE_CHROMA_FREQ_PAL_M		0x21e6efe3
+#define SUNXI_TVE_CHROMA_FREQ_PAL_NC		0x21f69446
+#define SUNXI_TVE_PORCH_NUM_PAL			0x008a0018
+#define SUNXI_TVE_PORCH_NUM_NTSC		0x00760020
+#define SUNXI_TVE_LINE_NUM_PAL			0x00160271
+#define SUNXI_TVE_LINE_NUM_NTSC			0x0016020d
+#define SUNXI_TVE_BLANK_BLACK_LEVEL_PAL		0x00fc00fc
+#define SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC	0x00f0011a
+#define SUNXI_TVE_UNKNOWN1_VGA			0x00000000
+#define SUNXI_TVE_UNKNOWN1_COMPOSITE		0x18181818
  #define SUNXI_TVE_AUTO_DETECT_EN_DET_EN(dac)	(1 << ((dac) + 0))
  #define SUNXI_TVE_AUTO_DETECT_EN_INT_EN(dac)	(1 << ((dac) + 16))
  #define SUNXI_TVE_AUTO_DETECT_INT_STATUS(dac)	(1 << ((dac) + 0))
arch/arm/include/asm/arch-sunxi/display.h +14 -0
@@ -512,6 +533,20 @@ struct sunxi_tve_reg {
  #define SUNXI_TVE_CSC_REG1			0x3b6dace1
  #define SUNXI_TVE_CSC_REG2			0x0e1d13dc
  #define SUNXI_TVE_CSC_REG3			0x00108080
+#define SUNXI_TVE_COLOR_BURST_PAL_M		0x00000000
+#define SUNXI_TVE_CBR_LEVEL_PAL			0x00002828
+#define SUNXI_TVE_CBR_LEVEL_NTSC		0x0000004f
+#define SUNXI_TVE_BURST_PHASE_NTSC		0x00000000
+#define SUNXI_TVE_BURST_WIDTH_COMPOSITE		0x0016447e
+#define SUNXI_TVE_UNKNOWN2_PAL			0x0000e0e0
+#define SUNXI_TVE_UNKNOWN2_NTSC			0x0000a0a0
+#define SUNXI_TVE_SYNC_VBI_LEVEL_NTSC		0x001000f0
+#define SUNXI_TVE_ACTIVE_NUM_COMPOSITE		0x000005a0
+#define SUNXI_TVE_CHROMA_BW_GAIN_COMP		0x00000002
+#define SUNXI_TVE_NOTCH_WIDTH_COMPOSITE		0x00000101
+#define SUNXI_TVE_RESYNC_NUM_PAL		0x800d000c
+#define SUNXI_TVE_RESYNC_NUM_NTSC		0x000e000c
+#define SUNXI_TVE_SLAVE_PARA_COMPOSITE		0x00000000
 
  int sunxi_simplefb_setup(void *blob);
 
drivers/video/sunxi_display.c +4 -6
index fa4241e..74a4280 100644
@@ -791,7 +791,7 @@ static void sunxi_lcdc_tcon1_mode_set(const
 struct ctfb_res_modes *mode,
 
  	bp = mode->vsync_len + mode->upper_margin;
  	total = mode->yres + mode->lower_margin + bp;
-	writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
+	writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(2 * total) |
  	       SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc
->tcon1_timing_v);
 
  	writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode
->vsync_len),
@@ -944,9 +944,9 @@ static void sunxi_vga_mode_set(void)
  	writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
  	       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
  	       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
-	writel(SUNXI_TVE_GCTRL_CFG0_VGA, &tve->cfg0);
-	writel(SUNXI_TVE_GCTRL_DAC_CFG0_VGA, &tve->dac_cfg0);
-	writel(SUNXI_TVE_GCTRL_UNKNOWN1_VGA, &tve->unknown1);
+	writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
+	writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
+	writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
  }
 
  static void sunxi_vga_enable(void)
#6 lore raw

PATCH 4/5 sunxi: display: Add support for interlaced modes

In reply to Hans de Goede

Add support for interlaced modes, this is a preparation patch for adding composite out support.

---
 drivers/video/sunxi_display.c | 34 +++++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 13 deletions(-)
drivers/video/sunxi_display.c +21 -13
index 74a4280..bed8a3e 100644
@@ -445,6 +445,10 @@ static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
 	writel(SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888, &de_be->layer0_attr1_ctrl);
 
 	setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE);
+	if (mode->vmode == FB_VMODE_INTERLACED)
+		setbits_le32(&de_be->mode,
+			     SUNXI_DE_BE_MODE_DEFLICKER_ENABLE |
+			     SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
 }
 
 static void sunxi_composer_enable(void)
@@ -668,6 +672,8 @@ static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode, int tcon)
 	int delay;
 
 	delay = mode->lower_margin + mode->vsync_len + mode->upper_margin;
+	if (mode->vmode == FB_VMODE_INTERLACED)
+		delay /= 2;
 	if (tcon == 1)
 		delay -= 2;
 
@@ -767,7 +773,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
 {
 	struct sunxi_lcdc_reg * const lcdc =
 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
-	int bp, clk_delay, total, val;
+	int bp, clk_delay, total, val, yres;
 
 	/* Use tcon1 */
 	clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
@@ -775,13 +781,18 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
 
 	clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
 	writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
+	       SUNXI_LCDC_TCON1_CTRL_INTERLACE(
+			mode->vmode == FB_VMODE_INTERLACED) |
 	       SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
 
-	writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
+	yres = mode->yres;
+	if (mode->vmode == FB_VMODE_INTERLACED)
+		yres /= 2;
+	writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
 	       &lcdc->tcon1_timing_source);
-	writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
+	writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
 	       &lcdc->tcon1_timing_scale);
-	writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
+	writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
 	       &lcdc->tcon1_timing_out);
 
 	bp = mode->hsync_len + mode->left_margin;
@@ -791,7 +802,9 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
 
 	bp = mode->vsync_len + mode->upper_margin;
 	total = mode->yres + mode->lower_margin + bp;
-	writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(2 * total) |
+	if (mode->vmode == FB_VMODE_NONINTERLACED)
+		total *= 2;
+	writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
 	       SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
 
 	writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
@@ -1223,14 +1236,6 @@ void *video_hw_init(void)
 		break;
 	}
 
-	if (mode->vmode != FB_VMODE_NONINTERLACED) {
-		printf("Only non-interlaced modes supported, falling back to 1024x768\n");
-		mode = &res_mode_init[RES_MODE_1024x768];
-	} else {
-		printf("Setting up a %dx%d %s console\n", mode->xres,
-		       mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));
-	}
-
 	sunxi_display.fb_size =
 		(mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
 	if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
@@ -1240,6 +1245,9 @@ void *video_hw_init(void)
 		return NULL;
 	}
 
+	printf("Setting up a %dx%d %s console\n", mode->xres,
+	       mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));
+
 	gd->fb_base = gd->bd->bi_dram[0].start +
 		      gd->bd->bi_dram[0].size - sunxi_display.fb_size;
 	sunxi_engines_init();
Signature · 1 line
2.4.3
#7 lore raw

PATCH 4/5 sunxi: display: Add support for interlaced modes

drivers/video/sunxi_display.c static void sunxi_lcdc_tcon1_mode_set(const · line 786

Quoted 7 lines · Hans de Goede
drivers/video/sunxi_display.c +2 -0
@@ -775,13 +781,18 @@ static void sunxi_lcdc_tcon1_mode_set(const
 struct ctfb_res_modes *mode,
 
 	clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
 	writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
+	       SUNXI_LCDC_TCON1_CTRL_INTERLACE(
+			mode->vmode == FB_VMODE_INTERLACED) |

I think this would be clearer if SUNXI_LCDC_TCON1_CTRL_INTERLACE was actually the enable bit (perhaps with _ENABLE on the name), rather than a macro which takes a boolean and returns 0 or the single bit, so you could just write

	mode->vmode == FB_VMODE_INTERLACED ? 
		SUNXI_LCDC_TCON1_CTRL_INTERLACE : 0

(in whichever wrapping style you prefer).

I think the macro is the bit style is more common in this code for boolean options too, we mainly use the macro-with-argument style for fields with more than 1 bit to them.

But ultimately the code is correct as you have it so either way as you prefer:

Although if you want to keep it the way it is then perhaps the macro sh ould have !!n instead of just n, to prevent surprises if someone uses a bitop rather than a full boolean op as an argument?

@@ -1240,6 +1245,9 @@ void *video_hw_init(void)

drivers/video/sunxi_display.c void *video_hw_init(void)

Quoted 5 lines
drivers/video/sunxi_display.c +2 -0
 		return NULL;
 	}
 
+> 	> printf("Setting up a %dx%d %s console\n", mode->xres,
+> 	>        mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));

Is it worth including the string "interlaced" here when appropriate? (Ack stands either way)

Ian.

#8 lore raw

PATCH 4/5 sunxi: display: Add support for interlaced modes

Hi,

Quoted 13 lines · Ian Campbell

drivers/video/sunxi_display.c static void sunxi_lcdc_tcon1_mode_set(const · line 786

Quoted 7 lines · Hans de Goede
drivers/video/sunxi_display.c +2 -0
@@ -775,13 +781,18 @@ static void sunxi_lcdc_tcon1_mode_set(const
 struct ctfb_res_modes *mode,
 
  	clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
  	writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
+	       SUNXI_LCDC_TCON1_CTRL_INTERLACE(
+			mode->vmode == FB_VMODE_INTERLACED) |

I think this would be clearer if SUNXI_LCDC_TCON1_CTRL_INTERLACE was actually the enable bit (perhaps with _ENABLE on the name), rather than a macro which takes a boolean and returns 0 or the single bit, so you could just write

Quoted 7 lines
	mode->vmode == FB_VMODE_INTERLACED ?
		SUNXI_LCDC_TCON1_CTRL_INTERLACE : 0

(in whichever wrapping style you prefer).

I think the macro is the bit style is more common in this code for boolean options too, we mainly use the macro-with-argument style for fields with more than 1 bit to them.

Agreed, fixed.

Quoted 14 lines

But ultimately the code is correct as you have it so either way as you prefer:

Although if you want to keep it the way it is then perhaps the macro sh ould have !!n instead of just n, to prevent surprises if someone uses a bitop rather than a full boolean op as an argument?

(quoted diff) +0 -0
@@ -1240,6 +1245,9 @@ void *video_hw_init(void)
 >   		return NULL;
 >   	}
Quoted 1 line
Quoted 5 lines
Quoted 2 lines

+> > printf("Setting up a %dx%d %s console\n", mode->xres,
+> > mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));

Is it worth including the string "interlaced" here when appropriate? (Ack stands either way)

Also fixed.

Thanks,

Hans

#9 lore raw

PATCH 5/5 sunxi: display: Add composite video out support

In reply to Hans de Goede

Add composite video out support.

This only gets enabled on the Mele M3 for now, since that is were it was tested. It will be enabled on more boards after testing.

---
 board/sunxi/Kconfig           |   7 ++
 configs/Mele_M3_defconfig     |   1 +
 doc/README.video              |   7 +-
 drivers/video/sunxi_display.c | 200 +++++++++++++++++++++++++++++++++++++-----
 4 files changed, 191 insertions(+), 24 deletions(-)
board/sunxi/Kconfig +7 -0
index b156701..7b4a23b 100644
@@ -410,6 +410,13 @@ config VIDEO_VGA_EXTERNAL_DAC_EN
 	Set the enable pin for the external VGA DAC. This takes a string in the
 	format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
 
+config VIDEO_COMPOSITE
+	boolean "Composite video output support"
+	depends on VIDEO && (MACH_SUN4I || MACH_SUN5I || MACH_SUN7I)
+	default n
+	---help---
+	Say Y here to add support for outputting composite video.
+
 config VIDEO_LCD_MODE
 	string "LCD panel timing details"
 	depends on VIDEO
configs/Mele_M3_defconfig +1 -0
index d498269..5c9796a 100644
@@ -5,6 +5,7 @@ CONFIG_DRAM_CLK=384
 CONFIG_MMC0_CD_PIN="PH1"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_VIDEO_VGA=y
+CONFIG_VIDEO_COMPOSITE=y
 CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-m3"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL=y
doc/README.video +5 -2
index d0a3ad6..4f7a4b5 100644
@@ -40,12 +40,15 @@ requires the CONFIG_VIDEO_LCD_MODE Kconfig value to be set.
 
 The sunxi u-boot driver supports the following video-mode options:
 
-- monitor=[none|dvi|hdmi|lcd] - Select the video output to use
+- monitor=[none|dvi|hdmi|lcd|vga|composite-*] - Select the video output to use
  none:     Disable video output.
  dvi/hdmi: Selects output over the hdmi connector with dvi resp. hdmi output
            format, if edid is used the format is automatically selected.
  lcd:      Selects video output to a LCD screen.
- vga:      Selects bideo output over the VGA connector.
+ vga:      Selects video output over the VGA connector.
+ composite-pal/composite-ntsc/composite-pal-m/composite-pal-nc:
+           Selects composite video output, note the specified resolution is
+           ignored with composite video output.
  Defaults to monitor=dvi.
 
 - hpd=[0|1] - Enable use of the hdmi HotPlug Detect feature
drivers/video/sunxi_display.c +178 -22

325 lines not on this page · raw message

Signature · 1 line
2.4.3
#11 lore raw

PATCH 1/5 sunxi: display: Replace #ifdef-ery with helper functions

In reply to Hans de Goede
Quoted 11 lines · Hans de Goede

All the #ifdef-ery in selecting the default and fallback monitor type is
becoming unyielding and makes the code hard to read, replace it with a few
helper functions.

This will also be useful with the upcoming CHIP board which has display
adapter daughterboards which should be runtime detectable.

I couldn't quite convince myself there was "no semantic change" here, but either way it's an improvement so: