sunxi: video: Add lcd output support
Subsystems (3)
PATCH v2 1/2 sunxi: video: Add lcd output support
Add lcd output support, see the new Kconfig entries and doc/README.video for how to enable / configure this.
---
Changes in v2:
-Do not request backlight gpio twices
-Fix some spelling errors in comments
-Fix some no longer accurate comments
--- arch/arm/include/asm/arch-sunxi/display.h | 25 ++++- arch/arm/include/asm/arch-sunxi/gpio.h | 2 + board/sunxi/Kconfig | 43 ++++++- doc/README.video | 50 +++++++-- drivers/video/sunxi_display.c | 179 ++++++++++++++++++++++++++++-- 5 files changed, 272 insertions(+), 27 deletions(-)
arch/arm/include/asm/arch-sunxi/display.h +19 -6
@@ -57,14 +57,13 @@ struct sunxi_lcdc_reg {u32 int0;/* 0x04 */ u32 int1;/* 0x08 */ u8 res0[0x04 ];/* 0x0c */ -u32 frame_ctrl;/* 0x10 */ -u8 res1[0x2c ];/* 0x14 */ +u32 frame_ctrl[12 ];/* 0x10 */ u32 tcon0_ctrl;/* 0x40 */ u32 tcon0_dclk;/* 0x44 */ -u32 tcon0_basic_timing0;/* 0x48 */ -u32 tcon0_basic_timing1;/* 0x4c */ -u32 tcon0_basic_timing2;/* 0x50 */ -u32 tcon0_basic_timing3;/* 0x54 */ +u32 tcon0_timing_active;/* 0x48 */ +u32 tcon0_timing_h;/* 0x4c */ +u32 tcon0_timing_v;/* 0x50 */ +u32 tcon0_timing_sync;/* 0x54 */ u32 tcon0_hv_intf;/* 0x58 */ u8 res2[0x04 ];/* 0x5c */ u32 tcon0_cpu_intf;/* 0x60 */
@@ -179,7 +178,21 @@ struct sunxi_hdmi_reg {#define SUNXI_LCDC_CTRL_IO_MAP_TCON0 (0 << 0)#define SUNXI_LCDC_CTRL_IO_MAP_TCON1 (1 << 0)#define SUNXI_LCDC_CTRL_TCON_ENABLE (1 << 31) +#define SUNXI_LCDC_FRAME_CTRL0_RGB666 ((1 << 31) | (0 << 4)) +#define SUNXI_LCDC_FRAME_CTRL0_RGB656 ((1 << 31) | (5 << 4)) +#define SUNXI_LCDC_FRAME_CTRL_DITHER0 0x11111111 +#define SUNXI_LCDC_FRAME_CTRL_DITHER1 0x01010000 +#define SUNXI_LCDC_FRAME_CTRL_DITHER2 0x15151111 +#define SUNXI_LCDC_FRAME_CTRL_DITHER3 0x57575555 +#define SUNXI_LCDC_FRAME_CTRL_DITHER4 0x7f7f7777 +#define SUNXI_LCDC_TCON0_CTRL_CLK_DELAY (n) (((n) & 0x1f) << 4) +#define SUNXI_LCDC_TCON0_CTRL_ENABLE (1 << 31) +#define SUNXI_LCDC_TCON0_DCLK_DIV (n) ((n) << 0)#define SUNXI_LCDC_TCON0_DCLK_ENABLE (0xf << 28) +#define SUNXI_LCDC_TCON0_TIMING_H_BP (n) (((n) - 1) << 0) +#define SUNXI_LCDC_TCON0_TIMING_H_TOTAL (n) (((n) - 1) << 16) +#define SUNXI_LCDC_TCON0_TIMING_V_BP (n) (((n) - 1) << 0) +#define SUNXI_LCDC_TCON0_TIMING_V_TOTAL (n) (((n) * 2) << 16)#define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY (n) (((n) & 0x1f) << 4)#define SUNXI_LCDC_TCON1_CTRL_ENABLE (1 << 31)#define SUNXI_LCDC_TCON1_TIMING_H_BP (n) (((n) - 1) << 0)
arch/arm/include/asm/arch-sunxi/gpio.h +2 -0
@@ -150,6 +150,8 @@ enum sunxi_gpio_number {#define SUNXI_GPC6_SDC2 3 +#define SUNXI_GPD0_LCD0 2 +#define SUNXI_GPF0_SDC0 2#define SUNXI_GPF2_SDC0 2
board/sunxi/Kconfig +39 -4
56 lines not on this page · raw message
doc/README.video +42 -8
61 lines not on this page · raw message
drivers/video/sunxi_display.c +170 -9
246 lines not on this page · raw message
Signature · 1 line
2.1.0
PATCH v2 2/2 sunxi: video: Enable video on sun8i, which supports LCD but not HDMI
The A23 (sun8i) only has lcd output support, so allow building the video code without HDMI support for use with the A23.
Also the A23 has the same reset bits (and necessity to enable the DRC block) as the sun6i, so enable those bits for sun8i too.
Note building without HDMI support is useful for the A13 (sun5i variant) too, as that one does not have HDMI either.
---
Changes in v2:
-Improve commit message to better reflect what the patch does
--- board/sunxi/Kconfig | 7 +++++++ drivers/video/sunxi_display.c | 30 ++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-)
board/sunxi/Kconfig +7 -0
@@ -288,6 +288,13 @@ config VIDEO or VGA output found on most sunxi devices. See doc/README.video for info on how to select the video output and mode. +config VIDEO_HDMI + boolean "HDMI output support" + depends on VIDEO && !MACH_SUN8I + default y + ---help--- + Say Y here to add support for outputting video over HDMI. + config VIDEO_LCD_MODE string "LCD panel timing details" depends on VIDEO
drivers/video/sunxi_display.c +26 -4
@@ -39,6 +39,8 @@ struct sunxi_display {unsigned int depth; } sunxi_display; +#ifdef CONFIG_VIDEO_HDMI +/* * Wait up to 200ms for value to be set in given part of reg. */
@@ -267,6 +269,8 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode) return 0; } +#endif /* CONFIG_VIDEO_HDMI */ +/* * This is the entity that mixes and matches the different layers and inputs. * Allwinner calls it the back-end, but i like composer better.
@@ -279,7 +283,7 @@ static void sunxi_composer_init(void) (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE ;int i; -#ifdef CONFIG_MACH_SUN6I +#if definedCONFIG_MACH_SUN6I || definedCONFIG_MACH_SUN8I /* Reset off */ setbits_le32 (&ccm->ahb_reset1_cfg,1 <<AHB_RESET_OFFSET_DE_BE0 );#endif
@@ -409,7 +413,7 @@ static void sunxi_lcdc_init(void) (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE ;/* Reset off */ -#ifdef CONFIG_MACH_SUN6I +#if definedCONFIG_MACH_SUN6I || definedCONFIG_MACH_SUN8I setbits_le32 (&ccm->ahb_reset1_cfg,1 <<AHB_RESET_OFFSET_LCD0 );#else setbits_le32 (&ccm->lcd0_ch0_clk_cfg,CCM_LCD_CH0_CTRL_RST );
@@ -565,6 +569,8 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode)writel (0 , &lcdc->tcon0_io_tristate); } +#ifdef CONFIG_VIDEO_HDMI +static void sunxi_lcdc_tcon1_mode_set (const struct ctfb_res_modes *mode,int *clk_div,int *clk_double) {
@@ -711,9 +717,11 @@ static void sunxi_hdmi_enable(void) setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE); } +#endif /* CONFIG_VIDEO_HDMI */ +static void sunxi_drc_init (void ) { -#ifdef CONFIG_MACH_SUN6I +#if definedCONFIG_MACH_SUN6I || definedCONFIG_MACH_SUN8I struct sunxi_ccm_reg *const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE ;
@@ -738,6 +746,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,break ;case sunxi_monitor_dvi:case sunxi_monitor_hdmi: { +#ifdef CONFIG_VIDEO_HDMI int clk_div, clk_double;sunxi_composer_mode_set (mode, address);sunxi_lcdc_tcon1_mode_set (mode, &clk_div, &clk_double);
@@ -745,6 +754,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,sunxi_composer_enable ();sunxi_lcdc_enable ();sunxi_hdmi_enable (); +#endif }break ;case sunxi_monitor_lcd:
@@ -778,9 +788,12 @@ void *video_hw_init(void)const struct ctfb_res_modes *mode;struct ctfb_res_modes custom;const char *options; -int i, ret, hpd, edid; +#ifdef CONFIG_VIDEO_HDMI +int ret, hpd, edid; +#endif char mon[16 ];char *lcd_mode =CONFIG_VIDEO_LCD_MODE ; +int i;memset (&sunxi_display,0 ,sizeof (struct sunxi_display ));
@@ -790,9 +803,13 @@ void *video_hw_init(void)video_get_ctfb_res_modes (RES_MODE_1024x768,24 , &mode, &sunxi_display.depth, &options); +#ifdef CONFIG_VIDEO_HDMI hpd =video_get_option_int (options,"hpd" ,1 ); edid =video_get_option_int (options,"edid" ,1 ); sunxi_display.monitor = sunxi_monitor_dvi; +#else + sunxi_display.monitor = sunxi_monitor_lcd; +#endif video_get_option_string (options,"monitor" , mon,sizeof (mon),sunxi_get_mon_desc (sunxi_display.monitor));for (i =0 ; i <=SUNXI_MONITOR_LAST ; i++) {
@@ -810,6 +827,10 @@ void *video_hw_init(void)return NULL ;case sunxi_monitor_dvi:case sunxi_monitor_hdmi: +#ifndef CONFIG_VIDEO_HDMI +printf ("HDMI/DVI not supported on this board\n" ); +return NULL ; +#else /* Always call hdp_detect, as it also enables clocks, etc. */ ret =sunxi_hdmi_hpd_detect ();if (ret) {
@@ -828,6 +849,7 @@ void *video_hw_init(void)/* Fall back / through to LCD */ sunxi_display.monitor = sunxi_monitor_lcd; +#endif case sunxi_monitor_lcd:if (lcd_mode[0 ]) { sunxi_display.depth =video_get_params (&custom, lcd_mode);
Signature · 1 line
2.1.0
PATCH v2 2/2 sunxi: video: Enable video on sun8i, which supports LCD but not HDMI
Quoted 6 lines · Hans de Goede
The A23 (sun8i) only has lcd output support, so allow building the video code without HDMI support for use with the A23.
Also the A23 has the same reset bits (and necessity to enable the DRC block) as the sun6i, so enable those bits for sun8i too.
Quoted 7 lines
Note building without HDMI support is useful for the A13 (sun5i variant) too, as that one does not have HDMI either.
Signed-off-by Hans de Goede <[email protected]>---
Changes in v2:
-Improve commit message to better reflect what the patch does
Much better, thanks. Acked-by: Ian Campbell <[email protected]>
I think a v3 is still pending on #1/2 based on Siahei's feedback, or did I miss it?
PATCH v2 2/2 sunxi: video: Enable video on sun8i, which supports LCD but not HDMI
Hi,
Quoted 15 lines · Ian Campbell
Quoted 6 lines · Hans de Goede
The A23 (sun8i) only has lcd output support, so allow building the video code without HDMI support for use with the A23.
Also the A23 has the same reset bits (and necessity to enable the DRC block) as the sun6i, so enable those bits for sun8i too.
Quoted 7 lines
Note building without HDMI support is useful for the A13 (sun5i variant) too, as that one does not have HDMI either.
Signed-off-by Hans de Goede <[email protected]>---
Changes in v2:
-Improve commit message to better reflect what the patch does
Quoted 4 lines
Much better, thanks. Acked-by: Ian Campbell <[email protected]>
I think a v3 is still pending on #1/2 based on Siahei's feedback, or did I miss it?
Fixing the RGB656 vs RGB565 thing was such a simple fix that I've simply squashed it into v2 in my personal tree, without sending a v3, but I can send a v3 if you want one ...
Regards,
Hans
PATCH v2 1/2 sunxi: video: Add lcd output support
In reply to Hans de GoedeQuoted 42 lines · On Wed, 31 Dec 2014 13:07:20 +0100 Hans de Goede <[email protected]> wrote:
Add lcd output support, see the new
Kconfigentries and doc/README.video for how to enable / configure this.Signed-off-by Hans de Goede <[email protected]>---
Changes in v2:(quoted diff) +0
-4-Do not request backlight gpio twices -Fix some spelling errors in comments -Fix some no longer accurate comments --- arch/arm/include/asm/arch-sunxi/display.h | 25 ++++- arch/arm/include/asm/arch-sunxi/gpio.h | 2 + board/sunxi/Kconfig | 43 ++++++- doc/README.video | 50 +++++++-- drivers/video/sunxi_display.c | 179 ++++++++++++++++++++++++++++-- 5 files changed, 272 insertions(+), 27 deletions(-)arch/arm/include/asm/arch-sunxi/display.h +5
-6@@ -57,14 +57,13 @@ struct sunxi_lcdc_reg {u32 int0;/* 0x04 */ u32 int1;/* 0x08 */ u8 res0[0x04 ];/* 0x0c */ -u32 frame_ctrl;/* 0x10 */ -u8 res1[0x2c ];/* 0x14 */ +u32 frame_ctrl[12 ];/* 0x10 */ u32 tcon0_ctrl;/* 0x40 */ u32 tcon0_dclk;/* 0x44 */ -u32 tcon0_basic_timing0;/* 0x48 */ -u32 tcon0_basic_timing1;/* 0x4c */ -u32 tcon0_basic_timing2;/* 0x50 */ -u32 tcon0_basic_timing3;/* 0x54 */ +u32 tcon0_timing_active;/* 0x48 */ +u32 tcon0_timing_h;/* 0x4c */ +u32 tcon0_timing_v;/* 0x50 */ +u32 tcon0_timing_sync;/* 0x54 */ u32 tcon0_hv_intf;/* 0x58 */ u8 res2[0x04 ];/* 0x5c */ u32 tcon0_cpu_intf;/* 0x60 */
arch/arm/include/asm/arch-sunxi/display.h struct sunxi_hdmi_reg { · line 182
Quoted 5 lines
arch/arm/include/asm/arch-sunxi/display.h +2
-0@@ -179,7 +178,21 @@ struct sunxi_hdmi_reg {#define SUNXI_LCDC_CTRL_IO_MAP_TCON0 (0 << 0)#define SUNXI_LCDC_CTRL_IO_MAP_TCON1 (1 << 0)#define SUNXI_LCDC_CTRL_TCON_ENABLE (1 << 31) +#define SUNXI_LCDC_FRAME_CTRL0_RGB666 ((1 << 31) | (0 << 4)) +#define SUNXI_LCDC_FRAME_CTRL0_RGB656 ((1 << 31) | (5 << 4))
This would be probably SUNXI_LCDC_FRAME_CTRL0_RGB565 according to the Allwinner documentation of the TCON0_FRM_CTL_REG register:
0: 6bit frm output
1: 5bit frm output
Since we have 5 there (101 bit pattern), it simply means RGB565.
Quoted 275 lines
arch/arm/include/asm/arch-sunxi/display.h +12
-0+#define SUNXI_LCDC_FRAME_CTRL_DITHER0 0x11111111 +#define SUNXI_LCDC_FRAME_CTRL_DITHER1 0x01010000 +#define SUNXI_LCDC_FRAME_CTRL_DITHER2 0x15151111 +#define SUNXI_LCDC_FRAME_CTRL_DITHER3 0x57575555 +#define SUNXI_LCDC_FRAME_CTRL_DITHER4 0x7f7f7777 +#define SUNXI_LCDC_TCON0_CTRL_CLK_DELAY (n) (((n) & 0x1f) << 4) +#define SUNXI_LCDC_TCON0_CTRL_ENABLE (1 << 31) +#define SUNXI_LCDC_TCON0_DCLK_DIV (n) ((n) << 0)#define SUNXI_LCDC_TCON0_DCLK_ENABLE (0xf << 28) +#define SUNXI_LCDC_TCON0_TIMING_H_BP (n) (((n) - 1) << 0) +#define SUNXI_LCDC_TCON0_TIMING_H_TOTAL (n) (((n) - 1) << 16) +#define SUNXI_LCDC_TCON0_TIMING_V_BP (n) (((n) - 1) << 0) +#define SUNXI_LCDC_TCON0_TIMING_V_TOTAL (n) (((n) * 2) << 16)#define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY (n) (((n) & 0x1f) << 4)#define SUNXI_LCDC_TCON1_CTRL_ENABLE (1 << 31)#define SUNXI_LCDC_TCON1_TIMING_H_BP (n) (((n) - 1) << 0)arch/arm/include/asm/arch-sunxi/gpio.h +2
-0@@ -150,6 +150,8 @@ enum sunxi_gpio_number {#define SUNXI_GPC6_SDC2 3 +#define SUNXI_GPD0_LCD0 2 +#define SUNXI_GPF0_SDC0 2#define SUNXI_GPF2_SDC0 2board/sunxi/Kconfig +39
-4@@ -281,17 +281,52 @@ config USB2_VBUS_PIN See USB1_VBUS_PIN help text. config VIDEO - boolean "Enable graphical uboot console on HDMI" + boolean "Enable graphical uboot console on HDMI, LCD or VGA" default y ---help--- - Say Y here to add support for using a cfb console on the HDMI output - found on most sunxi devices. + Say Y here to add support for using a cfb console on the HDMI, LCD + or VGA output found on most sunxi devices. See doc/README.video for + info on how to select the video output and mode. + +config VIDEO_LCD_MODE + string "LCD panel timing details" + depends on VIDEO + default "" + ---help--- + LCD panel timing details string, leave empty if there is no LCD panel. + This is in drivers/video/videomodes.c: video_get_params() format, e.g. + x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:0,vmode:0 + +config VIDEO_LCD_POWER + string "LCD panel power enable pin" + depends on VIDEO + default "" + ---help--- + Set the power enable pin for the LCD panel. This takes a string in the + format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H. + +config VIDEO_LCD_BL_EN + string "LCD panel backlight enable pin" + depends on VIDEO + default "" + ---help--- + Set the backlight enable pin for the LCD panel. This takes a string in the + the format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of + port H. + +config VIDEO_LCD_BL_PWM + string "LCD panel backlight pwm pin" + depends on VIDEO + default "" + ---help--- + Set the backlight pwm pin for the LCD panel. This takes a string in the + format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H. config USB_KEYBOARD boolean "Enable USB keyboard support" default y ---help--- Say Y here to add support for using a USB keyboard (typically used - in combination with a graphical console on HDMI). + in combination with a graphical console). endifdoc/README.video +42
-8@@ -5,15 +5,8 @@ * SPDX-License-Identifier: GPL-2.0+ */ -U-Boot MPC8xx video controller driver -====================================== - -The driver has been tested with the following configurations: - -- MPC823FADS with AD7176 on a PAL TV (YCbYCr) - arsenio at tin.it - "video-mode" environment variable -=============================== +================================= The 'video-mode' environment variable can be used to enable and configure some video drivers. The format matches the video= command-line option used@@ -28,4 +21,45 @@ for Linux: <freq> The frequency (in Hz) to use. <options> A comma-separated list of device-specific options + +U-Boot MPC8xx video controller driver +===================================== + +The driver has been tested with the following configurations: + +- MPC823FADS with AD7176 on a PAL TV (YCbYCr) - arsenio at tin.it + Example: video-mode=fslfb:1280x1024-32 at 60,monitor=dvi + + +U-boot sunxi video controller driver +==================================== + +U-boot supports hdmi and lcd output on Allwinner sunxi SoCs, lcd output +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 + 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. + Defaults to monitor=dvi. + +- hpd=[0|1] - Enable use of the hdmi HotPlug Detect feature + 0: Disabled. Configure dvi/hdmi output even if no cable is detected + 1: Enabled. If a LCD has been configured fallback to the LCD when no cable is + detected, if no LCD is configured, disable video ouput. + Defaults to hpd=1. + +- edid=[0|1] - Enable use of DDC + EDID to get monitor info + 0: Disabled. + 1: Enabled. If valid EDID info was read from the monitor the EDID info will + overrides the xres, yres and refresh from the video-mode env. variable. + Defaults to edid=1. + +For example to always use the hdmi connector, even if no cable is inserted, +using edid info when available and otherwise initalizing it at 1024x768 at 60Hz, +use: video-mode=sunxi:1024x768-24 at 60,monitor=dvi,hpd=0,edid=1 .drivers/video/sunxi_display.c +95
-0@@ -11,7 +11,9 @@#include <asm/arch/clock.h> #include <asm/arch/display.h> +#include <asm/arch/gpio.h> #include <asm/global_data.h> +#include <asm/gpio.h> #include <asm/io.h> #include <errno.h> #include <fdtdec.h> @@ -34,6 +36,7 @@ struct sunxi_display {GraphicDevice graphic_device;bool enabled;enum sunxi_monitor monitor; +unsigned int depth; } sunxi_display;/* @@ -435,6 +438,133 @@ static void sunxi_lcdc_enable(void)setbits_le32 (&lcdc->ctrl,SUNXI_LCDC_CTRL_TCON_ENABLE ); } +static void sunxi_lcdc_panel_enable (void ) +{ +int pin; + +/* +* Start with backlight disabled to avoid the screen flashing to +* white while the lcd inits. +*/ + pin =sunxi_name_to_gpio (CONFIG_VIDEO_LCD_BL_EN ); +if (pin !=-1 ) { +gpio_request (pin,"lcd_backlight_enable" ); +gpio_direction_output (pin,0 ); + } + + pin =sunxi_name_to_gpio (CONFIG_VIDEO_LCD_BL_PWM ); +if (pin !=-1 ) { +gpio_request (pin,"lcd_backlight_pwm" ); +/* backlight pwm is inverted, set to 1 to disable backlight */ +gpio_direction_output (pin,1 ); + } + +/* Give the backlight some time to turn off and power up the panel. */ +mdelay (40 ); + pin =sunxi_name_to_gpio (CONFIG_VIDEO_LCD_POWER ); +if (pin !=-1 ) { +gpio_request (pin,"lcd_power" ); +gpio_direction_output (pin,1 ); + } +} + +static void sunxi_lcdc_backlight_enable (void ) +{ +int pin; + +/* +* We want to have scanned out at least one frame before enabling the +* backlight to avoid the screen flashing to white when we enable it. +*/ +mdelay (40 ); + + pin =sunxi_name_to_gpio (CONFIG_VIDEO_LCD_BL_EN ); +if (pin !=-1 ) +gpio_direction_output (pin,1 ); + + pin =sunxi_name_to_gpio (CONFIG_VIDEO_LCD_BL_PWM ); +if (pin !=-1 ) { +/* backlight pwm is inverted, set to 0 to enable backlight */ +gpio_direction_output (pin,0 ); + } +} + +static int sunxi_lcdc_get_clk_delay (const struct ctfb_res_modes *mode) +{ +int delay; + + delay = mode->lower_margin + mode->vsync_len + mode->upper_margin -2 ; +return (delay >30 ) ?30 : delay; +} + +static void sunxi_lcdc_tcon0_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, clk_div, clk_double, pin, total; + +for (pin =SUNXI_GPD (0 ); pin <=SUNXI_GPD (27 ); pin++) +sunxi_gpio_set_cfgpin (pin,SUNXI_GPD0_LCD0 ); + +sunxi_lcdc_pll_set (0 , mode->pixclock_khz, &clk_div, &clk_double); + +/* Use tcon0 */ +clrsetbits_le32 (&lcdc->ctrl,SUNXI_LCDC_CTRL_IO_MAP_MASK , +SUNXI_LCDC_CTRL_IO_MAP_TCON0 ); + + clk_delay =sunxi_lcdc_get_clk_delay (mode); +writel (SUNXI_LCDC_TCON0_CTRL_ENABLE | +SUNXI_LCDC_TCON0_CTRL_CLK_DELAY (clk_delay), &lcdc->tcon0_ctrl); + +writel (SUNXI_LCDC_TCON0_DCLK_ENABLE | +SUNXI_LCDC_TCON0_DCLK_DIV (clk_div), &lcdc->tcon0_dclk); + +writel (SUNXI_LCDC_X (mode->xres) |SUNXI_LCDC_Y (mode->yres), + &lcdc->tcon0_timing_active); + + bp = mode->hsync_len + mode->left_margin; + total = mode->xres + mode->right_margin + bp; +writel (SUNXI_LCDC_TCON0_TIMING_H_TOTAL (total) | +SUNXI_LCDC_TCON0_TIMING_H_BP (bp), &lcdc->tcon0_timing_h); + + bp = mode->vsync_len + mode->upper_margin; + total = mode->yres + mode->lower_margin + bp; + writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
drivers/video/sunxi_display.c static void sunxi_lcdc_enable(void) · line 542
Quoted 10 lines
drivers/video/sunxi_display.c +10
-0+ SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v); + +writel (SUNXI_LCDC_X (mode->hsync_len) |SUNXI_LCDC_Y (mode->vsync_len), + &lcdc->tcon0_timing_sync); + +/* We only support hv-sync parallel lcd-s for now */ +writel (0 , &lcdc->tcon0_hv_intf); +writel (0 , &lcdc->tcon0_cpu_intf); + +if (sunxi_display.depth ==18 || sunxi_display.depth ==17 ) {
Here 17 is not quite correct for RGB565.
Also these are dithering settings, and this code just unconditionally enables the right dithering for 16-bit LCD displays (this seems to be never used in any real device from the sunxi-boards repository) or 18-bit LCD displays, which are very common.
Because 32-bit framebuffers support more colors than the 18-bit LCD hardware can show, dithering is needed and used:
http://en.wikipedia.org/wiki/Frame_rate_control
Do we want to have a separate option to enable/disable dithering? Or just keep it always enabled until somebody complains?
A simple program for testing dithering effects/usefulness can be found here:
http://lists.denx.de/pipermail/u-boot/2015-January/200031.html
Quoted 130 lines
drivers/video/sunxi_display.c +65
-9+writel (SUNXI_LCDC_FRAME_CTRL_DITHER0 , &lcdc->frame_ctrl[1 ]); +writel (SUNXI_LCDC_FRAME_CTRL_DITHER0 , &lcdc->frame_ctrl[2 ]); +writel (SUNXI_LCDC_FRAME_CTRL_DITHER0 , &lcdc->frame_ctrl[3 ]); +writel (SUNXI_LCDC_FRAME_CTRL_DITHER0 , &lcdc->frame_ctrl[4 ]); +writel (SUNXI_LCDC_FRAME_CTRL_DITHER0 , &lcdc->frame_ctrl[5 ]); +writel (SUNXI_LCDC_FRAME_CTRL_DITHER0 , &lcdc->frame_ctrl[6 ]); +writel (SUNXI_LCDC_FRAME_CTRL_DITHER1 , &lcdc->frame_ctrl[7 ]); +writel (SUNXI_LCDC_FRAME_CTRL_DITHER2 , &lcdc->frame_ctrl[8 ]); +writel (SUNXI_LCDC_FRAME_CTRL_DITHER3 , &lcdc->frame_ctrl[9 ]); +writel (SUNXI_LCDC_FRAME_CTRL_DITHER4 , &lcdc->frame_ctrl[10 ]); +writel (((sunxi_display.depth ==18 ) ? +SUNXI_LCDC_FRAME_CTRL0_RGB666 : +SUNXI_LCDC_FRAME_CTRL0_RGB656 ), + &lcdc->frame_ctrl[0 ]); + } + +/* +* Bit 24 and 25 of tcon0_io_polarity can be used to invert hsync / +* vsync polarity, but this leads to noise problems, so we always +* keep the polarity positive. +*/ +writel (0 , &lcdc->tcon0_io_polarity); +writel (0 , &lcdc->tcon0_io_tristate); +} +static void sunxi_lcdc_tcon1_mode_set (const struct ctfb_res_modes *mode,int *clk_div,int *clk_double) {@@ -618,7 +748,12 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, }break ;case sunxi_monitor_lcd: -/* TODO */ +sunxi_lcdc_panel_enable (); +sunxi_composer_mode_set (mode, address); +sunxi_lcdc_tcon0_mode_set (mode); +sunxi_composer_enable (); +sunxi_lcdc_enable (); +sunxi_lcdc_backlight_enable ();break ;case sunxi_monitor_vga:break ;@@ -641,11 +776,11 @@ void *video_hw_init(void) {static GraphicDevice *graphic_device = &sunxi_display.graphic_device;const struct ctfb_res_modes *mode; -struct ctfb_res_modes edid_mode; +struct ctfb_res_modes custom;const char *options; -unsigned int depth;int i, ret, hpd, edid;char mon[16 ]; +char *lcd_mode =CONFIG_VIDEO_LCD_MODE ;memset (&sunxi_display,0 ,sizeof (struct sunxi_display ));@@ -653,7 +788,8 @@ void *video_hw_init(void) CONFIG_SUNXI_FB_SIZE >> 10); gd->fb_base = gd->ram_top; -video_get_ctfb_res_modes (RES_MODE_1024x768,24 , &mode, &depth, &options); +video_get_ctfb_res_modes (RES_MODE_1024x768,24 , &mode, + &sunxi_display.depth, &options); hpd =video_get_option_int (options,"hpd" ,1 ); edid =video_get_option_int (options,"edid" ,1 ); sunxi_display.monitor = sunxi_monitor_dvi;@@ -678,16 +814,26 @@ void *video_hw_init(void) ret =sunxi_hdmi_hpd_detect ();if (ret) {printf ("HDMI connected: " ); -if (edid &&sunxi_hdmi_edid_get_mode (&edid_mode) ==0 ) - mode = &edid_mode; +if (edid &&sunxi_hdmi_edid_get_mode (&custom) ==0 ) + mode = &custom;break ; }if (!hpd)break ;/* User has requested to ignore hpd */ sunxi_hdmi_shutdown (); -return NULL ; + +if (lcd_mode[0 ] ==0 ) +return NULL ;/* No LCD, bail */ + +/* Fall back / through to LCD */ + sunxi_display.monitor = sunxi_monitor_lcd;case sunxi_monitor_lcd: +if (lcd_mode[0 ]) { + sunxi_display.depth =video_get_params (&custom, lcd_mode); + mode = &custom; +break ; + }printf ("LCD not supported on this board\n" );return NULL ;case sunxi_monitor_vga:@@ -729,16 +875,31 @@ int sunxi_simplefb_setup(void *blob) {static GraphicDevice *graphic_device = &sunxi_display.graphic_device;int offset, ret; +const char *pipeline =NULL ;if (!sunxi_display.enabled)return 0 ; -/* Find a framebuffer node, with pipeline == "de_be0-lcd0-hdmi" */ +switch (sunxi_display.monitor) { +case sunxi_monitor_none: +return 0 ; +case sunxi_monitor_dvi: +case sunxi_monitor_hdmi: + pipeline ="de_be0-lcd0-hdmi" ; +break ; +case sunxi_monitor_lcd: + pipeline ="de_be0-lcd0" ; +break ; +case sunxi_monitor_vga: +break ; + } + +/* Find a prefilled simpefb node, matching out pipeline config */ offset =fdt_node_offset_by_compatible (blob,-1 ,"allwinner,simple-framebuffer" );while (offset >=0 ) { ret =fdt_find_string (blob, offset,"allwinner,pipeline" , -"de_be0-lcd0-hdmi" ); + pipeline);if (ret ==0 )break ; offset = fdt_node_offset_by_compatible(blob, offset,
Signature · 2 lines
Best regards, Siarhei Siamashka
PATCH v2 1/2 sunxi: video: Add lcd output support
Hi,
Quoted 7 lines · Siarhei Siamashka
Quoted 4 lines · On Wed, 31 Dec 2014 13:07:20 +0100 Hans de Goede <[email protected]> wrote:
Add lcd output support, see the new
Kconfigentries and doc/README.video for how to enable / configure this.Signed-off-by Hans de Goede <[email protected]>
<snip>
Quoted 10 lines
arch/arm/include/asm/arch-sunxi/display.h struct sunxi_hdmi_reg { · line 182
Quoted 6 lines
arch/arm/include/asm/arch-sunxi/display.h +2
-0@@ -179,7 +178,21 @@ struct sunxi_hdmi_reg {#define SUNXI_LCDC_CTRL_IO_MAP_TCON0 (0 << 0)#define SUNXI_LCDC_CTRL_IO_MAP_TCON1 (1 << 0)#define SUNXI_LCDC_CTRL_TCON_ENABLE (1 << 31) +#define SUNXI_LCDC_FRAME_CTRL0_RGB666 ((1 << 31) | (0 << 4)) +#define SUNXI_LCDC_FRAME_CTRL0_RGB656 ((1 << 31) | (5 << 4))This would be probably
SUNXI_LCDC_FRAME_CTRL0_RGB565according to the Allwinner documentation of theTCON0_FRM_CTL_REGregister:
Quoted 4 lines
0: 6bit frm output
1: 5bit frm outputSince we have 5 there (101 bit pattern), it simply means RGB565.
You're completely right, I took over the weird RGB656 naming from the allwinner kernel code without thinking things through properly.
<snip>
Quoted 7 lines
Quoted 7 lines
drivers/video/sunxi_display.c +7
-0+ bp = mode->vsync_len + mode->upper_margin; + total = mode->yres + mode->lower_margin + bp; +writel (SUNXI_LCDC_TCON0_TIMING_V_TOTAL (total) | +SUNXI_LCDC_TCON0_TIMING_V_BP (bp), &lcdc->tcon0_timing_v); + +writel (SUNXI_LCDC_X (mode->hsync_len) |SUNXI_LCDC_Y (mode->vsync_len), + &lcdc->tcon0_timing_sync);
Quoted 8 lines
drivers/video/sunxi_display.c static void sunxi_lcdc_enable(void) · line 542
Quoted 6 lines
drivers/video/sunxi_display.c +6
-0+ +/* We only support hv-sync parallel lcd-s for now */ +writel (0 , &lcdc->tcon0_hv_intf); +writel (0 , &lcdc->tcon0_cpu_intf); + +if (sunxi_display.depth ==18 || sunxi_display.depth ==17 ) {Here 17 is not quite correct for RGB565.
Right, this should be 16 meaning plain old RGB565, I've fixed both in my personal tree. Thanks for pointing this out!
Quoted 10 lines
Also these are dithering settings, and this code just unconditionally enables the right dithering for 16-bit LCD displays (this seems to be never used in any real device from the sunxi-boards repository) or 18-bit LCD displays, which are very common.
Because 32-bit framebuffers support more colors than the 18-bit LCD hardware can show, dithering is needed and used:
http://en.wikipedia.org/wiki/Frame_rate_control
Quoted 6 lines
Do we want to have a separate option to enable/disable dithering? Or just keep it always enabled until somebody complains?
A simple program for testing dithering effects/usefulness can be found here:
http://lists.denx.de/pipermail/u-boot/2015-January/200031.html
<snip>
Regards,
Hans