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, |
