blob: ffd074b0f8cac70f8d824b92cfd57c358ad239e8 [file] [log] [blame]
Priyanka Jain337b0c52014-02-26 16:11:53 +05301/*
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 */
73int 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
164void 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
189int 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}