From e6c9428a2fe584c69374fd2d49ed61fdb1568114 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Thu, 28 Aug 2014 16:07:45 +0300 Subject: keystone2: use readl/writel functions instead of redefinition There is no reason to redefine pure readl/writel functions. So remove this redundancy. Signed-off-by: Ivan Khoronzhuk Acked-by: Vitaly Andrianov --- drivers/net/keystone_net.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index f95c928..d22b722 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -290,13 +290,12 @@ int mac_sl_reset(u32 port) return GMACSL_RET_INVALID_PORT; /* Set the soft reset bit */ - DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) + - CPGMACSL_REG_RESET, CPGMAC_REG_RESET_VAL_RESET); + writel(CPGMAC_REG_RESET_VAL_RESET, + DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); /* Wait for the bit to clear */ for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { - v = DEVICE_REG32_R(DEVICE_EMACSL_BASE(port) + - CPGMACSL_REG_RESET); + v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != CPGMAC_REG_RESET_VAL_RESET) return GMACSL_RET_OK; @@ -321,8 +320,7 @@ int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg) /* Must wait if the device is undergoing reset */ for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { - v = DEVICE_REG32_R(DEVICE_EMACSL_BASE(port) + - CPGMACSL_REG_RESET); + v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != CPGMAC_REG_RESET_VAL_RESET) break; @@ -331,11 +329,8 @@ int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg) if (i == DEVICE_EMACSL_RESET_POLL_COUNT) return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE; - DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN, - cfg->max_rx_len); - - DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL, - cfg->ctl); + writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN); + writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL); return ret; } @@ -345,24 +340,24 @@ int ethss_config(u32 ctl, u32 max_pkt_size) u32 i; /* Max length register */ - DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_MAXLEN, max_pkt_size); + writel(max_pkt_size, DEVICE_CPSW_BASE + CPSW_REG_MAXLEN); /* Control register */ - DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_CTL, ctl); + writel(ctl, DEVICE_CPSW_BASE + CPSW_REG_CTL); /* All statistics enabled by default */ - DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN, - CPSW_REG_VAL_STAT_ENABLE_ALL); + writel(CPSW_REG_VAL_STAT_ENABLE_ALL, + DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN); /* Reset and enable the ALE */ - DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL, - CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE | - CPSW_REG_VAL_ALE_CTL_BYPASS); + writel(CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE | + CPSW_REG_VAL_ALE_CTL_BYPASS, + DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL); /* All ports put into forward mode */ for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++) - DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i), - CPSW_REG_VAL_PORTCTL_FORWARD_MODE); + writel(CPSW_REG_VAL_PORTCTL_FORWARD_MODE, + DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i)); return 0; } -- cgit v1.1 From fc12a1f589ff54abafba42f17649955a1536ee04 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Tue, 2 Sep 2014 00:20:02 +0300 Subject: mtd: nand: davinci_nand: correct keystone RBL layout definition In case when 4K page keystone RBL layout is used the compilation error is appeared. That's because the #ifdef has to be placed under struct name. This patch correct it. Signed-off-by: Ivan Khoronzhuk --- drivers/mtd/nand/davinci_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index a079b1e..02a1130 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -306,8 +306,8 @@ static struct nand_ecclayout nand_davinci_4bit_layout_oobfirst = { }; #if defined CONFIG_KEYSTONE_RBL_NAND -#if defined(CONFIG_SYS_NAND_PAGE_2K) static struct nand_ecclayout nand_keystone_rbl_4bit_layout_oobfirst = { +#if defined(CONFIG_SYS_NAND_PAGE_2K) .eccbytes = 40, .eccpos = { 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -- cgit v1.1 From 5c3f7e0ead6db15dc1888cd126b2420ae87980c4 Mon Sep 17 00:00:00 2001 From: Rostislav Lisovy Date: Tue, 2 Sep 2014 16:23:58 +0200 Subject: mtd: nand: omap_gpmc: Enable multiple NAND flash devices Since the CS of a device connected to the GPMC was stored in the global variable, it was not possible to use multiple devices. In this patch the CS is stored per device in its 'struct omap_nand_info'. This makes it possible to use up to 'GPMC_MAX_CS' NAND Flash devices connected to U-boot. Signed-off-by: Rostislav Lisovy --- drivers/mtd/nand/omap_gpmc.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index 1acf06b..96618e1 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -27,10 +27,22 @@ static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2, 0x97, 0x79, 0xe5, 0x24, 0xb5}; #endif -static uint8_t cs; +static uint8_t cs_next; static __maybe_unused struct nand_ecclayout omap_ecclayout; /* + * Driver configurations + */ +struct omap_nand_info { + struct bch_control *control; + enum omap_ecc ecc_scheme; + int cs; +}; + +/* We are wasting a bit of memory but al least we are safe */ +static struct omap_nand_info omap_nand_info[GPMC_MAX_CS]; + +/* * omap_nand_hwcontrol - Set the address pointers corretly for the * following address/data/command operation */ @@ -38,6 +50,8 @@ static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd, uint32_t ctrl) { register struct nand_chip *this = mtd->priv; + struct omap_nand_info *info = this->priv; + int cs = info->cs; /* * Point the IO_ADDR to DATA and ADDRESS registers instead @@ -148,24 +162,6 @@ static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat, } /* - * Driver configurations - */ -struct omap_nand_info { - struct bch_control *control; - enum omap_ecc ecc_scheme; -}; - -/* - * This can be a single instance cause all current users have only one NAND - * with nearly the same setup (BCH8, some with ELM and others with sw BCH - * library). - * When some users with other BCH strength will exists this have to change! - */ -static __maybe_unused struct omap_nand_info omap_nand_info = { - .control = NULL -}; - -/* * omap_reverse_list - re-orders list elements in reverse order [internal] * @list: pointer to start of list * @length: length of list @@ -198,6 +194,7 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode) unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00; u32 ecc_size_config_val = 0; u32 ecc_config_val = 0; + int cs = info->cs; /* configure GPMC for specific ecc-scheme */ switch (info->ecc_scheme) { @@ -826,7 +823,7 @@ int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength) int board_nand_init(struct nand_chip *nand) { int32_t gpmc_config = 0; - cs = 0; + int cs = cs_next++; int err = 0; /* * xloader/Uboot's gpmc configuration would have configured GPMC for @@ -856,7 +853,9 @@ int board_nand_init(struct nand_chip *nand) nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat; nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd; - nand->priv = &omap_nand_info; + omap_nand_info[cs].control = NULL; + omap_nand_info[cs].cs = cs; + nand->priv = &omap_nand_info[cs]; nand->cmd_ctrl = omap_nand_hwcontrol; nand->options |= NAND_NO_PADDING | NAND_CACHEPRG; nand->chip_delay = 100; @@ -890,6 +889,5 @@ int board_nand_init(struct nand_chip *nand) nand->read_buf = nand_read_buf; nand->dev_ready = omap_spl_dev_ready; #endif - return 0; } -- cgit v1.1 From cc81a5291910d7a3016a65042bec7b4e54e81d03 Mon Sep 17 00:00:00 2001 From: Rostislav Lisovy Date: Tue, 2 Sep 2014 17:00:30 +0200 Subject: mtd: nand: omap_gpmc: Fix 'bit-flip' errors OMAP GPMC driver used with some NAND Flash devices (e.g. Spansion S34ML08G1) causes that U-boot shows hundreds of 'nand: bit-flip corrected' error messages. Possible cause was discussed in the mailinglist thread: http://lists.denx.de/pipermail/u-boot/2014-April/177508.html Quote (Author: Pekon Gupta ): "The issue is mainly due to a NAND protocol violation in the omap driver since the Random Data Output command (05h-E0h) expects to see only the column address that should be addressed within the already loaded read page into the read buffer. Only 2 address cycles with ALE active should be provided between the 05h and E0h commands. The Page read command expects the full address footprint (2bytes for column address + 3bytes for row address), but once the page is loaded into the read buffer, Random Data Output should be used with only 2bytes for column address." This patch combines the solution proposed in the mailinglist and the patch provided by the Spansion company (GPLv2 code, source: http://www.spansion.com/Support/Software/u-boot-psp-04.04.00.01-NAND.zip) Signed-off-by: Rostislav Lisovy --- drivers/mtd/nand/omap_gpmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index 96618e1..db1599e 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -475,11 +475,11 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, oob += eccbytes) { chip->ecc.hwctl(mtd, NAND_ECC_READ); /* read data */ - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page); + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, -1); chip->read_buf(mtd, p, eccsize); /* read respective ecc from oob area */ - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page); + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1); chip->read_buf(mtd, oob, eccbytes); /* read syndrome */ chip->ecc.calculate(mtd, p, &ecc_calc[i]); -- cgit v1.1 From f0017175e33d7c21269deebc5e2ca2827b1e5975 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Date: Fri, 5 Sep 2014 16:53:30 +0530 Subject: exynos_fb: Remove usage of static defines Previously, we used to statically assign values for vl_col, vl_row and vl_bpix using #defines like LCD_XRES, LCD_YRES and LCD_COLOR16. Introducing the function exynos_lcd_early_init() would take care of this assignment on the fly by parsing FIMD DT properties, thereby allowing us to remove LCD_XRES and LCD_YRES from the main config file. Signed-off-by: Ajay Kumar Acked-by: Simon Glass Tested-by: Simon Glass Signed-off-by: Minkyu Kang --- drivers/video/exynos_fb.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/video/exynos_fb.c b/drivers/video/exynos_fb.c index e1e0d80..180a3b4 100644 --- a/drivers/video/exynos_fb.c +++ b/drivers/video/exynos_fb.c @@ -27,17 +27,13 @@ DECLARE_GLOBAL_DATA_PTR; static unsigned int panel_width, panel_height; -/* - * board_init_f(arch/arm/lib/board.c) calls lcd_setmem() which needs - * panel_info.vl_col, panel_info.vl_row and panel_info.vl_bpix to reserve - * FB memory at a very early stage, i.e even before exynos_fimd_parse_dt() - * is called. So, we are forced to statically assign it. - */ #ifdef CONFIG_OF_CONTROL vidinfo_t panel_info = { - .vl_col = LCD_XRES, - .vl_row = LCD_YRES, - .vl_bpix = LCD_COLOR16, + /* + * Insert a value here so that we don't end up in the BSS + * Reference: drivers/video/tegra.c + */ + .vl_col = -1, }; #endif @@ -141,7 +137,7 @@ static void lcd_panel_on(vidinfo_t *vid) } #ifdef CONFIG_OF_CONTROL -int exynos_fimd_parse_dt(const void *blob) +int exynos_lcd_early_init(const void *blob) { unsigned int node; node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_FIMD); @@ -286,8 +282,6 @@ void lcd_ctrl_init(void *lcdbase) set_lcd_clk(); #ifdef CONFIG_OF_CONTROL - if (exynos_fimd_parse_dt(gd->fdt_blob)) - debug("Can't get proper panel info\n"); #ifdef CONFIG_EXYNOS_MIPI_DSIM exynos_init_dsim_platform_data(&panel_info); #endif -- cgit v1.1 From 45c480c9f6dbb80c7af721f451b4df5a32402899 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Date: Fri, 5 Sep 2014 16:53:33 +0530 Subject: video: exynos_fimd: Add framework to disable FIMD sysmmu On Exynos5420 and newer versions, the FIMD sysmmus are in "on state" by default. We have to disable them in order to make FIMD DMA work. This patch adds the required framework to exynos_fimd driver, and disables FIMD sysmmu on Exynos5420. Signed-off-by: Ajay Kumar Signed-off-by: Minkyu Kang --- drivers/video/exynos_fimd.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers') diff --git a/drivers/video/exynos_fimd.c b/drivers/video/exynos_fimd.c index cebbba7..f67fa81 100644 --- a/drivers/video/exynos_fimd.c +++ b/drivers/video/exynos_fimd.c @@ -251,6 +251,45 @@ void exynos_fimd_window_off(unsigned int win_id) writel(cfg, &fimd_ctrl->winshmap); } +#ifdef CONFIG_OF_CONTROL +/* +* The reset value for FIMD SYSMMU register MMU_CTRL is 3 +* on Exynos5420 and newer versions. +* This means FIMD SYSMMU is on by default on Exynos5420 +* and newer versions. +* Since in u-boot we don't use SYSMMU, we should disable +* those FIMD SYSMMU. +* Note that there are 2 SYSMMU for FIMD: m0 and m1. +* m0 handles windows 0 and 4, and m1 handles windows 1, 2 and 3. +* We disable both of them here. +*/ +void exynos_fimd_disable_sysmmu(void) +{ + u32 *sysmmufimd; + unsigned int node; + int node_list[2]; + int count; + int i; + + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "fimd", + COMPAT_SAMSUNG_EXYNOS_SYSMMU, node_list, 2); + for (i = 0; i < count; i++) { + node = node_list[i]; + if (node <= 0) { + debug("Can't get device node for fimd sysmmu\n"); + return; + } + + sysmmufimd = (u32 *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); + if (!sysmmufimd) { + debug("Can't get base address for sysmmu fimdm0"); + return; + } + + writel(0x0, sysmmufimd); + } +} +#endif void exynos_fimd_lcd_init(vidinfo_t *vid) { @@ -268,6 +307,10 @@ void exynos_fimd_lcd_init(vidinfo_t *vid) node, "reg"); if (fimd_ctrl == NULL) debug("Can't get the FIMD base address\n"); + + if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) + exynos_fimd_disable_sysmmu(); + #else fimd_ctrl = (struct exynos_fb *)samsung_get_base_fimd(); #endif -- cgit v1.1 From 9e8f664ecb25110c623d0385735db27596330ee7 Mon Sep 17 00:00:00 2001 From: Vadim Bendebury Date: Fri, 5 Sep 2014 16:53:34 +0530 Subject: video: Add driver for Parade PS8625 dP to LVDS bridge The initialization table comes from the "Illustration of I2C command for initialing PS8625" document supplied by Parade. Signed-off-by: Vadim Bendebury Signed-off-by: Ajay Kumar Acked-by: Simon Glass Tested-by: Simon Glass Signed-off-by: Minkyu Kang --- drivers/video/Makefile | 1 + drivers/video/parade.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 drivers/video/parade.c (limited to 'drivers') diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 93a91c3..248aa35 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -42,3 +42,4 @@ obj-$(CONFIG_VIDEO_TEGRA) += tegra.o obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o obj-$(CONFIG_FORMIKE) += formike.o obj-$(CONFIG_AM335X_LCD) += am335x-fb.o +obj-$(CONFIG_VIDEO_PARADE) += parade.o diff --git a/drivers/video/parade.c b/drivers/video/parade.c new file mode 100644 index 0000000..0f543f6 --- /dev/null +++ b/drivers/video/parade.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * This file is a driver for Parade dP<->LVDS bridges. The original submission + * is for the ps8625 chip. + */ +#include +#include +#include +#include + +/* + * Initialization of the chip is a process of writing certaing values into + * certain registers over i2c bus. The chip in fact responds to a range of + * addresses on the i2c bus, so for each written value three parameters are + * required: i2c address, register address and the actual value. + * + * The base address is derived from the device tree, only address offset is + * stored in the table below. + */ +/** + * struct reg_data() - data for a parade register write + * + * @addr_off offset from the i2c base address for parade + * @reg_addr register address to write + * @value value to be written + */ +struct reg_data { + uint8_t addr_off; + uint8_t reg; + uint8_t value; +} _packed; + +#define END_OF_TABLE 0xff /* Ficticious offset */ + +static const struct reg_data parade_values[] = { + {0x02, 0xa1, 0x01}, /* HPD low */ + /* + * SW setting + * [1:0] SW output 1.2V voltage is lower to 96% + */ + {0x04, 0x14, 0x01}, + /* + * RCO SS setting + * [5:4] = b01 0.5%, b10 1%, b11 1.5% + */ + {0x04, 0xe3, 0x20}, + {0x04, 0xe2, 0x80}, /* [7] RCO SS enable */ + /* + * RPHY Setting + * [3:2] CDR tune wait cycle before + * measure for fine tune b00: 1us, + * 01: 0.5us, 10:2us, 11:4us. + */ + {0x04, 0x8a, 0x0c}, + {0x04, 0x89, 0x08}, /* [3] RFD always on */ + /* + * CTN lock in/out: + * 20000ppm/80000ppm. Lock out 2 + * times. + */ + {0x04, 0x71, 0x2d}, + /* + * 2.7G CDR settings + * NOF=40LSB for HBR CDR setting + */ + {0x04, 0x7d, 0x07}, + {0x04, 0x7b, 0x00}, /* [1:0] Fmin=+4bands */ + {0x04, 0x7a, 0xfd}, /* [7:5] DCO_FTRNG=+-40% */ + /* + * 1.62G CDR settings + * [5:2]NOF=64LSB [1:0]DCO scale is 2/5 + */ + {0x04, 0xc0, 0x12}, + {0x04, 0xc1, 0x92}, /* Gitune=-37% */ + {0x04, 0xc2, 0x1c}, /* Fbstep=100% */ + {0x04, 0x32, 0x80}, /* [7] LOS signal disable */ + /* + * RPIO Setting + * [7:4] LVDS driver bias current : + * 75% (250mV swing) + */ + {0x04, 0x00, 0xb0}, + /* + * [7:6] Right-bar GPIO output strength is 8mA + */ + {0x04, 0x15, 0x40}, + /* EQ Training State Machine Setting */ + {0x04, 0x54, 0x10}, /* RCO calibration start */ + /* [4:0] MAX_LANE_COUNT set to one lane */ + {0x01, 0x02, 0x81}, + /* [4:0] LANE_COUNT_SET set to one lane */ + {0x01, 0x21, 0x81}, + {0x00, 0x52, 0x20}, + {0x00, 0xf1, 0x03}, /* HPD CP toggle enable */ + {0x00, 0x62, 0x41}, + /* Counter number, add 1ms counter delay */ + {0x00, 0xf6, 0x01}, + /* + * [6]PWM function control by + * DPCD0040f[7], default is PWM + * block always works. + */ + {0x00, 0x77, 0x06}, + /* + * 04h Adjust VTotal tolerance to + * fix the 30Hz no display issue + */ + {0x00, 0x4c, 0x04}, + /* DPCD00400='h00, Parade OUI = 'h001cf8 */ + {0x01, 0xc0, 0x00}, + {0x01, 0xc1, 0x1c}, /* DPCD00401='h1c */ + {0x01, 0xc2, 0xf8}, /* DPCD00402='hf8 */ + /* + * DPCD403~408 = ASCII code + * D2SLV5='h4432534c5635 + */ + {0x01, 0xc3, 0x44}, + {0x01, 0xc4, 0x32}, /* DPCD404 */ + {0x01, 0xc5, 0x53}, /* DPCD405 */ + {0x01, 0xc6, 0x4c}, /* DPCD406 */ + {0x01, 0xc7, 0x56}, /* DPCD407 */ + {0x01, 0xc8, 0x35}, /* DPCD408 */ + /* + * DPCD40A, Initial Code major revision + * '01' + */ + {0x01, 0xca, 0x01}, + /* DPCD40B, Initial Code minor revision '05' */ + {0x01, 0xcb, 0x05}, + /* DPCD720, Select internal PWM */ + {0x01, 0xa5, 0xa0}, + /* + * FFh for 100% PWM of brightness, 0h for 0% + * brightness + */ + {0x01, 0xa7, 0xff}, + /* + * Set LVDS output as 6bit-VESA mapping, + * single LVDS channel + */ + {0x01, 0xcc, 0x13}, + /* Enable SSC set by register */ + {0x02, 0xb1, 0x20}, + /* + * Set SSC enabled and +/-1% central + * spreading + */ + {0x04, 0x10, 0x16}, + /* MPU Clock source: LC => RCO */ + {0x04, 0x59, 0x60}, + {0x04, 0x54, 0x14}, /* LC -> RCO */ + {0x02, 0xa1, 0x91}, /* HPD high */ + {END_OF_TABLE} +}; + +/** + * Write values table into the Parade eDP bridge + * + * @return 0 on success, non-0 on failure + */ + +static int parade_write_regs(int base_addr, const struct reg_data *table) +{ + int ret = 0; + + while (!ret && (table->addr_off != END_OF_TABLE)) { + ret = i2c_write(base_addr + table->addr_off, + table->reg, 1, + (uint8_t *)&table->value, + sizeof(table->value)); + table++; + } + return ret; +} + +int parade_init(const void *blob) +{ + int bus, old_bus; + int parent; + int node; + int addr; + int ret; + + node = fdtdec_next_compatible(blob, 0, COMPAT_PARADE_PS8625); + if (node < 0) + return 0; + + parent = fdt_parent_offset(blob, node); + if (parent < 0) { + debug("%s: Could not find parent i2c node\n", __func__); + return -1; + } + addr = fdtdec_get_int(blob, node, "reg", -1); + if (addr < 0) { + debug("%s: Could not find i2c address\n", __func__); + return -1; + } + + bus = i2c_get_bus_num_fdt(parent); + old_bus = i2c_get_bus_num(); + + debug("%s: Using i2c bus %d\n", __func__, bus); + + /* + * TODO(sjg@chromium.org): Hmmm we seem to need some sort of delay + * here. + */ + mdelay(40); + i2c_set_bus_num(bus); + ret = parade_write_regs(addr, parade_values); + + i2c_set_bus_num(old_bus); + + return ret; +} -- cgit v1.1