1 #define USE_DVICHIP
2 #ifdef USE_DVICHIP
3 
4 #include "ddk750_sii164.h"
5 #include "ddk750_hwi2c.h"
6 
7 /* I2C Address of each SII164 chip */
8 #define SII164_I2C_ADDRESS                  0x70
9 
10 /* Define this definition to use hardware i2c. */
11 #define USE_HW_I2C
12 
13 #ifdef USE_HW_I2C
14     #define i2cWriteReg sm750_hw_i2c_write_reg
15     #define i2cReadReg  sm750_hw_i2c_read_reg
16 #else
17     #define i2cWriteReg swI2CWriteReg
18     #define i2cReadReg  swI2CReadReg
19 #endif
20 
21 /* SII164 Vendor and Device ID */
22 #define SII164_VENDOR_ID                    0x0001
23 #define SII164_DEVICE_ID                    0x0006
24 
25 #ifdef SII164_FULL_FUNCTIONS
26 /* Name of the DVI Controller chip */
27 static char *gDviCtrlChipName = "Silicon Image SiI 164";
28 #endif
29 
30 /*
31  *  sii164GetVendorID
32  *      This function gets the vendor ID of the DVI controller chip.
33  *
34  *  Output:
35  *      Vendor ID
36  */
37 unsigned short sii164GetVendorID(void)
38 {
39 	unsigned short vendorID;
40 
41 	vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) |
42 		    (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW);
43 
44 	return vendorID;
45 }
46 
47 /*
48  *  sii164GetDeviceID
49  *      This function gets the device ID of the DVI controller chip.
50  *
51  *  Output:
52  *      Device ID
53  */
54 unsigned short sii164GetDeviceID(void)
55 {
56 	unsigned short deviceID;
57 
58 	deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) |
59 		    (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW);
60 
61 	return deviceID;
62 }
63 
64 
65 
66 /* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */
67 
68 /*
69  *  sii164InitChip
70  *      This function initialize and detect the DVI controller chip.
71  *
72  *  Input:
73  *      edgeSelect          - Edge Select:
74  *                              0 = Input data is falling edge latched (falling edge
75  *                                  latched first in dual edge mode)
76  *                              1 = Input data is rising edge latched (rising edge
77  *                                  latched first in dual edge mode)
78  *      busSelect           - Input Bus Select:
79  *                              0 = Input data bus is 12-bits wide
80  *                              1 = Input data bus is 24-bits wide
81  *      dualEdgeClkSelect   - Dual Edge Clock Select
82  *                              0 = Input data is single edge latched
83  *                              1 = Input data is dual edge latched
84  *      hsyncEnable         - Horizontal Sync Enable:
85  *                              0 = HSYNC input is transmitted as fixed LOW
86  *                              1 = HSYNC input is transmitted as is
87  *      vsyncEnable         - Vertical Sync Enable:
88  *                              0 = VSYNC input is transmitted as fixed LOW
89  *                              1 = VSYNC input is transmitted as is
90  *      deskewEnable        - De-skewing Enable:
91  *                              0 = De-skew disabled
92  *                              1 = De-skew enabled
93  *      deskewSetting       - De-skewing Setting (increment of 260psec)
94  *                              0 = 1 step --> minimum setup / maximum hold
95  *                              1 = 2 step
96  *                              2 = 3 step
97  *                              3 = 4 step
98  *                              4 = 5 step
99  *                              5 = 6 step
100  *                              6 = 7 step
101  *                              7 = 8 step --> maximum setup / minimum hold
102  *      continuousSyncEnable- SYNC Continuous:
103  *                              0 = Disable
104  *                              1 = Enable
105  *      pllFilterEnable     - PLL Filter Enable
106  *                              0 = Disable PLL Filter
107  *                              1 = Enable PLL Filter
108  *      pllFilterValue      - PLL Filter characteristics:
109  *                              0~7 (recommended value is 4)
110  *
111  *  Output:
112  *      0   - Success
113  *     -1   - Fail.
114  */
115 long sii164InitChip(
116 	unsigned char edgeSelect,
117 	unsigned char busSelect,
118 	unsigned char dualEdgeClkSelect,
119 	unsigned char hsyncEnable,
120 	unsigned char vsyncEnable,
121 	unsigned char deskewEnable,
122 	unsigned char deskewSetting,
123 	unsigned char continuousSyncEnable,
124 	unsigned char pllFilterEnable,
125 	unsigned char pllFilterValue
126 )
127 {
128 	unsigned char config;
129 
130 	/* Initialize the i2c bus */
131 #ifdef USE_HW_I2C
132 	/* Use fast mode. */
133 	sm750_hw_i2c_init(1);
134 #else
135 	sm750_sw_i2c_init(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
136 #endif
137 
138 	/* Check if SII164 Chip exists */
139 	if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) {
140 		/*
141 		 *  Initialize SII164 controller chip.
142 		 */
143 
144 		/* Select the edge */
145 		if (edgeSelect == 0)
146 			config = SII164_CONFIGURATION_LATCH_FALLING;
147 		else
148 			config = SII164_CONFIGURATION_LATCH_RISING;
149 
150 		/* Select bus wide */
151 		if (busSelect == 0)
152 			config |= SII164_CONFIGURATION_BUS_12BITS;
153 		else
154 			config |= SII164_CONFIGURATION_BUS_24BITS;
155 
156 		/* Select Dual/Single Edge Clock */
157 		if (dualEdgeClkSelect == 0)
158 			config |= SII164_CONFIGURATION_CLOCK_SINGLE;
159 		else
160 			config |= SII164_CONFIGURATION_CLOCK_DUAL;
161 
162 		/* Select HSync Enable */
163 		if (hsyncEnable == 0)
164 			config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
165 		else
166 			config |= SII164_CONFIGURATION_HSYNC_AS_IS;
167 
168 		/* Select VSync Enable */
169 		if (vsyncEnable == 0)
170 			config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
171 		else
172 			config |= SII164_CONFIGURATION_VSYNC_AS_IS;
173 
174 		i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
175 
176 		/* De-skew enabled with default 111b value.
177 		   This will fix some artifacts problem in some mode on board 2.2.
178 		   Somehow this fix does not affect board 2.1.
179 		 */
180 		if (deskewEnable == 0)
181 			config = SII164_DESKEW_DISABLE;
182 		else
183 			config = SII164_DESKEW_ENABLE;
184 
185 		switch (deskewSetting) {
186 		case 0:
187 			config |= SII164_DESKEW_1_STEP;
188 			break;
189 		case 1:
190 			config |= SII164_DESKEW_2_STEP;
191 			break;
192 		case 2:
193 			config |= SII164_DESKEW_3_STEP;
194 			break;
195 		case 3:
196 			config |= SII164_DESKEW_4_STEP;
197 			break;
198 		case 4:
199 			config |= SII164_DESKEW_5_STEP;
200 			break;
201 		case 5:
202 			config |= SII164_DESKEW_6_STEP;
203 			break;
204 		case 6:
205 			config |= SII164_DESKEW_7_STEP;
206 			break;
207 		case 7:
208 			config |= SII164_DESKEW_8_STEP;
209 			break;
210 		}
211 		i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
212 
213 		/* Enable/Disable Continuous Sync. */
214 		if (continuousSyncEnable == 0)
215 			config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
216 		else
217 			config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
218 
219 		/* Enable/Disable PLL Filter */
220 		if (pllFilterEnable == 0)
221 			config |= SII164_PLL_FILTER_DISABLE;
222 		else
223 			config |= SII164_PLL_FILTER_ENABLE;
224 
225 		/* Set the PLL Filter value */
226 		config |= ((pllFilterValue & 0x07) << 1);
227 
228 		i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
229 
230 		/* Recover from Power Down and enable output. */
231 		config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
232 		config |= SII164_CONFIGURATION_POWER_NORMAL;
233 		i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
234 
235 		return 0;
236 	}
237 
238 	/* Return -1 if initialization fails. */
239 	return (-1);
240 }
241 
242 
243 
244 
245 
246 /* below sii164 function is not necessary */
247 
248 #ifdef SII164_FULL_FUNCTIONS
249 
250 /*
251  *  sii164ResetChip
252  *      This function resets the DVI Controller Chip.
253  */
254 void sii164ResetChip(void)
255 {
256 	/* Power down */
257 	sii164SetPower(0);
258 	sii164SetPower(1);
259 }
260 
261 
262 /*
263  * sii164GetChipString
264  *      This function returns a char string name of the current DVI Controller chip.
265  *      It's convenient for application need to display the chip name.
266  */
267 char *sii164GetChipString(void)
268 {
269 	return gDviCtrlChipName;
270 }
271 
272 
273 /*
274  *  sii164SetPower
275  *      This function sets the power configuration of the DVI Controller Chip.
276  *
277  *  Input:
278  *      powerUp - Flag to set the power down or up
279  */
280 void sii164SetPower(
281 	unsigned char powerUp
282 )
283 {
284 	unsigned char config;
285 
286 	config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
287 	if (powerUp == 1) {
288 		/* Power up the chip */
289 		config &= ~SII164_CONFIGURATION_POWER_MASK;
290 		config |= SII164_CONFIGURATION_POWER_NORMAL;
291 		i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
292 	} else {
293 		/* Power down the chip */
294 		config &= ~SII164_CONFIGURATION_POWER_MASK;
295 		config |= SII164_CONFIGURATION_POWER_DOWN;
296 		i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
297 	}
298 }
299 
300 
301 /*
302  *  sii164SelectHotPlugDetectionMode
303  *      This function selects the mode of the hot plug detection.
304  */
305 static void sii164SelectHotPlugDetectionMode(
306 	sii164_hot_plug_mode_t hotPlugMode
307 )
308 {
309 	unsigned char detectReg;
310 
311 	detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
312 	switch (hotPlugMode) {
313 	case SII164_HOTPLUG_DISABLE:
314 		detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
315 		break;
316 	case SII164_HOTPLUG_USE_MDI:
317 		detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
318 		detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
319 		detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
320 		break;
321 	case SII164_HOTPLUG_USE_RSEN:
322 		detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
323 		break;
324 	case SII164_HOTPLUG_USE_HTPLG:
325 		detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
326 		break;
327 	}
328 
329 	i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
330 }
331 
332 /*
333  *  sii164EnableHotPlugDetection
334  *      This function enables the Hot Plug detection.
335  *
336  *  enableHotPlug   - Enable (=1) / disable (=0) Hot Plug detection
337  */
338 void sii164EnableHotPlugDetection(
339 	unsigned char enableHotPlug
340 )
341 {
342 	unsigned char detectReg;
343 
344 	detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
345 
346 	/* Depending on each DVI controller, need to enable the hot plug based on each
347 	   individual chip design. */
348 	if (enableHotPlug != 0)
349 		sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
350 	else
351 		sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
352 }
353 
354 /*
355  *  sii164IsConnected
356  *      Check if the DVI Monitor is connected.
357  *
358  *  Output:
359  *      0   - Not Connected
360  *      1   - Connected
361  */
362 unsigned char sii164IsConnected(void)
363 {
364 	unsigned char hotPlugValue;
365 
366 	hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
367 	if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
368 		return 1;
369 	else
370 		return 0;
371 }
372 
373 /*
374  *  sii164CheckInterrupt
375  *      Checks if interrupt has occurred.
376  *
377  *  Output:
378  *      0   - No interrupt
379  *      1   - Interrupt occurs
380  */
381 unsigned char sii164CheckInterrupt(void)
382 {
383 	unsigned char detectReg;
384 
385 	detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
386 	if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
387 		return 1;
388 	else
389 		return 0;
390 }
391 
392 /*
393  *  sii164ClearInterrupt
394  *      Clear the hot plug interrupt.
395  */
396 void sii164ClearInterrupt(void)
397 {
398 	unsigned char detectReg;
399 
400 	/* Clear the MDI interrupt */
401 	detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
402 	i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
403 }
404 
405 #endif
406 
407 #endif
408 
409 
410