aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-08-31 04:12:40 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-09-30 09:16:46 -0400
commit937fce138ff295df6f3bbb3b07464e3902b6bc0f (patch)
tree21bce8b3607a0b8abb55f7b9f95de815f449a023
parent032b8ea508dd0c641785f338b87c342337419ed6 (diff)
OMAP: DSS2: HDMI: clean up edid reading & fix checksum
Clean up reading of EDID by passing direct address to the block being read, instead of start address of the whole EDID memory area. Rewrite the loop which reads the EDID. This also fixes the checksum calculation, which used to calculate the checksum only for the first block. Cc: Mythri P K <mythripk@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h6
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c67
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};
115int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); 114int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
116void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); 115void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
117int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, 116int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
118 u8 *pedid, u16 max_length);
119void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start); 117void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start);
120int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); 118int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
121void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); 119void 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
381int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, 391int 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
418static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, 419static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,