diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-08-22 10:47:56 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-09-30 09:16:46 -0400 |
commit | 032b8ea508dd0c641785f338b87c342337419ed6 (patch) | |
tree | 36e3c0c17ecf612daaa831e76e7404dab00a705a /drivers/video | |
parent | 2ea51fef8626debc6c3b73573cf99fae0593aa6a (diff) |
OMAP: DSS2: HDMI: split hdmi_core_ddc_edid
Split the DDC initialization off from hdmi_core_ddc_edid() into a
separate function hdmi_core_ddc_init(). This cleans up the
implementation.
Cc: Mythri P K <mythripk@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 117 |
1 files changed, 67 insertions, 50 deletions
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index d4cdfc2e6c5e..ecf854e2596c 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | |||
@@ -264,92 +264,105 @@ void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data) | |||
264 | hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); | 264 | hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); |
265 | } | 265 | } |
266 | 266 | ||
267 | static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, | 267 | static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data) |
268 | u8 *pedid, int ext) | ||
269 | { | 268 | { |
270 | u32 i, j; | 269 | void __iomem *base = hdmi_core_sys_base(ip_data); |
271 | char checksum = 0; | ||
272 | u32 offset = 0; | ||
273 | void __iomem *core_sys_base = hdmi_core_sys_base(ip_data); | ||
274 | 270 | ||
275 | /* Turn on CLK for DDC */ | 271 | /* Turn on CLK for DDC */ |
276 | REG_FLD_MOD(hdmi_av_base(ip_data), HDMI_CORE_AV_DPD, 0x7, 2, 0); | 272 | REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0); |
273 | |||
274 | /* IN_PROG */ | ||
275 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) { | ||
276 | /* Abort transaction */ | ||
277 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0); | ||
278 | /* IN_PROG */ | ||
279 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, | ||
280 | 4, 4, 0) != 0) { | ||
281 | DSSERR("Timeout aborting DDC transaction\n"); | ||
282 | return -ETIMEDOUT; | ||
283 | } | ||
284 | } | ||
277 | 285 | ||
278 | /* | 286 | /* Clk SCL Devices */ |
279 | * SW HACK : Without the Delay DDC(i2c bus) reads 0 values / | 287 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0); |
280 | * right shifted values( The behavior is not consistent and seen only | 288 | |
281 | * with some TV's) | 289 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ |
282 | */ | 290 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, |
283 | usleep_range(800, 1000); | 291 | 4, 4, 0) != 0) { |
292 | DSSERR("Timeout starting SCL clock\n"); | ||
293 | return -ETIMEDOUT; | ||
294 | } | ||
284 | 295 | ||
285 | if (!ext) { | 296 | /* Clear FIFO */ |
286 | /* Clk SCL Devices */ | 297 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0); |
287 | REG_FLD_MOD(core_sys_base, HDMI_CORE_DDC_CMD, 0xA, 3, 0); | ||
288 | 298 | ||
289 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | 299 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ |
290 | if (hdmi_wait_for_bit_change(core_sys_base, | 300 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, |
291 | HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) { | 301 | 4, 4, 0) != 0) { |
292 | pr_err("Failed to program DDC\n"); | 302 | DSSERR("Timeout clearing DDC fifo\n"); |
293 | return -ETIMEDOUT; | 303 | return -ETIMEDOUT; |
294 | } | 304 | } |
295 | 305 | ||
296 | /* Clear FIFO */ | 306 | return 0; |
297 | REG_FLD_MOD(core_sys_base, HDMI_CORE_DDC_CMD, 0x9, 3, 0); | 307 | } |
298 | 308 | ||
299 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | 309 | static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, |
300 | if (hdmi_wait_for_bit_change(core_sys_base, | 310 | u8 *pedid, int ext) |
301 | HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) { | 311 | { |
302 | pr_err("Failed to program DDC\n"); | 312 | void __iomem *base = hdmi_core_sys_base(ip_data); |
303 | return -ETIMEDOUT; | 313 | u32 i, j; |
304 | } | 314 | char checksum = 0; |
315 | u32 offset = 0; | ||
305 | 316 | ||
306 | } else { | 317 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ |
307 | if (ext % 2 != 0) | 318 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, |
308 | offset = 0x80; | 319 | 4, 4, 0) != 0) { |
320 | DSSERR("Timeout waiting DDC to be ready\n"); | ||
321 | return -ETIMEDOUT; | ||
309 | } | 322 | } |
310 | 323 | ||
324 | if (ext % 2 != 0) | ||
325 | offset = 0x80; | ||
326 | |||
311 | /* Load Segment Address Register */ | 327 | /* Load Segment Address Register */ |
312 | REG_FLD_MOD(core_sys_base, HDMI_CORE_DDC_SEGM, ext/2, 7, 0); | 328 | REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0); |
313 | 329 | ||
314 | /* Load Slave Address Register */ | 330 | /* Load Slave Address Register */ |
315 | REG_FLD_MOD(core_sys_base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); | 331 | REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); |
316 | 332 | ||
317 | /* Load Offset Address Register */ | 333 | /* Load Offset Address Register */ |
318 | REG_FLD_MOD(core_sys_base, HDMI_CORE_DDC_OFFSET, offset, 7, 0); | 334 | REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0); |
319 | 335 | ||
320 | /* Load Byte Count */ | 336 | /* Load Byte Count */ |
321 | REG_FLD_MOD(core_sys_base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); | 337 | REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); |
322 | REG_FLD_MOD(core_sys_base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); | 338 | REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); |
323 | 339 | ||
324 | /* Set DDC_CMD */ | 340 | /* Set DDC_CMD */ |
325 | if (ext) | 341 | if (ext) |
326 | REG_FLD_MOD(core_sys_base, HDMI_CORE_DDC_CMD, 0x4, 3, 0); | 342 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0); |
327 | else | 343 | else |
328 | REG_FLD_MOD(core_sys_base, HDMI_CORE_DDC_CMD, 0x2, 3, 0); | 344 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0); |
329 | 345 | ||
330 | /* HDMI_CORE_DDC_STATUS_BUS_LOW */ | 346 | /* HDMI_CORE_DDC_STATUS_BUS_LOW */ |
331 | if (REG_GET(core_sys_base, | 347 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) { |
332 | HDMI_CORE_DDC_STATUS, 6, 6) == 1) { | ||
333 | pr_err("I2C Bus Low?\n"); | 348 | pr_err("I2C Bus Low?\n"); |
334 | return -EIO; | 349 | return -EIO; |
335 | } | 350 | } |
336 | /* HDMI_CORE_DDC_STATUS_NO_ACK */ | 351 | /* HDMI_CORE_DDC_STATUS_NO_ACK */ |
337 | if (REG_GET(core_sys_base, | 352 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) { |
338 | HDMI_CORE_DDC_STATUS, 5, 5) == 1) { | ||
339 | pr_err("I2C No Ack\n"); | 353 | pr_err("I2C No Ack\n"); |
340 | return -EIO; | 354 | return -EIO; |
341 | } | 355 | } |
342 | 356 | ||
343 | i = ext * 128; | 357 | i = ext * 128; |
344 | j = 0; | 358 | j = 0; |
345 | while (((REG_GET(core_sys_base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) || | 359 | while (((REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) || |
346 | (REG_GET(core_sys_base, | 360 | (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && |
347 | HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && j < 128) { | 361 | j < 128) { |
348 | 362 | ||
349 | if (REG_GET(core_sys_base, HDMI_CORE_DDC_STATUS, 2, 2) == 0) { | 363 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 0) { |
350 | /* FIFO not empty */ | 364 | /* FIFO not empty */ |
351 | pedid[i++] = REG_GET(core_sys_base, | 365 | pedid[i++] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0); |
352 | HDMI_CORE_DDC_DATA, 7, 0); | ||
353 | j++; | 366 | j++; |
354 | } | 367 | } |
355 | } | 368 | } |
@@ -372,6 +385,10 @@ int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, | |||
372 | int max_ext_blocks = (max_length / 128) - 1; | 385 | int max_ext_blocks = (max_length / 128) - 1; |
373 | int len; | 386 | int len; |
374 | 387 | ||
388 | r = hdmi_core_ddc_init(ip_data); | ||
389 | if (r) | ||
390 | return r; | ||
391 | |||
375 | r = hdmi_core_ddc_edid(ip_data, pedid, 0); | 392 | r = hdmi_core_ddc_edid(ip_data, pedid, 0); |
376 | if (r) | 393 | if (r) |
377 | return r; | 394 | return r; |