mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
video: sunxi_display: Convert to DM_VIDEO
DM_VIDEO migration deadline is already expired, but around 80 Allwinner boards are still using video in a legacy way: ===================== WARNING ====================== This board does not use CONFIG_DM_VIDEO Please update the board to use CONFIG_DM_VIDEO before the v2019.07 release. Failure to update by the deadline may result in board removal. See doc/driver-model/migration.rst for more info. ==================================================== Convert the legacy video driver over to the DM_VIDEO framework. This is a minimal conversion: it doesn't use the DT for finding its resources, nor does it use DM clocks or DM devices for the outputs (LCD, HDMI, CVBS). Tested in Bananapi M1+ Plus 1920x1200 HDMI out. (Jagan) Signed-off-by: Jagan Teki <jagan@amarulasolutions.com> [Andre: rebase and smaller fixes] Signed-off-by: Andre Przywara <andre.przywara@arm.com> Acked-by: Maxime Ripard <mripard@kernel.org> Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
c5219c4a18
commit
5d235324ae
4 changed files with 158 additions and 141 deletions
|
@ -816,13 +816,14 @@ config VIDEO_SUNXI
|
|||
depends on !MACH_SUN9I
|
||||
depends on !MACH_SUN50I
|
||||
depends on !SUN50I_GEN_H6
|
||||
select VIDEO
|
||||
select DM_VIDEO
|
||||
select DISPLAY
|
||||
imply VIDEO_DT_SIMPLEFB
|
||||
default y
|
||||
---help---
|
||||
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.
|
||||
Say Y here to add support for using a graphical console on the HDMI,
|
||||
LCD or VGA output found on older sunxi devices. This will also provide
|
||||
a simple_framebuffer device for Linux.
|
||||
|
||||
config VIDEO_HDMI
|
||||
bool "HDMI output support"
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <display.h>
|
||||
#include <dm.h>
|
||||
#include <cpu_func.h>
|
||||
#include <efi_loader.h>
|
||||
#include <init.h>
|
||||
|
@ -28,7 +30,9 @@
|
|||
#include <fdt_support.h>
|
||||
#include <i2c.h>
|
||||
#include <malloc.h>
|
||||
#include <video.h>
|
||||
#include <video_fb.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include "../videomodes.h"
|
||||
#include "../anx9804.h"
|
||||
#include "../hitachi_tx18d42vm_lcd.h"
|
||||
|
@ -45,6 +49,11 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* Maximum LCD size we support */
|
||||
#define LCD_MAX_WIDTH 3840
|
||||
#define LCD_MAX_HEIGHT 2160
|
||||
#define LCD_MAX_LOG2_BPP VIDEO_BPP32
|
||||
|
||||
enum sunxi_monitor {
|
||||
sunxi_monitor_none,
|
||||
sunxi_monitor_dvi,
|
||||
|
@ -58,13 +67,12 @@ enum sunxi_monitor {
|
|||
};
|
||||
#define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
|
||||
|
||||
struct sunxi_display {
|
||||
GraphicDevice graphic_device;
|
||||
struct sunxi_display_priv {
|
||||
enum sunxi_monitor monitor;
|
||||
unsigned int depth;
|
||||
unsigned int fb_addr;
|
||||
unsigned int fb_size;
|
||||
} sunxi_display;
|
||||
};
|
||||
|
||||
const struct ctfb_res_modes composite_video_modes[2] = {
|
||||
/* x y hz pixclk ps/kHz le ri up lo hs vs s vmode */
|
||||
|
@ -214,7 +222,8 @@ static int sunxi_hdmi_edid_get_block(int block, u8 *buf)
|
|||
return r;
|
||||
}
|
||||
|
||||
static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode,
|
||||
static int sunxi_hdmi_edid_get_mode(struct sunxi_display_priv *sunxi_display,
|
||||
struct ctfb_res_modes *mode,
|
||||
bool verbose_mode)
|
||||
{
|
||||
struct edid1_info edid1;
|
||||
|
@ -291,14 +300,14 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode,
|
|||
}
|
||||
|
||||
/* Check for basic audio support, if found enable hdmi output */
|
||||
sunxi_display.monitor = sunxi_monitor_dvi;
|
||||
sunxi_display->monitor = sunxi_monitor_dvi;
|
||||
for (i = 0; i < ext_blocks; i++) {
|
||||
if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG ||
|
||||
cea681[i].revision < 2)
|
||||
continue;
|
||||
|
||||
if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
|
||||
sunxi_display.monitor = sunxi_monitor_hdmi;
|
||||
sunxi_display->monitor = sunxi_monitor_hdmi;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -414,9 +423,9 @@ static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
|
|||
static void sunxi_frontend_enable(void) {}
|
||||
#endif
|
||||
|
||||
static bool sunxi_is_composite(void)
|
||||
static bool sunxi_is_composite(enum sunxi_monitor monitor)
|
||||
{
|
||||
switch (sunxi_display.monitor) {
|
||||
switch (monitor) {
|
||||
case sunxi_monitor_none:
|
||||
case sunxi_monitor_dvi:
|
||||
case sunxi_monitor_hdmi:
|
||||
|
@ -473,7 +482,8 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
|
|||
};
|
||||
|
||||
static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
|
||||
unsigned int address)
|
||||
unsigned int address,
|
||||
enum sunxi_monitor monitor)
|
||||
{
|
||||
struct sunxi_de_be_reg * const de_be =
|
||||
(struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
|
||||
|
@ -502,7 +512,7 @@ static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
|
|||
#endif
|
||||
SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
|
||||
|
||||
if (sunxi_is_composite()) {
|
||||
if (sunxi_is_composite(monitor)) {
|
||||
writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
|
||||
&de_be->output_color_ctrl);
|
||||
for (i = 0; i < 12; i++)
|
||||
|
@ -616,7 +626,8 @@ static void sunxi_lcdc_backlight_enable(void)
|
|||
gpio_direction_output(pin, PWM_ON);
|
||||
}
|
||||
|
||||
static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
|
||||
static void sunxi_lcdc_tcon0_mode_set(struct sunxi_display_priv *sunxi_display,
|
||||
const struct ctfb_res_modes *mode,
|
||||
bool for_ext_vga_dac)
|
||||
{
|
||||
struct sunxi_lcdc_reg * const lcdc =
|
||||
|
@ -643,17 +654,18 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
|
|||
}
|
||||
|
||||
lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double,
|
||||
sunxi_is_composite());
|
||||
sunxi_is_composite(sunxi_display->monitor));
|
||||
|
||||
video_ctfb_mode_to_display_timing(mode, &timing);
|
||||
lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
|
||||
sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
|
||||
sunxi_display->depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
|
||||
}
|
||||
|
||||
#if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
|
||||
static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
|
||||
int *clk_div, int *clk_double,
|
||||
bool use_portd_hvsync)
|
||||
bool use_portd_hvsync,
|
||||
enum sunxi_monitor monitor)
|
||||
{
|
||||
struct sunxi_lcdc_reg * const lcdc =
|
||||
(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
|
||||
|
@ -663,7 +675,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
|
|||
|
||||
video_ctfb_mode_to_display_timing(mode, &timing);
|
||||
lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync,
|
||||
sunxi_is_composite());
|
||||
sunxi_is_composite(monitor));
|
||||
|
||||
if (use_portd_hvsync) {
|
||||
sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
|
||||
|
@ -671,7 +683,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
|
|||
}
|
||||
|
||||
lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double,
|
||||
sunxi_is_composite());
|
||||
sunxi_is_composite(monitor));
|
||||
}
|
||||
#endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
|
||||
|
||||
|
@ -725,7 +737,8 @@ static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
|
|||
}
|
||||
|
||||
static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
|
||||
int clk_div, int clk_double)
|
||||
int clk_div, int clk_double,
|
||||
enum sunxi_monitor monitor)
|
||||
{
|
||||
struct sunxi_hdmi_reg * const hdmi =
|
||||
(struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
|
||||
|
@ -734,7 +747,7 @@ static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
|
|||
/* Write clear interrupt status bits */
|
||||
writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
|
||||
|
||||
if (sunxi_display.monitor == sunxi_monitor_hdmi)
|
||||
if (monitor == sunxi_monitor_hdmi)
|
||||
sunxi_hdmi_setup_info_frames(mode);
|
||||
|
||||
/* Set input sync enable */
|
||||
|
@ -789,7 +802,7 @@ static void sunxi_hdmi_enable(void)
|
|||
|
||||
#if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
|
||||
|
||||
static void sunxi_tvencoder_mode_set(void)
|
||||
static void sunxi_tvencoder_mode_set(enum sunxi_monitor monitor)
|
||||
{
|
||||
struct sunxi_ccm_reg * const ccm =
|
||||
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
|
||||
|
@ -801,7 +814,7 @@ static void sunxi_tvencoder_mode_set(void)
|
|||
/* Clock on */
|
||||
setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
|
||||
|
||||
switch (sunxi_display.monitor) {
|
||||
switch (monitor) {
|
||||
case sunxi_monitor_vga:
|
||||
tvencoder_mode_set(tve, tve_mode_vga);
|
||||
break;
|
||||
|
@ -896,26 +909,28 @@ static void sunxi_engines_init(void)
|
|||
sunxi_drc_init();
|
||||
}
|
||||
|
||||
static void sunxi_mode_set(const struct ctfb_res_modes *mode,
|
||||
static void sunxi_mode_set(struct sunxi_display_priv *sunxi_display,
|
||||
const struct ctfb_res_modes *mode,
|
||||
unsigned int address)
|
||||
{
|
||||
enum sunxi_monitor monitor = sunxi_display->monitor;
|
||||
int __maybe_unused clk_div, clk_double;
|
||||
struct sunxi_lcdc_reg * const lcdc =
|
||||
(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
|
||||
struct sunxi_tve_reg * __maybe_unused const tve =
|
||||
(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
|
||||
|
||||
switch (sunxi_display.monitor) {
|
||||
switch (sunxi_display->monitor) {
|
||||
case sunxi_monitor_none:
|
||||
break;
|
||||
case sunxi_monitor_dvi:
|
||||
case sunxi_monitor_hdmi:
|
||||
#ifdef CONFIG_VIDEO_HDMI
|
||||
sunxi_composer_mode_set(mode, address);
|
||||
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
|
||||
sunxi_hdmi_mode_set(mode, clk_div, clk_double);
|
||||
sunxi_composer_mode_set(mode, address, monitor);
|
||||
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
|
||||
sunxi_hdmi_mode_set(mode, clk_div, clk_double, monitor);
|
||||
sunxi_composer_enable();
|
||||
lcdc_enable(lcdc, sunxi_display.depth);
|
||||
lcdc_enable(lcdc, sunxi_display->depth);
|
||||
sunxi_hdmi_enable();
|
||||
#endif
|
||||
break;
|
||||
|
@ -930,7 +945,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
|
|||
axp_set_eldo(3, 1800);
|
||||
anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
|
||||
ANX9804_DATA_RATE_1620M,
|
||||
sunxi_display.depth);
|
||||
sunxi_display->depth);
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
|
||||
mdelay(50); /* Wait for lcd controller power on */
|
||||
|
@ -942,10 +957,10 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
|
|||
i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
|
||||
i2c_set_bus_num(orig_i2c_bus);
|
||||
}
|
||||
sunxi_composer_mode_set(mode, address);
|
||||
sunxi_lcdc_tcon0_mode_set(mode, false);
|
||||
sunxi_composer_mode_set(mode, address, monitor);
|
||||
sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, false);
|
||||
sunxi_composer_enable();
|
||||
lcdc_enable(lcdc, sunxi_display.depth);
|
||||
lcdc_enable(lcdc, sunxi_display->depth);
|
||||
#ifdef CONFIG_VIDEO_LCD_SSD2828
|
||||
sunxi_ssd2828_init(mode);
|
||||
#endif
|
||||
|
@ -953,17 +968,17 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
|
|||
break;
|
||||
case sunxi_monitor_vga:
|
||||
#ifdef CONFIG_VIDEO_VGA
|
||||
sunxi_composer_mode_set(mode, address);
|
||||
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
|
||||
sunxi_tvencoder_mode_set();
|
||||
sunxi_composer_mode_set(mode, address, monitor);
|
||||
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1, monitor);
|
||||
sunxi_tvencoder_mode_set(monitor);
|
||||
sunxi_composer_enable();
|
||||
lcdc_enable(lcdc, sunxi_display.depth);
|
||||
lcdc_enable(lcdc, sunxi_display->depth);
|
||||
tvencoder_enable(tve);
|
||||
#elif defined CONFIG_VIDEO_VGA_VIA_LCD
|
||||
sunxi_composer_mode_set(mode, address);
|
||||
sunxi_lcdc_tcon0_mode_set(mode, true);
|
||||
sunxi_composer_mode_set(mode, address, monitor);
|
||||
sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, true);
|
||||
sunxi_composer_enable();
|
||||
lcdc_enable(lcdc, sunxi_display.depth);
|
||||
lcdc_enable(lcdc, sunxi_display->depth);
|
||||
sunxi_vga_external_dac_enable();
|
||||
#endif
|
||||
break;
|
||||
|
@ -972,11 +987,11 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
|
|||
case sunxi_monitor_composite_pal_m:
|
||||
case sunxi_monitor_composite_pal_nc:
|
||||
#ifdef CONFIG_VIDEO_COMPOSITE
|
||||
sunxi_composer_mode_set(mode, address);
|
||||
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
|
||||
sunxi_tvencoder_mode_set();
|
||||
sunxi_composer_mode_set(mode, address, monitor);
|
||||
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
|
||||
sunxi_tvencoder_mode_set(monitor);
|
||||
sunxi_composer_enable();
|
||||
lcdc_enable(lcdc, sunxi_display.depth);
|
||||
lcdc_enable(lcdc, sunxi_display->depth);
|
||||
tvencoder_enable(tve);
|
||||
#endif
|
||||
break;
|
||||
|
@ -999,11 +1014,6 @@ static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -1052,9 +1062,11 @@ static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
|
|||
return sunxi_monitor_none;
|
||||
}
|
||||
|
||||
void *video_hw_init(void)
|
||||
static int sunxi_de_probe(struct udevice *dev)
|
||||
{
|
||||
static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
|
||||
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
|
||||
struct sunxi_display_priv *sunxi_display = dev_get_priv(dev);
|
||||
const struct ctfb_res_modes *mode;
|
||||
struct ctfb_res_modes custom;
|
||||
const char *options;
|
||||
|
@ -1067,10 +1079,8 @@ void *video_hw_init(void)
|
|||
char mon[16];
|
||||
char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
|
||||
|
||||
memset(&sunxi_display, 0, sizeof(struct sunxi_display));
|
||||
|
||||
video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
|
||||
&sunxi_display.depth, &options);
|
||||
&sunxi_display->depth, &options);
|
||||
#ifdef CONFIG_VIDEO_HDMI
|
||||
hpd = video_get_option_int(options, "hpd", 1);
|
||||
hpd_delay = video_get_option_int(options, "hpd_delay", 500);
|
||||
|
@ -1078,35 +1088,35 @@ void *video_hw_init(void)
|
|||
#endif
|
||||
overscan_x = video_get_option_int(options, "overscan_x", -1);
|
||||
overscan_y = video_get_option_int(options, "overscan_y", -1);
|
||||
sunxi_display.monitor = sunxi_get_default_mon(true);
|
||||
sunxi_display->monitor = sunxi_get_default_mon(true);
|
||||
video_get_option_string(options, "monitor", mon, sizeof(mon),
|
||||
sunxi_get_mon_desc(sunxi_display.monitor));
|
||||
sunxi_get_mon_desc(sunxi_display->monitor));
|
||||
for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
|
||||
if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
|
||||
sunxi_display.monitor = i;
|
||||
sunxi_display->monitor = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i > SUNXI_MONITOR_LAST)
|
||||
printf("Unknown monitor: '%s', falling back to '%s'\n",
|
||||
mon, sunxi_get_mon_desc(sunxi_display.monitor));
|
||||
mon, sunxi_get_mon_desc(sunxi_display->monitor));
|
||||
|
||||
#ifdef CONFIG_VIDEO_HDMI
|
||||
/* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
|
||||
if (sunxi_display.monitor == sunxi_monitor_dvi ||
|
||||
sunxi_display.monitor == sunxi_monitor_hdmi) {
|
||||
if (sunxi_display->monitor == sunxi_monitor_dvi ||
|
||||
sunxi_display->monitor == sunxi_monitor_hdmi) {
|
||||
/* Always call hdp_detect, as it also enables clocks, etc. */
|
||||
hdmi_present = (sunxi_hdmi_hpd_detect(hpd_delay) == 1);
|
||||
if (hdmi_present && edid) {
|
||||
printf("HDMI connected: ");
|
||||
if (sunxi_hdmi_edid_get_mode(&custom, true) == 0)
|
||||
if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, true) == 0)
|
||||
mode = &custom;
|
||||
else
|
||||
hdmi_present = false;
|
||||
}
|
||||
/* Fall back to EDID in case HPD failed */
|
||||
if (edid && !hdmi_present) {
|
||||
if (sunxi_hdmi_edid_get_mode(&custom, false) == 0) {
|
||||
if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, false) == 0) {
|
||||
mode = &custom;
|
||||
hdmi_present = true;
|
||||
}
|
||||
|
@ -1114,38 +1124,39 @@ void *video_hw_init(void)
|
|||
/* Shut down when display was not found */
|
||||
if ((hpd || edid) && !hdmi_present) {
|
||||
sunxi_hdmi_shutdown();
|
||||
sunxi_display.monitor = sunxi_get_default_mon(false);
|
||||
sunxi_display->monitor = sunxi_get_default_mon(false);
|
||||
} /* else continue with hdmi/dvi without a cable connected */
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (sunxi_display.monitor) {
|
||||
switch (sunxi_display->monitor) {
|
||||
case sunxi_monitor_none:
|
||||
return NULL;
|
||||
printf("Unknown monitor\n");
|
||||
return -EINVAL;
|
||||
case sunxi_monitor_dvi:
|
||||
case sunxi_monitor_hdmi:
|
||||
if (!sunxi_has_hdmi()) {
|
||||
printf("HDMI/DVI not supported on this board\n");
|
||||
sunxi_display.monitor = sunxi_monitor_none;
|
||||
return NULL;
|
||||
sunxi_display->monitor = sunxi_monitor_none;
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case sunxi_monitor_lcd:
|
||||
if (!sunxi_has_lcd()) {
|
||||
printf("LCD not supported on this board\n");
|
||||
sunxi_display.monitor = sunxi_monitor_none;
|
||||
return NULL;
|
||||
sunxi_display->monitor = sunxi_monitor_none;
|
||||
return -EINVAL;
|
||||
}
|
||||
sunxi_display.depth = video_get_params(&custom, lcd_mode);
|
||||
sunxi_display->depth = video_get_params(&custom, lcd_mode);
|
||||
mode = &custom;
|
||||
break;
|
||||
case sunxi_monitor_vga:
|
||||
if (!sunxi_has_vga()) {
|
||||
printf("VGA not supported on this board\n");
|
||||
sunxi_display.monitor = sunxi_monitor_none;
|
||||
return NULL;
|
||||
sunxi_display->monitor = sunxi_monitor_none;
|
||||
return -EINVAL;
|
||||
}
|
||||
sunxi_display.depth = 18;
|
||||
sunxi_display->depth = 18;
|
||||
break;
|
||||
case sunxi_monitor_composite_pal:
|
||||
case sunxi_monitor_composite_ntsc:
|
||||
|
@ -1153,85 +1164,99 @@ void *video_hw_init(void)
|
|||
case sunxi_monitor_composite_pal_nc:
|
||||
if (!sunxi_has_composite()) {
|
||||
printf("Composite video not supported on this board\n");
|
||||
sunxi_display.monitor = sunxi_monitor_none;
|
||||
return NULL;
|
||||
sunxi_display->monitor = sunxi_monitor_none;
|
||||
return -EINVAL;
|
||||
}
|
||||
if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
|
||||
sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
|
||||
if (sunxi_display->monitor == sunxi_monitor_composite_pal ||
|
||||
sunxi_display->monitor == sunxi_monitor_composite_pal_nc)
|
||||
mode = &composite_video_modes[0];
|
||||
else
|
||||
mode = &composite_video_modes[1];
|
||||
sunxi_display.depth = 24;
|
||||
sunxi_display->depth = 24;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Yes these defaults are quite high, overscan on composite sucks... */
|
||||
if (overscan_x == -1)
|
||||
overscan_x = sunxi_is_composite() ? 32 : 0;
|
||||
overscan_x = sunxi_is_composite(sunxi_display->monitor) ? 32 : 0;
|
||||
if (overscan_y == -1)
|
||||
overscan_y = sunxi_is_composite() ? 20 : 0;
|
||||
overscan_y = sunxi_is_composite(sunxi_display->monitor) ? 20 : 0;
|
||||
|
||||
sunxi_display.fb_size =
|
||||
(mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
|
||||
sunxi_display->fb_size = plat->size;
|
||||
overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
|
||||
/* We want to keep the fb_base for simplefb page aligned, where as
|
||||
* the sunxi dma engines will happily accept an unaligned address. */
|
||||
if (overscan_offset)
|
||||
sunxi_display.fb_size += 0x1000;
|
||||
|
||||
if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
|
||||
printf("Error need %dkB for fb, but only %dkB is reserved\n",
|
||||
sunxi_display.fb_size >> 10,
|
||||
CONFIG_SUNXI_MAX_FB_SIZE >> 10);
|
||||
return NULL;
|
||||
}
|
||||
sunxi_display->fb_size += 0x1000;
|
||||
|
||||
printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
|
||||
mode->xres, mode->yres,
|
||||
(mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
|
||||
sunxi_get_mon_desc(sunxi_display.monitor),
|
||||
sunxi_get_mon_desc(sunxi_display->monitor),
|
||||
overscan_x, overscan_y);
|
||||
|
||||
gd->fb_base = gd->bd->bi_dram[0].start +
|
||||
gd->bd->bi_dram[0].size - sunxi_display.fb_size;
|
||||
sunxi_display->fb_addr = plat->base;
|
||||
sunxi_engines_init();
|
||||
|
||||
#ifdef CONFIG_EFI_LOADER
|
||||
efi_add_memory_map(gd->fb_base, sunxi_display.fb_size,
|
||||
efi_add_memory_map(sunxi_display->fb_addr, sunxi_display->fb_size,
|
||||
EFI_RESERVED_MEMORY_TYPE);
|
||||
#endif
|
||||
|
||||
fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
|
||||
sunxi_display.fb_addr = gd->fb_base;
|
||||
fb_dma_addr = sunxi_display->fb_addr - CONFIG_SYS_SDRAM_BASE;
|
||||
if (overscan_offset) {
|
||||
fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
|
||||
sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
|
||||
memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
|
||||
flush_cache(gd->fb_base, sunxi_display.fb_size);
|
||||
sunxi_display->fb_addr += ALIGN(overscan_offset, 0x1000);
|
||||
memset((void *)sunxi_display->fb_addr, 0, sunxi_display->fb_size);
|
||||
flush_cache(sunxi_display->fb_addr, sunxi_display->fb_size);
|
||||
}
|
||||
sunxi_mode_set(mode, fb_dma_addr);
|
||||
sunxi_mode_set(sunxi_display, mode, fb_dma_addr);
|
||||
|
||||
/*
|
||||
* These are the only members of this structure that are used. All the
|
||||
* others are driver specific. The pitch is stored in plnSizeX.
|
||||
*/
|
||||
graphic_device->frameAdrs = sunxi_display.fb_addr;
|
||||
graphic_device->gdfIndex = GDF_32BIT_X888RGB;
|
||||
graphic_device->gdfBytesPP = 4;
|
||||
graphic_device->winSizeX = mode->xres - 2 * overscan_x;
|
||||
graphic_device->winSizeY = mode->yres - 2 * overscan_y;
|
||||
graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
|
||||
/* The members of struct video_priv to be set by the driver. */
|
||||
uc_priv->bpix = VIDEO_BPP32;
|
||||
uc_priv->xsize = mode->xres;
|
||||
uc_priv->ysize = mode->yres;
|
||||
|
||||
return graphic_device;
|
||||
video_set_flush_dcache(dev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sunxi_de_bind(struct udevice *dev)
|
||||
{
|
||||
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
|
||||
|
||||
plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * VNBYTES(LCD_MAX_LOG2_BPP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct video_ops sunxi_de_ops = {
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sunxi_de) = {
|
||||
.name = "sunxi_de",
|
||||
.id = UCLASS_VIDEO,
|
||||
.ops = &sunxi_de_ops,
|
||||
.bind = sunxi_de_bind,
|
||||
.probe = sunxi_de_probe,
|
||||
.priv_auto = sizeof(struct sunxi_display_priv),
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
U_BOOT_DRVINFO(sunxi_de) = {
|
||||
.name = "sunxi_de"
|
||||
};
|
||||
|
||||
/*
|
||||
* Simplefb support.
|
||||
*/
|
||||
#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
|
||||
int sunxi_simplefb_setup(void *blob)
|
||||
{
|
||||
static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
|
||||
struct sunxi_display_priv *sunxi_display;
|
||||
struct video_priv *uc_priv;
|
||||
struct udevice *de;
|
||||
int offset, ret;
|
||||
u64 start, size;
|
||||
const char *pipeline = NULL;
|
||||
|
@ -1242,7 +1267,19 @@ int sunxi_simplefb_setup(void *blob)
|
|||
#define PIPELINE_PREFIX
|
||||
#endif
|
||||
|
||||
switch (sunxi_display.monitor) {
|
||||
ret = uclass_find_device_by_name(UCLASS_VIDEO, "sunxi_de", &de);
|
||||
if (ret) {
|
||||
printf("DE not present\n");
|
||||
return 0;
|
||||
} else if (!device_active(de)) {
|
||||
printf("DE is present but not probed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uc_priv = dev_get_uclass_priv(de);
|
||||
sunxi_display = dev_get_priv(de);
|
||||
|
||||
switch (sunxi_display->monitor) {
|
||||
case sunxi_monitor_none:
|
||||
return 0;
|
||||
case sunxi_monitor_dvi:
|
||||
|
@ -1280,16 +1317,17 @@ int sunxi_simplefb_setup(void *blob)
|
|||
* linux/arch/arm/mm/ioremap.c around line 301.
|
||||
*/
|
||||
start = gd->bd->bi_dram[0].start;
|
||||
size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
|
||||
size = sunxi_display->fb_addr - start;
|
||||
ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
|
||||
if (ret) {
|
||||
eprintf("Cannot setup simplefb: Error reserving memory\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
|
||||
graphic_device->winSizeX, graphic_device->winSizeY,
|
||||
graphic_device->plnSizeX, "x8r8g8b8");
|
||||
ret = fdt_setup_simplefb_node(blob, offset, sunxi_display->fb_addr,
|
||||
uc_priv->xsize, uc_priv->ysize,
|
||||
VNBYTES(uc_priv->bpix) * uc_priv->xsize,
|
||||
"x8r8g8b8");
|
||||
if (ret)
|
||||
eprintf("Cannot setup simplefb: Error setting properties\n");
|
||||
|
||||
|
|
|
@ -223,23 +223,6 @@ extern int soft_i2c_gpio_scl;
|
|||
#define CONFIG_VIDEO_LCD_I2C_BUS -1 /* NA, but necessary to compile */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VIDEO_SUNXI
|
||||
/*
|
||||
* The amount of RAM to keep free at the top of RAM when relocating u-boot,
|
||||
* to use as framebuffer. This must be a multiple of 4096.
|
||||
*/
|
||||
#define CONFIG_SUNXI_MAX_FB_SIZE (16 << 20)
|
||||
|
||||
#define CONFIG_VIDEO_LOGO
|
||||
#define CONFIG_VIDEO_STD_TIMINGS
|
||||
#define CONFIG_I2C_EDID
|
||||
#define VIDEO_LINE_LEN (pGD->plnSizeX)
|
||||
|
||||
/* allow both serial and cfb console. */
|
||||
/* stop x86 thinking in cfbconsole from trying to init a pc keyboard */
|
||||
|
||||
#endif /* CONFIG_VIDEO_SUNXI */
|
||||
|
||||
/* Ethernet support */
|
||||
|
||||
#ifdef CONFIG_USB_EHCI_HCD
|
||||
|
@ -401,11 +384,7 @@ extern int soft_i2c_gpio_scl;
|
|||
"stdin=serial\0"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VIDEO
|
||||
#define CONSOLE_STDOUT_SETTINGS \
|
||||
"stdout=serial,vga\0" \
|
||||
"stderr=serial,vga\0"
|
||||
#elif CONFIG_DM_VIDEO
|
||||
#ifdef CONFIG_DM_VIDEO
|
||||
#define CONSOLE_STDOUT_SETTINGS \
|
||||
"stdout=serial,vidconsole\0" \
|
||||
"stderr=serial,vidconsole\0"
|
||||
|
|
|
@ -1636,7 +1636,6 @@ CONFIG_STV0991
|
|||
CONFIG_STV0991_HZ
|
||||
CONFIG_STV0991_HZ_CLOCK
|
||||
CONFIG_ST_SMI
|
||||
CONFIG_SUNXI_MAX_FB_SIZE
|
||||
CONFIG_SXNI855T
|
||||
CONFIG_SYSFLAGS_ADDR
|
||||
CONFIG_SYSFS
|
||||
|
|
Loading…
Reference in a new issue