diff options
-rw-r--r-- | drivers/video/omap2/dss/ti_hdmi.h | 6 | ||||
-rw-r--r-- | drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 67 |
2 files changed, 36 insertions, 37 deletions
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h index acf102267700..390cd85b122f 100644 --- a/drivers/video/omap2/dss/ti_hdmi.h +++ b/drivers/video/omap2/dss/ti_hdmi.h | |||
@@ -92,8 +92,7 @@ struct ti_hdmi_ip_ops { | |||
92 | 92 | ||
93 | void (*phy_disable)(struct hdmi_ip_data *ip_data); | 93 | void (*phy_disable)(struct hdmi_ip_data *ip_data); |
94 | 94 | ||
95 | int (*read_edid)(struct hdmi_ip_data *ip_data, | 95 | int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len); |
96 | u8 *pedid, u16 max_length); | ||
97 | 96 | ||
98 | int (*pll_enable)(struct hdmi_ip_data *ip_data); | 97 | int (*pll_enable)(struct hdmi_ip_data *ip_data); |
99 | 98 | ||
@@ -114,8 +113,7 @@ struct hdmi_ip_data { | |||
114 | }; | 113 | }; |
115 | int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); | 114 | int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); |
116 | void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); | 115 | void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); |
117 | int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, | 116 | int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); |
118 | u8 *pedid, u16 max_length); | ||
119 | void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start); | 117 | void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start); |
120 | int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); | 118 | int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); |
121 | void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); | 119 | void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); |
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index ecf854e2596c..e9885dcc4122 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | |||
@@ -310,8 +310,8 @@ static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, | |||
310 | u8 *pedid, int ext) | 310 | u8 *pedid, int ext) |
311 | { | 311 | { |
312 | void __iomem *base = hdmi_core_sys_base(ip_data); | 312 | void __iomem *base = hdmi_core_sys_base(ip_data); |
313 | u32 i, j; | 313 | u32 i; |
314 | char checksum = 0; | 314 | char checksum; |
315 | u32 offset = 0; | 315 | u32 offset = 0; |
316 | 316 | ||
317 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | 317 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ |
@@ -354,21 +354,31 @@ static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, | |||
354 | return -EIO; | 354 | return -EIO; |
355 | } | 355 | } |
356 | 356 | ||
357 | i = ext * 128; | 357 | for (i = 0; i < 0x80; ++i) { |
358 | j = 0; | 358 | int t; |
359 | while (((REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) || | ||
360 | (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && | ||
361 | j < 128) { | ||
362 | 359 | ||
363 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 0) { | 360 | /* IN_PROG */ |
364 | /* FIFO not empty */ | 361 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) { |
365 | pedid[i++] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0); | 362 | DSSERR("operation stopped when reading edid\n"); |
366 | j++; | 363 | return -EIO; |
364 | } | ||
365 | |||
366 | t = 0; | ||
367 | /* FIFO_EMPTY */ | ||
368 | while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) { | ||
369 | if (t++ > 10000) { | ||
370 | DSSERR("timeout reading edid\n"); | ||
371 | return -ETIMEDOUT; | ||
372 | } | ||
373 | udelay(1); | ||
367 | } | 374 | } |
375 | |||
376 | pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0); | ||
368 | } | 377 | } |
369 | 378 | ||
370 | for (j = 0; j < 128; j++) | 379 | checksum = 0; |
371 | checksum += pedid[j]; | 380 | for (i = 0; i < 0x80; ++i) |
381 | checksum += pedid[i]; | ||
372 | 382 | ||
373 | if (checksum != 0) { | 383 | if (checksum != 0) { |
374 | pr_err("E-EDID checksum failed!!\n"); | 384 | pr_err("E-EDID checksum failed!!\n"); |
@@ -379,40 +389,31 @@ static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, | |||
379 | } | 389 | } |
380 | 390 | ||
381 | int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, | 391 | int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, |
382 | u8 *pedid, u16 max_length) | 392 | u8 *edid, int len) |
383 | { | 393 | { |
384 | int r = 0, n = 0, i = 0; | 394 | int r, l; |
385 | int max_ext_blocks = (max_length / 128) - 1; | 395 | |
386 | int len; | 396 | if (len < 128) |
397 | return -EINVAL; | ||
387 | 398 | ||
388 | r = hdmi_core_ddc_init(ip_data); | 399 | r = hdmi_core_ddc_init(ip_data); |
389 | if (r) | 400 | if (r) |
390 | return r; | 401 | return r; |
391 | 402 | ||
392 | r = hdmi_core_ddc_edid(ip_data, pedid, 0); | 403 | r = hdmi_core_ddc_edid(ip_data, edid, 0); |
393 | if (r) | 404 | if (r) |
394 | return r; | 405 | return r; |
395 | 406 | ||
396 | len = 128; | 407 | l = 128; |
397 | n = pedid[0x7e]; | ||
398 | |||
399 | /* | ||
400 | * README: need to comply with max_length set by the caller. | ||
401 | * Better implementation should be to allocate necessary | ||
402 | * memory to store EDID according to nb_block field found | ||
403 | * in first block | ||
404 | */ | ||
405 | if (n > max_ext_blocks) | ||
406 | n = max_ext_blocks; | ||
407 | 408 | ||
408 | for (i = 1; i <= n; i++) { | 409 | if (len >= 128 * 2 && edid[0x7e] > 0) { |
409 | r = hdmi_core_ddc_edid(ip_data, pedid, i); | 410 | r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1); |
410 | if (r) | 411 | if (r) |
411 | return r; | 412 | return r; |
412 | len += 128; | 413 | l += 128; |
413 | } | 414 | } |
414 | 415 | ||
415 | return len; | 416 | return l; |
416 | } | 417 | } |
417 | 418 | ||
418 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | 419 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, |