2 #include "../../edid.h"
4 #define hdmi_edid_error(fmt, ...) \
5 printk(pr_fmt(fmt), ##__VA_ARGS__)
8 #define hdmi_edid_debug(fmt, ...) \
9 printk(pr_fmt(fmt), ##__VA_ARGS__)
11 #define hdmi_edid_debug(fmt, ...)
14 enum HDMI_EDID_ERRORCODE {
15 E_HDMI_EDID_SUCCESS = 0,
20 E_HDMI_EDID_UNKOWNDATA,
24 static const unsigned int double_aspect_vic[] = {
25 3, 7, 9, 11, 13, 15, 18, 22, 24, 26, 28, 30,
26 36, 38, 43, 45, 49, 51, 53, 55, 57, 59
29 static int hdmi_edid_checksum(unsigned char *buf)
34 for (i = 0; i < HDMI_EDID_BLOCK_SIZE; i++)
40 return E_HDMI_EDID_SUCCESS;
42 return E_HDMI_EDID_CHECKSUM;
46 * @Des Parse Detail Timing Descriptor.
47 * @Param buf : pointer to DTD data.
48 * @Param pvic: VIC of DTD descripted.
50 static int hdmi_edid_parse_dtd(unsigned char *block, struct fb_videomode *mode)
52 mode->xres = H_ACTIVE;
53 mode->yres = V_ACTIVE;
54 mode->pixclock = PIXEL_CLOCK;
56 mode->pixclock /= 1000;
57 mode->pixclock = KHZ2PICOS(mode->pixclock);
59 mode->right_margin = H_SYNC_OFFSET;
60 mode->left_margin = (H_ACTIVE + H_BLANKING) -
61 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
62 mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
64 mode->lower_margin = V_SYNC_OFFSET;
65 mode->hsync_len = H_SYNC_WIDTH;
66 mode->vsync_len = V_SYNC_WIDTH;
68 mode->sync |= FB_SYNC_HOR_HIGH_ACT;
70 mode->sync |= FB_SYNC_VERT_HIGH_ACT;
71 mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
72 (V_ACTIVE + V_BLANKING));
75 mode->upper_margin *= 2;
76 mode->lower_margin *= 2;
78 mode->vmode |= FB_VMODE_INTERLACED;
80 mode->flag = FB_MODE_IS_DETAILED;
82 hdmi_edid_debug("<<<<<<<<Detailed Time>>>>>>>>>\n");
83 hdmi_edid_debug("%d KHz Refresh %d Hz", PIXEL_CLOCK/1000,
85 hdmi_edid_debug("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
86 H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
87 hdmi_edid_debug("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
88 V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
89 hdmi_edid_debug("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
90 (VSYNC_POSITIVE) ? "+" : "-");
91 return E_HDMI_EDID_SUCCESS;
94 static int hdmi_edid_parse_base(unsigned char *buf, int *extend_num,
95 struct hdmi_edid *pedid)
99 if (buf == NULL || extend_num == NULL)
100 return E_HDMI_EDID_PARAM;
103 for (i = 0; i < HDMI_EDID_BLOCK_SIZE; i++) {
104 hdmi_edid_debug("%02x ", buf[i]&0xff);
106 hdmi_edid_debug("\n");
110 /* Check first 8 byte to ensure it is an edid base block. */
111 if (buf[0] != 0x00 ||
119 hdmi_edid_error("[EDID] check header error\n");
120 return E_HDMI_EDID_HEAD;
123 *extend_num = buf[0x7e];
125 hdmi_edid_debug("[EDID] extend block num is %d\n", buf[0x7e]);
129 rc = hdmi_edid_checksum(buf);
130 if (rc != E_HDMI_EDID_SUCCESS) {
131 hdmi_edid_error("[EDID] base block checksum error\n");
132 return E_HDMI_EDID_CHECKSUM;
135 pedid->specs = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
136 if (pedid->specs == NULL)
137 return E_HDMI_EDID_NOMEMORY;
139 fb_edid_to_monspecs(buf, pedid->specs);
141 return E_HDMI_EDID_SUCCESS;
144 /* Parse CEA Short Video Descriptor */
145 static int hdmi_edid_get_cea_svd(unsigned char *buf, struct hdmi_edid *pedid)
147 const struct fb_videomode *mode;
148 int count, i, j, vic;
150 count = buf[0] & 0x1F;
151 for (i = 0; i < count; i++) {
152 hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
156 #ifndef HDMI_VERSION_2
157 vic = buf[1 + i] & 0x7f;
159 vic = buf[1 + i] & 0xff;
161 for (j = 0; j < ARRAY_SIZE(double_aspect_vic); j++) {
162 if (vic == double_aspect_vic[j]) {
168 mode = hdmi_vic_to_videomode(vic);
170 hdmi_add_videomode(mode, &pedid->modelist);
176 /* Parse CEA Short Audio Descriptor */
177 static int hdmi_edid_parse_cea_sad(unsigned char *buf, struct hdmi_edid *pedid)
181 count = buf[0] & 0x1F;
182 pedid->audio = kmalloc((count / 3) * sizeof(struct hdmi_audio),
184 if (pedid->audio == NULL)
185 return E_HDMI_EDID_NOMEMORY;
187 pedid->audio_num = count / 3;
188 for (i = 0; i < pedid->audio_num; i++) {
189 pedid->audio[i].type = (buf[1 + i * 3] >> 3) & 0x0F;
190 pedid->audio[i].channel = (buf[1 + i * 3] & 0x07) + 1;
191 pedid->audio[i].rate = buf[1 + i * 3 + 1];
192 if (pedid->audio[i].type == HDMI_AUDIO_LPCM) /* LPCM */
193 pedid->audio[i].word_length = buf[1 + i * 3 + 2];
195 printk("[EDID-CEA] type %d channel %d rate %d word length %d\n",
196 pedid->audio[i].type, pedid->audio[i].channel,
197 pedid->audio[i].rate, pedid->audio[i].word_length);
200 return E_HDMI_EDID_SUCCESS;
203 /* Parse CEA Vendor Specific Data Block */
204 static int hdmi_edid_parse_cea_sdb(unsigned char *buf, struct hdmi_edid *pedid)
206 unsigned int count = 0, cur_offset = 0, i = 0;
207 unsigned int IEEEOUI = 0;
208 unsigned int supports_ai, dc_48bit, dc_36bit, dc_30bit, dc_y444;
209 unsigned int len_3d, len_4k;
210 unsigned char vic = 0;
211 const struct fb_videomode *mode;
213 count = buf[0] & 0x1F;
219 hdmi_edid_debug("[EDID-CEA] IEEEOUI is 0x%08x.\n", IEEEOUI);
220 if (IEEEOUI == 0x0c03)
221 pedid->sink_hdmi = 1;
224 pedid->deepcolor = (buf[6] >> 3) & 0x0F;
225 supports_ai = buf[6] >> 7;
226 dc_48bit = (buf[6] >> 6) & 0x1;
227 dc_36bit = (buf[6] >> 5) & 0x1;
228 dc_30bit = (buf[6] >> 4) & 0x1;
229 dc_y444 = (buf[6] >> 3) & 0x1;
230 hdmi_edid_debug("[EDID-CEA] supports_ai %d\n"
231 "dc_48bit %d dc_36bit %d dc_30bit %d dc_y444 %d\n",
233 dc_48bit, dc_36bit, dc_30bit, dc_y444);
236 pedid->maxtmdsclock = buf[7] * 5000000;
239 pedid->latency_fields_present = (buf[8] & 0x80) ? 1 : 0;
240 pedid->i_latency_fields_present = (buf[8] & 0x40) ? 1 : 0;
241 pedid->video_present = (buf[8] & 0x20) ? 1 : 0;
245 if (count >= cur_offset) {
246 if (pedid->latency_fields_present == 1) {
247 pedid->video_latency = buf[cur_offset++];
248 pedid->audio_latency = buf[cur_offset++];
250 if (count >= cur_offset && pedid->i_latency_fields_present) {
251 pedid->interlaced_video_latency = buf[cur_offset++];
252 pedid->interlaced_audio_latency = buf[cur_offset++];
256 if (pedid->video_present == 0)
257 return E_HDMI_EDID_SUCCESS;
259 if (count >= cur_offset) {
260 pedid->support_3d = (buf[cur_offset++] & 0x80) ? 1 : 0;
262 len_4k = (buf[cur_offset] >> 5) & 0x07;
263 len_3d = buf[cur_offset] & 0x1F;
266 if (count >= cur_offset && len_4k > 0) {
267 for (i = 0; i < len_4k; i++) {
268 #ifndef HDMI_VERSION_2
269 vic = buf[cur_offset + i] & 0x7f;
270 if (vic > 0 && vic < 5)
271 vic = (vic == 4) ? 98 : (96 - vic);
272 hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
275 buf[cur_offset + i] >> 7);
277 vic = buf[cur_offset + i] & 0xff;
278 hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
279 buf[cur_offset + i], vic);
282 mode = hdmi_vic_to_videomode(vic);
284 hdmi_add_videomode(mode,
291 /* TODO Daisen wait to add
292 if (count >= cur_offset && pedid->support_3d && len_3d > 0) {
296 return E_HDMI_EDID_SUCCESS;
299 /* Parse CEA 861 Serial Extension. */
300 static int hdmi_edid_parse_extensions_cea(unsigned char *buf,
301 struct hdmi_edid *pedid)
303 unsigned int ddc_offset, native_dtd_num, cur_offset = 4;
304 unsigned int underscan_support, baseaudio_support;
308 return E_HDMI_EDID_PARAM;
310 /* Check ces extension version */
312 hdmi_edid_error("[EDID-CEA] error version.\n");
313 return E_HDMI_EDID_VERSION;
317 underscan_support = (buf[3] >> 7) & 0x01;
318 baseaudio_support = (buf[3] >> 6) & 0x01;
319 pedid->ycbcr444 = (buf[3] >> 5) & 0x01;
320 pedid->ycbcr422 = (buf[3] >> 4) & 0x01;
321 native_dtd_num = buf[3] & 0x0F;
322 pedid->base_audio_support = baseaudio_support;
324 /* Parse data block */
325 while (cur_offset < ddc_offset) {
326 tag = buf[cur_offset] >> 5;
328 case 0x02: /* Video Data Block */
329 hdmi_edid_debug("[EDID-CEA] It is a Video Data Block.\n");
330 hdmi_edid_get_cea_svd(buf + cur_offset, pedid);
332 case 0x01: /* Audio Data Block */
333 hdmi_edid_debug("[EDID-CEA] It is a Audio Data Block.\n");
334 hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);
336 case 0x04: /* Speaker Allocation Data Block */
337 hdmi_edid_debug("[EDID-CEA] It is a Speaker Allocation Data Block.\n");
339 case 0x03: /* Vendor Specific Data Block */
340 hdmi_edid_debug("[EDID-CEA] It is a Vendor Specific Data Block.\n");
341 hdmi_edid_parse_cea_sdb(buf + cur_offset, pedid);
343 case 0x05: /* VESA DTC Data Block */
344 hdmi_edid_debug("[EDID-CEA] It is a VESA DTC Data Block.\n");
346 case 0x07: /* Use Extended Tag */
347 hdmi_edid_debug("[EDID-CEA] It is a Use Extended Tag Data Block.\n");
350 hdmi_edid_error("[EDID-CEA] unkowned data block tag.\n");
353 cur_offset += (buf[cur_offset] & 0x1F) + 1;
358 struct fb_videomode *vmode = kmalloc(sizeof(struct fb_videomode),
361 return E_HDMI_EDID_SUCCESS;
362 /* buf[126] = 0 and buf[127] = checksum */
363 while (ddc_offset < HDMI_EDID_BLOCK_SIZE - 2) {
364 if (!buf[ddc_offset] && !buf[ddc_offset + 1])
366 memset(vmode, 0, sizeof(struct fb_videomode));
367 hdmi_edid_parse_dtd(buf + ddc_offset, vmode);
368 hdmi_add_videomode(vmode, &pedid->modelist);
374 return E_HDMI_EDID_SUCCESS;
377 static int hdmi_edid_parse_extensions(unsigned char *buf,
378 struct hdmi_edid *pedid)
382 if (buf == NULL || pedid == NULL)
383 return E_HDMI_EDID_PARAM;
386 rc = hdmi_edid_checksum(buf);
387 if (rc != E_HDMI_EDID_SUCCESS) {
388 hdmi_edid_error("[EDID] extensions block checksum error\n");
389 return E_HDMI_EDID_CHECKSUM;
394 hdmi_edid_debug("[EDID-EXTEND] It is a extensions block map.\n");
397 hdmi_edid_debug("[EDID-EXTEND] It is a CEA 861 Series Extension.\n");
398 hdmi_edid_parse_extensions_cea(buf, pedid);
401 hdmi_edid_debug("[EDID-EXTEND] It is a Video Timing Block Extension.\n");
404 hdmi_edid_debug("[EDID-EXTEND] It is a Display Information Extension.\n");
407 hdmi_edid_debug("[EDID-EXTEND] It is a Localized String Extension.\n");
410 hdmi_edid_debug("[EDID-EXTEND] It is a Digital Packet Video Link Extension.\n");
413 hdmi_edid_error("[EDID-EXTEND] Unkowned extension.\n");
414 return E_HDMI_EDID_UNKOWNDATA;
417 return E_HDMI_EDID_SUCCESS;
421 int hdmi_sys_parse_edid(struct hdmi *hdmi)
423 struct hdmi_edid *pedid;
424 unsigned char *buff = NULL;
425 int rc = HDMI_ERROR_SUCESS, extendblock = 0, i;
428 return HDMI_ERROR_FALSE;
430 pedid = &(hdmi->edid);
431 memset(pedid, 0, sizeof(struct hdmi_edid));
432 INIT_LIST_HEAD(&pedid->modelist);
434 buff = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
437 "[%s] can not allocate memory for edid buff.\n",
442 /* Read base block edid. */
443 memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
444 rc = hdmi->read_edid(hdmi, 0, buff);
446 dev_err(hdmi->dev, "[HDMI] read edid base block error\n");
449 rc = hdmi_edid_parse_base(buff, &extendblock, pedid);
451 dev_err(hdmi->dev, "[HDMI] parse edid base block error\n");
454 for (i = 1; i < extendblock + 1; i++) {
455 memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
456 rc = hdmi->read_edid(hdmi, i, buff);
458 printk("[HDMI] read edid block %d error\n", i);
461 rc = hdmi_edid_parse_extensions(buff, pedid);
463 dev_err(hdmi->dev, "[HDMI] parse edid block %d error\n",
470 rc = hdmi_ouputmode_select(hdmi, rc);