1 #include <linux/delay.h>
\r
2 #include <linux/mfd/rk610_core.h>
\r
3 #include "rk610_hdmi.h"
\r
4 #include "rk610_hdmi_hw.h"
\r
5 static struct rk610_hdmi_hw_inf g_hw_inf;
\r
6 static EDID_INF g_edid;
\r
7 static byte edid_buf[EDID_BLOCK_SIZE];
\r
8 static struct edid_result Rk610_edid_result;
\r
9 byte DoEdidRead (struct i2c_client *client);
\r
10 static int RK610_hdmi_soft_reset(struct i2c_client *client);
\r
11 static int Rk610_hdmi_Display_switch(struct i2c_client *client);
\r
12 static void Rk610_hdmi_plug(struct i2c_client *client);
\r
13 static void Rk610_hdmi_unplug(struct i2c_client *client);
\r
15 static int Rk610_hdmi_i2c_read_p0_reg(struct i2c_client *client, char reg, char *val)
\r
17 return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
\r
19 static int Rk610_hdmi_i2c_write_p0_reg(struct i2c_client *client, char reg, char *val)
\r
21 return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
\r
24 static int Rk610_hdmi_pwr_mode(struct i2c_client *client, int mode)
\r
31 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe4, &c);
\r
33 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe7, &c);
\r
35 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c);
\r
37 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c);
\r
39 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c);
\r
43 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe3, &c);
\r
45 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c);
\r
47 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c);
\r
49 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe7, &c);
\r
51 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe4, &c);
\r
54 RK610_ERR(&client->dev,"unkown rk610 hdmi pwr mode %d\n",mode);
\r
59 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
60 int Rk610_hdmi_suspend(struct i2c_client *client)
\r
63 RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
\r
64 g_hw_inf.suspend_flag = 1;
\r
66 Rk610_hdmi_unplug(client);
\r
69 int Rk610_hdmi_resume(struct i2c_client *client)
\r
73 RK610_DBG(&client->dev, "%s \n",__FUNCTION__);
\r
74 Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c);
\r
75 if(c & RK610_HPD_PLUG ){
\r
76 Rk610_hdmi_plug(client);
\r
80 Rk610_hdmi_unplug(client);
\r
83 g_hw_inf.suspend_flag = 0;
\r
87 static int Rk610_hdmi_sys_power_down(struct i2c_client *client)
\r
91 RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
\r
92 c= RK610_SYS_CLK<<2 |RK610_SYS_PWR_OFF<<1 |RK610_INT_POL;
\r
93 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x00, &c);
\r
96 static int Rk610_hdmi_sys_power_up(struct i2c_client *client)
\r
100 RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
\r
101 c= RK610_SYS_CLK<<2 |RK610_SYS_PWR_ON<<1 |RK610_INT_POL;
\r
102 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x00, &c);
\r
105 //X=11.2896M/(4*100k), X = {0x4c,0x4b}
\r
106 static int RK610_DDC_BUS_CONFIG(struct i2c_client *client)
\r
110 c= RK610_DDC_CONFIG&0xff;
\r
111 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x4b, &c);
\r
112 c= (RK610_DDC_CONFIG>>8)&0xff;
\r
113 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x4c, &c);
\r
116 static int RK610_read_edid_block(struct i2c_client *client,u8 block, u8 * buf)
\r
123 Offset = EDID_BLOCK_SIZE;
\r
126 RK610_DBG(&client->dev,"EDID DATA (Segment = %d Block = %d Offset = %d):\n", (int) Segment, (int) block, (int) Offset);
\r
127 //set edid fifo first addr
\r
129 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x4f, &c);
\r
130 //set edid word address 00/80
\r
132 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x4e, &c);
\r
133 //set edid segment pointer
\r
135 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x4d, &c);
\r
137 //enable edid interrupt
\r
139 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc0, &c);
\r
140 //wait edid interrupt
\r
142 RK610_DBG(&client->dev,"Interrupt generated\n");
\r
144 ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xc1, &c);
\r
145 RK610_DBG(&client->dev,"Interrupt reg=%x \n",c);
\r
146 //clear EDID interrupt reg
\r
148 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc1, &c);
\r
149 for(i=0; i <EDID_BLOCK_SIZE;i++){
\r
151 Rk610_hdmi_i2c_read_p0_reg(client, 0x50, &c);
\r
157 //------------------------------------------------------------------------------
\r
158 // Function Name: Parse861ShortDescriptors()
\r
159 // Function Description: Parse CEA-861 extension short descriptors of the EDID block
\r
160 // passed as a parameter and save them in global structure g_edid.
\r
162 // Accepts: A pointer to the EDID 861 Extension block being parsed.
\r
163 // Returns: EDID_PARSED_OK if EDID parsed correctly. Error code if failed.
\r
164 // Globals: EDID data
\r
165 // NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed.
\r
166 //------------------------------------------------------------------------------
\r
167 byte Parse861ShortDescriptors (byte *Data)
\r
169 byte LongDescriptorOffset;
\r
170 byte DataBlockLength;
\r
172 byte ExtendedTagCode;
\r
173 byte VSDB_BaseOffset = 0;
\r
175 byte V_DescriptorIndex = 0; // static to support more than one extension
\r
176 byte A_DescriptorIndex = 0; // static to support more than one extension
\r
183 if (Data[EDID_TAG_ADDR] != EDID_EXTENSION_TAG)
\r
185 RK610_HDMI_ERR("EDID -> Extension Tag Error\n");
\r
186 return EDID_EXT_TAG_ERROR;
\r
189 if (Data[EDID_REV_ADDR] != EDID_REV_THREE)
\r
191 RK610_HDMI_ERR("EDID -> Revision Error\n"));
\r
192 return EDID_REV_ADDR_ERROR;
\r
195 LongDescriptorOffset = Data[LONG_DESCR_PTR_IDX]; // block offset where long descriptors start
\r
197 g_edid.UnderScan = ((Data[MISC_SUPPORT_IDX]) >> 7) & LSBIT; // byte #3 of CEA extension version 3
\r
198 g_edid.BasicAudio = ((Data[MISC_SUPPORT_IDX]) >> 6) & LSBIT;
\r
199 g_edid.YCbCr_4_4_4 = ((Data[MISC_SUPPORT_IDX]) >> 5) & LSBIT;
\r
200 g_edid.YCbCr_4_2_2 = ((Data[MISC_SUPPORT_IDX]) >> 4) & LSBIT;
\r
202 DataIndex = EDID_DATA_START; // 4
\r
204 while (DataIndex < LongDescriptorOffset)
\r
206 TagCode = (Data[DataIndex] >> 5) & THREE_LSBITS;
\r
207 DataBlockLength = Data[DataIndex++] & FIVE_LSBITS;
\r
208 if ((DataIndex + DataBlockLength) > LongDescriptorOffset)
\r
210 RK610_HDMI_ERR("EDID -> V Descriptor Overflow\n");
\r
211 return EDID_V_DESCR_OVERFLOW;
\r
214 i = 0; // num of short video descriptors in current data block
\r
218 case VIDEO_D_BLOCK:
\r
219 while ((i < DataBlockLength) && (i < MAX_V_DESCRIPTORS)) // each SVD is 1 byte long
\r
221 g_edid.VideoDescriptor[V_DescriptorIndex++] = Data[DataIndex++];
\r
224 DataIndex += DataBlockLength - i; // if there are more STDs than MAX_V_DESCRIPTORS, skip the last ones. Update DataIndex
\r
226 RK610_RK610_DBG(&client->dev,"EDID -> Short Descriptor Video Block\n");
\r
229 case AUDIO_D_BLOCK:
\r
230 while (i < DataBlockLength/3) // each SAD is 3 bytes long
\r
233 while (j < AUDIO_DESCR_SIZE) // 3
\r
235 g_edid.AudioDescriptor[A_DescriptorIndex][j++] = Data[DataIndex++];
\r
237 A_DescriptorIndex++;
\r
240 RK610_HDMI_DBG("EDID -> Short Descriptor Audio Block\n");
\r
243 case SPKR_ALLOC_D_BLOCK:
\r
244 g_edid.SpkrAlloc[i++] = Data[DataIndex++]; // although 3 bytes are assigned to Speaker Allocation, only
\r
245 DataIndex += 2; // the first one carries information, so the next two are ignored by this code.
\r
246 RK610_HDMI_DBG("EDID -> Short Descriptor Speaker Allocation Block\n");
\r
249 case USE_EXTENDED_TAG:
\r
250 ExtendedTagCode = Data[DataIndex++];
\r
252 switch (ExtendedTagCode)
\r
254 case VIDEO_CAPABILITY_D_BLOCK:
\r
255 RK610_HDMI_DBG("EDID -> Short Descriptor Video Capability Block\n");
\r
257 // TO BE ADDED HERE: Save "video capability" parameters in g_edid data structure
\r
258 // Need to modify that structure definition
\r
259 // In the meantime: just increment DataIndex by 1
\r
260 DataIndex += 1; // replace with reading and saving the proper data per CEA-861 sec. 7.5.6 while incrementing DataIndex
\r
263 case COLORIMETRY_D_BLOCK:
\r
264 g_edid.ColorimetrySupportFlags = Data[DataIndex++] & BITS_1_0;
\r
265 g_edid.MetadataProfile = Data[DataIndex++] & BITS_2_1_0;
\r
267 RK610_HDMI_DBG("EDID -> Short Descriptor Colorimetry Block\n");
\r
272 case VENDOR_SPEC_D_BLOCK:
\r
273 VSDB_BaseOffset = DataIndex - 1;
\r
275 if ((Data[DataIndex++] == 0x03) && // check if sink is HDMI compatible
\r
276 (Data[DataIndex++] == 0x0C) &&
\r
277 (Data[DataIndex++] == 0x00))
\r
279 g_edid.RK610_HDMI_Sink = TRUE;
\r
281 g_edid.RK610_HDMI_Sink = FALSE;
\r
283 g_edid.CEC_A_B = Data[DataIndex++]; // CEC Physical address
\r
284 g_edid.CEC_C_D = Data[DataIndex++];
\r
286 #ifdef DEV_SUPPORT_CEC
\r
287 // Take the Address that was passed in the EDID and use this API
\r
288 // to set the physical address for CEC.
\r
291 phyAddr = (word)g_edid.CEC_C_D; // Low-order nibbles
\r
292 phyAddr |= ((word)g_edid.CEC_A_B << 8); // Hi-order nibbles
\r
293 // Is the new PA different from the current PA?
\r
294 if (phyAddr != SI_CecGetDevicePA ())
\r
296 // Yes! So change the PA
\r
297 SI_CecSetDevicePA (phyAddr);
\r
302 if ((DataIndex + 7) > VSDB_BaseOffset + DataBlockLength) // Offset of 3D_Present bit in VSDB
\r
303 g_edid._3D_Supported = FALSE;
\r
304 else if (Data[DataIndex + 7] >> 7)
\r
305 g_edid._3D_Supported = TRUE;
\r
307 g_edid._3D_Supported = FALSE;
\r
309 DataIndex += DataBlockLength - RK610_HDMI_SIGNATURE_LEN - CEC_PHYS_ADDR_LEN; // Point to start of next block
\r
310 RK610_HDMI_DBG("EDID -> Short Descriptor Vendor Block\n");
\r
314 RK610_HDMI_DBG("EDID -> Unknown Tag Code\n");
\r
315 return EDID_UNKNOWN_TAG_CODE;
\r
317 } // End, Switch statement
\r
318 } // End, while (DataIndex < LongDescriptorOffset) statement
\r
320 return EDID_SHORT_DESCRIPTORS_OK;
\r
323 //------------------------------------------------------------------------------
\r
324 // Function Name: Parse861LongDescriptors()
\r
325 // Function Description: Parse CEA-861 extension long descriptors of the EDID block
\r
326 // passed as a parameter and printf() them to the screen.
\r
328 // Accepts: A pointer to the EDID block being parsed
\r
329 // Returns: An error code if no long descriptors found; EDID_PARSED_OK if descriptors found.
\r
331 //------------------------------------------------------------------------------
\r
332 byte Parse861LongDescriptors (byte *Data)
\r
334 byte LongDescriptorsOffset;
\r
335 byte DescriptorNum = 1;
\r
337 LongDescriptorsOffset = Data[LONG_DESCR_PTR_IDX]; // EDID block offset 2 holds the offset
\r
339 if (!LongDescriptorsOffset) // per CEA-861-D, table 27
\r
341 TPI_DEBUG_PRINT(("EDID -> No Detailed Descriptors\n"));
\r
342 return EDID_NO_DETAILED_DESCRIPTORS;
\r
345 // of the 1st 18-byte descriptor
\r
346 while (LongDescriptorsOffset + LONG_DESCR_LEN < EDID_BLOCK_SIZE)
\r
348 TPI_EDID_PRINT(("Parse Results - CEA-861 Long Descriptor #%d:\n", (int) DescriptorNum));
\r
349 TPI_EDID_PRINT(("===============================================================\n"));
\r
351 #if (CONF__TPI_EDID_PRINT == ENABLE)
\r
352 if (!ParseDetailedTiming(Data, LongDescriptorsOffset, EDID_BLOCK_2_3))
\r
355 LongDescriptorsOffset += LONG_DESCR_LEN;
\r
359 return EDID_LONG_DESCRIPTORS_OK;
\r
362 //------------------------------------------------------------------------------
\r
363 // Function Name: Parse861Extensions()
\r
364 // Function Description: Parse CEA-861 extensions from EDID ROM (EDID blocks beyond
\r
365 // block #0). Save short descriptors in global structure
\r
366 // g_edid. printf() long descriptors to the screen.
\r
368 // Accepts: The number of extensions in the EDID being parsed
\r
369 // Returns: EDID_PARSED_OK if EDID parsed correctly. Error code if failed.
\r
370 // Globals: EDID data
\r
371 // NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed.
\r
372 //------------------------------------------------------------------------------
\r
373 byte Parse861Extensions (struct i2c_client *client,byte NumOfExtensions)
\r
379 // byte V_DescriptorIndex = 0;
\r
380 // byte A_DescriptorIndex = 0;
\r
384 g_edid.HDMI_Sink = FALSE;
\r
391 for (j=0, i=0; j<128; j++)
\r
394 HDMI_DBG("%2.2X ", (int) k);
\r
404 RK610_read_edid_block(client,Block, edid_buf);
\r
405 if ((NumOfExtensions > 1) && (Block == 1))
\r
410 ErrCode = Parse861ShortDescriptors(edid_buf);
\r
411 if (ErrCode != EDID_SHORT_DESCRIPTORS_OK)
\r
416 ErrCode = Parse861LongDescriptors(edid_buf);
\r
417 if (ErrCode != EDID_LONG_DESCRIPTORS_OK)
\r
422 } while (Block < NumOfExtensions);
\r
427 //------------------------------------------------------------------------------
\r
428 // Function Name: ParseEDID()
\r
429 // Function Description: Extract sink properties from its EDID file and save them in
\r
430 // global structure g_edid.
\r
433 // Returns: TRUE or FLASE
\r
434 // Globals: EDID data
\r
435 // NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed.
\r
436 //------------------------------------------------------------------------------
\r
437 static byte ParseEDID (byte *pEdid, byte *numExt)
\r
439 if (!CheckEDID_Header(pEdid))
\r
441 // first 8 bytes of EDID must be {0, FF, FF, FF, FF, FF, FF, 0}
\r
442 HDMI_ERR("EDID -> Incorrect Header\n");
\r
443 return EDID_INCORRECT_HEADER;
\r
446 if (!DoEDID_Checksum(pEdid))
\r
448 // non-zero EDID checksum
\r
449 HDMI_ERR("EDID -> Checksum Error\n");
\r
450 return EDID_CHECKSUM_ERROR;
\r
453 *numExt = pEdid[NUM_OF_EXTEN_ADDR]; // read # of extensions from offset 0x7E of block 0
\r
454 HDMI_DBG("EDID -> 861 Extensions = %d\n", (int) *numExt);
\r
458 // No extensions to worry about
\r
459 HDMI_DBG("EDID -> EDID_NO_861_EXTENSIONS\n");
\r
460 return EDID_NO_861_EXTENSIONS;
\r
466 //------------------------------------------------------------------------------
\r
467 // Function Name: CheckEDID_Header()
\r
468 // Function Description: Checks if EDID header is correct per VESA E-EDID standard
\r
470 // Accepts: Pointer to 1st EDID block
\r
471 // Returns: TRUE or FLASE
\r
472 // Globals: EDID data
\r
473 //------------------------------------------------------------------------------
\r
474 byte CheckEDID_Header (byte *Block)
\r
478 if (Block[i]) // byte 0 must be 0
\r
481 for (i = 1; i < 1 + EDID_HDR_NO_OF_FF; i++)
\r
483 if(Block[i] != 0xFF) // bytes [1..6] must be 0xFF
\r
487 if (Block[i]) // byte 7 must be 0
\r
493 //------------------------------------------------------------------------------
\r
494 // Function Name: DoEDID_Checksum()
\r
495 // Function Description: Calculte checksum of the 128 byte block pointed to by the
\r
496 // pointer passed as parameter
\r
498 // Accepts: Pointer to a 128 byte block whose checksum needs to be calculated
\r
499 // Returns: TRUE or FLASE
\r
500 // Globals: EDID data
\r
501 //------------------------------------------------------------------------------
\r
502 byte DoEDID_Checksum (byte *Block)
\r
507 for (i = 0; i < EDID_BLOCK_SIZE; i++)
\r
508 CheckSum += Block[i];
\r
515 //------------------------------------------------------------------------------
\r
516 // Function Name: Parse861ShortDescriptors()
\r
517 // Function Description: Parse CEA-861 extension short descriptors of the EDID block
\r
518 // passed as a parameter and save them in global structure g_edid.
\r
520 // Accepts: A pointer to the EDID 861 Extension block being parsed.
\r
521 // Returns: EDID_PARSED_OK if EDID parsed correctly. Error code if failed.
\r
522 // Globals: EDID data
\r
523 // NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed.
\r
524 //------------------------------------------------------------------------------
\r
525 byte Parse861ShortDescriptors (struct i2c_client *client,byte *Data)
\r
527 byte LongDescriptorOffset;
\r
528 byte DataBlockLength;
\r
530 byte ExtendedTagCode;
\r
531 byte VSDB_BaseOffset = 0;
\r
533 byte V_DescriptorIndex = 0; // static to support more than one extension
\r
534 byte A_DescriptorIndex = 0; // static to support more than one extension
\r
541 if (Data[EDID_TAG_ADDR] != EDID_EXTENSION_TAG)
\r
543 RK610_ERR(&client->dev,"EDID -> Extension Tag Error\n");
\r
544 return EDID_EXT_TAG_ERROR;
\r
547 if (Data[EDID_REV_ADDR] != EDID_REV_THREE)
\r
549 RK610_ERR(&client->dev,"EDID -> Revision Error\n");
\r
550 return EDID_REV_ADDR_ERROR;
\r
553 LongDescriptorOffset = Data[LONG_DESCR_PTR_IDX]; // block offset where long descriptors start
\r
555 g_edid.UnderScan = ((Data[MISC_SUPPORT_IDX]) >> 7) & LSBIT; // byte #3 of CEA extension version 3
\r
556 g_edid.BasicAudio = ((Data[MISC_SUPPORT_IDX]) >> 6) & LSBIT;
\r
557 g_edid.YCbCr_4_4_4 = ((Data[MISC_SUPPORT_IDX]) >> 5) & LSBIT;
\r
558 g_edid.YCbCr_4_2_2 = ((Data[MISC_SUPPORT_IDX]) >> 4) & LSBIT;
\r
560 DataIndex = EDID_DATA_START; // 4
\r
562 while (DataIndex < LongDescriptorOffset)
\r
564 TagCode = (Data[DataIndex] >> 5) & THREE_LSBITS;
\r
565 DataBlockLength = Data[DataIndex++] & FIVE_LSBITS;
\r
566 if ((DataIndex + DataBlockLength) > LongDescriptorOffset)
\r
568 RK610_ERR(&client->dev,"EDID -> V Descriptor Overflow\n");
\r
569 return EDID_V_DESCR_OVERFLOW;
\r
572 i = 0; // num of short video descriptors in current data block
\r
576 case VIDEO_D_BLOCK:
\r
577 while ((i < DataBlockLength) && (i < MAX_V_DESCRIPTORS)) // each SVD is 1 byte long
\r
579 g_edid.VideoDescriptor[V_DescriptorIndex++] = Data[DataIndex++];
\r
582 DataIndex += DataBlockLength - i; // if there are more STDs than MAX_V_DESCRIPTORS, skip the last ones. Update DataIndex
\r
584 RK610_DBG(&client->dev,"EDID -> Short Descriptor Video Block\n");
\r
587 case AUDIO_D_BLOCK:
\r
588 while (i < DataBlockLength/3) // each SAD is 3 bytes long
\r
591 while (j < AUDIO_DESCR_SIZE) // 3
\r
593 g_edid.AudioDescriptor[A_DescriptorIndex][j++] = Data[DataIndex++];
\r
595 A_DescriptorIndex++;
\r
598 RK610_DBG(&client->dev,"EDID -> Short Descriptor Audio Block\n");
\r
601 case SPKR_ALLOC_D_BLOCK:
\r
602 g_edid.SpkrAlloc[i++] = Data[DataIndex++]; // although 3 bytes are assigned to Speaker Allocation, only
\r
603 DataIndex += 2; // the first one carries information, so the next two are ignored by this code.
\r
604 RK610_DBG(&client->dev,"EDID -> Short Descriptor Speaker Allocation Block\n");
\r
607 case USE_EXTENDED_TAG:
\r
608 ExtendedTagCode = Data[DataIndex++];
\r
610 switch (ExtendedTagCode)
\r
612 case VIDEO_CAPABILITY_D_BLOCK:
\r
613 RK610_DBG(&client->dev,"EDID -> Short Descriptor Video Capability Block\n");
\r
615 // TO BE ADDED HERE: Save "video capability" parameters in g_edid data structure
\r
616 // Need to modify that structure definition
\r
617 // In the meantime: just increment DataIndex by 1
\r
618 DataIndex += 1; // replace with reading and saving the proper data per CEA-861 sec. 7.5.6 while incrementing DataIndex
\r
621 case COLORIMETRY_D_BLOCK:
\r
622 g_edid.ColorimetrySupportFlags = Data[DataIndex++] & BITS_1_0;
\r
623 g_edid.MetadataProfile = Data[DataIndex++] & BITS_2_1_0;
\r
625 RK610_DBG(&client->dev,"EDID -> Short Descriptor Colorimetry Block\n");
\r
630 case VENDOR_SPEC_D_BLOCK:
\r
631 VSDB_BaseOffset = DataIndex - 1;
\r
633 if ((Data[DataIndex++] == 0x03) && // check if sink is HDMI compatible
\r
634 (Data[DataIndex++] == 0x0C) &&
\r
635 (Data[DataIndex++] == 0x00))
\r
637 g_edid.HDMI_Sink = TRUE;
\r
639 g_edid.HDMI_Sink = FALSE;
\r
641 g_edid.CEC_A_B = Data[DataIndex++]; // CEC Physical address
\r
642 g_edid.CEC_C_D = Data[DataIndex++];
\r
644 #ifdef DEV_SUPPORT_CEC
\r
645 // Take the Address that was passed in the EDID and use this API
\r
646 // to set the physical address for CEC.
\r
649 phyAddr = (word)g_edid.CEC_C_D; // Low-order nibbles
\r
650 phyAddr |= ((word)g_edid.CEC_A_B << 8); // Hi-order nibbles
\r
651 // Is the new PA different from the current PA?
\r
652 if (phyAddr != SI_CecGetDevicePA ())
\r
654 // Yes! So change the PA
\r
655 SI_CecSetDevicePA (phyAddr);
\r
660 if ((DataIndex + 7) > VSDB_BaseOffset + DataBlockLength) // Offset of 3D_Present bit in VSDB
\r
661 g_edid._3D_Supported = FALSE;
\r
662 else if (Data[DataIndex + 7] >> 7)
\r
663 g_edid._3D_Supported = TRUE;
\r
665 g_edid._3D_Supported = FALSE;
\r
667 DataIndex += DataBlockLength - HDMI_SIGNATURE_LEN - CEC_PHYS_ADDR_LEN; // Point to start of next block
\r
668 RK610_DBG(&client->dev,"EDID -> Short Descriptor Vendor Block\n");
\r
672 RK610_ERR(&client->dev,"EDID -> Unknown Tag Code\n");
\r
673 return EDID_UNKNOWN_TAG_CODE;
\r
675 } // End, Switch statement
\r
676 } // End, while (DataIndex < LongDescriptorOffset) statement
\r
678 return EDID_SHORT_DESCRIPTORS_OK;
\r
680 //------------------------------------------------------------------------------
\r
681 // Function Name: ParseEDID()
\r
682 // Function Description: Extract sink properties from its EDID file and save them in
\r
683 // global structure g_edid.
\r
686 // Returns: TRUE or FLASE
\r
687 // Globals: EDID data
\r
688 // NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed.
\r
689 //------------------------------------------------------------------------------
\r
690 static byte ParseEDID (struct i2c_client *client,byte *pEdid, byte *numExt)
\r
692 if (!CheckEDID_Header(pEdid))
\r
694 // first 8 bytes of EDID must be {0, FF, FF, FF, FF, FF, FF, 0}
\r
695 RK610_ERR(&client->dev,"EDID -> Incorrect Header\n");
\r
696 return EDID_INCORRECT_HEADER;
\r
699 if (!DoEDID_Checksum(pEdid))
\r
701 // non-zero EDID checksum
\r
702 RK610_ERR(&client->dev,"EDID -> Checksum Error\n");
\r
703 return EDID_CHECKSUM_ERROR;
\r
706 *numExt = pEdid[NUM_OF_EXTEN_ADDR]; // read # of extensions from offset 0x7E of block 0
\r
707 RK610_DBG(&client->dev,"EDID -> 861 Extensions = %d\n", (int) *numExt);
\r
711 // No extensions to worry about
\r
712 RK610_DBG(&client->dev,"EDID -> EDID_NO_861_EXTENSIONS\n");
\r
713 return EDID_NO_861_EXTENSIONS;
\r
718 int Rk610_Parse_resolution(void)
\r
721 memset(&Rk610_edid_result,0,sizeof(struct edid_result));
\r
722 for(i=0;i < MAX_V_DESCRIPTORS;i++){
\r
723 vic = g_edid.VideoDescriptor[i]&0x7f;
\r
724 if(vic == HDMI_VIC_1080p_50Hz)
\r
725 Rk610_edid_result.supported_1080p_50Hz = 1;
\r
726 else if(vic == HDMI_VIC_1080p_60Hz)
\r
727 Rk610_edid_result.supported_1080p_60Hz = 1;
\r
728 else if(vic == HDMI_VIC_720p_50Hz)
\r
729 Rk610_edid_result.supported_720p_50Hz = 1;
\r
730 else if(vic == HDMI_VIC_720p_60Hz)
\r
731 Rk610_edid_result.supported_720p_60Hz = 1;
\r
732 else if(vic == HDMI_VIC_576p_50Hz)
\r
733 Rk610_edid_result.supported_576p_50Hz = 1;
\r
734 else if(vic == HDMI_VIC_480p_60Hz)
\r
735 Rk610_edid_result.supported_720x480p_60Hz = 1;
\r
738 printk("rk610_hdmi:1080p_50Hz %s\n",Rk610_edid_result.supported_1080p_50Hz?"support":"not support");
\r
739 printk("rk610_hdmi:1080p_60Hz %s\n",Rk610_edid_result.supported_1080p_60Hz?"support":"not support");
\r
740 printk("rk610_hdmi:720p_50Hz %s\n",Rk610_edid_result.supported_720p_50Hz?"support":"not support");
\r
741 printk("rk610_hdmi:720p_60Hz %s\n",Rk610_edid_result.supported_720p_60Hz?"support":"not support");
\r
742 printk("rk610_hdmi:576p_50Hz %s\n",Rk610_edid_result.supported_576p_50Hz?"support":"not support");
\r
743 printk("rk610_hdmi:720x480p_60Hz %s\n",Rk610_edid_result.supported_720x480p_60Hz?"support":"not support");
\r
748 int Rk610_Get_Optimal_resolution(int resolution_set)
\r
750 int resolution_real;
\r
751 int find_resolution = 0;
\r
753 Rk610_Parse_resolution();
\r
754 switch(resolution_set){
\r
755 case HDMI_1280x720p_50Hz:
\r
756 if(Rk610_edid_result.supported_720p_50Hz){
\r
757 resolution_real = HDMI_1280x720p_50Hz;
\r
758 find_resolution = 1;
\r
761 case HDMI_1280x720p_60Hz:
\r
762 if(Rk610_edid_result.supported_720p_60Hz){
\r
763 resolution_real = HDMI_1280x720p_60Hz;
\r
764 find_resolution = 1;
\r
767 case HDMI_720x576p_50Hz_4x3:
\r
768 if(Rk610_edid_result.supported_576p_50Hz){
\r
769 resolution_real = HDMI_720x576p_50Hz_4x3;
\r
770 find_resolution = 1;
\r
773 case HDMI_720x576p_50Hz_16x9:
\r
774 if(Rk610_edid_result.supported_576p_50Hz){
\r
775 resolution_real = HDMI_720x576p_50Hz_16x9;
\r
776 find_resolution = 1;
\r
779 case HDMI_720x480p_60Hz_4x3:
\r
780 if(Rk610_edid_result.supported_720x480p_60Hz){
\r
781 resolution_real = HDMI_720x480p_60Hz_4x3;
\r
782 find_resolution = 1;
\r
785 case HDMI_720x480p_60Hz_16x9:
\r
786 if(Rk610_edid_result.supported_720x480p_60Hz){
\r
787 resolution_real = HDMI_720x480p_60Hz_16x9;
\r
788 find_resolution = 1;
\r
791 case HDMI_1920x1080p_50Hz:
\r
792 if(Rk610_edid_result.supported_1080p_50Hz){
\r
793 resolution_real = HDMI_1920x1080p_50Hz;
\r
794 find_resolution = 1;
\r
797 case HDMI_1920x1080p_60Hz:
\r
798 if(Rk610_edid_result.supported_1080p_60Hz){
\r
799 resolution_real = HDMI_1920x1080p_60Hz;
\r
800 find_resolution = 1;
\r
807 if(find_resolution == 0){
\r
809 if(Rk610_edid_result.supported_720p_50Hz)
\r
810 resolution_real = HDMI_1280x720p_50Hz;
\r
811 else if(Rk610_edid_result.supported_720p_60Hz)
\r
812 resolution_real = HDMI_1280x720p_60Hz;
\r
813 else if(Rk610_edid_result.supported_1080p_50Hz)
\r
814 resolution_real = HDMI_1920x1080p_50Hz;
\r
815 else if(Rk610_edid_result.supported_1080p_60Hz)
\r
816 resolution_real = HDMI_1920x1080p_60Hz;
\r
817 else if(Rk610_edid_result.supported_576p_50Hz)
\r
818 resolution_real = HDMI_720x576p_50Hz_4x3;
\r
819 else if(Rk610_edid_result.supported_720x480p_60Hz)
\r
820 resolution_real = HDMI_720x480p_60Hz_4x3;
\r
822 resolution_real = HDMI_1280x720p_60Hz;
\r
825 return resolution_real;
\r
828 byte DoEdidRead (struct i2c_client *client)
\r
830 u8 NumOfExtensions=0;
\r
833 // If we already have valid EDID data, ship this whole thing
\r
834 if (g_edid.edidDataValid == FALSE)
\r
836 Rk610_hdmi_sys_power_up(client);
\r
837 // Request access to DDC bus from the receiver
\r
838 RK610_DDC_BUS_CONFIG(client);
\r
839 memset(edid_buf,0,EDID_BLOCK_SIZE);
\r
840 RK610_read_edid_block(client,EDID_BLOCK0, edid_buf); // read first 128 bytes of EDID ROM
\r
841 RK610_DBG(&client->dev,"/************first block*******/\n");
\r
843 for (j=0; j<EDID_BLOCK_SIZE; j++)
\r
846 printk("\n%x :",j);
\r
847 printk("%2.2x ", edid_buf[j]);
\r
850 Result = ParseEDID(client,edid_buf, &NumOfExtensions);
\r
851 if(Result!=EDID_OK){
\r
852 if(Result==EDID_NO_861_EXTENSIONS){
\r
853 g_edid.HDMI_Sink = FALSE;
\r
856 g_edid.HDMI_Sink = FALSE;
\r
861 NumOfExtensions = edid_buf[NUM_OF_EXTEN_ADDR];
\r
862 for(i=1;i<=NumOfExtensions;i++){
\r
863 RK610_DBG(&client->dev,"\n/************block %d*******/\n",i);
\r
864 memset(edid_buf,0,EDID_BLOCK_SIZE);
\r
865 RK610_read_edid_block(client,i, edid_buf);
\r
866 Parse861ShortDescriptors(client,edid_buf);
\r
868 for (j=0; j<EDID_BLOCK_SIZE; j++){
\r
870 printk("\n%x :",j);
\r
871 printk("%2.2X ", edid_buf[j]);
\r
876 g_edid.HDMI_Sink = TRUE;
\r
880 Result = ParseEDID(edid_buf, &NumOfExtensions);
\r
881 if (Result != EDID_OK)
\r
883 if (Result == EDID_NO_861_EXTENSIONS)
\r
885 RK610_DBG(&client->dev,"EDID -> No 861 Extensions\n");
\r
886 g_edid.HDMI_Sink = FALSE;
\r
887 g_edid.YCbCr_4_4_4 = FALSE;
\r
888 g_edid.YCbCr_4_2_2 = FALSE;
\r
889 g_edid.CEC_A_B = 0x00;
\r
890 g_edid.CEC_C_D = 0x00;
\r
894 RK610_DBG(&client->dev,"EDID -> Parse FAILED\n");
\r
895 g_edid.HDMI_Sink = TRUE;
\r
896 g_edid.YCbCr_4_4_4 = FALSE;
\r
897 g_edid.YCbCr_4_2_2 = FALSE;
\r
898 g_edid.CEC_A_B = 0x00;
\r
899 g_edid.CEC_C_D = 0x00;
\r
904 RK610_DBG(&client->dev,"EDID -> Parse OK\n");
\r
905 Result = Parse861Extensions(NumOfExtensions); // Parse 861 Extensions (short and long descriptors);
\r
906 if (Result != EDID_OK)
\r
908 RK610_DBG(&client->dev,"EDID -> Extension Parse FAILED\n");
\r
909 g_edid.HDMI_Sink = FALSE;
\r
910 g_edid.YCbCr_4_4_4 = FALSE;
\r
911 g_edid.YCbCr_4_2_2 = FALSE;
\r
912 g_edid.CEC_A_B = 0x00;
\r
913 g_edid.CEC_C_D = 0x00;
\r
917 RK610_DBG(&client->dev,"EDID -> Extension Parse OK\n");
\r
918 g_edid.HDMI_Sink = TRUE;
\r
922 RK610_DBG(&client->dev,"EDID -> NumOfExtensions = %d\n", NumOfExtensions);
\r
923 RK610_DBG(&client->dev,"EDID -> g_edid.HDMI_Sink = %d\n", (int)g_edid.HDMI_Sink);
\r
924 //RK610_DBG(&client->dev,"EDID -> g_edid.YCbCr_4_4_4 = %d\n", (int)g_edid.YCbCr_4_4_4);
\r
925 //RK610_DBG(&client->dev,"EDID -> g_edid.YCbCr_4_2_2 = %d\n", (int)g_edid.YCbCr_4_2_2);
\r
926 //RK610_DBG(&client->dev,"EDID -> g_edid.CEC_A_B = 0x%x\n", (int)g_edid.CEC_A_B);
\r
927 //RK610_DBG(&client->dev,"EDID -> g_edid.CEC_C_D = 0x%x\n", (int)g_edid.CEC_C_D);
\r
929 g_edid.edidDataValid = TRUE;
\r
934 static int Rk610_hdmi_Display_switch(struct i2c_client *client)
\r
939 mode = (g_edid.HDMI_Sink == TRUE)? DISPLAY_HDMI:DISPLAY_DVI;
\r
940 ret = Rk610_hdmi_i2c_read_p0_reg(client, 0x52, &c);
\r
941 c &= ((~(1<<1))| mode<<1);
\r
942 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x52, &c);
\r
943 RK610_DBG(&client->dev,">>>%s mode=%d,c=%x",__func__,mode,c);
\r
947 static int Rk610_hdmi_Config_audio_informat(struct i2c_client *client)
\r
951 RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
\r
952 //Select configure for Audio Info
\r
954 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x9f, &c);
\r
955 //Configure the Audio info to HDMI RX.
\r
957 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa0, &c);
\r
959 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa1, &c);
\r
961 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa2, &c);
\r
963 //ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa3, &c);
\r
965 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa4, &c);
\r
967 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa5, &c);
\r
969 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa6, &c);
\r
971 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa7, &c);
\r
973 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa8, &c);
\r
977 static int Rk610_hdmi_Config_Avi_informat(struct i2c_client *client ,u8 vic)
\r
981 RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
\r
982 //Select configure for AVI Info
\r
984 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x9f, &c);
\r
986 //Configure the AVI info to HDMI RX
\r
988 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa0, &c);
\r
990 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa1, &c);
\r
992 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa2, &c);
\r
994 //ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa3, &c);
\r
996 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa4, &c);
\r
998 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa5, &c);
\r
1000 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa6, &c);
\r
1002 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa7, &c);
\r
1004 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xa8, &c);
\r
1007 static int Rk610_hdmi_Config_Video(struct i2c_client *client, u8 video_format)
\r
1011 RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
\r
1012 switch(video_format){
\r
1013 case HDMI_720x480p_60Hz_4x3:
\r
1014 case HDMI_720x480p_60Hz_16x9:
\r
1015 vic = HDMI_VIC_480p_60Hz;
\r
1017 case HDMI_720x576p_50Hz_4x3:
\r
1018 case HDMI_720x576p_50Hz_16x9:
\r
1019 vic = HDMI_VIC_576p_50Hz;
\r
1021 case HDMI_1280x720p_50Hz:
\r
1022 vic = HDMI_VIC_720p_50Hz;
\r
1024 case HDMI_1280x720p_60Hz:
\r
1025 vic = HDMI_VIC_720p_60Hz;
\r
1027 case HDMI_1920x1080p_50Hz:
\r
1028 vic = HDMI_VIC_1080p_50Hz;
\r
1030 case HDMI_1920x1080p_60Hz:
\r
1031 vic = HDMI_VIC_1080p_60Hz;
\r
1037 ret = Rk610_hdmi_Config_Avi_informat(client,vic);
\r
1040 static int Rk610_hdmi_Config_Audio(struct i2c_client *client ,u8 audio_fs)
\r
1044 RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
\r
1046 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x35, &c);
\r
1048 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x38, &c);
\r
1050 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x39, &c);
\r
1052 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x40, &c);
\r
1054 case HDMI_I2S_Fs_44100:
\r
1056 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x41, &c);
\r
1058 case HDMI_I2S_Fs_48000:
\r
1060 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x41, &c);
\r
1064 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0x41, &c);
\r
1067 Rk610_hdmi_Config_audio_informat(client);
\r
1071 int Rk610_hdmi_Set_Video(u8 video_format)
\r
1073 if(g_hw_inf.video_format !=video_format){
\r
1074 g_hw_inf.video_format = video_format;
\r
1075 g_hw_inf.config_param |= VIDEO_CHANGE;
\r
1079 int Rk610_hdmi_Set_Audio(u8 audio_fs)
\r
1081 if(g_hw_inf.audio_fs !=audio_fs){
\r
1082 g_hw_inf.audio_fs = audio_fs;
\r
1083 g_hw_inf.config_param |= AUDIO_CHANGE;
\r
1087 static int RK610_hdmi_Driver_mode(struct i2c_client *client)
\r
1092 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe1, &c);
\r
1094 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xe2, &c);
\r
1097 static int RK610_hdmi_PLL_mode(struct i2c_client *client)
\r
1102 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xe8, &c);
\r
1104 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xe6, &c);
\r
1106 ret = Rk610_hdmi_i2c_write_p0_reg(client, 0xe5, &c);
\r
1109 static void Rk610_hdmi_plug(struct i2c_client *client)
\r
1111 RK610_DBG(&client->dev,">>> hdmi plug \n");
\r
1112 DoEdidRead(client);
\r
1113 Rk610_hdmi_Display_switch(client);
\r
1114 Rk610_hdmi_pwr_mode(client,LOWER_PWR);
\r
1115 Rk610_hdmi_pwr_mode(client,NORMAL);
\r
1117 static void Rk610_hdmi_unplug(struct i2c_client *client)
\r
1119 RK610_DBG(&client->dev,">>> hdmi unplug \n");
\r
1120 g_edid.edidDataValid = FALSE;
\r
1121 Rk610_hdmi_pwr_mode(client,LOWER_PWR);
\r
1123 void Rk610_hdmi_event_work(struct i2c_client *client, bool *hpd)
\r
1127 if(g_hw_inf.suspend_flag == 1){
\r
1133 ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xc1, &c);
\r
1134 if(c & RK610_HPD_EVENT){
\r
1135 RK610_DBG(&client->dev,">>>HPD EVENT\n");
\r
1136 /**********clear hpd event******/
\r
1137 c = RK610_HPD_EVENT;
\r
1138 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc1, &c);
\r
1139 ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c);
\r
1140 if(c & RK610_HPD_PLUG ){
\r
1141 Rk610_hdmi_plug(client);
\r
1145 Rk610_hdmi_unplug(client);
\r
1150 if(c & RK610_EDID_EVENT){
\r
1151 /**********clear hpd event******/
\r
1152 c = RK610_EDID_EVENT;
\r
1153 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0xc1, &c);
\r
1154 RK610_DBG(&client->dev,">>>EDID EVENT\n");
\r
1155 /*************clear edid event*********/
\r
1157 *hpd = g_hw_inf.hpd;
\r
1159 int Rk610_hdmi_Config_Done(struct i2c_client *client)
\r
1163 RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
\r
1165 ret =Rk610_hdmi_sys_power_up(client);
\r
1167 if(g_hw_inf.config_param != 0){
\r
1169 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x04, &c);
\r
1171 ret =Rk610_hdmi_i2c_write_p0_reg(client, 0x01, &c);
\r
1172 if(g_hw_inf.config_param & VIDEO_CHANGE){
\r
1173 Rk610_hdmi_Config_Video(client,g_hw_inf.video_format);
\r
1174 g_hw_inf.config_param &= (~VIDEO_CHANGE);
\r
1176 if(g_hw_inf.config_param & AUDIO_CHANGE){
\r
1177 Rk610_hdmi_Config_Audio(client,g_hw_inf.audio_fs);
\r
1178 g_hw_inf.config_param &= (~AUDIO_CHANGE);
\r
1181 ret =Rk610_hdmi_sys_power_down(client);
\r
1182 ret =Rk610_hdmi_sys_power_up(client);
\r
1183 ret =Rk610_hdmi_sys_power_down(client);
\r
1188 int Rk610_hdmi_hpd(struct i2c_client *client)
\r
1191 RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
\r
1192 if(Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c)<0){
\r
1193 RK610_ERR(">>>%s I2c trans err",__FUNCTION__);
\r
1197 return (c & RK610_HPD_PLUG)?1:0;
\r
1200 static int RK610_hdmi_soft_reset(struct i2c_client *client)
\r
1206 ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xce, &c);
\r
1209 ret =Rk610_hdmi_i2c_read_p0_reg(client, 0xce, &c);
\r
1213 static void Rk610_hdmi_Variable_Initial(void)
\r
1215 memset(&g_hw_inf,0,sizeof(struct rk610_hdmi_hw_inf));
\r
1216 g_edid.edidDataValid = FALSE;
\r
1217 g_hw_inf.edid_inf = &g_edid;
\r
1218 g_hw_inf.audio_fs = HDMI_I2S_DEFAULT_Fs;
\r
1219 g_hw_inf.video_format = HDMI_DEFAULT_RESOLUTION;
\r
1220 g_hw_inf.config_param = AUDIO_CHANGE | VIDEO_CHANGE;
\r
1222 g_hw_inf.suspend_flag = 0;
\r
1225 int Rk610_hdmi_init(struct i2c_client *client)
\r
1228 RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
\r
1229 Rk610_hdmi_Variable_Initial();
\r
1230 RK610_hdmi_soft_reset(client);
\r
1231 RK610_hdmi_Driver_mode(client);
\r
1232 RK610_hdmi_PLL_mode(client);
\r
1233 Rk610_hdmi_Set_Video(g_hw_inf.video_format);
\r
1234 Rk610_hdmi_Set_Audio(g_hw_inf.audio_fs);
\r
1235 Rk610_hdmi_Config_Done(client);
\r
1237 Rk610_hdmi_i2c_read_p0_reg(client, 0xc8, &c);
\r
1238 if(c & RK610_HPD_PLUG ){
\r
1239 Rk610_hdmi_plug(client);
\r
1242 Rk610_hdmi_unplug(client);
\r