From patchwork Wed Jun 17 20:24:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 1395 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-pj1-f72.google.com (mail-pj1-f72.google.com [209.85.216.72]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id AF4F53F03F for ; Wed, 17 Jun 2020 22:25:35 +0200 (CEST) Received: by mail-pj1-f72.google.com with SMTP id d14sf2364660pjw.5 for ; Wed, 17 Jun 2020 13:25:35 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1592425534; cv=pass; d=google.com; s=arc-20160816; b=rDE24XFtoaNNyU3l+e/tmEuei7mEBwaXjGGy+jwnbIKR/I3qQwWhPUUN37N1fdyozb zIrQioMOZMEzxA15ANjcSlD3SG2Nia0ngP1h+ZIgKkM+/xKICPXoY+JAOMR9CCdKX8xi /Hlp6oFmh4lDcvhMEOaranKSjeiLJ15fBvzW/vOokHbCAauqmQ8Bowycccypyh/HgZyG EMaCahi5HmzhhNqyOozf8TSg8nTFF/+5SHl9Mvd/M5R6nYpoqgjd9Gye/MJbTbPmDwq5 TqnyVjkNbMmWKJb5Ulzv5II9y6MDk5C4bH2sT5CuFVTbIcMfFqScPy3WmYSUEdgkctjG lq6w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=m37AnqFsW3RaktMn8vblbo1kE3v1xVJUXV71t7HN5XE=; b=a6S56ZN+HWe7ie4IlR6/VZDZnFoe/0IzQHPZaFTHCPcmnZi0CEneuOOiuCSwj+2EfO +yyMPC/Qz912XXWxaVYeGRWmXz8n3osjcgiXuHMNRQCfN2ssOAvf5uJE6oSN0pBoMXiB DiW9t7Rw0Q/Co5b2sUTMQ4IGUR143jpSOj59YKFTLI74GerwCliWE/DOlK7MYp2oXbi8 KImkNKfd95CmFJilNWjSBx3GesV9BV99J4vpzo35YZPhQvRoB8QI5mLS6szWRTdC9Rt6 6ctnlzGR2unEUTt00yCtvmqbno/+OoPwd++jh5SGhaIy0lNyHfoFnpP3zvLguIsXNH+f Lvzg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=h8R6KEH2; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=m37AnqFsW3RaktMn8vblbo1kE3v1xVJUXV71t7HN5XE=; b=NQJVpRXsD265TdR/HbQiUkDIom57+RtNBadV2tJOQsvWATag/mTc5qF99DvQHsg7c1 MMC++oTSCTjdKb7SSeqUltfBdPEdjZgZS0LRSZNgRYMUvCXNkeSO/vJJeaYVtYEbhYS+ MPDvKAzikqYIzVZux7mFAvbibKFM90xC/JSws= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive :list-unsubscribe; bh=m37AnqFsW3RaktMn8vblbo1kE3v1xVJUXV71t7HN5XE=; b=SRbM43WTcBJzzMeIo28U2gPpqwQcODflG9TWuXESOlKQRX1GZS+3iry5+PfiL9bh4q kVhkuKOSbyubynyn8aaJjTShwxjyGlOae6NeJrV+3cuV+c14NO7r0R73GY7MDKbNy5UW DoAJ7kVBJq2JaIO5XVeVzNlva42q58VhxLxmc55cOC8b+lVzaFPA7ylq2wqfDzzRDAyC t1+Kbf4KSOJfSfPiJPokik5fouoGI5uJlY6GUPClRQWWCiIUW5ENnR0lGb6uNVIMmAYj pDb+H5GQwIaO/fBozkq3cwDDxPDfTYUsMagucCRNgwOrJ+Ma6lP4E54u1VQcL+vaxxTR IyyQ== X-Gm-Message-State: AOAM531u8WjXYJu0skRZS6Fp4fuACFv3DeFBB5eGSGpl/FPbMsS5u0vv TEMgId9dXR7bQVZ20I+tLDucumYm X-Google-Smtp-Source: ABdhPJynRGqnZrm7+l81ppxLx4IYIBuS6XRmgxeHF0kycQxO5hR+q4jgw4Jeeye/6yfAL1ynEBaN3A== X-Received: by 2002:a63:7d1:: with SMTP id 200mr483066pgh.117.1592425534427; Wed, 17 Jun 2020 13:25:34 -0700 (PDT) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a62:8858:: with SMTP id l85ls1079657pfd.6.gmail; Wed, 17 Jun 2020 13:25:34 -0700 (PDT) X-Received: by 2002:a62:68c7:: with SMTP id d190mr412303pfc.175.1592425533797; Wed, 17 Jun 2020 13:25:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1592425533; cv=none; d=google.com; s=arc-20160816; b=cClCaoZSkG9HgoHco+f0bB7pox73bj6uE/TNa/QHl1O4HUHXV5zl74BrgPGQnejwbz UfuyTvCRzKIaSuhM7nyqUS2ti6qan8lSzlmZ0U0yHrr5rwQaCDA4KiyJV+LVdsl/M3DL 617pJz7KlMaw66aQp09I5soHJLtzwvThKvuqEPK11QdddNA5KKcPO/I1QYAFefPff4in agIquBc6um65lnO7YfdtU9d6nG3qfpMLYsORcqK0NvdnX/rVPL5HOgi8ICaCypOcGlCU 4HWXuSRAIPxwXTOosKHjuw5SPPD8TZQmiwMOon0UbpTTk2XhgQZpFvsnqFET+aPh2UB/ Fr7g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=xhLYdCsbUS9COceIQnqLX4v64kYEWYIw7/8945D7Pjg=; b=htrdvJ/4kGP9HMc0On+Gad123M0478w0/GbMwZo/u9rlLg+F7voT0OS2+2UkW15M0U 9B2xhCRQFuDhHFaEa+NNaFoeFm71s4T9u6OdsMgcAa7lAaP2+Tkqj8pfFYct9v/bdFJ5 QybbT8W8viJo5l5+3DInR9NxdHD1xpuSGsHuxaL0xw2Pm8icyEiqm8gddhyi9gwOc5tn lD19IODOSw4sCs7r9IKxh8W2lnN/j28CSzJPFjG/Fx1a9jbMbz2iYyfl3KN/yzo+NGMO qIMXXbQgRQP0FQssmRlkFi/2bzepiI8PB0uhTIs0jjhAUuCRBjxQo+dzbl2tQkxzEg87 +TQQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=h8R6KEH2; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id v12sor1248375pfu.62.2020.06.17.13.25.33 for (Google Transport Security); Wed, 17 Jun 2020 13:25:33 -0700 (PDT) Received-SPF: pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; X-Received: by 2002:a62:c105:: with SMTP id i5mr472971pfg.250.1592425533273; Wed, 17 Jun 2020 13:25:33 -0700 (PDT) Received: from localhost.localdomain ([2405:201:c809:c7d5:99e:1516:4428:c83b]) by smtp.gmail.com with ESMTPSA id b1sm376613pjc.33.2020.06.17.13.25.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Jun 2020 13:25:32 -0700 (PDT) From: Jagan Teki To: Anatolij Gustschin , Maxime Ripard , u-boot@lists.denx.de Cc: Hans de Goede , Zoltan Herpai , Aleksei Mamlin , Priit Laes , Paul Kocialkowski , Chen-Yu Tsai , Phil Han , Siarhei Siamashka , Peter Korsgaard , Stefan Mavrodiev , Icenowy Zheng , Quentin Schulz , FUKAUMI Naoki , Marcus Cooper , Stefan Mavrodiev , Iain Paton , Olliver Schinagl , Ian Campbell , Stefan Roese , Jelle de Jong , Adam Sampson , Tom Rini , linux-sunxi@googlegroups.com, linux-amarula@amarulasolutions.com, Jagan Teki Subject: [PATCH v2 3/3] video: sunxi_display: Convert to DM_VIDEO Date: Thu, 18 Jun 2020 01:54:37 +0530 Message-Id: <20200617202437.301108-4-jagan@amarulasolutions.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200617202437.301108-1-jagan@amarulasolutions.com> References: <20200617202437.301108-1-jagan@amarulasolutions.com> MIME-Version: 1.0 X-Original-Sender: jagan@amarulasolutions.com X-Original-Authentication-Results: mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=h8R6KEH2; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com Content-Type: text/plain; charset="UTF-8" Precedence: list Mailing-list: list linux-amarula@amarulasolutions.com; contact linux-amarula+owners@amarulasolutions.com List-ID: X-Spam-Checked-In-Group: linux-amarula@amarulasolutions.com X-Google-Group-Id: 476853432473 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , 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. ==================================================== So let's live these boards on the tree before the video maintainer removes it by converting in to DM_VIDEO. Tested in Bananapi M1+ Plus 1920x1200 HDMI out. Signed-off-by: Jagan Teki --- Changes for v2: - add BMP support arch/arm/mach-sunxi/Kconfig | 4 +- drivers/video/sunxi/sunxi_display.c | 264 ++++++++++++++++------------ include/configs/sunxi-common.h | 17 -- scripts/config_whitelist.txt | 1 - 4 files changed, 157 insertions(+), 129 deletions(-) diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index be0822bfb7..7d2fb55ff0 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -758,8 +758,10 @@ config VIDEO_SUNXI depends on !MACH_SUN9I depends on !MACH_SUN50I depends on !MACH_SUN50I_H6 - select VIDEO + select DM_VIDEO + select DISPLAY imply VIDEO_DT_SIMPLEFB + imply CMD_BMP default y ---help--- Say Y here to add support for using a cfb console on the HDMI, LCD diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index f52aba4d21..fb51b0c5ba 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -7,6 +7,8 @@ */ #include +#include +#include #include #include #include @@ -28,7 +30,9 @@ #include #include #include +#include #include +#include #include "../videomodes.h" #include "../anx9804.h" #include "../hitachi_tx18d42vm_lcd.h" @@ -45,6 +49,13 @@ DECLARE_GLOBAL_DATA_PTR; +enum { + /* Maximum LCD size we support */ + LCD_MAX_WIDTH = 3840, + LCD_MAX_HEIGHT = 2160, + LCD_MAX_LOG2_BPP = VIDEO_BPP32, +}; + enum sunxi_monitor { sunxi_monitor_none, sunxi_monitor_dvi, @@ -59,12 +70,11 @@ enum sunxi_monitor { #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc struct sunxi_display { - GraphicDevice graphic_device; 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 +224,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 *sunxi_display, + struct ctfb_res_modes *mode, bool verbose_mode) { struct edid1_info edid1; @@ -291,14 +302,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 +425,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 +484,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 +514,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 +628,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 *sunxi_display, + const struct ctfb_res_modes *mode, bool for_ext_vga_dac) { struct sunxi_lcdc_reg * const lcdc = @@ -643,17 +656,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 +677,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 +685,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 +739,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 +749,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 +804,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 +816,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 +911,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 *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 +947,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 +959,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 +970,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 +989,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 +1016,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 +1064,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_platdata *plat = dev_get_uclass_platdata(dev); + struct sunxi_display *sunxi_display = dev_get_priv(dev); const struct ctfb_res_modes *mode; struct ctfb_res_modes custom; const char *options; @@ -1067,10 +1081,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 +1090,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 +1126,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 +1166,103 @@ 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 += (overscan_offset + 0xfff) & ~0xfff; + 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; - - return graphic_device; + uc_priv->bpix = VIDEO_BPP32; + uc_priv->xsize = mode->xres; + uc_priv->ysize = mode->yres; + + video_set_flush_dcache(dev, 1); + + return 0; +} + +static int sunxi_de_bind(struct udevice *dev) +{ + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + + plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * + (1 << LCD_MAX_LOG2_BPP) / 8; + + 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_alloc_size = sizeof(struct sunxi_display), + .flags = DM_FLAG_PRE_RELOC, +}; + +U_BOOT_DEVICE(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 *sunxi_display; + struct video_priv *uc_priv; + struct udevice *de; int offset, ret; u64 start, size; const char *pipeline = NULL; @@ -1242,7 +1273,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 +1323,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 = gd->bd->bi_dram[0].size - sunxi_display->fb_size; 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"); diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 308d7a42aa..affedda46c 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -253,23 +253,6 @@ extern int soft_i2c_gpio_scl; #endif #endif /* ifdef CONFIG_REQUIRE_SERIAL_CONSOLE */ -#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 */ - #if CONFIG_IS_ENABLED(CMD_BMP) # define CONFIG_VIDEO_BMP_RLE8 # define CONFIG_SPLASH_SCREEN diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index f6bf6f2474..30a101638e 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -1724,7 +1724,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