1 /*-----------------------------------------------------------------------------
2 * Copyright (c) Chrontel Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 *-----------------------------------------------------------------------------
25 *-----------------------------------------------------------------------------
29 #include "ch7036_intf.h"
30 #include "ch7036_attr.h"
34 #include "lvds/lvds.h"
40 ch7036_status_t ch7036_get_hdmi_hpd(ch7036_device_context_t* p_ctx, uint8 *hpd);
42 unsigned long ch7036_invis_6x4_modes_table_size[3] = {2,3,5};
43 unsigned long ch7036_invis_8x6_7x4_table_size[3] = {3,5,6};
45 OUT_FMT hdmi_timing_table[OUT_HDMI_END] = {
48 {1, 25175, 1, {800, 640, 16, 96, 525, 480, 10, 2, 59, SCANTYPE_PROGRESSIVE} },
49 {1, 25250, 1, {800, 640, 16, 96, 525, 480, 10, 2, 60, SCANTYPE_PROGRESSIVE} },
50 {2, 27000, 1, {858, 720, 16, 62, 525, 480, 9, 6, 59, SCANTYPE_PROGRESSIVE} },
51 {2, 27027, 1, {858, 720, 16, 62, 525, 480, 9, 6, 60, SCANTYPE_PROGRESSIVE} },
52 {17, 27000, 1, {864, 720, 12, 64, 625, 576, 5, 5, 50, SCANTYPE_PROGRESSIVE} },
54 {4, 74176, 2, {1650, 1280, 110, 40, 750, 720, 5, 5, 59, SCANTYPE_PROGRESSIVE} },
55 {4, 74250, 2, {1650, 1280, 110, 40, 750, 720, 5, 5, 60, SCANTYPE_PROGRESSIVE} },
56 {5, 74176, 2, {2200, 1920, 88, 44, 1125, 1080, 2, 5, 59, SCANTYPE_INTERLACED} },
57 {5, 74250, 2, {2200, 1920, 88, 44, 1125, 1080, 2, 5, 60, SCANTYPE_INTERLACED} },
58 {16, 148350, 2, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 59, SCANTYPE_PROGRESSIVE} },
59 // {16, 148352, 2, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 59, SCANTYPE_PROGRESSIVE} },
60 {16, 148500, 2, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 60, SCANTYPE_PROGRESSIVE} },
62 // {17, 27000, 1, {864, 720, 12, 64, 625, 576, 5, 5, 50, SCANTYPE_PROGRESSIVE} },
63 {19, 74250, 2, {1980, 1280, 440, 40, 750, 720, 5, 5, 50, SCANTYPE_PROGRESSIVE} },
65 {20, 74250, 2, {2640, 1920, 528, 44, 1125, 1080, 2, 5, 50, SCANTYPE_INTERLACED} },
68 {31, 148500, 2, {2640, 1920, 528, 44, 1125, 1080, 4, 5, 50, SCANTYPE_PROGRESSIVE} },
69 {32, 74175, 2, {2750, 1920, 638, 44, 1125, 1080, 4, 5, 23, SCANTYPE_PROGRESSIVE} },
70 {32, 74250, 2, {2750, 1920, 638, 44, 1125, 1080, 4, 5, 24, SCANTYPE_PROGRESSIVE} },
71 {33, 74250, 2, {2640, 1920, 528, 44, 1125, 1080, 4, 5, 25, SCANTYPE_PROGRESSIVE} },
72 {34, 74175, 2, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 29, SCANTYPE_PROGRESSIVE} },
73 {34, 74250, 2, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 30, SCANTYPE_PROGRESSIVE} },
75 {40, 148500, 2, {2640, 1920, 528, 44, 1124, 1080, 4, 10, 100, SCANTYPE_INTERLACED} },
76 {41, 148500, 2, {1980, 1280, 440, 40, 750, 720, 5, 5, 100, SCANTYPE_PROGRESSIVE} },
77 {42, 54000, 1, {864, 720, 12, 64, 625, 576, 5, 5, 100, SCANTYPE_PROGRESSIVE} },
80 {46, 148352, 2, {2200, 1920, 88, 44, 1124, 1080, 4, 10, 119, SCANTYPE_INTERLACED} },
81 {46, 148500, 2, {2200, 1920, 88, 44, 1124, 1080, 4, 10, 120, SCANTYPE_INTERLACED} },
83 {47, 148352, 2, {1650, 1280, 110, 40, 750, 720, 5, 5, 119, SCANTYPE_PROGRESSIVE} },
84 {47, 148500, 2, {1650, 1280, 110, 40, 750, 720, 5, 5, 120, SCANTYPE_PROGRESSIVE} },
86 {48, 54000, 1, {858, 720, 16, 62, 525, 480, 9, 6, 119, SCANTYPE_PROGRESSIVE} },
87 {48, 54054, 1, {858, 720, 16, 62, 525, 480, 9, 6, 120, SCANTYPE_PROGRESSIVE} },
89 {52, 108000, 1, {864, 720, 12, 64, 625, 576, 5, 5, 200, SCANTYPE_PROGRESSIVE} },
91 {56, 108000, 1, {858, 720, 16, 62, 525, 480, 9, 6, 239, SCANTYPE_PROGRESSIVE} },
92 {56, 108108, 1, {858, 720, 16, 62, 525, 480, 9, 6, 240, SCANTYPE_PROGRESSIVE} },
96 OUT_FMT dvi_timing_table[OUT_DVI_END] = {
100 {0, 25170, 0, { 800, 640, 16, 96, 525, 480, 10, 2, 60, SCANTYPE_PROGRESSIVE} },
101 {0, 31500, 0, { 832, 640, 24, 40, 520, 480, 9, 3, 72, SCANTYPE_PROGRESSIVE} },
102 {0, 31500, 0, { 800, 640, 16, 96, 525, 480, 11, 2, 75, SCANTYPE_PROGRESSIVE} },
104 {0, 28322, 0, { 900, 720, 15, 108, 449, 400, 11, 2, 70, SCANTYPE_PROGRESSIVE} },
106 {0, 38100, 0, {1088, 800, 32, 128, 619, 600, 1, 4, 56, SCANTYPE_PROGRESSIVE} },
109 {0, 40000, 0, {1056, 800, 40, 128, 628, 600, 1, 4, 60, SCANTYPE_PROGRESSIVE} },
110 {0, 50000, 0, {1040, 800, 56, 120, 666, 600, 37, 6, 72, SCANTYPE_PROGRESSIVE} },
111 {0, 49500, 0, {1056, 800, 16, 80, 624, 600, 1, 2, 75, SCANTYPE_PROGRESSIVE} },
113 {0, 65000, 0, {1344, 1024, 24, 136, 806, 768, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
114 {0, 75000, 0, {1328, 1024, 24, 136, 806, 768, 3, 6, 70, SCANTYPE_PROGRESSIVE} },
115 {0, 78750, 0, {1312, 1024, 16, 96, 800, 768, 1, 3, 75, SCANTYPE_PROGRESSIVE} },
117 {0, 81517, 0, {1688, 1152, 48,112,1066, 864, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
119 {0, 83460, 0, {1680, 1280, 64, 136, 828, 720, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
121 {0, 83865, 0, {1680, 1280, 64, 136, 828, 800, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
123 {0, 100638, 0, {1688, 1280, 48, 112, 1066, 960, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
125 {0, 108000, 0, {1688, 1280, 48, 112, 1066, 1024, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
126 {0, 135000, 0, {1688, 1280, 16, 144, 1066, 1024, 1, 3, 75, SCANTYPE_PROGRESSIVE} },
128 {0, 85543, 0, {2256, 1360,104, 184, 1087, 768, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
129 {0, 85920, 0, {2256, 1366,104, 184, 1087, 768, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
131 {0, 121750, 0, {1864, 1400, 88,144,1089, 1050, 3, 4, 60, SCANTYPE_PROGRESSIVE} },
132 {0, 156000, 0, {1896, 1400,104,144,1099, 1050, 3, 4, 75, SCANTYPE_PROGRESSIVE} },
135 {0, 88750, 0, {1600, 1440, 48, 32, 926, 900, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
136 {0, 119000, 0, {1840, 1440, 48, 32, 1080, 1050, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
138 {0, 117936, 0, {2256, 1600,104, 184, 1250, 900, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
139 {0, 162000, 0, {2160, 1600, 64, 192, 1250, 1200, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
141 {0, 147130, 0, {2256, 1680,104, 184, 1087, 1050, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
142 {0, 148500, 0, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 60, SCANTYPE_PROGRESSIVE} },
143 {0, 154000, 0, {2080, 1920, 48, 32, 1235, 1200, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
150 OUT_FMT ch7036_crt_timing_table[OUT_CRT_END] = {
153 {100, 31500, 1, {832, 640, 32, 64, 445, 400, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
155 {100, 25175, 1, {800, 640, 8, 96, 525, 480, 2, 2, 60, SCANTYPE_PROGRESSIVE} },
156 {100, 31500, 1, {832, 640, 16, 40, 520, 480, 1, 3, 72, SCANTYPE_PROGRESSIVE} },
157 {100, 31500, 1, {840, 640, 16, 64, 500, 480, 1, 3, 75, SCANTYPE_PROGRESSIVE} },
158 {100, 36000, 1, {832, 640, 56, 56, 509, 480, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
160 {100, 35500, 1, {936, 720, 36, 72, 446, 400, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
164 {100, 36000, 1, {1024, 800, 24, 72, 625, 600, 1, 2, 56, SCANTYPE_PROGRESSIVE} },
167 {100, 38250, 1, {1024, 800, 32, 80, 624, 600, 3, 4, 60, SCANTYPE_PROGRESSIVE} },
168 {100, 50000, 1, {1040, 800, 56, 120, 666, 600, 37, 6, 72, SCANTYPE_PROGRESSIVE} },
169 {100, 49000, 1, {1040, 800, 40, 80, 629, 600, 3, 4, 75, SCANTYPE_PROGRESSIVE} },
170 {100, 56750, 1, {1056, 800, 48, 80, 633, 600, 3, 4, 85, SCANTYPE_PROGRESSIVE} },
173 {100, 65000, 1, {1344, 1024, 24, 136, 806, 768, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
174 {100, 75000, 1, {1328, 1024, 24, 136, 806, 768, 3, 6, 70, SCANTYPE_PROGRESSIVE} },
175 {100, 78750, 1, {1312, 1024, 16, 96, 800, 768, 1, 3, 75, SCANTYPE_PROGRESSIVE} },
177 {100, 94500, 1, {1376, 1024, 48, 96, 808, 768, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
180 {100, 108000, 1, {1600, 1152, 64, 128, 900, 864, 1, 2, 75, SCANTYPE_PROGRESSIVE} },
183 {100, 79500, 1, {1664, 1280, 64, 128, 798, 768, 3, 7, 60, SCANTYPE_PROGRESSIVE} },
184 {100, 102250, 1, {1696, 1280, 80, 128, 805, 768, 3, 7, 75, SCANTYPE_PROGRESSIVE} },
185 {100, 117500, 1, {1712, 1280, 80, 136, 809, 768, 3, 7, 85, SCANTYPE_PROGRESSIVE} },
188 {100, 108000, 1, {1800, 1280, 96, 112, 1000, 960, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
189 {100, 148500, 1, {1728, 1280, 64, 160, 1011, 960, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
192 {100, 108000, 1, {1688, 1280, 48, 112, 1066, 1024, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
193 {100, 135000, 1, {1688, 1280, 16, 144, 1066, 1024, 1, 3, 75, SCANTYPE_PROGRESSIVE} },
194 {100, 157500, 1, {1728, 1280, 64, 160, 1072, 1024, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
197 {100, 85500, 1, {1792, 1360, 64, 112, 795, 768, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
200 {100, 121750, 1, {1864, 1400, 88,144,1089, 1050, 3, 4, 60, SCANTYPE_PROGRESSIVE} },
201 {100, 156000, 1, {1896, 1400,104,144,1099, 1050, 3, 4, 75, SCANTYPE_PROGRESSIVE} },
204 {100, 88750, 1, {1600, 1440, 48, 32, 926, 900, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
207 {100, 119000, 1, {1840, 1440, 48, 32, 1080, 1050, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
210 {100, 117936, 1, {2256, 1600,104, 184, 1250, 900, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
213 {100, 162000, 1, {2160, 1600, 64, 192, 1250, 1200, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
217 {100, 148500, 1, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 60, SCANTYPE_PROGRESSIVE} },
227 uint8 I2CRead(DEV_CONTEXT* pDevContext,uint8 index)
230 ch7036_device_context_t *p_ctx= pDevContext->pd_context;
231 pd_reg_t reg_list[2];
233 reg_list[0].reg = (i2c_reg_t)index;
234 reg_list[1].reg = PD_REG_LIST_END;
236 p_ctx->p_callback->read_regs(p_ctx->p_callback->callback_context, reg_list,PD_REG_DDC);
238 return (uint8)(reg_list[0].value);
241 void I2CWrite(DEV_CONTEXT* pDevContext,uint8 index, uint8 value)
243 ch7036_device_context_t *p_ctx= pDevContext->pd_context;
244 pd_reg_t reg_list[2];
248 reg_list[0].reg = (i2c_reg_t)index;
249 reg_list[0].value = (i2c_reg_t)value;
251 reg_list[1].reg = PD_REG_LIST_END;
253 p_ctx->p_callback->write_regs(p_ctx->p_callback->callback_context, reg_list,PD_REG_DDC);
259 void I2CBlockWrite(DEV_CONTEXT* pDevContext,uint8 index, uint8* value, uint16 len)
261 ch7036_device_context_t *p_ctx= pDevContext->pd_context;
262 pd_reg_t reg_list[MAX_I2C_BLOCK_SIZE +1];
267 reg_list[i].reg = (i2c_reg_t)index;
268 reg_list[i].value = (i2c_reg_t)value[i];
271 reg_list[len].reg = PD_REG_LIST_END;
273 p_ctx->p_callback->write_regs(p_ctx->p_callback->callback_context, reg_list,PD_REG_DDC);
278 ch7036_status_t ch7036_device_prepare(ch7036_device_context_t* p_ctx)
280 DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
281 ch7036_status_t status = SS_SUCCESS;
283 PD_DEBUG("ch7036_intf: ch7036_device_prepare()\n");
286 if(!DevicePrepare(p_ch_ctx))
288 p_ctx->last_emsg = GetLastErrorMessage();
289 status = SS_UNSUCCESSFUL;
295 ch7036_status_t ch7036_device_config(ch7036_device_context_t* p_ctx)
297 DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
298 ch7036_status_t status = SS_SUCCESS;
300 PD_DEBUG("ch7036_intf: ch7036_device_config()\n");
303 if(!DeviceConfig(p_ch_ctx))
305 p_ctx->last_emsg = GetLastErrorMessage();
306 status = SS_UNSUCCESSFUL;
313 ch7036_status_t ch7036_device_start(ch7036_device_context_t* p_ctx)
316 DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
317 ch7036_status_t status = SS_SUCCESS;
319 PD_DEBUG("ch7036_intf: ch7036_device_start()\n");
321 if(!DeviceRunning(p_ch_ctx))
323 p_ctx->last_emsg = GetLastErrorMessage();
324 status = SS_UNSUCCESSFUL;
331 ch7036_status_t ch7036_device_set_power(ch7036_device_context_t* p_ctx, unsigned long channel)
333 DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
334 ch7036_status_t status = SS_SUCCESS;
336 PD_DEBUG("ch7036_intf: ch7036_device_set_power()- channel [%x]\n", channel);
338 if(!DeviceSetPower(p_ch_ctx,channel))
340 p_ctx->last_emsg = GetLastErrorMessage();
341 status = SS_UNSUCCESSFUL;
349 ch7036_status_t ch7036_load_firmware(ch7036_device_context_t* p_ctx)
352 DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
354 ch7036_status_t status = SS_UNSUCCESSFUL;
356 PD_DEBUG("ch7036: ch7036_load_firmware()\n");
359 if(LHFM_load_firmware(p_ch_ctx) == -1) {
360 PD_DEBUG("ch7036_load_firmware: LHFM_load_firmware()- firmware loading FAILED...\n");
364 PD_DEBUG("ch7036_load_firmware: LHFM_load_firmware()- firmware loading is a SUCCESS\n");
378 ch7036_status_t ch7036_get_hdvi_display_modes_supported(ch7036_device_context_t* p_ctx)
380 DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
381 ch7036_status_t status;
382 ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
385 PD_DEBUG("ch7036_get_hdvi_display_modes_supported()- enter\n");
387 status = LHFM_get_hdmi_modeinfo(p_ch7xxx_context,p_hedid->supported_modes);
389 if (status == SS_SUCCESS) {
391 PD_DEBUG("HDMI_Modes=%02X. Vesa_Modes=%02x\r\n", p_hedid->supported_modes[13], p_hedid->supported_modes[14]);
396 PD_DEBUG("ch7036_get_hdvi_display_modes_supported()-- failed!\r\n");
397 PD_DEBUG("status: [%s]\n",status == SS_FIRMWARE_TIMEOUT?"timeout!":"firmware_error!");
407 ch7036_status_t ch7036_read_edid(ch7036_device_context_t* p_ctx, uint32 channel)
410 DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
411 OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
412 ch7036_status_t status = SS_UNSUCCESSFUL;
414 \r#ifdef T_CH7036_EDID_DUMP
419 ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
420 ch7036_edid_blk_t* p_cedid = (ch7036_edid_blk_t *)p_ctx->cedid;
423 unsigned char* hedidblk = p_hedid->edidblk;
424 unsigned char* cedidblk = p_cedid->edidblk;
430 case CHANNEL_LVDS_HDMI:
434 status = LHFM_get_edid(p_ch7xxx_context,hedidblk, &(p_hedid->ebn), CH7036_HDMI_DDC);
436 if(status == SS_SUCCESS) {
438 PD_DEBUG("ch7036_read_edid()-hdmi-dvi hpd status- attached, hdmi-dvi edid read is a SUCCESS\n");
439 PD_DEBUG("ch7036_read_edid()- number of blocks read [%x]\n", p_hedid->ebn);
441 p_hedid->is_edid = 1;
442 if(p_hedid->ebn == 1)
443 pOutput_Info->hdmi_fmt.is_dvi_mode =1;
446 pOutput_Info->hdmi_fmt.is_dvi_mode =0;
450 #ifdef T_CH7036_EDID_DUMP
452 if (p_hedid->ebn <= MAX_EDID_BLOCKS) {
453 for (i=0; i<p_hedid->ebn; i++)
454 ch7036_dump("HDMI-DVI EDID Data", 128, &hedidblk[i*128]);
463 p_hedid->is_edid = 0;
465 status = SS_UNSUCCESSFUL;
471 case CHANNEL_LVDS_VGA:
474 I2CWrite(p_ch7xxx_context,0x03, 0x01);
475 I2CWrite(p_ch7xxx_context,0x0F, I2CRead(p_ch7xxx_context,0x0F) & 0x7F);
478 status = LHFM_get_edid(p_ch7xxx_context,cedidblk, &(p_cedid->ebn), CH7036_VGA_DDC);
479 if (status== SS_SUCCESS) {
481 PD_DEBUG("ch7036_read_edid()- crt hpd status- attached, crt edid read is a SUCCESS\n");
482 PD_DEBUG("ch7036_read_edid()- number of blocks read [%x]\n", p_cedid->ebn);
484 #ifdef T_CH7036_EDID_DUMP
485 if (p_cedid->ebn <= MAX_EDID_BLOCKS)
486 for (i=0; i<p_cedid->ebn; i++)
487 ch7036_dump("VGA EDID Data", 128, &cedidblk[i*128]);
496 status = SS_UNSUCCESSFUL;
512 ch7036_status_t ch7036_get_hdmi_hpd(ch7036_device_context_t* p_ctx, uint8 *hpd)
514 DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
515 ch7036_status_t status= SS_SUCCESS;
516 unsigned char reg, reg_hpdpw;
518 I2CWrite(p_ch7xxx_context,0x03, 0x03);
519 reg = I2CRead(p_ch7xxx_context,0x25);
521 I2CWrite(p_ch7xxx_context,0x03, 0x04);
522 reg_hpdpw = I2CRead(p_ch7xxx_context,0x51);
525 if(!(reg & 0x10) && (reg_hpdpw & 0x80) ){
530 switch (reg & 0x10) {
532 if(p_ctx->hpd & CH7036HPD_HDVI_ATTACHED)
538 if(p_ctx->hpd & CH7036HPD_HDVI_ATTACHED)
546 PD_DEBUG("ch7036: ch7036_get_hdmi_hpd- exit...*hpd [0x%x]\n",*hpd);
551 ch7036_status_t ch7036_get_attached_device(ch7036_device_context_t* p_ctx)
553 DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
554 OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
556 ch7036_status_t status = SS_SUCCESS;
557 ch7036_status_t status_hdmi, status_crt;
559 ch7036_edid_blk_t * p_hedid = (ch7036_edid_blk_t *)(p_ctx->hedid);
565 I2CWrite(p_ch7xxx_context,0x03, 0x04);
566 reg = I2CRead(p_ch7xxx_context,0x52);
569 I2CWrite(p_ch7xxx_context,0x52, reg);
572 I2CWrite(p_ch7xxx_context,0x03, 0x0);
573 reg = I2CRead(p_ch7xxx_context,0x07);
576 I2CWrite(p_ch7xxx_context,0x07, reg);
578 I2CWrite(p_ch7xxx_context,0x03, 0x01);
579 reg = I2CRead(p_ch7xxx_context,0x0F);
582 I2CWrite(p_ch7xxx_context,0x0F, reg);
584 I2CWrite(p_ch7xxx_context,0x0E, I2CRead(p_ch7xxx_context,0x0E) & 0x7F);
586 PD_DEBUG("ch7036_get_attached_device()- enter- p_ctx->hpd= [0x%x]\n", p_ctx->hpd);
588 status_hdmi = ch7036_get_hdmi_hpd(p_ctx,&hpd);
589 LHFM_enable_crt_hpd(p_ch7xxx_context);
590 status_crt = LHFM_get_crt_hpd(p_ch7xxx_context);
592 PD_DEBUG("ch7036_get_attached_device()- enter- pOutput_Info->channel = [0x%x]\n", pOutput_Info->channel);
594 if(p_ctx->man_sel_out==1) { //manual selection
597 if( (status_crt == SS_SUCCESS) || ( (hpd & 0x01)== 1 ) ) {
599 switch (pOutput_Info->channel) {
600 case CHANNEL_LVDS_DVI:
602 case CHANNEL_LVDS_HDMI:
606 if( (status_crt == SS_SUCCESS) && ( (hpd & 0x01)== 0 ) ) {
608 p_ctx->hpd = 0x16; //bit 4=1 to indicate SS_DISPLAY_CHOICE_NOT_ALLOWED, check edid and parse it
609 status = SS_DISPLAY_CHOICE_NOT_ALLOWED;
614 if (!p_ctx->init_done || ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x02) != 0x02 )
617 p_ctx->hpd = ( ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x02) == 0x02)?0xA0:0x60;
624 case CHANNEL_LVDS_VGA:
628 if((status_crt != SS_SUCCESS) && ((hpd & 0x01)==1 ) ) {
630 if(!p_ctx->init_done) {
635 p_ctx->hpd = (hpd & 0x80)?0x70:0x30;
636 status = SS_DISPLAY_CHOICE_NOT_ALLOWED;
642 if ( (!p_ctx->init_done) || ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x04) != 0x04 )//at init, need to read edid, and parse it
645 p_ctx->hpd = ( ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x04) == 0x04)?0x0A:0x06;
655 if(status == SS_DISPLAY_CHOICE_NOT_ALLOWED)
656 PD_DEBUG("ch7036_get_attached_device()- manual selection- display choice is not allowed...\n");
661 if (!p_ctx->init_done) {
667 PD_DEBUG("ch7036_get_attached_device()- manual selection- none is connected- not allowed...\n");
669 status = SS_DISPLAY_CHOICE_NOT_ALLOWED;
677 PD_DEBUG("ch7036_get_attached_device()- manual selection- exit- p_ctx->hpd= [0x%x]\n", p_ctx->hpd);
678 PD_DEBUG("ch7036_get_attached_device()- exit- pOutput_Info->channel = [0x%x]\n", pOutput_Info->channel);
680 I2CWrite(p_ch7xxx_context,0x03, 0x03);
681 reg = I2CRead(p_ch7xxx_context,0x25);
683 PD_DEBUG("ch7036_get_attached_device()- manual selection- exit...HPD_MCU [0x%x]\n",reg);
690 if(status_hdmi == SS_SUCCESS) {
693 if(p_ctx->hpd & CH7036HPD_HDVI_ATTACHED) {
695 p_ctx->hpd = (p_ctx->hpd & 0x9F) & ((~CH7036HPD_HDVI_STATUS_CHANGED) | CH7036HPD_HDVI_ATTACHED);
697 ch7036_get_hdvi_display_modes_supported(p_ctx);
700 ((pOutput_Info->hdmi_fmt.is_dvi_mode== 0) && (p_hedid->supported_modes[13] == 0) )||
701 ((pOutput_Info->hdmi_fmt.is_dvi_mode== 1) && (p_hedid->supported_modes[13] > 0))
704 p_ctx->hpd = (p_ctx->hpd & 0x9F) | (CH7036HPD_HDVI_STATUS_CHANGED | CH7036HPD_HDVI_ATTACHED);
705 PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status changed [HDMI<->DVI] since last query and it's HIGH\n");
709 PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status has not changed since last query and it's HIGH\n");
714 p_ctx->hpd = (p_ctx->hpd & 0x9F) | (CH7036HPD_HDVI_STATUS_CHANGED | CH7036HPD_HDVI_ATTACHED);
715 PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status changed since last query and it's HIGH\n");
718 else if (hpd ==0x80) {
719 if( (p_ctx->hpd & CH7036HPD_HDVI_ATTACHED) ==0 ) {
721 p_ctx->hpd = (p_ctx->hpd & 0x9F) & ((~ CH7036HPD_HDVI_STATUS_CHANGED) & (~CH7036HPD_HDVI_ATTACHED)) ;
722 PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status not changed since last query and it's LOW\n");
726 p_ctx->hpd = (p_ctx->hpd & 0x9F) | (CH7036HPD_HDVI_STATUS_CHANGED & (~CH7036HPD_HDVI_ATTACHED)) ;
727 PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status changed since last query and it's LOW\n");
731 else if (hpd == 0x01) {
733 p_ctx->hpd = (p_ctx->hpd & 0x9F) & ((~CH7036HPD_HDVI_STATUS_CHANGED) | CH7036HPD_HDVI_ATTACHED);
734 PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status has not changed since last query and it's HIGH\n");
739 PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status has not changed since last query and it's LOW\n");
744 PD_DEBUG("ch7036: ch7036_get_attached_device()- SUCCESS- hdmi hpd [0x%x]\n", hpd);
750 if ( (!p_ctx->init_done) && (hpd == 0x86) ) {
752 p_ctx->hpd |= CH7036HPD_HDVI_ATTACHED;
757 p_ctx->hpd &= ~CH7036HPD_HDVI_ATTACHED;
763 if(status_crt == SS_SUCCESS) {
765 if( (p_ctx->hpd & CH7036HPD_CRT_ATTACHED )== CH7036HPD_CRT_ATTACHED)
766 p_ctx->hpd = (p_ctx->hpd & 0xF9) & ((~CH7036HPD_CRT_STATUS_CHANGED) | CH7036HPD_CRT_ATTACHED);
769 p_ctx->hpd = ((p_ctx->hpd & 0xF9) | ( CH7036HPD_CRT_STATUS_CHANGED | CH7036HPD_CRT_ATTACHED));
774 if( (p_ctx->hpd & CH7036HPD_CRT_ATTACHED ) == 0 ) {
777 if( (p_ctx->hpd & CH7036HPD_HDVI_ATTACHED)== 0 )
783 if ( (p_ctx->hpd & CH7036HPD_HDVI_ATTACHED) ==0 )
786 p_ctx->hpd = (p_ctx->hpd & 0xF9) | CH7036HPD_CRT_STATUS_CHANGED;
791 PD_DEBUG("ch7036_get_attached_device()- auto detection - exit- p_ctx->hpd= [0x%x]\n", p_ctx->hpd);
796 void ch7036_reset(ch7036_device_context_t* p_ctx)
798 DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
800 ch7036_reset_mcu(p_ch_ctx);
801 ch7036_reset_datapath(p_ch_ctx);
806 void ch7036_reset_datapath(DEV_CONTEXT* p_ch_ctx)
809 PD_DEBUG("ch7036: ch7036_reset_datapath()-enter\n");
810 I2CWrite(p_ch_ctx,0x03, 0x04);
811 I2CWrite(p_ch_ctx,0x52, 0x2E);
814 I2CWrite(p_ch_ctx,0x52, 0x2F);
819 void ch7036_reset_mcu(DEV_CONTEXT* p_ch_ctx)
822 PD_DEBUG("ch7036: ch7036_reset_mcu()-enter\n");
824 I2CWrite(p_ch_ctx,0x03, 0x04);
825 I2CWrite(p_ch_ctx,0x52, 0x2B);
828 I2CWrite(p_ch_ctx,0x52, 0x2F);
831 PD_DEBUG("ch7036: ch7036_reset_mcu()-exit-\n");
839 void ch7036_set_input_timing_info(ch7036_device_context_t *p_ctx, INPUT_INFO* pInput_Info)
841 DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
842 OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
844 pd_timing_t * p_current_mode = &(p_ctx->native_dtd);
845 uint8 audio_id = AUDIO_SPDIF;
846 PD_DEBUG("ch7036_intf: ch7036_set_input_timing_info()-\n");
849 if (p_ctx->init_done) {
852 pInput_Info->timing.ht = p_current_mode->htotal+1;
854 pInput_Info->timing.ha = p_current_mode->width;
855 pInput_Info->timing.ho = p_current_mode->hsync_start - p_current_mode->hblank_start;
856 pInput_Info->timing.hw = p_current_mode->hsync_end - p_current_mode->hsync_start;
857 pInput_Info->timing.vt = p_current_mode->vtotal+1;
859 pInput_Info->timing.va = p_current_mode->height;
860 pInput_Info->timing.vo = p_current_mode->vsync_start - p_current_mode->vblank_start;
861 pInput_Info->timing.vw = p_current_mode->vsync_end - p_current_mode->vsync_start;
864 pInput_Info->rx_clk_khz = p_current_mode->dclk;
867 pInput_Info->hs_pol = ((uint8)(((p_current_mode)->mode_info_flags & PD_HSYNC_HIGH) >> 24 ))?1:0;
868 pInput_Info->vs_pol = ((uint8)(((p_current_mode)->mode_info_flags & PD_VSYNC_HIGH) >> 24))?1:0;
876 pInput_Info->pixel_fmt = ((lvds_context_t *)p_ctx->internal_lvds)->panel_depth == 18?PIXEL_FMT_18BIT:3;
879 pInput_Info->data_ch_pol = POL_NO_INV;
882 pInput_Info->data_ch_invert = POL_NO_INV;
888 pInput_Info->de_pol = POL_HIGH;
894 if(pOutput_Info->channel & CHANNEL_HDMI)
895 ch7036_set_audio_type(pInput_Info, audio_id);
899 void ch7036_set_output_timing_info(ch7036_device_context_t *p_ctx, OUTPUT_INFO* pOutput_Info)
903 PD_DEBUG("ch7036: ch7036_set_output_timing_info()\n");
906 PD_DEBUG("ch7036_set_output_timing_info()- output channel from pd context[%u]\n",pOutput_Info->channel);
909 pOutput_Info->lvds_fmt.channel_swap = LVDS_CHANNEL_SWAP_DEF;
910 pOutput_Info->lvds_fmt.channel_pol = (POL_LOW << 4) | (POL_LOW << 3) | (POL_LOW << 2) | (POL_LOW << 1) | (POL_LOW << 0);
911 pOutput_Info->lvds_fmt.pixel_fmt = p_ctx->dither_select;
915 pOutput_Info->hdmi_fmt.channel_swap = 0;
916 pOutput_Info->hdmi_fmt.data_pol_invert = POL_NO_INV;
917 pOutput_Info->hdmi_fmt.protect_enable = 0;
922 if (pOutput_Info->channel & CHANNEL_HDMI)
925 if(!(pOutput_Info->hdmi_fmt.is_dvi_mode))
927 PD_DEBUG("ch7036_set_output_timing_info- hdmi mode index is [0x%x]\n",p_ctx->hdmi_mode_index);
928 pOutput_Info->hdmi_fmt.format_index = (uint8)hdmi_timing_table[p_ctx->hdmi_mode_index].fmt_index;
929 pOutput_Info->hdmi_fmt.aspect_ratio = (uint8)hdmi_timing_table[p_ctx->hdmi_mode_index].aspect;
931 pOutput_Info->timing.ht = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.ht;
932 pOutput_Info->timing.ha = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.ha;
933 pOutput_Info->timing.ho = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.ho;
934 pOutput_Info->timing.hw = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.hw;
935 pOutput_Info->timing.vt = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.vt;
936 pOutput_Info->timing.va = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.va;
937 pOutput_Info->timing.vo = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.vo;
938 pOutput_Info->timing.vw = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.vw;
939 pOutput_Info->uclk_khz = hdmi_timing_table[p_ctx->hdmi_mode_index].clk_freq;
943 pOutput_Info->hdmi_fmt.format_index = (uint8)dvi_timing_table[p_ctx->dvi_mode_index].fmt_index;
944 pOutput_Info->hdmi_fmt.aspect_ratio = (uint8)dvi_timing_table[p_ctx->dvi_mode_index].aspect;
946 pOutput_Info->timing.ht = dvi_timing_table[p_ctx->dvi_mode_index].timing.ht;
947 pOutput_Info->timing.ha = dvi_timing_table[p_ctx->dvi_mode_index].timing.ha;
948 pOutput_Info->timing.ho = dvi_timing_table[p_ctx->dvi_mode_index].timing.ho;
949 pOutput_Info->timing.hw = dvi_timing_table[p_ctx->dvi_mode_index].timing.hw;
950 pOutput_Info->timing.vt = dvi_timing_table[p_ctx->dvi_mode_index].timing.vt;
951 pOutput_Info->timing.va = dvi_timing_table[p_ctx->dvi_mode_index].timing.va;
952 pOutput_Info->timing.vo = dvi_timing_table[p_ctx->dvi_mode_index].timing.vo;
953 pOutput_Info->timing.vw = dvi_timing_table[p_ctx->dvi_mode_index].timing.vw;
954 pOutput_Info->uclk_khz = dvi_timing_table[p_ctx->dvi_mode_index].clk_freq;
960 } else if((pOutput_Info->channel & CHANNEL_VGA) && ((pOutput_Info->channel & CHANNEL_HDMI)==0x00) )
965 PD_DEBUG("ch7036_set_output_timing_info- crt mode index is [0x%x]\n",p_ctx->crt_mode_index);
966 pOutput_Info->timing.ht = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.ht;
967 pOutput_Info->timing.ha = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.ha;
968 pOutput_Info->timing.ho = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.ho;
969 pOutput_Info->timing.hw = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.hw;
970 pOutput_Info->timing.vt = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.vt;
971 pOutput_Info->timing.va = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.va;
972 pOutput_Info->timing.vo = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.vo;
973 pOutput_Info->timing.vw = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.vw;
974 pOutput_Info->uclk_khz = ch7036_crt_timing_table[p_ctx->crt_mode_index].clk_freq;
981 if(pOutput_Info->channel & CHANNEL_HDMI)
982 ch7036_set_hdmi_sync_polarity(pOutput_Info);
984 if(pOutput_Info->channel & CHANNEL_HDMI || pOutput_Info->channel & CHANNEL_VGA) {
986 ch7036_set_rotate (pOutput_Info);
987 ch7036_set_hflip (pOutput_Info);
988 ch7036_set_vflip (pOutput_Info);
992 void ch7036_set_prefer_timing_info(ch7036_device_context_t *p_ctx, PREFER_INFO* pPrefer_Info)
998 PD_DEBUG("ch7036_intf: ch7036_set_prefer_timing_info()\n");
1001 if (!p_ctx->init_done) {
1003 pPrefer_Info->mclk_khz = 166000;
1004 pPrefer_Info->uclkod_sel = 1;
1005 pPrefer_Info->dat16_32b = 0;
1006 pPrefer_Info->true24 = 0;
1007 pPrefer_Info->true_com = 0;
1008 pPrefer_Info->lvds_out_hs_tolerance = HS_TOLERANCE_LEVEL0;
1009 pPrefer_Info->lvds_out_reset_bit_sel = RST_BIT_VSYNC;
1010 pPrefer_Info->dither_filter_enable = DITHER_ENABLE;
1012 pPrefer_Info->hscale_ratio_gate = 130;
1013 pPrefer_Info->reset=0;
1014 pPrefer_Info->vga_enable=0;
1016 pPrefer_Info->text_enhancement = DEFAULT_TEXT_ENHANCE;
1017 pPrefer_Info->pll_ref_dly = DEF_PLL_REF_DLY;
1018 pPrefer_Info->pll_ref_fbdly = DEF_PLL_REF_FBDLY;
1019 pPrefer_Info->lvds_txdrv_ctrl = DEF_LVDS_TXDRV_CTRL;
1021 pPrefer_Info->eye_bgtrim=0;
1022 pPrefer_Info->eye_dacg=0;
1023 pPrefer_Info->eye_dri_demp=0;
1024 pPrefer_Info->eye_dri_pll_cp=0;
1025 pPrefer_Info->eye_dri_damp=0;
1026 pPrefer_Info->eye_dri_pll_rlf=0;
1027 pPrefer_Info->eye_rdac=0;
1031 pPrefer_Info->scale_line_adjust = 0;
1038 ch7036_status_t ch7036_parse_standard_edid(ch7036_device_context_t* p_ctx, uint32 channel)
1042 ch7036_edid_blk_t* p_edid = (ch7036_edid_blk_t *)p_ctx->cedid;
1043 unsigned char* p_edidblk = p_edid->edidblk;
1046 OUT_FMT* p_table = ch7036_crt_timing_table;
1055 established_timings_t *p_etiming_I = p_edid->etiming_I;
1056 established_timings_t *p_etiming_II = p_edid->etiming_II;
1060 standard_timings_t *stiming = p_edid->stiming;
1061 ch7036_attr_table_index_t* p_modes = p_edid->modes;
1063 unsigned long idx = 2;
1066 PD_DEBUG("ch7036_parse_stardard_edid() channel [0x%x] - enter...\n", channel);
1069 if(channel == CHANNEL_LVDS_HDMI) {
1071 p_edid = (ch7036_edid_blk_t *)p_ctx->hedid;
1072 p_edidblk = p_edid->edidblk;
1073 p_etiming_I = p_edid->etiming_I;
1074 p_etiming_II = p_edid->etiming_II;
1076 stiming = p_edid->stiming;
1077 p_modes = p_edid->modes;
1080 if (p_edid->ebn > 1) {
1082 p_table = hdmi_timing_table;
1086 p_table = dvi_timing_table;
1094 while (index < MAX_ATTR_LIST_SIZE)
1095 p_modes[index++] = FALSE;
1098 if (p_edidblk[EDID_EXTENSION_FLAG] == 0x00 ) {
1101 ch7036_parse_standard_timing(p_edid,0);
1104 ch7036_parse_established_timing(p_ctx, p_edid);
1108 ch7036_parse_detailed_descriptor_blocks(p_ctx, p_edid);
1116 while (index < MAX_ATTR_LIST_SIZE ) {
1117 if(p_modes[index]== TRUE) {
1121 p_timing = &(p_table[index].timing);
1123 if ( (p_edid->dtblk[j]).data_tag & 0x00FFFFFF ) {
1124 OUT_FMT* p_dtd = &((p_edid->dtblk[j]).dtiming);
1126 if( (p_dtd->timing.ha == p_timing->ha) && (p_dtd->timing.va == p_timing->va) && (p_dtd->timing.hz >= p_timing->hz) ) {
1127 p_modes[index] = TRUE;
1130 PD_DEBUG("ch7036_parse_standard_edid()- detailed timing mode supported- index [%d] name [%s]...\n",index,ch7036_get_mode_name(channel,index) );
1137 if( (stiming[i].ha == p_timing->ha) && (stiming[i].va == p_timing->va) && (stiming[i].refresh_rate >= p_timing->hz) ) {
1138 p_modes[index] = TRUE;
1139 PD_DEBUG("ch7036_parse_standard_edid()- std_timing mode supported- index [%d] name [%s]...\n",index,ch7036_get_mode_name(channel,index) );
1150 if ( (p_edid->dtblk[i]).data_tag == 0xFA000000) {
1162 if( (p_etiming_I[i].is_supported == TRUE) && (p_etiming_I[i].index[idx] != OUT_CRT_END) ) {
1163 p_modes[p_etiming_I[i].index[idx]] = TRUE;
1164 PD_DEBUG("ch7036_parse_standard_edid()- et1 mode supported- index [%d] name [%s]...\n",p_etiming_I[i].index[idx],p_etiming_I[i].mode_name);
1170 if( (i==7) && (channel ==7) && (p_etiming_I[i].is_supported == TRUE) ) {
1171 p_modes[p_etiming_I[i].index[idx]] = TRUE;
1172 PD_DEBUG("ch7036_parse_standard_edid()- et1 mode supported- index [%d] name [%s]...\n",p_etiming_I[i].index[idx],p_etiming_I[i].mode_name);
1180 if( (p_etiming_II[i].is_supported == TRUE) && (p_etiming_II[i].index[idx] != OUT_CRT_END) ) {
1181 p_modes[p_etiming_II[i].index[idx]] = TRUE;
1182 PD_DEBUG("ch7036_parse_standard_edid()- et2 mode supported- index [%d] name [%s]...\n",p_etiming_II[i].index[idx],p_etiming_II[i].mode_name);
1193 PD_DEBUG("ch7036_parse_standard_edid()- vga/dvi has more than one 128 byte block\n");
1197 PD_DEBUG("ch7036_parse_stardard_edid()-channel [0x%x] - exit...\n", channel);
1203 void ch7036_parse_detailed_descriptor_blocks(ch7036_device_context_t* p_ctx, ch7036_edid_blk_t* p_edid)
1205 unsigned long *monitor_descriptor;
1206 unsigned char* p_ebuf, *p_st;
1207 unsigned char* p_edidblk = p_edid->edidblk;
1212 p_ebuf = &(p_edidblk[EDID_DETAILED_TIMING_DESCRIPTION_1]);
1214 PD_DEBUG("parse_detailed_descriptor_blocks()- enter...\n");
1218 monitor_descriptor = (unsigned long *) p_ebuf;
1220 if((*monitor_descriptor) & 0x00FFFFFF ) {
1223 p_dt = &(p_edid->dtblk[i].dtiming);
1224 ch7036_parse_detailed_timing(p_dt, p_ebuf);
1233 switch (*monitor_descriptor) {
1235 ch7036_parse_standard_timing(p_edid,p_st);
1239 (p_edid->rtiming).vrate_min = *p_st;
1240 (p_edid->rtiming).vrate_max = *(p_st+1);
1241 (p_edid->rtiming).hrate_min = *(p_st+2);
1242 (p_edid->rtiming).hrate_max = *(p_st+3);
1243 (p_edid->rtiming).pclk_max = (unsigned long)(*(p_st+4))*10000L;
1255 (p_edid->dtblk[i]).data_tag = *monitor_descriptor;
1263 void ch7036_parse_detailed_timing(OUT_FMT *p_dt, unsigned char* p_ebuf)
1266 unsigned short blanking;
1268 PD_DEBUG("ch7036_parse_detailed_descriptor_timing()- enter...\n");
1271 p_dt->clk_freq = ((uint32)(p_ebuf[1]<<8) | p_ebuf[0]) * 10;
1273 p_dt->timing.ha = ((uint16)(p_ebuf[4] & 0xF0) << 4) | p_ebuf[2];
1275 PD_DEBUG("ch7036_parse_detailed_timing() byte 3 [%x] byte 5 [%x]\n",p_ebuf[2],p_ebuf[4]);
1277 blanking = ((uint16)(p_ebuf[4] & 0x0F) << 8) | p_ebuf[3];
1278 p_dt->timing.ht = p_dt->timing.ha + blanking;
1280 p_dt->timing.va = ((uint16)(p_ebuf[7] & 0xF0) << 4) | p_ebuf[5];
1282 PD_DEBUG("ch7036_parse_detailed_timing() byte 6 [%x] byte 8 [%x]\n",p_ebuf[5],p_ebuf[7]);
1284 blanking = ((uint16)(p_ebuf[7] & 0x0F) << 8) | p_ebuf[6];
1285 p_dt->timing.vt = p_dt->timing.va + blanking;
1287 PD_DEBUG("ch7036_parse_detailed_timing()- pclk [%d] Khz ha [%d] va [%d] ht [%d] vt [%d]\n",p_dt->clk_freq,p_dt->timing.ha,p_dt->timing.va,p_dt->timing.ht,p_dt->timing.vt);
1289 p_dt->timing.hz = (((p_dt->clk_freq / p_dt->timing.ht) + 1 ) * 1000) / p_dt->timing.vt;
1291 p_dt->timing.stype = (p_ebuf[17] & 0x80)?0:1;
1293 PD_DEBUG("ch7036_parse_detailed_timing()- refresh [%d] scantype [%d]\n",
1294 p_dt->timing.hz,p_dt->timing.stype);
1301 void ch7036_parse_standard_timing(ch7036_edid_blk_t* p_edid, unsigned char* p_addtional_st)
1303 standard_timings_t *stiming = p_edid->stiming;
1304 unsigned char i, max=8;
1306 unsigned char* p_edidblk = &(p_edid->edidblk[EDID_STANDARD_TIMINGS]);
1309 PD_DEBUG("ch7036_parse_standard_timing()- enter\n");
1311 if(p_addtional_st) {
1312 p_edidblk = p_addtional_st;
1313 stiming = p_edid->stiming_x;
1317 for(i = 0; i < max; stiming++,i++) {
1320 if( (*p_edidblk) == 0x01 && *(p_edidblk+1) == 0x01)
1323 stiming->ha = ((*p_edidblk) + 31) << 3 ;
1325 stiming->refresh_rate = (*(p_edidblk + 1) & 0x3F) + 60;
1327 switch(*(p_edidblk +1) >> 6) {
1330 stiming->va = (stiming->ha *10) >> 4;
1333 stiming->va = (stiming->ha *3) >> 2;
1336 stiming->va = (stiming->ha << 2) / 5;
1339 stiming->va = (stiming->ha* 9) >>4;
1347 PD_DEBUG("ch7036_parse_standard_timing()- ha [%d] va [%d] refresh [%d]\n",stiming->ha,stiming->va,stiming->refresh_rate);
1357 void ch7036_parse_established_timing(ch7036_device_context_t* p_ctx, ch7036_edid_blk_t* p_edid)
1360 unsigned char* p_edidblk = p_edid->edidblk;
1364 established_timings_t *p_etiming_I = p_edid->etiming_I;
1365 established_timings_t *p_etiming_II = p_edid->etiming_II;
1366 established_timings_t *p_etiming_man = p_edid->etiming_man;
1369 unsigned char et1, et2;
1371 PD_DEBUG("ch7036_parse_established_timing()- enter...\n");
1373 et1 = p_edidblk[EDID_ESTABLISHED_TIMINGS_1];
1374 et2 = p_edidblk[EDID_ESTABLISHED_TIMINGS_2];
1379 p_etiming_I[i].is_supported = FALSE;
1380 p_etiming_II[i].is_supported = FALSE;
1385 p_etiming_man->is_supported = FALSE;
1393 p_etiming_I[i].is_supported = TRUE;
1399 p_etiming_II[i].is_supported = TRUE;
1410 if (p_edidblk[EDID_MANUFACTURERS_RESERVED_TIMINGS] & 0x80) {
1412 p_etiming_man->is_supported = TRUE;
1422 ch7036_status_t ch7036_parse_cea_edid(ch7036_device_context_t* p_ctx)
1424 uint8 tag, blk_size =0;
1432 ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
1434 unsigned char* p_edidblk = p_hedid->edidblk;
1435 ch7036_attr_table_index_t* p_modes = p_hedid->modes;
1438 PD_DEBUG("ch7036_parse_cea_edid()- enter...\n");
1440 while (index < MAX_ATTR_LIST_SIZE )
1441 p_modes[index++] = FALSE;
1444 if(p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET] == 0 || p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET] > 124) {
1445 PD_DEBUG("ch7036_parse_cea_edid()- invalid data block size [%d]\n", p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET]);
1446 return SS_UNSUCCESSFUL;
1451 PD_DEBUG("ch7036_parse_cea_edid()- CEA revision [0x%x]...\n",p_edidblk[EDID_CEA_REVISION]);
1453 if(p_edidblk[EDID_CEA_TAG] == 0x02 && p_edidblk[EDID_CEA_REVISION] == 0x03)
1456 p_buff = &(p_edidblk[EDID_CEA_DATA_BLOCK]);
1461 for(; count < p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET]; p_buff += blk_size) {
1463 blk_size = (*p_buff) & 0x1F;
1464 tag = (*p_buff) & 0xE0;
1466 PD_DEBUG("ch7036_parse_cea_edid()- data type [0x%x] block_size [%d]\n", tag, blk_size);
1476 ch7036_parse_cea_video_data_block(blk_size, p_buff, p_hedid);
1490 count += (blk_size + 1);
1498 PD_DEBUG("ch7036_parse_cea_edid()- exit...\n");
1506 void ch7036_parse_cea_video_data_block(uint8 blk_size, uint8* p_buff, ch7036_edid_blk_t* p_edid)
1510 ch7036_attr_table_index_t* p_modes = p_edid->modes;
1512 for(i=1; i <= blk_size; i++, p_buff++ ) {
1516 PD_DEBUG("ch7036_parse_cea_video_data_block()- HDMI display video code [0x%x]\n",(*p_buff) & 0x7F);
1518 while (index < OUT_HDMI_END) {
1521 if( p_modes[index] == TRUE ) {
1527 if( ((*p_buff) & 0x7F) == hdmi_timing_table[index].fmt_index ) {
1529 p_modes[index] = TRUE;
1530 PD_DEBUG("ch7036_parse_cea_video_data_block()- mode supported: global table index [%d] name [%s]...\n",index, ch7036_get_mode_name(CHANNEL_LVDS_HDMI,index) );
1532 if( hdmi_timing_table[index-1].fmt_index == hdmi_timing_table[index].fmt_index) {
1548 ch7036_status_t ch7036_parse_edid(ch7036_device_context_t* p_ctx)
1552 DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
1553 OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
1555 ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
1556 ch7036_edid_blk_t* p_cedid = (ch7036_edid_blk_t *)p_ctx->cedid;
1558 unsigned char* p_edidblk=0;
1559 ch7036_attr_table_index_t* p_modes = 0;
1560 pd_attr_t *p_attr = NULL ;
1563 PD_DEBUG("ch7036_parse_edid()- enter...\n");
1566 //hpd checking schemes
1572 ( (pOutput_Info->channel & 0x02) && (p_ctx->hpd & 0x80) )||
1573 ( (pOutput_Info->channel & 0x04) && (p_ctx->hpd & 0x08) )
1575 //parsing is already done
1579 switch (pOutput_Info->channel) {
1580 case CHANNEL_LVDS_HDMI:
1582 if(p_hedid->is_edid) {
1583 p_edidblk = p_hedid->edidblk;
1585 p_hedid->is_preferred_timing = (p_edidblk[EDID_FEATURE_SUPPORT] >> 1) & 0x1;
1588 if(pOutput_Info->hdmi_fmt.is_dvi_mode == 0) {
1589 p_attr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs, PD_ATTR_ID_HDMI_OUT_MODE, 0);
1590 ch7036_parse_cea_edid(p_ctx);
1593 p_attr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs, PD_ATTR_ID_DVI_OUT_MODE, 0);
1594 ch7036_parse_standard_edid(p_ctx, CHANNEL_LVDS_HDMI);
1599 p_ctx->hpd |= 0x80; //don't parse again next time
1604 PD_DEBUG("ch7036_parse_edid()- hdmi edid read failed or never done...use default...\n");
1605 ch7036_set_edid_display_supported_attr( (void *)p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,p_ctx->downscaled,p_hedid->modes,RESET);
1606 p_ctx->hpd &= 0x7F; //allow to enter parsing block again
1610 p_modes = p_hedid->modes;
1614 case CHANNEL_LVDS_VGA:
1616 if(p_cedid->is_edid) {
1617 p_edidblk = p_cedid->edidblk;
1619 p_cedid->is_preferred_timing = (p_edidblk[EDID_FEATURE_SUPPORT] >> 1) & 0x1;
1620 p_attr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs, PD_ATTR_ID_CRT_OUT_MODE, 0);
1622 ch7036_parse_standard_edid(p_ctx, CHANNEL_LVDS_VGA);
1626 PD_DEBUG("ch7036_parse_edid()- vga edid read failed or never done...use default...\n");
1627 ch7036_set_edid_display_supported_attr( (void *)p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,p_ctx->downscaled,p_cedid->modes,RESET);
1628 p_ctx->hpd &= 0x7F; //allow to enter parsing block again
1630 p_modes = p_cedid->modes;
1634 //there is no separate DVI display channel, or LVDS edid reading at this time
1635 //DVI display option should already be mapped to HDMI channel
1642 ch7036_set_edid_display_supported_attr( (void *)p_attr,0,p_ctx->downscaled,p_modes,0);
1646 PD_DEBUG("ch7036_parse_edid()- exit...\n");
1652 void ch7036_alter_display_table(int all, void *p_table,unsigned char* p_modes, void* val,unsigned long* p_invis,unsigned char is_invis,unsigned char is_6x4)
1658 PD_DEBUG("ch7036_alter_display_table()-enter...\n");
1661 unsigned long* num_attrs = (unsigned long *)val;
1662 for(i=0;i<3;i++) { //all 3 tables: hdmi, dvi, vga
1664 p_attr = pd_get_attr((pd_attr_t *)p_table, *num_attrs, PD_ATTR_ID_HDMI_OUT_MODE+i, 0);
1668 p_attr= p_attr + ch7036_invis_6x4_modes_table_size[i] + 1; //1 is to skip header
1671 for(j=0; j < *p_invis;j++) {
1673 p_attr->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
1675 p_attr->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
1680 p_invis++; //now, grab dvi, then vga table size
1687 unsigned long id= 0,k;
1688 p_attr = (pd_attr_t *)p_table;
1696 p_attr= p_attr + ch7036_invis_6x4_modes_table_size[id - PD_ATTR_ID_HDMI_OUT_MODE] + 1; //point to the first 7x4 entry
1697 j= ch7036_invis_6x4_modes_table_size[id - PD_ATTR_ID_HDMI_OUT_MODE];
1699 p_invis = p_invis + (id - PD_ATTR_ID_HDMI_OUT_MODE);
1704 p_attr->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
1715 ch7036_status_t ch7036_set_edid_display_supported_attr(void *p_table, unsigned long num_attrs, unsigned char* p_downscaled, unsigned char* p_modes, int is_reset)
1718 pd_list_attr_t *p_hdr = (pd_list_attr_t *)p_table;
1719 pd_attr_t *p_entry = (pd_attr_t *)p_table;
1723 #ifdef T_SHOW_EDID_DISPLAY_ATTR
1724 pd_list_entry_attr_t *list_entry;
1727 PD_DEBUG("ch7036_set_edid_display_supported_attr()-enter... is_reset status = [%d]\n", is_reset);
1730 while (i < MAX_ATTR_LIST_SIZE ) {
1731 p_modes[i++] = TRUE;
1736 //special handling for 1080i/p @ 59Hz
1737 p_entry = pd_get_attr((pd_attr_t *)p_table, num_attrs, PD_ATTR_ID_HDMI_OUT_MODE, 0);
1739 p_entry = p_entry + OUT_HDMI_1920x1080I_59;
1740 p_entry->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
1742 p_entry->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
1747 PD_DEBUG("ch7036_set_edid_display_supported_attr()-start to build edid display mode list...\n");
1751 for (i = 0; i < p_hdr->num_entries ; ++i,++p_entry) {
1753 (p_modes[i] == FALSE) ||
1755 ((p_hdr->id == PD_ATTR_ID_HDMI_OUT_MODE) && (i == OUT_HDMI_1920x1080I_59 || i== OUT_HDMI_1920x1080P_59) ) ){
1757 p_entry->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
1762 p_entry->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
1769 //special handling for 8x6,7x4,6x4-
1770 ch7036_alter_display_table(is_reset,p_table,p_modes,(void *)&num_attrs,ch7036_invis_6x4_modes_table_size,*p_downscaled,1);
1772 ch7036_alter_display_table(is_reset,p_table,p_modes,(void *)&num_attrs,ch7036_invis_8x6_7x4_table_size,*p_downscaled,0);
1774 #ifdef T_SHOW_EDID_DISPLAY_ATTR
1776 list_entry = (pd_list_entry_attr_t *)(p_table);
1778 for (i = 0,++list_entry; i < p_hdr->num_entries; ++i, ++list_entry)
1779 PD_DEBUG("ch7036 : ch7036_set_edid_display_supported_attr : \n"
1780 "list entry[%hhu]=%s, id=%lu, "
1781 "value=%lu, flags=0x%x \n",
1782 i, list_entry->name, list_entry->id,
1783 list_entry->value, (unsigned char)list_entry->flags);
1791 uint8 * ch7036_get_mode_name(uint32 channel, uint8 index)
1793 uint8* str = "Name String Is Not Yet Converted";
1797 case CHANNEL_LVDS_HDMI:
1799 case OUT_HDMI_640x480P_59:
1800 return ("OUT_HDMI_640x480P_59");
1801 case OUT_HDMI_640x480P_60:
1802 return ("OUT_HDMI_640x480P_60");
1803 case OUT_HDMI_720x480P_59:
1804 return ("OUT_HDMI_720x480P_59");
1805 case OUT_HDMI_720x480P_60:
1806 return ("OUT_HDMI_720x480P_60");
1807 case OUT_HDMI_1280x720P_59:
1808 return ("OUT_HDMI_1280x720P_59");
1809 case OUT_HDMI_1280x720P_60:
1810 return ("OUT_HDMI_1280x720P_60");
1811 case OUT_HDMI_1920x1080I_59:
1812 return ("OUT_HDMI_1920x1080I_59");
1813 case OUT_HDMI_1920x1080I_60:
1814 return ("OUT_HDMI_1920x1080I_60");
1815 case OUT_HDMI_1920x1080P_59:
1816 return ("OUT_HDMI_1920x1080P_59");
1817 case OUT_HDMI_1920x1080P_60:
1818 return ("OUT_HDMI_1920x1080P_60");
1824 case CHANNEL_LVDS_VGA:
1828 case OUT_CRT_640x400_85:
1829 return ("OUT_CRT_640x400_85");
1831 case OUT_CRT_640x480_60:
1832 return ("OUT_CRT_640x480_60");
1833 case OUT_CRT_640x480_72:
1834 return ("OUT_CRT_640x480_72");
1835 case OUT_CRT_640x480_75:
1836 return ("OUT_CRT_640x480_75");
1837 case OUT_CRT_640x480_85:
1838 return ("OUT_CRT_640x480_85");
1840 case OUT_CRT_720x400_85:
1841 return ("OUT_CRT_720x400_85");
1843 case OUT_CRT_800x600_56:
1844 return ("OUT_CRT_800x600_56");
1845 case OUT_CRT_800x600_60:
1846 return ("OUT_CRT_800x600_60");
1847 case OUT_CRT_800x600_72:
1848 return ("OUT_CRT_800x600_72");
1849 case OUT_CRT_800x600_75:
1850 return ("OUT_CRT_800x600_75");
1852 case OUT_CRT_800x600_85:
1853 return ("OUT_CRT_800x600_85");
1855 case OUT_CRT_1024x768_60:
1856 return ("OUT_CRT_1024x768_60");
1857 case OUT_CRT_1024x768_70:
1858 return ("OUT_CRT_1024x768_70");
1859 case OUT_CRT_1024x768_75:
1860 return ("OUT_CRT_1024x768_75");
1861 case OUT_CRT_1024x768_85:
1862 return ("OUT_CRT_1024x768_85");
1864 case OUT_CRT_1152x864_75:
1865 return ("OUT_CRT_1152x864_75");
1867 case OUT_CRT_1280x768_60:
1868 return ("OUT_CRT_1280x768_60");
1869 case OUT_CRT_1280x768_75:
1870 return ("OUT_CRT_1280x768_75");
1871 case OUT_CRT_1280x768_85:
1872 return ("OUT_CRT_1280x768_85");
1874 case OUT_CRT_1280x960_60:
1875 return ("OUT_CRT_1280x960_60");
1876 case OUT_CRT_1280x960_85:
1877 return ("OUT_CRT_1280x960_85");
1879 case OUT_CRT_1280x1024_60:
1880 return ("OUT_CRT_1280x1024_60");
1881 case OUT_CRT_1280x1024_75:
1882 return ("OUT_CRT_1280x1024_75");
1883 case OUT_CRT_1280x1024_85:
1884 return ("OUT_CRT_1280x1024_85");
1886 case OUT_CRT_1360x768_60:
1887 return ("OUT_CRT_1360x768_60");
1889 case OUT_CRT_1400x1050_60:
1890 return ("OUT_CRT_1400x1050_60");
1891 case OUT_CRT_1400x1050_75:
1892 return ("OUT_CRT_1400x1050_75");
1894 case OUT_CRT_1440x900_60:
1895 return ("OUT_CRT_1440x900_60");
1897 case OUT_CRT_1440x1050_60:
1898 return ("OUT_CRT_1440x1050_60");
1900 case OUT_CRT_1600x900_60:
1901 return ("OUT_CRT_1600x900_60");
1903 case OUT_CRT_1600x1200_60:
1904 return ("OUT_CRT_1600x1200_60");
1906 case OUT_CRT_1920x1080_60:
1907 return ("OUT_CRT_1920x1080_60");
1914 case OUT_DVI_640x480_60:
1915 return ("OUT_DVI_640x480_60");
1916 case OUT_DVI_640x480_72:
1917 return ("OUT_DVI_640x480_72");
1919 case OUT_DVI_720x400_70:
1920 return ("OUT_DVI_720x400_70");
1922 case OUT_DVI_800x600_56:
1923 return ("OUT_DVI_800x600_56");
1924 case OUT_DVI_800x600_60:
1925 return ("OUT_DVI_800x600_60");
1926 case OUT_DVI_800x600_72:
1927 return ("OUT_DVI_800x600_72");
1928 case OUT_DVI_800x600_75:
1929 return ("OUT_DVI_800x600_75");
1931 case OUT_DVI_1024x768_60:
1932 return ("OUT_DVI_1024x768_60");
1933 case OUT_DVI_1024x768_70:
1934 return ("OUT_DVI_1024x768_70");
1935 case OUT_DVI_1024x768_75:
1936 return ("OUT_DVI_1024x768_75");
1938 case OUT_DVI_1152x864_60:
1939 return ("OUT_CRT_1152x864_60");
1941 case OUT_DVI_1280x720_60:
1942 return ("OUT_DVI_1280x720_60");
1944 case OUT_DVI_1280x800_60:
1945 return ("OUT_DVI_1280x800_60");
1947 case OUT_DVI_1280x960_60:
1948 return ("OUT_DVI_1280x960_60");
1950 case OUT_DVI_1280x1024_60:
1951 return ("OUT_DVI_1280x1024_60");
1952 case OUT_DVI_1280x1024_75:
1953 return ("OUT_DVI_1280x1024_75");
1955 case OUT_DVI_1360x768_60:
1956 return ("OUT_DVI_1360x768_60");
1958 case OUT_DVI_1366x768_60:
1959 return ("OUT_DVI_1366x768_60");
1961 case OUT_DVI_1400x1050_60:
1962 return ("OUT_DVI_1400x1050_60");
1963 case OUT_DVI_1400x1050_75:
1964 return ("OUT_DVI_1400x1050_75");
1966 case OUT_DVI_1440x900_60:
1967 return ("OUT_DVI_1440x900_60");
1969 case OUT_DVI_1440x1050_60:
1970 return ("OUT_DVI_1440x1050_60");
1972 case OUT_DVI_1600x900_60:
1973 return ("OUT_DVI_1600x900_60");
1975 case OUT_DVI_1600x1200_60:
1976 return ("OUT_DVI_1600x1200_60");
1978 case OUT_DVI_1680x1050_60:
1979 return ("OUT_DVI_1680x1050_60");
1981 case OUT_DVI_1920x1080_60:
1982 return ("OUT_DVI_1920x1080_60");