Commit 337b0c52b3296f371d04aef71a833e09110e0e6b
powerpc/t1040qds: Add Video - HDMI support
T1040 has internal display interface unit (DIU) for driving video. T1040QDS supports video mode via -LCD using TI enconder -HDMI type interface via HDMI encoder Chrontel, CH7301C encoder which is I2C programmable is used as HDMI connector on T1040QDS. This patch add support to -enable Video interface for T1040QDS -route qixis multiplexing to enable DIU-HDMI interface on board -program DIU pixel clock gerenartor for T1040 -program HDMI encoder via I2C on board Signed-off-by: Priyanka Jain <Priyanka.Jain@freescale.com> Reviewed-by: York Sun <yorksun@freescale.com>
Showing 5 changed files with 255 additions and 1 deletions Side-by-side Diff
1 | +/* | |
2 | + * Copyright 2014 Freescale Semiconductor, Inc. | |
3 | + * Author: Priyanka Jain <Priyanka.Jain@freescale.com> | |
4 | + * | |
5 | + * SPDX-License-Identifier: GPL-2.0+ | |
6 | + */ | |
7 | + | |
8 | +#include <common.h> | |
9 | +#include <command.h> | |
10 | +#include <linux/ctype.h> | |
11 | +#include <asm/io.h> | |
12 | +#include <stdio_dev.h> | |
13 | +#include <video_fb.h> | |
14 | +#include <fsl_diu_fb.h> | |
15 | +#include "../common/qixis.h" | |
16 | +#include "t1040qds.h" | |
17 | +#include "t1040qds_qixis.h" | |
18 | +#include <i2c.h> | |
19 | + | |
20 | + | |
21 | +#define I2C_DVI_INPUT_DATA_FORMAT_REG 0x1F | |
22 | +#define I2C_DVI_PLL_CHARGE_CNTL_REG 0x33 | |
23 | +#define I2C_DVI_PLL_DIVIDER_REG 0x34 | |
24 | +#define I2C_DVI_PLL_SUPPLY_CNTL_REG 0x35 | |
25 | +#define I2C_DVI_PLL_FILTER_REG 0x36 | |
26 | +#define I2C_DVI_TEST_PATTERN_REG 0x48 | |
27 | +#define I2C_DVI_POWER_MGMT_REG 0x49 | |
28 | +#define I2C_DVI_LOCK_STATE_REG 0x4D | |
29 | +#define I2C_DVI_SYNC_POLARITY_REG 0x56 | |
30 | + | |
31 | +/* | |
32 | + * Set VSYNC/HSYNC to active high. This is polarity of sync signals | |
33 | + * from DIU->DVI. The DIU default is active igh, so DVI is set to | |
34 | + * active high. | |
35 | + */ | |
36 | +#define I2C_DVI_INPUT_DATA_FORMAT_VAL 0x98 | |
37 | + | |
38 | +#define I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL 0x06 | |
39 | +#define I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL 0x26 | |
40 | +#define I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL 0xA0 | |
41 | +#define I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL 0x08 | |
42 | +#define I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL 0x16 | |
43 | +#define I2C_DVI_PLL_FILTER_LOW_SPEED_VAL 0x60 | |
44 | + | |
45 | +/* Clear test pattern */ | |
46 | +#define I2C_DVI_TEST_PATTERN_VAL 0x18 | |
47 | +/* Exit Power-down mode */ | |
48 | +#define I2C_DVI_POWER_MGMT_VAL 0xC0 | |
49 | + | |
50 | +/* Monitor polarity is handled via DVI Sync Polarity Register */ | |
51 | +#define I2C_DVI_SYNC_POLARITY_VAL 0x00 | |
52 | + | |
53 | +/* | |
54 | + * DIU Area Descriptor | |
55 | + * | |
56 | + * Note that we need to byte-swap the value before it's written to the AD | |
57 | + * register. So even though the registers don't look like they're in the same | |
58 | + * bit positions as they are on the MPC8610, the same value is written to the | |
59 | + * AD register on the MPC8610 and on the P1022. | |
60 | + */ | |
61 | +#define AD_BYTE_F 0x10000000 | |
62 | +#define AD_ALPHA_C_SHIFT 25 | |
63 | +#define AD_BLUE_C_SHIFT 23 | |
64 | +#define AD_GREEN_C_SHIFT 21 | |
65 | +#define AD_RED_C_SHIFT 19 | |
66 | +#define AD_PIXEL_S_SHIFT 16 | |
67 | +#define AD_COMP_3_SHIFT 12 | |
68 | +#define AD_COMP_2_SHIFT 8 | |
69 | +#define AD_COMP_1_SHIFT 4 | |
70 | +#define AD_COMP_0_SHIFT 0 | |
71 | + | |
72 | +/* Programming of HDMI Chrontel CH7301 connector */ | |
73 | +int diu_set_dvi_encoder(unsigned int pixclock) | |
74 | +{ | |
75 | + int ret; | |
76 | + u8 temp; | |
77 | + select_i2c_ch_pca9547(I2C_MUX_CH_DIU); | |
78 | + | |
79 | + temp = I2C_DVI_TEST_PATTERN_VAL; | |
80 | + ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_TEST_PATTERN_REG, 1, | |
81 | + &temp, 1); | |
82 | + if (ret) { | |
83 | + puts("I2C: failed to select proper dvi test pattern\n"); | |
84 | + return ret; | |
85 | + } | |
86 | + temp = I2C_DVI_INPUT_DATA_FORMAT_VAL; | |
87 | + ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_INPUT_DATA_FORMAT_REG, | |
88 | + 1, &temp, 1); | |
89 | + if (ret) { | |
90 | + puts("I2C: failed to select dvi input data format\n"); | |
91 | + return ret; | |
92 | + } | |
93 | + | |
94 | + /* Set Sync polarity register */ | |
95 | + temp = I2C_DVI_SYNC_POLARITY_VAL; | |
96 | + ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_SYNC_POLARITY_REG, 1, | |
97 | + &temp, 1); | |
98 | + if (ret) { | |
99 | + puts("I2C: failed to select dvi syc polarity\n"); | |
100 | + return ret; | |
101 | + } | |
102 | + | |
103 | + /* Set PLL registers based on pixel clock rate*/ | |
104 | + if (pixclock > 65000000) { | |
105 | + temp = I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL; | |
106 | + ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, | |
107 | + I2C_DVI_PLL_CHARGE_CNTL_REG, 1, &temp, 1); | |
108 | + if (ret) { | |
109 | + puts("I2C: failed to select dvi pll charge_cntl\n"); | |
110 | + return ret; | |
111 | + } | |
112 | + temp = I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL; | |
113 | + ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, | |
114 | + I2C_DVI_PLL_DIVIDER_REG, 1, &temp, 1); | |
115 | + if (ret) { | |
116 | + puts("I2C: failed to select dvi pll divider\n"); | |
117 | + return ret; | |
118 | + } | |
119 | + temp = I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL; | |
120 | + ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, | |
121 | + I2C_DVI_PLL_FILTER_REG, 1, &temp, 1); | |
122 | + if (ret) { | |
123 | + puts("I2C: failed to select dvi pll filter\n"); | |
124 | + return ret; | |
125 | + } | |
126 | + } else { | |
127 | + temp = I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL; | |
128 | + ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, | |
129 | + I2C_DVI_PLL_CHARGE_CNTL_REG, 1, &temp, 1); | |
130 | + if (ret) { | |
131 | + puts("I2C: failed to select dvi pll charge_cntl\n"); | |
132 | + return ret; | |
133 | + } | |
134 | + temp = I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL; | |
135 | + ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, | |
136 | + I2C_DVI_PLL_DIVIDER_REG, 1, &temp, 1); | |
137 | + if (ret) { | |
138 | + puts("I2C: failed to select dvi pll divider\n"); | |
139 | + return ret; | |
140 | + } | |
141 | + temp = I2C_DVI_PLL_FILTER_LOW_SPEED_VAL; | |
142 | + ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, | |
143 | + I2C_DVI_PLL_FILTER_REG, 1, &temp, 1); | |
144 | + if (ret) { | |
145 | + puts("I2C: failed to select dvi pll filter\n"); | |
146 | + return ret; | |
147 | + } | |
148 | + } | |
149 | + | |
150 | + temp = I2C_DVI_POWER_MGMT_VAL; | |
151 | + ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_POWER_MGMT_REG, 1, | |
152 | + &temp, 1); | |
153 | + if (ret) { | |
154 | + puts("I2C: failed to select dvi power mgmt\n"); | |
155 | + return ret; | |
156 | + } | |
157 | + | |
158 | + udelay(500); | |
159 | + | |
160 | + select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); | |
161 | + return 0; | |
162 | +} | |
163 | + | |
164 | +void diu_set_pixel_clock(unsigned int pixclock) | |
165 | +{ | |
166 | + unsigned long speed_ccb, temp; | |
167 | + u32 pixval; | |
168 | + int ret = 0; | |
169 | + speed_ccb = get_bus_freq(0); | |
170 | + temp = 1000000000 / pixclock; | |
171 | + temp *= 1000; | |
172 | + pixval = speed_ccb / temp; | |
173 | + | |
174 | + /* Program HDMI encoder */ | |
175 | + ret = diu_set_dvi_encoder(temp); | |
176 | + if (ret) { | |
177 | + puts("Failed to set DVI encoder\n"); | |
178 | + return; | |
179 | + } | |
180 | + | |
181 | + /* Program pixel clock */ | |
182 | + out_be32((unsigned *)CONFIG_SYS_FSL_SCFG_PIXCLK_ADDR, | |
183 | + ((pixval << PXCK_BITS_START) & PXCK_MASK)); | |
184 | + /* enable clock*/ | |
185 | + out_be32((unsigned *)CONFIG_SYS_FSL_SCFG_PIXCLK_ADDR, PXCKEN_MASK | | |
186 | + ((pixval << PXCK_BITS_START) & PXCK_MASK)); | |
187 | +} | |
188 | + | |
189 | +int platform_diu_init(unsigned int xres, unsigned int yres, const char *port) | |
190 | +{ | |
191 | + u32 pixel_format; | |
192 | + u8 sw; | |
193 | + | |
194 | + /*Route I2C4 to DIU system as HSYNC/VSYNC*/ | |
195 | + sw = QIXIS_READ(brdcfg[5]); | |
196 | + QIXIS_WRITE(brdcfg[5], | |
197 | + ((sw & ~(BRDCFG5_IMX_MASK)) | (BRDCFG5_IMX_DIU))); | |
198 | + | |
199 | + /*Configure Display ouput port as HDMI*/ | |
200 | + sw = QIXIS_READ(brdcfg[15]); | |
201 | + QIXIS_WRITE(brdcfg[15], | |
202 | + ((sw & ~(BRDCFG15_LCDPD_MASK | BRDCFG15_DIUSEL_MASK)) | |
203 | + | (BRDCFG15_LCDPD_ENABLED | BRDCFG15_DIUSEL_HDMI))); | |
204 | + | |
205 | + pixel_format = cpu_to_le32(AD_BYTE_F | (3 << AD_ALPHA_C_SHIFT) | | |
206 | + (0 << AD_BLUE_C_SHIFT) | (1 << AD_GREEN_C_SHIFT) | | |
207 | + (2 << AD_RED_C_SHIFT) | (8 << AD_COMP_3_SHIFT) | | |
208 | + (8 << AD_COMP_2_SHIFT) | (8 << AD_COMP_1_SHIFT) | | |
209 | + (8 << AD_COMP_0_SHIFT) | (3 << AD_PIXEL_S_SHIFT)); | |
210 | + | |
211 | + printf("DIU: Switching to monitor @ %ux%u\n", xres, yres); | |
212 | + | |
213 | + | |
214 | + return fsl_diu_init(xres, yres, pixel_format, 0); | |
215 | +} |
... | ... | @@ -13,6 +13,18 @@ |
13 | 13 | #define BRDCFG4_EMISEL_MASK 0xE0 |
14 | 14 | #define BRDCFG4_EMISEL_SHIFT 5 |
15 | 15 | |
16 | +/* BRDCFG5[0:1] controls routing and use of I2C3 & I2C4 ports*/ | |
17 | +#define BRDCFG5_IMX_MASK 0xC0 | |
18 | +#define BRDCFG5_IMX_DIU 0x80 | |
19 | + | |
20 | +/* BRDCFG15[3] controls LCD Panel Powerdown*/ | |
21 | +#define BRDCFG15_LCDPD_MASK 0x10 | |
22 | +#define BRDCFG15_LCDPD_ENABLED 0x00 | |
23 | + | |
24 | +/* BRDCFG15[6:7] controls DIU MUX selction*/ | |
25 | +#define BRDCFG15_DIUSEL_MASK 0x03 | |
26 | +#define BRDCFG15_DIUSEL_HDMI 0x00 | |
27 | + | |
16 | 28 | /* SYSCLK */ |
17 | 29 | #define QIXIS_SYSCLK_66 0x0 |
18 | 30 | #define QIXIS_SYSCLK_83 0x1 |
... | ... | @@ -375,7 +375,7 @@ |
375 | 375 | #define CONFIG_SYS_INIT_SP_OFFSET CONFIG_SYS_GBL_DATA_OFFSET |
376 | 376 | |
377 | 377 | #define CONFIG_SYS_MONITOR_LEN (512 * 1024) |
378 | -#define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024) | |
378 | +#define CONFIG_SYS_MALLOC_LEN (10 * 1024 * 1024) | |
379 | 379 | |
380 | 380 | /* Serial Port - controlled on board with jumper J8 |
381 | 381 | * open - index 2 |
... | ... | @@ -401,6 +401,25 @@ |
401 | 401 | #define CONFIG_SYS_HUSH_PARSER |
402 | 402 | #define CONFIG_SYS_PROMPT_HUSH_PS2 "> " |
403 | 403 | |
404 | +/* Video */ | |
405 | +#define CONFIG_FSL_DIU_FB | |
406 | +#ifdef CONFIG_FSL_DIU_FB | |
407 | +#define CONFIG_SYS_DIU_ADDR (CONFIG_SYS_CCSRBAR + 0x180000) | |
408 | +#define CONFIG_VIDEO | |
409 | +#define CONFIG_CMD_BMP | |
410 | +#define CONFIG_CFB_CONSOLE | |
411 | +#define CONFIG_VIDEO_SW_CURSOR | |
412 | +#define CONFIG_VGA_AS_SINGLE_DEVICE | |
413 | +#define CONFIG_VIDEO_LOGO | |
414 | +#define CONFIG_VIDEO_BMP_LOGO | |
415 | +#define CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS | |
416 | +/* | |
417 | + * With CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS, flash I/O is really slow, so | |
418 | + * disable empty flash sector detection, which is I/O-intensive. | |
419 | + */ | |
420 | +#undef CONFIG_SYS_FLASH_EMPTY_INFO | |
421 | +#endif | |
422 | + | |
404 | 423 | /* pass open firmware flat tree */ |
405 | 424 | #define CONFIG_OF_LIBFDT |
406 | 425 | #define CONFIG_OF_BOARD_SETUP |
407 | 426 | |
... | ... | @@ -426,7 +445,12 @@ |
426 | 445 | |
427 | 446 | /* I2C bus multiplexer */ |
428 | 447 | #define I2C_MUX_CH_DEFAULT 0x8 |
448 | +#define I2C_MUX_CH_DIU 0xC | |
429 | 449 | |
450 | +/* LDI/DVI Encoder for display */ | |
451 | +#define CONFIG_SYS_I2C_LDI_ADDR 0x38 | |
452 | +#define CONFIG_SYS_I2C_DVI_ADDR 0x75 | |
453 | + | |
430 | 454 | /* |
431 | 455 | * RTC configuration |
432 | 456 | */ |
... | ... | @@ -703,6 +727,7 @@ |
703 | 727 | "bank_intlv=cs0_cs1;" \ |
704 | 728 | "usb1:dr_mode=host,phy_type=" __stringify(__USB_PHY_TYPE) "\0"\ |
705 | 729 | "netdev=eth0\0" \ |
730 | + "video-mode=fslfb:1024x768-32@60,monitor=dvi\0" \ | |
706 | 731 | "uboot=" __stringify(CONFIG_UBOOTPATH) "\0" \ |
707 | 732 | "ubootaddr=" __stringify(CONFIG_SYS_TEXT_BASE) "\0" \ |
708 | 733 | "tftpflash=tftpboot $loadaddr $uboot && " \ |
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda
-
mentioned in commit cf8dda