1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2014 Freescale Semiconductor, Inc.
4  * Copyright 2019 NXP
5  */
6 
7 #include <asm/io.h>
8 #include <common.h>
9 #include <fsl_dcu_fb.h>
10 #include <i2c.h>
11 #include <linux/fb.h>
12 
13 #define PIXEL_CLK_LSB_REG		0x00
14 #define PIXEL_CLK_MSB_REG		0x01
15 #define VERT_FREQ_LSB_REG		0x02
16 #define VERT_FREQ_MSB_REG		0x03
17 #define TOTAL_PIXELS_LSB_REG		0x04
18 #define TOTAL_PIXELS_MSB_REG		0x05
19 #define TOTAL_LINES_LSB_REG		0x06
20 #define TOTAL_LINES_MSB_REG		0x07
21 #define TPI_INBUS_FMT_REG		0x08
22 #define TPI_INPUT_FMT_REG		0x09
23 #define TPI_OUTPUT_FMT_REG		0x0A
24 #define TPI_SYS_CTRL_REG		0x1A
25 #define TPI_PWR_STAT_REG		0x1E
26 #define TPI_AUDIO_HANDING_REG		0x25
27 #define TPI_AUDIO_INTF_REG		0x26
28 #define TPI_AUDIO_FREQ_REG		0x27
29 #define TPI_SET_PAGE_REG		0xBC
30 #define TPI_SET_OFFSET_REG		0xBD
31 #define TPI_RW_ACCESS_REG		0xBE
32 #define TPI_TRANS_MODE_REG		0xC7
33 
34 #define TPI_INBUS_CLOCK_RATIO_1		(1 << 6)
35 #define TPI_INBUS_FULL_PIXEL_WIDE	(1 << 5)
36 #define TPI_INBUS_RISING_EDGE		(1 << 4)
37 #define TPI_INPUT_CLR_DEPTH_8BIT	(0 << 6)
38 #define TPI_INPUT_VRANGE_EXPAN_AUTO	(0 << 2)
39 #define TPI_INPUT_CLR_RGB		(0 << 0)
40 #define TPI_OUTPUT_CLR_DEPTH_8BIT	(0 << 6)
41 #define TPI_OUTPUT_VRANGE_COMPRE_AUTO	(0 << 2)
42 #define TPI_OUTPUT_CLR_HDMI_RGB		(0 << 0)
43 #define TPI_SYS_TMDS_OUTPUT		(0 << 4)
44 #define TPI_SYS_AV_NORAML		(0 << 3)
45 #define TPI_SYS_AV_MUTE			(1 << 3)
46 #define TPI_SYS_DVI_MODE		(0 << 0)
47 #define TPI_SYS_HDMI_MODE		(1 << 0)
48 #define TPI_PWR_STAT_MASK		(3 << 0)
49 #define TPI_PWR_STAT_D0			(0 << 0)
50 #define TPI_AUDIO_PASS_BASIC		(0 << 0)
51 #define TPI_AUDIO_INTF_I2S		(2 << 6)
52 #define TPI_AUDIO_INTF_NORMAL		(0 << 4)
53 #define TPI_AUDIO_TYPE_PCM		(1 << 0)
54 #define TPI_AUDIO_SAMP_SIZE_16BIT	(1 << 6)
55 #define TPI_AUDIO_SAMP_FREQ_44K		(2 << 3)
56 #define TPI_SET_PAGE_SII9022A		0x01
57 #define TPI_SET_OFFSET_SII9022A		0x82
58 #define TPI_RW_EN_SRC_TERMIN		(1 << 0)
59 #define TPI_TRANS_MODE_ENABLE		(0 << 7)
60 
61 /* Programming of Silicon SIi9022a HDMI Transmitter */
dcu_set_dvi_encoder(struct fb_videomode * videomode)62 int dcu_set_dvi_encoder(struct fb_videomode *videomode)
63 {
64 	u8 temp;
65 	u16 temp1, temp2;
66 	u32 temp3;
67 #if CONFIG_IS_ENABLED(DM_I2C)
68 	struct udevice *dev;
69 	int ret;
70 
71 	ret = i2c_get_chip_for_busnum(CONFIG_SYS_I2C_DVI_BUS_NUM,
72 				      CONFIG_SYS_I2C_DVI_ADDR,
73 				      1, &dev);
74 	if (ret) {
75 		printf("%s: Cannot find udev for a bus %d\n", __func__,
76 		       CONFIG_SYS_I2C_DVI_BUS_NUM);
77 		return ret;
78 	}
79 
80 	/* Enable TPI transmitter mode */
81 	temp = TPI_TRANS_MODE_ENABLE;
82 	dm_i2c_write(dev, TPI_TRANS_MODE_REG, &temp, 1);
83 
84 	/* Enter into D0 state, full operation */
85 	dm_i2c_read(dev, TPI_PWR_STAT_REG, &temp, 1);
86 	temp &= ~TPI_PWR_STAT_MASK;
87 	temp |= TPI_PWR_STAT_D0;
88 	dm_i2c_write(dev, TPI_PWR_STAT_REG, &temp, 1);
89 
90 	/* Enable source termination */
91 	temp = TPI_SET_PAGE_SII9022A;
92 	dm_i2c_write(dev, TPI_SET_PAGE_REG, &temp, 1);
93 	temp = TPI_SET_OFFSET_SII9022A;
94 	dm_i2c_write(dev, TPI_SET_OFFSET_REG, &temp, 1);
95 
96 	dm_i2c_read(dev, TPI_RW_ACCESS_REG, &temp, 1);
97 	temp |= TPI_RW_EN_SRC_TERMIN;
98 	dm_i2c_write(dev, TPI_RW_ACCESS_REG, &temp, 1);
99 
100 	/* Set TPI system control */
101 	temp = TPI_SYS_TMDS_OUTPUT | TPI_SYS_AV_NORAML | TPI_SYS_DVI_MODE;
102 	dm_i2c_write(dev, TPI_SYS_CTRL_REG, &temp, 1);
103 
104 	/* Set pixel clock */
105 	temp1 = PICOS2KHZ(videomode->pixclock) / 10;
106 	temp = (u8)(temp1 & 0xFF);
107 	dm_i2c_write(dev, PIXEL_CLK_LSB_REG, &temp, 1);
108 	temp = (u8)(temp1 >> 8);
109 	dm_i2c_write(dev, PIXEL_CLK_MSB_REG, &temp, 1);
110 
111 	/* Set total pixels per line */
112 	temp1 = videomode->hsync_len + videomode->left_margin +
113 		videomode->xres + videomode->right_margin;
114 	temp = (u8)(temp1 & 0xFF);
115 	dm_i2c_write(dev, TOTAL_PIXELS_LSB_REG, &temp, 1);
116 	temp = (u8)(temp1 >> 8);
117 	dm_i2c_write(dev, TOTAL_PIXELS_MSB_REG, &temp, 1);
118 
119 	/* Set total lines */
120 	temp2 = videomode->vsync_len + videomode->upper_margin +
121 		videomode->yres + videomode->lower_margin;
122 	temp = (u8)(temp2 & 0xFF);
123 	dm_i2c_write(dev, TOTAL_LINES_LSB_REG, &temp, 1);
124 	temp = (u8)(temp2 >> 8);
125 	dm_i2c_write(dev, TOTAL_LINES_MSB_REG, &temp, 1);
126 
127 	/* Set vertical frequency in Hz */
128 	temp3 = temp1 * temp2;
129 	temp3 = (PICOS2KHZ(videomode->pixclock) * 1000) / temp3;
130 	temp1 = (u16)temp3 * 100;
131 	temp = (u8)(temp1 & 0xFF);
132 	dm_i2c_write(dev, VERT_FREQ_LSB_REG, &temp, 1);
133 	temp = (u8)(temp1 >> 8);
134 	dm_i2c_write(dev, VERT_FREQ_MSB_REG, &temp, 1);
135 
136 	/* Set TPI input bus and pixel repetition data */
137 	temp = TPI_INBUS_CLOCK_RATIO_1 | TPI_INBUS_FULL_PIXEL_WIDE |
138 		TPI_INBUS_RISING_EDGE;
139 	dm_i2c_write(dev, TPI_INBUS_FMT_REG, &temp, 1);
140 
141 	/* Set TPI AVI Input format data */
142 	temp = TPI_INPUT_CLR_DEPTH_8BIT | TPI_INPUT_VRANGE_EXPAN_AUTO |
143 		TPI_INPUT_CLR_RGB;
144 	dm_i2c_write(dev, TPI_INPUT_FMT_REG, &temp, 1);
145 
146 	/* Set TPI AVI Output format data */
147 	temp = TPI_OUTPUT_CLR_DEPTH_8BIT | TPI_OUTPUT_VRANGE_COMPRE_AUTO |
148 		TPI_OUTPUT_CLR_HDMI_RGB;
149 	dm_i2c_write(dev, TPI_OUTPUT_FMT_REG, &temp, 1);
150 
151 	/* Set TPI audio configuration write data */
152 	temp = TPI_AUDIO_PASS_BASIC;
153 	dm_i2c_write(dev, TPI_AUDIO_HANDING_REG, &temp, 1);
154 
155 	temp = TPI_AUDIO_INTF_I2S | TPI_AUDIO_INTF_NORMAL |
156 		TPI_AUDIO_TYPE_PCM;
157 	dm_i2c_write(dev, TPI_AUDIO_INTF_REG, &temp, 1);
158 
159 	temp = TPI_AUDIO_SAMP_SIZE_16BIT | TPI_AUDIO_SAMP_FREQ_44K;
160 	dm_i2c_write(dev, TPI_AUDIO_FREQ_REG, &temp, 1);
161 #else
162 	i2c_set_bus_num(CONFIG_SYS_I2C_DVI_BUS_NUM);
163 
164 	/* Enable TPI transmitter mode */
165 	temp = TPI_TRANS_MODE_ENABLE;
166 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_TRANS_MODE_REG, 1, &temp, 1);
167 
168 	/* Enter into D0 state, full operation */
169 	i2c_read(CONFIG_SYS_I2C_DVI_ADDR, TPI_PWR_STAT_REG, 1, &temp, 1);
170 	temp &= ~TPI_PWR_STAT_MASK;
171 	temp |= TPI_PWR_STAT_D0;
172 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_PWR_STAT_REG, 1, &temp, 1);
173 
174 	/* Enable source termination */
175 	temp = TPI_SET_PAGE_SII9022A;
176 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_SET_PAGE_REG, 1, &temp, 1);
177 	temp = TPI_SET_OFFSET_SII9022A;
178 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_SET_OFFSET_REG, 1, &temp, 1);
179 
180 	i2c_read(CONFIG_SYS_I2C_DVI_ADDR, TPI_RW_ACCESS_REG, 1, &temp, 1);
181 	temp |= TPI_RW_EN_SRC_TERMIN;
182 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_RW_ACCESS_REG, 1, &temp, 1);
183 
184 	/* Set TPI system control */
185 	temp = TPI_SYS_TMDS_OUTPUT | TPI_SYS_AV_NORAML | TPI_SYS_DVI_MODE;
186 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_SYS_CTRL_REG, 1, &temp, 1);
187 
188 	/* Set pixel clock */
189 	temp1 = PICOS2KHZ(videomode->pixclock) / 10;
190 	temp = (u8)(temp1 & 0xFF);
191 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, PIXEL_CLK_LSB_REG, 1, &temp, 1);
192 	temp = (u8)(temp1 >> 8);
193 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, PIXEL_CLK_MSB_REG, 1, &temp, 1);
194 
195 	/* Set total pixels per line */
196 	temp1 = videomode->hsync_len + videomode->left_margin +
197 		videomode->xres + videomode->right_margin;
198 	temp = (u8)(temp1 & 0xFF);
199 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TOTAL_PIXELS_LSB_REG, 1, &temp, 1);
200 	temp = (u8)(temp1 >> 8);
201 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TOTAL_PIXELS_MSB_REG, 1, &temp, 1);
202 
203 	/* Set total lines */
204 	temp2 = videomode->vsync_len + videomode->upper_margin +
205 		videomode->yres + videomode->lower_margin;
206 	temp = (u8)(temp2 & 0xFF);
207 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TOTAL_LINES_LSB_REG, 1, &temp, 1);
208 	temp = (u8)(temp2 >> 8);
209 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TOTAL_LINES_MSB_REG, 1, &temp, 1);
210 
211 	/* Set vertical frequency in Hz */
212 	temp3 = temp1 * temp2;
213 	temp3 = (PICOS2KHZ(videomode->pixclock) * 1000) / temp3;
214 	temp1 = (u16)temp3 * 100;
215 	temp = (u8)(temp1 & 0xFF);
216 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, VERT_FREQ_LSB_REG, 1, &temp, 1);
217 	temp = (u8)(temp1 >> 8);
218 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, VERT_FREQ_MSB_REG, 1, &temp, 1);
219 
220 	/* Set TPI input bus and pixel repetition data */
221 	temp = TPI_INBUS_CLOCK_RATIO_1 | TPI_INBUS_FULL_PIXEL_WIDE |
222 		TPI_INBUS_RISING_EDGE;
223 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_INBUS_FMT_REG, 1, &temp, 1);
224 
225 	/* Set TPI AVI Input format data */
226 	temp = TPI_INPUT_CLR_DEPTH_8BIT | TPI_INPUT_VRANGE_EXPAN_AUTO |
227 		TPI_INPUT_CLR_RGB;
228 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_INPUT_FMT_REG, 1, &temp, 1);
229 
230 	/* Set TPI AVI Output format data */
231 	temp = TPI_OUTPUT_CLR_DEPTH_8BIT | TPI_OUTPUT_VRANGE_COMPRE_AUTO |
232 		TPI_OUTPUT_CLR_HDMI_RGB;
233 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_OUTPUT_FMT_REG, 1, &temp, 1);
234 
235 	/* Set TPI audio configuration write data */
236 	temp = TPI_AUDIO_PASS_BASIC;
237 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_AUDIO_HANDING_REG, 1, &temp, 1);
238 
239 	temp = TPI_AUDIO_INTF_I2S | TPI_AUDIO_INTF_NORMAL |
240 		TPI_AUDIO_TYPE_PCM;
241 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_AUDIO_INTF_REG, 1, &temp, 1);
242 
243 	temp = TPI_AUDIO_SAMP_SIZE_16BIT | TPI_AUDIO_SAMP_FREQ_44K;
244 	i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_AUDIO_FREQ_REG, 1, &temp, 1);
245 #endif
246 
247 	return 0;
248 }
249