import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / hdmi / internal_hdmi / mt8127 / hdmiddc.c
CommitLineData
6fa3eb70
S
1 /******************************************************************************
2*[File] tx9134ddc.c
3*[Version] v0.1
4*[Revision Date] 2008-04-18
5*[Author] Kenny Hsieh
6*[Description]
7* source file for hdmi general control routine
8*
9*
10******************************************************************************/
11#ifdef CONFIG_MTK_INTERNAL_HDMI_SUPPORT
12
13#include "hdmi_ctrl.h"
14#include "hdmiddc.h"
15#include <mach/mt_pmic_wrap.h>
16
17#define HDMIDDC_BASE (0xF1013000)
18
19void internal_ddc_read(unsigned int u4Reg, unsigned int *p4Data)
20{
21 *p4Data = (*(volatile unsigned int*)(u4Reg));
22}
23
24void internal_ddc_write(unsigned int u4Reg, unsigned int u4data)
25{
26 *(volatile unsigned int*)(u4Reg) = (u4data);
27}
28
29unsigned int hdmi_ddc_read(unsigned short u2Reg)
30{
31 unsigned int u4Data;
32 internal_ddc_read(HDMIDDC_BASE+u2Reg, &u4Data);
33
34 HDMI_DDC_LOG("[R]ddc = 0x%04x, data = 0x%08x\n", u2Reg, u4Data);
35 return u4Data;
36}
37
38void hdmi_ddc_write(unsigned short u2Reg, unsigned int u4Data)
39{
40 internal_ddc_write(HDMIDDC_BASE+u2Reg, u4Data);
41
42 HDMI_DDC_LOG("[W]ddc = 0x%04x, data = 0x%08x\n", u2Reg, u4Data);
43}
44
45#define SIF_READ32(u4Addr) (hdmi_ddc_read(u4Addr))
46#define SIF_WRITE32(u4Addr, u4Val) (hdmi_ddc_write(u4Addr, u4Val))
47
48#define SIF_SET_BIT(u4Addr, u4Val) SIF_WRITE32((u4Addr), (SIF_READ32(u4Addr) | (u4Val)))
49#define SIF_CLR_BIT(u4Addr, u4Val) SIF_WRITE32((u4Addr), (SIF_READ32(u4Addr) & (~(u4Val))))
50
51#define IS_SIF_BIT(u4Addr, u4Val) ((SIF_READ32(u4Addr) & (u4Val)) == (u4Val))
52
53#define SIF_WRITE_MASK(u4Addr, u4Mask, u4Offet, u4Val) SIF_WRITE32(u4Addr, ((SIF_READ32(u4Addr) & (~(u4Mask))) | (((u4Val) << (u4Offet)) & (u4Mask))))
54#define SIF_READ_MASK(u4Addr, u4Mask, u4Offet) ((SIF_READ32(u4Addr) & (u4Mask)) >> (u4Offet))
55
56#define DDCM_DATA0_READ() SIF_READ_MASK(DDC_DDCMD0, DDCM_DATA0, 0)
57#define DDCM_DATA1_READ() SIF_READ_MASK(DDC_DDCMD0, DDCM_DATA1, 8)
58#define DDCM_DATA2_READ() SIF_READ_MASK(DDC_DDCMD0, DDCM_DATA2, 16)
59#define DDCM_DATA3_READ() SIF_READ_MASK(DDC_DDCMD0, DDCM_DATA3, 24)
60#define DDCM_DATA4_READ() SIF_READ_MASK(DDC_DDCMD1, DDCM_DATA4, 0)
61#define DDCM_DATA5_READ() SIF_READ_MASK(DDC_DDCMD1, DDCM_DATA5, 8)
62#define DDCM_DATA6_READ() SIF_READ_MASK(DDC_DDCMD1, DDCM_DATA6, 16)
63#define DDCM_DATA7_READ() SIF_READ_MASK(DDC_DDCMD1, DDCM_DATA7, 24)
64
65#define DDCM_DATA0_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMD0, DDCM_DATA0, 0, u4Val)
66#define DDCM_DATA1_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMD0, DDCM_DATA1, 8, u4Val)
67#define DDCM_DATA2_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMD0, DDCM_DATA2, 16, u4Val)
68#define DDCM_DATA3_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMD0, DDCM_DATA3, 24, u4Val)
69#define DDCM_DATA4_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMD1, DDCM_DATA4, 0, u4Val)
70#define DDCM_DATA5_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMD1, DDCM_DATA5, 8, u4Val)
71#define DDCM_DATA6_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMD1, DDCM_DATA6, 16, u4Val)
72#define DDCM_DATA7_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMD1, DDCM_DATA7, 24, u4Val)
73
74#define DDCM_CLK_DIV_READ() SIF_READ_MASK(DDC_DDCMCTL0, DDCM_CLK_DIV_MASK, DDCM_CLK_DIV_OFFSET)
75#define DDCM_CLK_DIV_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMCTL0, DDCM_CLK_DIV_MASK, DDCM_CLK_DIV_OFFSET, u4Val)
76
77#define DDCM_ACK_READ() SIF_READ_MASK(DDC_DDCMCTL1, DDCM_ACK_MASK, DDCM_ACK_OFFSET)
78
79#define DDCM_PGLEN_READ() SIF_READ_MASK(DDC_DDCMCTL1, DDCM_PGLEN_MASK, DDCM_PGLEN_OFFSET)
80#define DDCM_PGLEN_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMCTL1, DDCM_PGLEN_MASK, DDCM_PGLEN_OFFSET, u4Val)
81
82#define DDCM_SIF_MODE_READ() SIF_READ_MASK(DDC_DDCMCTL1, DDCM_SIF_MODE_MASK, DDCM_SIF_MODE_OFFSET)
83#define DDCM_SIF_MODE_WRITE(u4Val) SIF_WRITE_MASK(DDC_DDCMCTL1, DDCM_SIF_MODE_MASK, DDCM_SIF_MODE_OFFSET, u4Val)
84
85
86int i4DDCM_Suspend(void *param)
87{
88 HDMI_DDC_FUNC();
89 //SIF_CLR_BIT(SIF_INTEN, DDCCI_INTEN);
90 SIF_CLR_BIT(DDC_DDCMCTL0, DDCM_SM0EN);
91
92 return 0;
93}
94
95int i4DDCM_Resume(void *param)
96{
97 HDMI_DDC_FUNC();
98
99 SIF_SET_BIT(DDC_DDCMCTL0, DDCM_SM0EN);
100 //SIF_SET_BIT(SIF_INTEN, DDCCI_INTEN);
101
102 return 0;
103}
104
105unsigned int DDCM_Init(void)
106{
107 HDMI_DDC_FUNC();
108 SIF_SET_BIT(DDC_DDCMCTL0, DDCM_SM0EN);
109 SIF_CLR_BIT(DDC_DDCMCTL0, DDCM_ODRAIN);
110
111 return 1;
112}
113
114static unsigned int DDCM_TrigMode(unsigned int u4Mode)
115{
116 HDMI_DDC_FUNC();
117
118 DDCM_SIF_MODE_WRITE(u4Mode);
119 SIF_SET_BIT(DDC_DDCMCTL1,DDCM_TRI);
120
121 while(IS_SIF_BIT(DDC_DDCMCTL1,DDCM_TRI)){udelay(2);}
122
123 return (0);
124}
125
126static unsigned char _DDCMRead(unsigned char ucCurAddrMode, unsigned int u4ClkDiv, unsigned char ucDev, unsigned int u4Addr, SIF_BIT_T ucAddrType, unsigned char *pucValue, unsigned int u4Count)
127{
128 unsigned int u4Ack;
129 unsigned char ucReadCount, ucIdx, ucAckCount, ucAckFinal, ucTmpCount;
130
131 HDMI_DDC_FUNC();
132 DDCM_Init();
133 if ((pucValue == NULL) ||
134 (u4Count == 0)||
135 (u4ClkDiv == 0))
136 {
137 return 0;
138 }
139
140 ucIdx = 0;
141
142 // check busy/trigger bit
143 if (IS_SIF_BIT(DDC_DDCMCTL1, DDCM_TRI))
144 {
145 return 0;
146 }
147
148
149 DDCM_CLK_DIV_WRITE(u4ClkDiv);
150
151 DDCM_TrigMode(DDCM_START);
152
153 if (ucDev > EDID_ID) //Max'0619'04, 4-block EEDID reading
154 {
155 DDCM_DATA0_WRITE(0x60);
156
157 DDCM_DATA1_WRITE(ucDev-EDID_ID);
158 DDCM_PGLEN_WRITE(0x01);
159 DDCM_TrigMode(DDCM_WRITE_DATA);
160 u4Ack = DDCM_ACK_READ();
161 if(u4Ack != 0x3)
162 {
163 goto ddc_master_read_end;
164 }
165 DDCM_TrigMode(DDCM_START);
166 ucDev = EDID_ID;
167 }
168
169 if(ucCurAddrMode == 0)
170 {
171 DDCM_DATA0_WRITE((ucDev<<1));
172
173 if(ucAddrType == SIF_8_BIT)
174 {
175 DDCM_DATA1_WRITE(u4Addr);
176 DDCM_PGLEN_WRITE(0x01);
177 DDCM_TrigMode(DDCM_WRITE_DATA);
178 u4Ack = DDCM_ACK_READ();
179 if(u4Ack != 0x3)
180 {
181 goto ddc_master_read_end;
182 }
183 }
184 else if(ucAddrType == SIF_16_BIT)
185 {
186 DDCM_DATA1_WRITE((u4Addr>>8));
187 DDCM_DATA2_WRITE(u4Addr);
188 DDCM_PGLEN_WRITE(0x02);
189 DDCM_TrigMode(DDCM_WRITE_DATA);
190 u4Ack = DDCM_ACK_READ();
191 if(u4Ack != 0x7)
192 {
193 goto ddc_master_read_end;
194 }
195 }
196
197 DDCM_TrigMode(DDCM_START);
198 }
199
200 DDCM_DATA0_WRITE(((ucDev<<1) + 1));
201 DDCM_PGLEN_WRITE(0x00);
202 DDCM_TrigMode(DDCM_WRITE_DATA);
203 u4Ack = DDCM_ACK_READ();
204 if(u4Ack != 0x1)
205 {
206 goto ddc_master_read_end;
207 }
208
209 ucAckCount = (u4Count-1)/8;
210 ucAckFinal = 0;
211 while (u4Count > 0)
212 {
213 if(ucAckCount > 0)
214 {
215 ucReadCount = 8;
216 ucAckFinal = 0;
217 ucAckCount --;
218 }
219 else
220 {
221 ucReadCount = (unsigned char)u4Count;
222 ucAckFinal = 1;
223 }
224
225 DDCM_PGLEN_WRITE((ucReadCount - 1));
226 DDCM_TrigMode((ucAckFinal == 1)? DDCM_READ_DATA_NO_ACK: DDCM_READ_DATA_ACK);
227
228 //ack, killua
229 u4Ack = DDCM_ACK_READ();
230 for(ucTmpCount = 0; ((u4Ack & (1 << ucTmpCount)) != 0) && (ucTmpCount < 8); ucTmpCount++){}
231 if(((ucAckFinal == 1) && (ucTmpCount != (ucReadCount - 1)))
232 ||((ucAckFinal == 0) && (ucTmpCount != ucReadCount)))
233 {
234 HDMI_DDC_LOG("[DDC] Device(0x%x)/Word(0x%x) Address NACK! ACK(0x%x)\n", ucDev, u4Addr, u4Ack);
235 break;
236 }
237
238 switch(ucReadCount)
239 {
240 case 8:
241 pucValue[ucIdx + 7] = DDCM_DATA7_READ();
242 case 7:
243 pucValue[ucIdx + 6] = DDCM_DATA6_READ();
244 case 6:
245 pucValue[ucIdx + 5] = DDCM_DATA5_READ();
246 case 5:
247 pucValue[ucIdx + 4] = DDCM_DATA4_READ();
248 case 4:
249 pucValue[ucIdx + 3] = DDCM_DATA3_READ();
250 case 3:
251 pucValue[ucIdx + 2] = DDCM_DATA2_READ();
252 case 2:
253 pucValue[ucIdx + 1] = DDCM_DATA1_READ();
254 case 1:
255 pucValue[ucIdx + 0] = DDCM_DATA0_READ();
256 default:
257 break;
258 }
259
260 u4Count -= ucReadCount;
261 ucIdx += ucReadCount;
262 }
263
264ddc_master_read_end:
265 DDCM_TrigMode(DDCM_STOP);
266 return ucIdx;
267}
268
269static unsigned char _DDCMWrite(unsigned char ucCurAddrMode, unsigned int u4ClkDiv, unsigned char ucDev, unsigned int u4Addr, SIF_BIT_T ucAddrType, const unsigned char *pucValue, unsigned int u4Count)
270{
271 unsigned int u4Ack;
272 unsigned char ucWriteCount, ucIdx, ucTmpCount;
273
274 HDMI_DDC_FUNC();
275 DDCM_Init();
276 if ((pucValue == NULL) ||
277 (u4Count == 0)||
278 (u4ClkDiv == 0))
279 {
280 return 0;
281 }
282
283 ucIdx = 0;
284
285 // check busy/trigger bit
286 if (IS_SIF_BIT(DDC_DDCMCTL1, DDCM_TRI))
287 {
288 return 0;
289 }
290
291
292
293 DDCM_CLK_DIV_WRITE(u4ClkDiv);
294
295 DDCM_TrigMode(DDCM_START);
296
297 DDCM_DATA0_WRITE((ucDev<<1));
298 if(ucAddrType == SIF_8_BIT)
299 {
300 DDCM_DATA1_WRITE(u4Addr);
301 DDCM_PGLEN_WRITE(0x01);
302 DDCM_TrigMode(DDCM_WRITE_DATA);
303 u4Ack = DDCM_ACK_READ();
304 if(u4Ack != 0x3)
305 {
306 goto ddc_master_write_end;
307 }
308 }
309 else if(ucAddrType == SIF_16_BIT)
310 {
311 DDCM_DATA1_WRITE((u4Addr>>8));
312 DDCM_DATA2_WRITE(u4Addr);
313 DDCM_PGLEN_WRITE(0x02);
314 DDCM_TrigMode(DDCM_WRITE_DATA);
315 u4Ack = DDCM_ACK_READ();
316 if(u4Ack != 0x7)
317 {
318 goto ddc_master_write_end;
319 }
320 }
321
322 while (u4Count > 0)
323 {
324 ucWriteCount = (u4Count > 8) ? 8 : ((unsigned char)u4Count);
325
326 switch(ucWriteCount)
327 {
328 case 8:
329 DDCM_DATA7_WRITE(pucValue[ucIdx + 7]);
330 case 7:
331 DDCM_DATA6_WRITE(pucValue[ucIdx + 6]);
332 case 6:
333 DDCM_DATA5_WRITE(pucValue[ucIdx + 5]);
334 case 5:
335 DDCM_DATA4_WRITE(pucValue[ucIdx + 4]);
336 case 4:
337 DDCM_DATA3_WRITE(pucValue[ucIdx + 3]);
338 case 3:
339 DDCM_DATA2_WRITE(pucValue[ucIdx + 2]);
340 case 2:
341 DDCM_DATA1_WRITE(pucValue[ucIdx + 1]);
342 case 1:
343 DDCM_DATA0_WRITE(pucValue[ucIdx + 0]);
344 default:
345 break;
346 }
347
348 DDCM_PGLEN_WRITE((ucWriteCount - 1));
349 DDCM_TrigMode(DDCM_WRITE_DATA);
350
351 //ack, killua
352 u4Ack = DDCM_ACK_READ();
353 for(ucTmpCount = 0; ((u4Ack & (1 << ucTmpCount)) != 0) && (ucTmpCount < 8); ucTmpCount++){}
354 if(ucTmpCount != ucWriteCount)
355 {
356 HDMI_DDC_LOG("[DDC] Device(0x%x)/Word(0x%x) Address NACK! ACK(0x%x)\n", ucDev, u4Addr, u4Ack);
357 break;
358 }
359
360 u4Count -= ucWriteCount;
361 ucIdx += ucWriteCount;
362 }
363
364ddc_master_write_end:
365 DDCM_TrigMode(DDCM_STOP);
366 return ucIdx;
367}
368
369unsigned int DDCM_RanAddr_Write(unsigned int u4ClkDiv, unsigned char ucDev, unsigned int u4Addr, SIF_BIT_T ucAddrType, const unsigned char *pucValue, unsigned int u4Count)
370{
371 unsigned int u4WriteCount1;
372 unsigned char ucReturnVaule;
373
374 HDMI_DDC_FUNC();
375
376 if ((pucValue == NULL) ||
377 (u4Count == 0)||
378 (u4ClkDiv == 0)||
379 (ucAddrType > SIF_16_BIT)||
380 ((ucAddrType == SIF_8_BIT) && (u4Addr > 255)) ||
381 ((ucAddrType == SIF_16_BIT) && (u4Addr > 65535)))
382 {
383 return 0;
384 }
385
386
387 if(ucAddrType == SIF_8_BIT)
388 {
389 u4WriteCount1 = ((255 - u4Addr) + 1);
390 }
391 else if(ucAddrType == SIF_16_BIT)
392 {
393 u4WriteCount1 = ((65535 - u4Addr) + 1);
394 }
395 u4WriteCount1 = (u4WriteCount1 > u4Count) ? u4Count : u4WriteCount1;
396 ucReturnVaule = _DDCMWrite(0,u4ClkDiv, ucDev, u4Addr, ucAddrType, pucValue, u4WriteCount1);
397
398 return ((unsigned int)ucReturnVaule);
399}
400
401unsigned int DDCM_CurAddr_Read(unsigned int u4ClkDiv, unsigned char ucDev, unsigned char *pucValue, unsigned int u4Count)
402{
403 unsigned char ucReturnVaule;
404
405 HDMI_DDC_FUNC();
406
407 if ((pucValue == NULL) ||
408 (u4Count == 0)||
409 (u4ClkDiv == 0))
410 {
411 return 0;
412 }
413
414 ucReturnVaule = _DDCMRead(1,u4ClkDiv, ucDev, 0, SIF_8_BIT, pucValue, u4Count);
415
416 return ((UINT32)ucReturnVaule);
417}
418
419unsigned char DDCM_RanAddr_Read(unsigned int u4ClkDiv, unsigned char ucDev, unsigned int u4Addr, SIF_BIT_T ucAddrType, unsigned char *pucValue, unsigned int u4Count)
420{
421 unsigned int u4ReadCount;
422 unsigned char ucReturnVaule;
423
424 HDMI_DDC_FUNC();
425 if ((pucValue == NULL) ||
426 (u4Count == 0)||
427 (u4ClkDiv == 0)||
428 (ucAddrType > SIF_16_BIT)||
429 ((ucAddrType == SIF_8_BIT) && (u4Addr > 255)) ||
430 ((ucAddrType == SIF_16_BIT) && (u4Addr > 65535)))
431 {
432 return 0;
433 }
434
435 if(ucAddrType == SIF_8_BIT)
436 {
437 u4ReadCount = ((255 - u4Addr) + 1);
438 }
439 else if(ucAddrType == SIF_16_BIT)
440 {
441 u4ReadCount = ((65535 - u4Addr) + 1);
442 }
443 u4ReadCount = (u4ReadCount > u4Count) ? u4Count : u4ReadCount;
444 ucReturnVaule = _DDCMRead(0, u4ClkDiv, ucDev, u4Addr, ucAddrType, pucValue, u4ReadCount);
445
446
447 return (ucReturnVaule);
448}
449
450unsigned char fgDDCDataRead(unsigned char bDevice, unsigned char bData_Addr, unsigned char bDataCount,unsigned char *prData)
451{
452 HDMI_DDC_FUNC();
453 if(DDCM_RanAddr_Read(SIF1_CLOK, (unsigned char)bDevice, (unsigned int)bData_Addr, SIF_8_BIT, (unsigned char *)prData, (unsigned int)bDataCount)== bDataCount)
454 return TRUE;
455 else
456 return FALSE;
457}
458
459unsigned char fgDDCDataWrite(unsigned char bDevice, unsigned char bData_Addr, unsigned char bDataCount,unsigned char *prData)
460{
461 HDMI_DDC_FUNC();
462 if((DDCM_RanAddr_Write(SIF1_CLOK, (unsigned char)bDevice, (unsigned int) bData_Addr, SIF_8_BIT, (unsigned char *)prData, (unsigned int)bDataCount))== bDataCount)
463 return TRUE;
464 else
465 return FALSE;
466}
467
468
469#endif
470