Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | /* |
2 | ||
3 | SiI8348 Linux Driver | |
4 | ||
5 | Copyright (C) 2013 Silicon Image, Inc. | |
6 | ||
7 | This program is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU General Public License as | |
9 | published by the Free Software Foundation version 2. | |
10 | This program is distributed AS-IS WITHOUT ANY WARRANTY of any | |
11 | kind, whether express or implied; INCLUDING without the implied warranty | |
12 | of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE or NON-INFRINGEMENT. See | |
13 | the GNU General Public License for more details at http://www.gnu.org/licenses/gpl-2.0.html. | |
14 | ||
15 | */ | |
16 | ||
17 | #include <linux/slab.h> | |
18 | #include <linux/hrtimer.h> | |
19 | #include <linux/semaphore.h> | |
20 | #include <linux/cdev.h> | |
21 | #include <linux/device.h> | |
22 | ||
23 | #include "sii_hal.h" | |
24 | #include "si_fw_macros.h" | |
25 | #include "si_mhl_defs.h" | |
26 | #include "si_infoframe.h" | |
27 | #include "si_edid.h" | |
28 | #include "si_mhl2_edid_3d_api.h" | |
29 | #include "si_8348_internal_api.h" | |
30 | #include "si_mhl_tx_hw_drv_api.h" | |
31 | #ifdef MEDIA_DATA_TUNNEL_SUPPORT | |
32 | #include "si_mdt_inputdev.h" | |
33 | #endif | |
34 | #include "mhl_linux_tx.h" | |
35 | #include "platform.h" | |
36 | #include "hdmi_drv.h" | |
37 | #include "si_timing_defs.h" | |
38 | ||
39 | #define SET_3D_FLAG(context,x) \ | |
40 | { \ | |
41 | context->parse_data.flags.x = 1; \ | |
42 | MHL_TX_EDID_INFO(context->dev_context, \ | |
43 | "set %s\n",#x); \ | |
44 | } | |
45 | #define CLR_3D_FLAG(context,x) \ | |
46 | { \ | |
47 | context->parse_data.flags.x = 0; \ | |
48 | MHL_TX_EDID_INFO(context->dev_context, \ | |
49 | "clr %s\n",#x); \ | |
50 | } | |
51 | #define TEST_3D_FLAG(context,x) (context->parse_data.flags.x) | |
52 | ||
53 | typedef struct _timing_mode_from_data_sheet_t | |
54 | { | |
55 | uint16_t h_total; | |
56 | uint16_t v_total; | |
57 | uint32_t pixel_clock; | |
58 | struct | |
59 | { | |
60 | uint8_t interlaced:1; | |
61 | uint8_t reserved:7; | |
62 | }flags; | |
63 | char *description; | |
64 | }timing_mode_from_data_sheet_t,*Ptiming_mode_from_data_sheet_t; | |
65 | ||
66 | ||
67 | timing_mode_from_data_sheet_t timing_modes_from_data_sheet[]= | |
68 | { | |
69 | { 800, 525, 25175000,{0,0},"VGA"} | |
70 | ,{1088, 517, 33750000,{0,0},"WVGA"} | |
71 | ,{1056, 628, 40000000,{0,0},"SVGA"} | |
72 | ,{1344, 806, 65000000,{0,0},"XGA"} | |
73 | ,{1716, 262, 27000000,{1,0},"480i"}/* DS has VTOTAL for progressive */ | |
74 | ,{1728, 312, 27000000,{1,0},"576i"}/* DS has VTOTAL for progressive */ | |
75 | ,{ 858, 525, 27000000,{0,0},"480p"} | |
76 | ,{ 864, 625, 27000000,{0,0},"576p"} | |
77 | ,{1650, 750, 74250000,{0,0},"720p"} | |
78 | ,{2200, 562, 74250000,{1,0},"1080i"}/* DS has VTOTAL for progressive */ | |
79 | ,{2750,1125, 74250000,{0,0},"1080p,24/30"} | |
80 | ,{2640,1125,148500000,{0,0},"1080p50"} | |
81 | ,{2200,1125,148500000,{0,0},"1080p60"} | |
82 | }; | |
83 | ||
84 | void display_timing_enumeration_begin(edid_3d_data_p mhl_edid_3d_data) | |
85 | { | |
86 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
87 | "Begin MHL display timing enumeration\n"); | |
88 | } | |
89 | ||
90 | void display_timing_enumeration_callback(edid_3d_data_p mhl_edid_3d_data, | |
91 | uint16_t columns, uint16_t rows, | |
92 | uint8_t bits_per_pixel, | |
93 | uint32_t vertical_refresh_rate_in_milliHz, | |
94 | MHL2_video_descriptor_t mhl2_video_descriptor) | |
95 | { | |
96 | ||
97 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
98 | "%4d x %4d, %2d bpp at %u Hz 3D - %16s %16s %16s\n\n" | |
99 | ,columns | |
100 | ,rows | |
101 | ,(uint16_t)bits_per_pixel | |
102 | ,vertical_refresh_rate_in_milliHz | |
103 | ,mhl2_video_descriptor.left_right ?"Left/Right" :"" | |
104 | ,mhl2_video_descriptor.top_bottom ?"Top/Bottom" :"" | |
105 | ,mhl2_video_descriptor.frame_sequential?"Frame Sequential":"" | |
106 | ); | |
107 | } | |
108 | ||
109 | void display_timing_enumeration_end(edid_3d_data_p mhl_edid_3d_data) | |
110 | { | |
111 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
112 | "End MHL display timing enumeration\n"); | |
113 | } | |
114 | ||
115 | uint32_t si_mhl_tx_find_timings_from_totals( edid_3d_data_p mhl_edid_3d_data) | |
116 | { | |
117 | uint32_t ret_val=0; | |
118 | uint8_t i; | |
119 | uint16_t h_total, v_total; | |
120 | /* Measure the HTOTAL and VTOTAL and look them up in a table */ | |
121 | h_total = si_mhl_tx_drv_get_incoming_horizontal_total(mhl_edid_3d_data->drv_context); | |
122 | v_total = si_mhl_tx_drv_get_incoming_vertical_total(mhl_edid_3d_data->drv_context); | |
123 | for (i = 0 ; i < sizeof(timing_modes_from_data_sheet)/sizeof(timing_modes_from_data_sheet[0]); ++i) { | |
124 | if (timing_modes_from_data_sheet[i].h_total == h_total) { | |
125 | if (timing_modes_from_data_sheet[i].v_total == v_total) { | |
126 | ret_val = timing_modes_from_data_sheet[i].pixel_clock; | |
127 | MHL_TX_DBG_ERR(,"vic was 0, %s\n" | |
128 | ,timing_modes_from_data_sheet[i].description); | |
129 | return ret_val; | |
130 | } | |
131 | } | |
132 | } | |
133 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context, | |
134 | "VIC was zero!!! h_total: 0x%04x v_total:0x%04x\n", | |
135 | h_total,v_total); | |
136 | return ret_val; | |
137 | } | |
138 | ||
139 | PLACE_IN_CODE_SEG char *psz_space ="n/a"; | |
140 | PLACE_IN_CODE_SEG char *psz_frame_sequential ="FS "; | |
141 | PLACE_IN_CODE_SEG char *psz_top_bottom ="TB "; | |
142 | PLACE_IN_CODE_SEG char *psz_left_right ="LR "; | |
143 | ||
144 | /* VIC is a place holder, and not actually stored */ | |
145 | #define CEA_861_D_VIC_info_entry(VIC,columns,rows,HBlank,VBLank,FieldRate,image_aspect_ratio,scanmode,PixelAspectRatio,flags,clocksPerPelShift,AdditionalVBlank) \ | |
146 | {columns,rows,HBlank,VBLank,FieldRate,{image_aspect_ratio,scanmode,PixelAspectRatio,flags,clocksPerPelShift,AdditionalVBlank}} | |
147 | VIC_info_t VIC_info[]= | |
148 | { | |
149 | CEA_861_D_VIC_info_entry( 0, 0, 0, 0, 0, 0000 ,iar_16_to_10 ,vsm_progressive,par_1_to_1 ,vif_single_frame_rate,0,0) | |
150 | ,CEA_861_D_VIC_info_entry( 1, 640, 480,160,45, 60000 ,iar_4_to_3 ,vsm_progressive,par_1_to_1 ,vif_dual_frame_rate ,0,0) | |
151 | ,CEA_861_D_VIC_info_entry( 2, 720, 480,138,45, 60000 ,iar_4_to_3 ,vsm_progressive,par_8_to_9 ,vif_dual_frame_rate ,0,0) | |
152 | ,CEA_861_D_VIC_info_entry( 3, 720, 480,138,45, 60000 ,iar_16_to_9 ,vsm_progressive,par_32_to_27 ,vif_dual_frame_rate ,0,0) | |
153 | ,CEA_861_D_VIC_info_entry( 4,1280, 720,370,30, 60000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_dual_frame_rate ,0,0) | |
154 | ,CEA_861_D_VIC_info_entry( 5,1920,1080,280,22, 60000 ,iar_16_to_9 ,vsm_interlaced ,par_1_to_1 ,vif_dual_frame_rate ,0,1) | |
155 | ,CEA_861_D_VIC_info_entry( 6, 720, 480,276,22, 60000 ,iar_4_to_3 ,vsm_interlaced ,par_8_to_9 ,vif_dual_frame_rate ,1,1) | |
156 | ,CEA_861_D_VIC_info_entry( 7, 720, 480,276,22, 60000 ,iar_16_to_9 ,vsm_interlaced ,par_32_to_27 ,vif_dual_frame_rate ,1,1) | |
157 | ,CEA_861_D_VIC_info_entry( 8, 720, 240,276,22, 60000 ,iar_4_to_3 ,vsm_progressive,par_4_to_9 ,vif_dual_frame_rate ,1,1) | |
158 | ,CEA_861_D_VIC_info_entry( 9, 720, 428,276,22, 60000 ,iar_16_to_9 ,vsm_progressive,par_16_to_27 ,vif_dual_frame_rate ,1,1) | |
159 | ,CEA_861_D_VIC_info_entry(10,2880, 480,552,22, 60000 ,iar_4_to_3 ,vsm_interlaced ,par_2_to_9_20_to_9 ,vif_dual_frame_rate ,0,1) | |
160 | ,CEA_861_D_VIC_info_entry(11,2880, 480,552,22, 60000 ,iar_16_to_9 ,vsm_interlaced ,par_8_to_27_80_to_27 ,vif_dual_frame_rate ,0,1) | |
161 | ,CEA_861_D_VIC_info_entry(12,2880, 240,552,22, 60000 ,iar_4_to_3 ,vsm_progressive,par_1_to_9_10_to_9 ,vif_dual_frame_rate ,0,1) | |
162 | ,CEA_861_D_VIC_info_entry(13,2880, 240,552,22, 60000 ,iar_16_to_9 ,vsm_progressive,par_4_to_27_40_to_27 ,vif_dual_frame_rate ,0,1) | |
163 | ,CEA_861_D_VIC_info_entry(14,1440, 480,276,45, 60000 ,iar_4_to_3 ,vsm_progressive,par_4_to_9 ,vif_dual_frame_rate ,0,0) | |
164 | ,CEA_861_D_VIC_info_entry(15,1440, 480,276,45, 60000 ,iar_16_to_9 ,vsm_progressive,par_16_to_27 ,vif_dual_frame_rate ,0,0) | |
165 | ,CEA_861_D_VIC_info_entry(16,1920,1080,280,45, 60000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_dual_frame_rate ,0,0) | |
166 | ,CEA_861_D_VIC_info_entry(17, 720, 576,144,49, 50000 ,iar_4_to_3 ,vsm_progressive,par_16_to_15 ,vif_single_frame_rate,0,0) | |
167 | ,CEA_861_D_VIC_info_entry(18, 720, 576,144,49, 50000 ,iar_16_to_9 ,vsm_progressive,par_64_to_45 ,vif_single_frame_rate,0,0) | |
168 | ,CEA_861_D_VIC_info_entry(19,1280, 720,700,30, 50000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_single_frame_rate,0,0) | |
169 | ,CEA_861_D_VIC_info_entry(20,1920,1080,720,22, 50000 ,iar_16_to_9 ,vsm_interlaced ,par_1_to_1 ,vif_single_frame_rate,0,1) | |
170 | ,CEA_861_D_VIC_info_entry(21, 720, 576,288,24, 50000 ,iar_4_to_3 ,vsm_interlaced ,par_16_to_15 ,vif_single_frame_rate,1,1) /* (1440) */ | |
171 | ,CEA_861_D_VIC_info_entry(22, 720, 576,288,24, 50000 ,iar_16_to_9 ,vsm_interlaced ,par_64_to_45 ,vif_single_frame_rate,1,1) /* (1440) */ | |
172 | ,CEA_861_D_VIC_info_entry(23, 720, 288,288,24, 50000 ,iar_4_to_3 ,vsm_progressive,par_8_to_15 ,vif_single_frame_rate,1,2) /* (1440) */ | |
173 | ,CEA_861_D_VIC_info_entry(24, 720, 288,288,24, 50000 ,iar_16_to_9 ,vsm_progressive,par_32_to_45 ,vif_single_frame_rate,1,2) /* (1440) */ | |
174 | ,CEA_861_D_VIC_info_entry(25,2880, 576,576,24, 50000 ,iar_4_to_3 ,vsm_interlaced ,par_2_to_15_20_to_15 ,vif_single_frame_rate,0,1) | |
175 | ,CEA_861_D_VIC_info_entry(26,2880, 576,576,24, 50000 ,iar_16_to_9 ,vsm_interlaced ,par_16_to_45_160_to_45 ,vif_single_frame_rate,0,1) | |
176 | ,CEA_861_D_VIC_info_entry(27,2880, 288,576,24, 50000 ,iar_4_to_3 ,vsm_progressive,par_1_to_15_10_to_15 ,vif_single_frame_rate,0,2) | |
177 | ,CEA_861_D_VIC_info_entry(28,2880, 288,576,24, 50000 ,iar_16_to_9 ,vsm_progressive,par_8_to_45_80_to_45 ,vif_single_frame_rate,0,2) | |
178 | ,CEA_861_D_VIC_info_entry(29,1440, 576,288,49, 50000 ,iar_4_to_3 ,vsm_progressive,par_8_to_15 ,vif_single_frame_rate,0,0) | |
179 | ,CEA_861_D_VIC_info_entry(30,1440, 576,288,49, 50000 ,iar_16_to_9 ,vsm_progressive,par_32_to_45 ,vif_single_frame_rate,0,0) | |
180 | ,CEA_861_D_VIC_info_entry(31,1920,1080,720,45, 50000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_single_frame_rate,0,0) | |
181 | ,CEA_861_D_VIC_info_entry(32,1920,1080,830,45, 24000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_dual_frame_rate ,0,0) | |
182 | ,CEA_861_D_VIC_info_entry(33,1920,1080,720,45, 25000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_single_frame_rate,0,0) | |
183 | ,CEA_861_D_VIC_info_entry(34,1920,1080,280,45, 30000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_dual_frame_rate ,0,0) | |
184 | ,CEA_861_D_VIC_info_entry(35,2880, 480,552,45, 60000 ,iar_4_to_3 ,vsm_progressive,par_2_to_9 ,vif_dual_frame_rate ,0,0) | |
185 | ,CEA_861_D_VIC_info_entry(36,2880, 480,552,45, 60000 ,iar_16_to_9 ,vsm_progressive,par_8_to_27 ,vif_dual_frame_rate ,0,0) | |
186 | ,CEA_861_D_VIC_info_entry(37,2880, 576,576,49, 50000 ,iar_4_to_3 ,vsm_progressive,par_4_to_15 ,vif_single_frame_rate,0,0) | |
187 | ,CEA_861_D_VIC_info_entry(38,2880, 576,576,49, 50000 ,iar_16_to_9 ,vsm_progressive,par_16_to_45 ,vif_single_frame_rate,0,0) | |
188 | ,CEA_861_D_VIC_info_entry(39,1920,1080,384,85, 50000 ,iar_16_to_9 ,vsm_interlaced ,par_1_to_1 ,vif_single_frame_rate,0,0) /*1250,total*/ | |
189 | ,CEA_861_D_VIC_info_entry(40,1920,1080,720,22,100000 ,iar_16_to_9 ,vsm_interlaced ,par_1_to_1 ,vif_single_frame_rate,0,1) | |
190 | ,CEA_861_D_VIC_info_entry(41,1280, 720,700,30,100000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_single_frame_rate,0,0) | |
191 | ,CEA_861_D_VIC_info_entry(42, 720, 576,144,49,100000 ,iar_4_to_3 ,vsm_progressive,par_16_to_15 ,vif_single_frame_rate,0,0) | |
192 | ,CEA_861_D_VIC_info_entry(43, 720, 576,144,49,100000 ,iar_16_to_9 ,vsm_progressive,par_64_to_45 ,vif_single_frame_rate,0,0) | |
193 | ,CEA_861_D_VIC_info_entry(44, 720, 576,288,24,100000 ,iar_4_to_3 ,vsm_interlaced ,par_16_to_15 ,vif_single_frame_rate,1,1) /* (1440) */ | |
194 | ,CEA_861_D_VIC_info_entry(45, 720, 576,288,24,100000 ,iar_16_to_9 ,vsm_interlaced ,par_64_to_45 ,vif_single_frame_rate,1,1) /* (1440) */ | |
195 | ,CEA_861_D_VIC_info_entry(46,1920,1080,280,22,120000 ,iar_16_to_9 ,vsm_interlaced ,par_1_to_1 ,vif_dual_frame_rate ,0,1) | |
196 | ,CEA_861_D_VIC_info_entry(47,1280, 720,370,30,120000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_dual_frame_rate ,0,0) | |
197 | ,CEA_861_D_VIC_info_entry(48, 720, 480,138,45,120000 ,iar_4_to_3 ,vsm_progressive,par_8_to_9 ,vif_dual_frame_rate ,0,0) | |
198 | ,CEA_861_D_VIC_info_entry(49, 720, 480,138,45,120000 ,iar_16_to_9 ,vsm_progressive,par_32_to_27 ,vif_dual_frame_rate ,0,0) | |
199 | ,CEA_861_D_VIC_info_entry(50, 720, 480,276,22,120000 ,iar_4_to_3 ,vsm_interlaced ,par_8_to_9 ,vif_dual_frame_rate ,1,1) /* (1440) */ | |
200 | ,CEA_861_D_VIC_info_entry(51, 720, 480,276,22,120000 ,iar_16_to_9 ,vsm_interlaced ,par_32_to_27 ,vif_dual_frame_rate ,1,1) /* (1440) */ | |
201 | ,CEA_861_D_VIC_info_entry(52, 720, 576,144,49,200000 ,iar_4_to_3 ,vsm_progressive,par_16_to_15 ,vif_single_frame_rate,0,0) | |
202 | ,CEA_861_D_VIC_info_entry(53, 720, 576,144,49,200000 ,iar_16_to_9 ,vsm_progressive,par_64_to_45 ,vif_single_frame_rate,0,0) | |
203 | ,CEA_861_D_VIC_info_entry(54, 720, 576,288,24,200000 ,iar_4_to_3 ,vsm_interlaced ,par_16_to_15 ,vif_single_frame_rate,1,1) /* (1440) */ | |
204 | ,CEA_861_D_VIC_info_entry(55, 720, 576,288,24,200000 ,iar_16_to_9 ,vsm_interlaced ,par_64_to_45 ,vif_single_frame_rate,1,1) /* (1440) */ | |
205 | ,CEA_861_D_VIC_info_entry(56, 720, 480,138,45,240000 ,iar_4_to_3 ,vsm_progressive,par_8_to_9 ,vif_dual_frame_rate ,0,0) | |
206 | ,CEA_861_D_VIC_info_entry(57, 720, 480,138,45,240000 ,iar_16_to_9 ,vsm_progressive,par_32_to_27 ,vif_dual_frame_rate ,0,0) | |
207 | ,CEA_861_D_VIC_info_entry(58, 720, 480,276,22,240000 ,iar_4_to_3 ,vsm_interlaced ,par_8_to_9 ,vif_dual_frame_rate ,1,1) /* (1440) */ | |
208 | ,CEA_861_D_VIC_info_entry(59, 720, 480,276,22,240000 ,iar_16_to_9 ,vsm_interlaced ,par_32_to_27 ,vif_dual_frame_rate ,1,1) /* (1440) */ | |
209 | ,CEA_861_D_VIC_info_entry(60,1280, 720,370,30, 24000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_dual_frame_rate ,0,0) | |
210 | ,CEA_861_D_VIC_info_entry(61,1280, 720,370,30, 25000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_single_frame_rate,0,0) | |
211 | ,CEA_861_D_VIC_info_entry(62,1280, 720,370,30, 30000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_dual_frame_rate ,0,0) | |
212 | ,CEA_861_D_VIC_info_entry(63,1920,1080,280,45,120000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_dual_frame_rate ,0,0) | |
213 | ,CEA_861_D_VIC_info_entry(64,1920,1080,280,45,100000 ,iar_16_to_9 ,vsm_progressive,par_1_to_1 ,vif_single_frame_rate,0,0) | |
214 | ||
215 | }; | |
216 | ||
217 | uint32_t calculate_pixel_clock(edid_3d_data_p mhl_edid_3d_data, | |
218 | uint16_t columns, uint16_t rows, | |
219 | uint32_t vertical_sync_frequency_in_milliHz, | |
220 | uint8_t VIC) | |
221 | { | |
222 | uint32_t pixel_clock_frequency; | |
223 | uint32_t vertical_sync_period_in_microseconds; | |
224 | uint32_t vertical_active_period_in_microseconds; | |
225 | uint32_t vertical_blank_period_in_microseconds; | |
226 | uint32_t horizontal_sync_frequency_in_hundredths_of_KHz; | |
227 | uint32_t horizontal_sync_period_in_nanoseconds; | |
228 | uint32_t horizontal_active_period_in_nanoseconds; | |
229 | uint32_t horizontal_blank_period_in_nanoseconds; | |
230 | ||
231 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
232 | "vertical_sync_frequency_in_milliHz: %u\n",vertical_sync_frequency_in_milliHz ); | |
233 | ||
234 | vertical_sync_period_in_microseconds = 1000000000/vertical_sync_frequency_in_milliHz; | |
235 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
236 | "vertical_sync_frequency_in_milliHz:%u vertical_sync_period_in_microseconds: %u\n",vertical_sync_frequency_in_milliHz,vertical_sync_period_in_microseconds); | |
237 | ||
238 | if (0 == VIC) { | |
239 | /* rule of thumb: */ | |
240 | vertical_active_period_in_microseconds = (vertical_sync_period_in_microseconds * 8) / 10; | |
241 | ||
242 | } else { | |
243 | uint16_t v_total_in_lines; | |
244 | uint16_t v_blank_in_lines; | |
245 | ||
246 | if (vsm_interlaced == VIC_info[VIC].fields.interlaced) { | |
247 | /* fix up these two values */ | |
248 | vertical_sync_frequency_in_milliHz /= 2; | |
249 | vertical_sync_period_in_microseconds *= 2; | |
250 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
251 | "interlaced vertical_sync_frequency_in_milliHz:%u" | |
252 | " vertical_sync_period_in_microseconds: %u\n" | |
253 | ,vertical_sync_frequency_in_milliHz | |
254 | ,vertical_sync_period_in_microseconds); | |
255 | ||
256 | /* proceed with calculations */ | |
257 | v_blank_in_lines = 2 * VIC_info[VIC].v_blank_in_pixels + VIC_info[VIC].fields.field2_v_blank; | |
258 | ||
259 | } else { | |
260 | /* when multiple vertical blanking values present, | |
261 | allow for higher clocks by calculating maximum possible | |
262 | */ | |
263 | v_blank_in_lines = VIC_info[VIC].v_blank_in_pixels + VIC_info[VIC].fields.field2_v_blank; | |
264 | } | |
265 | v_total_in_lines = VIC_info[VIC].rows +v_blank_in_lines ; | |
266 | vertical_active_period_in_microseconds = (vertical_sync_period_in_microseconds * VIC_info[VIC].rows) / v_total_in_lines; | |
267 | ||
268 | } | |
269 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
270 | "vertical_active_period_in_microseconds: %u\n",vertical_active_period_in_microseconds); | |
271 | ||
272 | /* rigorous calculation: */ | |
273 | vertical_blank_period_in_microseconds = vertical_sync_period_in_microseconds - vertical_active_period_in_microseconds; | |
274 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
275 | "vertical_blank_period_in_microseconds: %u\n",vertical_blank_period_in_microseconds); | |
276 | ||
277 | horizontal_sync_frequency_in_hundredths_of_KHz = rows * 100000; | |
278 | horizontal_sync_frequency_in_hundredths_of_KHz /= vertical_active_period_in_microseconds; | |
279 | ||
280 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
281 | "horizontal_sync_frequency_in_hundredths_of_KHz: %u\n",horizontal_sync_frequency_in_hundredths_of_KHz); | |
282 | ||
283 | horizontal_sync_period_in_nanoseconds = 100000000 / horizontal_sync_frequency_in_hundredths_of_KHz; | |
284 | ||
285 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
286 | "horizontal_sync_period_in_nanoseconds: %u\n",horizontal_sync_period_in_nanoseconds); | |
287 | ||
288 | if (0 == VIC) { | |
289 | /* rule of thumb: */ | |
290 | horizontal_active_period_in_nanoseconds = (horizontal_sync_period_in_nanoseconds * 8) / 10; | |
291 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
292 | "horizontal_active_period_in_nanoseconds: %u\n",horizontal_active_period_in_nanoseconds); | |
293 | } else { | |
294 | uint16_t h_total_in_pixels; | |
295 | uint16_t h_clocks; | |
296 | h_clocks = VIC_info[VIC].columns << VIC_info[VIC].fields.clocks_per_pixel_shift_count; | |
297 | h_total_in_pixels = h_clocks + VIC_info[VIC].h_blank_in_pixels; | |
298 | horizontal_active_period_in_nanoseconds = (horizontal_sync_period_in_nanoseconds * h_clocks) / h_total_in_pixels; | |
299 | } | |
300 | /* rigorous calculation: */ | |
301 | horizontal_blank_period_in_nanoseconds = horizontal_sync_period_in_nanoseconds - horizontal_active_period_in_nanoseconds; | |
302 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
303 | "horizontal_blank_period_in_nanoseconds: %u\n",horizontal_blank_period_in_nanoseconds); | |
304 | ||
305 | pixel_clock_frequency = columns * (1000000000/ horizontal_active_period_in_nanoseconds); | |
306 | ||
307 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
308 | "pixel_clock_frequency: %u\n",pixel_clock_frequency); | |
309 | ||
310 | return pixel_clock_frequency; | |
311 | } | |
312 | ||
313 | uint8_t qualify_pixel_clock_for_mhl(edid_3d_data_p mhl_edid_3d_data, uint32_t pixel_clock_frequency, uint8_t bits_per_pixel) | |
314 | { | |
315 | uint32_t pixel_clock_frequency_div_8; | |
316 | uint32_t link_clock_frequency; | |
317 | uint32_t max_link_clock_frequency; | |
318 | uint8_t ret_val; | |
319 | ||
320 | pixel_clock_frequency_div_8 = pixel_clock_frequency / 8; | |
321 | ||
322 | link_clock_frequency = pixel_clock_frequency_div_8 * (uint32_t)bits_per_pixel; | |
323 | ||
324 | if ( si_peer_supports_packed_pixel(mhl_edid_3d_data->dev_context) ) { | |
325 | max_link_clock_frequency = 300000000; | |
326 | } else { | |
327 | max_link_clock_frequency = 225000000; | |
328 | } | |
329 | ||
330 | if (link_clock_frequency < max_link_clock_frequency) { | |
331 | ret_val = 1; | |
332 | } else { | |
333 | ret_val = 0; | |
334 | } | |
335 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
336 | "Link clock:%u Hz %12s for MHL at %d bpp (max: %u Hz)\n" | |
337 | ,link_clock_frequency | |
338 | ,ret_val?"valid":"unattainable" | |
339 | ,(uint16_t)bits_per_pixel | |
340 | ,max_link_clock_frequency); | |
341 | return ret_val; | |
342 | } | |
343 | ||
344 | /* | |
345 | is_MHL_timing_mode | |
346 | ||
347 | MHL has a maximum link clock of 75Mhz. | |
348 | For now, we use a rule of thumb regarding | |
349 | blanking intervals to calculate a pixel clock, | |
350 | then we convert it to a link clock and compare to 75MHz | |
351 | ||
352 | */ | |
353 | ||
354 | ||
355 | static uint8_t is_MHL_timing_mode(edid_3d_data_p mhl_edid_3d_data, | |
356 | uint16_t columns, uint16_t rows, | |
357 | uint32_t vertical_sync_frequency_in_milliHz, | |
358 | PMHL2_video_descriptor_t p_MHL2_video_descriptor_parm, | |
359 | uint8_t VIC) | |
360 | { | |
361 | uint32_t pixel_clock_frequency; | |
362 | uint8_t ret_val = 0; | |
363 | MHL2_video_descriptor_t dummy; | |
364 | PMHL2_video_descriptor_t pMHL2_video_descriptor = p_MHL2_video_descriptor_parm; | |
365 | if (NULL == p_MHL2_video_descriptor_parm) { | |
366 | dummy.frame_sequential=0; | |
367 | dummy.left_right=0; | |
368 | dummy.top_bottom=0; | |
369 | dummy.reserved_high=0; | |
370 | dummy.reserved_low=0; | |
371 | pMHL2_video_descriptor=&dummy; | |
372 | } | |
373 | ||
374 | pixel_clock_frequency = calculate_pixel_clock(mhl_edid_3d_data, columns, rows, | |
375 | vertical_sync_frequency_in_milliHz, VIC); | |
376 | ||
377 | if (qualify_pixel_clock_for_mhl(mhl_edid_3d_data,pixel_clock_frequency, 24)) { | |
378 | display_timing_enumeration_callback(mhl_edid_3d_data, columns, rows, | |
379 | 24, vertical_sync_frequency_in_milliHz,*pMHL2_video_descriptor); | |
380 | ret_val = 1; | |
381 | } | |
382 | if (qualify_pixel_clock_for_mhl(mhl_edid_3d_data,pixel_clock_frequency, 16)) { | |
383 | display_timing_enumeration_callback(mhl_edid_3d_data, columns, rows, | |
384 | 16, vertical_sync_frequency_in_milliHz,*pMHL2_video_descriptor); | |
385 | ret_val = 1; | |
386 | } | |
387 | ||
388 | return ret_val; | |
389 | } | |
390 | #ifdef PRUNE_EDID | |
391 | void si_mhl_tx_prune_dtd_list(edid_3d_data_p mhl_edid_3d_data, | |
392 | P_18_byte_descriptor_u p_desc,uint8_t limit) | |
393 | { | |
394 | uint8_t i; | |
395 | uint8_t number_that_we_pruned = 0; | |
396 | #define DTD_Demoresolution | |
397 | #ifdef DTD_Demoresolution | |
398 | const uint8_t DemodetailTiming [18]={0x01, 0x1D, 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20, 0x6E, 0x28, 0x55, 0x00, 0xC4, 0x8E, 0x21, 0x00, 0x00, 0x1E}; | |
399 | //extern void *memcpy(void *dest, const void *src, uint8_t n); | |
400 | #endif | |
401 | ||
402 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"limit: %d\n",(uint16_t)limit); | |
403 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context," si_peer_supports_packed_pixel(mhl_edid_3d_data->dev_context) :0x%02x\n", (uint16_t) si_peer_supports_packed_pixel(mhl_edid_3d_data->dev_context) ); | |
404 | if (limit&&(! si_peer_supports_packed_pixel(mhl_edid_3d_data->dev_context) )) | |
405 | { | |
406 | for (i = 0 ; i < limit -1 ; ++i) | |
407 | { | |
408 | TX_PRUNE_PRINT(("limit4444: %d,i=%d,(p_desc->dtd.pixel_clock_high):0x%02x, si_peer_supports_packed_pixel(mhl_edid_3d_data->dev_context) :0x%02x\n", | |
409 | (uint16_t)limit,i,(uint16_t)(p_desc->dtd.pixel_clock_high),(uint16_t) si_peer_supports_packed_pixel(mhl_edid_3d_data->dev_context) )); | |
410 | //DumpEdidBlock(pEdidBlock0,sizeof(*pEdidBlock0)); | |
411 | ||
412 | if ((0 != p_desc->dtd.pixel_clock_low) || (0 != p_desc->dtd.pixel_clock_high)) | |
413 | { | |
414 | if ((0 == p_desc->dtd.horz_active_7_0)&&(0 == p_desc->dtd.horz_active_blanking_high.horz_blanking_11_8)) | |
415 | { | |
416 | P_18_byte_descriptor_u pHolder=p_desc,pNextDesc = p_desc+1; | |
417 | uint8_t j; | |
418 | number_that_we_pruned++; | |
419 | for (j = i+1; j < limit ; ++j) | |
420 | {TX_PRUNE_PRINT(("limit555555: %d, i=%d, j=%d\n",(uint16_t)limit,i,j)); | |
421 | // move the rest of the entries one by one | |
422 | *p_desc++ = *pNextDesc++; | |
423 | } | |
424 | // re-consider the new occupant of the i'th entry on the next iteration | |
425 | //i--; | |
426 | p_desc=pHolder; | |
427 | } | |
428 | } | |
429 | if ((p_desc->dtd.pixel_clock_high>0x20)&&(! si_peer_supports_packed_pixel(mhl_edid_3d_data->dev_context) )) | |
430 | #ifndef DTD_Demoresolution | |
431 | { | |
432 | P_18_byte_descriptor_u pNextDesc = p_desc+1;//pHolder=p_desc, | |
433 | uint8_t j; | |
434 | number_that_we_pruned++; | |
435 | for (j = i+1; j < limit ; ++j) | |
436 | { | |
437 | //TX_PRUNE_PRINT(("limit6666666: %d,*p_desc:0x%02x\n",(uint16_t)limit,*p_desc)); | |
438 | // move the rest of the entries one by one | |
439 | *p_desc++ = *pNextDesc++; | |
440 | } | |
441 | // re-consider the new occupant of the i'th entry on the next iteration | |
442 | i--; | |
443 | //p_desc=pHolder; | |
444 | } | |
445 | #else | |
446 | { | |
447 | //TX_PRUNE_PRINT(("limit6666666: %d,*p_desc:0x%02x\n",(uint16_t)limit,*p_desc)); | |
448 | memcpy(p_desc, &DemodetailTiming[0],18); | |
449 | } | |
450 | #endif | |
451 | ||
452 | } | |
453 | TX_PRUNE_PRINT(("limit2: %d\n",(uint16_t)limit)); | |
454 | // at this point "i" holds the value of mhlTxConfig.svdDataBlockLength-1 | |
455 | // and p_desc points to the last entry in the list | |
456 | for (;number_that_we_pruned >0;--number_that_we_pruned,--p_desc) | |
457 | { | |
458 | uint8_t *pu8Temp = (uint8_t *)p_desc; | |
459 | uint8_t size; | |
460 | ||
461 | for (size = sizeof(*p_desc); size > 0; --size) | |
462 | {TX_PRUNE_PRINT(("*pu8Temp: %d\n",(uint16_t)*pu8Temp)); | |
463 | *pu8Temp++ = 0; | |
464 | } | |
465 | } | |
466 | TX_PRUNE_PRINT(("limit3: %d\n",(uint16_t)limit)); | |
467 | } | |
468 | } | |
469 | #endif | |
470 | ||
471 | ||
472 | /* | |
473 | ||
474 | FUNCTION : si_mhl_tx_parse_detailed_timing_descriptor() | |
475 | ||
476 | PURPOSE : Parse the detailed timing section of EDID Block 0 and | |
477 | print their decoded meaning to the screen. | |
478 | ||
479 | INPUT PARAMS : Pointer to the array where the data read from EDID | |
480 | Block0 is stored. | |
481 | ||
482 | Offset to the beginning of the Detailed Timing Descriptor | |
483 | data. | |
484 | ||
485 | Block indicator to distinguish between block #0 and blocks | |
486 | #2, #3 | |
487 | ||
488 | OUTPUT PARAMS: None | |
489 | ||
490 | GLOBALS USED : None | |
491 | ||
492 | RETURNS : true if valid timing, false if not | |
493 | ||
494 | */ | |
495 | ||
496 | static bool si_mhl_tx_parse_detailed_timing_descriptor( | |
497 | edid_3d_data_p mhl_edid_3d_data, | |
498 | P_18_byte_descriptor_u p_desc , | |
499 | uint8_t Block, uint8_t *p_is_timing, | |
500 | PMHL2_video_descriptor_t pMHL2_video_descriptor) | |
501 | { | |
502 | uint8_t tmp_byte; | |
503 | uint8_t i; | |
504 | uint16_t tmp_word; | |
505 | ||
506 | *p_is_timing = 0; | |
507 | tmp_word = p_desc->dtd.pixel_clock_low + 256 * p_desc->dtd.pixel_clock_high; | |
508 | /* 18 byte partition is used as either for Monitor Name or for Monitor Range Limits or it is unused */ | |
509 | if (tmp_word == 0x00) { | |
510 | /* if called from Block #0 and first 2 bytes are 0 => either Monitor Name or for Monitor Range Limits */ | |
511 | if (Block == EDID_BLOCK_0) { | |
512 | if (0xFC == p_desc->name.data_type_tag) { | |
513 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
514 | "Monitor Name: "); | |
515 | ||
516 | for (i = 0; i < 13; i++) { | |
517 | // TODO: FD, TBI | |
518 | printk("%c", p_desc->name.ascii_name[i]); /* Display monitor name */ | |
519 | #if 0 | |
520 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
521 | "%c", p_desc->name.ascii_name[i]); /* Display monitor name */ | |
522 | #endif | |
523 | } | |
524 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, "\n"); | |
525 | } else if (0xFD == p_desc->name.data_type_tag) { | |
526 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
527 | "Monitor Range Limits:\n\n"); | |
528 | ||
529 | //i = 0; | |
530 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
531 | "Min Vertical Rate in Hz: %d\n", | |
532 | (int)p_desc->range_limits.min_vertical_rate_in_Hz); | |
533 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
534 | "Max Vertical Rate in Hz: %d\n", | |
535 | (int)p_desc->range_limits.max_vertical_rate_in_Hz); | |
536 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
537 | "Min Horizontal Rate in KHz: %d\n", | |
538 | (int)p_desc->range_limits.min_horizontal_rate_in_KHz); | |
539 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
540 | "Max Horizontal Rate in KHz: %d\n", | |
541 | (int)p_desc->range_limits.max_horizontal_rate_in_KHz); | |
542 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
543 | "Max Supported pixel clock rate in MHz/10: %d\n", | |
544 | (int)p_desc->range_limits.max_pixel_clock_in_MHz_div_10); | |
545 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
546 | "Tag for secondary timing formula (00h=not used): %d\n", | |
547 | (int)p_desc->range_limits.tag_secondary_formula); | |
548 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"\n"); | |
549 | } | |
550 | } else if (Block == EDID_BLOCK_2_3) { | |
551 | /* if called from block #2 or #3 and first 2 bytes are 0x00 (padding) then this | |
552 | descriptor partition is not used and parsing should be stopped | |
553 | */ | |
554 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
555 | "No More Detailed descriptors in this block\n"); | |
556 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, "\n"); | |
557 | return false; | |
558 | } | |
559 | } else { | |
560 | /* first 2 bytes are not 0 => this is a detailed timing descriptor from either block */ | |
561 | uint32_t pixel_clock_frequency; | |
562 | uint16_t columns,rows,vertical_sync_period_in_lines; | |
563 | uint32_t vertical_refresh_rate_in_milliHz,horizontal_sync_frequency_in_Hz,horizontal_sync_period_in_pixels; | |
564 | ||
565 | *p_is_timing = 1; | |
566 | ||
567 | pixel_clock_frequency = (uint32_t)tmp_word * 10000; | |
568 | ||
569 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
570 | "Pixel Clock: %d.%02d MHz or %d Hz (0x%x Hz)\n", | |
571 | tmp_word/100, tmp_word%100,pixel_clock_frequency,pixel_clock_frequency); | |
572 | ||
573 | columns = p_desc->dtd.horz_active_7_0 + 256 * p_desc->dtd.horz_active_blanking_high.horz_active_11_8; | |
574 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
575 | "Horizontal Active Pixels: %d\n", columns); | |
576 | ||
577 | tmp_word = p_desc->dtd.horz_blanking_7_0 + 256 * p_desc->dtd.horz_active_blanking_high.horz_blanking_11_8; | |
578 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
579 | "Horizontal Blanking (Pixels): %d\n", tmp_word); | |
580 | ||
581 | horizontal_sync_period_in_pixels = (uint32_t)columns + (uint32_t)tmp_word; | |
582 | horizontal_sync_frequency_in_Hz = pixel_clock_frequency/horizontal_sync_period_in_pixels; | |
583 | ||
584 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
585 | "horizontal period %u pixels, "\ | |
586 | "horizontal_sync_frequency_in_Hz: %u Hz\n", | |
587 | horizontal_sync_period_in_pixels,horizontal_sync_frequency_in_Hz); | |
588 | ||
589 | rows = p_desc->dtd.vert_active_7_0 + 256 * p_desc->dtd.vert_active_blanking_high.vert_active_11_8; | |
590 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
591 | "Vertical Active (Lines): %u\n", rows); | |
592 | ||
593 | tmp_word = p_desc->dtd.vert_blanking_7_0 + 256 * p_desc->dtd.vert_active_blanking_high.vert_blanking_11_8; | |
594 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
595 | "Vertical Blanking (Lines): %u\n", tmp_word); | |
596 | ||
597 | vertical_sync_period_in_lines = rows + tmp_word; | |
598 | vertical_refresh_rate_in_milliHz = horizontal_sync_frequency_in_Hz*1000/(vertical_sync_period_in_lines); | |
599 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
600 | "vertical period %u lines, frequency %u MilliHz\n", | |
601 | vertical_sync_period_in_lines,vertical_refresh_rate_in_milliHz); | |
602 | ||
603 | tmp_word = p_desc->dtd.horz_sync_offset_7_0 + 256 * p_desc->dtd.hs_offset_hs_pulse_width_vs_offset_vs_pulse_width.horzSyncOffset9_8; | |
604 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
605 | "Horizontal Sync Offset (Pixels): %d\n", tmp_word); | |
606 | ||
607 | tmp_word = p_desc->dtd.horz_sync_pulse_width7_0 + 256 * p_desc->dtd.hs_offset_hs_pulse_width_vs_offset_vs_pulse_width.horz_sync_pulse_width_9_8; | |
608 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
609 | "Horizontal Sync Pulse Width (Pixels): %d\n", tmp_word); | |
610 | ||
611 | tmp_word = p_desc->dtd.vert_sync_offset_width.vert_sync_offset_3_0 + 16 * p_desc->dtd.hs_offset_hs_pulse_width_vs_offset_vs_pulse_width.vert_sync_offset_5_4; | |
612 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
613 | "Vertical Sync Offset (Lines): %d\n", tmp_word); | |
614 | ||
615 | tmp_word = p_desc->dtd.vert_sync_offset_width.vert_sync_pulse_width_3_0 | |
616 | + 16 * p_desc->dtd.hs_offset_hs_pulse_width_vs_offset_vs_pulse_width.vert_sync_pulse_width_5_4; | |
617 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
618 | "Vertical Sync Pulse Width (Lines): %d\n", tmp_word); | |
619 | ||
620 | tmp_word = p_desc->dtd.horz_image_size_in_mm_7_0 | |
621 | + 256 * p_desc->dtd.image_size_high.horz_image_size_in_mm_11_8; | |
622 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
623 | "Horizontal Image Size (mm): %d\n", tmp_word); | |
624 | ||
625 | tmp_word = p_desc->dtd.vert_image_size_in_mm_7_0 | |
626 | + 256 * p_desc->dtd.image_size_high.vert_image_size_in_mm_11_8; | |
627 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
628 | "Vertical Image Size (mm): %d\n", tmp_word); | |
629 | ||
630 | tmp_byte = p_desc->dtd.horz_border_in_lines; | |
631 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
632 | "Horizontal Border (Pixels): %d\n", (int)tmp_byte); | |
633 | ||
634 | tmp_byte = p_desc->dtd.vert_border_in_pixels; | |
635 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
636 | "Vertical Border (Lines): %d\n", (int)tmp_byte); | |
637 | ||
638 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, "%sInterlaced\n",p_desc->dtd.flags.interlaced ? "" : "Non-" ); | |
639 | ||
640 | switch (p_desc->dtd.flags.stereo_bits_2_1) | |
641 | { | |
642 | case 0: | |
643 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
644 | "Normal Display, No Stereo\n"); | |
645 | break; | |
646 | case 1: | |
647 | if (0 == p_desc->dtd.flags.stereo_bit_0) { | |
648 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
649 | "Field sequential stereo, right image when "\ | |
650 | "stereo sync signal == 1\n"); | |
651 | } else { | |
652 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
653 | "2-way interleaved stereo, right image on "\ | |
654 | "even lines\n"); | |
655 | } | |
656 | break; | |
657 | case 2: | |
658 | if (0 == p_desc->dtd.flags.stereo_bit_0) { | |
659 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
660 | "field-sequential stereo, left image when "\ | |
661 | "stereo sync signal == 1\n"); | |
662 | } else { | |
663 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
664 | "2-way interleaved stereo, left image on even "\ | |
665 | "lines.\n"); | |
666 | } | |
667 | break; | |
668 | case 3: | |
669 | if (0 == p_desc->dtd.flags.stereo_bit_0) { | |
670 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
671 | "4-way interleaved stereo\n"); | |
672 | } else { | |
673 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
674 | "side-by-side interleaved stereo.\n"); | |
675 | } | |
676 | break; | |
677 | } | |
678 | ||
679 | switch ( p_desc->dtd.flags.sync_signal_type ) | |
680 | { | |
681 | case 0x0: | |
682 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
683 | "Analog Composite\n"); | |
684 | break; | |
685 | case 0x1: | |
686 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
687 | "Bipolar Analog Composite\n"); | |
688 | break; | |
689 | case 0x2: | |
690 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
691 | "Digital Composite\n"); | |
692 | break; | |
693 | case 0x3: | |
694 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
695 | "Digital Separate\n"); | |
696 | break; | |
697 | } | |
698 | if (pMHL2_video_descriptor) { | |
699 | uint8_t this_mode_doable=0; | |
700 | if ((this_mode_doable=qualify_pixel_clock_for_mhl((void*)mhl_edid_3d_data,pixel_clock_frequency,24))) { | |
701 | display_timing_enumeration_callback(mhl_edid_3d_data, columns, | |
702 | rows, 24, vertical_refresh_rate_in_milliHz, | |
703 | *pMHL2_video_descriptor); | |
704 | } | |
705 | ||
706 | if (this_mode_doable |=qualify_pixel_clock_for_mhl((void*)mhl_edid_3d_data,pixel_clock_frequency,16)) { | |
707 | display_timing_enumeration_callback(mhl_edid_3d_data, columns, | |
708 | rows, 16, vertical_refresh_rate_in_milliHz, | |
709 | *pMHL2_video_descriptor); | |
710 | } | |
711 | if (!this_mode_doable) { | |
712 | return false; | |
713 | } | |
714 | } | |
715 | } | |
716 | return true; | |
717 | } | |
718 | ||
719 | static uint8_t si_mhl_tx_parse_861_long_descriptors(edid_3d_data_p mhl_edid_3d_data,uint8_t *p_EDID_block_data) | |
720 | { | |
721 | PCEA_extension_t p_CEA_extension = (PCEA_extension_t)p_EDID_block_data; | |
722 | ||
723 | ||
724 | /* per CEA-861-D, table 27 */ | |
725 | if (!p_CEA_extension->byte_offset_to_18_byte_descriptors) { | |
726 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context, | |
727 | "EDID -> No Detailed Descriptors\n"); | |
728 | return EDID_NO_DETAILED_DESCRIPTORS; | |
729 | } else { | |
730 | uint8_t *puc_next_block; | |
731 | uint8_t descriptor_num = 1; | |
732 | union | |
733 | { | |
734 | uint8_t *puc_data_block; | |
735 | P_18_byte_descriptor_u p_long_descriptors; | |
736 | }p_data_u; | |
737 | ||
738 | p_data_u.p_long_descriptors= (P_18_byte_descriptor_u)(((uint8_t *)p_CEA_extension) + p_CEA_extension->byte_offset_to_18_byte_descriptors); | |
739 | puc_next_block = ((uint8_t *)p_CEA_extension) + EDID_BLOCK_SIZE; | |
740 | ||
741 | while ((uint8_t *)(p_data_u.p_long_descriptors + 1) < puc_next_block) { | |
742 | uint8_t is_timing=0; | |
743 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
744 | "Parse Results - CEA-861 Long Descriptor #%d:\n", | |
745 | (int) descriptor_num); | |
746 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
747 | "===============================================================\n"); | |
748 | ||
749 | if (!si_mhl_tx_parse_detailed_timing_descriptor(mhl_edid_3d_data,p_data_u.p_long_descriptors, EDID_BLOCK_2_3,&is_timing,NULL)) { | |
750 | break; | |
751 | } | |
752 | p_data_u.p_long_descriptors++; | |
753 | descriptor_num++; | |
754 | } | |
755 | ||
756 | return EDID_LONG_DESCRIPTORS_OK; | |
757 | } | |
758 | ||
759 | } | |
760 | ||
761 | #ifdef PRUNE_EDID | |
762 | static void si_mhl_tx_prune_edid(edid_3d_data_p mhl_edid_3d_data) | |
763 | { | |
764 | PEDID_block0_t p_EDID_block_0 = (PEDID_block0_t)&mhl_edid_3d_data->EDID_block_data[0]; | |
765 | uint8_t dtd_limit; | |
766 | PCEA_extension_t p_CEA_extension = (PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE]; | |
767 | Pblock_map_t p_block_map = NULL; | |
768 | uint8_t *pb_limit; | |
769 | union | |
770 | { | |
771 | uint8_t *puc_data_block; | |
772 | P_18_byte_descriptor_u p_long_descriptors; | |
773 | }p_data_u; | |
774 | ||
775 | if (EDID_EXTENSION_BLOCK_MAP == p_CEA_extension->tag) { | |
776 | /* save to overwrite later */ | |
777 | p_block_map = (Pblock_map_t)p_CEA_extension; | |
778 | ||
779 | /* advance to next block */ | |
780 | p_CEA_extension++; | |
781 | } | |
782 | pb_limit = (uint8_t *)(p_CEA_extension+1); | |
783 | ||
784 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
785 | "mhl_tx: %s\n",__FUNCTION__); | |
786 | p_data_u.puc_data_block = (uint8_t *)p_CEA_extension + p_CEA_extension->byte_offset_to_18_byte_descriptors; | |
787 | ||
788 | DUMP_EDID_BLOCK(0,p_EDID_block_0,sizeof(*p_EDID_block_0)) /* no semicolon needed here */ | |
789 | /* zero out checksums before modifying data */ | |
790 | p_CEA_extension->checksum=0; | |
791 | p_EDID_block_0->checksum = 0; | |
792 | ||
793 | /* Is there an HDMI VSDB? */ | |
794 | if (mhl_edid_3d_data->parse_data.p_HDMI_vsdb) { | |
795 | PHDMI_LLC_vsdb_payload_t p_HDMI_vendor_specific_payload = &mhl_edid_3d_data->parse_data.p_HDMI_vsdb->payload_u.HDMI_LLC; | |
796 | uint8_t *p_next_db = (uint8_t *)p_HDMI_vendor_specific_payload +mhl_edid_3d_data->parse_data.p_HDMI_vsdb->header.fields.length_following_header; | |
797 | ||
798 | /* if deep color information is provided... */ | |
799 | if (((uint8_t *)&p_HDMI_vendor_specific_payload->byte6) < p_next_db) { | |
800 | p_HDMI_vendor_specific_payload->byte6.DC_Y444 =0; | |
801 | p_HDMI_vendor_specific_payload->byte6.DC_30bit=0; | |
802 | p_HDMI_vendor_specific_payload->byte6.DC_36bit=0; | |
803 | p_HDMI_vendor_specific_payload->byte6.DC_48bit=0; | |
804 | } | |
805 | } | |
806 | /* prune the DTDs in block 0 */ | |
807 | dtd_limit = sizeof(p_EDID_block_0->detailed_timing_descriptors)/sizeof(p_EDID_block_0->detailed_timing_descriptors[0]); | |
808 | si_mhl_tx_prune_dtd_list(mhl_edid_3d_data,(P_18_byte_descriptor_u)&p_EDID_block_0->detailed_timing_descriptors[0],dtd_limit); | |
809 | DUMP_EDID_BLOCK(0,p_EDID_block_0,sizeof(*p_EDID_block_0)) /* no semicolon needed here */ | |
810 | ||
811 | DUMP_EDID_BLOCK(0,p_CEA_extension,sizeof(*p_CEA_extension)) /* no semicolon needed here */ | |
812 | /* prune the DTDs in the CEA-861D extension */ | |
813 | dtd_limit = (uint8_t)p_CEA_extension->version_u.version3.misc_support.total_number_detailed_timing_descriptors_in_entire_EDID; | |
814 | si_mhl_tx_prune_dtd_list(mhl_edid_3d_data,&p_data_u.p_long_descriptors[0],dtd_limit); | |
815 | /* adjust the mask according to which 2D VICs were set to zero */ | |
816 | if (mhl_edid_3d_data->parse_data.p_3d_mask) { | |
817 | uint8_t lower_mask; | |
818 | uint32_t mask32; | |
819 | int8_t index = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[0]->header.fields.length_following_header-1; | |
820 | index = (index > 15) ? 15 : index; | |
821 | ||
822 | mask32 = 0xFFFF00 >> (15 - index); | |
823 | lower_mask = (index > 7) ? 0x7F : (0x7F >> (7 - index)); | |
824 | ||
825 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
826 | "3d mask 15..8: 0x%02x", | |
827 | (uint16_t)mhl_edid_3d_data->parse_data.p_3d_mask->_3D_mask_15_8); | |
828 | for ( | |
829 | ; index >= 8 | |
830 | ; mask32>>=1,lower_mask >>=1, --index) { | |
831 | if (0 == mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[0]->short_descriptors[index].VIC) { | |
832 | uint8_t lower_bits,upper_bits; | |
833 | uint8_t upper_mask; | |
834 | upper_mask = (uint8_t)mask32; | |
835 | ||
836 | /* preserve the lower bits */ | |
837 | lower_bits = lower_mask & mhl_edid_3d_data->parse_data.p_3d_mask->_3D_mask_15_8; | |
838 | ||
839 | /* and out the bit in question */ | |
840 | upper_bits = upper_mask & mhl_edid_3d_data->parse_data.p_3d_mask->_3D_mask_15_8; | |
841 | ||
842 | /* adjust the positions of the upper bits */ | |
843 | upper_bits >>=1; | |
844 | ||
845 | mhl_edid_3d_data->parse_data.p_3d_mask->_3D_mask_15_8 = lower_bits | upper_bits; | |
846 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
847 | "3d mask 15..8: 0x%02x", | |
848 | (uint16_t)mhl_edid_3d_data->parse_data.p_3d_mask->_3D_mask_15_8); | |
849 | } | |
850 | } | |
851 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
852 | "3d mask 7..0: 0x%02x", | |
853 | (uint16_t)mhl_edid_3d_data->parse_data.p_3d_mask->_3D_mask_7_0); | |
854 | lower_mask = 0x7F >> (7 - index); | |
855 | for ( | |
856 | ; index >= 0 | |
857 | ; mask32>>=1,lower_mask >>=1, --index) { | |
858 | if (0 == mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[0]->short_descriptors[index].VIC) { | |
859 | uint8_t lower_bits,upper_bits; | |
860 | uint8_t upper_mask; | |
861 | upper_mask = (uint8_t)mask32; | |
862 | ||
863 | /* preserve the lower bits */ | |
864 | lower_bits = lower_mask & mhl_edid_3d_data->parse_data.p_3d_mask->_3D_mask_7_0; | |
865 | ||
866 | /* AND out the bit in question */ | |
867 | upper_bits = upper_mask & mhl_edid_3d_data->parse_data.p_3d_mask->_3D_mask_7_0; | |
868 | ||
869 | /* adjust the positions of the upper bits */ | |
870 | upper_bits >>=1; | |
871 | ||
872 | mhl_edid_3d_data->parse_data.p_3d_mask->_3D_mask_7_0 = lower_bits | upper_bits; | |
873 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
874 | "3d mask 7..0: 0x%02x\n", | |
875 | (uint16_t)mhl_edid_3d_data->parse_data.p_3d_mask->_3D_mask_7_0); | |
876 | } | |
877 | } | |
878 | } | |
879 | ||
880 | if (mhl_edid_3d_data->parse_data.p_three_d) { | |
881 | uint8_t num_3D_structure_bytes_pruned=0; | |
882 | union | |
883 | { | |
884 | P_3D_structure_and_detail_entry_u p_3D; | |
885 | P_3D_structure_and_detail_entry_sans_byte1_t p_sans_byte_1; | |
886 | P_3D_structure_and_detail_entry_with_byte1_t p_with_byte_1; | |
887 | uint8_t *p_as_bytes; | |
888 | }p_3D_u; | |
889 | uint32_t deletion_mask=0; | |
890 | uint8_t limit_2D_VIC = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[0]->header.fields.length_following_header; | |
891 | /* | |
892 | prior to moving things around, | |
893 | make a bitmap of the positions of the VICs that are zero | |
894 | */ | |
895 | { | |
896 | uint8_t i; | |
897 | uint32_t this_bit; | |
898 | for (i =0,this_bit=1; i < limit_2D_VIC;++i,this_bit<<=1) | |
899 | { | |
900 | uint8_t VIC; | |
901 | VIC = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[0]->short_descriptors[i].VIC; | |
902 | if (0 == VIC) | |
903 | { | |
904 | // set the bit that corresponds to the VIC that was set to zero | |
905 | deletion_mask |= this_bit; | |
906 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"vic: 0x%02x deletion_mask:0x%08x this_bit:0x%08x\n" | |
907 | ,VIC ,deletion_mask ,this_bit | |
908 | ); | |
909 | } | |
910 | } | |
911 | } | |
912 | ||
913 | p_3D_u.p_3D = mhl_edid_3d_data->parse_data.p_three_d; | |
914 | while ( p_3D_u.p_as_bytes < mhl_edid_3d_data->parse_data.p_3d_limit) { | |
915 | uint8_t _2D_VIC_order = p_3D_u.p_sans_byte_1->byte0._2D_VIC_order; | |
916 | _3D_structure_e _3D_structure = p_3D_u.p_sans_byte_1->byte0._3D_structure; | |
917 | uint8_t VIC; | |
918 | VIC = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[0]->short_descriptors[_2D_VIC_order].VIC; | |
919 | if (0 == VIC) { | |
920 | /* delete this 3D_Structure/3D_detail information */ | |
921 | uint8_t *pSrc,*pDest=p_3D_u.p_as_bytes; | |
922 | ||
923 | if (_3D_structure < tdsSideBySide) { | |
924 | pSrc = (uint8_t *)(p_3D_u.p_sans_byte_1+1); | |
925 | num_3D_structure_bytes_pruned += sizeof(*p_3D_u.p_sans_byte_1); | |
926 | } else { | |
927 | pSrc = (uint8_t *)(p_3D_u.p_with_byte_1+1); | |
928 | num_3D_structure_bytes_pruned += sizeof(*p_3D_u.p_with_byte_1); | |
929 | } | |
930 | while (pSrc < pb_limit) { | |
931 | *pDest++=*pSrc++; | |
932 | } | |
933 | while (pDest < pb_limit) { | |
934 | *pDest++=0; | |
935 | } | |
936 | } else { | |
937 | uint8_t i; | |
938 | uint8_t limit = _2D_VIC_order; | |
939 | uint32_t this_bit; | |
940 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"2D vic order: 0x%02x deletion_mask:0x%08x\n" | |
941 | ,_2D_VIC_order | |
942 | ,deletion_mask | |
943 | ); | |
944 | ||
945 | for (i = 0,this_bit=1; i < limit;++i,this_bit<<=1) | |
946 | { | |
947 | if (this_bit & deletion_mask) | |
948 | { | |
949 | _2D_VIC_order--; | |
950 | } | |
951 | } | |
952 | p_3D_u.p_sans_byte_1->byte0._2D_VIC_order = _2D_VIC_order; | |
953 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"2D vic order: 0x%02x this_bit:0x%08x\n" | |
954 | ,_2D_VIC_order | |
955 | ,this_bit | |
956 | ); | |
957 | ||
958 | ||
959 | if (_3D_structure < tdsSideBySide) { | |
960 | p_3D_u.p_sans_byte_1++; | |
961 | } else { | |
962 | p_3D_u.p_with_byte_1++; | |
963 | } | |
964 | } | |
965 | } | |
966 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"num_3D_structure_bytes_pruned:0x%x " | |
967 | "byte14: 0x%02x " | |
968 | "offset to DTDs: 0x%x " | |
969 | "vsdb header: 0x%x\n" | |
970 | ,num_3D_structure_bytes_pruned | |
971 | ,*((uint8_t *)&mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte14) | |
972 | ,p_CEA_extension->byte_offset_to_18_byte_descriptors | |
973 | ,*((uint8_t *)&mhl_edid_3d_data->parse_data.p_HDMI_vsdb->header) | |
974 | ); | |
975 | ||
976 | mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte14.HDMI_3D_len -= num_3D_structure_bytes_pruned; | |
977 | p_CEA_extension->byte_offset_to_18_byte_descriptors -= num_3D_structure_bytes_pruned; | |
978 | mhl_edid_3d_data->parse_data.p_HDMI_vsdb->header.fields.length_following_header -= num_3D_structure_bytes_pruned; | |
979 | ||
980 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"num_3D_structure_bytes_pruned:0x%x " | |
981 | "byte14: 0x%02x " | |
982 | "offset to DTDs: 0x%x " | |
983 | "vsdb header: 0x%x\n" | |
984 | ,num_3D_structure_bytes_pruned | |
985 | ,*((uint8_t *)&mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte14) | |
986 | ,p_CEA_extension->byte_offset_to_18_byte_descriptors | |
987 | ,*((uint8_t *)&mhl_edid_3d_data->parse_data.p_HDMI_vsdb->header) | |
988 | ); | |
989 | } | |
990 | /* now prune the HDMI VSDB VIC list */ | |
991 | if (mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15) { | |
992 | uint8_t length_VIC= mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte14.HDMI_VIC_len; | |
993 | ||
994 | if (0 ==length_VIC) { | |
995 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
996 | "length_VIC:%d \n",(uint16_t)length_VIC); | |
997 | } else { | |
998 | uint8_t i,num_HDMI_VICs_pruned=0; | |
999 | uint8_t inner_loop_limit; | |
1000 | uint8_t outer_loop_limit; | |
1001 | inner_loop_limit = length_VIC; | |
1002 | outer_loop_limit = length_VIC - 1; | |
1003 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1004 | "length_VIC:%d inner_loop_limit: %d outer_loop_limit: %d \n", | |
1005 | (uint16_t)length_VIC,(uint16_t)inner_loop_limit, | |
1006 | (uint16_t)outer_loop_limit); | |
1007 | for (i=0; i < outer_loop_limit;) { | |
1008 | if (0 == mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[i]) { | |
1009 | uint8_t j,prev; | |
1010 | for (prev=i,j = i+1; j < inner_loop_limit;++j,++prev) { | |
1011 | uint16_t VIC0,VIC1; | |
1012 | ||
1013 | VIC0 = mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[prev]; | |
1014 | VIC1 = mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[j]; | |
1015 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1016 | "replacing VIC: %3d at index: %3d with "\ | |
1017 | "VIC:%3d from index: %3d \n" | |
1018 | ,VIC0 | |
1019 | ,(uint16_t)prev | |
1020 | ,VIC1 | |
1021 | ,(uint16_t)j | |
1022 | ); | |
1023 | mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[prev] | |
1024 | = mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[j]; | |
1025 | } | |
1026 | /* we just removed one */ | |
1027 | num_HDMI_VICs_pruned++; | |
1028 | inner_loop_limit--; | |
1029 | outer_loop_limit--; | |
1030 | } else { | |
1031 | /* this mode is doable on MHL, so move on to the next index */ | |
1032 | ++i; | |
1033 | } | |
1034 | } | |
1035 | /* check the last one */ | |
1036 | if (0 == mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[outer_loop_limit]) { | |
1037 | num_HDMI_VICs_pruned++; | |
1038 | inner_loop_limit--; | |
1039 | } | |
1040 | ||
1041 | DUMP_EDID_BLOCK(0,p_CEA_extension,sizeof(*p_CEA_extension)) /* no semicolon needed here */ | |
1042 | /* now move all other data up */ | |
1043 | if (num_HDMI_VICs_pruned) { | |
1044 | uint8_t *pb_dest = (uint8_t *)&mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[inner_loop_limit]; | |
1045 | uint8_t *pb_src = (uint8_t *)&mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[length_VIC]; | |
1046 | ||
1047 | SII_ASSERT(EDID_BLOCK_SIZE==sizeof(*p_CEA_extension),("\n\n unexpected extension size\n\n")); | |
1048 | while(pb_src < pb_limit) { | |
1049 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1050 | "moving data up %02x(0x%02x) <- %02x(0x%02x)\n", | |
1051 | pb_dest,(uint16_t)*pb_dest,pb_src,(uint16_t)*pb_src); | |
1052 | *pb_dest++=*pb_src++; | |
1053 | } | |
1054 | ||
1055 | while(pb_dest < pb_limit) { | |
1056 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1057 | "clearing data %02x <- 0\n",pb_dest); | |
1058 | *pb_dest++=0; | |
1059 | } | |
1060 | ||
1061 | } | |
1062 | mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte14.HDMI_VIC_len = inner_loop_limit; | |
1063 | p_CEA_extension->byte_offset_to_18_byte_descriptors -= num_HDMI_VICs_pruned; | |
1064 | ||
1065 | MHL_TX_EDID_INFO(,"%p\n",mhl_edid_3d_data->parse_data.p_HDMI_vsdb); | |
1066 | if (mhl_edid_3d_data->parse_data.p_HDMI_vsdb){ | |
1067 | mhl_edid_3d_data->parse_data.p_HDMI_vsdb->header.fields.length_following_header -= num_HDMI_VICs_pruned; | |
1068 | }else if (num_HDMI_VICs_pruned){ | |
1069 | MHL_TX_DBG_ERR(,"How can you have HDMI vics to prune if you have no HDMI VSDB?\n"); | |
1070 | } | |
1071 | } | |
1072 | } | |
1073 | ||
1074 | /* Now prune the SVD list and move the CEA 861-D data blocks and DTDs up */ | |
1075 | { | |
1076 | uint8_t i,num_CEA_VICs_pruned=0; | |
1077 | /* | |
1078 | pack each vdb to eliminate the bytes that have been zeroed. | |
1079 | */ | |
1080 | int8_t vdb_index; | |
1081 | for (vdb_index =mhl_edid_3d_data->parse_data.num_video_data_blocks-1 | |
1082 | ;vdb_index >= 0 ;--vdb_index) { | |
1083 | uint8_t inner_loop_limit = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->header.fields.length_following_header; | |
1084 | if (inner_loop_limit) { | |
1085 | uint8_t outer_loop_limit = inner_loop_limit-1; | |
1086 | ||
1087 | for (i=0; i < outer_loop_limit;) { | |
1088 | if (0 == mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[i].VIC) { | |
1089 | uint8_t j,prev; | |
1090 | num_CEA_VICs_pruned++; | |
1091 | for (prev=i,j = i+1; j < inner_loop_limit;++j,++prev) { | |
1092 | uint16_t VIC0,VIC1; | |
1093 | ||
1094 | VIC0 = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[prev].VIC; | |
1095 | VIC1 = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[j].VIC; | |
1096 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1097 | "replacing SVD:%6s 0x%02x at index: 0x%02x with "\ | |
1098 | "SVD:%6s 0x%02x from index: 0x%02x \n" | |
1099 | ,mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]-> | |
1100 | short_descriptors[prev].native ? "Native":"" | |
1101 | ,VIC0 | |
1102 | ,(uint16_t)prev | |
1103 | ,mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]-> | |
1104 | short_descriptors[j].native ? "Native":"" | |
1105 | ,VIC1 | |
1106 | ,(uint16_t)j | |
1107 | ); | |
1108 | mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[prev] | |
1109 | = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[j]; | |
1110 | } | |
1111 | /* we just removed one */ | |
1112 | inner_loop_limit--; | |
1113 | outer_loop_limit--; | |
1114 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context | |
1115 | ,"outer_loop_limit:0x%x inner_loop_limit:0x%x\n" | |
1116 | , (uint16_t)outer_loop_limit | |
1117 | , (uint16_t)inner_loop_limit | |
1118 | ); | |
1119 | } else { | |
1120 | /* this mode is doable on MHL, so move on to the next index */ | |
1121 | ++i; | |
1122 | } | |
1123 | } | |
1124 | /* check the last one */ | |
1125 | if (0 == mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[outer_loop_limit].VIC) { | |
1126 | num_CEA_VICs_pruned++; | |
1127 | inner_loop_limit--; | |
1128 | mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[outer_loop_limit].native=0; | |
1129 | } | |
1130 | ||
1131 | ||
1132 | DUMP_EDID_BLOCK(0,p_CEA_extension,sizeof(*p_CEA_extension)) /* no semicolon needed here */ | |
1133 | ||
1134 | /* now move all other data up */ | |
1135 | { | |
1136 | uint8_t *pb_dest = (uint8_t *)&mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[inner_loop_limit]; | |
1137 | uint8_t *pb_src= (uint8_t *)&mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->header.fields.length_following_header]; | |
1138 | ||
1139 | SII_ASSERT(EDID_BLOCK_SIZE==sizeof(*p_CEA_extension),("\n\n unexpected extension size\n\n")); | |
1140 | while(pb_src < pb_limit) { | |
1141 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1142 | "moving data up %p(0x%02x) <- %p(0x%02x)\n", | |
1143 | pb_dest,(uint16_t)*pb_dest,pb_src,(uint16_t)*pb_src); | |
1144 | *pb_dest++=*pb_src++; | |
1145 | } | |
1146 | ||
1147 | while(pb_dest < pb_limit) { | |
1148 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1149 | "clearing data %02x <- 0\n", *pb_dest); | |
1150 | *pb_dest++=0; | |
1151 | } | |
1152 | ||
1153 | } | |
1154 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1155 | "CEA-861-D DTDs began at 0x%02x" \ | |
1156 | "CEA-861-D SVD count: 0x%x\n" | |
1157 | ,(uint16_t)p_CEA_extension->byte_offset_to_18_byte_descriptors | |
1158 | ,(uint16_t)mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]-> | |
1159 | header.fields.length_following_header); | |
1160 | ||
1161 | p_CEA_extension->byte_offset_to_18_byte_descriptors -= num_CEA_VICs_pruned; | |
1162 | mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->header.fields.length_following_header = inner_loop_limit; | |
1163 | ||
1164 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1165 | "CEA-861-D DTDs now begin at 0x%02x" \ | |
1166 | "CEA-861-D SVD count: 0x%x\n" | |
1167 | ,(uint16_t)p_CEA_extension->byte_offset_to_18_byte_descriptors | |
1168 | ,(uint16_t)mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]-> | |
1169 | header.fields.length_following_header); | |
1170 | ||
1171 | DUMP_EDID_BLOCK(0,p_CEA_extension,sizeof(*p_CEA_extension)) /* no semicolon needed here */ | |
1172 | } | |
1173 | } | |
1174 | } | |
1175 | ||
1176 | /* re-compute the checksum(s) */ | |
1177 | SII_ASSERT(EDID_BLOCK_SIZE==sizeof(*p_EDID_block_0),("\n\n unexpected size for block 0\n\n")); | |
1178 | SII_ASSERT(EDID_BLOCK_SIZE==sizeof(*p_CEA_extension),("\n\n unexpected size for CEA extension\n\n")); | |
1179 | ||
1180 | if (p_block_map) { | |
1181 | PCEA_extension_t p_CEA_extensionDest=(PCEA_extension_t)p_block_map; | |
1182 | *p_CEA_extensionDest = *p_CEA_extension; | |
1183 | } | |
1184 | ||
1185 | ||
1186 | p_EDID_block_0->checksum = calculate_generic_checksum((uint8_t *)p_EDID_block_0,0,sizeof(*p_EDID_block_0)); | |
1187 | ||
1188 | p_CEA_extension->checksum=calculate_generic_checksum((uint8_t *)p_CEA_extension,0,sizeof(*p_CEA_extension)); | |
1189 | ||
1190 | ||
1191 | DUMP_EDID_BLOCK(0,p_CEA_extension,sizeof(*p_CEA_extension)) /* no semicolon needed here */ | |
1192 | ||
1193 | ||
1194 | /* | |
1195 | TODO: adjust all pointers into the EDID along the way of pruning the contents, instead of re-parsing here | |
1196 | */ | |
1197 | #ifndef EDID_PASSTHROUGH //( | |
1198 | if (0 == si_mhl_tx_drv_set_upstream_edid(mhl_edid_3d_data->drv_context,mhl_edid_3d_data->EDID_block_data,2*EDID_BLOCK_SIZE)) | |
1199 | #endif //) | |
1200 | { | |
1201 | SET_3D_FLAG(mhl_edid_3d_data,FLAGS_EDID_READ_DONE) | |
1202 | si_mhl_tx_drv_enable_video_path(mhl_edid_3d_data->drv_context); // TODO: FD, TBI, debug? | |
1203 | } | |
1204 | } | |
1205 | #endif | |
1206 | /* | |
1207 | */ | |
1208 | static uint8_t IsQualifiedMhlVIC(edid_3d_data_p mhl_edid_3d_data,uint8_t VIC,PMHL2_video_descriptor_t p_mhl2_video_descriptor) | |
1209 | { | |
1210 | uint8_t ret_val=0; | |
1211 | if (VIC > 0) { | |
1212 | ret_val= is_MHL_timing_mode(mhl_edid_3d_data,VIC_info[VIC].columns, VIC_info[VIC].rows, VIC_info[VIC].field_rate_in_milliHz,p_mhl2_video_descriptor,VIC); | |
1213 | if (vif_dual_frame_rate == VIC_info[VIC].fields.frame_rate_info) { | |
1214 | uint32_t field_rate_in_milliHz; | |
1215 | switch(VIC_info[VIC].field_rate_in_milliHz) | |
1216 | { | |
1217 | case 24000: /* 23.97 */ | |
1218 | field_rate_in_milliHz = 23970; | |
1219 | break; | |
1220 | ||
1221 | case 30000: /* 29.97 */ | |
1222 | field_rate_in_milliHz = 29970; | |
1223 | break; | |
1224 | ||
1225 | case 60000: /* 59.94 */ | |
1226 | field_rate_in_milliHz = 59940; | |
1227 | break; | |
1228 | ||
1229 | case 120000: /* 119.88 */ | |
1230 | field_rate_in_milliHz = 119880; | |
1231 | break; | |
1232 | ||
1233 | case 240000: /* 239.76 */ | |
1234 | field_rate_in_milliHz = 239760; | |
1235 | break; | |
1236 | ||
1237 | default: /* error or unknown case */ | |
1238 | field_rate_in_milliHz=0; | |
1239 | break; | |
1240 | } | |
1241 | ret_val |= is_MHL_timing_mode(mhl_edid_3d_data,VIC_info[VIC].columns, VIC_info[VIC].rows, field_rate_in_milliHz,p_mhl2_video_descriptor,VIC); | |
1242 | } | |
1243 | } | |
1244 | return ret_val; | |
1245 | } | |
1246 | /* HDMI_VIC is a place holder, and not actually stored */ | |
1247 | #define hdmi_vic_infoEntry(HDMI_VIC,columns,rows,FieldRate0,FieldRate1,pixel_clock_0,pixel_clock_1) \ | |
1248 | {columns,rows,FieldRate0,FieldRate1,pixel_clock_0,pixel_clock_1} | |
1249 | ||
1250 | PLACE_IN_CODE_SEG HDMI_VIC_info_t hdmi_vic_info[]= | |
1251 | { | |
1252 | hdmi_vic_infoEntry( 0, 0, 0, 0, 0, 0, 0) | |
1253 | ,hdmi_vic_infoEntry( 1,3840,2160,30000,29970, 297000000,296703000) | |
1254 | ,hdmi_vic_infoEntry( 2,3840,2160,25000,25000, 297000000,297000000) | |
1255 | ,hdmi_vic_infoEntry( 3,3840,2160,24000,23976, 297000000,296703000) | |
1256 | ,hdmi_vic_infoEntry( 4,4096,2160,24000,24000, 297000000,297000000) | |
1257 | }; | |
1258 | /* | |
1259 | */ | |
1260 | static uint8_t is_qualified_mhl_hdmi_vic(edid_3d_data_p mhl_edid_3d_data,uint8_t VIC,PMHL2_video_descriptor_t pMHL2_video_descriptor) | |
1261 | { | |
1262 | uint8_t ret_val=0; | |
1263 | ||
1264 | if (qualify_pixel_clock_for_mhl(mhl_edid_3d_data, hdmi_vic_info[VIC].pixel_clock_0, 24)) { | |
1265 | display_timing_enumeration_callback(mhl_edid_3d_data, | |
1266 | hdmi_vic_info[VIC].columns, hdmi_vic_info[VIC].rows, 24, | |
1267 | hdmi_vic_info[VIC].field_rate_0_in_milliHz, | |
1268 | *pMHL2_video_descriptor); | |
1269 | ret_val = 1; | |
1270 | } | |
1271 | if (qualify_pixel_clock_for_mhl(mhl_edid_3d_data,hdmi_vic_info[VIC].pixel_clock_0, 16)) { | |
1272 | display_timing_enumeration_callback(mhl_edid_3d_data, | |
1273 | hdmi_vic_info[VIC].columns, hdmi_vic_info[VIC].rows, 16, | |
1274 | hdmi_vic_info[VIC].field_rate_0_in_milliHz,*pMHL2_video_descriptor); | |
1275 | ret_val = 1; | |
1276 | } | |
1277 | if (hdmi_vic_info[VIC].pixel_clock_0 != hdmi_vic_info[VIC].pixel_clock_1) { | |
1278 | if (qualify_pixel_clock_for_mhl(mhl_edid_3d_data,hdmi_vic_info[VIC].pixel_clock_1, 24)) { | |
1279 | display_timing_enumeration_callback(mhl_edid_3d_data, | |
1280 | hdmi_vic_info[VIC].columns, hdmi_vic_info[VIC].rows, 24, | |
1281 | hdmi_vic_info[VIC].field_rate_1_in_milliHz, | |
1282 | *pMHL2_video_descriptor); | |
1283 | ret_val = 1; | |
1284 | } | |
1285 | if (qualify_pixel_clock_for_mhl(mhl_edid_3d_data,hdmi_vic_info[VIC].pixel_clock_1, 16)) { | |
1286 | display_timing_enumeration_callback(mhl_edid_3d_data, | |
1287 | hdmi_vic_info[VIC].columns, hdmi_vic_info[VIC].rows, 16, | |
1288 | hdmi_vic_info[VIC].field_rate_1_in_milliHz, | |
1289 | *pMHL2_video_descriptor); | |
1290 | ret_val = 1; | |
1291 | } | |
1292 | } | |
1293 | return ret_val; | |
1294 | } | |
1295 | ||
1296 | void si_mhl_tx_enumerate_hdmi_vsdb(edid_3d_data_p mhl_edid_3d_data) | |
1297 | { | |
1298 | int8_t vdb_index=0; | |
1299 | if (mhl_edid_3d_data->parse_data.p_HDMI_vsdb) { | |
1300 | PHDMI_LLC_vsdb_payload_t p_HDMI_vendor_specific_payload = &mhl_edid_3d_data->parse_data.p_HDMI_vsdb->payload_u.HDMI_LLC; | |
1301 | uint8_t *p_next_db = (uint8_t *)p_HDMI_vendor_specific_payload +mhl_edid_3d_data->parse_data.p_HDMI_vsdb->header.fields.length_following_header; | |
1302 | /* if 3D_present field is included */ | |
1303 | if (mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15) { | |
1304 | if (((uint8_t *)&mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte13) < p_next_db) { | |
1305 | uint8_t hdmi3D_present = mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte13._3D_present; | |
1306 | uint8_t hdmi_3D_multi_present = mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte13._3D_multi_present; | |
1307 | ||
1308 | /* if HDMI_VIC_len is present... */ | |
1309 | if (((uint8_t *)&mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte14) < p_next_db) { | |
1310 | uint8_t length_VIC; | |
1311 | uint8_t index; | |
1312 | MHL2_video_descriptor_t mhl2_video_descriptor; | |
1313 | length_VIC = mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte14.HDMI_VIC_len; | |
1314 | mhl2_video_descriptor.left_right = 0; | |
1315 | mhl2_video_descriptor.top_bottom = 0; | |
1316 | mhl2_video_descriptor.frame_sequential= 0; | |
1317 | for (index = 0; index < length_VIC;++index) { | |
1318 | uint8_t VIC; | |
1319 | ||
1320 | VIC = mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[index]; | |
1321 | if (!is_qualified_mhl_hdmi_vic(mhl_edid_3d_data,VIC,&mhl2_video_descriptor)) { | |
1322 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1323 | "'can't do HDMI VIC:%d\n",(uint16_t)VIC); | |
1324 | mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[index] = 0; | |
1325 | } | |
1326 | } | |
1327 | if (hdmi3D_present) { | |
1328 | uint8_t length_3D; | |
1329 | PHDMI_3D_sub_block_t pThree3DSubBlock= (PHDMI_3D_sub_block_t)&mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[length_VIC]; | |
1330 | union | |
1331 | { | |
1332 | P_3D_structure_and_detail_entry_u p_3D; | |
1333 | P_3D_structure_and_detail_entry_sans_byte1_t p_sans_byte_1; | |
1334 | P_3D_structure_and_detail_entry_with_byte1_t p_with_byte_1; | |
1335 | uint8_t *p_as_bytes; | |
1336 | }p_3D_u; | |
1337 | uint8_t limit; | |
1338 | p_3D_u.p_3D=NULL; | |
1339 | length_3D = mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte14.HDMI_3D_len; | |
1340 | limit =mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->header.fields.length_following_header; | |
1341 | /* only do the first 16 */ | |
1342 | limit = (limit > 16)?16:limit; | |
1343 | switch(hdmi_3D_multi_present) | |
1344 | { | |
1345 | case 0x00: | |
1346 | /* 3D_Structure_ALL_15..0 and 3D_MASK_15..0 fields are not present */ | |
1347 | p_3D_u.p_3D = &pThree3DSubBlock->hDMI_3D_sub_block_sans_all_AND_mask._3D_structure_and_detail_list[0]; | |
1348 | break; | |
1349 | case 0x01: | |
1350 | /* | |
1351 | 3D_Structure_ALL_15..0 is present and assigns 3D formats | |
1352 | to all of the VICs listed in the first 16 entries in the EDID | |
1353 | 3D_mask_15..0 is not present | |
1354 | */ | |
1355 | { | |
1356 | P_3D_structure_all_t p_3D_structure_all=(P_3D_structure_all_t)&mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[length_VIC]; | |
1357 | mhl2_video_descriptor.left_right = p_3D_structure_all->_3D_structure_all_7_0.side_by_side; | |
1358 | mhl2_video_descriptor.top_bottom = p_3D_structure_all->_3D_structure_all_15_8.top_bottom; | |
1359 | mhl2_video_descriptor.frame_sequential= p_3D_structure_all->_3D_structure_all_15_8.frame_packing; | |
1360 | DUMP_EDID_BLOCK(0,(PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE],EDID_BLOCK_SIZE) /* no semicolon needed here */ | |
1361 | for (index = 0; index < limit;++index) { | |
1362 | uint8_t VIC; | |
1363 | ||
1364 | VIC = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[index].VIC; | |
1365 | if (VIC) { | |
1366 | if (!IsQualifiedMhlVIC(mhl_edid_3d_data,VIC,&mhl2_video_descriptor)) { | |
1367 | mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[index].VIC=0; | |
1368 | } | |
1369 | } | |
1370 | } | |
1371 | DUMP_EDID_BLOCK(0,(PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE],EDID_BLOCK_SIZE) /* no semicolon needed here */ | |
1372 | length_3D -= sizeof(*p_3D_structure_all); | |
1373 | } | |
1374 | p_3D_u.p_3D = &pThree3DSubBlock->HDMI_3D_sub_block_sans_mask._3D_structure_and_detail_list[0]; | |
1375 | break; | |
1376 | case 0x02: | |
1377 | /* | |
1378 | 3D_Structure_ALL_15..0 and 3D_mask_15..0 are present and | |
1379 | assign 3D formats to some of the VICS listed in the first | |
1380 | 16 entries in the EDID | |
1381 | ||
1382 | */ | |
1383 | { | |
1384 | P_3D_structure_all_t p_3D_structure_all=(P_3D_structure_all_t)&mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->vicList[length_VIC]; | |
1385 | P_3D_mask_t p3DMask = (P_3D_mask_t)(p_3D_structure_all+1); | |
1386 | uint8_t mask; | |
1387 | mhl2_video_descriptor.left_right = p_3D_structure_all->_3D_structure_all_7_0.side_by_side; | |
1388 | mhl2_video_descriptor.top_bottom = p_3D_structure_all->_3D_structure_all_15_8.top_bottom; | |
1389 | mhl2_video_descriptor.frame_sequential= p_3D_structure_all->_3D_structure_all_15_8.frame_packing; | |
1390 | DUMP_EDID_BLOCK(0,(PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE],EDID_BLOCK_SIZE) /* no semicolon needed here */ | |
1391 | for (mask=1,index = 0; (mask > 0) && (index < limit);++index,mask<<=1) { | |
1392 | uint8_t VIC; | |
1393 | MHL2_video_descriptor_t this_MHL2_video_descriptor; | |
1394 | ||
1395 | if (mask & p3DMask->_3D_mask_7_0) { | |
1396 | this_MHL2_video_descriptor = mhl2_video_descriptor; | |
1397 | } else { | |
1398 | this_MHL2_video_descriptor.left_right = 0; | |
1399 | this_MHL2_video_descriptor.top_bottom = 0; | |
1400 | this_MHL2_video_descriptor.frame_sequential= 0; | |
1401 | } | |
1402 | ||
1403 | VIC = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[index].VIC; | |
1404 | if (VIC) { | |
1405 | if (!IsQualifiedMhlVIC(mhl_edid_3d_data,VIC,&mhl2_video_descriptor)) { | |
1406 | mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[index].VIC=0; | |
1407 | } | |
1408 | } | |
1409 | } | |
1410 | DUMP_EDID_BLOCK(0,(PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE],EDID_BLOCK_SIZE) /* no semicolon needed here */ | |
1411 | for (mask=1;(mask > 0) && (index < limit);++index,mask<<=1) { | |
1412 | uint8_t VIC; | |
1413 | MHL2_video_descriptor_t this_MHL2_video_descriptor; | |
1414 | ||
1415 | if (mask & p3DMask->_3D_mask_15_8) { | |
1416 | this_MHL2_video_descriptor = mhl2_video_descriptor; | |
1417 | } else { | |
1418 | this_MHL2_video_descriptor.left_right = 0; | |
1419 | this_MHL2_video_descriptor.top_bottom = 0; | |
1420 | this_MHL2_video_descriptor.frame_sequential= 0; | |
1421 | } | |
1422 | ||
1423 | VIC = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[index].VIC; | |
1424 | if (VIC) { | |
1425 | if (!IsQualifiedMhlVIC(mhl_edid_3d_data,VIC,&mhl2_video_descriptor)) { | |
1426 | mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[index].VIC=0; | |
1427 | } | |
1428 | } | |
1429 | } | |
1430 | DUMP_EDID_BLOCK(0,(PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE],EDID_BLOCK_SIZE) /* no semicolon needed here */ | |
1431 | length_3D -= sizeof(*p_3D_structure_all); | |
1432 | length_3D -= sizeof(*p3DMask); | |
1433 | } | |
1434 | p_3D_u.p_3D = &pThree3DSubBlock->HDMI_3D_sub_block_with_all_AND_mask._3D_structure_and_detail_list[0]; | |
1435 | mhl_edid_3d_data->parse_data.p_3d_mask = &pThree3DSubBlock->HDMI_3D_sub_block_with_all_AND_mask._3D_mask; | |
1436 | break; | |
1437 | case 0x03: | |
1438 | /* | |
1439 | Reserved for future use. | |
1440 | 3D_Structure_ALL_15..0 and 3D_mask_15..0 are NOT present | |
1441 | */ | |
1442 | p_3D_u.p_3D = &pThree3DSubBlock->hDMI_3D_sub_block_sans_all_AND_mask._3D_structure_and_detail_list[0]; | |
1443 | break; | |
1444 | } | |
1445 | mhl_edid_3d_data->parse_data.p_three_d =p_3D_u.p_3D; | |
1446 | mhl_edid_3d_data->parse_data.p_3d_limit = &p_3D_u.p_as_bytes[length_3D]; | |
1447 | DUMP_EDID_BLOCK(0,(PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE],EDID_BLOCK_SIZE) /* no semicolon needed here */ | |
1448 | while ( p_3D_u.p_as_bytes < mhl_edid_3d_data->parse_data.p_3d_limit) { | |
1449 | uint8_t _2D_VIC_order = p_3D_u.p_sans_byte_1->byte0._2D_VIC_order; | |
1450 | _3D_structure_e _3D_structure = p_3D_u.p_sans_byte_1->byte0._3D_structure; | |
1451 | uint8_t VIC; | |
1452 | VIC = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[_2D_VIC_order].VIC; | |
1453 | /* this VIC position might have gotten disqualified already */ | |
1454 | if (VIC) { | |
1455 | mhl2_video_descriptor.left_right = 0; | |
1456 | mhl2_video_descriptor.top_bottom = 0; | |
1457 | mhl2_video_descriptor.frame_sequential = 0; | |
1458 | switch(_3D_structure) | |
1459 | { | |
1460 | case tdsSideBySide: | |
1461 | { | |
1462 | //re-visit uint8_t _3D_detail = p_3D_u.p_with_byte_1->byte1._3D_detail; | |
1463 | mhl2_video_descriptor.left_right = 1; | |
1464 | } | |
1465 | break; | |
1466 | case tdsTopAndBottom: | |
1467 | mhl2_video_descriptor.top_bottom = 1; | |
1468 | break; | |
1469 | case tdsFramePacking: | |
1470 | mhl2_video_descriptor.frame_sequential = 1; | |
1471 | break; | |
1472 | } | |
1473 | if (!IsQualifiedMhlVIC(mhl_edid_3d_data,VIC,&mhl2_video_descriptor)) { | |
1474 | mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[vdb_index]->short_descriptors[_2D_VIC_order].VIC=0; | |
1475 | } | |
1476 | } | |
1477 | if (_3D_structure < tdsSideBySide) { | |
1478 | p_3D_u.p_sans_byte_1++; | |
1479 | } else { | |
1480 | p_3D_u.p_with_byte_1++; | |
1481 | } | |
1482 | } | |
1483 | DUMP_EDID_BLOCK(0,(PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE],EDID_BLOCK_SIZE) /* no semicolon needed here */ | |
1484 | } | |
1485 | } | |
1486 | } | |
1487 | } | |
1488 | } | |
1489 | } | |
1490 | ||
1491 | static void si_mhl_tx_display_timing_enumeration_end(edid_3d_data_p mhl_edid_3d_data) | |
1492 | { | |
1493 | mhl_edid_3d_data->parse_data.flags.parse_3d_in_progress = 0; | |
1494 | /* finish off with any 3D modes reported via the HDMI VSDB */ | |
1495 | si_mhl_tx_enumerate_hdmi_vsdb(mhl_edid_3d_data); | |
1496 | /* notify the app (board specific) layer */ | |
1497 | display_timing_enumeration_end(mhl_edid_3d_data); | |
1498 | SET_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_DONE); | |
1499 | #ifdef PRUNE_EDID | |
1500 | si_mhl_tx_prune_edid(mhl_edid_3d_data); | |
1501 | #else | |
1502 | SET_3D_FLAG(mhl_edid_3d_data,FLAGS_EDID_READ_DONE) | |
1503 | si_mhl_tx_drv_enable_video_path(mhl_edid_3d_data->drv_context); // //TODO: FD, TBI, debug? | |
1504 | #endif | |
1505 | } | |
1506 | ||
1507 | static void CheckForAll3DBurstDone(edid_3d_data_p mhl_edid_3d_data) | |
1508 | { | |
1509 | if (TEST_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_VIC_DONE)){ | |
1510 | if (TEST_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_DTD_DONE)) { | |
1511 | if (!TEST_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_DONE)) { | |
1512 | si_mhl_tx_display_timing_enumeration_end(mhl_edid_3d_data); | |
1513 | } | |
1514 | } | |
1515 | } | |
1516 | } | |
1517 | ||
1518 | /* | |
1519 | */ | |
1520 | void si_mhl_tx_process_3d_vic_burst( | |
1521 | void *context | |
1522 | , PMHL2_video_format_data_t p_write_burst_data /* from 3D_REQ */ | |
1523 | ) | |
1524 | { | |
1525 | edid_3d_data_p mhl_edid_3d_data=(edid_3d_data_p)context; | |
1526 | uint8_t block_index = 0; | |
1527 | PMHL2_video_descriptor_t p_mhl2_video_descriptor; | |
1528 | //re-visit uint8_t edidLimit = mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte14.HDMI_3D_len; | |
1529 | ||
1530 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"burstEntryCount3D_VIC: %d\n",mhl_edid_3d_data->parse_data.burst_entry_count_3d_vic); | |
1531 | ||
1532 | if ( mhl_edid_3d_data->parse_data.flags.parse_3d_in_progress) { | |
1533 | /* check to see if it's time to move on to the next block */ | |
1534 | if (mhl_edid_3d_data->parse_data.vic_2d_index >= mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[mhl_edid_3d_data->parse_data.video_data_block_index]->header.fields.length_following_header) { | |
1535 | mhl_edid_3d_data->parse_data.video_data_block_index++; | |
1536 | if ( mhl_edid_3d_data->parse_data.video_data_block_index >= mhl_edid_3d_data->parse_data.num_video_data_blocks){ | |
1537 | SET_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_VIC_DONE) | |
1538 | CheckForAll3DBurstDone(mhl_edid_3d_data); | |
1539 | return; | |
1540 | } | |
1541 | } | |
1542 | ||
1543 | if (mhl_edid_3d_data->parse_data.burst_entry_count_3d_vic < mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[mhl_edid_3d_data->parse_data.video_data_block_index]->header.fields.length_following_header) { | |
1544 | /* each SVD is 1 byte long */ | |
1545 | DUMP_EDID_BLOCK(0,(PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE],EDID_BLOCK_SIZE) /* no semicolon needed here */ | |
1546 | for (/* block_index is set to zero above */ | |
1547 | ;(block_index < p_write_burst_data->num_entries_this_burst) | |
1548 | && | |
1549 | (mhl_edid_3d_data->parse_data.burst_entry_count_3d_vic < p_write_burst_data->total_entries ) | |
1550 | ;++block_index | |
1551 | ,++mhl_edid_3d_data->parse_data.burst_entry_count_3d_vic | |
1552 | ,++mhl_edid_3d_data->parse_data.vic_2d_index) { | |
1553 | uint8_t VIC; | |
1554 | uint8_t this_mode_doable=0; | |
1555 | /* check to see if it's time to move on to the next block */ | |
1556 | if (mhl_edid_3d_data->parse_data.vic_2d_index >= mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[mhl_edid_3d_data->parse_data.video_data_block_index]->header.fields.length_following_header) { | |
1557 | mhl_edid_3d_data->parse_data.video_data_block_index++; | |
1558 | if ( mhl_edid_3d_data->parse_data.video_data_block_index >= mhl_edid_3d_data->parse_data.num_video_data_blocks){ | |
1559 | SET_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_VIC_DONE) | |
1560 | break; | |
1561 | } | |
1562 | } | |
1563 | ||
1564 | p_mhl2_video_descriptor = &p_write_burst_data->video_descriptors[block_index]; | |
1565 | VIC = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[mhl_edid_3d_data->parse_data.video_data_block_index]->short_descriptors[mhl_edid_3d_data->parse_data.vic_2d_index].VIC; | |
1566 | ||
1567 | if (VIC) { | |
1568 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1569 | "short Descriptor[%d] 3D VIC: %d %s %s %s\n" | |
1570 | ,mhl_edid_3d_data->parse_data.burst_entry_count_3d_vic | |
1571 | ,VIC | |
1572 | ,p_mhl2_video_descriptor->left_right ?psz_left_right :psz_space | |
1573 | ,p_mhl2_video_descriptor->top_bottom ?psz_top_bottom :psz_space | |
1574 | ,p_mhl2_video_descriptor->frame_sequential?psz_frame_sequential:psz_space | |
1575 | ); | |
1576 | this_mode_doable = IsQualifiedMhlVIC(mhl_edid_3d_data,VIC,p_mhl2_video_descriptor); | |
1577 | if (!this_mode_doable) { | |
1578 | /* prune this mode from EDID */ | |
1579 | ||
1580 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1581 | "'can't do CEA VIC:%d\n",(uint16_t)VIC); | |
1582 | mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[mhl_edid_3d_data->parse_data.video_data_block_index]->short_descriptors[mhl_edid_3d_data->parse_data.vic_2d_index].VIC = 0; | |
1583 | } | |
1584 | } | |
1585 | } | |
1586 | DUMP_EDID_BLOCK(0,(PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE],EDID_BLOCK_SIZE) /* no semicolon needed here */ | |
1587 | } | |
1588 | ||
1589 | if ( mhl_edid_3d_data->parse_data.burst_entry_count_3d_vic >= p_write_burst_data->total_entries ) { | |
1590 | SET_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_VIC_DONE) | |
1591 | } | |
1592 | CheckForAll3DBurstDone(mhl_edid_3d_data); | |
1593 | } | |
1594 | } | |
1595 | ||
1596 | void check_3d_dtd_sequence_done(edid_3d_data_p mhl_edid_3d_data | |
1597 | ,PMHL2_video_format_data_t p_write_burst_data,uint8_t dtd_limit) | |
1598 | { | |
1599 | int flag=0; | |
1600 | if (mhl_edid_3d_data->parse_data.cea_861_dtd_index>= dtd_limit) { | |
1601 | flag = 1; | |
1602 | } | |
1603 | ||
1604 | if ( mhl_edid_3d_data->parse_data.burst_entry_count_3d_dtd >= p_write_burst_data->total_entries ) { | |
1605 | flag =1; | |
1606 | } | |
1607 | if (flag) { | |
1608 | SET_3D_FLAG(mhl_edid_3d_data, FLAGS_BURST_3D_DTD_DONE) | |
1609 | if (TEST_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_VIC_DONE)) { | |
1610 | if (!TEST_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_DONE)) { | |
1611 | si_mhl_tx_display_timing_enumeration_end(mhl_edid_3d_data); | |
1612 | } | |
1613 | } | |
1614 | } | |
1615 | } | |
1616 | ||
1617 | ||
1618 | void si_mhl_tx_process_3d_dtd_burst(void *context,PMHL2_video_format_data_t p_write_burst_data) | |
1619 | { | |
1620 | edid_3d_data_p mhl_edid_3d_data =(edid_3d_data_p)context; | |
1621 | PMHL2_video_descriptor_t p_mhl2_video_descriptor; | |
1622 | int burst_index=0; | |
1623 | uint8_t is_timing=0; | |
1624 | PCEA_extension_t p_CEA_extension = (PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE]; | |
1625 | uint8_t dtd_limit = (uint8_t)p_CEA_extension->version_u.version3.misc_support.total_number_detailed_timing_descriptors_in_entire_EDID; | |
1626 | ||
1627 | if ( mhl_edid_3d_data->parse_data.flags.parse_3d_in_progress) { | |
1628 | if (!TEST_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_DTD_VESA_DONE)) { | |
1629 | PEDID_block0_t p_EDID_block_0 = (PEDID_block0_t)&mhl_edid_3d_data->EDID_block_data[0]; | |
1630 | /* | |
1631 | up to four DTDs are possible in the base VESA EDID | |
1632 | this will be covered by a single burst. | |
1633 | */ | |
1634 | for (/* burst_index is set to zero above */ | |
1635 | ;(burst_index < p_write_burst_data->num_entries_this_burst) | |
1636 | && | |
1637 | (mhl_edid_3d_data->parse_data.burst_entry_count_3d_dtd < p_write_burst_data->total_entries ) | |
1638 | && | |
1639 | (mhl_edid_3d_data->parse_data.vesa_dtd_index < sizeof(p_EDID_block_0->detailed_timing_descriptors)/sizeof(p_EDID_block_0->detailed_timing_descriptors[0])) | |
1640 | ;++mhl_edid_3d_data->parse_data.vesa_dtd_index) { | |
1641 | P_18_byte_descriptor_u p_desc = (P_18_byte_descriptor_u)&p_EDID_block_0->detailed_timing_descriptors[mhl_edid_3d_data->parse_data.vesa_dtd_index]; | |
1642 | bool is_valid=0; | |
1643 | ||
1644 | p_mhl2_video_descriptor = &p_write_burst_data->video_descriptors[burst_index]; | |
1645 | is_valid = si_mhl_tx_parse_detailed_timing_descriptor( | |
1646 | mhl_edid_3d_data, p_desc, EDID_BLOCK_0, | |
1647 | &is_timing, p_mhl2_video_descriptor); | |
1648 | /* only count it if it's a valid timing */ | |
1649 | if (is_timing) { | |
1650 | ||
1651 | if (is_valid) { | |
1652 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1653 | "VESA DTD index: %d burst index:%d DTD SP "\ | |
1654 | "index:%d %s %s %s\n" | |
1655 | ,(uint16_t)mhl_edid_3d_data->parse_data.vesa_dtd_index,(uint16_t)burst_index,(uint16_t)mhl_edid_3d_data->parse_data.burst_entry_count_3d_dtd | |
1656 | ,p_mhl2_video_descriptor->left_right ?psz_left_right :psz_space | |
1657 | ,p_mhl2_video_descriptor->top_bottom ?psz_top_bottom :psz_space | |
1658 | ,p_mhl2_video_descriptor->frame_sequential?psz_frame_sequential:psz_space | |
1659 | ); | |
1660 | } else { | |
1661 | /* mark this mode for pruning by setting horizontal active to zero */ | |
1662 | p_desc->dtd.horz_active_7_0 = 0; | |
1663 | p_desc->dtd.horz_active_blanking_high.horz_active_11_8= 0; | |
1664 | } | |
1665 | ||
1666 | burst_index++; | |
1667 | mhl_edid_3d_data->parse_data.burst_entry_count_3d_dtd++; | |
1668 | } else { | |
1669 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1670 | "VESA DTD index: %d\n", | |
1671 | (uint16_t)mhl_edid_3d_data->parse_data.vesa_dtd_index); | |
1672 | } | |
1673 | } | |
1674 | ||
1675 | if (mhl_edid_3d_data->parse_data.vesa_dtd_index >= sizeof(p_EDID_block_0->detailed_timing_descriptors)/sizeof(p_EDID_block_0->detailed_timing_descriptors[0])) { | |
1676 | /* we got past the VESA DTDs in this burst */ | |
1677 | SET_3D_FLAG(mhl_edid_3d_data, FLAGS_BURST_3D_DTD_VESA_DONE) | |
1678 | } else { | |
1679 | check_3d_dtd_sequence_done(mhl_edid_3d_data,p_write_burst_data,dtd_limit); | |
1680 | /* more VESA DTDs to process in next burst */ | |
1681 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"%s\n",TEST_3D_FLAG(mhl_edid_3d_data,FLAGS_BURST_3D_DTD_DONE) | |
1682 | ?"3D DTD descriptors exhausted" | |
1683 | :"more VESA DTDs to process"); | |
1684 | return; | |
1685 | } | |
1686 | } | |
1687 | { | |
1688 | PCEA_extension_t p_CEA_extension = (PCEA_extension_t)&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE]; | |
1689 | uint8_t dtd_limit = (uint8_t)p_CEA_extension->version_u.version3.misc_support.total_number_detailed_timing_descriptors_in_entire_EDID; | |
1690 | union | |
1691 | { | |
1692 | uint8_t *puc_data_block; | |
1693 | P_18_byte_descriptor_u p_long_descriptors; | |
1694 | }p_data_u; | |
1695 | p_data_u.p_long_descriptors= (P_18_byte_descriptor_u)(((uint8_t *)p_CEA_extension) + p_CEA_extension->byte_offset_to_18_byte_descriptors); | |
1696 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context | |
1697 | ,"continuing with CEA-861-D/E DTDs" | |
1698 | "\n\tburst_index: %d" | |
1699 | "\n\tburst_entry_count_3d_dtd: %d" | |
1700 | "\n\tnum_entries_this_burst: %d" | |
1701 | "\n\ttotal_entries:%d" | |
1702 | "\n\tdtd_limit:%d" | |
1703 | "\n\toffsetTo18_byte_descriptors:0x%x\n" | |
1704 | ,burst_index | |
1705 | ,mhl_edid_3d_data->parse_data.burst_entry_count_3d_dtd | |
1706 | ,p_write_burst_data->num_entries_this_burst | |
1707 | ,p_write_burst_data->total_entries | |
1708 | ,dtd_limit | |
1709 | ,p_CEA_extension->byte_offset_to_18_byte_descriptors | |
1710 | ); | |
1711 | /* continue with CEA-861-D/E DTDs when done with VESA DTDs */ | |
1712 | for (/* burst_index is set to zero above */ | |
1713 | ;(burst_index < p_write_burst_data->num_entries_this_burst) | |
1714 | && | |
1715 | (mhl_edid_3d_data->parse_data.burst_entry_count_3d_dtd < p_write_burst_data->total_entries ) | |
1716 | && | |
1717 | (mhl_edid_3d_data->parse_data.cea_861_dtd_index < dtd_limit) | |
1718 | ;++mhl_edid_3d_data->parse_data.cea_861_dtd_index) { | |
1719 | P_18_byte_descriptor_u p_desc = &p_data_u.p_long_descriptors[mhl_edid_3d_data->parse_data.cea_861_dtd_index]; | |
1720 | bool is_valid=0; | |
1721 | p_mhl2_video_descriptor = &p_write_burst_data->video_descriptors[burst_index]; | |
1722 | is_valid=si_mhl_tx_parse_detailed_timing_descriptor(mhl_edid_3d_data,p_desc, EDID_BLOCK_2_3,&is_timing,p_mhl2_video_descriptor); | |
1723 | /* only count it if it's a valid timing */ | |
1724 | if (is_timing) { | |
1725 | ||
1726 | if (is_valid) { | |
1727 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1728 | "CEA-861 DTD index: %d burst index:%d DTD "\ | |
1729 | "SP index:%d %s %s %s\n\n" | |
1730 | ,(uint16_t)mhl_edid_3d_data->parse_data.cea_861_dtd_index,(uint16_t)burst_index,(uint16_t)mhl_edid_3d_data->parse_data.burst_entry_count_3d_dtd | |
1731 | ,p_mhl2_video_descriptor->left_right ?psz_left_right :psz_space | |
1732 | ,p_mhl2_video_descriptor->top_bottom ?psz_top_bottom :psz_space | |
1733 | ,p_mhl2_video_descriptor->frame_sequential?psz_frame_sequential:psz_space | |
1734 | ); | |
1735 | } else { | |
1736 | /* mark this mode for pruning by setting horizontal active to zero */ | |
1737 | p_desc->dtd.horz_active_7_0 = 0; | |
1738 | p_desc->dtd.horz_active_blanking_high.horz_active_11_8= 0; | |
1739 | } | |
1740 | ||
1741 | ++burst_index; | |
1742 | ++mhl_edid_3d_data->parse_data.burst_entry_count_3d_dtd; | |
1743 | } else { | |
1744 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1745 | "CEA-861 DTD index: %d\n", | |
1746 | (uint16_t)mhl_edid_3d_data->parse_data.vesa_dtd_index); | |
1747 | } | |
1748 | } | |
1749 | ||
1750 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1751 | "DTD burst complete\n"); | |
1752 | check_3d_dtd_sequence_done(mhl_edid_3d_data,p_write_burst_data,dtd_limit); | |
1753 | } | |
1754 | } | |
1755 | } | |
1756 | ||
1757 | ||
1758 | /* | |
1759 | ||
1760 | FUNCTION : si_mhl_tx_parse_established_timing() | |
1761 | ||
1762 | PURPOSE : Parse the established timing section of EDID Block 0 and | |
1763 | print their decoded meaning to the screen. | |
1764 | ||
1765 | INPUT PARAMS : Pointer to the array where the data read from EDID | |
1766 | Block0 is stored. | |
1767 | ||
1768 | OUTPUT PARAMS: None | |
1769 | ||
1770 | GLOBALS USED : None | |
1771 | ||
1772 | RETURNS : Void | |
1773 | ||
1774 | */ | |
1775 | ||
1776 | #define STRINGIZE(x) #x | |
1777 | #define DUMP_OFFSET(c,s,m) MHL_TX_EDID_INFO(c->dev_context, STRINGIZE(m)" offset:%x\n",SII_OFFSETOF(s,m) ); | |
1778 | #define DUMP_ESTABLISHED_TIMING(context,group,width,height,refresh,progressive) \ | |
1779 | if (p_EDID_block_0->group.et##width##x##height##_##refresh##Hz##progressive) { \ | |
1780 | MHL_TX_EDID_INFO(context->dev_context, STRINGIZE(group)"."STRINGIZE(width)"x"STRINGIZE(height)"_"STRINGIZE(refresh)"Hz"STRINGIZE(progressive)"\n"); \ | |
1781 | if (!is_MHL_timing_mode(mhl_edid_3d_data,width, height, refresh*1000,NULL,0)) { \ | |
1782 | p_EDID_block_0->group.et##width##x##height##_##refresh##Hz##progressive = 0; \ | |
1783 | } \ | |
1784 | } | |
1785 | ||
1786 | static void si_mhl_tx_parse_established_timing (edid_3d_data_p mhl_edid_3d_data,PEDID_block0_t p_EDID_block_0) | |
1787 | { | |
1788 | ||
1789 | ||
1790 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,header_data[0]); | |
1791 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,id_manufacturer_name); | |
1792 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,id_product_code); | |
1793 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,serial_number[0]); | |
1794 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,week_of_manufacture); | |
1795 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,year_of_manufacture); | |
1796 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,EDID_version); | |
1797 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,EDID_revision); | |
1798 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,video_input_definition); | |
1799 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,horz_screen_size_or_aspect_ratio); | |
1800 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,vert_screen_size_or_aspect_ratio); | |
1801 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,display_transfer_characteristic); | |
1802 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,feature_support); | |
1803 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,red_green_bits_1_0); | |
1804 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,blue_white_bits_1_0); | |
1805 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,red_x); | |
1806 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,red_y); | |
1807 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,green_x); | |
1808 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,green_y); | |
1809 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,blue_x); | |
1810 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,blue_y); | |
1811 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,white_x); | |
1812 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,white_y); | |
1813 | ||
1814 | /* MHL cannot support these modes, so prune them */ | |
1815 | p_EDID_block_0->established_timings_II.et1280x1024_75Hz = 0; | |
1816 | p_EDID_block_0->manufacturers_timings.et1152x870_75Hz = 0; | |
1817 | ||
1818 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1819 | "Parsing Established Timing:\n"); | |
1820 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1821 | "===========================\n"); | |
1822 | ||
1823 | ||
1824 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,established_timings_I) /* no semicolon needed here ... ... see macro */ | |
1825 | /* Parse Established Timing Byte #0 */ | |
1826 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_I,720,400,70,) | |
1827 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_I,720,400,88,) | |
1828 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_I,640,480,60,) | |
1829 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_I,640,480,67,) | |
1830 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_I,640,480,72,) | |
1831 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_I,640,480,75,) | |
1832 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_I,800,600,56,) | |
1833 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_I,800,600,60,) | |
1834 | ||
1835 | /* Parse Established Timing Byte #1: */ | |
1836 | ||
1837 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,established_timings_II) /* no semicolon needed here ... ... see macro */ | |
1838 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_II, 800, 600,72,) | |
1839 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_II, 800, 600,75,) | |
1840 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_II, 832, 624,75,) | |
1841 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_II,1024, 768,87,I) | |
1842 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_II,1024, 768,60,) | |
1843 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_II,1024, 768,70,) | |
1844 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_II,1024, 768,75,) | |
1845 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, established_timings_II,1280,1024,75,) | |
1846 | ||
1847 | /* Parse Established Timing Byte #2: */ | |
1848 | ||
1849 | DUMP_OFFSET(mhl_edid_3d_data, EDID_block0_t,manufacturers_timings) /* no semicolon needed here ... ... see macro */ | |
1850 | DUMP_ESTABLISHED_TIMING(mhl_edid_3d_data, manufacturers_timings,1152,870,75,) | |
1851 | ||
1852 | if( (!p_EDID_block_0->header_data[0]) | |
1853 | &&(0 == *((uint8_t *)&p_EDID_block_0->established_timings_II) ) | |
1854 | &&(!p_EDID_block_0->header_data[2]) | |
1855 | ) { | |
1856 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1857 | "No established video modes\n"); | |
1858 | } | |
1859 | } | |
1860 | /* | |
1861 | ||
1862 | FUNCTION : si_mhl_tx_parse_standard_timing() | |
1863 | ||
1864 | PURPOSE : Parse the standard timing section of EDID Block 0 and | |
1865 | print their decoded meaning to the screen. | |
1866 | ||
1867 | INPUT PARAMS : Pointer to the array where the data read from EDID | |
1868 | Block0 is stored. | |
1869 | ||
1870 | OUTPUT PARAMS: None | |
1871 | ||
1872 | GLOBALS USED : None | |
1873 | ||
1874 | RETURNS : Void | |
1875 | ||
1876 | */ | |
1877 | ||
1878 | static void si_mhl_tx_parse_standard_timing(edid_3d_data_p mhl_edid_3d_data,PEDID_block0_t p_EDID_block_0) | |
1879 | { | |
1880 | uint8_t i; | |
1881 | uint8_t AR_code; | |
1882 | ||
1883 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, "Parsing Standard Timing:\n"); | |
1884 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, "========================\n"); | |
1885 | ||
1886 | for (i = 0; i < sizeof(p_EDID_block_0->standard_timings)/sizeof(p_EDID_block_0->standard_timings[0]); i += 2) { | |
1887 | if ( | |
1888 | (1 == p_EDID_block_0->standard_timings[i].horz_pix_div_8_minus_31) | |
1889 | && (1 == p_EDID_block_0->standard_timings[i].field_refresh_rate_minus_60) | |
1890 | && (0 == p_EDID_block_0->standard_timings[i].image_aspect_ratio) | |
1891 | ) { | |
1892 | /* per VESA EDID standard, Release A, Revision 1, February 9, 2000, Sec. 3.9 */ | |
1893 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1894 | "Standard Timing Undefined\n"); | |
1895 | } else { | |
1896 | uint16_t horz_active=(uint16_t)((p_EDID_block_0->standard_timings[i].horz_pix_div_8_minus_31 + 31)*8); | |
1897 | uint16_t vert_active=0; | |
1898 | uint16_t refresh_rate_in_milliHz = (uint16_t)(p_EDID_block_0->standard_timings[i].field_refresh_rate_minus_60+ 60)*1000; | |
1899 | char *psz_ratio_string=""; | |
1900 | ||
1901 | /* per VESA EDID standard, Release A, Revision 1, February 9, 2000, Table 3.15 */ | |
1902 | AR_code = p_EDID_block_0->standard_timings[i].image_aspect_ratio; | |
1903 | ||
1904 | switch(AR_code) | |
1905 | { | |
1906 | case iar_16_to_10: | |
1907 | psz_ratio_string = "16:10"; | |
1908 | vert_active = horz_active * 10/16; | |
1909 | break; | |
1910 | ||
1911 | case iar_4_to_3: | |
1912 | psz_ratio_string = "4:3"; | |
1913 | vert_active = horz_active * 3/ 4; | |
1914 | break; | |
1915 | ||
1916 | case iar_5_to_4: | |
1917 | psz_ratio_string = "5:4"; | |
1918 | vert_active = horz_active * 4/ 5; | |
1919 | break; | |
1920 | ||
1921 | case iar_16_to_9: | |
1922 | psz_ratio_string = "16:9"; | |
1923 | vert_active = horz_active * 9/16; | |
1924 | break; | |
1925 | } | |
1926 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1927 | "Aspect Ratio: %5s %4d x %4d at %3d Hz.\n", | |
1928 | psz_ratio_string, horz_active,vert_active, | |
1929 | refresh_rate_in_milliHz); | |
1930 | ||
1931 | if (!is_MHL_timing_mode(mhl_edid_3d_data,horz_active, vert_active, refresh_rate_in_milliHz,NULL,0)) { | |
1932 | /* disable this mode */ | |
1933 | p_EDID_block_0->standard_timings[i].horz_pix_div_8_minus_31 = 1; | |
1934 | p_EDID_block_0->standard_timings[i].field_refresh_rate_minus_60 = 1; | |
1935 | p_EDID_block_0->standard_timings[i].image_aspect_ratio = 0; | |
1936 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1937 | "Disabled\n\n"); | |
1938 | } | |
1939 | } | |
1940 | } | |
1941 | } | |
1942 | ||
1943 | ||
1944 | /* | |
1945 | ||
1946 | FUNCTION : si_mhl_tx_parse_block_zero_timing_descriptors() | |
1947 | ||
1948 | PURPOSE : Parse EDID Block 0 timing descriptors per EEDID 1.3 | |
1949 | standard. printf() values to screen. | |
1950 | ||
1951 | INPUT PARAMS : Pointer to the 128 byte array where the data read from EDID | |
1952 | Block0 is stored. | |
1953 | ||
1954 | OUTPUT PARAMS: None | |
1955 | ||
1956 | GLOBALS USED : None | |
1957 | ||
1958 | RETURNS : Void | |
1959 | ||
1960 | */ | |
1961 | #if 0 | |
1962 | static void si_mhl_tx_parse_block_zero_timing_descriptors(edid_3d_data_p mhl_edid_3d_data,PEDID_block0_t p_EDID_block_0) | |
1963 | { | |
1964 | uint8_t i; | |
1965 | uint8_t is_timing=0; | |
1966 | si_mhl_tx_parse_established_timing(mhl_edid_3d_data,p_EDID_block_0); | |
1967 | si_mhl_tx_parse_standard_timing(mhl_edid_3d_data,p_EDID_block_0); | |
1968 | ||
1969 | for (i = 0; i < sizeof(p_EDID_block_0->detailed_timing_descriptors)/sizeof(p_EDID_block_0->detailed_timing_descriptors[0]); i++) { | |
1970 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1971 | "Parse Results, EDID Block #0, Detailed Descriptor Number %d:\n", | |
1972 | (int)i); | |
1973 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
1974 | "===========================================================\n\n"); | |
1975 | si_mhl_tx_parse_detailed_timing_descriptor(mhl_edid_3d_data,(P_18_byte_descriptor_u)&p_EDID_block_0->detailed_timing_descriptors[i], EDID_BLOCK_0,&is_timing,NULL); | |
1976 | } | |
1977 | } | |
1978 | #endif | |
1979 | /* | |
1980 | ||
1981 | FUNCTION : bool si_mhl_tx_do_edid_checksum() | |
1982 | ||
1983 | PURPOSE : Calculte checksum of the 128 byte block pointed to by the | |
1984 | pointer passed as parameter | |
1985 | ||
1986 | INPUT PARAMS : Pointer to a 128 byte block whose checksum needs to be | |
1987 | calculated | |
1988 | ||
1989 | OUTPUT PARAMS: None | |
1990 | ||
1991 | GLOBALS USED : None | |
1992 | ||
1993 | RETURNS : true if chcksum is 0. false if not. | |
1994 | ||
1995 | */ | |
1996 | ||
1997 | static bool si_mhl_tx_do_edid_checksum(uint8_t *p_EDID_block_data) | |
1998 | { | |
1999 | uint8_t i; | |
2000 | uint8_t checksum = 0; | |
2001 | ||
2002 | for (i = 0; i < EDID_BLOCK_SIZE; i++) { | |
2003 | checksum += p_EDID_block_data[i]; | |
2004 | } | |
2005 | ||
2006 | if (checksum) { | |
2007 | return false; | |
2008 | } | |
2009 | ||
2010 | return true; | |
2011 | } | |
2012 | ||
2013 | ||
2014 | /* | |
2015 | ||
2016 | FUNCTION : bool si_mhl_tx_check_edid_header() | |
2017 | ||
2018 | PURPOSE : Checks if EDID header is correct per VESA E-EDID standard | |
2019 | Must be 00 FF FF FF FF FF FF 00 | |
2020 | ||
2021 | INPUT PARAMS : Pointer to EDID parser context area | |
2022 | Pointer to 1st EDID block | |
2023 | ||
2024 | OUTPUT PARAMS: None | |
2025 | ||
2026 | GLOBALS USED : None | |
2027 | ||
2028 | RETURNS : true if Header is correct. false if not. | |
2029 | ||
2030 | */ | |
2031 | ||
2032 | ||
2033 | /* Block 0 */ | |
2034 | #define EDID_OFFSET_HEADER_FIRST_00 0x00 | |
2035 | #define EDID_OFFSET_HEADER_FIRST_FF 0x01 | |
2036 | #define EDID_OFFSET_HEADER_LAST_FF 0x06 | |
2037 | #define EDID_OFFSET_HEADER_LAST_00 0x07 | |
2038 | static bool si_mhl_tx_check_edid_header(edid_3d_data_p mhl_edid_3d_data, | |
2039 | PEDID_block0_t p_EDID_block_0) | |
2040 | { | |
2041 | uint8_t i = 0; | |
2042 | ||
2043 | if (0 != p_EDID_block_0->header_data[EDID_OFFSET_HEADER_FIRST_00]) { | |
2044 | DUMP_EDID_BLOCK(1,p_EDID_block_0,sizeof(*p_EDID_block_0)) | |
2045 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context | |
2046 | ,"EDID 0 first check failed\n\n\n"); | |
2047 | return false; | |
2048 | } | |
2049 | ||
2050 | for (i = EDID_OFFSET_HEADER_FIRST_FF; i <= EDID_OFFSET_HEADER_LAST_FF; i++) { | |
2051 | if(0xFF != p_EDID_block_0->header_data[i]) { | |
2052 | DUMP_EDID_BLOCK(1,p_EDID_block_0,sizeof(*p_EDID_block_0)) | |
2053 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context | |
2054 | ,"EDID -1 check failed\n"); | |
2055 | return false; | |
2056 | } | |
2057 | } | |
2058 | ||
2059 | if (0x00 != p_EDID_block_0->header_data[EDID_OFFSET_HEADER_LAST_00]) { | |
2060 | DUMP_EDID_BLOCK(1,p_EDID_block_0,sizeof(*p_EDID_block_0)) | |
2061 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context | |
2062 | ,"EDID 0 last check failed\n"); | |
2063 | return false; | |
2064 | } | |
2065 | ||
2066 | return true; | |
2067 | } | |
2068 | ||
2069 | ||
2070 | ||
2071 | void SiiMhlTxMakeItDVI(edid_3d_data_p mhl_edid_3d_data,PEDID_block0_t p_EDID_block_0) | |
2072 | { | |
2073 | /* Make it DVI */ | |
2074 | mhl_edid_3d_data->parse_data.HDMI_sink = false; | |
2075 | { | |
2076 | uint8_t *p_EDID_block_data =(uint8_t *)p_EDID_block_0; | |
2077 | uint8_t counter; | |
2078 | ||
2079 | p_EDID_block_0->extension_flag = 0; | |
2080 | ||
2081 | // blank out the second block of the upstream EDID | |
2082 | MHL_TX_DBG_INFO(mhl_edid_3d_data->dev_context, | |
2083 | "DVI EDID ...Setting second block to 0xFF %d\n", | |
2084 | (uint16_t)EDID_REV_ADDR_ERROR); | |
2085 | p_EDID_block_data += EDID_BLOCK_SIZE; | |
2086 | for (counter = 0; counter < EDID_BLOCK_SIZE; counter++) | |
2087 | p_EDID_block_data[counter] = 0xFF; | |
2088 | } | |
2089 | ||
2090 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context | |
2091 | ,"EDID: second block now all 0xFF\n"); | |
2092 | } | |
2093 | ||
2094 | #if 0 | |
2095 | static void SiiMhlTx3dReqForNonTranscodeMode( edid_3d_data_p mhl_edid_3d_data ) | |
2096 | { | |
2097 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2098 | "Mhl2Tx: outputMode: %s\n", | |
2099 | mhl_edid_3d_data->parse_data.HDMI_sink ? "HDMI":"DVI"); | |
2100 | if (mhl_edid_3d_data->parse_data.HDMI_sink) { | |
2101 | if (0x20 <= si_get_peer_mhl_version(mhl_edid_3d_data->dev_context)) { | |
2102 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2103 | "MHL 2.x sink detected\n"); | |
2104 | ||
2105 | mhl_edid_3d_data->parse_data.flags.parse_3d_in_progress = 1; | |
2106 | display_timing_enumeration_begin(mhl_edid_3d_data); | |
2107 | /* tell the sink to begin sending 3D write bursts */ | |
2108 | si_mhl_tx_set_int( mhl_edid_3d_data->dev_context,MHL_RCHANGE_INT, MHL2_INT_3D_REQ,0); | |
2109 | ||
2110 | mhl_edid_3d_data->parse_data.video_data_block_index=0; | |
2111 | mhl_edid_3d_data->parse_data.burst_entry_count_3d_dtd=0; | |
2112 | mhl_edid_3d_data->parse_data.vesa_dtd_index=0; | |
2113 | mhl_edid_3d_data->parse_data.burst_entry_count_3d_vic=0; | |
2114 | mhl_edid_3d_data->parse_data.vic_2d_index=0; | |
2115 | mhl_edid_3d_data->parse_data.vic_3d_index=0; | |
2116 | mhl_edid_3d_data->parse_data.cea_861_dtd_index=0; | |
2117 | ||
2118 | SET_3D_FLAG(mhl_edid_3d_data, FLAGS_SENT_3D_REQ) | |
2119 | CLR_3D_FLAG(mhl_edid_3d_data, FLAGS_BURST_3D_DONE) | |
2120 | CLR_3D_FLAG(mhl_edid_3d_data, FLAGS_BURST_3D_VIC_DONE) | |
2121 | CLR_3D_FLAG(mhl_edid_3d_data, FLAGS_BURST_3D_DTD_VESA_DONE) | |
2122 | } else { | |
2123 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2124 | "MHL 1.x sink detected\n"); | |
2125 | ||
2126 | // EDID read need to be done in SW TPI mode, as it is done now, switch back to default TPI mode: HW TPI mode | |
2127 | si_mhl_tx_drv_set_hw_tpi_mode( mhl_edid_3d_data->drv_context, true ); | |
2128 | #ifdef PRUNE_EDID | |
2129 | si_mhl_tx_prune_edid(mhl_edid_3d_data); | |
2130 | #else | |
2131 | SET_3D_FLAG(mhl_edid_3d_data,FLAGS_EDID_READ_DONE) | |
2132 | si_mhl_tx_drv_enable_video_path(mhl_edid_3d_data->drv_context); // //TODO: FD, TBI, debug? | |
2133 | #endif | |
2134 | ||
2135 | } | |
2136 | } else { | |
2137 | #ifndef EDID_PASSTHROUGH //( | |
2138 | if (0 == si_mhl_tx_drv_set_upstream_edid(mhl_edid_3d_data->drv_context,mhl_edid_3d_data->EDID_block_data,2*EDID_BLOCK_SIZE)) | |
2139 | #endif //) | |
2140 | { | |
2141 | // EDID read need to be done in SW TPI mode, as it is done now, switch back to default TPI mode: HW TPI mode | |
2142 | si_mhl_tx_drv_set_hw_tpi_mode( mhl_edid_3d_data->drv_context, true ); | |
2143 | ||
2144 | SET_3D_FLAG(mhl_edid_3d_data, FLAGS_EDID_READ_DONE); | |
2145 | si_mhl_tx_drv_enable_video_path(mhl_edid_3d_data->drv_context); // TODO: FD, TBI, debug? | |
2146 | } | |
2147 | } | |
2148 | } | |
2149 | #endif | |
2150 | ||
2151 | ||
2152 | uint8_t CA=0;//Channel/Speaker Allocation. | |
2153 | uint8_t MAX_channel=2;//Channel. | |
2154 | uint8_t Samplebit; | |
2155 | ||
2156 | uint8_t Cap_MAX_channel; | |
2157 | uint8_t Cap_Samplebit; | |
2158 | uint16_t Cap_SampleRate; | |
2159 | static uint8_t parse_861_short_descriptors ( | |
2160 | edid_3d_data_p mhl_edid_3d_data | |
2161 | , uint8_t *p_EDID_block_data) | |
2162 | { | |
2163 | uint8_t i; | |
2164 | PCEA_extension_t p_CEA_extension = (PCEA_extension_t)p_EDID_block_data; | |
2165 | ||
2166 | if (EDID_EXTENSION_TAG != p_CEA_extension->tag) { | |
2167 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context, | |
2168 | "EDID -> Non-CEA Extension\n"); | |
2169 | return EDID_EXT_TAG_ERROR; | |
2170 | } else { | |
2171 | if (EDID_REV_THREE != p_CEA_extension->revision) { | |
2172 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context, | |
2173 | "EDID -> Non-HDMI EIA-861 Revision ID. Expected %02X. Got %02X\n", | |
2174 | (int)EDID_REV_THREE, (int)p_CEA_extension->revision); | |
2175 | return EDID_REV_ADDR_ERROR; | |
2176 | } else { | |
2177 | PCEA_extension_version_3_t p_CEA_extension_version_3 = &p_CEA_extension->version_u.version3; | |
2178 | union | |
2179 | { | |
2180 | uint8_t *puc_data_block; | |
2181 | PCEA_data_block_collection_t p_CEA_data_block; | |
2182 | }p_data_u; | |
2183 | uint8_t *puc_long_descriptors; | |
2184 | /* block offset where long descriptors start */ | |
2185 | puc_long_descriptors= ((uint8_t *)p_CEA_extension) + p_CEA_extension->byte_offset_to_18_byte_descriptors; | |
2186 | ||
2187 | /* byte #3 of CEA extension version 3 */ | |
2188 | mhl_edid_3d_data->parse_data.underscan = p_CEA_extension_version_3->misc_support.underscan_IT_formats_by_default?1:0; | |
2189 | mhl_edid_3d_data->parse_data.basic_audio = p_CEA_extension_version_3->misc_support.basic_audio_support?1:0; | |
2190 | mhl_edid_3d_data->parse_data.YCbCr_4_4_4 = p_CEA_extension_version_3->misc_support.YCrCb444_support; | |
2191 | mhl_edid_3d_data->parse_data.YCbCr_4_2_2 = p_CEA_extension_version_3->misc_support.YCrCb422_support; | |
2192 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2193 | "misc support index-> %02x\n", | |
2194 | *((uint8_t *)&p_CEA_extension_version_3->misc_support) ); | |
2195 | ||
2196 | #ifdef NEVER | |
2197 | /* choose output color depth in order of preference */ | |
2198 | if (mhl_edid_3d_data->parse_data.YCbCr_4_4_4) { | |
2199 | si_mhl_tx_drv_set_output_color_space( mhl_edid_3d_data->drv_context,BIT_EDID_FIELD_FORMAT_YCbCr444 ); | |
2200 | } else if (mhl_edid_3d_data->parse_data.YCbCr_4_2_2) { | |
2201 | si_mhl_tx_drv_set_output_color_space( mhl_edid_3d_data->drv_context,BIT_EDID_FIELD_FORMAT_YCbCr422 ); | |
2202 | } else { | |
2203 | si_mhl_tx_drv_set_output_color_space( mhl_edid_3d_data->drv_context,BIT_EDID_FIELD_FORMAT_HDMI_TO_RGB); | |
2204 | } | |
2205 | #endif // NEVER | |
2206 | ||
2207 | p_data_u.puc_data_block = &p_CEA_extension->version_u.version3.Offset4_u.data_block_collection[0]; | |
2208 | ||
2209 | while (p_data_u.puc_data_block < puc_long_descriptors) { | |
2210 | data_block_tag_code_e tag_code; | |
2211 | uint8_t data_block_length; | |
2212 | tag_code = p_data_u.p_CEA_data_block->header.fields.tag_code; | |
2213 | data_block_length = p_data_u.p_CEA_data_block->header.fields.length_following_header; | |
2214 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2215 | "tag_code:%d data_block_length:%d\n", | |
2216 | tag_code,data_block_length); | |
2217 | if (( p_data_u.puc_data_block + data_block_length) > puc_long_descriptors) { | |
2218 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context, | |
2219 | "EDID -> V Descriptor Overflow\n"); | |
2220 | return EDID_V_DESCR_OVERFLOW; | |
2221 | } | |
2222 | ||
2223 | i = 0; /* num of short video descriptors in current data block */ | |
2224 | ||
2225 | switch (tag_code) | |
2226 | { | |
2227 | case DBTC_VIDEO_DATA_BLOCK: | |
2228 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2229 | "DBTC_VIDEO_DATA_BLOCK:\n"); | |
2230 | if (mhl_edid_3d_data->parse_data.num_video_data_blocks < NUM_VIDEO_DATA_BLOCKS_LIMIT) { | |
2231 | mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[mhl_edid_3d_data->parse_data.num_video_data_blocks] = (p_video_data_block_t)p_data_u.puc_data_block; | |
2232 | ||
2233 | /* each SVD is 1 byte long */ | |
2234 | while (i < data_block_length) { | |
2235 | uint8_t VIC; | |
2236 | VIC = mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[mhl_edid_3d_data->parse_data.num_video_data_blocks]->short_descriptors[i].VIC; | |
2237 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2238 | "short desc[%d]: VIC: %d\n",i,VIC); | |
2239 | // update_av_info_edid(true, VIC, 0); | |
2240 | mhl_event_notify(mhl_edid_3d_data->dev_context, MHL_TX_EVENT_EDID_UPDATE, VIC, NULL); | |
2241 | ||
2242 | if (!IsQualifiedMhlVIC(mhl_edid_3d_data,VIC,NULL)) { | |
2243 | mhl_edid_3d_data->parse_data.p_video_data_blocks_2d[mhl_edid_3d_data->parse_data.num_video_data_blocks]->short_descriptors[i].VIC = 0; | |
2244 | } | |
2245 | i++; | |
2246 | } | |
2247 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2248 | "EDID -> %d descriptors in Short Descriptor Video Block\n",i); | |
2249 | mhl_edid_3d_data->parse_data.num_video_data_blocks++; | |
2250 | } | |
2251 | break; | |
2252 | ||
2253 | case DBTC_AUDIO_DATA_BLOCK: | |
2254 | { | |
2255 | Paudio_data_block_t p_audio_data_block = (Paudio_data_block_t) p_data_u.puc_data_block; | |
2256 | uint8_t A_descriptor_index = 0; | |
2257 | uint8_t AudioFormatCode; | |
2258 | while (i < data_block_length/sizeof(p_audio_data_block->short_audio_descriptors[0]) ) { | |
2259 | mhl_edid_3d_data->parse_data.audio_descriptors[A_descriptor_index] | |
2260 | = p_audio_data_block->short_audio_descriptors[i]; | |
2261 | ||
2262 | pr_info("\n(uint8_t)p_audio_data_block->short_audio_descriptors[%d].max_channels_minus_one: %d",i,(uint8_t)p_audio_data_block->short_audio_descriptors[i].max_channels_minus_one); | |
2263 | ||
2264 | AudioFormatCode =p_audio_data_block->short_audio_descriptors[i].audio_format_code; | |
2265 | pr_info("\nAudio Format Code %i",(int)AudioFormatCode); | |
2266 | switch (AudioFormatCode){ | |
2267 | case 1: pr_info("Liniar PCM"); break; | |
2268 | case 2: pr_info("AC-3"); break; | |
2269 | case 3: pr_info("MPEG-1"); break; | |
2270 | case 4: pr_info("MP3"); break; | |
2271 | case 5: pr_info("MPEG2"); break; | |
2272 | case 6: pr_info("ACC"); break; | |
2273 | case 7: pr_info("DTS"); break; | |
2274 | case 8: pr_info("ATRAC"); break; | |
2275 | default: pr_info("reserved"); | |
2276 | } | |
2277 | if(AudioFormatCode==1){ | |
2278 | MAX_channel=(uint8_t)p_audio_data_block->short_audio_descriptors[i].max_channels_minus_one+1; | |
2279 | pr_info("\nMax N of channels %d",MAX_channel); | |
2280 | pr_info("\nFs: "); | |
2281 | ||
2282 | if(MAX_channel>2){ | |
2283 | MAX_channel=8; | |
2284 | Cap_MAX_channel = HDMI_CHANNEL_8; | |
2285 | /* | |
2286 | if(p_audio_data_block->short_audio_descriptors[i].freq_32_Khz){ | |
2287 | pr_info(" AUDIO_32K_8CH"); | |
2288 | siHdmiTx_AudioSel(AUDIO_32K_8CH); | |
2289 | } | |
2290 | else if(p_audio_data_block->short_audio_descriptors[i].freq_44_1_KHz){ | |
2291 | pr_info(" AUDIO_44K_8CH"); | |
2292 | siHdmiTx_AudioSel(AUDIO_44K_8CH); | |
2293 | } | |
2294 | else if(p_audio_data_block->short_audio_descriptors[i].freq_48_KHz){ | |
2295 | pr_info(" AUDIO_48K_8CH "); | |
2296 | siHdmiTx_AudioSel(AUDIO_48K_8CH); | |
2297 | } | |
2298 | else if(p_audio_data_block->short_audio_descriptors[i].freq_96_KHz){ | |
2299 | pr_info(" AUDIO_96K_8CH"); | |
2300 | siHdmiTx_AudioSel(AUDIO_96K_8CH); | |
2301 | } | |
2302 | else if(p_audio_data_block->short_audio_descriptors[i].freq_192_KHz){ | |
2303 | pr_info(" AUDIO_192K_8CH "); | |
2304 | siHdmiTx_AudioSel(AUDIO_192K_8CH); | |
2305 | Cap_SampleRate = 192; | |
2306 | } | |
2307 | */ | |
2308 | if(p_audio_data_block->short_audio_descriptors[i].freq_32_Khz){ | |
2309 | pr_info(" AUDIO_32K_8CH"); | |
2310 | siHdmiTx_AudioSel(AUDIO_32K_8CH); | |
2311 | Cap_SampleRate = HDMI_SAMPLERATE_32; | |
2312 | } | |
2313 | if(p_audio_data_block->short_audio_descriptors[i].freq_44_1_KHz){ | |
2314 | pr_info(" AUDIO_44K_8CH"); | |
2315 | siHdmiTx_AudioSel(AUDIO_44K_8CH); | |
2316 | Cap_SampleRate = HDMI_SAMPLERATE_44; | |
2317 | } | |
2318 | if(p_audio_data_block->short_audio_descriptors[i].freq_48_KHz){ | |
2319 | pr_info(" AUDIO_48K_8CH "); | |
2320 | Cap_SampleRate = HDMI_SAMPLERATE_48; | |
2321 | siHdmiTx_AudioSel(AUDIO_48K_8CH); | |
2322 | } | |
2323 | if(p_audio_data_block->short_audio_descriptors[i].freq_96_KHz){ | |
2324 | pr_info(" AUDIO_96K_8CH"); | |
2325 | siHdmiTx_AudioSel(AUDIO_96K_8CH); | |
2326 | Cap_SampleRate = HDMI_SAMPLERATE_96; | |
2327 | } | |
2328 | if(p_audio_data_block->short_audio_descriptors[i].freq_192_KHz){ | |
2329 | pr_info(" AUDIO_192K_8CH "); | |
2330 | siHdmiTx_AudioSel(AUDIO_192K_8CH); | |
2331 | Cap_SampleRate = HDMI_SAMPLERATE_192; | |
2332 | } | |
2333 | } | |
2334 | else{ | |
2335 | MAX_channel=2; | |
2336 | Cap_MAX_channel = HDMI_CHANNEL_2; | |
2337 | /* | |
2338 | if(p_audio_data_block->short_audio_descriptors[i].freq_32_Khz){ | |
2339 | pr_info(" AUDIO_32K_2CH"); | |
2340 | siHdmiTx_AudioSel(AUDIO_32K_2CH); | |
2341 | } | |
2342 | else if(p_audio_data_block->short_audio_descriptors[i].freq_44_1_KHz){ | |
2343 | pr_info(" AUDIO_44K_2CH"); | |
2344 | siHdmiTx_AudioSel(AUDIO_44K_2CH); | |
2345 | } | |
2346 | else if(p_audio_data_block->short_audio_descriptors[i].freq_48_KHz){ | |
2347 | pr_info(" AUDIO_48K_2CH "); | |
2348 | siHdmiTx_AudioSel(AUDIO_48K_2CH); | |
2349 | } | |
2350 | else if(p_audio_data_block->short_audio_descriptors[i].freq_96_KHz){ | |
2351 | pr_info(" AUDIO_96K_2CH"); | |
2352 | siHdmiTx_AudioSel(AUDIO_96K_2CH); | |
2353 | } | |
2354 | else if(p_audio_data_block->short_audio_descriptors[i].freq_192_KHz){ | |
2355 | pr_info(" AUDIO_192K_2CH "); | |
2356 | siHdmiTx_AudioSel(AUDIO_192K_2CH); | |
2357 | } | |
2358 | */ | |
2359 | if(p_audio_data_block->short_audio_descriptors[i].freq_32_Khz){ | |
2360 | pr_info(" AUDIO_32K_2CH"); | |
2361 | siHdmiTx_AudioSel(AUDIO_32K_2CH); | |
2362 | Cap_SampleRate = HDMI_SAMPLERATE_32; | |
2363 | } | |
2364 | if(p_audio_data_block->short_audio_descriptors[i].freq_44_1_KHz){ | |
2365 | pr_info(" AUDIO_44K_2CH"); | |
2366 | siHdmiTx_AudioSel(AUDIO_44K_2CH); | |
2367 | Cap_SampleRate = HDMI_SAMPLERATE_44; | |
2368 | } | |
2369 | if(p_audio_data_block->short_audio_descriptors[i].freq_48_KHz){ | |
2370 | pr_info(" AUDIO_48K_2CH "); | |
2371 | siHdmiTx_AudioSel(AUDIO_48K_2CH); | |
2372 | Cap_SampleRate = HDMI_SAMPLERATE_48; | |
2373 | } | |
2374 | if(p_audio_data_block->short_audio_descriptors[i].freq_96_KHz){ | |
2375 | pr_info(" AUDIO_96K_2CH"); | |
2376 | siHdmiTx_AudioSel(AUDIO_96K_2CH); | |
2377 | Cap_SampleRate = HDMI_SAMPLERATE_96; | |
2378 | } | |
2379 | if(p_audio_data_block->short_audio_descriptors[i].freq_192_KHz){ | |
2380 | pr_info(" AUDIO_192K_2CH "); | |
2381 | siHdmiTx_AudioSel(AUDIO_192K_2CH); | |
2382 | Cap_SampleRate = HDMI_SAMPLERATE_192; | |
2383 | } | |
2384 | } | |
2385 | if(AudioFormatCode == 1){ | |
2386 | pr_info("Supported length: "); | |
2387 | ||
2388 | if(p_audio_data_block->short_audio_descriptors[i].byte3.audio_code_1_LPCM.res_16_bit){ | |
2389 | pr_info("16bits "); | |
2390 | Samplebit=16; | |
2391 | Cap_Samplebit = HDMI_BITWIDTH_16; | |
2392 | } | |
2393 | if(p_audio_data_block->short_audio_descriptors[i].byte3.audio_code_1_LPCM.res_20_bit){ | |
2394 | pr_info("20 "); | |
2395 | Samplebit=20; | |
2396 | Cap_Samplebit = HDMI_BITWIDTH_20; | |
2397 | } | |
2398 | if(p_audio_data_block->short_audio_descriptors[i].byte3.audio_code_1_LPCM.res_24_bit){ | |
2399 | pr_info("24bits "); | |
2400 | Samplebit=24; | |
2401 | Cap_Samplebit = HDMI_BITWIDTH_24; | |
2402 | } | |
2403 | pr_info("\n"); | |
2404 | } | |
2405 | } | |
2406 | A_descriptor_index++; | |
2407 | i++; | |
2408 | } | |
2409 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2410 | "EDID -> Short Descriptor Audio Block\n"); | |
2411 | } | |
2412 | break; | |
2413 | ||
2414 | case DBTC_SPEAKER_ALLOCATION_DATA_BLOCK: | |
2415 | { | |
2416 | uint8_t p_speaker_payload; | |
2417 | CA = 0; | |
2418 | Pspeaker_allocation_data_block_t p_speaker_allocation_data_block = (Pspeaker_allocation_data_block_t) p_data_u.puc_data_block; | |
2419 | ||
2420 | *((Pspeaker_allocation_flags_t)&mhl_edid_3d_data->parse_data.speaker_alloc[i++]) = p_speaker_allocation_data_block->payload.speaker_alloc_flags; | |
2421 | p_speaker_payload = mhl_edid_3d_data->parse_data.speaker_alloc[i-1]; | |
2422 | pr_info("EDID -> Short Descriptor Speaker Allocation Block\n"); | |
2423 | { | |
2424 | pr_info("\nSpeakers' allocation: "); | |
2425 | if(p_speaker_payload & 0x01){ | |
2426 | CA+=0; | |
2427 | pr_info("FL/FR"); | |
2428 | } | |
2429 | if( p_speaker_payload& 0x02){ | |
2430 | CA+=0x01; | |
2431 | pr_info("LFE"); | |
2432 | } | |
2433 | if( p_speaker_payload & 0x04){ | |
2434 | CA+=0x02; | |
2435 | pr_info("FC"); | |
2436 | } | |
2437 | if(p_speaker_payload & 0x08){ | |
2438 | CA+=0x08; | |
2439 | pr_info("RL/RR"); | |
2440 | } | |
2441 | if(p_speaker_payload & 0x10){ | |
2442 | CA+=0x04; | |
2443 | pr_info("RC"); | |
2444 | } | |
2445 | if(p_speaker_payload& 0x20){ | |
2446 | CA+=0x14; | |
2447 | pr_info("FLC/FRC"); | |
2448 | } | |
2449 | if(p_speaker_payload & 0x40){ | |
2450 | CA+=0x08; | |
2451 | pr_info("RLC/RRC"); | |
2452 | } | |
2453 | pr_info("\nCA=0x%x\n",CA); | |
2454 | } | |
2455 | } | |
2456 | break; | |
2457 | ||
2458 | case DBTC_USE_EXTENDED_TAG: | |
2459 | { | |
2460 | extended_tag_code_t extended_tag_code; | |
2461 | extended_tag_code = p_data_u.p_CEA_data_block->payload_u.extended_tag; | |
2462 | switch (extended_tag_code.etc) | |
2463 | { | |
2464 | case ETC_VIDEO_CAPABILITY_DATA_BLOCK: | |
2465 | { | |
2466 | Pvideo_capability_data_block_t p_video_capability_data_block = (Pvideo_capability_data_block_t)p_data_u.puc_data_block; | |
2467 | Pvideo_capability_data_payload_t p_payload = &p_video_capability_data_block->payload; | |
2468 | mhl_edid_3d_data->parse_data.video_capability_flags = *((uint8_t *)p_payload); | |
2469 | mhl_edid_3d_data->parse_data.p_video_capability_data_block = p_video_capability_data_block; | |
2470 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2471 | "EDID -> Short Descriptor Video Capability Block\n"); | |
2472 | } | |
2473 | break; | |
2474 | ||
2475 | case ETC_COLORIMETRY_DATA_BLOCK: | |
2476 | { | |
2477 | Pcolorimetry_data_block_t p_colorimetry_data_block = (Pcolorimetry_data_block_t)p_data_u.puc_data_block; | |
2478 | Pcolorimetry_data_payload_t p_payload= &p_colorimetry_data_block->payload; | |
2479 | mhl_edid_3d_data->parse_data.colorimetry_support_flags = p_payload->ci_data.xvYCC; | |
2480 | mhl_edid_3d_data->parse_data.meta_data_profile = p_payload->cm_meta_data.meta_data; | |
2481 | } | |
2482 | ||
2483 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2484 | "EDID -> Short Descriptor Colorimetry Block\n"); | |
2485 | break; | |
2486 | } | |
2487 | } | |
2488 | ||
2489 | break; | |
2490 | ||
2491 | case DBTC_VENDOR_SPECIFIC_DATA_BLOCK: | |
2492 | { | |
2493 | P_vsdb_t p_vsdb = (P_vsdb_t) p_data_u.puc_data_block; | |
2494 | uint8_t *puc_next_db = ((uint8_t *)&p_vsdb->header) + sizeof(p_vsdb->header) + data_block_length; | |
2495 | ||
2496 | // TODO: FD, TBI, any chance of MHL OUI here? 0x030C00 is HDMI OUI | |
2497 | if ( (p_vsdb->IEEE_OUI[0] == 0x03) | |
2498 | && (p_vsdb->IEEE_OUI[1] == 0x0C) | |
2499 | && (p_vsdb->IEEE_OUI[2] == 0x00) | |
2500 | ) { | |
2501 | PHDMI_LLC_vsdb_payload_t p_HDMI_vendor_specific_payload = &p_vsdb->payload_u.HDMI_LLC; | |
2502 | mhl_edid_3d_data->parse_data.p_HDMI_vsdb = p_vsdb; | |
2503 | SII_ASSERT (5 <= data_block_length,("unexpected data_block_length\n")); | |
2504 | mhl_edid_3d_data->parse_data.HDMI_sink = true; | |
2505 | *((PHDMI_LLC_BA_t)&mhl_edid_3d_data->parse_data.CEC_A_B) = p_HDMI_vendor_specific_payload->B_A; /* CEC Physical address */ | |
2506 | *((PHDMI_LLC_DC_t)&mhl_edid_3d_data->parse_data.CEC_C_D) = p_HDMI_vendor_specific_payload->D_C; | |
2507 | /* Offset of 3D_Present bit in VSDB */ | |
2508 | if (p_HDMI_vendor_specific_payload->byte8.latency_fields_present) { | |
2509 | if(p_HDMI_vendor_specific_payload->byte8.I_latency_fields_present) { | |
2510 | mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15= &p_HDMI_vendor_specific_payload->vsdb_fields_byte_9_through_byte_15.vsdb_all_fields_byte_9_through_byte_15.byte_13_through_byte_15; | |
2511 | } else { | |
2512 | mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15 = &p_HDMI_vendor_specific_payload->vsdb_fields_byte_9_through_byte_15.vsdb_all_fields_byte_9_through_byte_15_sans_interlaced_latency.byte_13_through_byte_15; | |
2513 | } | |
2514 | } else { | |
2515 | if(p_HDMI_vendor_specific_payload->byte8.I_latency_fields_present) { | |
2516 | mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15 = &p_HDMI_vendor_specific_payload->vsdb_fields_byte_9_through_byte_15.vsdb_all_fields_byte_9_through_byte_15_sans_progressive_latency.byte_13_through_byte_15; | |
2517 | } else { | |
2518 | mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15 = &p_HDMI_vendor_specific_payload->vsdb_fields_byte_9_through_byte_15.vsdb_all_fields_byte_9_through_byte_15_sans_all_latency.byte_13_through_byte_15; | |
2519 | } | |
2520 | } | |
2521 | if ( ((uint8_t *)&mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte13) >= puc_next_db ) { | |
2522 | mhl_edid_3d_data->parse_data._3D_supported = false; | |
2523 | } else if (mhl_edid_3d_data->parse_data.p_byte_13_through_byte_15->byte13._3D_present) { | |
2524 | mhl_edid_3d_data->parse_data._3D_supported = true; | |
2525 | } else { | |
2526 | mhl_edid_3d_data->parse_data._3D_supported = false; | |
2527 | } | |
2528 | ||
2529 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2530 | "EDID indicates %s3D support\n", | |
2531 | mhl_edid_3d_data->parse_data._3D_supported?"":"NO " ); | |
2532 | } else { | |
2533 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"check VS IEEE code failed!\n"); | |
2534 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"00:%02X, 01:%02X, 02:%02X\n", p_vsdb->IEEE_OUI[0], p_vsdb->IEEE_OUI[1],p_vsdb->IEEE_OUI[2]); | |
2535 | mhl_edid_3d_data->parse_data.HDMI_sink = false; | |
2536 | } | |
2537 | ||
2538 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2539 | "EDID -> Short Descriptor Vendor Block\n\n"); | |
2540 | } | |
2541 | ||
2542 | break; | |
2543 | case DBTC_TERMINATOR: | |
2544 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2545 | "found terminator tag code\n"); | |
2546 | return EDID_SHORT_DESCRIPTORS_OK; | |
2547 | break; | |
2548 | ||
2549 | default: | |
2550 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context, | |
2551 | "EDID -> Unknown Tag Code:0x%02x\n",(uint16_t)tag_code); | |
2552 | return EDID_UNKNOWN_TAG_CODE; | |
2553 | ||
2554 | } | |
2555 | p_data_u.puc_data_block += sizeof(p_data_u.p_CEA_data_block->header)+ data_block_length; | |
2556 | } | |
2557 | ||
2558 | return EDID_SHORT_DESCRIPTORS_OK; | |
2559 | } | |
2560 | } | |
2561 | } | |
2562 | ||
2563 | static uint8_t parse_861_block(edid_3d_data_p mhl_edid_3d_data,uint8_t *p_EDID_block_data) | |
2564 | { | |
2565 | ||
2566 | uint8_t err_code; | |
2567 | PCEA_extension_t p_CEA_extension = (PCEA_extension_t)p_EDID_block_data; | |
2568 | ||
2569 | mhl_edid_3d_data->parse_data.p_HDMI_vsdb = NULL; | |
2570 | ||
2571 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"tag:place holder EDID block:%p\n",p_EDID_block_data); | |
2572 | if (EDID_EXTENSION_BLOCK_MAP == p_CEA_extension->tag) { | |
2573 | Pblock_map_t p_block_map = (Pblock_map_t)p_EDID_block_data; | |
2574 | int i; | |
2575 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"Edid: Block Map\n"); | |
2576 | /* loop limit is adjusted by one to account for block map */ | |
2577 | for(i=0;i<mhl_edid_3d_data->parse_data.num_EDID_extensions-1;++i) { | |
2578 | if (EDID_EXTENSION_TAG != p_block_map->block_tags[i]) { | |
2579 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"Edid: Adjusting number of extensions according to Block Map\n"); | |
2580 | mhl_edid_3d_data->parse_data.num_EDID_extensions=i; /* include block map in count */ | |
2581 | break; | |
2582 | } | |
2583 | } | |
2584 | ||
2585 | return EDID_OK; | |
2586 | ||
2587 | } else { | |
2588 | err_code = parse_861_short_descriptors(mhl_edid_3d_data,p_EDID_block_data); | |
2589 | if (err_code != EDID_SHORT_DESCRIPTORS_OK) { | |
2590 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context, | |
2591 | "EDID: Non-HDMI extension Errcode:%d\n",(uint16_t)err_code); | |
2592 | return err_code; | |
2593 | } | |
2594 | #if 0 | |
2595 | /* adjust */ | |
2596 | err_code = si_mhl_tx_parse_861_long_descriptors(mhl_edid_3d_data,p_EDID_block_data); | |
2597 | if (err_code != EDID_LONG_DESCRIPTORS_OK) { | |
2598 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context, | |
2599 | "EDID: Errcode:%d\n",(uint16_t)err_code); | |
2600 | return err_code; | |
2601 | } | |
2602 | #endif | |
2603 | } | |
2604 | return EDID_OK; | |
2605 | } | |
2606 | ||
2607 | void si_mhl_tx_handle_atomic_hw_edid_read_complete(edid_3d_data_p mhl_edid_3d_data,struct cbus_req *req) | |
2608 | { | |
2609 | PEDID_block0_t p_EDID_block_0 = (PEDID_block0_t)&mhl_edid_3d_data->EDID_block_data[0]; | |
2610 | uint8_t counter; | |
2611 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"tag: Entire EDID Read complete\n"); | |
2612 | #ifdef EDID_PASSTHROUGH //( | |
2613 | si_mhl_tx_drv_set_upstream_edid(mhl_edid_3d_data->drv_context,mhl_edid_3d_data->EDID_block_data,2*EDID_BLOCK_SIZE); | |
2614 | #endif //) | |
2615 | /* Parse EDID Block #0 Desctiptors */ | |
2616 | //si_mhl_tx_parse_block_zero_timing_descriptors(mhl_edid_3d_data,p_EDID_block_0); | |
2617 | ||
2618 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context | |
2619 | ,"EDID -> Number of 861 Extensions = %d\n" | |
2620 | , (uint16_t)p_EDID_block_0->extension_flag ); | |
2621 | ||
2622 | mhl_edid_3d_data->parse_data.num_EDID_extensions = p_EDID_block_0->extension_flag; | |
2623 | if (0 == p_EDID_block_0->extension_flag) { | |
2624 | /* No extensions to worry about */ | |
2625 | DUMP_EDID_BLOCK(0,(uint8_t *)p_EDID_block_0,EDID_BLOCK_SIZE) | |
2626 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context | |
2627 | ,"EDID -> no extensions, assuming DVI. tag offset:0x%x\n" | |
2628 | , SII_OFFSETOF(EDID_block0_t,extension_flag)); | |
2629 | mhl_edid_3d_data->parse_data.HDMI_sink = false; | |
2630 | SiiMhlTxMakeItDVI(mhl_edid_3d_data,p_EDID_block_0); | |
2631 | } else { | |
2632 | uint8_t Result = EDID_OK; | |
2633 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context," tag:place holder \n"); | |
2634 | /* number of extensions is one less than number of blocks */ | |
2635 | for (counter = 1; counter <= mhl_edid_3d_data->parse_data.num_EDID_extensions;++counter) { | |
2636 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context," counter:%d tag:place holder EDID block:%p\n",counter,&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE * counter]); | |
2637 | Result = parse_861_block(mhl_edid_3d_data,&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE * counter]); | |
2638 | if (EDID_OK != Result) { | |
2639 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context | |
2640 | ,"EDID -> Extension[%d] is not HDMI: Result:%d\n" | |
2641 | , counter | |
2642 | ,(uint16_t)Result); | |
2643 | SiiMhlTxMakeItDVI(mhl_edid_3d_data,p_EDID_block_0); | |
2644 | Result = EDID_OK; | |
2645 | } | |
2646 | } | |
2647 | } | |
2648 | /* | |
2649 | * Since our working copy of the block zero EDID gets modified, | |
2650 | * we must re-compute its checksum | |
2651 | */ | |
2652 | p_EDID_block_0->checksum = 0; | |
2653 | p_EDID_block_0->checksum = calculate_generic_checksum((uint8_t *)p_EDID_block_0,0,sizeof(*p_EDID_block_0)); | |
2654 | ||
2655 | //SiiMhlTx3dReqForNonTranscodeMode(mhl_edid_3d_data); | |
2656 | } | |
2657 | ||
2658 | /* | |
2659 | EXPORTED FUNCTIONS | |
2660 | */ | |
2661 | ||
2662 | void si_mhl_tx_initiate_edid_sequence(void *context) | |
2663 | { | |
2664 | edid_3d_data_p mhl_edid_3d_data =(edid_3d_data_p)context; | |
2665 | ||
2666 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"tag:\n"); | |
2667 | mhl_edid_3d_data->parse_data.num_video_data_blocks=0; | |
2668 | ||
2669 | /* | |
2670 | Initiate the EDID reading sequence see | |
2671 | SiiMhlTxMscCommandDone for additional processing. | |
2672 | */ | |
2673 | ||
2674 | si_edid_reset(mhl_edid_3d_data); | |
2675 | si_mhl_tx_request_first_edid_block( mhl_edid_3d_data->dev_context); | |
2676 | } | |
2677 | ||
2678 | int si_mhl_tx_get_num_cea_861_extensions(void *context, uint8_t block_number) | |
2679 | { | |
2680 | edid_3d_data_p mhl_edid_3d_data =(edid_3d_data_p)context; | |
2681 | ||
2682 | PEDID_block0_t p_EDID_block_0 = (PEDID_block0_t) &mhl_edid_3d_data->EDID_block_data; | |
2683 | uint8_t limit_blocks = sizeof(mhl_edid_3d_data->EDID_block_data) / | |
2684 | EDID_BLOCK_SIZE; | |
2685 | ||
2686 | uint8_t *pb_data = &mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE * block_number]; | |
2687 | ||
2688 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context,"block number:%d pb_data:%x\n",block_number,pb_data); | |
2689 | ||
2690 | if (ne_SUCCESS == si_mhl_tx_drv_get_edid_fifo_next_block(mhl_edid_3d_data->drv_context, pb_data)) { | |
2691 | if (0 == block_number) { | |
2692 | if (!si_mhl_tx_check_edid_header(mhl_edid_3d_data,p_EDID_block_0)) { | |
2693 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context,"EDID -> Incorrect Header pb_data:%x\n",pb_data); | |
2694 | DUMP_EDID_BLOCK(1,pb_data,sizeof(*p_EDID_block_0)) /* no semicolon needed here */ | |
2695 | if (si_mhl_tx_check_edid_header(mhl_edid_3d_data,(PEDID_block0_t)&mhl_edid_3d_data->EDID_block_data[1])) { | |
2696 | // return ne_BAD_HEADER_OFFSET_BY_1; | |
2697 | } | |
2698 | } | |
2699 | } | |
2700 | if (! si_mhl_tx_do_edid_checksum(pb_data)) { | |
2701 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context,"EDID -> Checksum Error pb_data:%x\n",pb_data); | |
2702 | DUMP_EDID_BLOCK(1,pb_data,EDID_BLOCK_SIZE) /* no semicolon needed here */ | |
2703 | // return ne_BAD_CHECKSUM; | |
2704 | } | |
2705 | ||
2706 | if(p_EDID_block_0->extension_flag < limit_blocks) { | |
2707 | return p_EDID_block_0->extension_flag; | |
2708 | } else { | |
2709 | MHL_TX_DBG_ERR(mhl_edid_3d_data->dev_context, | |
2710 | "not enough room for %d extension\n", | |
2711 | p_EDID_block_0->extension_flag); | |
2712 | return (int)limit_blocks-1; | |
2713 | } | |
2714 | } else { | |
2715 | return ne_NO_HPD; | |
2716 | } | |
2717 | ||
2718 | } | |
2719 | ||
2720 | int si_edid_sink_is_hdmi ( void *context ) | |
2721 | { | |
2722 | edid_3d_data_p mhl_edid_3d_data =(edid_3d_data_p)context; | |
2723 | return mhl_edid_3d_data->parse_data.HDMI_sink; | |
2724 | } | |
2725 | ||
2726 | int si_edid_quantization_range_selectable( void *context ) | |
2727 | { | |
2728 | edid_3d_data_p mhl_edid_3d_data =(edid_3d_data_p)context; | |
2729 | return mhl_edid_3d_data->parse_data.video_capability_flags & 0x80; | |
2730 | } | |
2731 | ||
2732 | int si_edid_sink_supports_YCbCr422 ( void *context ) | |
2733 | { | |
2734 | edid_3d_data_p mhl_edid_3d_data =(edid_3d_data_p)context; | |
2735 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2736 | "Mhl2Tx: YCbCr422 support:%s\n", | |
2737 | mhl_edid_3d_data->parse_data.YCbCr_4_2_2?"Yup":"Nope"); | |
2738 | return mhl_edid_3d_data->parse_data.YCbCr_4_2_2; | |
2739 | } | |
2740 | ||
2741 | int si_edid_sink_supports_YCbCr444 ( void *context ) | |
2742 | { | |
2743 | edid_3d_data_p mhl_edid_3d_data =(edid_3d_data_p)context; | |
2744 | MHL_TX_EDID_INFO(mhl_edid_3d_data->dev_context, | |
2745 | "Mhl2Tx: YCbCr444 support:%s\n", | |
2746 | mhl_edid_3d_data->parse_data.YCbCr_4_4_4?"Yup":"Nope"); | |
2747 | return mhl_edid_3d_data->parse_data.YCbCr_4_4_4; | |
2748 | } | |
2749 | ||
2750 | int si_edid_find_pixel_clock_from_HDMI_VIC(void *context, uint8_t vic) | |
2751 | { | |
2752 | return hdmi_vic_info[vic].pixel_clock_0; | |
2753 | } | |
2754 | int si_edid_find_pixel_clock_from_AVI_VIC(void *context, uint8_t vic) | |
2755 | { | |
2756 | return calculate_pixel_clock(context | |
2757 | , (uint16_t)VIC_info[vic].columns | |
2758 | , (uint16_t)VIC_info[vic].rows | |
2759 | , (uint32_t)VIC_info[vic].field_rate_in_milliHz | |
2760 | , vic | |
2761 | ); | |
2762 | } | |
2763 | int si_edid_read_done(void *context) | |
2764 | { | |
2765 | edid_3d_data_p mhl_edid_3d_data =(edid_3d_data_p)context; | |
2766 | return TEST_3D_FLAG(mhl_edid_3d_data,FLAGS_EDID_READ_DONE); | |
2767 | } | |
2768 | ||
2769 | void si_edid_reset( edid_3d_data_p mhl_edid_3d_data ) | |
2770 | { | |
2771 | int i; | |
2772 | uint8_t *pData=(uint8_t *) &mhl_edid_3d_data->parse_data; | |
2773 | ||
2774 | /* clear out EDID parse results */ | |
2775 | for (i=0; i < sizeof(mhl_edid_3d_data->parse_data);++i) { | |
2776 | pData[i]=0; | |
2777 | } | |
2778 | CLR_3D_FLAG(mhl_edid_3d_data, FLAGS_EDID_READ_DONE); | |
2779 | } | |
2780 | ||
2781 | void *si_edid_create_context(void *dev_context,void *drv_context) | |
2782 | { | |
2783 | edid_3d_data_p temp; | |
2784 | temp = (edid_3d_data_p )kmalloc(sizeof(edid_3d_data_t),GFP_KERNEL); | |
2785 | if (temp) { | |
2786 | memset((void *)temp,0,sizeof(*temp)); | |
2787 | temp->dev_context=dev_context; | |
2788 | temp->drv_context=drv_context; | |
2789 | } | |
2790 | return (void *)temp; | |
2791 | } | |
2792 | void si_edid_destroy_context(void *context) | |
2793 | { | |
2794 | if (context) { | |
2795 | memset(context,0,sizeof(edid_3d_data_t)); | |
2796 | kfree(context); | |
2797 | } | |
2798 | } | |
2799 | #if 1//def ENABLE_EDID_DEBUG_PRINT //( | |
2800 | void dump_EDID_block_impl(const char *pszFunction, int iLineNum,uint8_t override,uint8_t *pData,uint16_t length) | |
2801 | { | |
2802 | uint16_t i; | |
2803 | printk("%s:%d EDID DATA:\n",pszFunction,iLineNum); | |
2804 | for (i = 0; i < length; ) | |
2805 | { | |
2806 | uint16_t j; | |
2807 | uint16_t temp = i; | |
2808 | for(j=0; (j < 16)&& (i<length);++j,++i) | |
2809 | { | |
2810 | printk("%02X ", pData[i]); | |
2811 | } | |
2812 | printk(" | "); | |
2813 | for(j=0; (j < 16)&& (temp<length);++j,++temp) | |
2814 | { | |
2815 | printk("%c",((pData[temp]>=' ')&&(pData[temp]<='z'))?pData[temp]:'.'); | |
2816 | } | |
2817 | printk("\n"); | |
2818 | } | |
2819 | } | |
2820 | #endif //) |