From patchwork Tue Jan 29 12:42:28 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikita Kiryanov X-Patchwork-Id: 216522 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id BCE812C0086 for ; Tue, 29 Jan 2013 23:46:53 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D987E4A1EA; Tue, 29 Jan 2013 13:46:33 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qaAYEl3sUJtU; Tue, 29 Jan 2013 13:46:33 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 7AA664A1D5; Tue, 29 Jan 2013 13:45:38 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 3BE584A1A7 for ; Tue, 29 Jan 2013 13:43:45 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id YkJAakqaQtcA for ; Tue, 29 Jan 2013 13:43:29 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from compulab.co.il (softlayer.compulab.co.il [50.23.254.55]) by theia.denx.de (Postfix) with ESMTPS id 1435F4A182 for ; Tue, 29 Jan 2013 13:42:53 +0100 (CET) Received: from [62.90.235.247] (port=38290 helo=zimbra-mta.compulab.co.il) by softlayer.compulab.co.il with esmtp (Exim 4.80) (envelope-from ) id 1U0AWU-00088k-AI; Tue, 29 Jan 2013 14:42:48 +0200 Received: from localhost (localhost.localdomain [127.0.0.1]) by zimbra-mta.compulab.co.il (Postfix) with ESMTP id F0BEC644194; Tue, 29 Jan 2013 14:42:41 +0200 (IST) X-Virus-Scanned: amavisd-new at compulab.co.il Received: from zimbra-mta.compulab.co.il ([127.0.0.1]) by localhost (zimbra-mta.compulab.co.il [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aVuW-LRf6QhS; Tue, 29 Jan 2013 14:42:40 +0200 (IST) Received: from compulab.co.il (nikita-pc.compulab.local [192.168.11.211]) by zimbra-mta.compulab.co.il (Postfix) with ESMTP id 36CE164419D; Tue, 29 Jan 2013 14:42:40 +0200 (IST) Received: by compulab.co.il (Postfix, from userid 1000) id CA025FC069F; Tue, 29 Jan 2013 14:42:40 +0200 (IST) From: Nikita Kiryanov To: u-boot@lists.denx.de Date: Tue, 29 Jan 2013 14:42:28 +0200 Message-Id: <1359463349-11649-7-git-send-email-nikita@compulab.co.il> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1359463349-11649-1-git-send-email-nikita@compulab.co.il> References: <1359463349-11649-1-git-send-email-nikita@compulab.co.il> X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - softlayer.compulab.co.il X-AntiAbuse: Original Domain - lists.denx.de X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - compulab.co.il X-Get-Message-Sender-Via: softlayer.compulab.co.il: acl_c_relayhosts_text_entry: nikita@compulab.co.il|compulab.co.il Cc: jeroen@myspectrum.nl, trini@ti.com Subject: [U-Boot] [PATCH V2 6/7] cm-t35: add support for user defined lcd parameters X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Add support for user defined lcd parameters for cm-t35 splash screen. Signed-off-by: Nikita Kiryanov Signed-off-by: Igor Grinberg --- Changes in V2: - Set gfx_format to GFXFORMAT_RGB16 after parsing custom lcd settings. board/cm_t35/display.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 211 insertions(+), 3 deletions(-) diff --git a/board/cm_t35/display.c b/board/cm_t35/display.c index da7784a..6d46762 100644 --- a/board/cm_t35/display.c +++ b/board/cm_t35/display.c @@ -3,6 +3,8 @@ * * Authors: Nikita Kiryanov * + * Parsing code based on linux/drivers/video/pxafb.c + * * See file CREDITS for list of people who contributed to this * project. * @@ -33,6 +35,7 @@ DECLARE_GLOBAL_DATA_PTR; enum display_type { NONE, DVI, + DVI_CUSTOM, }; /* @@ -150,6 +153,206 @@ static enum display_type set_dvi_preset(const struct panel_config preset, } /* + * parse_mode() - parse the mode parameter of custom lcd settings + * + * @mode: x + * + * Returns -1 on error, 0 on success. + */ +static int parse_mode(const char *mode) +{ + unsigned int modelen = strlen(mode); + int res_specified = 0; + unsigned int xres = 0, yres = 0; + int yres_specified = 0; + int i; + + for (i = modelen - 1; i >= 0; i--) { + switch (mode[i]) { + case 'x': + if (!yres_specified) { + yres = simple_strtoul(&mode[i + 1], NULL, 0); + yres_specified = 1; + } else { + goto done_parsing; + } + + break; + case '0' ... '9': + break; + default: + goto done_parsing; + } + } + + if (i < 0 && yres_specified) { + xres = simple_strtoul(mode, NULL, 0); + res_specified = 1; + } + +done_parsing: + if (res_specified) { + set_resolution_params(xres, yres); + } else { + printf("LCD: invalid mode: %s\n", mode); + return -1; + } + + return 0; +} + +#define PIXEL_CLK_NUMERATOR (26 * 432 / 39) +/* + * parse_pixclock() - Parse the pixclock parameter of custom lcd settings + * + * @pixclock: the desired pixel clock + * + * Returns -1 on error, 0 on success. + * + * Handling the pixel_clock: + * + * Pixel clock is defined in the OMAP35x TRM as follows: + * pixel_clock = + * (SYS_CLK * 2 * PRCM.CM_CLKSEL2_PLL[18:8]) / + * (DSS.DISPC_DIVISOR[23:16] * DSS.DISPC_DIVISOR[6:0] * + * PRCM.CM_CLKSEL_DSS[4:0] * (PRCM.CM_CLKSEL2_PLL[6:0] + 1)) + * + * In practice, this means that in order to set the + * divisor for the desired pixel clock one needs to + * solve the following equation: + * + * 26 * 432 / (39 * ) = DSS.DISPC_DIVISOR[6:0] + * + * NOTE: the explicit equation above is reduced. Do not + * try to infer anything from these numbers. + */ +static int parse_pixclock(char *pixclock) +{ + int divisor, pixclock_val; + char *pixclk_start = pixclock; + + pixclock_val = simple_strtoul(pixclock, &pixclock, 10); + divisor = DIV_ROUND_UP(PIXEL_CLK_NUMERATOR, pixclock_val); + /* 0 and 1 are illegal values for PCD */ + if (divisor <= 1) + divisor = 2; + + panel_cfg.divisor = divisor | (1 << 16); + if (pixclock[0] != '\0') { + printf("LCD: invalid value for pixclock:%s\n", pixclk_start); + return -1; + } + + return 0; +} + +/* + * parse_setting() - parse a single setting of custom lcd parameters + * + * @setting: The custom lcd setting : + * + * Returns -1 on failure, 0 on success. + */ +static int parse_setting(char *setting) +{ + int num_val; + char *setting_start = setting; + + if (!strncmp(setting, "mode:", 5)) { + return parse_mode(setting + 5); + } else if (!strncmp(setting, "pixclock:", 9)) { + return parse_pixclock(setting + 9); + } else if (!strncmp(setting, "left:", 5)) { + num_val = simple_strtoul(setting + 5, &setting, 0); + panel_cfg.timing_h |= DSS_HBP(num_val); + } else if (!strncmp(setting, "right:", 6)) { + num_val = simple_strtoul(setting + 6, &setting, 0); + panel_cfg.timing_h |= DSS_HFP(num_val); + } else if (!strncmp(setting, "upper:", 6)) { + num_val = simple_strtoul(setting + 6, &setting, 0); + panel_cfg.timing_v |= DSS_VBP(num_val); + } else if (!strncmp(setting, "lower:", 6)) { + num_val = simple_strtoul(setting + 6, &setting, 0); + panel_cfg.timing_v |= DSS_VFP(num_val); + } else if (!strncmp(setting, "hsynclen:", 9)) { + num_val = simple_strtoul(setting + 9, &setting, 0); + panel_cfg.timing_h |= DSS_HSW(num_val); + } else if (!strncmp(setting, "vsynclen:", 9)) { + num_val = simple_strtoul(setting + 9, &setting, 0); + panel_cfg.timing_v |= DSS_VSW(num_val); + } else if (!strncmp(setting, "hsync:", 6)) { + if (simple_strtoul(setting + 6, &setting, 0) == 0) + panel_cfg.pol_freq |= DSS_IHS; + else + panel_cfg.pol_freq &= ~DSS_IHS; + } else if (!strncmp(setting, "vsync:", 6)) { + if (simple_strtoul(setting + 6, &setting, 0) == 0) + panel_cfg.pol_freq |= DSS_IVS; + else + panel_cfg.pol_freq &= ~DSS_IVS; + } else if (!strncmp(setting, "outputen:", 9)) { + if (simple_strtoul(setting + 9, &setting, 0) == 0) + panel_cfg.pol_freq |= DSS_IEO; + else + panel_cfg.pol_freq &= ~DSS_IEO; + } else if (!strncmp(setting, "pixclockpol:", 12)) { + if (simple_strtoul(setting + 12, &setting, 0) == 0) + panel_cfg.pol_freq |= DSS_IPC; + else + panel_cfg.pol_freq &= ~DSS_IPC; + } else if (!strncmp(setting, "active", 6)) { + panel_cfg.panel_type = ACTIVE_DISPLAY; + return 0; /* Avoid sanity check below */ + } else if (!strncmp(setting, "passive", 7)) { + panel_cfg.panel_type = PASSIVE_DISPLAY; + return 0; /* Avoid sanity check below */ + } else if (!strncmp(setting, "display:", 8)) { + if (!strncmp(setting + 8, "dvi", 3)) { + lcd_def = DVI_CUSTOM; + return 0; /* Avoid sanity check below */ + } + } else { + printf("LCD: unknown option %s\n", setting_start); + return -1; + } + + if (setting[0] != '\0') { + printf("LCD: invalid value for %s\n", setting_start); + return -1; + } + + return 0; +} + +/* + * env_parse_customlcd() - parse custom lcd params from an environment variable. + * + * @custom_lcd_params: The environment variable containing the lcd params. + * + * Returns -1 on failure, 0 on success. + */ +static int parse_customlcd(char *custom_lcd_params) +{ + char params_cpy[160]; + char *setting; + + strncpy(params_cpy, custom_lcd_params, 160); + setting = strtok(params_cpy, ","); + while (setting) { + if (parse_setting(setting) < 0) + return -1; + + setting = strtok(NULL, ","); + } + + /* Currently we don't support changing this via custom lcd params */ + panel_cfg.data_lines = LCD_INTERFACE_24_BIT; + panel_cfg.gfx_format = GFXFORMAT_RGB16; /* See dvi predefines note */ + + return 0; +} + +/* * env_parse_displaytype() - parse display type. * * Parses the environment variable "displaytype", which contains the @@ -187,14 +390,19 @@ void *lcd_console_address; void lcd_ctrl_init(void *lcdbase) { struct prcm *prcm = (struct prcm *)PRCM_BASE; + char *custom_lcd; char *displaytype = getenv("displaytype"); if (displaytype == NULL) return; lcd_def = env_parse_displaytype(displaytype); - if (lcd_def == NONE) - return; + /* If we did not recognize the preset, check if it's an env variable */ + if (lcd_def == NONE) { + custom_lcd = getenv(displaytype); + if (custom_lcd == NULL || parse_customlcd(custom_lcd) < 0) + return; + } panel_cfg.frame_buffer = lcdbase; omap3_dss_panel_config(&panel_cfg); @@ -209,7 +417,7 @@ void lcd_ctrl_init(void *lcdbase) void lcd_enable(void) { - if (lcd_def == DVI) { + if (lcd_def == DVI || lcd_def == DVI_CUSTOM) { gpio_direction_output(54, 0); /* Turn on DVI */ omap3_dss_enable(); }