import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / hdmi / Sii8348 / si_mhl2_edid_3d.c
CommitLineData
6fa3eb70
S
1/*
2
3SiI8348 Linux Driver
4
5Copyright (C) 2013 Silicon Image, Inc.
6
7This program is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation version 2.
10This program is distributed AS-IS WITHOUT ANY WARRANTY of any
11kind, whether express or implied; INCLUDING without the implied warranty
12of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE or NON-INFRINGEMENT. See
13the 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
53typedef 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
67timing_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
84void 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
90void 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
109void 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
115uint32_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
139PLACE_IN_CODE_SEG char *psz_space ="n/a";
140PLACE_IN_CODE_SEG char *psz_frame_sequential ="FS ";
141PLACE_IN_CODE_SEG char *psz_top_bottom ="TB ";
142PLACE_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}}
147VIC_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
217uint32_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
313uint8_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
355static 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{
361uint32_t pixel_clock_frequency;
362uint8_t ret_val = 0;
363MHL2_video_descriptor_t dummy;
364PMHL2_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
391void 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
496static 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
719static 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
762static 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*/
1208static 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
1250PLACE_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*/
1260static 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{
1262uint8_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
1296void 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
1491static 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
1507static 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*/
1520void 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
1596void 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{
1599int 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
1618void 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) \
1779if (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
1786static 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
1878static 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
1962static 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
1997static 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
2038static 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
2071void 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
2095static 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
2152uint8_t CA=0;//Channel/Speaker Allocation.
2153uint8_t MAX_channel=2;//Channel.
2154uint8_t Samplebit;
2155
2156uint8_t Cap_MAX_channel;
2157uint8_t Cap_Samplebit;
2158uint16_t Cap_SampleRate;
2159static uint8_t parse_861_short_descriptors (
2160 edid_3d_data_p mhl_edid_3d_data
2161 , uint8_t *p_EDID_block_data)
2162{
2163uint8_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
2563static 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
2607void 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
2662void 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
2678int 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
2720int 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
2726int 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
2732int 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
2741int 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
2750int si_edid_find_pixel_clock_from_HDMI_VIC(void *context, uint8_t vic)
2751{
2752 return hdmi_vic_info[vic].pixel_clock_0;
2753}
2754int 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}
2763int 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
2769void 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
2781void *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}
2792void 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 //(
2800void 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 //)