From 689be5f83c17af6221764ab3a3890510af3c9022 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Mon, 16 Sep 2013 21:49:58 +0300 Subject: cm-t35: move the eeprom code to common place Compulab boards use the same eeprom code, so move the eeprom related code to live under board/compulab/common directory. Also make several adjustments to eeprom functions namespace, so it will be generic for compulab boards. Signed-off-by: Igor Grinberg Tested-by: Nikita Kiryanov --- board/compulab/cm_t35/Makefile | 1 - board/compulab/cm_t35/cm_t35.c | 7 +-- board/compulab/cm_t35/eeprom.c | 118 ---------------------------------------- board/compulab/cm_t35/eeprom.h | 27 --------- board/compulab/common/Makefile | 35 ++++++++++++ board/compulab/common/eeprom.c | 121 +++++++++++++++++++++++++++++++++++++++++ board/compulab/common/eeprom.h | 27 +++++++++ 7 files changed, 186 insertions(+), 150 deletions(-) delete mode 100644 board/compulab/cm_t35/eeprom.c delete mode 100644 board/compulab/cm_t35/eeprom.h create mode 100644 board/compulab/common/Makefile create mode 100644 board/compulab/common/eeprom.c create mode 100644 board/compulab/common/eeprom.h (limited to 'board/compulab') diff --git a/board/compulab/cm_t35/Makefile b/board/compulab/cm_t35/Makefile index 6d07947d51..8b922b3d7e 100644 --- a/board/compulab/cm_t35/Makefile +++ b/board/compulab/cm_t35/Makefile @@ -11,7 +11,6 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).o -COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += eeprom.o COBJS-$(CONFIG_LCD) += display.o COBJS := cm_t35.o leds.o $(COBJS-y) diff --git a/board/compulab/cm_t35/cm_t35.c b/board/compulab/cm_t35/cm_t35.c index 3caa5be845..a6d4aba250 100644 --- a/board/compulab/cm_t35/cm_t35.c +++ b/board/compulab/cm_t35/cm_t35.c @@ -33,7 +33,7 @@ #include #include -#include "eeprom.h" +#include "../common/eeprom.h" DECLARE_GLOBAL_DATA_PTR; @@ -160,7 +160,7 @@ static u32 cm_t3x_rev; u32 get_board_rev(void) { if (!cm_t3x_rev) - cm_t3x_rev = cm_t3x_eeprom_get_board_rev(); + cm_t3x_rev = cl_eeprom_get_board_rev(); return cm_t3x_rev; }; @@ -509,7 +509,7 @@ static int handle_mac_address(void) if (rc) return 0; - rc = cm_t3x_eeprom_read_mac_addr(enetaddr); + rc = cl_eeprom_read_mac_addr(enetaddr); if (rc) return rc; @@ -598,5 +598,4 @@ int ehci_hcd_stop(void) { return omap_ehci_hcd_stop(); } - #endif /* CONFIG_USB_EHCI_OMAP */ diff --git a/board/compulab/cm_t35/eeprom.c b/board/compulab/cm_t35/eeprom.c deleted file mode 100644 index df91acd4a7..0000000000 --- a/board/compulab/cm_t35/eeprom.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * (C) Copyright 2011 CompuLab, Ltd. - * - * Authors: Nikita Kiryanov - * Igor Grinberg - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -#define EEPROM_LAYOUT_VER_OFFSET 44 -#define BOARD_SERIAL_OFFSET 20 -#define BOARD_SERIAL_OFFSET_LEGACY 8 -#define BOARD_REV_OFFSET 0 -#define BOARD_REV_OFFSET_LEGACY 6 -#define BOARD_REV_SIZE 2 -#define MAC_ADDR_OFFSET 4 -#define MAC_ADDR_OFFSET_LEGACY 0 - -#define LAYOUT_INVALID 0 -#define LAYOUT_LEGACY 0xff - -static int eeprom_layout; /* Implicitly LAYOUT_INVALID */ - -static int cm_t3x_eeprom_read(uint offset, uchar *buf, int len) -{ - return i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, offset, - CONFIG_SYS_I2C_EEPROM_ADDR_LEN, buf, len); -} - -static int eeprom_setup_layout(void) -{ - int res; - - if (eeprom_layout != LAYOUT_INVALID) - return 0; - - res = cm_t3x_eeprom_read(EEPROM_LAYOUT_VER_OFFSET, - (uchar *)&eeprom_layout, 1); - if (res) { - eeprom_layout = LAYOUT_INVALID; - return res; - } - - if (eeprom_layout == 0 || eeprom_layout >= 0x20) - eeprom_layout = LAYOUT_LEGACY; - - return 0; -} - -void get_board_serial(struct tag_serialnr *serialnr) -{ - u32 serial[2]; - uint offset; - - memset(serialnr, 0, sizeof(*serialnr)); - if (eeprom_setup_layout()) - return; - - offset = (eeprom_layout != LAYOUT_LEGACY) ? - BOARD_SERIAL_OFFSET : BOARD_SERIAL_OFFSET_LEGACY; - if (cm_t3x_eeprom_read(offset, (uchar *)serial, 8)) - return; - - if (serial[0] != 0xffffffff && serial[1] != 0xffffffff) { - serialnr->low = serial[0]; - serialnr->high = serial[1]; - } -} - -/* - * Routine: cm_t3x_eeprom_read_mac_addr - * Description: read mac address and store it in buf. - */ -int cm_t3x_eeprom_read_mac_addr(uchar *buf) -{ - uint offset; - - if (eeprom_setup_layout()) - return 0; - - offset = (eeprom_layout != LAYOUT_LEGACY) ? - MAC_ADDR_OFFSET : MAC_ADDR_OFFSET_LEGACY; - return cm_t3x_eeprom_read(offset, buf, 6); -} - -/* - * Routine: cm_t3x_eeprom_get_board_rev - * Description: read system revision from eeprom - */ -u32 cm_t3x_eeprom_get_board_rev(void) -{ - u32 rev = 0; - char str[5]; /* Legacy representation can contain at most 4 digits */ - uint offset = BOARD_REV_OFFSET_LEGACY; - - if (eeprom_setup_layout()) - return 0; - - if (eeprom_layout != LAYOUT_LEGACY) - offset = BOARD_REV_OFFSET; - - if (cm_t3x_eeprom_read(offset, (uchar *)&rev, BOARD_REV_SIZE)) - return 0; - - /* - * Convert legacy syntactic representation to semantic - * representation. i.e. for rev 1.00: 0x100 --> 0x64 - */ - if (eeprom_layout == LAYOUT_LEGACY) { - sprintf(str, "%x", rev); - rev = simple_strtoul(str, NULL, 10); - } - - return rev; -}; diff --git a/board/compulab/cm_t35/eeprom.h b/board/compulab/cm_t35/eeprom.h deleted file mode 100644 index 02ffbb1a99..0000000000 --- a/board/compulab/cm_t35/eeprom.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * (C) Copyright 2011 CompuLab, Ltd. - * - * Authors: Nikita Kiryanov - * Igor Grinberg - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _EEPROM_ -#define _EEPROM_ - -#ifdef CONFIG_DRIVER_OMAP34XX_I2C -int cm_t3x_eeprom_read_mac_addr(uchar *buf); -u32 cm_t3x_eeprom_get_board_rev(void); -#else -static inline int cm_t3x_eeprom_read_mac_addr(uchar *buf) -{ - return 1; -} -static inline u32 cm_t3x_eeprom_get_board_rev(void) -{ - return 0; -} -#endif - -#endif diff --git a/board/compulab/common/Makefile b/board/compulab/common/Makefile new file mode 100644 index 0000000000..ec2e510cd6 --- /dev/null +++ b/board/compulab/common/Makefile @@ -0,0 +1,35 @@ +# +# (C) Copyright 2011 - 2013 CompuLab, Ltd. +# +# Author: Igor Grinberg +# +# SPDX-License-Identifier: GPL-2.0+ +# + +include $(TOPDIR)/config.mk + +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)board/$(VENDOR)/common) +endif + +LIB = $(obj)lib$(VENDOR).o + +COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += eeprom.o + +COBJS := $(COBJS-y) +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(call cmd_link_o_target, $(OBJS) $(SOBJS)) + +######################################################################### +# This is for $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/compulab/common/eeprom.c b/board/compulab/common/eeprom.c new file mode 100644 index 0000000000..5aa3dbd295 --- /dev/null +++ b/board/compulab/common/eeprom.c @@ -0,0 +1,121 @@ +/* + * (C) Copyright 2011 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov + * Igor Grinberg + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#define EEPROM_LAYOUT_VER_OFFSET 44 +#define BOARD_SERIAL_OFFSET 20 +#define BOARD_SERIAL_OFFSET_LEGACY 8 +#define BOARD_REV_OFFSET 0 +#define BOARD_REV_OFFSET_LEGACY 6 +#define BOARD_REV_SIZE 2 +#define MAC_ADDR_OFFSET 4 +#define MAC_ADDR_OFFSET_LEGACY 0 + +#define LAYOUT_INVALID 0 +#define LAYOUT_LEGACY 0xff + +static int cl_eeprom_layout; /* Implicitly LAYOUT_INVALID */ + +static int cl_eeprom_read(uint offset, uchar *buf, int len) +{ + return i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, offset, + CONFIG_SYS_I2C_EEPROM_ADDR_LEN, buf, len); +} + +static int cl_eeprom_setup_layout(void) +{ + int res; + + if (cl_eeprom_layout != LAYOUT_INVALID) + return 0; + + res = cl_eeprom_read(EEPROM_LAYOUT_VER_OFFSET, + (uchar *)&cl_eeprom_layout, 1); + if (res) { + cl_eeprom_layout = LAYOUT_INVALID; + return res; + } + + if (cl_eeprom_layout == 0 || cl_eeprom_layout >= 0x20) + cl_eeprom_layout = LAYOUT_LEGACY; + + return 0; +} + +void get_board_serial(struct tag_serialnr *serialnr) +{ + u32 serial[2]; + uint offset; + + memset(serialnr, 0, sizeof(*serialnr)); + + if (cl_eeprom_setup_layout()) + return; + + offset = (cl_eeprom_layout != LAYOUT_LEGACY) ? + BOARD_SERIAL_OFFSET : BOARD_SERIAL_OFFSET_LEGACY; + + if (cl_eeprom_read(offset, (uchar *)serial, 8)) + return; + + if (serial[0] != 0xffffffff && serial[1] != 0xffffffff) { + serialnr->low = serial[0]; + serialnr->high = serial[1]; + } +} + +/* + * Routine: cl_eeprom_read_mac_addr + * Description: read mac address and store it in buf. + */ +int cl_eeprom_read_mac_addr(uchar *buf) +{ + uint offset; + + if (cl_eeprom_setup_layout()) + return 0; + + offset = (cl_eeprom_layout != LAYOUT_LEGACY) ? + MAC_ADDR_OFFSET : MAC_ADDR_OFFSET_LEGACY; + + return cl_eeprom_read(offset, buf, 6); +} + +/* + * Routine: cl_eeprom_get_board_rev + * Description: read system revision from eeprom + */ +u32 cl_eeprom_get_board_rev(void) +{ + u32 rev = 0; + char str[5]; /* Legacy representation can contain at most 4 digits */ + uint offset = BOARD_REV_OFFSET_LEGACY; + + if (cl_eeprom_setup_layout()) + return 0; + + if (cl_eeprom_layout != LAYOUT_LEGACY) + offset = BOARD_REV_OFFSET; + + if (cl_eeprom_read(offset, (uchar *)&rev, BOARD_REV_SIZE)) + return 0; + + /* + * Convert legacy syntactic representation to semantic + * representation. i.e. for rev 1.00: 0x100 --> 0x64 + */ + if (cl_eeprom_layout == LAYOUT_LEGACY) { + sprintf(str, "%x", rev); + rev = simple_strtoul(str, NULL, 10); + } + + return rev; +}; diff --git a/board/compulab/common/eeprom.h b/board/compulab/common/eeprom.h new file mode 100644 index 0000000000..cf8c302b2e --- /dev/null +++ b/board/compulab/common/eeprom.h @@ -0,0 +1,27 @@ +/* + * (C) Copyright 2011 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov + * Igor Grinberg + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _EEPROM_ +#define _EEPROM_ + +#ifdef CONFIG_DRIVER_OMAP34XX_I2C +int cl_eeprom_read_mac_addr(uchar *buf); +u32 cl_eeprom_get_board_rev(void); +#else +static inline int cl_eeprom_read_mac_addr(uchar *buf) +{ + return 1; +} +static inline u32 cl_eeprom_get_board_rev(void) +{ + return 0; +} +#endif + +#endif -- cgit From e1e55c13c965c1c2316cd1540c3e46e1c07fc4ee Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Mon, 16 Sep 2013 21:49:59 +0300 Subject: cm-t35: move the display code to common place Compulab OMAP3 boards use the same display initialization code. Move the display initialization code to live under board/compulab/common directory. Signed-off-by: Igor Grinberg Tested-by: Nikita Kiryanov --- board/compulab/cm_t35/Makefile | 2 - board/compulab/cm_t35/display.c | 406 ---------------------------------- board/compulab/common/Makefile | 1 + board/compulab/common/omap3_display.c | 406 ++++++++++++++++++++++++++++++++++ 4 files changed, 407 insertions(+), 408 deletions(-) delete mode 100644 board/compulab/cm_t35/display.c create mode 100644 board/compulab/common/omap3_display.c (limited to 'board/compulab') diff --git a/board/compulab/cm_t35/Makefile b/board/compulab/cm_t35/Makefile index 8b922b3d7e..213423ec65 100644 --- a/board/compulab/cm_t35/Makefile +++ b/board/compulab/cm_t35/Makefile @@ -11,8 +11,6 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).o -COBJS-$(CONFIG_LCD) += display.o - COBJS := cm_t35.o leds.o $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/board/compulab/cm_t35/display.c b/board/compulab/cm_t35/display.c deleted file mode 100644 index fae8d95403..0000000000 --- a/board/compulab/cm_t35/display.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * (C) Copyright 2012 - 2013 CompuLab, Ltd. - * - * Authors: Nikita Kiryanov - * - * Parsing code based on linux/drivers/video/pxafb.c - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -enum display_type { - NONE, - DVI, - DVI_CUSTOM, -}; - -#define CMAP_ADDR 0x80100000 - -/* - * The frame buffer is allocated before we have the chance to parse user input. - * To make sure enough memory is allocated for all resolutions, we define - * vl_{col | row} to the maximal resolution supported by OMAP3. - */ -vidinfo_t panel_info = { - .vl_col = 1400, - .vl_row = 1050, - .vl_bpix = LCD_BPP, - .cmap = (ushort *)CMAP_ADDR, -}; - -static struct panel_config panel_cfg; -static enum display_type lcd_def; - -/* - * A note on DVI presets; - * U-Boot can convert 8 bit BMP data to 16 bit BMP data, and OMAP DSS can - * convert 16 bit data into 24 bit data. Thus, GFXFORMAT_RGB16 allows us to - * support two BMP types with one setting. - */ -static const struct panel_config preset_dvi_640X480 = { - .lcd_size = PANEL_LCD_SIZE(640, 480), - .timing_h = DSS_HBP(48) | DSS_HFP(16) | DSS_HSW(96), - .timing_v = DSS_VBP(33) | DSS_VFP(10) | DSS_VSW(2), - .divisor = 12 | (1 << 16), - .data_lines = LCD_INTERFACE_24_BIT, - .panel_type = ACTIVE_DISPLAY, - .load_mode = 2, - .gfx_format = GFXFORMAT_RGB16, -}; - -static const struct panel_config preset_dvi_800X600 = { - .lcd_size = PANEL_LCD_SIZE(800, 600), - .timing_h = DSS_HBP(88) | DSS_HFP(40) | DSS_HSW(128), - .timing_v = DSS_VBP(23) | DSS_VFP(1) | DSS_VSW(4), - .divisor = 8 | (1 << 16), - .data_lines = LCD_INTERFACE_24_BIT, - .panel_type = ACTIVE_DISPLAY, - .load_mode = 2, - .gfx_format = GFXFORMAT_RGB16, -}; - -static const struct panel_config preset_dvi_1024X768 = { - .lcd_size = PANEL_LCD_SIZE(1024, 768), - .timing_h = DSS_HBP(160) | DSS_HFP(24) | DSS_HSW(136), - .timing_v = DSS_VBP(29) | DSS_VFP(3) | DSS_VSW(6), - .divisor = 5 | (1 << 16), - .data_lines = LCD_INTERFACE_24_BIT, - .panel_type = ACTIVE_DISPLAY, - .load_mode = 2, - .gfx_format = GFXFORMAT_RGB16, -}; - -static const struct panel_config preset_dvi_1152X864 = { - .lcd_size = PANEL_LCD_SIZE(1152, 864), - .timing_h = DSS_HBP(256) | DSS_HFP(64) | DSS_HSW(128), - .timing_v = DSS_VBP(32) | DSS_VFP(1) | DSS_VSW(3), - .divisor = 3 | (1 << 16), - .data_lines = LCD_INTERFACE_24_BIT, - .panel_type = ACTIVE_DISPLAY, - .load_mode = 2, - .gfx_format = GFXFORMAT_RGB16, -}; - -static const struct panel_config preset_dvi_1280X960 = { - .lcd_size = PANEL_LCD_SIZE(1280, 960), - .timing_h = DSS_HBP(312) | DSS_HFP(96) | DSS_HSW(112), - .timing_v = DSS_VBP(36) | DSS_VFP(1) | DSS_VSW(3), - .divisor = 3 | (1 << 16), - .data_lines = LCD_INTERFACE_24_BIT, - .panel_type = ACTIVE_DISPLAY, - .load_mode = 2, - .gfx_format = GFXFORMAT_RGB16, -}; - -static const struct panel_config preset_dvi_1280X1024 = { - .lcd_size = PANEL_LCD_SIZE(1280, 1024), - .timing_h = DSS_HBP(248) | DSS_HFP(48) | DSS_HSW(112), - .timing_v = DSS_VBP(38) | DSS_VFP(1) | DSS_VSW(3), - .divisor = 3 | (1 << 16), - .data_lines = LCD_INTERFACE_24_BIT, - .panel_type = ACTIVE_DISPLAY, - .load_mode = 2, - .gfx_format = GFXFORMAT_RGB16, -}; - -/* - * set_resolution_params() - * - * Due to usage of multiple display related APIs resolution data is located in - * more than one place. This function updates them all. - */ -static void set_resolution_params(int x, int y) -{ - panel_cfg.lcd_size = PANEL_LCD_SIZE(x, y); - panel_info.vl_col = x; - panel_info.vl_row = y; - lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; -} - -static void set_preset(const struct panel_config preset, int x_res, int y_res) -{ - panel_cfg = preset; - set_resolution_params(x_res, y_res); -} - -static enum display_type set_dvi_preset(const struct panel_config preset, - int x_res, int y_res) -{ - set_preset(preset, x_res, y_res); - return DVI; -} - -/* - * 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 - * name of the display type or preset, in which case it applies its - * configurations. - * - * Returns the type of display that was specified. - */ -static enum display_type env_parse_displaytype(char *displaytype) -{ - if (!strncmp(displaytype, "dvi640x480", 10)) - return set_dvi_preset(preset_dvi_640X480, 640, 480); - else if (!strncmp(displaytype, "dvi800x600", 10)) - return set_dvi_preset(preset_dvi_800X600, 800, 600); - else if (!strncmp(displaytype, "dvi1024x768", 11)) - return set_dvi_preset(preset_dvi_1024X768, 1024, 768); - else if (!strncmp(displaytype, "dvi1152x864", 11)) - return set_dvi_preset(preset_dvi_1152X864, 1152, 864); - else if (!strncmp(displaytype, "dvi1280x960", 11)) - return set_dvi_preset(preset_dvi_1280X960, 1280, 960); - else if (!strncmp(displaytype, "dvi1280x1024", 12)) - return set_dvi_preset(preset_dvi_1280X1024, 1280, 1024); - - return NONE; -} - -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 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); - /* - * Pixel clock is defined with many divisions and only few - * multiplications of the system clock. Since DSS FCLK divisor is set - * to 16 by default, we need to set it to a smaller value, like 3 - * (chosen via trial and error). - */ - clrsetbits_le32(&prcm->clksel_dss, 0xF, 3); -} - -void lcd_enable(void) -{ - if (lcd_def == DVI || lcd_def == DVI_CUSTOM) { - gpio_direction_output(54, 0); /* Turn on DVI */ - omap3_dss_enable(); - } -} - -void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) {} diff --git a/board/compulab/common/Makefile b/board/compulab/common/Makefile index ec2e510cd6..b399c8f46b 100644 --- a/board/compulab/common/Makefile +++ b/board/compulab/common/Makefile @@ -15,6 +15,7 @@ endif LIB = $(obj)lib$(VENDOR).o COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += eeprom.o +COBJS-$(CONFIG_LCD) += omap3_display.o COBJS := $(COBJS-y) SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/board/compulab/common/omap3_display.c b/board/compulab/common/omap3_display.c new file mode 100644 index 0000000000..fae8d95403 --- /dev/null +++ b/board/compulab/common/omap3_display.c @@ -0,0 +1,406 @@ +/* + * (C) Copyright 2012 - 2013 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov + * + * Parsing code based on linux/drivers/video/pxafb.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +enum display_type { + NONE, + DVI, + DVI_CUSTOM, +}; + +#define CMAP_ADDR 0x80100000 + +/* + * The frame buffer is allocated before we have the chance to parse user input. + * To make sure enough memory is allocated for all resolutions, we define + * vl_{col | row} to the maximal resolution supported by OMAP3. + */ +vidinfo_t panel_info = { + .vl_col = 1400, + .vl_row = 1050, + .vl_bpix = LCD_BPP, + .cmap = (ushort *)CMAP_ADDR, +}; + +static struct panel_config panel_cfg; +static enum display_type lcd_def; + +/* + * A note on DVI presets; + * U-Boot can convert 8 bit BMP data to 16 bit BMP data, and OMAP DSS can + * convert 16 bit data into 24 bit data. Thus, GFXFORMAT_RGB16 allows us to + * support two BMP types with one setting. + */ +static const struct panel_config preset_dvi_640X480 = { + .lcd_size = PANEL_LCD_SIZE(640, 480), + .timing_h = DSS_HBP(48) | DSS_HFP(16) | DSS_HSW(96), + .timing_v = DSS_VBP(33) | DSS_VFP(10) | DSS_VSW(2), + .divisor = 12 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +static const struct panel_config preset_dvi_800X600 = { + .lcd_size = PANEL_LCD_SIZE(800, 600), + .timing_h = DSS_HBP(88) | DSS_HFP(40) | DSS_HSW(128), + .timing_v = DSS_VBP(23) | DSS_VFP(1) | DSS_VSW(4), + .divisor = 8 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +static const struct panel_config preset_dvi_1024X768 = { + .lcd_size = PANEL_LCD_SIZE(1024, 768), + .timing_h = DSS_HBP(160) | DSS_HFP(24) | DSS_HSW(136), + .timing_v = DSS_VBP(29) | DSS_VFP(3) | DSS_VSW(6), + .divisor = 5 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +static const struct panel_config preset_dvi_1152X864 = { + .lcd_size = PANEL_LCD_SIZE(1152, 864), + .timing_h = DSS_HBP(256) | DSS_HFP(64) | DSS_HSW(128), + .timing_v = DSS_VBP(32) | DSS_VFP(1) | DSS_VSW(3), + .divisor = 3 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +static const struct panel_config preset_dvi_1280X960 = { + .lcd_size = PANEL_LCD_SIZE(1280, 960), + .timing_h = DSS_HBP(312) | DSS_HFP(96) | DSS_HSW(112), + .timing_v = DSS_VBP(36) | DSS_VFP(1) | DSS_VSW(3), + .divisor = 3 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +static const struct panel_config preset_dvi_1280X1024 = { + .lcd_size = PANEL_LCD_SIZE(1280, 1024), + .timing_h = DSS_HBP(248) | DSS_HFP(48) | DSS_HSW(112), + .timing_v = DSS_VBP(38) | DSS_VFP(1) | DSS_VSW(3), + .divisor = 3 | (1 << 16), + .data_lines = LCD_INTERFACE_24_BIT, + .panel_type = ACTIVE_DISPLAY, + .load_mode = 2, + .gfx_format = GFXFORMAT_RGB16, +}; + +/* + * set_resolution_params() + * + * Due to usage of multiple display related APIs resolution data is located in + * more than one place. This function updates them all. + */ +static void set_resolution_params(int x, int y) +{ + panel_cfg.lcd_size = PANEL_LCD_SIZE(x, y); + panel_info.vl_col = x; + panel_info.vl_row = y; + lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; +} + +static void set_preset(const struct panel_config preset, int x_res, int y_res) +{ + panel_cfg = preset; + set_resolution_params(x_res, y_res); +} + +static enum display_type set_dvi_preset(const struct panel_config preset, + int x_res, int y_res) +{ + set_preset(preset, x_res, y_res); + return DVI; +} + +/* + * 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 + * name of the display type or preset, in which case it applies its + * configurations. + * + * Returns the type of display that was specified. + */ +static enum display_type env_parse_displaytype(char *displaytype) +{ + if (!strncmp(displaytype, "dvi640x480", 10)) + return set_dvi_preset(preset_dvi_640X480, 640, 480); + else if (!strncmp(displaytype, "dvi800x600", 10)) + return set_dvi_preset(preset_dvi_800X600, 800, 600); + else if (!strncmp(displaytype, "dvi1024x768", 11)) + return set_dvi_preset(preset_dvi_1024X768, 1024, 768); + else if (!strncmp(displaytype, "dvi1152x864", 11)) + return set_dvi_preset(preset_dvi_1152X864, 1152, 864); + else if (!strncmp(displaytype, "dvi1280x960", 11)) + return set_dvi_preset(preset_dvi_1280X960, 1280, 960); + else if (!strncmp(displaytype, "dvi1280x1024", 12)) + return set_dvi_preset(preset_dvi_1280X1024, 1280, 1024); + + return NONE; +} + +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 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); + /* + * Pixel clock is defined with many divisions and only few + * multiplications of the system clock. Since DSS FCLK divisor is set + * to 16 by default, we need to set it to a smaller value, like 3 + * (chosen via trial and error). + */ + clrsetbits_le32(&prcm->clksel_dss, 0xF, 3); +} + +void lcd_enable(void) +{ + if (lcd_def == DVI || lcd_def == DVI_CUSTOM) { + gpio_direction_output(54, 0); /* Turn on DVI */ + omap3_dss_enable(); + } +} + +void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) {} -- cgit From f9f6686ff8ad3cbc860a51aa2b6b6def4188f15b Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Mon, 7 Oct 2013 18:55:46 +0300 Subject: cm_t35: update lcd predefines Current predefines do not fit cm-t3730 very well (some of them produce artifacts in the image). Update LCD predefines to accommodate both cm-t35 and cm-t3730 modules. Signed-off-by: Nikita Kiryanov Signed-off-by: Igor Grinberg --- board/compulab/common/omap3_display.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'board/compulab') diff --git a/board/compulab/common/omap3_display.c b/board/compulab/common/omap3_display.c index fae8d95403..ead821eeb7 100644 --- a/board/compulab/common/omap3_display.c +++ b/board/compulab/common/omap3_display.c @@ -51,6 +51,7 @@ static const struct panel_config preset_dvi_640X480 = { .lcd_size = PANEL_LCD_SIZE(640, 480), .timing_h = DSS_HBP(48) | DSS_HFP(16) | DSS_HSW(96), .timing_v = DSS_VBP(33) | DSS_VFP(10) | DSS_VSW(2), + .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC, .divisor = 12 | (1 << 16), .data_lines = LCD_INTERFACE_24_BIT, .panel_type = ACTIVE_DISPLAY, @@ -62,6 +63,7 @@ static const struct panel_config preset_dvi_800X600 = { .lcd_size = PANEL_LCD_SIZE(800, 600), .timing_h = DSS_HBP(88) | DSS_HFP(40) | DSS_HSW(128), .timing_v = DSS_VBP(23) | DSS_VFP(1) | DSS_VSW(4), + .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC, .divisor = 8 | (1 << 16), .data_lines = LCD_INTERFACE_24_BIT, .panel_type = ACTIVE_DISPLAY, @@ -73,6 +75,7 @@ static const struct panel_config preset_dvi_1024X768 = { .lcd_size = PANEL_LCD_SIZE(1024, 768), .timing_h = DSS_HBP(160) | DSS_HFP(24) | DSS_HSW(136), .timing_v = DSS_VBP(29) | DSS_VFP(3) | DSS_VSW(6), + .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC, .divisor = 5 | (1 << 16), .data_lines = LCD_INTERFACE_24_BIT, .panel_type = ACTIVE_DISPLAY, @@ -84,7 +87,8 @@ static const struct panel_config preset_dvi_1152X864 = { .lcd_size = PANEL_LCD_SIZE(1152, 864), .timing_h = DSS_HBP(256) | DSS_HFP(64) | DSS_HSW(128), .timing_v = DSS_VBP(32) | DSS_VFP(1) | DSS_VSW(3), - .divisor = 3 | (1 << 16), + .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC, + .divisor = 4 | (1 << 16), .data_lines = LCD_INTERFACE_24_BIT, .panel_type = ACTIVE_DISPLAY, .load_mode = 2, @@ -95,6 +99,7 @@ static const struct panel_config preset_dvi_1280X960 = { .lcd_size = PANEL_LCD_SIZE(1280, 960), .timing_h = DSS_HBP(312) | DSS_HFP(96) | DSS_HSW(112), .timing_v = DSS_VBP(36) | DSS_VFP(1) | DSS_VSW(3), + .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC, .divisor = 3 | (1 << 16), .data_lines = LCD_INTERFACE_24_BIT, .panel_type = ACTIVE_DISPLAY, @@ -106,6 +111,7 @@ static const struct panel_config preset_dvi_1280X1024 = { .lcd_size = PANEL_LCD_SIZE(1280, 1024), .timing_h = DSS_HBP(248) | DSS_HFP(48) | DSS_HSW(112), .timing_v = DSS_VBP(38) | DSS_VFP(1) | DSS_VSW(3), + .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC, .divisor = 3 | (1 << 16), .data_lines = LCD_INTERFACE_24_BIT, .panel_type = ACTIVE_DISPLAY, -- cgit