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)
102 if (buf == NULL || extend_num == NULL)
103 return E_HDMI_EDID_PARAM;
106 for (i = 0; i < HDMI_EDID_BLOCK_SIZE; i++) {
107 hdmi_edid_debug("%02x ", buf[i]&0xff);
109 hdmi_edid_debug("\n");
113 /* Check first 8 byte to ensure it is an edid base block. */
114 if (buf[0] != 0x00 ||
122 hdmi_edid_error("[EDID] check header error\n");
123 return E_HDMI_EDID_HEAD;
126 *extend_num = buf[0x7e];
128 hdmi_edid_debug("[EDID] extend block num is %d\n", buf[0x7e]);
132 rc = hdmi_edid_checksum(buf);
133 if (rc != E_HDMI_EDID_SUCCESS) {
134 hdmi_edid_error("[EDID] base block checksum error\n");
135 return E_HDMI_EDID_CHECKSUM;
138 pedid->specs = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
139 if (pedid->specs == NULL)
140 return E_HDMI_EDID_NOMEMORY;
142 fb_edid_to_monspecs(buf, pedid->specs);
144 return E_HDMI_EDID_SUCCESS;
147 /* Parse CEA Short Video Descriptor */
148 static int hdmi_edid_get_cea_svd(unsigned char *buf, struct hdmi_edid *pedid)
150 const struct fb_videomode *mode;
151 int count, i, j, vic;
153 count = buf[0] & 0x1F;
154 for (i = 0; i < count; i++) {
155 hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
159 #ifndef HDMI_VERSION_2
160 vic = buf[1 + i] & 0x7f;
162 vic = buf[1 + i] & 0xff;
164 for (j = 0; j < ARRAY_SIZE(double_aspect_vic); j++) {
165 if (vic == double_aspect_vic[j]) {
171 mode = hdmi_vic_to_videomode(vic);
173 hdmi_add_videomode(mode, &pedid->modelist);
179 /* Parse CEA Short Audio Descriptor */
180 static int hdmi_edid_parse_cea_sad(unsigned char *buf, struct hdmi_edid *pedid)
184 count = buf[0] & 0x1F;
185 pedid->audio = kmalloc((count / 3) * sizeof(struct hdmi_audio),
187 if (pedid->audio == NULL)
188 return E_HDMI_EDID_NOMEMORY;
190 pedid->audio_num = count / 3;
191 for (i = 0; i < pedid->audio_num; i++) {
192 pedid->audio[i].type = (buf[1 + i * 3] >> 3) & 0x0F;
193 pedid->audio[i].channel = (buf[1 + i * 3] & 0x07) + 1;
194 pedid->audio[i].rate = buf[1 + i * 3 + 1];
195 if (pedid->audio[i].type == HDMI_AUDIO_LPCM) /* LPCM */
196 pedid->audio[i].word_length = buf[1 + i * 3 + 2];
198 printk("[EDID-CEA] type %d channel %d rate %d word length %d\n",
199 pedid->audio[i].type, pedid->audio[i].channel,
200 pedid->audio[i].rate, pedid->audio[i].word_length);
203 return E_HDMI_EDID_SUCCESS;
206 /* Parse CEA Vendor Specific Data Block */
207 static int hdmi_edid_parse_cea_sdb(unsigned char *buf, struct hdmi_edid *pedid)
209 unsigned int count = 0, cur_offset = 0, i = 0;
210 unsigned int IEEEOUI = 0;
211 unsigned int supports_ai, dc_48bit, dc_36bit, dc_30bit, dc_y444;
212 unsigned int len_3d, len_4k;
213 unsigned char vic = 0;
214 const struct fb_videomode *mode;
216 count = buf[0] & 0x1F;
222 hdmi_edid_debug("[EDID-CEA] IEEEOUI is 0x%08x.\n", IEEEOUI);
223 if (IEEEOUI == 0x0c03)
224 pedid->sink_hdmi = 1;
227 pedid->deepcolor = (buf[6] >> 3) & 0x0F;
228 supports_ai = buf[6] >> 7;
229 dc_48bit = (buf[6] >> 6) & 0x1;
230 dc_36bit = (buf[6] >> 5) & 0x1;
231 dc_30bit = (buf[6] >> 4) & 0x1;
232 dc_y444 = (buf[6] >> 3) & 0x1;
233 hdmi_edid_debug("[EDID-CEA] supports_ai %d\n"
234 "dc_48bit %d dc_36bit %d dc_30bit %d dc_y444 %d\n",
236 dc_48bit, dc_36bit, dc_30bit, dc_y444);
239 pedid->maxtmdsclock = buf[7] * 5000000;
242 pedid->latency_fields_present = (buf[8] & 0x80) ? 1 : 0;
243 pedid->i_latency_fields_present = (buf[8] & 0x40) ? 1 : 0;
244 pedid->video_present = (buf[8] & 0x20) ? 1 : 0;
248 if (count >= cur_offset) {
249 if (pedid->latency_fields_present == 1) {
250 pedid->video_latency = buf[cur_offset++];
251 pedid->audio_latency = buf[cur_offset++];
253 if (count >= cur_offset && pedid->i_latency_fields_present) {
254 pedid->interlaced_video_latency = buf[cur_offset++];
255 pedid->interlaced_audio_latency = buf[cur_offset++];
259 if (pedid->video_present == 0)
260 return E_HDMI_EDID_SUCCESS;
262 if (count >= cur_offset) {
263 pedid->support_3d = (buf[cur_offset++] & 0x80) ? 1 : 0;
265 len_4k = (buf[cur_offset] >> 5) & 0x07;
266 len_3d = buf[cur_offset] & 0x1F;
269 if (count >= cur_offset && len_4k > 0) {
270 for (i = 0; i < len_4k; i++) {
271 #ifndef HDMI_VERSION_2
272 vic = buf[cur_offset + i] & 0x7f;
273 if (vic > 0 && vic < 5)
274 vic = (vic == 4) ? 98 : (96 - vic);
275 hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
278 buf[cur_offset + i] >> 7);
280 vic = buf[cur_offset + i] & 0xff;
281 hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
282 buf[cur_offset + i], vic);
285 mode = hdmi_vic_to_videomode(vic);
287 hdmi_add_videomode(mode,
294 /* TODO Daisen wait to add
295 if (count >= cur_offset && pedid->support_3d && len_3d > 0) {
299 return E_HDMI_EDID_SUCCESS;
302 /* Parse CEA 861 Serial Extension. */
303 static int hdmi_edid_parse_extensions_cea(unsigned char *buf,
304 struct hdmi_edid *pedid)
306 unsigned int ddc_offset, native_dtd_num, cur_offset = 4;
307 unsigned int underscan_support, baseaudio_support;
311 return E_HDMI_EDID_PARAM;
313 /* Check ces extension version */
315 hdmi_edid_error("[EDID-CEA] error version.\n");
316 return E_HDMI_EDID_VERSION;
320 underscan_support = (buf[3] >> 7) & 0x01;
321 baseaudio_support = (buf[3] >> 6) & 0x01;
322 pedid->ycbcr444 = (buf[3] >> 5) & 0x01;
323 pedid->ycbcr422 = (buf[3] >> 4) & 0x01;
324 native_dtd_num = buf[3] & 0x0F;
325 pedid->base_audio_support = baseaudio_support;
327 /* Parse data block */
328 while (cur_offset < ddc_offset) {
329 tag = buf[cur_offset] >> 5;
331 case 0x02: /* Video Data Block */
332 hdmi_edid_debug("[EDID-CEA] It is a Video Data Block.\n");
333 hdmi_edid_get_cea_svd(buf + cur_offset, pedid);
335 case 0x01: /* Audio Data Block */
336 hdmi_edid_debug("[EDID-CEA] It is a Audio Data Block.\n");
337 hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);
339 case 0x04: /* Speaker Allocation Data Block */
340 hdmi_edid_debug("[EDID-CEA] It is a Speaker Allocation Data Block.\n");
342 case 0x03: /* Vendor Specific Data Block */
343 hdmi_edid_debug("[EDID-CEA] It is a Vendor Specific Data Block.\n");
344 hdmi_edid_parse_cea_sdb(buf + cur_offset, pedid);
346 case 0x05: /* VESA DTC Data Block */
347 hdmi_edid_debug("[EDID-CEA] It is a VESA DTC Data Block.\n");
349 case 0x07: /* Use Extended Tag */
350 hdmi_edid_debug("[EDID-CEA] It is a Use Extended Tag Data Block.\n");
353 hdmi_edid_error("[EDID-CEA] unkowned data block tag.\n");
356 cur_offset += (buf[cur_offset] & 0x1F) + 1;
361 struct fb_videomode *vmode = kmalloc(sizeof(struct fb_videomode),
364 return E_HDMI_EDID_SUCCESS;
365 /* buf[126] = 0 and buf[127] = checksum */
366 while (ddc_offset < HDMI_EDID_BLOCK_SIZE - 2) {
367 if (!buf[ddc_offset] && !buf[ddc_offset + 1])
369 memset(vmode, 0, sizeof(struct fb_videomode));
370 hdmi_edid_parse_dtd(buf + ddc_offset, vmode);
371 hdmi_add_videomode(vmode, &pedid->modelist);
377 return E_HDMI_EDID_SUCCESS;
380 static int hdmi_edid_parse_extensions(unsigned char *buf,
381 struct hdmi_edid *pedid)
385 if (buf == NULL || pedid == NULL)
386 return E_HDMI_EDID_PARAM;
389 rc = hdmi_edid_checksum(buf);
390 if (rc != E_HDMI_EDID_SUCCESS) {
391 hdmi_edid_error("[EDID] extensions block checksum error\n");
392 return E_HDMI_EDID_CHECKSUM;
397 hdmi_edid_debug("[EDID-EXTEND] It is a extensions block map.\n");
400 hdmi_edid_debug("[EDID-EXTEND] It is a CEA 861 Series Extension.\n");
401 hdmi_edid_parse_extensions_cea(buf, pedid);
404 hdmi_edid_debug("[EDID-EXTEND] It is a Video Timing Block Extension.\n");
407 hdmi_edid_debug("[EDID-EXTEND] It is a Display Information Extension.\n");
410 hdmi_edid_debug("[EDID-EXTEND] It is a Localized String Extension.\n");
413 hdmi_edid_debug("[EDID-EXTEND] It is a Digital Packet Video Link Extension.\n");
416 hdmi_edid_error("[EDID-EXTEND] Unkowned extension.\n");
417 return E_HDMI_EDID_UNKOWNDATA;
420 return E_HDMI_EDID_SUCCESS;
424 int hdmi_sys_parse_edid(struct hdmi *hdmi)
426 struct hdmi_edid *pedid;
427 unsigned char *buff = NULL;
428 int rc = HDMI_ERROR_SUCESS, extendblock = 0, i;
431 return HDMI_ERROR_FALSE;
433 pedid = &(hdmi->edid);
434 memset(pedid, 0, sizeof(struct hdmi_edid));
435 INIT_LIST_HEAD(&pedid->modelist);
437 buff = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
440 "[%s] can not allocate memory for edid buff.\n",
445 /* Read base block edid. */
446 memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
447 rc = hdmi->read_edid(hdmi, 0, buff);
449 dev_err(hdmi->dev, "[HDMI] read edid base block error\n");
452 rc = hdmi_edid_parse_base(buff, &extendblock, pedid);
454 dev_err(hdmi->dev, "[HDMI] parse edid base block error\n");
457 for (i = 1; i < extendblock + 1; i++) {
458 memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
459 rc = hdmi->read_edid(hdmi, i, buff);
461 printk("[HDMI] read edid block %d error\n", i);
464 rc = hdmi_edid_parse_extensions(buff, pedid);
466 dev_err(hdmi->dev, "[HDMI] parse edid block %d error\n",
473 rc = hdmi_ouputmode_select(hdmi, rc);