diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/video/omap2/displays/panel-taal.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/video/omap2/displays/panel-taal.c')
-rw-r--r-- | drivers/video/omap2/displays/panel-taal.c | 631 |
1 files changed, 504 insertions, 127 deletions
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index e1c765d11419..fdd5d4ae437d 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -33,8 +33,8 @@ | |||
33 | #include <linux/regulator/consumer.h> | 33 | #include <linux/regulator/consumer.h> |
34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
35 | 35 | ||
36 | #include <plat/display.h> | 36 | #include <video/omapdss.h> |
37 | #include <plat/nokia-dsi-panel.h> | 37 | #include <video/omap-panel-nokia-dsi.h> |
38 | 38 | ||
39 | /* DSI Virtual channel. Hardcoded for now. */ | 39 | /* DSI Virtual channel. Hardcoded for now. */ |
40 | #define TCH 0 | 40 | #define TCH 0 |
@@ -63,12 +63,12 @@ | |||
63 | #define DCS_GET_ID2 0xdb | 63 | #define DCS_GET_ID2 0xdb |
64 | #define DCS_GET_ID3 0xdc | 64 | #define DCS_GET_ID3 0xdc |
65 | 65 | ||
66 | #define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000) | ||
67 | |||
68 | static irqreturn_t taal_te_isr(int irq, void *data); | 66 | static irqreturn_t taal_te_isr(int irq, void *data); |
69 | static void taal_te_timeout_work_callback(struct work_struct *work); | 67 | static void taal_te_timeout_work_callback(struct work_struct *work); |
70 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); | 68 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); |
71 | 69 | ||
70 | static int taal_panel_reset(struct omap_dss_device *dssdev); | ||
71 | |||
72 | struct panel_regulator { | 72 | struct panel_regulator { |
73 | struct regulator *regulator; | 73 | struct regulator *regulator; |
74 | const char *name; | 74 | const char *name; |
@@ -218,6 +218,8 @@ struct taal_data { | |||
218 | u16 w; | 218 | u16 w; |
219 | u16 h; | 219 | u16 h; |
220 | } update_region; | 220 | } update_region; |
221 | int channel; | ||
222 | |||
221 | struct delayed_work te_timeout_work; | 223 | struct delayed_work te_timeout_work; |
222 | 224 | ||
223 | bool use_dsi_bl; | 225 | bool use_dsi_bl; |
@@ -227,8 +229,14 @@ struct taal_data { | |||
227 | 229 | ||
228 | bool intro_printed; | 230 | bool intro_printed; |
229 | 231 | ||
230 | struct workqueue_struct *esd_wq; | 232 | struct workqueue_struct *workqueue; |
233 | |||
231 | struct delayed_work esd_work; | 234 | struct delayed_work esd_work; |
235 | unsigned esd_interval; | ||
236 | |||
237 | bool ulps_enabled; | ||
238 | unsigned ulps_timeout; | ||
239 | struct delayed_work ulps_work; | ||
232 | 240 | ||
233 | struct panel_config *panel_config; | 241 | struct panel_config *panel_config; |
234 | }; | 242 | }; |
@@ -240,6 +248,7 @@ static inline struct nokia_dsi_panel_data | |||
240 | } | 248 | } |
241 | 249 | ||
242 | static void taal_esd_work(struct work_struct *work); | 250 | static void taal_esd_work(struct work_struct *work); |
251 | static void taal_ulps_work(struct work_struct *work); | ||
243 | 252 | ||
244 | static void hw_guard_start(struct taal_data *td, int guard_msec) | 253 | static void hw_guard_start(struct taal_data *td, int guard_msec) |
245 | { | 254 | { |
@@ -257,12 +266,12 @@ static void hw_guard_wait(struct taal_data *td) | |||
257 | } | 266 | } |
258 | } | 267 | } |
259 | 268 | ||
260 | static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) | 269 | static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data) |
261 | { | 270 | { |
262 | int r; | 271 | int r; |
263 | u8 buf[1]; | 272 | u8 buf[1]; |
264 | 273 | ||
265 | r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1); | 274 | r = dsi_vc_dcs_read(td->dssdev, td->channel, dcs_cmd, buf, 1); |
266 | 275 | ||
267 | if (r < 0) | 276 | if (r < 0) |
268 | return r; | 277 | return r; |
@@ -272,17 +281,17 @@ static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) | |||
272 | return 0; | 281 | return 0; |
273 | } | 282 | } |
274 | 283 | ||
275 | static int taal_dcs_write_0(u8 dcs_cmd) | 284 | static int taal_dcs_write_0(struct taal_data *td, u8 dcs_cmd) |
276 | { | 285 | { |
277 | return dsi_vc_dcs_write(TCH, &dcs_cmd, 1); | 286 | return dsi_vc_dcs_write(td->dssdev, td->channel, &dcs_cmd, 1); |
278 | } | 287 | } |
279 | 288 | ||
280 | static int taal_dcs_write_1(u8 dcs_cmd, u8 param) | 289 | static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param) |
281 | { | 290 | { |
282 | u8 buf[2]; | 291 | u8 buf[2]; |
283 | buf[0] = dcs_cmd; | 292 | buf[0] = dcs_cmd; |
284 | buf[1] = param; | 293 | buf[1] = param; |
285 | return dsi_vc_dcs_write(TCH, buf, 2); | 294 | return dsi_vc_dcs_write(td->dssdev, td->channel, buf, 2); |
286 | } | 295 | } |
287 | 296 | ||
288 | static int taal_sleep_in(struct taal_data *td) | 297 | static int taal_sleep_in(struct taal_data *td) |
@@ -294,7 +303,7 @@ static int taal_sleep_in(struct taal_data *td) | |||
294 | hw_guard_wait(td); | 303 | hw_guard_wait(td); |
295 | 304 | ||
296 | cmd = DCS_SLEEP_IN; | 305 | cmd = DCS_SLEEP_IN; |
297 | r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1); | 306 | r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1); |
298 | if (r) | 307 | if (r) |
299 | return r; | 308 | return r; |
300 | 309 | ||
@@ -312,7 +321,7 @@ static int taal_sleep_out(struct taal_data *td) | |||
312 | 321 | ||
313 | hw_guard_wait(td); | 322 | hw_guard_wait(td); |
314 | 323 | ||
315 | r = taal_dcs_write_0(DCS_SLEEP_OUT); | 324 | r = taal_dcs_write_0(td, DCS_SLEEP_OUT); |
316 | if (r) | 325 | if (r) |
317 | return r; | 326 | return r; |
318 | 327 | ||
@@ -324,30 +333,30 @@ static int taal_sleep_out(struct taal_data *td) | |||
324 | return 0; | 333 | return 0; |
325 | } | 334 | } |
326 | 335 | ||
327 | static int taal_get_id(u8 *id1, u8 *id2, u8 *id3) | 336 | static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3) |
328 | { | 337 | { |
329 | int r; | 338 | int r; |
330 | 339 | ||
331 | r = taal_dcs_read_1(DCS_GET_ID1, id1); | 340 | r = taal_dcs_read_1(td, DCS_GET_ID1, id1); |
332 | if (r) | 341 | if (r) |
333 | return r; | 342 | return r; |
334 | r = taal_dcs_read_1(DCS_GET_ID2, id2); | 343 | r = taal_dcs_read_1(td, DCS_GET_ID2, id2); |
335 | if (r) | 344 | if (r) |
336 | return r; | 345 | return r; |
337 | r = taal_dcs_read_1(DCS_GET_ID3, id3); | 346 | r = taal_dcs_read_1(td, DCS_GET_ID3, id3); |
338 | if (r) | 347 | if (r) |
339 | return r; | 348 | return r; |
340 | 349 | ||
341 | return 0; | 350 | return 0; |
342 | } | 351 | } |
343 | 352 | ||
344 | static int taal_set_addr_mode(u8 rotate, bool mirror) | 353 | static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror) |
345 | { | 354 | { |
346 | int r; | 355 | int r; |
347 | u8 mode; | 356 | u8 mode; |
348 | int b5, b6, b7; | 357 | int b5, b6, b7; |
349 | 358 | ||
350 | r = taal_dcs_read_1(DCS_READ_MADCTL, &mode); | 359 | r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode); |
351 | if (r) | 360 | if (r) |
352 | return r; | 361 | return r; |
353 | 362 | ||
@@ -381,10 +390,11 @@ static int taal_set_addr_mode(u8 rotate, bool mirror) | |||
381 | mode &= ~((1<<7) | (1<<6) | (1<<5)); | 390 | mode &= ~((1<<7) | (1<<6) | (1<<5)); |
382 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); | 391 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); |
383 | 392 | ||
384 | return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode); | 393 | return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode); |
385 | } | 394 | } |
386 | 395 | ||
387 | static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) | 396 | static int taal_set_update_window(struct taal_data *td, |
397 | u16 x, u16 y, u16 w, u16 h) | ||
388 | { | 398 | { |
389 | int r; | 399 | int r; |
390 | u16 x1 = x; | 400 | u16 x1 = x; |
@@ -399,7 +409,7 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) | |||
399 | buf[3] = (x2 >> 8) & 0xff; | 409 | buf[3] = (x2 >> 8) & 0xff; |
400 | buf[4] = (x2 >> 0) & 0xff; | 410 | buf[4] = (x2 >> 0) & 0xff; |
401 | 411 | ||
402 | r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); | 412 | r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, buf, sizeof(buf)); |
403 | if (r) | 413 | if (r) |
404 | return r; | 414 | return r; |
405 | 415 | ||
@@ -409,15 +419,132 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) | |||
409 | buf[3] = (y2 >> 8) & 0xff; | 419 | buf[3] = (y2 >> 8) & 0xff; |
410 | buf[4] = (y2 >> 0) & 0xff; | 420 | buf[4] = (y2 >> 0) & 0xff; |
411 | 421 | ||
412 | r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); | 422 | r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, buf, sizeof(buf)); |
413 | if (r) | 423 | if (r) |
414 | return r; | 424 | return r; |
415 | 425 | ||
416 | dsi_vc_send_bta_sync(TCH); | 426 | dsi_vc_send_bta_sync(td->dssdev, td->channel); |
427 | |||
428 | return r; | ||
429 | } | ||
430 | |||
431 | static void taal_queue_esd_work(struct omap_dss_device *dssdev) | ||
432 | { | ||
433 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
434 | |||
435 | if (td->esd_interval > 0) | ||
436 | queue_delayed_work(td->workqueue, &td->esd_work, | ||
437 | msecs_to_jiffies(td->esd_interval)); | ||
438 | } | ||
439 | |||
440 | static void taal_cancel_esd_work(struct omap_dss_device *dssdev) | ||
441 | { | ||
442 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
443 | |||
444 | cancel_delayed_work(&td->esd_work); | ||
445 | } | ||
446 | |||
447 | static void taal_queue_ulps_work(struct omap_dss_device *dssdev) | ||
448 | { | ||
449 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
450 | |||
451 | if (td->ulps_timeout > 0) | ||
452 | queue_delayed_work(td->workqueue, &td->ulps_work, | ||
453 | msecs_to_jiffies(td->ulps_timeout)); | ||
454 | } | ||
455 | |||
456 | static void taal_cancel_ulps_work(struct omap_dss_device *dssdev) | ||
457 | { | ||
458 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
459 | |||
460 | cancel_delayed_work(&td->ulps_work); | ||
461 | } | ||
462 | |||
463 | static int taal_enter_ulps(struct omap_dss_device *dssdev) | ||
464 | { | ||
465 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
466 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
467 | int r; | ||
468 | |||
469 | if (td->ulps_enabled) | ||
470 | return 0; | ||
471 | |||
472 | taal_cancel_ulps_work(dssdev); | ||
473 | |||
474 | r = _taal_enable_te(dssdev, false); | ||
475 | if (r) | ||
476 | goto err; | ||
477 | |||
478 | disable_irq(gpio_to_irq(panel_data->ext_te_gpio)); | ||
479 | |||
480 | omapdss_dsi_display_disable(dssdev, false, true); | ||
481 | |||
482 | td->ulps_enabled = true; | ||
483 | |||
484 | return 0; | ||
485 | |||
486 | err: | ||
487 | dev_err(&dssdev->dev, "enter ULPS failed"); | ||
488 | taal_panel_reset(dssdev); | ||
489 | |||
490 | td->ulps_enabled = false; | ||
491 | |||
492 | taal_queue_ulps_work(dssdev); | ||
493 | |||
494 | return r; | ||
495 | } | ||
496 | |||
497 | static int taal_exit_ulps(struct omap_dss_device *dssdev) | ||
498 | { | ||
499 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
500 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
501 | int r; | ||
502 | |||
503 | if (!td->ulps_enabled) | ||
504 | return 0; | ||
505 | |||
506 | r = omapdss_dsi_display_enable(dssdev); | ||
507 | if (r) | ||
508 | goto err; | ||
509 | |||
510 | omapdss_dsi_vc_enable_hs(dssdev, td->channel, true); | ||
511 | |||
512 | r = _taal_enable_te(dssdev, true); | ||
513 | if (r) | ||
514 | goto err; | ||
515 | |||
516 | enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); | ||
517 | |||
518 | taal_queue_ulps_work(dssdev); | ||
519 | |||
520 | td->ulps_enabled = false; | ||
521 | |||
522 | return 0; | ||
523 | |||
524 | err: | ||
525 | dev_err(&dssdev->dev, "exit ULPS failed"); | ||
526 | r = taal_panel_reset(dssdev); | ||
527 | |||
528 | enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); | ||
529 | td->ulps_enabled = false; | ||
530 | |||
531 | taal_queue_ulps_work(dssdev); | ||
417 | 532 | ||
418 | return r; | 533 | return r; |
419 | } | 534 | } |
420 | 535 | ||
536 | static int taal_wake_up(struct omap_dss_device *dssdev) | ||
537 | { | ||
538 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
539 | |||
540 | if (td->ulps_enabled) | ||
541 | return taal_exit_ulps(dssdev); | ||
542 | |||
543 | taal_cancel_ulps_work(dssdev); | ||
544 | taal_queue_ulps_work(dssdev); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
421 | static int taal_bl_update_status(struct backlight_device *dev) | 548 | static int taal_bl_update_status(struct backlight_device *dev) |
422 | { | 549 | { |
423 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); | 550 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); |
@@ -438,9 +565,13 @@ static int taal_bl_update_status(struct backlight_device *dev) | |||
438 | 565 | ||
439 | if (td->use_dsi_bl) { | 566 | if (td->use_dsi_bl) { |
440 | if (td->enabled) { | 567 | if (td->enabled) { |
441 | dsi_bus_lock(); | 568 | dsi_bus_lock(dssdev); |
442 | r = taal_dcs_write_1(DCS_BRIGHTNESS, level); | 569 | |
443 | dsi_bus_unlock(); | 570 | r = taal_wake_up(dssdev); |
571 | if (!r) | ||
572 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); | ||
573 | |||
574 | dsi_bus_unlock(dssdev); | ||
444 | } else { | 575 | } else { |
445 | r = 0; | 576 | r = 0; |
446 | } | 577 | } |
@@ -465,7 +596,7 @@ static int taal_bl_get_intensity(struct backlight_device *dev) | |||
465 | return 0; | 596 | return 0; |
466 | } | 597 | } |
467 | 598 | ||
468 | static struct backlight_ops taal_bl_ops = { | 599 | static const struct backlight_ops taal_bl_ops = { |
469 | .get_brightness = taal_bl_get_intensity, | 600 | .get_brightness = taal_bl_get_intensity, |
470 | .update_status = taal_bl_update_status, | 601 | .update_status = taal_bl_update_status, |
471 | }; | 602 | }; |
@@ -501,9 +632,13 @@ static ssize_t taal_num_errors_show(struct device *dev, | |||
501 | mutex_lock(&td->lock); | 632 | mutex_lock(&td->lock); |
502 | 633 | ||
503 | if (td->enabled) { | 634 | if (td->enabled) { |
504 | dsi_bus_lock(); | 635 | dsi_bus_lock(dssdev); |
505 | r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); | 636 | |
506 | dsi_bus_unlock(); | 637 | r = taal_wake_up(dssdev); |
638 | if (!r) | ||
639 | r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors); | ||
640 | |||
641 | dsi_bus_unlock(dssdev); | ||
507 | } else { | 642 | } else { |
508 | r = -ENODEV; | 643 | r = -ENODEV; |
509 | } | 644 | } |
@@ -527,9 +662,13 @@ static ssize_t taal_hw_revision_show(struct device *dev, | |||
527 | mutex_lock(&td->lock); | 662 | mutex_lock(&td->lock); |
528 | 663 | ||
529 | if (td->enabled) { | 664 | if (td->enabled) { |
530 | dsi_bus_lock(); | 665 | dsi_bus_lock(dssdev); |
531 | r = taal_get_id(&id1, &id2, &id3); | 666 | |
532 | dsi_bus_unlock(); | 667 | r = taal_wake_up(dssdev); |
668 | if (!r) | ||
669 | r = taal_get_id(td, &id1, &id2, &id3); | ||
670 | |||
671 | dsi_bus_unlock(dssdev); | ||
533 | } else { | 672 | } else { |
534 | r = -ENODEV; | 673 | r = -ENODEV; |
535 | } | 674 | } |
@@ -576,6 +715,7 @@ static ssize_t store_cabc_mode(struct device *dev, | |||
576 | struct omap_dss_device *dssdev = to_dss_device(dev); | 715 | struct omap_dss_device *dssdev = to_dss_device(dev); |
577 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 716 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
578 | int i; | 717 | int i; |
718 | int r; | ||
579 | 719 | ||
580 | for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { | 720 | for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { |
581 | if (sysfs_streq(cabc_modes[i], buf)) | 721 | if (sysfs_streq(cabc_modes[i], buf)) |
@@ -588,10 +728,19 @@ static ssize_t store_cabc_mode(struct device *dev, | |||
588 | mutex_lock(&td->lock); | 728 | mutex_lock(&td->lock); |
589 | 729 | ||
590 | if (td->enabled) { | 730 | if (td->enabled) { |
591 | dsi_bus_lock(); | 731 | dsi_bus_lock(dssdev); |
592 | if (!td->cabc_broken) | 732 | |
593 | taal_dcs_write_1(DCS_WRITE_CABC, i); | 733 | if (!td->cabc_broken) { |
594 | dsi_bus_unlock(); | 734 | r = taal_wake_up(dssdev); |
735 | if (r) | ||
736 | goto err; | ||
737 | |||
738 | r = taal_dcs_write_1(td, DCS_WRITE_CABC, i); | ||
739 | if (r) | ||
740 | goto err; | ||
741 | } | ||
742 | |||
743 | dsi_bus_unlock(dssdev); | ||
595 | } | 744 | } |
596 | 745 | ||
597 | td->cabc_mode = i; | 746 | td->cabc_mode = i; |
@@ -599,6 +748,10 @@ static ssize_t store_cabc_mode(struct device *dev, | |||
599 | mutex_unlock(&td->lock); | 748 | mutex_unlock(&td->lock); |
600 | 749 | ||
601 | return count; | 750 | return count; |
751 | err: | ||
752 | dsi_bus_unlock(dssdev); | ||
753 | mutex_unlock(&td->lock); | ||
754 | return r; | ||
602 | } | 755 | } |
603 | 756 | ||
604 | static ssize_t show_cabc_available_modes(struct device *dev, | 757 | static ssize_t show_cabc_available_modes(struct device *dev, |
@@ -617,18 +770,161 @@ static ssize_t show_cabc_available_modes(struct device *dev, | |||
617 | return len < PAGE_SIZE ? len : PAGE_SIZE - 1; | 770 | return len < PAGE_SIZE ? len : PAGE_SIZE - 1; |
618 | } | 771 | } |
619 | 772 | ||
773 | static ssize_t taal_store_esd_interval(struct device *dev, | ||
774 | struct device_attribute *attr, | ||
775 | const char *buf, size_t count) | ||
776 | { | ||
777 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
778 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
779 | |||
780 | unsigned long t; | ||
781 | int r; | ||
782 | |||
783 | r = strict_strtoul(buf, 10, &t); | ||
784 | if (r) | ||
785 | return r; | ||
786 | |||
787 | mutex_lock(&td->lock); | ||
788 | taal_cancel_esd_work(dssdev); | ||
789 | td->esd_interval = t; | ||
790 | if (td->enabled) | ||
791 | taal_queue_esd_work(dssdev); | ||
792 | mutex_unlock(&td->lock); | ||
793 | |||
794 | return count; | ||
795 | } | ||
796 | |||
797 | static ssize_t taal_show_esd_interval(struct device *dev, | ||
798 | struct device_attribute *attr, | ||
799 | char *buf) | ||
800 | { | ||
801 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
802 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
803 | unsigned t; | ||
804 | |||
805 | mutex_lock(&td->lock); | ||
806 | t = td->esd_interval; | ||
807 | mutex_unlock(&td->lock); | ||
808 | |||
809 | return snprintf(buf, PAGE_SIZE, "%u\n", t); | ||
810 | } | ||
811 | |||
812 | static ssize_t taal_store_ulps(struct device *dev, | ||
813 | struct device_attribute *attr, | ||
814 | const char *buf, size_t count) | ||
815 | { | ||
816 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
817 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
818 | unsigned long t; | ||
819 | int r; | ||
820 | |||
821 | r = strict_strtoul(buf, 10, &t); | ||
822 | if (r) | ||
823 | return r; | ||
824 | |||
825 | mutex_lock(&td->lock); | ||
826 | |||
827 | if (td->enabled) { | ||
828 | dsi_bus_lock(dssdev); | ||
829 | |||
830 | if (t) | ||
831 | r = taal_enter_ulps(dssdev); | ||
832 | else | ||
833 | r = taal_wake_up(dssdev); | ||
834 | |||
835 | dsi_bus_unlock(dssdev); | ||
836 | } | ||
837 | |||
838 | mutex_unlock(&td->lock); | ||
839 | |||
840 | if (r) | ||
841 | return r; | ||
842 | |||
843 | return count; | ||
844 | } | ||
845 | |||
846 | static ssize_t taal_show_ulps(struct device *dev, | ||
847 | struct device_attribute *attr, | ||
848 | char *buf) | ||
849 | { | ||
850 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
851 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
852 | unsigned t; | ||
853 | |||
854 | mutex_lock(&td->lock); | ||
855 | t = td->ulps_enabled; | ||
856 | mutex_unlock(&td->lock); | ||
857 | |||
858 | return snprintf(buf, PAGE_SIZE, "%u\n", t); | ||
859 | } | ||
860 | |||
861 | static ssize_t taal_store_ulps_timeout(struct device *dev, | ||
862 | struct device_attribute *attr, | ||
863 | const char *buf, size_t count) | ||
864 | { | ||
865 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
866 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
867 | unsigned long t; | ||
868 | int r; | ||
869 | |||
870 | r = strict_strtoul(buf, 10, &t); | ||
871 | if (r) | ||
872 | return r; | ||
873 | |||
874 | mutex_lock(&td->lock); | ||
875 | td->ulps_timeout = t; | ||
876 | |||
877 | if (td->enabled) { | ||
878 | /* taal_wake_up will restart the timer */ | ||
879 | dsi_bus_lock(dssdev); | ||
880 | r = taal_wake_up(dssdev); | ||
881 | dsi_bus_unlock(dssdev); | ||
882 | } | ||
883 | |||
884 | mutex_unlock(&td->lock); | ||
885 | |||
886 | if (r) | ||
887 | return r; | ||
888 | |||
889 | return count; | ||
890 | } | ||
891 | |||
892 | static ssize_t taal_show_ulps_timeout(struct device *dev, | ||
893 | struct device_attribute *attr, | ||
894 | char *buf) | ||
895 | { | ||
896 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
897 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
898 | unsigned t; | ||
899 | |||
900 | mutex_lock(&td->lock); | ||
901 | t = td->ulps_timeout; | ||
902 | mutex_unlock(&td->lock); | ||
903 | |||
904 | return snprintf(buf, PAGE_SIZE, "%u\n", t); | ||
905 | } | ||
906 | |||
620 | static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); | 907 | static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); |
621 | static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); | 908 | static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); |
622 | static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, | 909 | static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, |
623 | show_cabc_mode, store_cabc_mode); | 910 | show_cabc_mode, store_cabc_mode); |
624 | static DEVICE_ATTR(cabc_available_modes, S_IRUGO, | 911 | static DEVICE_ATTR(cabc_available_modes, S_IRUGO, |
625 | show_cabc_available_modes, NULL); | 912 | show_cabc_available_modes, NULL); |
913 | static DEVICE_ATTR(esd_interval, S_IRUGO | S_IWUSR, | ||
914 | taal_show_esd_interval, taal_store_esd_interval); | ||
915 | static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR, | ||
916 | taal_show_ulps, taal_store_ulps); | ||
917 | static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR, | ||
918 | taal_show_ulps_timeout, taal_store_ulps_timeout); | ||
626 | 919 | ||
627 | static struct attribute *taal_attrs[] = { | 920 | static struct attribute *taal_attrs[] = { |
628 | &dev_attr_num_dsi_errors.attr, | 921 | &dev_attr_num_dsi_errors.attr, |
629 | &dev_attr_hw_revision.attr, | 922 | &dev_attr_hw_revision.attr, |
630 | &dev_attr_cabc_mode.attr, | 923 | &dev_attr_cabc_mode.attr, |
631 | &dev_attr_cabc_available_modes.attr, | 924 | &dev_attr_cabc_available_modes.attr, |
925 | &dev_attr_esd_interval.attr, | ||
926 | &dev_attr_ulps.attr, | ||
927 | &dev_attr_ulps_timeout.attr, | ||
632 | NULL, | 928 | NULL, |
633 | }; | 929 | }; |
634 | 930 | ||
@@ -697,6 +993,9 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
697 | } | 993 | } |
698 | td->dssdev = dssdev; | 994 | td->dssdev = dssdev; |
699 | td->panel_config = panel_config; | 995 | td->panel_config = panel_config; |
996 | td->esd_interval = panel_data->esd_interval; | ||
997 | td->ulps_enabled = false; | ||
998 | td->ulps_timeout = panel_data->ulps_timeout; | ||
700 | 999 | ||
701 | mutex_init(&td->lock); | 1000 | mutex_init(&td->lock); |
702 | 1001 | ||
@@ -707,13 +1006,14 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
707 | if (r) | 1006 | if (r) |
708 | goto err_reg; | 1007 | goto err_reg; |
709 | 1008 | ||
710 | td->esd_wq = create_singlethread_workqueue("taal_esd"); | 1009 | td->workqueue = create_singlethread_workqueue("taal_esd"); |
711 | if (td->esd_wq == NULL) { | 1010 | if (td->workqueue == NULL) { |
712 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); | 1011 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); |
713 | r = -ENOMEM; | 1012 | r = -ENOMEM; |
714 | goto err_wq; | 1013 | goto err_wq; |
715 | } | 1014 | } |
716 | INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); | 1015 | INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); |
1016 | INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work); | ||
717 | 1017 | ||
718 | dev_set_drvdata(&dssdev->dev, td); | 1018 | dev_set_drvdata(&dssdev->dev, td); |
719 | 1019 | ||
@@ -729,8 +1029,10 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
729 | props.max_brightness = 255; | 1029 | props.max_brightness = 255; |
730 | else | 1030 | else |
731 | props.max_brightness = 127; | 1031 | props.max_brightness = 127; |
732 | bldev = backlight_device_register("taal", &dssdev->dev, dssdev, | 1032 | |
733 | &taal_bl_ops, &props); | 1033 | props.type = BACKLIGHT_RAW; |
1034 | bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, | ||
1035 | dssdev, &taal_bl_ops, &props); | ||
734 | if (IS_ERR(bldev)) { | 1036 | if (IS_ERR(bldev)) { |
735 | r = PTR_ERR(bldev); | 1037 | r = PTR_ERR(bldev); |
736 | goto err_bl; | 1038 | goto err_bl; |
@@ -774,14 +1076,29 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
774 | dev_dbg(&dssdev->dev, "Using GPIO TE\n"); | 1076 | dev_dbg(&dssdev->dev, "Using GPIO TE\n"); |
775 | } | 1077 | } |
776 | 1078 | ||
1079 | r = omap_dsi_request_vc(dssdev, &td->channel); | ||
1080 | if (r) { | ||
1081 | dev_err(&dssdev->dev, "failed to get virtual channel\n"); | ||
1082 | goto err_req_vc; | ||
1083 | } | ||
1084 | |||
1085 | r = omap_dsi_set_vc_id(dssdev, td->channel, TCH); | ||
1086 | if (r) { | ||
1087 | dev_err(&dssdev->dev, "failed to set VC_ID\n"); | ||
1088 | goto err_vc_id; | ||
1089 | } | ||
1090 | |||
777 | r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); | 1091 | r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); |
778 | if (r) { | 1092 | if (r) { |
779 | dev_err(&dssdev->dev, "failed to create sysfs files\n"); | 1093 | dev_err(&dssdev->dev, "failed to create sysfs files\n"); |
780 | goto err_sysfs; | 1094 | goto err_vc_id; |
781 | } | 1095 | } |
782 | 1096 | ||
783 | return 0; | 1097 | return 0; |
784 | err_sysfs: | 1098 | |
1099 | err_vc_id: | ||
1100 | omap_dsi_release_vc(dssdev, td->channel); | ||
1101 | err_req_vc: | ||
785 | if (panel_data->use_ext_te) | 1102 | if (panel_data->use_ext_te) |
786 | free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); | 1103 | free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); |
787 | err_irq: | 1104 | err_irq: |
@@ -790,7 +1107,7 @@ err_irq: | |||
790 | err_gpio: | 1107 | err_gpio: |
791 | backlight_device_unregister(bldev); | 1108 | backlight_device_unregister(bldev); |
792 | err_bl: | 1109 | err_bl: |
793 | destroy_workqueue(td->esd_wq); | 1110 | destroy_workqueue(td->workqueue); |
794 | err_wq: | 1111 | err_wq: |
795 | free_regulators(panel_config->regulators, panel_config->num_regulators); | 1112 | free_regulators(panel_config->regulators, panel_config->num_regulators); |
796 | err_reg: | 1113 | err_reg: |
@@ -799,7 +1116,7 @@ err: | |||
799 | return r; | 1116 | return r; |
800 | } | 1117 | } |
801 | 1118 | ||
802 | static void taal_remove(struct omap_dss_device *dssdev) | 1119 | static void __exit taal_remove(struct omap_dss_device *dssdev) |
803 | { | 1120 | { |
804 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1121 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
805 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 1122 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); |
@@ -808,6 +1125,7 @@ static void taal_remove(struct omap_dss_device *dssdev) | |||
808 | dev_dbg(&dssdev->dev, "remove\n"); | 1125 | dev_dbg(&dssdev->dev, "remove\n"); |
809 | 1126 | ||
810 | sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); | 1127 | sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); |
1128 | omap_dsi_release_vc(dssdev, td->channel); | ||
811 | 1129 | ||
812 | if (panel_data->use_ext_te) { | 1130 | if (panel_data->use_ext_te) { |
813 | int gpio = panel_data->ext_te_gpio; | 1131 | int gpio = panel_data->ext_te_gpio; |
@@ -820,8 +1138,9 @@ static void taal_remove(struct omap_dss_device *dssdev) | |||
820 | taal_bl_update_status(bldev); | 1138 | taal_bl_update_status(bldev); |
821 | backlight_device_unregister(bldev); | 1139 | backlight_device_unregister(bldev); |
822 | 1140 | ||
823 | cancel_delayed_work(&td->esd_work); | 1141 | taal_cancel_ulps_work(dssdev); |
824 | destroy_workqueue(td->esd_wq); | 1142 | taal_cancel_esd_work(dssdev); |
1143 | destroy_workqueue(td->workqueue); | ||
825 | 1144 | ||
826 | /* reset, to be sure that the panel is in a valid state */ | 1145 | /* reset, to be sure that the panel is in a valid state */ |
827 | taal_hw_reset(dssdev); | 1146 | taal_hw_reset(dssdev); |
@@ -846,13 +1165,13 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
846 | 1165 | ||
847 | taal_hw_reset(dssdev); | 1166 | taal_hw_reset(dssdev); |
848 | 1167 | ||
849 | omapdss_dsi_vc_enable_hs(TCH, false); | 1168 | omapdss_dsi_vc_enable_hs(dssdev, td->channel, false); |
850 | 1169 | ||
851 | r = taal_sleep_out(td); | 1170 | r = taal_sleep_out(td); |
852 | if (r) | 1171 | if (r) |
853 | goto err; | 1172 | goto err; |
854 | 1173 | ||
855 | r = taal_get_id(&id1, &id2, &id3); | 1174 | r = taal_get_id(td, &id1, &id2, &id3); |
856 | if (r) | 1175 | if (r) |
857 | goto err; | 1176 | goto err; |
858 | 1177 | ||
@@ -861,30 +1180,30 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
861 | (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) | 1180 | (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) |
862 | td->cabc_broken = true; | 1181 | td->cabc_broken = true; |
863 | 1182 | ||
864 | r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); | 1183 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff); |
865 | if (r) | 1184 | if (r) |
866 | goto err; | 1185 | goto err; |
867 | 1186 | ||
868 | r = taal_dcs_write_1(DCS_CTRL_DISPLAY, | 1187 | r = taal_dcs_write_1(td, DCS_CTRL_DISPLAY, |
869 | (1<<2) | (1<<5)); /* BL | BCTRL */ | 1188 | (1<<2) | (1<<5)); /* BL | BCTRL */ |
870 | if (r) | 1189 | if (r) |
871 | goto err; | 1190 | goto err; |
872 | 1191 | ||
873 | r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ | 1192 | r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ |
874 | if (r) | 1193 | if (r) |
875 | goto err; | 1194 | goto err; |
876 | 1195 | ||
877 | r = taal_set_addr_mode(td->rotate, td->mirror); | 1196 | r = taal_set_addr_mode(td, td->rotate, td->mirror); |
878 | if (r) | 1197 | if (r) |
879 | goto err; | 1198 | goto err; |
880 | 1199 | ||
881 | if (!td->cabc_broken) { | 1200 | if (!td->cabc_broken) { |
882 | r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); | 1201 | r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode); |
883 | if (r) | 1202 | if (r) |
884 | goto err; | 1203 | goto err; |
885 | } | 1204 | } |
886 | 1205 | ||
887 | r = taal_dcs_write_0(DCS_DISPLAY_ON); | 1206 | r = taal_dcs_write_0(td, DCS_DISPLAY_ON); |
888 | if (r) | 1207 | if (r) |
889 | goto err; | 1208 | goto err; |
890 | 1209 | ||
@@ -903,7 +1222,7 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
903 | td->intro_printed = true; | 1222 | td->intro_printed = true; |
904 | } | 1223 | } |
905 | 1224 | ||
906 | omapdss_dsi_vc_enable_hs(TCH, true); | 1225 | omapdss_dsi_vc_enable_hs(dssdev, td->channel, true); |
907 | 1226 | ||
908 | return 0; | 1227 | return 0; |
909 | err: | 1228 | err: |
@@ -911,7 +1230,7 @@ err: | |||
911 | 1230 | ||
912 | taal_hw_reset(dssdev); | 1231 | taal_hw_reset(dssdev); |
913 | 1232 | ||
914 | omapdss_dsi_display_disable(dssdev); | 1233 | omapdss_dsi_display_disable(dssdev, true, false); |
915 | err0: | 1234 | err0: |
916 | return r; | 1235 | return r; |
917 | } | 1236 | } |
@@ -921,7 +1240,7 @@ static void taal_power_off(struct omap_dss_device *dssdev) | |||
921 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1240 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
922 | int r; | 1241 | int r; |
923 | 1242 | ||
924 | r = taal_dcs_write_0(DCS_DISPLAY_OFF); | 1243 | r = taal_dcs_write_0(td, DCS_DISPLAY_OFF); |
925 | if (!r) { | 1244 | if (!r) { |
926 | r = taal_sleep_in(td); | 1245 | r = taal_sleep_in(td); |
927 | /* HACK: wait a bit so that the message goes through */ | 1246 | /* HACK: wait a bit so that the message goes through */ |
@@ -934,15 +1253,23 @@ static void taal_power_off(struct omap_dss_device *dssdev) | |||
934 | taal_hw_reset(dssdev); | 1253 | taal_hw_reset(dssdev); |
935 | } | 1254 | } |
936 | 1255 | ||
937 | omapdss_dsi_display_disable(dssdev); | 1256 | omapdss_dsi_display_disable(dssdev, true, false); |
938 | 1257 | ||
939 | td->enabled = 0; | 1258 | td->enabled = 0; |
940 | } | 1259 | } |
941 | 1260 | ||
1261 | static int taal_panel_reset(struct omap_dss_device *dssdev) | ||
1262 | { | ||
1263 | dev_err(&dssdev->dev, "performing LCD reset\n"); | ||
1264 | |||
1265 | taal_power_off(dssdev); | ||
1266 | taal_hw_reset(dssdev); | ||
1267 | return taal_power_on(dssdev); | ||
1268 | } | ||
1269 | |||
942 | static int taal_enable(struct omap_dss_device *dssdev) | 1270 | static int taal_enable(struct omap_dss_device *dssdev) |
943 | { | 1271 | { |
944 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1272 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
945 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
946 | int r; | 1273 | int r; |
947 | 1274 | ||
948 | dev_dbg(&dssdev->dev, "enable\n"); | 1275 | dev_dbg(&dssdev->dev, "enable\n"); |
@@ -954,18 +1281,16 @@ static int taal_enable(struct omap_dss_device *dssdev) | |||
954 | goto err; | 1281 | goto err; |
955 | } | 1282 | } |
956 | 1283 | ||
957 | dsi_bus_lock(); | 1284 | dsi_bus_lock(dssdev); |
958 | 1285 | ||
959 | r = taal_power_on(dssdev); | 1286 | r = taal_power_on(dssdev); |
960 | 1287 | ||
961 | dsi_bus_unlock(); | 1288 | dsi_bus_unlock(dssdev); |
962 | 1289 | ||
963 | if (r) | 1290 | if (r) |
964 | goto err; | 1291 | goto err; |
965 | 1292 | ||
966 | if (panel_data->use_esd_check) | 1293 | taal_queue_esd_work(dssdev); |
967 | queue_delayed_work(td->esd_wq, &td->esd_work, | ||
968 | TAAL_ESD_CHECK_PERIOD); | ||
969 | 1294 | ||
970 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 1295 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
971 | 1296 | ||
@@ -986,14 +1311,17 @@ static void taal_disable(struct omap_dss_device *dssdev) | |||
986 | 1311 | ||
987 | mutex_lock(&td->lock); | 1312 | mutex_lock(&td->lock); |
988 | 1313 | ||
989 | cancel_delayed_work(&td->esd_work); | 1314 | taal_cancel_ulps_work(dssdev); |
1315 | taal_cancel_esd_work(dssdev); | ||
990 | 1316 | ||
991 | dsi_bus_lock(); | 1317 | dsi_bus_lock(dssdev); |
992 | 1318 | ||
993 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | 1319 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { |
1320 | taal_wake_up(dssdev); | ||
994 | taal_power_off(dssdev); | 1321 | taal_power_off(dssdev); |
1322 | } | ||
995 | 1323 | ||
996 | dsi_bus_unlock(); | 1324 | dsi_bus_unlock(dssdev); |
997 | 1325 | ||
998 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 1326 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; |
999 | 1327 | ||
@@ -1014,13 +1342,16 @@ static int taal_suspend(struct omap_dss_device *dssdev) | |||
1014 | goto err; | 1342 | goto err; |
1015 | } | 1343 | } |
1016 | 1344 | ||
1017 | cancel_delayed_work(&td->esd_work); | 1345 | taal_cancel_ulps_work(dssdev); |
1346 | taal_cancel_esd_work(dssdev); | ||
1018 | 1347 | ||
1019 | dsi_bus_lock(); | 1348 | dsi_bus_lock(dssdev); |
1020 | 1349 | ||
1021 | taal_power_off(dssdev); | 1350 | r = taal_wake_up(dssdev); |
1351 | if (!r) | ||
1352 | taal_power_off(dssdev); | ||
1022 | 1353 | ||
1023 | dsi_bus_unlock(); | 1354 | dsi_bus_unlock(dssdev); |
1024 | 1355 | ||
1025 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | 1356 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; |
1026 | 1357 | ||
@@ -1035,7 +1366,6 @@ err: | |||
1035 | static int taal_resume(struct omap_dss_device *dssdev) | 1366 | static int taal_resume(struct omap_dss_device *dssdev) |
1036 | { | 1367 | { |
1037 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1368 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
1038 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
1039 | int r; | 1369 | int r; |
1040 | 1370 | ||
1041 | dev_dbg(&dssdev->dev, "resume\n"); | 1371 | dev_dbg(&dssdev->dev, "resume\n"); |
@@ -1047,19 +1377,17 @@ static int taal_resume(struct omap_dss_device *dssdev) | |||
1047 | goto err; | 1377 | goto err; |
1048 | } | 1378 | } |
1049 | 1379 | ||
1050 | dsi_bus_lock(); | 1380 | dsi_bus_lock(dssdev); |
1051 | 1381 | ||
1052 | r = taal_power_on(dssdev); | 1382 | r = taal_power_on(dssdev); |
1053 | 1383 | ||
1054 | dsi_bus_unlock(); | 1384 | dsi_bus_unlock(dssdev); |
1055 | 1385 | ||
1056 | if (r) { | 1386 | if (r) { |
1057 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 1387 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; |
1058 | } else { | 1388 | } else { |
1059 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 1389 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
1060 | if (panel_data->use_esd_check) | 1390 | taal_queue_esd_work(dssdev); |
1061 | queue_delayed_work(td->esd_wq, &td->esd_work, | ||
1062 | TAAL_ESD_CHECK_PERIOD); | ||
1063 | } | 1391 | } |
1064 | 1392 | ||
1065 | mutex_unlock(&td->lock); | 1393 | mutex_unlock(&td->lock); |
@@ -1074,7 +1402,7 @@ static void taal_framedone_cb(int err, void *data) | |||
1074 | { | 1402 | { |
1075 | struct omap_dss_device *dssdev = data; | 1403 | struct omap_dss_device *dssdev = data; |
1076 | dev_dbg(&dssdev->dev, "framedone, err %d\n", err); | 1404 | dev_dbg(&dssdev->dev, "framedone, err %d\n", err); |
1077 | dsi_bus_unlock(); | 1405 | dsi_bus_unlock(dssdev); |
1078 | } | 1406 | } |
1079 | 1407 | ||
1080 | static irqreturn_t taal_te_isr(int irq, void *data) | 1408 | static irqreturn_t taal_te_isr(int irq, void *data) |
@@ -1089,7 +1417,7 @@ static irqreturn_t taal_te_isr(int irq, void *data) | |||
1089 | if (old) { | 1417 | if (old) { |
1090 | cancel_delayed_work(&td->te_timeout_work); | 1418 | cancel_delayed_work(&td->te_timeout_work); |
1091 | 1419 | ||
1092 | r = omap_dsi_update(dssdev, TCH, | 1420 | r = omap_dsi_update(dssdev, td->channel, |
1093 | td->update_region.x, | 1421 | td->update_region.x, |
1094 | td->update_region.y, | 1422 | td->update_region.y, |
1095 | td->update_region.w, | 1423 | td->update_region.w, |
@@ -1102,7 +1430,7 @@ static irqreturn_t taal_te_isr(int irq, void *data) | |||
1102 | return IRQ_HANDLED; | 1430 | return IRQ_HANDLED; |
1103 | err: | 1431 | err: |
1104 | dev_err(&dssdev->dev, "start update failed\n"); | 1432 | dev_err(&dssdev->dev, "start update failed\n"); |
1105 | dsi_bus_unlock(); | 1433 | dsi_bus_unlock(dssdev); |
1106 | return IRQ_HANDLED; | 1434 | return IRQ_HANDLED; |
1107 | } | 1435 | } |
1108 | 1436 | ||
@@ -1115,7 +1443,7 @@ static void taal_te_timeout_work_callback(struct work_struct *work) | |||
1115 | dev_err(&dssdev->dev, "TE not received for 250ms!\n"); | 1443 | dev_err(&dssdev->dev, "TE not received for 250ms!\n"); |
1116 | 1444 | ||
1117 | atomic_set(&td->do_update, 0); | 1445 | atomic_set(&td->do_update, 0); |
1118 | dsi_bus_unlock(); | 1446 | dsi_bus_unlock(dssdev); |
1119 | } | 1447 | } |
1120 | 1448 | ||
1121 | static int taal_update(struct omap_dss_device *dssdev, | 1449 | static int taal_update(struct omap_dss_device *dssdev, |
@@ -1128,7 +1456,11 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1128 | dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); | 1456 | dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); |
1129 | 1457 | ||
1130 | mutex_lock(&td->lock); | 1458 | mutex_lock(&td->lock); |
1131 | dsi_bus_lock(); | 1459 | dsi_bus_lock(dssdev); |
1460 | |||
1461 | r = taal_wake_up(dssdev); | ||
1462 | if (r) | ||
1463 | goto err; | ||
1132 | 1464 | ||
1133 | if (!td->enabled) { | 1465 | if (!td->enabled) { |
1134 | r = 0; | 1466 | r = 0; |
@@ -1139,7 +1471,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1139 | if (r) | 1471 | if (r) |
1140 | goto err; | 1472 | goto err; |
1141 | 1473 | ||
1142 | r = taal_set_update_window(x, y, w, h); | 1474 | r = taal_set_update_window(td, x, y, w, h); |
1143 | if (r) | 1475 | if (r) |
1144 | goto err; | 1476 | goto err; |
1145 | 1477 | ||
@@ -1153,7 +1485,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1153 | msecs_to_jiffies(250)); | 1485 | msecs_to_jiffies(250)); |
1154 | atomic_set(&td->do_update, 1); | 1486 | atomic_set(&td->do_update, 1); |
1155 | } else { | 1487 | } else { |
1156 | r = omap_dsi_update(dssdev, TCH, x, y, w, h, | 1488 | r = omap_dsi_update(dssdev, td->channel, x, y, w, h, |
1157 | taal_framedone_cb, dssdev); | 1489 | taal_framedone_cb, dssdev); |
1158 | if (r) | 1490 | if (r) |
1159 | goto err; | 1491 | goto err; |
@@ -1163,7 +1495,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1163 | mutex_unlock(&td->lock); | 1495 | mutex_unlock(&td->lock); |
1164 | return 0; | 1496 | return 0; |
1165 | err: | 1497 | err: |
1166 | dsi_bus_unlock(); | 1498 | dsi_bus_unlock(dssdev); |
1167 | mutex_unlock(&td->lock); | 1499 | mutex_unlock(&td->lock); |
1168 | return r; | 1500 | return r; |
1169 | } | 1501 | } |
@@ -1175,8 +1507,8 @@ static int taal_sync(struct omap_dss_device *dssdev) | |||
1175 | dev_dbg(&dssdev->dev, "sync\n"); | 1507 | dev_dbg(&dssdev->dev, "sync\n"); |
1176 | 1508 | ||
1177 | mutex_lock(&td->lock); | 1509 | mutex_lock(&td->lock); |
1178 | dsi_bus_lock(); | 1510 | dsi_bus_lock(dssdev); |
1179 | dsi_bus_unlock(); | 1511 | dsi_bus_unlock(dssdev); |
1180 | mutex_unlock(&td->lock); | 1512 | mutex_unlock(&td->lock); |
1181 | 1513 | ||
1182 | dev_dbg(&dssdev->dev, "sync done\n"); | 1514 | dev_dbg(&dssdev->dev, "sync done\n"); |
@@ -1191,9 +1523,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1191 | int r; | 1523 | int r; |
1192 | 1524 | ||
1193 | if (enable) | 1525 | if (enable) |
1194 | r = taal_dcs_write_1(DCS_TEAR_ON, 0); | 1526 | r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); |
1195 | else | 1527 | else |
1196 | r = taal_dcs_write_0(DCS_TEAR_OFF); | 1528 | r = taal_dcs_write_0(td, DCS_TEAR_OFF); |
1197 | 1529 | ||
1198 | if (!panel_data->use_ext_te) | 1530 | if (!panel_data->use_ext_te) |
1199 | omapdss_dsi_enable_te(dssdev, enable); | 1531 | omapdss_dsi_enable_te(dssdev, enable); |
@@ -1214,9 +1546,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1214 | if (td->te_enabled == enable) | 1546 | if (td->te_enabled == enable) |
1215 | goto end; | 1547 | goto end; |
1216 | 1548 | ||
1217 | dsi_bus_lock(); | 1549 | dsi_bus_lock(dssdev); |
1218 | 1550 | ||
1219 | if (td->enabled) { | 1551 | if (td->enabled) { |
1552 | r = taal_wake_up(dssdev); | ||
1553 | if (r) | ||
1554 | goto err; | ||
1555 | |||
1220 | r = _taal_enable_te(dssdev, enable); | 1556 | r = _taal_enable_te(dssdev, enable); |
1221 | if (r) | 1557 | if (r) |
1222 | goto err; | 1558 | goto err; |
@@ -1224,13 +1560,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1224 | 1560 | ||
1225 | td->te_enabled = enable; | 1561 | td->te_enabled = enable; |
1226 | 1562 | ||
1227 | dsi_bus_unlock(); | 1563 | dsi_bus_unlock(dssdev); |
1228 | end: | 1564 | end: |
1229 | mutex_unlock(&td->lock); | 1565 | mutex_unlock(&td->lock); |
1230 | 1566 | ||
1231 | return 0; | 1567 | return 0; |
1232 | err: | 1568 | err: |
1233 | dsi_bus_unlock(); | 1569 | dsi_bus_unlock(dssdev); |
1234 | mutex_unlock(&td->lock); | 1570 | mutex_unlock(&td->lock); |
1235 | 1571 | ||
1236 | return r; | 1572 | return r; |
@@ -1260,22 +1596,26 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | |||
1260 | if (td->rotate == rotate) | 1596 | if (td->rotate == rotate) |
1261 | goto end; | 1597 | goto end; |
1262 | 1598 | ||
1263 | dsi_bus_lock(); | 1599 | dsi_bus_lock(dssdev); |
1264 | 1600 | ||
1265 | if (td->enabled) { | 1601 | if (td->enabled) { |
1266 | r = taal_set_addr_mode(rotate, td->mirror); | 1602 | r = taal_wake_up(dssdev); |
1603 | if (r) | ||
1604 | goto err; | ||
1605 | |||
1606 | r = taal_set_addr_mode(td, rotate, td->mirror); | ||
1267 | if (r) | 1607 | if (r) |
1268 | goto err; | 1608 | goto err; |
1269 | } | 1609 | } |
1270 | 1610 | ||
1271 | td->rotate = rotate; | 1611 | td->rotate = rotate; |
1272 | 1612 | ||
1273 | dsi_bus_unlock(); | 1613 | dsi_bus_unlock(dssdev); |
1274 | end: | 1614 | end: |
1275 | mutex_unlock(&td->lock); | 1615 | mutex_unlock(&td->lock); |
1276 | return 0; | 1616 | return 0; |
1277 | err: | 1617 | err: |
1278 | dsi_bus_unlock(); | 1618 | dsi_bus_unlock(dssdev); |
1279 | mutex_unlock(&td->lock); | 1619 | mutex_unlock(&td->lock); |
1280 | return r; | 1620 | return r; |
1281 | } | 1621 | } |
@@ -1304,21 +1644,25 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | |||
1304 | if (td->mirror == enable) | 1644 | if (td->mirror == enable) |
1305 | goto end; | 1645 | goto end; |
1306 | 1646 | ||
1307 | dsi_bus_lock(); | 1647 | dsi_bus_lock(dssdev); |
1308 | if (td->enabled) { | 1648 | if (td->enabled) { |
1309 | r = taal_set_addr_mode(td->rotate, enable); | 1649 | r = taal_wake_up(dssdev); |
1650 | if (r) | ||
1651 | goto err; | ||
1652 | |||
1653 | r = taal_set_addr_mode(td, td->rotate, enable); | ||
1310 | if (r) | 1654 | if (r) |
1311 | goto err; | 1655 | goto err; |
1312 | } | 1656 | } |
1313 | 1657 | ||
1314 | td->mirror = enable; | 1658 | td->mirror = enable; |
1315 | 1659 | ||
1316 | dsi_bus_unlock(); | 1660 | dsi_bus_unlock(dssdev); |
1317 | end: | 1661 | end: |
1318 | mutex_unlock(&td->lock); | 1662 | mutex_unlock(&td->lock); |
1319 | return 0; | 1663 | return 0; |
1320 | err: | 1664 | err: |
1321 | dsi_bus_unlock(); | 1665 | dsi_bus_unlock(dssdev); |
1322 | mutex_unlock(&td->lock); | 1666 | mutex_unlock(&td->lock); |
1323 | return r; | 1667 | return r; |
1324 | } | 1668 | } |
@@ -1348,23 +1692,27 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | |||
1348 | goto err1; | 1692 | goto err1; |
1349 | } | 1693 | } |
1350 | 1694 | ||
1351 | dsi_bus_lock(); | 1695 | dsi_bus_lock(dssdev); |
1696 | |||
1697 | r = taal_wake_up(dssdev); | ||
1698 | if (r) | ||
1699 | goto err2; | ||
1352 | 1700 | ||
1353 | r = taal_dcs_read_1(DCS_GET_ID1, &id1); | 1701 | r = taal_dcs_read_1(td, DCS_GET_ID1, &id1); |
1354 | if (r) | 1702 | if (r) |
1355 | goto err2; | 1703 | goto err2; |
1356 | r = taal_dcs_read_1(DCS_GET_ID2, &id2); | 1704 | r = taal_dcs_read_1(td, DCS_GET_ID2, &id2); |
1357 | if (r) | 1705 | if (r) |
1358 | goto err2; | 1706 | goto err2; |
1359 | r = taal_dcs_read_1(DCS_GET_ID3, &id3); | 1707 | r = taal_dcs_read_1(td, DCS_GET_ID3, &id3); |
1360 | if (r) | 1708 | if (r) |
1361 | goto err2; | 1709 | goto err2; |
1362 | 1710 | ||
1363 | dsi_bus_unlock(); | 1711 | dsi_bus_unlock(dssdev); |
1364 | mutex_unlock(&td->lock); | 1712 | mutex_unlock(&td->lock); |
1365 | return 0; | 1713 | return 0; |
1366 | err2: | 1714 | err2: |
1367 | dsi_bus_unlock(); | 1715 | dsi_bus_unlock(dssdev); |
1368 | err1: | 1716 | err1: |
1369 | mutex_unlock(&td->lock); | 1717 | mutex_unlock(&td->lock); |
1370 | return r; | 1718 | return r; |
@@ -1394,7 +1742,11 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1394 | dssdev->panel.timings.x_res * | 1742 | dssdev->panel.timings.x_res * |
1395 | dssdev->panel.timings.y_res * 3); | 1743 | dssdev->panel.timings.y_res * 3); |
1396 | 1744 | ||
1397 | dsi_bus_lock(); | 1745 | dsi_bus_lock(dssdev); |
1746 | |||
1747 | r = taal_wake_up(dssdev); | ||
1748 | if (r) | ||
1749 | goto err2; | ||
1398 | 1750 | ||
1399 | /* plen 1 or 2 goes into short packet. until checksum error is fixed, | 1751 | /* plen 1 or 2 goes into short packet. until checksum error is fixed, |
1400 | * use short packets. plen 32 works, but bigger packets seem to cause | 1752 | * use short packets. plen 32 works, but bigger packets seem to cause |
@@ -1404,9 +1756,9 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1404 | else | 1756 | else |
1405 | plen = 2; | 1757 | plen = 2; |
1406 | 1758 | ||
1407 | taal_set_update_window(x, y, w, h); | 1759 | taal_set_update_window(td, x, y, w, h); |
1408 | 1760 | ||
1409 | r = dsi_vc_set_max_rx_packet_size(TCH, plen); | 1761 | r = dsi_vc_set_max_rx_packet_size(dssdev, td->channel, plen); |
1410 | if (r) | 1762 | if (r) |
1411 | goto err2; | 1763 | goto err2; |
1412 | 1764 | ||
@@ -1414,7 +1766,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1414 | u8 dcs_cmd = first ? 0x2e : 0x3e; | 1766 | u8 dcs_cmd = first ? 0x2e : 0x3e; |
1415 | first = 0; | 1767 | first = 0; |
1416 | 1768 | ||
1417 | r = dsi_vc_dcs_read(TCH, dcs_cmd, | 1769 | r = dsi_vc_dcs_read(dssdev, td->channel, dcs_cmd, |
1418 | buf + buf_used, size - buf_used); | 1770 | buf + buf_used, size - buf_used); |
1419 | 1771 | ||
1420 | if (r < 0) { | 1772 | if (r < 0) { |
@@ -1440,14 +1792,35 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1440 | r = buf_used; | 1792 | r = buf_used; |
1441 | 1793 | ||
1442 | err3: | 1794 | err3: |
1443 | dsi_vc_set_max_rx_packet_size(TCH, 1); | 1795 | dsi_vc_set_max_rx_packet_size(dssdev, td->channel, 1); |
1444 | err2: | 1796 | err2: |
1445 | dsi_bus_unlock(); | 1797 | dsi_bus_unlock(dssdev); |
1446 | err1: | 1798 | err1: |
1447 | mutex_unlock(&td->lock); | 1799 | mutex_unlock(&td->lock); |
1448 | return r; | 1800 | return r; |
1449 | } | 1801 | } |
1450 | 1802 | ||
1803 | static void taal_ulps_work(struct work_struct *work) | ||
1804 | { | ||
1805 | struct taal_data *td = container_of(work, struct taal_data, | ||
1806 | ulps_work.work); | ||
1807 | struct omap_dss_device *dssdev = td->dssdev; | ||
1808 | |||
1809 | mutex_lock(&td->lock); | ||
1810 | |||
1811 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !td->enabled) { | ||
1812 | mutex_unlock(&td->lock); | ||
1813 | return; | ||
1814 | } | ||
1815 | |||
1816 | dsi_bus_lock(dssdev); | ||
1817 | |||
1818 | taal_enter_ulps(dssdev); | ||
1819 | |||
1820 | dsi_bus_unlock(dssdev); | ||
1821 | mutex_unlock(&td->lock); | ||
1822 | } | ||
1823 | |||
1451 | static void taal_esd_work(struct work_struct *work) | 1824 | static void taal_esd_work(struct work_struct *work) |
1452 | { | 1825 | { |
1453 | struct taal_data *td = container_of(work, struct taal_data, | 1826 | struct taal_data *td = container_of(work, struct taal_data, |
@@ -1464,9 +1837,15 @@ static void taal_esd_work(struct work_struct *work) | |||
1464 | return; | 1837 | return; |
1465 | } | 1838 | } |
1466 | 1839 | ||
1467 | dsi_bus_lock(); | 1840 | dsi_bus_lock(dssdev); |
1841 | |||
1842 | r = taal_wake_up(dssdev); | ||
1843 | if (r) { | ||
1844 | dev_err(&dssdev->dev, "failed to exit ULPS\n"); | ||
1845 | goto err; | ||
1846 | } | ||
1468 | 1847 | ||
1469 | r = taal_dcs_read_1(DCS_RDDSDR, &state1); | 1848 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); |
1470 | if (r) { | 1849 | if (r) { |
1471 | dev_err(&dssdev->dev, "failed to read Taal status\n"); | 1850 | dev_err(&dssdev->dev, "failed to read Taal status\n"); |
1472 | goto err; | 1851 | goto err; |
@@ -1479,7 +1858,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1479 | goto err; | 1858 | goto err; |
1480 | } | 1859 | } |
1481 | 1860 | ||
1482 | r = taal_dcs_read_1(DCS_RDDSDR, &state2); | 1861 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state2); |
1483 | if (r) { | 1862 | if (r) { |
1484 | dev_err(&dssdev->dev, "failed to read Taal status\n"); | 1863 | dev_err(&dssdev->dev, "failed to read Taal status\n"); |
1485 | goto err; | 1864 | goto err; |
@@ -1495,27 +1874,25 @@ static void taal_esd_work(struct work_struct *work) | |||
1495 | /* Self-diagnostics result is also shown on TE GPIO line. We need | 1874 | /* Self-diagnostics result is also shown on TE GPIO line. We need |
1496 | * to re-enable TE after self diagnostics */ | 1875 | * to re-enable TE after self diagnostics */ |
1497 | if (td->te_enabled && panel_data->use_ext_te) { | 1876 | if (td->te_enabled && panel_data->use_ext_te) { |
1498 | r = taal_dcs_write_1(DCS_TEAR_ON, 0); | 1877 | r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); |
1499 | if (r) | 1878 | if (r) |
1500 | goto err; | 1879 | goto err; |
1501 | } | 1880 | } |
1502 | 1881 | ||
1503 | dsi_bus_unlock(); | 1882 | dsi_bus_unlock(dssdev); |
1504 | 1883 | ||
1505 | queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); | 1884 | taal_queue_esd_work(dssdev); |
1506 | 1885 | ||
1507 | mutex_unlock(&td->lock); | 1886 | mutex_unlock(&td->lock); |
1508 | return; | 1887 | return; |
1509 | err: | 1888 | err: |
1510 | dev_err(&dssdev->dev, "performing LCD reset\n"); | 1889 | dev_err(&dssdev->dev, "performing LCD reset\n"); |
1511 | 1890 | ||
1512 | taal_power_off(dssdev); | 1891 | taal_panel_reset(dssdev); |
1513 | taal_hw_reset(dssdev); | ||
1514 | taal_power_on(dssdev); | ||
1515 | 1892 | ||
1516 | dsi_bus_unlock(); | 1893 | dsi_bus_unlock(dssdev); |
1517 | 1894 | ||
1518 | queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); | 1895 | taal_queue_esd_work(dssdev); |
1519 | 1896 | ||
1520 | mutex_unlock(&td->lock); | 1897 | mutex_unlock(&td->lock); |
1521 | } | 1898 | } |
@@ -1536,7 +1913,7 @@ static enum omap_dss_update_mode taal_get_update_mode( | |||
1536 | 1913 | ||
1537 | static struct omap_dss_driver taal_driver = { | 1914 | static struct omap_dss_driver taal_driver = { |
1538 | .probe = taal_probe, | 1915 | .probe = taal_probe, |
1539 | .remove = taal_remove, | 1916 | .remove = __exit_p(taal_remove), |
1540 | 1917 | ||
1541 | .enable = taal_enable, | 1918 | .enable = taal_enable, |
1542 | .disable = taal_disable, | 1919 | .disable = taal_disable, |