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;
226 pedid->cecaddress = buf[cur_offset + 5];
227 pedid->cecaddress |= buf[cur_offset + 4] << 8;
228 hdmi_edid_debug("[EDID-CEA] CEC Physical addres is 0x%08x.\n", pedid->cecaddress);
231 pedid->deepcolor = (buf[6] >> 3) & 0x0F;
232 supports_ai = buf[6] >> 7;
233 dc_48bit = (buf[6] >> 6) & 0x1;
234 dc_36bit = (buf[6] >> 5) & 0x1;
235 dc_30bit = (buf[6] >> 4) & 0x1;
236 dc_y444 = (buf[6] >> 3) & 0x1;
237 hdmi_edid_debug("[EDID-CEA] supports_ai %d\n"
238 "dc_48bit %d dc_36bit %d dc_30bit %d dc_y444 %d\n",
240 dc_48bit, dc_36bit, dc_30bit, dc_y444);
243 pedid->maxtmdsclock = buf[7] * 5000000;
246 pedid->latency_fields_present = (buf[8] & 0x80) ? 1 : 0;
247 pedid->i_latency_fields_present = (buf[8] & 0x40) ? 1 : 0;
248 pedid->video_present = (buf[8] & 0x20) ? 1 : 0;
252 if (count >= cur_offset) {
253 if (pedid->latency_fields_present == 1) {
254 pedid->video_latency = buf[cur_offset++];
255 pedid->audio_latency = buf[cur_offset++];
257 if (count >= cur_offset && pedid->i_latency_fields_present) {
258 pedid->interlaced_video_latency = buf[cur_offset++];
259 pedid->interlaced_audio_latency = buf[cur_offset++];
263 if (pedid->video_present == 0)
264 return E_HDMI_EDID_SUCCESS;
266 if (count >= cur_offset) {
267 pedid->support_3d = (buf[cur_offset++] & 0x80) ? 1 : 0;
269 len_4k = (buf[cur_offset] >> 5) & 0x07;
270 len_3d = buf[cur_offset] & 0x1F;
273 if (count >= cur_offset && len_4k > 0) {
274 for (i = 0; i < len_4k; i++) {
275 #ifndef HDMI_VERSION_2
276 vic = buf[cur_offset + i] & 0x7f;
277 if (vic > 0 && vic < 5)
278 vic = (vic == 4) ? 98 : (96 - vic);
279 hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
282 buf[cur_offset + i] >> 7);
284 vic = buf[cur_offset + i] & 0xff;
285 hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n",
286 buf[cur_offset + i], vic);
289 mode = hdmi_vic_to_videomode(vic);
291 hdmi_add_videomode(mode,
298 /* TODO Daisen wait to add
299 if (count >= cur_offset && pedid->support_3d && len_3d > 0) {
303 return E_HDMI_EDID_SUCCESS;
306 /* Parse CEA 861 Serial Extension. */
307 static int hdmi_edid_parse_extensions_cea(unsigned char *buf,
308 struct hdmi_edid *pedid)
310 unsigned int ddc_offset, native_dtd_num, cur_offset = 4;
311 unsigned int underscan_support, baseaudio_support;
315 return E_HDMI_EDID_PARAM;
317 /* Check ces extension version */
319 hdmi_edid_error("[EDID-CEA] error version.\n");
320 return E_HDMI_EDID_VERSION;
324 underscan_support = (buf[3] >> 7) & 0x01;
325 baseaudio_support = (buf[3] >> 6) & 0x01;
326 pedid->ycbcr444 = (buf[3] >> 5) & 0x01;
327 pedid->ycbcr422 = (buf[3] >> 4) & 0x01;
328 native_dtd_num = buf[3] & 0x0F;
329 pedid->base_audio_support = baseaudio_support;
331 /* Parse data block */
332 while (cur_offset < ddc_offset) {
333 tag = buf[cur_offset] >> 5;
335 case 0x02: /* Video Data Block */
336 hdmi_edid_debug("[EDID-CEA] It is a Video Data Block.\n");
337 hdmi_edid_get_cea_svd(buf + cur_offset, pedid);
339 case 0x01: /* Audio Data Block */
340 hdmi_edid_debug("[EDID-CEA] It is a Audio Data Block.\n");
341 hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);
343 case 0x04: /* Speaker Allocation Data Block */
344 hdmi_edid_debug("[EDID-CEA] It is a Speaker Allocation Data Block.\n");
346 case 0x03: /* Vendor Specific Data Block */
347 hdmi_edid_debug("[EDID-CEA] It is a Vendor Specific Data Block.\n");
348 hdmi_edid_parse_cea_sdb(buf + cur_offset, pedid);
350 case 0x05: /* VESA DTC Data Block */
351 hdmi_edid_debug("[EDID-CEA] It is a VESA DTC Data Block.\n");
353 case 0x07: /* Use Extended Tag */
354 hdmi_edid_debug("[EDID-CEA] It is a Use Extended Tag Data Block.\n");
357 hdmi_edid_error("[EDID-CEA] unkowned data block tag.\n");
360 cur_offset += (buf[cur_offset] & 0x1F) + 1;
365 struct fb_videomode *vmode = kmalloc(sizeof(struct fb_videomode),
368 return E_HDMI_EDID_SUCCESS;
369 /* buf[126] = 0 and buf[127] = checksum */
370 while (ddc_offset < HDMI_EDID_BLOCK_SIZE - 2) {
371 if (!buf[ddc_offset] && !buf[ddc_offset + 1])
373 memset(vmode, 0, sizeof(struct fb_videomode));
374 hdmi_edid_parse_dtd(buf + ddc_offset, vmode);
375 hdmi_add_videomode(vmode, &pedid->modelist);
381 return E_HDMI_EDID_SUCCESS;
384 static int hdmi_edid_parse_extensions(unsigned char *buf,
385 struct hdmi_edid *pedid)
389 if (buf == NULL || pedid == NULL)
390 return E_HDMI_EDID_PARAM;
393 rc = hdmi_edid_checksum(buf);
394 if (rc != E_HDMI_EDID_SUCCESS) {
395 hdmi_edid_error("[EDID] extensions block checksum error\n");
396 return E_HDMI_EDID_CHECKSUM;
401 hdmi_edid_debug("[EDID-EXTEND] It is a extensions block map.\n");
404 hdmi_edid_debug("[EDID-EXTEND] It is a CEA 861 Series Extension.\n");
405 hdmi_edid_parse_extensions_cea(buf, pedid);
408 hdmi_edid_debug("[EDID-EXTEND] It is a Video Timing Block Extension.\n");
411 hdmi_edid_debug("[EDID-EXTEND] It is a Display Information Extension.\n");
414 hdmi_edid_debug("[EDID-EXTEND] It is a Localized String Extension.\n");
417 hdmi_edid_debug("[EDID-EXTEND] It is a Digital Packet Video Link Extension.\n");
420 hdmi_edid_error("[EDID-EXTEND] Unkowned extension.\n");
421 return E_HDMI_EDID_UNKOWNDATA;
424 return E_HDMI_EDID_SUCCESS;
428 int hdmi_sys_parse_edid(struct hdmi *hdmi)
430 struct hdmi_edid *pedid;
431 unsigned char *buff = NULL;
432 int rc = HDMI_ERROR_SUCESS, extendblock = 0, i;
435 return HDMI_ERROR_FALSE;
437 pedid = &(hdmi->edid);
438 memset(pedid, 0, sizeof(struct hdmi_edid));
439 INIT_LIST_HEAD(&pedid->modelist);
441 buff = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
444 "[%s] can not allocate memory for edid buff.\n",
449 /* Read base block edid. */
450 memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
451 rc = hdmi->read_edid(hdmi, 0, buff);
453 dev_err(hdmi->dev, "[HDMI] read edid base block error\n");
456 rc = hdmi_edid_parse_base(buff, &extendblock, pedid);
458 dev_err(hdmi->dev, "[HDMI] parse edid base block error\n");
461 for (i = 1; i < extendblock + 1; i++) {
462 memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
463 rc = hdmi->read_edid(hdmi, i, buff);
465 printk("[HDMI] read edid block %d error\n", i);
468 rc = hdmi_edid_parse_extensions(buff, pedid);
470 dev_err(hdmi->dev, "[HDMI] parse edid block %d error\n",
477 rc = hdmi_ouputmode_select(hdmi, rc);