diff options
Diffstat (limited to 'drivers/video/omap2/dss/dsi.c')
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 967 |
1 files changed, 722 insertions, 245 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index ddf3a0560822..0a7f1a47f8e3 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -38,12 +38,11 @@ | |||
38 | #include <plat/clock.h> | 38 | #include <plat/clock.h> |
39 | 39 | ||
40 | #include "dss.h" | 40 | #include "dss.h" |
41 | #include "dss_features.h" | ||
41 | 42 | ||
42 | /*#define VERBOSE_IRQ*/ | 43 | /*#define VERBOSE_IRQ*/ |
43 | #define DSI_CATCH_MISSING_TE | 44 | #define DSI_CATCH_MISSING_TE |
44 | 45 | ||
45 | #define DSI_BASE 0x4804FC00 | ||
46 | |||
47 | struct dsi_reg { u16 idx; }; | 46 | struct dsi_reg { u16 idx; }; |
48 | 47 | ||
49 | #define DSI_REG(idx) ((const struct dsi_reg) { idx }) | 48 | #define DSI_REG(idx) ((const struct dsi_reg) { idx }) |
@@ -186,13 +185,15 @@ struct dsi_reg { u16 idx; }; | |||
186 | #define DSI_DT_RX_SHORT_READ_1 0x21 | 185 | #define DSI_DT_RX_SHORT_READ_1 0x21 |
187 | #define DSI_DT_RX_SHORT_READ_2 0x22 | 186 | #define DSI_DT_RX_SHORT_READ_2 0x22 |
188 | 187 | ||
189 | #define FINT_MAX 2100000 | 188 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); |
190 | #define FINT_MIN 750000 | 189 | |
191 | #define REGN_MAX (1 << 7) | 190 | #define DSI_MAX_NR_ISRS 2 |
192 | #define REGM_MAX ((1 << 11) - 1) | 191 | |
193 | #define REGM3_MAX (1 << 4) | 192 | struct dsi_isr_data { |
194 | #define REGM4_MAX (1 << 4) | 193 | omap_dsi_isr_t isr; |
195 | #define LP_DIV_MAX ((1 << 13) - 1) | 194 | void *arg; |
195 | u32 mask; | ||
196 | }; | ||
196 | 197 | ||
197 | enum fifo_size { | 198 | enum fifo_size { |
198 | DSI_FIFO_SIZE_0 = 0, | 199 | DSI_FIFO_SIZE_0 = 0, |
@@ -220,9 +221,17 @@ struct dsi_irq_stats { | |||
220 | unsigned cio_irqs[32]; | 221 | unsigned cio_irqs[32]; |
221 | }; | 222 | }; |
222 | 223 | ||
224 | struct dsi_isr_tables { | ||
225 | struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS]; | ||
226 | struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS]; | ||
227 | struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; | ||
228 | }; | ||
229 | |||
223 | static struct | 230 | static struct |
224 | { | 231 | { |
232 | struct platform_device *pdev; | ||
225 | void __iomem *base; | 233 | void __iomem *base; |
234 | int irq; | ||
226 | 235 | ||
227 | struct dsi_clock_info current_cinfo; | 236 | struct dsi_clock_info current_cinfo; |
228 | 237 | ||
@@ -232,6 +241,7 @@ static struct | |||
232 | enum dsi_vc_mode mode; | 241 | enum dsi_vc_mode mode; |
233 | struct omap_dss_device *dssdev; | 242 | struct omap_dss_device *dssdev; |
234 | enum fifo_size fifo_size; | 243 | enum fifo_size fifo_size; |
244 | int vc_id; | ||
235 | } vc[4]; | 245 | } vc[4]; |
236 | 246 | ||
237 | struct mutex lock; | 247 | struct mutex lock; |
@@ -239,8 +249,10 @@ static struct | |||
239 | 249 | ||
240 | unsigned pll_locked; | 250 | unsigned pll_locked; |
241 | 251 | ||
242 | struct completion bta_completion; | 252 | spinlock_t irq_lock; |
243 | void (*bta_callback)(void); | 253 | struct dsi_isr_tables isr_tables; |
254 | /* space for a copy used by the interrupt handler */ | ||
255 | struct dsi_isr_tables isr_tables_copy; | ||
244 | 256 | ||
245 | int update_channel; | 257 | int update_channel; |
246 | struct dsi_update_region update_region; | 258 | struct dsi_update_region update_region; |
@@ -275,6 +287,11 @@ static struct | |||
275 | spinlock_t irq_stats_lock; | 287 | spinlock_t irq_stats_lock; |
276 | struct dsi_irq_stats irq_stats; | 288 | struct dsi_irq_stats irq_stats; |
277 | #endif | 289 | #endif |
290 | /* DSI PLL Parameter Ranges */ | ||
291 | unsigned long regm_max, regn_max; | ||
292 | unsigned long regm_dispc_max, regm_dsi_max; | ||
293 | unsigned long fint_min, fint_max; | ||
294 | unsigned long lpdiv_max; | ||
278 | } dsi; | 295 | } dsi; |
279 | 296 | ||
280 | #ifdef DEBUG | 297 | #ifdef DEBUG |
@@ -318,6 +335,11 @@ static bool dsi_bus_is_locked(void) | |||
318 | return dsi.bus_lock.count == 0; | 335 | return dsi.bus_lock.count == 0; |
319 | } | 336 | } |
320 | 337 | ||
338 | static void dsi_completion_handler(void *data, u32 mask) | ||
339 | { | ||
340 | complete((struct completion *)data); | ||
341 | } | ||
342 | |||
321 | static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, | 343 | static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, |
322 | int value) | 344 | int value) |
323 | { | 345 | { |
@@ -387,6 +409,9 @@ static void dsi_perf_show(const char *name) | |||
387 | 409 | ||
388 | static void print_irq_status(u32 status) | 410 | static void print_irq_status(u32 status) |
389 | { | 411 | { |
412 | if (status == 0) | ||
413 | return; | ||
414 | |||
390 | #ifndef VERBOSE_IRQ | 415 | #ifndef VERBOSE_IRQ |
391 | if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) | 416 | if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) |
392 | return; | 417 | return; |
@@ -422,6 +447,9 @@ static void print_irq_status(u32 status) | |||
422 | 447 | ||
423 | static void print_irq_status_vc(int channel, u32 status) | 448 | static void print_irq_status_vc(int channel, u32 status) |
424 | { | 449 | { |
450 | if (status == 0) | ||
451 | return; | ||
452 | |||
425 | #ifndef VERBOSE_IRQ | 453 | #ifndef VERBOSE_IRQ |
426 | if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) | 454 | if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) |
427 | return; | 455 | return; |
@@ -448,6 +476,9 @@ static void print_irq_status_vc(int channel, u32 status) | |||
448 | 476 | ||
449 | static void print_irq_status_cio(u32 status) | 477 | static void print_irq_status_cio(u32 status) |
450 | { | 478 | { |
479 | if (status == 0) | ||
480 | return; | ||
481 | |||
451 | printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); | 482 | printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); |
452 | 483 | ||
453 | #define PIS(x) \ | 484 | #define PIS(x) \ |
@@ -478,22 +509,33 @@ static void print_irq_status_cio(u32 status) | |||
478 | printk("\n"); | 509 | printk("\n"); |
479 | } | 510 | } |
480 | 511 | ||
481 | static int debug_irq; | 512 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
482 | 513 | static void dsi_collect_irq_stats(u32 irqstatus, u32 *vcstatus, u32 ciostatus) | |
483 | /* called from dss */ | ||
484 | void dsi_irq_handler(void) | ||
485 | { | 514 | { |
486 | u32 irqstatus, vcstatus, ciostatus; | ||
487 | int i; | 515 | int i; |
488 | 516 | ||
489 | irqstatus = dsi_read_reg(DSI_IRQSTATUS); | ||
490 | |||
491 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
492 | spin_lock(&dsi.irq_stats_lock); | 517 | spin_lock(&dsi.irq_stats_lock); |
518 | |||
493 | dsi.irq_stats.irq_count++; | 519 | dsi.irq_stats.irq_count++; |
494 | dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); | 520 | dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); |
521 | |||
522 | for (i = 0; i < 4; ++i) | ||
523 | dss_collect_irq_stats(vcstatus[i], dsi.irq_stats.vc_irqs[i]); | ||
524 | |||
525 | dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); | ||
526 | |||
527 | spin_unlock(&dsi.irq_stats_lock); | ||
528 | } | ||
529 | #else | ||
530 | #define dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus) | ||
495 | #endif | 531 | #endif |
496 | 532 | ||
533 | static int debug_irq; | ||
534 | |||
535 | static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus) | ||
536 | { | ||
537 | int i; | ||
538 | |||
497 | if (irqstatus & DSI_IRQ_ERROR_MASK) { | 539 | if (irqstatus & DSI_IRQ_ERROR_MASK) { |
498 | DSSERR("DSI error, irqstatus %x\n", irqstatus); | 540 | DSSERR("DSI error, irqstatus %x\n", irqstatus); |
499 | print_irq_status(irqstatus); | 541 | print_irq_status(irqstatus); |
@@ -504,37 +546,88 @@ void dsi_irq_handler(void) | |||
504 | print_irq_status(irqstatus); | 546 | print_irq_status(irqstatus); |
505 | } | 547 | } |
506 | 548 | ||
507 | #ifdef DSI_CATCH_MISSING_TE | 549 | for (i = 0; i < 4; ++i) { |
508 | if (irqstatus & DSI_IRQ_TE_TRIGGER) | 550 | if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) { |
509 | del_timer(&dsi.te_timer); | 551 | DSSERR("DSI VC(%d) error, vc irqstatus %x\n", |
510 | #endif | 552 | i, vcstatus[i]); |
553 | print_irq_status_vc(i, vcstatus[i]); | ||
554 | } else if (debug_irq) { | ||
555 | print_irq_status_vc(i, vcstatus[i]); | ||
556 | } | ||
557 | } | ||
558 | |||
559 | if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) { | ||
560 | DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); | ||
561 | print_irq_status_cio(ciostatus); | ||
562 | } else if (debug_irq) { | ||
563 | print_irq_status_cio(ciostatus); | ||
564 | } | ||
565 | } | ||
566 | |||
567 | static void dsi_call_isrs(struct dsi_isr_data *isr_array, | ||
568 | unsigned isr_array_size, u32 irqstatus) | ||
569 | { | ||
570 | struct dsi_isr_data *isr_data; | ||
571 | int i; | ||
572 | |||
573 | for (i = 0; i < isr_array_size; i++) { | ||
574 | isr_data = &isr_array[i]; | ||
575 | if (isr_data->isr && isr_data->mask & irqstatus) | ||
576 | isr_data->isr(isr_data->arg, irqstatus); | ||
577 | } | ||
578 | } | ||
579 | |||
580 | static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables, | ||
581 | u32 irqstatus, u32 *vcstatus, u32 ciostatus) | ||
582 | { | ||
583 | int i; | ||
584 | |||
585 | dsi_call_isrs(isr_tables->isr_table, | ||
586 | ARRAY_SIZE(isr_tables->isr_table), | ||
587 | irqstatus); | ||
511 | 588 | ||
512 | for (i = 0; i < 4; ++i) { | 589 | for (i = 0; i < 4; ++i) { |
513 | if ((irqstatus & (1<<i)) == 0) | 590 | if (vcstatus[i] == 0) |
514 | continue; | 591 | continue; |
592 | dsi_call_isrs(isr_tables->isr_table_vc[i], | ||
593 | ARRAY_SIZE(isr_tables->isr_table_vc[i]), | ||
594 | vcstatus[i]); | ||
595 | } | ||
515 | 596 | ||
516 | vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 597 | if (ciostatus != 0) |
598 | dsi_call_isrs(isr_tables->isr_table_cio, | ||
599 | ARRAY_SIZE(isr_tables->isr_table_cio), | ||
600 | ciostatus); | ||
601 | } | ||
517 | 602 | ||
518 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 603 | static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) |
519 | dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); | 604 | { |
520 | #endif | 605 | u32 irqstatus, vcstatus[4], ciostatus; |
606 | int i; | ||
521 | 607 | ||
522 | if (vcstatus & DSI_VC_IRQ_BTA) { | 608 | spin_lock(&dsi.irq_lock); |
523 | complete(&dsi.bta_completion); | ||
524 | 609 | ||
525 | if (dsi.bta_callback) | 610 | irqstatus = dsi_read_reg(DSI_IRQSTATUS); |
526 | dsi.bta_callback(); | ||
527 | } | ||
528 | 611 | ||
529 | if (vcstatus & DSI_VC_IRQ_ERROR_MASK) { | 612 | /* IRQ is not for us */ |
530 | DSSERR("DSI VC(%d) error, vc irqstatus %x\n", | 613 | if (!irqstatus) { |
531 | i, vcstatus); | 614 | spin_unlock(&dsi.irq_lock); |
532 | print_irq_status_vc(i, vcstatus); | 615 | return IRQ_NONE; |
533 | } else if (debug_irq) { | 616 | } |
534 | print_irq_status_vc(i, vcstatus); | 617 | |
618 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | ||
619 | /* flush posted write */ | ||
620 | dsi_read_reg(DSI_IRQSTATUS); | ||
621 | |||
622 | for (i = 0; i < 4; ++i) { | ||
623 | if ((irqstatus & (1 << i)) == 0) { | ||
624 | vcstatus[i] = 0; | ||
625 | continue; | ||
535 | } | 626 | } |
536 | 627 | ||
537 | dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus); | 628 | vcstatus[i] = dsi_read_reg(DSI_VC_IRQSTATUS(i)); |
629 | |||
630 | dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus[i]); | ||
538 | /* flush posted write */ | 631 | /* flush posted write */ |
539 | dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 632 | dsi_read_reg(DSI_VC_IRQSTATUS(i)); |
540 | } | 633 | } |
@@ -542,117 +635,307 @@ void dsi_irq_handler(void) | |||
542 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { | 635 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { |
543 | ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 636 | ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); |
544 | 637 | ||
545 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
546 | dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); | ||
547 | #endif | ||
548 | |||
549 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); | 638 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); |
550 | /* flush posted write */ | 639 | /* flush posted write */ |
551 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 640 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); |
641 | } else { | ||
642 | ciostatus = 0; | ||
643 | } | ||
552 | 644 | ||
553 | if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) { | 645 | #ifdef DSI_CATCH_MISSING_TE |
554 | DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); | 646 | if (irqstatus & DSI_IRQ_TE_TRIGGER) |
555 | print_irq_status_cio(ciostatus); | 647 | del_timer(&dsi.te_timer); |
556 | } else if (debug_irq) { | 648 | #endif |
557 | print_irq_status_cio(ciostatus); | 649 | |
558 | } | 650 | /* make a copy and unlock, so that isrs can unregister |
651 | * themselves */ | ||
652 | memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables)); | ||
653 | |||
654 | spin_unlock(&dsi.irq_lock); | ||
655 | |||
656 | dsi_handle_isrs(&dsi.isr_tables_copy, irqstatus, vcstatus, ciostatus); | ||
657 | |||
658 | dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus); | ||
659 | |||
660 | dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus); | ||
661 | |||
662 | return IRQ_HANDLED; | ||
663 | } | ||
664 | |||
665 | /* dsi.irq_lock has to be locked by the caller */ | ||
666 | static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array, | ||
667 | unsigned isr_array_size, u32 default_mask, | ||
668 | const struct dsi_reg enable_reg, | ||
669 | const struct dsi_reg status_reg) | ||
670 | { | ||
671 | struct dsi_isr_data *isr_data; | ||
672 | u32 mask; | ||
673 | u32 old_mask; | ||
674 | int i; | ||
675 | |||
676 | mask = default_mask; | ||
677 | |||
678 | for (i = 0; i < isr_array_size; i++) { | ||
679 | isr_data = &isr_array[i]; | ||
680 | |||
681 | if (isr_data->isr == NULL) | ||
682 | continue; | ||
683 | |||
684 | mask |= isr_data->mask; | ||
559 | } | 685 | } |
560 | 686 | ||
561 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | 687 | old_mask = dsi_read_reg(enable_reg); |
562 | /* flush posted write */ | 688 | /* clear the irqstatus for newly enabled irqs */ |
563 | dsi_read_reg(DSI_IRQSTATUS); | 689 | dsi_write_reg(status_reg, (mask ^ old_mask) & mask); |
690 | dsi_write_reg(enable_reg, mask); | ||
564 | 691 | ||
565 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 692 | /* flush posted writes */ |
566 | spin_unlock(&dsi.irq_stats_lock); | 693 | dsi_read_reg(enable_reg); |
694 | dsi_read_reg(status_reg); | ||
695 | } | ||
696 | |||
697 | /* dsi.irq_lock has to be locked by the caller */ | ||
698 | static void _omap_dsi_set_irqs(void) | ||
699 | { | ||
700 | u32 mask = DSI_IRQ_ERROR_MASK; | ||
701 | #ifdef DSI_CATCH_MISSING_TE | ||
702 | mask |= DSI_IRQ_TE_TRIGGER; | ||
567 | #endif | 703 | #endif |
704 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table, | ||
705 | ARRAY_SIZE(dsi.isr_tables.isr_table), mask, | ||
706 | DSI_IRQENABLE, DSI_IRQSTATUS); | ||
707 | } | ||
708 | |||
709 | /* dsi.irq_lock has to be locked by the caller */ | ||
710 | static void _omap_dsi_set_irqs_vc(int vc) | ||
711 | { | ||
712 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_vc[vc], | ||
713 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[vc]), | ||
714 | DSI_VC_IRQ_ERROR_MASK, | ||
715 | DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc)); | ||
568 | } | 716 | } |
569 | 717 | ||
718 | /* dsi.irq_lock has to be locked by the caller */ | ||
719 | static void _omap_dsi_set_irqs_cio(void) | ||
720 | { | ||
721 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_cio, | ||
722 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio), | ||
723 | DSI_CIO_IRQ_ERROR_MASK, | ||
724 | DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS); | ||
725 | } | ||
570 | 726 | ||
571 | static void _dsi_initialize_irq(void) | 727 | static void _dsi_initialize_irq(void) |
572 | { | 728 | { |
573 | u32 l; | 729 | unsigned long flags; |
730 | int vc; | ||
731 | |||
732 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
733 | |||
734 | memset(&dsi.isr_tables, 0, sizeof(dsi.isr_tables)); | ||
735 | |||
736 | _omap_dsi_set_irqs(); | ||
737 | for (vc = 0; vc < 4; ++vc) | ||
738 | _omap_dsi_set_irqs_vc(vc); | ||
739 | _omap_dsi_set_irqs_cio(); | ||
740 | |||
741 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
742 | } | ||
743 | |||
744 | static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask, | ||
745 | struct dsi_isr_data *isr_array, unsigned isr_array_size) | ||
746 | { | ||
747 | struct dsi_isr_data *isr_data; | ||
748 | int free_idx; | ||
574 | int i; | 749 | int i; |
575 | 750 | ||
576 | /* disable all interrupts */ | 751 | BUG_ON(isr == NULL); |
577 | dsi_write_reg(DSI_IRQENABLE, 0); | ||
578 | for (i = 0; i < 4; ++i) | ||
579 | dsi_write_reg(DSI_VC_IRQENABLE(i), 0); | ||
580 | dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0); | ||
581 | 752 | ||
582 | /* clear interrupt status */ | 753 | /* check for duplicate entry and find a free slot */ |
583 | l = dsi_read_reg(DSI_IRQSTATUS); | 754 | free_idx = -1; |
584 | dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK); | 755 | for (i = 0; i < isr_array_size; i++) { |
756 | isr_data = &isr_array[i]; | ||
585 | 757 | ||
586 | for (i = 0; i < 4; ++i) { | 758 | if (isr_data->isr == isr && isr_data->arg == arg && |
587 | l = dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 759 | isr_data->mask == mask) { |
588 | dsi_write_reg(DSI_VC_IRQSTATUS(i), l); | 760 | return -EINVAL; |
761 | } | ||
762 | |||
763 | if (isr_data->isr == NULL && free_idx == -1) | ||
764 | free_idx = i; | ||
589 | } | 765 | } |
590 | 766 | ||
591 | l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 767 | if (free_idx == -1) |
592 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l); | 768 | return -EBUSY; |
593 | 769 | ||
594 | /* enable error irqs */ | 770 | isr_data = &isr_array[free_idx]; |
595 | l = DSI_IRQ_ERROR_MASK; | 771 | isr_data->isr = isr; |
596 | #ifdef DSI_CATCH_MISSING_TE | 772 | isr_data->arg = arg; |
597 | l |= DSI_IRQ_TE_TRIGGER; | 773 | isr_data->mask = mask; |
598 | #endif | ||
599 | dsi_write_reg(DSI_IRQENABLE, l); | ||
600 | 774 | ||
601 | l = DSI_VC_IRQ_ERROR_MASK; | 775 | return 0; |
602 | for (i = 0; i < 4; ++i) | 776 | } |
603 | dsi_write_reg(DSI_VC_IRQENABLE(i), l); | 777 | |
778 | static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask, | ||
779 | struct dsi_isr_data *isr_array, unsigned isr_array_size) | ||
780 | { | ||
781 | struct dsi_isr_data *isr_data; | ||
782 | int i; | ||
783 | |||
784 | for (i = 0; i < isr_array_size; i++) { | ||
785 | isr_data = &isr_array[i]; | ||
786 | if (isr_data->isr != isr || isr_data->arg != arg || | ||
787 | isr_data->mask != mask) | ||
788 | continue; | ||
789 | |||
790 | isr_data->isr = NULL; | ||
791 | isr_data->arg = NULL; | ||
792 | isr_data->mask = 0; | ||
793 | |||
794 | return 0; | ||
795 | } | ||
604 | 796 | ||
605 | l = DSI_CIO_IRQ_ERROR_MASK; | 797 | return -EINVAL; |
606 | dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l); | ||
607 | } | 798 | } |
608 | 799 | ||
609 | static u32 dsi_get_errors(void) | 800 | static int dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask) |
610 | { | 801 | { |
611 | unsigned long flags; | 802 | unsigned long flags; |
612 | u32 e; | 803 | int r; |
613 | spin_lock_irqsave(&dsi.errors_lock, flags); | 804 | |
614 | e = dsi.errors; | 805 | spin_lock_irqsave(&dsi.irq_lock, flags); |
615 | dsi.errors = 0; | 806 | |
616 | spin_unlock_irqrestore(&dsi.errors_lock, flags); | 807 | r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table, |
617 | return e; | 808 | ARRAY_SIZE(dsi.isr_tables.isr_table)); |
809 | |||
810 | if (r == 0) | ||
811 | _omap_dsi_set_irqs(); | ||
812 | |||
813 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
814 | |||
815 | return r; | ||
618 | } | 816 | } |
619 | 817 | ||
620 | static void dsi_vc_enable_bta_irq(int channel) | 818 | static int dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask) |
621 | { | 819 | { |
622 | u32 l; | 820 | unsigned long flags; |
821 | int r; | ||
822 | |||
823 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
824 | |||
825 | r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table, | ||
826 | ARRAY_SIZE(dsi.isr_tables.isr_table)); | ||
827 | |||
828 | if (r == 0) | ||
829 | _omap_dsi_set_irqs(); | ||
623 | 830 | ||
624 | dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA); | 831 | spin_unlock_irqrestore(&dsi.irq_lock, flags); |
625 | 832 | ||
626 | l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); | 833 | return r; |
627 | l |= DSI_VC_IRQ_BTA; | ||
628 | dsi_write_reg(DSI_VC_IRQENABLE(channel), l); | ||
629 | } | 834 | } |
630 | 835 | ||
631 | static void dsi_vc_disable_bta_irq(int channel) | 836 | static int dsi_register_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, |
837 | u32 mask) | ||
632 | { | 838 | { |
633 | u32 l; | 839 | unsigned long flags; |
840 | int r; | ||
841 | |||
842 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
843 | |||
844 | r = _dsi_register_isr(isr, arg, mask, | ||
845 | dsi.isr_tables.isr_table_vc[channel], | ||
846 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); | ||
847 | |||
848 | if (r == 0) | ||
849 | _omap_dsi_set_irqs_vc(channel); | ||
850 | |||
851 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
852 | |||
853 | return r; | ||
854 | } | ||
855 | |||
856 | static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, | ||
857 | u32 mask) | ||
858 | { | ||
859 | unsigned long flags; | ||
860 | int r; | ||
861 | |||
862 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
863 | |||
864 | r = _dsi_unregister_isr(isr, arg, mask, | ||
865 | dsi.isr_tables.isr_table_vc[channel], | ||
866 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); | ||
867 | |||
868 | if (r == 0) | ||
869 | _omap_dsi_set_irqs_vc(channel); | ||
870 | |||
871 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
872 | |||
873 | return r; | ||
874 | } | ||
875 | |||
876 | static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) | ||
877 | { | ||
878 | unsigned long flags; | ||
879 | int r; | ||
880 | |||
881 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
882 | |||
883 | r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio, | ||
884 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio)); | ||
885 | |||
886 | if (r == 0) | ||
887 | _omap_dsi_set_irqs_cio(); | ||
888 | |||
889 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
890 | |||
891 | return r; | ||
892 | } | ||
893 | |||
894 | static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) | ||
895 | { | ||
896 | unsigned long flags; | ||
897 | int r; | ||
898 | |||
899 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
900 | |||
901 | r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio, | ||
902 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio)); | ||
903 | |||
904 | if (r == 0) | ||
905 | _omap_dsi_set_irqs_cio(); | ||
906 | |||
907 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
634 | 908 | ||
635 | l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); | 909 | return r; |
636 | l &= ~DSI_VC_IRQ_BTA; | ||
637 | dsi_write_reg(DSI_VC_IRQENABLE(channel), l); | ||
638 | } | 910 | } |
639 | 911 | ||
640 | /* DSI func clock. this could also be DSI2_PLL_FCLK */ | 912 | static u32 dsi_get_errors(void) |
913 | { | ||
914 | unsigned long flags; | ||
915 | u32 e; | ||
916 | spin_lock_irqsave(&dsi.errors_lock, flags); | ||
917 | e = dsi.errors; | ||
918 | dsi.errors = 0; | ||
919 | spin_unlock_irqrestore(&dsi.errors_lock, flags); | ||
920 | return e; | ||
921 | } | ||
922 | |||
923 | /* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ | ||
641 | static inline void enable_clocks(bool enable) | 924 | static inline void enable_clocks(bool enable) |
642 | { | 925 | { |
643 | if (enable) | 926 | if (enable) |
644 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 927 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
645 | else | 928 | else |
646 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 929 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
647 | } | 930 | } |
648 | 931 | ||
649 | /* source clock for DSI PLL. this could also be PCLKFREE */ | 932 | /* source clock for DSI PLL. this could also be PCLKFREE */ |
650 | static inline void dsi_enable_pll_clock(bool enable) | 933 | static inline void dsi_enable_pll_clock(bool enable) |
651 | { | 934 | { |
652 | if (enable) | 935 | if (enable) |
653 | dss_clk_enable(DSS_CLK_FCK2); | 936 | dss_clk_enable(DSS_CLK_SYSCK); |
654 | else | 937 | else |
655 | dss_clk_disable(DSS_CLK_FCK2); | 938 | dss_clk_disable(DSS_CLK_SYSCK); |
656 | 939 | ||
657 | if (enable && dsi.pll_locked) { | 940 | if (enable && dsi.pll_locked) { |
658 | if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) | 941 | if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) |
@@ -707,14 +990,14 @@ static inline int dsi_if_enable(bool enable) | |||
707 | return 0; | 990 | return 0; |
708 | } | 991 | } |
709 | 992 | ||
710 | unsigned long dsi_get_dsi1_pll_rate(void) | 993 | unsigned long dsi_get_pll_hsdiv_dispc_rate(void) |
711 | { | 994 | { |
712 | return dsi.current_cinfo.dsi1_pll_fclk; | 995 | return dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk; |
713 | } | 996 | } |
714 | 997 | ||
715 | static unsigned long dsi_get_dsi2_pll_rate(void) | 998 | static unsigned long dsi_get_pll_hsdiv_dsi_rate(void) |
716 | { | 999 | { |
717 | return dsi.current_cinfo.dsi2_pll_fclk; | 1000 | return dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk; |
718 | } | 1001 | } |
719 | 1002 | ||
720 | static unsigned long dsi_get_txbyteclkhs(void) | 1003 | static unsigned long dsi_get_txbyteclkhs(void) |
@@ -726,12 +1009,12 @@ static unsigned long dsi_fclk_rate(void) | |||
726 | { | 1009 | { |
727 | unsigned long r; | 1010 | unsigned long r; |
728 | 1011 | ||
729 | if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) { | 1012 | if (dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK) { |
730 | /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ | 1013 | /* DSI FCLK source is DSS_CLK_FCK */ |
731 | r = dss_clk_get_rate(DSS_CLK_FCK1); | 1014 | r = dss_clk_get_rate(DSS_CLK_FCK); |
732 | } else { | 1015 | } else { |
733 | /* DSI FCLK source is DSI2_PLL_FCLK */ | 1016 | /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ |
734 | r = dsi_get_dsi2_pll_rate(); | 1017 | r = dsi_get_pll_hsdiv_dsi_rate(); |
735 | } | 1018 | } |
736 | 1019 | ||
737 | return r; | 1020 | return r; |
@@ -745,7 +1028,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) | |||
745 | 1028 | ||
746 | lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; | 1029 | lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; |
747 | 1030 | ||
748 | if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX) | 1031 | if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max) |
749 | return -EINVAL; | 1032 | return -EINVAL; |
750 | 1033 | ||
751 | dsi_fclk = dsi_fclk_rate(); | 1034 | dsi_fclk = dsi_fclk_rate(); |
@@ -795,22 +1078,22 @@ static int dsi_pll_power(enum dsi_pll_power_state state) | |||
795 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | 1078 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, |
796 | struct dsi_clock_info *cinfo) | 1079 | struct dsi_clock_info *cinfo) |
797 | { | 1080 | { |
798 | if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) | 1081 | if (cinfo->regn == 0 || cinfo->regn > dsi.regn_max) |
799 | return -EINVAL; | 1082 | return -EINVAL; |
800 | 1083 | ||
801 | if (cinfo->regm == 0 || cinfo->regm > REGM_MAX) | 1084 | if (cinfo->regm == 0 || cinfo->regm > dsi.regm_max) |
802 | return -EINVAL; | 1085 | return -EINVAL; |
803 | 1086 | ||
804 | if (cinfo->regm3 > REGM3_MAX) | 1087 | if (cinfo->regm_dispc > dsi.regm_dispc_max) |
805 | return -EINVAL; | 1088 | return -EINVAL; |
806 | 1089 | ||
807 | if (cinfo->regm4 > REGM4_MAX) | 1090 | if (cinfo->regm_dsi > dsi.regm_dsi_max) |
808 | return -EINVAL; | 1091 | return -EINVAL; |
809 | 1092 | ||
810 | if (cinfo->use_dss2_fck) { | 1093 | if (cinfo->use_sys_clk) { |
811 | cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2); | 1094 | cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); |
812 | /* XXX it is unclear if highfreq should be used | 1095 | /* XXX it is unclear if highfreq should be used |
813 | * with DSS2_FCK source also */ | 1096 | * with DSS_SYS_CLK source also */ |
814 | cinfo->highfreq = 0; | 1097 | cinfo->highfreq = 0; |
815 | } else { | 1098 | } else { |
816 | cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); | 1099 | cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); |
@@ -823,7 +1106,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
823 | 1106 | ||
824 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); | 1107 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); |
825 | 1108 | ||
826 | if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN) | 1109 | if (cinfo->fint > dsi.fint_max || cinfo->fint < dsi.fint_min) |
827 | return -EINVAL; | 1110 | return -EINVAL; |
828 | 1111 | ||
829 | cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; | 1112 | cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; |
@@ -831,15 +1114,17 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
831 | if (cinfo->clkin4ddr > 1800 * 1000 * 1000) | 1114 | if (cinfo->clkin4ddr > 1800 * 1000 * 1000) |
832 | return -EINVAL; | 1115 | return -EINVAL; |
833 | 1116 | ||
834 | if (cinfo->regm3 > 0) | 1117 | if (cinfo->regm_dispc > 0) |
835 | cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3; | 1118 | cinfo->dsi_pll_hsdiv_dispc_clk = |
1119 | cinfo->clkin4ddr / cinfo->regm_dispc; | ||
836 | else | 1120 | else |
837 | cinfo->dsi1_pll_fclk = 0; | 1121 | cinfo->dsi_pll_hsdiv_dispc_clk = 0; |
838 | 1122 | ||
839 | if (cinfo->regm4 > 0) | 1123 | if (cinfo->regm_dsi > 0) |
840 | cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4; | 1124 | cinfo->dsi_pll_hsdiv_dsi_clk = |
1125 | cinfo->clkin4ddr / cinfo->regm_dsi; | ||
841 | else | 1126 | else |
842 | cinfo->dsi2_pll_fclk = 0; | 1127 | cinfo->dsi_pll_hsdiv_dsi_clk = 0; |
843 | 1128 | ||
844 | return 0; | 1129 | return 0; |
845 | } | 1130 | } |
@@ -852,23 +1137,25 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, | |||
852 | struct dispc_clock_info best_dispc; | 1137 | struct dispc_clock_info best_dispc; |
853 | int min_fck_per_pck; | 1138 | int min_fck_per_pck; |
854 | int match = 0; | 1139 | int match = 0; |
855 | unsigned long dss_clk_fck2; | 1140 | unsigned long dss_sys_clk, max_dss_fck; |
1141 | |||
1142 | dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); | ||
856 | 1143 | ||
857 | dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); | 1144 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); |
858 | 1145 | ||
859 | if (req_pck == dsi.cache_req_pck && | 1146 | if (req_pck == dsi.cache_req_pck && |
860 | dsi.cache_cinfo.clkin == dss_clk_fck2) { | 1147 | dsi.cache_cinfo.clkin == dss_sys_clk) { |
861 | DSSDBG("DSI clock info found from cache\n"); | 1148 | DSSDBG("DSI clock info found from cache\n"); |
862 | *dsi_cinfo = dsi.cache_cinfo; | 1149 | *dsi_cinfo = dsi.cache_cinfo; |
863 | dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk, | 1150 | dispc_find_clk_divs(is_tft, req_pck, |
864 | dispc_cinfo); | 1151 | dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo); |
865 | return 0; | 1152 | return 0; |
866 | } | 1153 | } |
867 | 1154 | ||
868 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | 1155 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; |
869 | 1156 | ||
870 | if (min_fck_per_pck && | 1157 | if (min_fck_per_pck && |
871 | req_pck * min_fck_per_pck > DISPC_MAX_FCK) { | 1158 | req_pck * min_fck_per_pck > max_dss_fck) { |
872 | DSSERR("Requested pixel clock not possible with the current " | 1159 | DSSERR("Requested pixel clock not possible with the current " |
873 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " | 1160 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " |
874 | "the constraint off.\n"); | 1161 | "the constraint off.\n"); |
@@ -882,24 +1169,24 @@ retry: | |||
882 | memset(&best_dispc, 0, sizeof(best_dispc)); | 1169 | memset(&best_dispc, 0, sizeof(best_dispc)); |
883 | 1170 | ||
884 | memset(&cur, 0, sizeof(cur)); | 1171 | memset(&cur, 0, sizeof(cur)); |
885 | cur.clkin = dss_clk_fck2; | 1172 | cur.clkin = dss_sys_clk; |
886 | cur.use_dss2_fck = 1; | 1173 | cur.use_sys_clk = 1; |
887 | cur.highfreq = 0; | 1174 | cur.highfreq = 0; |
888 | 1175 | ||
889 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ | 1176 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ |
890 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ | 1177 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ |
891 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ | 1178 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ |
892 | for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { | 1179 | for (cur.regn = 1; cur.regn < dsi.regn_max; ++cur.regn) { |
893 | if (cur.highfreq == 0) | 1180 | if (cur.highfreq == 0) |
894 | cur.fint = cur.clkin / cur.regn; | 1181 | cur.fint = cur.clkin / cur.regn; |
895 | else | 1182 | else |
896 | cur.fint = cur.clkin / (2 * cur.regn); | 1183 | cur.fint = cur.clkin / (2 * cur.regn); |
897 | 1184 | ||
898 | if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) | 1185 | if (cur.fint > dsi.fint_max || cur.fint < dsi.fint_min) |
899 | continue; | 1186 | continue; |
900 | 1187 | ||
901 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ | 1188 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ |
902 | for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { | 1189 | for (cur.regm = 1; cur.regm < dsi.regm_max; ++cur.regm) { |
903 | unsigned long a, b; | 1190 | unsigned long a, b; |
904 | 1191 | ||
905 | a = 2 * cur.regm * (cur.clkin/1000); | 1192 | a = 2 * cur.regm * (cur.clkin/1000); |
@@ -909,30 +1196,32 @@ retry: | |||
909 | if (cur.clkin4ddr > 1800 * 1000 * 1000) | 1196 | if (cur.clkin4ddr > 1800 * 1000 * 1000) |
910 | break; | 1197 | break; |
911 | 1198 | ||
912 | /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ | 1199 | /* dsi_pll_hsdiv_dispc_clk(MHz) = |
913 | for (cur.regm3 = 1; cur.regm3 < REGM3_MAX; | 1200 | * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ |
914 | ++cur.regm3) { | 1201 | for (cur.regm_dispc = 1; cur.regm_dispc < dsi.regm_dispc_max; |
1202 | ++cur.regm_dispc) { | ||
915 | struct dispc_clock_info cur_dispc; | 1203 | struct dispc_clock_info cur_dispc; |
916 | cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3; | 1204 | cur.dsi_pll_hsdiv_dispc_clk = |
1205 | cur.clkin4ddr / cur.regm_dispc; | ||
917 | 1206 | ||
918 | /* this will narrow down the search a bit, | 1207 | /* this will narrow down the search a bit, |
919 | * but still give pixclocks below what was | 1208 | * but still give pixclocks below what was |
920 | * requested */ | 1209 | * requested */ |
921 | if (cur.dsi1_pll_fclk < req_pck) | 1210 | if (cur.dsi_pll_hsdiv_dispc_clk < req_pck) |
922 | break; | 1211 | break; |
923 | 1212 | ||
924 | if (cur.dsi1_pll_fclk > DISPC_MAX_FCK) | 1213 | if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck) |
925 | continue; | 1214 | continue; |
926 | 1215 | ||
927 | if (min_fck_per_pck && | 1216 | if (min_fck_per_pck && |
928 | cur.dsi1_pll_fclk < | 1217 | cur.dsi_pll_hsdiv_dispc_clk < |
929 | req_pck * min_fck_per_pck) | 1218 | req_pck * min_fck_per_pck) |
930 | continue; | 1219 | continue; |
931 | 1220 | ||
932 | match = 1; | 1221 | match = 1; |
933 | 1222 | ||
934 | dispc_find_clk_divs(is_tft, req_pck, | 1223 | dispc_find_clk_divs(is_tft, req_pck, |
935 | cur.dsi1_pll_fclk, | 1224 | cur.dsi_pll_hsdiv_dispc_clk, |
936 | &cur_dispc); | 1225 | &cur_dispc); |
937 | 1226 | ||
938 | if (abs(cur_dispc.pck - req_pck) < | 1227 | if (abs(cur_dispc.pck - req_pck) < |
@@ -961,9 +1250,9 @@ found: | |||
961 | return -EINVAL; | 1250 | return -EINVAL; |
962 | } | 1251 | } |
963 | 1252 | ||
964 | /* DSI2_PLL_FCLK (regm4) is not used */ | 1253 | /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */ |
965 | best.regm4 = 0; | 1254 | best.regm_dsi = 0; |
966 | best.dsi2_pll_fclk = 0; | 1255 | best.dsi_pll_hsdiv_dsi_clk = 0; |
967 | 1256 | ||
968 | if (dsi_cinfo) | 1257 | if (dsi_cinfo) |
969 | *dsi_cinfo = best; | 1258 | *dsi_cinfo = best; |
@@ -982,23 +1271,27 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
982 | int r = 0; | 1271 | int r = 0; |
983 | u32 l; | 1272 | u32 l; |
984 | int f; | 1273 | int f; |
1274 | u8 regn_start, regn_end, regm_start, regm_end; | ||
1275 | u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; | ||
985 | 1276 | ||
986 | DSSDBGF(); | 1277 | DSSDBGF(); |
987 | 1278 | ||
988 | dsi.current_cinfo.fint = cinfo->fint; | 1279 | dsi.current_cinfo.fint = cinfo->fint; |
989 | dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; | 1280 | dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; |
990 | dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk; | 1281 | dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk = |
991 | dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk; | 1282 | cinfo->dsi_pll_hsdiv_dispc_clk; |
1283 | dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk = | ||
1284 | cinfo->dsi_pll_hsdiv_dsi_clk; | ||
992 | 1285 | ||
993 | dsi.current_cinfo.regn = cinfo->regn; | 1286 | dsi.current_cinfo.regn = cinfo->regn; |
994 | dsi.current_cinfo.regm = cinfo->regm; | 1287 | dsi.current_cinfo.regm = cinfo->regm; |
995 | dsi.current_cinfo.regm3 = cinfo->regm3; | 1288 | dsi.current_cinfo.regm_dispc = cinfo->regm_dispc; |
996 | dsi.current_cinfo.regm4 = cinfo->regm4; | 1289 | dsi.current_cinfo.regm_dsi = cinfo->regm_dsi; |
997 | 1290 | ||
998 | DSSDBG("DSI Fint %ld\n", cinfo->fint); | 1291 | DSSDBG("DSI Fint %ld\n", cinfo->fint); |
999 | 1292 | ||
1000 | DSSDBG("clkin (%s) rate %ld, highfreq %d\n", | 1293 | DSSDBG("clkin (%s) rate %ld, highfreq %d\n", |
1001 | cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree", | 1294 | cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree", |
1002 | cinfo->clkin, | 1295 | cinfo->clkin, |
1003 | cinfo->highfreq); | 1296 | cinfo->highfreq); |
1004 | 1297 | ||
@@ -1015,24 +1308,39 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1015 | 1308 | ||
1016 | DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); | 1309 | DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); |
1017 | 1310 | ||
1018 | DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n", | 1311 | DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc, |
1019 | cinfo->regm3, cinfo->dsi1_pll_fclk); | 1312 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
1020 | DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n", | 1313 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
1021 | cinfo->regm4, cinfo->dsi2_pll_fclk); | 1314 | cinfo->dsi_pll_hsdiv_dispc_clk); |
1315 | DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi, | ||
1316 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | ||
1317 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | ||
1318 | cinfo->dsi_pll_hsdiv_dsi_clk); | ||
1319 | |||
1320 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end); | ||
1321 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, ®m_start, ®m_end); | ||
1322 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, ®m_dispc_start, | ||
1323 | ®m_dispc_end); | ||
1324 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, ®m_dsi_start, | ||
1325 | ®m_dsi_end); | ||
1022 | 1326 | ||
1023 | REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ | 1327 | REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ |
1024 | 1328 | ||
1025 | l = dsi_read_reg(DSI_PLL_CONFIGURATION1); | 1329 | l = dsi_read_reg(DSI_PLL_CONFIGURATION1); |
1026 | l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ | 1330 | l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ |
1027 | l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ | 1331 | /* DSI_PLL_REGN */ |
1028 | l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ | 1332 | l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end); |
1029 | l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0, | 1333 | /* DSI_PLL_REGM */ |
1030 | 22, 19); /* DSI_CLOCK_DIV */ | 1334 | l = FLD_MOD(l, cinfo->regm, regm_start, regm_end); |
1031 | l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0, | 1335 | /* DSI_CLOCK_DIV */ |
1032 | 26, 23); /* DSIPROTO_CLOCK_DIV */ | 1336 | l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0, |
1337 | regm_dispc_start, regm_dispc_end); | ||
1338 | /* DSIPROTO_CLOCK_DIV */ | ||
1339 | l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0, | ||
1340 | regm_dsi_start, regm_dsi_end); | ||
1033 | dsi_write_reg(DSI_PLL_CONFIGURATION1, l); | 1341 | dsi_write_reg(DSI_PLL_CONFIGURATION1, l); |
1034 | 1342 | ||
1035 | BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000); | 1343 | BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max); |
1036 | if (cinfo->fint < 1000000) | 1344 | if (cinfo->fint < 1000000) |
1037 | f = 0x3; | 1345 | f = 0x3; |
1038 | else if (cinfo->fint < 1250000) | 1346 | else if (cinfo->fint < 1250000) |
@@ -1046,7 +1354,7 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1046 | 1354 | ||
1047 | l = dsi_read_reg(DSI_PLL_CONFIGURATION2); | 1355 | l = dsi_read_reg(DSI_PLL_CONFIGURATION2); |
1048 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ | 1356 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ |
1049 | l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, | 1357 | l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, |
1050 | 11, 11); /* DSI_PLL_CLKSEL */ | 1358 | 11, 11); /* DSI_PLL_CLKSEL */ |
1051 | l = FLD_MOD(l, cinfo->highfreq, | 1359 | l = FLD_MOD(l, cinfo->highfreq, |
1052 | 12, 12); /* DSI_PLL_HIGHFREQ */ | 1360 | 12, 12); /* DSI_PLL_HIGHFREQ */ |
@@ -1101,6 +1409,26 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | |||
1101 | 1409 | ||
1102 | DSSDBG("PLL init\n"); | 1410 | DSSDBG("PLL init\n"); |
1103 | 1411 | ||
1412 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | ||
1413 | /* | ||
1414 | * HACK: this is just a quick hack to get the USE_DSI_PLL | ||
1415 | * option working. USE_DSI_PLL is itself a big hack, and | ||
1416 | * should be removed. | ||
1417 | */ | ||
1418 | if (dsi.vdds_dsi_reg == NULL) { | ||
1419 | struct regulator *vdds_dsi; | ||
1420 | |||
1421 | vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi"); | ||
1422 | |||
1423 | if (IS_ERR(vdds_dsi)) { | ||
1424 | DSSERR("can't get VDDS_DSI regulator\n"); | ||
1425 | return PTR_ERR(vdds_dsi); | ||
1426 | } | ||
1427 | |||
1428 | dsi.vdds_dsi_reg = vdds_dsi; | ||
1429 | } | ||
1430 | #endif | ||
1431 | |||
1104 | enable_clocks(1); | 1432 | enable_clocks(1); |
1105 | dsi_enable_pll_clock(1); | 1433 | dsi_enable_pll_clock(1); |
1106 | 1434 | ||
@@ -1162,6 +1490,10 @@ void dsi_dump_clocks(struct seq_file *s) | |||
1162 | { | 1490 | { |
1163 | int clksel; | 1491 | int clksel; |
1164 | struct dsi_clock_info *cinfo = &dsi.current_cinfo; | 1492 | struct dsi_clock_info *cinfo = &dsi.current_cinfo; |
1493 | enum dss_clk_source dispc_clk_src, dsi_clk_src; | ||
1494 | |||
1495 | dispc_clk_src = dss_get_dispc_clk_source(); | ||
1496 | dsi_clk_src = dss_get_dsi_clk_source(); | ||
1165 | 1497 | ||
1166 | enable_clocks(1); | 1498 | enable_clocks(1); |
1167 | 1499 | ||
@@ -1171,30 +1503,34 @@ void dsi_dump_clocks(struct seq_file *s) | |||
1171 | 1503 | ||
1172 | seq_printf(s, "dsi pll source = %s\n", | 1504 | seq_printf(s, "dsi pll source = %s\n", |
1173 | clksel == 0 ? | 1505 | clksel == 0 ? |
1174 | "dss2_alwon_fclk" : "pclkfree"); | 1506 | "dss_sys_clk" : "pclkfree"); |
1175 | 1507 | ||
1176 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); | 1508 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); |
1177 | 1509 | ||
1178 | seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", | 1510 | seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", |
1179 | cinfo->clkin4ddr, cinfo->regm); | 1511 | cinfo->clkin4ddr, cinfo->regm); |
1180 | 1512 | ||
1181 | seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n", | 1513 | seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n", |
1182 | cinfo->dsi1_pll_fclk, | 1514 | dss_get_generic_clk_source_name(dispc_clk_src), |
1183 | cinfo->regm3, | 1515 | dss_feat_get_clk_source_name(dispc_clk_src), |
1184 | dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1516 | cinfo->dsi_pll_hsdiv_dispc_clk, |
1517 | cinfo->regm_dispc, | ||
1518 | dispc_clk_src == DSS_CLK_SRC_FCK ? | ||
1185 | "off" : "on"); | 1519 | "off" : "on"); |
1186 | 1520 | ||
1187 | seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n", | 1521 | seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n", |
1188 | cinfo->dsi2_pll_fclk, | 1522 | dss_get_generic_clk_source_name(dsi_clk_src), |
1189 | cinfo->regm4, | 1523 | dss_feat_get_clk_source_name(dsi_clk_src), |
1190 | dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1524 | cinfo->dsi_pll_hsdiv_dsi_clk, |
1525 | cinfo->regm_dsi, | ||
1526 | dsi_clk_src == DSS_CLK_SRC_FCK ? | ||
1191 | "off" : "on"); | 1527 | "off" : "on"); |
1192 | 1528 | ||
1193 | seq_printf(s, "- DSI -\n"); | 1529 | seq_printf(s, "- DSI -\n"); |
1194 | 1530 | ||
1195 | seq_printf(s, "dsi fclk source = %s\n", | 1531 | seq_printf(s, "dsi fclk source = %s (%s)\n", |
1196 | dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1532 | dss_get_generic_clk_source_name(dsi_clk_src), |
1197 | "dss1_alwon_fclk" : "dsi2_pll_fclk"); | 1533 | dss_feat_get_clk_source_name(dsi_clk_src)); |
1198 | 1534 | ||
1199 | seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); | 1535 | seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); |
1200 | 1536 | ||
@@ -1306,7 +1642,7 @@ void dsi_dump_regs(struct seq_file *s) | |||
1306 | { | 1642 | { |
1307 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) | 1643 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) |
1308 | 1644 | ||
1309 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1645 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
1310 | 1646 | ||
1311 | DUMPREG(DSI_REVISION); | 1647 | DUMPREG(DSI_REVISION); |
1312 | DUMPREG(DSI_SYSCONFIG); | 1648 | DUMPREG(DSI_SYSCONFIG); |
@@ -1378,7 +1714,7 @@ void dsi_dump_regs(struct seq_file *s) | |||
1378 | DUMPREG(DSI_PLL_CONFIGURATION1); | 1714 | DUMPREG(DSI_PLL_CONFIGURATION1); |
1379 | DUMPREG(DSI_PLL_CONFIGURATION2); | 1715 | DUMPREG(DSI_PLL_CONFIGURATION2); |
1380 | 1716 | ||
1381 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1717 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
1382 | #undef DUMPREG | 1718 | #undef DUMPREG |
1383 | } | 1719 | } |
1384 | 1720 | ||
@@ -1622,20 +1958,6 @@ static int _dsi_reset(void) | |||
1622 | return _dsi_wait_reset(); | 1958 | return _dsi_wait_reset(); |
1623 | } | 1959 | } |
1624 | 1960 | ||
1625 | static void dsi_reset_tx_fifo(int channel) | ||
1626 | { | ||
1627 | u32 mask; | ||
1628 | u32 l; | ||
1629 | |||
1630 | /* set fifosize of the channel to 0, then return the old size */ | ||
1631 | l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE); | ||
1632 | |||
1633 | mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4); | ||
1634 | dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask); | ||
1635 | |||
1636 | dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l); | ||
1637 | } | ||
1638 | |||
1639 | static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, | 1961 | static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, |
1640 | enum fifo_size size3, enum fifo_size size4) | 1962 | enum fifo_size size3, enum fifo_size size4) |
1641 | { | 1963 | { |
@@ -1753,8 +2075,6 @@ static void dsi_vc_initial_config(int channel) | |||
1753 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ | 2075 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ |
1754 | 2076 | ||
1755 | dsi_write_reg(DSI_VC_CTRL(channel), r); | 2077 | dsi_write_reg(DSI_VC_CTRL(channel), r); |
1756 | |||
1757 | dsi.vc[channel].mode = DSI_VC_MODE_L4; | ||
1758 | } | 2078 | } |
1759 | 2079 | ||
1760 | static int dsi_vc_config_l4(int channel) | 2080 | static int dsi_vc_config_l4(int channel) |
@@ -1922,33 +2242,44 @@ static int dsi_vc_send_bta(int channel) | |||
1922 | 2242 | ||
1923 | int dsi_vc_send_bta_sync(int channel) | 2243 | int dsi_vc_send_bta_sync(int channel) |
1924 | { | 2244 | { |
2245 | DECLARE_COMPLETION_ONSTACK(completion); | ||
1925 | int r = 0; | 2246 | int r = 0; |
1926 | u32 err; | 2247 | u32 err; |
1927 | 2248 | ||
1928 | INIT_COMPLETION(dsi.bta_completion); | 2249 | r = dsi_register_isr_vc(channel, dsi_completion_handler, |
2250 | &completion, DSI_VC_IRQ_BTA); | ||
2251 | if (r) | ||
2252 | goto err0; | ||
1929 | 2253 | ||
1930 | dsi_vc_enable_bta_irq(channel); | 2254 | r = dsi_register_isr(dsi_completion_handler, &completion, |
2255 | DSI_IRQ_ERROR_MASK); | ||
2256 | if (r) | ||
2257 | goto err1; | ||
1931 | 2258 | ||
1932 | r = dsi_vc_send_bta(channel); | 2259 | r = dsi_vc_send_bta(channel); |
1933 | if (r) | 2260 | if (r) |
1934 | goto err; | 2261 | goto err2; |
1935 | 2262 | ||
1936 | if (wait_for_completion_timeout(&dsi.bta_completion, | 2263 | if (wait_for_completion_timeout(&completion, |
1937 | msecs_to_jiffies(500)) == 0) { | 2264 | msecs_to_jiffies(500)) == 0) { |
1938 | DSSERR("Failed to receive BTA\n"); | 2265 | DSSERR("Failed to receive BTA\n"); |
1939 | r = -EIO; | 2266 | r = -EIO; |
1940 | goto err; | 2267 | goto err2; |
1941 | } | 2268 | } |
1942 | 2269 | ||
1943 | err = dsi_get_errors(); | 2270 | err = dsi_get_errors(); |
1944 | if (err) { | 2271 | if (err) { |
1945 | DSSERR("Error while sending BTA: %x\n", err); | 2272 | DSSERR("Error while sending BTA: %x\n", err); |
1946 | r = -EIO; | 2273 | r = -EIO; |
1947 | goto err; | 2274 | goto err2; |
1948 | } | 2275 | } |
1949 | err: | 2276 | err2: |
1950 | dsi_vc_disable_bta_irq(channel); | 2277 | dsi_unregister_isr(dsi_completion_handler, &completion, |
1951 | 2278 | DSI_IRQ_ERROR_MASK); | |
2279 | err1: | ||
2280 | dsi_unregister_isr_vc(channel, dsi_completion_handler, | ||
2281 | &completion, DSI_VC_IRQ_BTA); | ||
2282 | err0: | ||
1952 | return r; | 2283 | return r; |
1953 | } | 2284 | } |
1954 | EXPORT_SYMBOL(dsi_vc_send_bta_sync); | 2285 | EXPORT_SYMBOL(dsi_vc_send_bta_sync); |
@@ -1961,7 +2292,7 @@ static inline void dsi_vc_write_long_header(int channel, u8 data_type, | |||
1961 | 2292 | ||
1962 | WARN_ON(!dsi_bus_is_locked()); | 2293 | WARN_ON(!dsi_bus_is_locked()); |
1963 | 2294 | ||
1964 | data_id = data_type | channel << 6; | 2295 | data_id = data_type | dsi.vc[channel].vc_id << 6; |
1965 | 2296 | ||
1966 | val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | | 2297 | val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | |
1967 | FLD_VAL(ecc, 31, 24); | 2298 | FLD_VAL(ecc, 31, 24); |
@@ -2064,7 +2395,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) | |||
2064 | return -EINVAL; | 2395 | return -EINVAL; |
2065 | } | 2396 | } |
2066 | 2397 | ||
2067 | data_id = data_type | channel << 6; | 2398 | data_id = data_type | dsi.vc[channel].vc_id << 6; |
2068 | 2399 | ||
2069 | r = (data_id << 0) | (data << 8) | (ecc << 24); | 2400 | r = (data_id << 0) | (data << 8) | (ecc << 24); |
2070 | 2401 | ||
@@ -2762,19 +3093,20 @@ static void dsi_te_timeout(unsigned long arg) | |||
2762 | } | 3093 | } |
2763 | #endif | 3094 | #endif |
2764 | 3095 | ||
3096 | static void dsi_framedone_bta_callback(void *data, u32 mask); | ||
3097 | |||
2765 | static void dsi_handle_framedone(int error) | 3098 | static void dsi_handle_framedone(int error) |
2766 | { | 3099 | { |
2767 | const int channel = dsi.update_channel; | 3100 | const int channel = dsi.update_channel; |
2768 | 3101 | ||
2769 | cancel_delayed_work(&dsi.framedone_timeout_work); | 3102 | dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, |
3103 | NULL, DSI_VC_IRQ_BTA); | ||
2770 | 3104 | ||
2771 | dsi_vc_disable_bta_irq(channel); | 3105 | cancel_delayed_work(&dsi.framedone_timeout_work); |
2772 | 3106 | ||
2773 | /* SIDLEMODE back to smart-idle */ | 3107 | /* SIDLEMODE back to smart-idle */ |
2774 | dispc_enable_sidle(); | 3108 | dispc_enable_sidle(); |
2775 | 3109 | ||
2776 | dsi.bta_callback = NULL; | ||
2777 | |||
2778 | if (dsi.te_enabled) { | 3110 | if (dsi.te_enabled) { |
2779 | /* enable LP_RX_TO again after the TE */ | 3111 | /* enable LP_RX_TO again after the TE */ |
2780 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ | 3112 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ |
@@ -2808,7 +3140,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work) | |||
2808 | dsi_handle_framedone(-ETIMEDOUT); | 3140 | dsi_handle_framedone(-ETIMEDOUT); |
2809 | } | 3141 | } |
2810 | 3142 | ||
2811 | static void dsi_framedone_bta_callback(void) | 3143 | static void dsi_framedone_bta_callback(void *data, u32 mask) |
2812 | { | 3144 | { |
2813 | dsi_handle_framedone(0); | 3145 | dsi_handle_framedone(0); |
2814 | 3146 | ||
@@ -2848,15 +3180,19 @@ static void dsi_framedone_irq_callback(void *data, u32 mask) | |||
2848 | * asynchronously. | 3180 | * asynchronously. |
2849 | * */ | 3181 | * */ |
2850 | 3182 | ||
2851 | dsi.bta_callback = dsi_framedone_bta_callback; | 3183 | r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback, |
2852 | 3184 | NULL, DSI_VC_IRQ_BTA); | |
2853 | barrier(); | 3185 | if (r) { |
2854 | 3186 | DSSERR("Failed to register BTA ISR\n"); | |
2855 | dsi_vc_enable_bta_irq(channel); | 3187 | dsi_handle_framedone(-EIO); |
3188 | return; | ||
3189 | } | ||
2856 | 3190 | ||
2857 | r = dsi_vc_send_bta(channel); | 3191 | r = dsi_vc_send_bta(channel); |
2858 | if (r) { | 3192 | if (r) { |
2859 | DSSERR("BTA after framedone failed\n"); | 3193 | DSSERR("BTA after framedone failed\n"); |
3194 | dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, | ||
3195 | NULL, DSI_VC_IRQ_BTA); | ||
2860 | dsi_handle_framedone(-EIO); | 3196 | dsi_handle_framedone(-EIO); |
2861 | } | 3197 | } |
2862 | } | 3198 | } |
@@ -2984,12 +3320,12 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | |||
2984 | struct dsi_clock_info cinfo; | 3320 | struct dsi_clock_info cinfo; |
2985 | int r; | 3321 | int r; |
2986 | 3322 | ||
2987 | /* we always use DSS2_FCK as input clock */ | 3323 | /* we always use DSS_CLK_SYSCK as input clock */ |
2988 | cinfo.use_dss2_fck = true; | 3324 | cinfo.use_sys_clk = true; |
2989 | cinfo.regn = dssdev->phy.dsi.div.regn; | 3325 | cinfo.regn = dssdev->phy.dsi.div.regn; |
2990 | cinfo.regm = dssdev->phy.dsi.div.regm; | 3326 | cinfo.regm = dssdev->phy.dsi.div.regm; |
2991 | cinfo.regm3 = dssdev->phy.dsi.div.regm3; | 3327 | cinfo.regm_dispc = dssdev->phy.dsi.div.regm_dispc; |
2992 | cinfo.regm4 = dssdev->phy.dsi.div.regm4; | 3328 | cinfo.regm_dsi = dssdev->phy.dsi.div.regm_dsi; |
2993 | r = dsi_calc_clock_rates(dssdev, &cinfo); | 3329 | r = dsi_calc_clock_rates(dssdev, &cinfo); |
2994 | if (r) { | 3330 | if (r) { |
2995 | DSSERR("Failed to calc dsi clocks\n"); | 3331 | DSSERR("Failed to calc dsi clocks\n"); |
@@ -3011,7 +3347,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
3011 | int r; | 3347 | int r; |
3012 | unsigned long long fck; | 3348 | unsigned long long fck; |
3013 | 3349 | ||
3014 | fck = dsi_get_dsi1_pll_rate(); | 3350 | fck = dsi_get_pll_hsdiv_dispc_rate(); |
3015 | 3351 | ||
3016 | dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; | 3352 | dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; |
3017 | dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; | 3353 | dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; |
@@ -3045,8 +3381,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
3045 | if (r) | 3381 | if (r) |
3046 | goto err1; | 3382 | goto err1; |
3047 | 3383 | ||
3048 | dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); | 3384 | dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); |
3049 | dss_select_dsi_clk_source(DSS_SRC_DSI2_PLL_FCLK); | 3385 | dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI); |
3050 | 3386 | ||
3051 | DSSDBG("PLL OK\n"); | 3387 | DSSDBG("PLL OK\n"); |
3052 | 3388 | ||
@@ -3082,8 +3418,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
3082 | err3: | 3418 | err3: |
3083 | dsi_complexio_uninit(); | 3419 | dsi_complexio_uninit(); |
3084 | err2: | 3420 | err2: |
3085 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3421 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); |
3086 | dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3422 | dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); |
3087 | err1: | 3423 | err1: |
3088 | dsi_pll_uninit(); | 3424 | dsi_pll_uninit(); |
3089 | err0: | 3425 | err0: |
@@ -3099,8 +3435,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) | |||
3099 | dsi_vc_enable(2, 0); | 3435 | dsi_vc_enable(2, 0); |
3100 | dsi_vc_enable(3, 0); | 3436 | dsi_vc_enable(3, 0); |
3101 | 3437 | ||
3102 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3438 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); |
3103 | dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3439 | dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); |
3104 | dsi_complexio_uninit(); | 3440 | dsi_complexio_uninit(); |
3105 | dsi_pll_uninit(); | 3441 | dsi_pll_uninit(); |
3106 | } | 3442 | } |
@@ -3220,29 +3556,107 @@ int dsi_init_display(struct omap_dss_device *dssdev) | |||
3220 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | | 3556 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | |
3221 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; | 3557 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; |
3222 | 3558 | ||
3223 | dsi.vc[0].dssdev = dssdev; | 3559 | if (dsi.vdds_dsi_reg == NULL) { |
3224 | dsi.vc[1].dssdev = dssdev; | 3560 | struct regulator *vdds_dsi; |
3561 | |||
3562 | vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi"); | ||
3563 | |||
3564 | if (IS_ERR(vdds_dsi)) { | ||
3565 | DSSERR("can't get VDDS_DSI regulator\n"); | ||
3566 | return PTR_ERR(vdds_dsi); | ||
3567 | } | ||
3568 | |||
3569 | dsi.vdds_dsi_reg = vdds_dsi; | ||
3570 | } | ||
3225 | 3571 | ||
3226 | return 0; | 3572 | return 0; |
3227 | } | 3573 | } |
3228 | 3574 | ||
3229 | void dsi_wait_dsi1_pll_active(void) | 3575 | int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel) |
3576 | { | ||
3577 | int i; | ||
3578 | |||
3579 | for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { | ||
3580 | if (!dsi.vc[i].dssdev) { | ||
3581 | dsi.vc[i].dssdev = dssdev; | ||
3582 | *channel = i; | ||
3583 | return 0; | ||
3584 | } | ||
3585 | } | ||
3586 | |||
3587 | DSSERR("cannot get VC for display %s", dssdev->name); | ||
3588 | return -ENOSPC; | ||
3589 | } | ||
3590 | EXPORT_SYMBOL(omap_dsi_request_vc); | ||
3591 | |||
3592 | int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id) | ||
3593 | { | ||
3594 | if (vc_id < 0 || vc_id > 3) { | ||
3595 | DSSERR("VC ID out of range\n"); | ||
3596 | return -EINVAL; | ||
3597 | } | ||
3598 | |||
3599 | if (channel < 0 || channel > 3) { | ||
3600 | DSSERR("Virtual Channel out of range\n"); | ||
3601 | return -EINVAL; | ||
3602 | } | ||
3603 | |||
3604 | if (dsi.vc[channel].dssdev != dssdev) { | ||
3605 | DSSERR("Virtual Channel not allocated to display %s\n", | ||
3606 | dssdev->name); | ||
3607 | return -EINVAL; | ||
3608 | } | ||
3609 | |||
3610 | dsi.vc[channel].vc_id = vc_id; | ||
3611 | |||
3612 | return 0; | ||
3613 | } | ||
3614 | EXPORT_SYMBOL(omap_dsi_set_vc_id); | ||
3615 | |||
3616 | void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel) | ||
3617 | { | ||
3618 | if ((channel >= 0 && channel <= 3) && | ||
3619 | dsi.vc[channel].dssdev == dssdev) { | ||
3620 | dsi.vc[channel].dssdev = NULL; | ||
3621 | dsi.vc[channel].vc_id = 0; | ||
3622 | } | ||
3623 | } | ||
3624 | EXPORT_SYMBOL(omap_dsi_release_vc); | ||
3625 | |||
3626 | void dsi_wait_pll_hsdiv_dispc_active(void) | ||
3230 | { | 3627 | { |
3231 | if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) | 3628 | if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) |
3232 | DSSERR("DSI1 PLL clock not active\n"); | 3629 | DSSERR("%s (%s) not active\n", |
3630 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), | ||
3631 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)); | ||
3233 | } | 3632 | } |
3234 | 3633 | ||
3235 | void dsi_wait_dsi2_pll_active(void) | 3634 | void dsi_wait_pll_hsdiv_dsi_active(void) |
3236 | { | 3635 | { |
3237 | if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) | 3636 | if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) |
3238 | DSSERR("DSI2 PLL clock not active\n"); | 3637 | DSSERR("%s (%s) not active\n", |
3638 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | ||
3639 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); | ||
3640 | } | ||
3641 | |||
3642 | static void dsi_calc_clock_param_ranges(void) | ||
3643 | { | ||
3644 | dsi.regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN); | ||
3645 | dsi.regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM); | ||
3646 | dsi.regm_dispc_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC); | ||
3647 | dsi.regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI); | ||
3648 | dsi.fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT); | ||
3649 | dsi.fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT); | ||
3650 | dsi.lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); | ||
3239 | } | 3651 | } |
3240 | 3652 | ||
3241 | int dsi_init(struct platform_device *pdev) | 3653 | static int dsi_init(struct platform_device *pdev) |
3242 | { | 3654 | { |
3243 | u32 rev; | 3655 | u32 rev; |
3244 | int r; | 3656 | int r, i; |
3657 | struct resource *dsi_mem; | ||
3245 | 3658 | ||
3659 | spin_lock_init(&dsi.irq_lock); | ||
3246 | spin_lock_init(&dsi.errors_lock); | 3660 | spin_lock_init(&dsi.errors_lock); |
3247 | dsi.errors = 0; | 3661 | dsi.errors = 0; |
3248 | 3662 | ||
@@ -3251,8 +3665,6 @@ int dsi_init(struct platform_device *pdev) | |||
3251 | dsi.irq_stats.last_reset = jiffies; | 3665 | dsi.irq_stats.last_reset = jiffies; |
3252 | #endif | 3666 | #endif |
3253 | 3667 | ||
3254 | init_completion(&dsi.bta_completion); | ||
3255 | |||
3256 | mutex_init(&dsi.lock); | 3668 | mutex_init(&dsi.lock); |
3257 | sema_init(&dsi.bus_lock, 1); | 3669 | sema_init(&dsi.bus_lock, 1); |
3258 | 3670 | ||
@@ -3268,24 +3680,45 @@ int dsi_init(struct platform_device *pdev) | |||
3268 | dsi.te_timer.function = dsi_te_timeout; | 3680 | dsi.te_timer.function = dsi_te_timeout; |
3269 | dsi.te_timer.data = 0; | 3681 | dsi.te_timer.data = 0; |
3270 | #endif | 3682 | #endif |
3271 | dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); | 3683 | dsi_mem = platform_get_resource(dsi.pdev, IORESOURCE_MEM, 0); |
3684 | if (!dsi_mem) { | ||
3685 | DSSERR("can't get IORESOURCE_MEM DSI\n"); | ||
3686 | r = -EINVAL; | ||
3687 | goto err1; | ||
3688 | } | ||
3689 | dsi.base = ioremap(dsi_mem->start, resource_size(dsi_mem)); | ||
3272 | if (!dsi.base) { | 3690 | if (!dsi.base) { |
3273 | DSSERR("can't ioremap DSI\n"); | 3691 | DSSERR("can't ioremap DSI\n"); |
3274 | r = -ENOMEM; | 3692 | r = -ENOMEM; |
3275 | goto err1; | 3693 | goto err1; |
3276 | } | 3694 | } |
3695 | dsi.irq = platform_get_irq(dsi.pdev, 0); | ||
3696 | if (dsi.irq < 0) { | ||
3697 | DSSERR("platform_get_irq failed\n"); | ||
3698 | r = -ENODEV; | ||
3699 | goto err2; | ||
3700 | } | ||
3277 | 3701 | ||
3278 | dsi.vdds_dsi_reg = dss_get_vdds_dsi(); | 3702 | r = request_irq(dsi.irq, omap_dsi_irq_handler, IRQF_SHARED, |
3279 | if (IS_ERR(dsi.vdds_dsi_reg)) { | 3703 | "OMAP DSI1", dsi.pdev); |
3280 | DSSERR("can't get VDDS_DSI regulator\n"); | 3704 | if (r < 0) { |
3281 | r = PTR_ERR(dsi.vdds_dsi_reg); | 3705 | DSSERR("request_irq failed\n"); |
3282 | goto err2; | 3706 | goto err2; |
3283 | } | 3707 | } |
3284 | 3708 | ||
3709 | /* DSI VCs initialization */ | ||
3710 | for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { | ||
3711 | dsi.vc[i].mode = DSI_VC_MODE_L4; | ||
3712 | dsi.vc[i].dssdev = NULL; | ||
3713 | dsi.vc[i].vc_id = 0; | ||
3714 | } | ||
3715 | |||
3716 | dsi_calc_clock_param_ranges(); | ||
3717 | |||
3285 | enable_clocks(1); | 3718 | enable_clocks(1); |
3286 | 3719 | ||
3287 | rev = dsi_read_reg(DSI_REVISION); | 3720 | rev = dsi_read_reg(DSI_REVISION); |
3288 | printk(KERN_INFO "OMAP DSI rev %d.%d\n", | 3721 | dev_dbg(&pdev->dev, "OMAP DSI rev %d.%d\n", |
3289 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 3722 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
3290 | 3723 | ||
3291 | enable_clocks(0); | 3724 | enable_clocks(0); |
@@ -3298,8 +3731,14 @@ err1: | |||
3298 | return r; | 3731 | return r; |
3299 | } | 3732 | } |
3300 | 3733 | ||
3301 | void dsi_exit(void) | 3734 | static void dsi_exit(void) |
3302 | { | 3735 | { |
3736 | if (dsi.vdds_dsi_reg != NULL) { | ||
3737 | regulator_put(dsi.vdds_dsi_reg); | ||
3738 | dsi.vdds_dsi_reg = NULL; | ||
3739 | } | ||
3740 | |||
3741 | free_irq(dsi.irq, dsi.pdev); | ||
3303 | iounmap(dsi.base); | 3742 | iounmap(dsi.base); |
3304 | 3743 | ||
3305 | destroy_workqueue(dsi.workqueue); | 3744 | destroy_workqueue(dsi.workqueue); |
@@ -3307,3 +3746,41 @@ void dsi_exit(void) | |||
3307 | DSSDBG("omap_dsi_exit\n"); | 3746 | DSSDBG("omap_dsi_exit\n"); |
3308 | } | 3747 | } |
3309 | 3748 | ||
3749 | /* DSI1 HW IP initialisation */ | ||
3750 | static int omap_dsi1hw_probe(struct platform_device *pdev) | ||
3751 | { | ||
3752 | int r; | ||
3753 | dsi.pdev = pdev; | ||
3754 | r = dsi_init(pdev); | ||
3755 | if (r) { | ||
3756 | DSSERR("Failed to initialize DSI\n"); | ||
3757 | goto err_dsi; | ||
3758 | } | ||
3759 | err_dsi: | ||
3760 | return r; | ||
3761 | } | ||
3762 | |||
3763 | static int omap_dsi1hw_remove(struct platform_device *pdev) | ||
3764 | { | ||
3765 | dsi_exit(); | ||
3766 | return 0; | ||
3767 | } | ||
3768 | |||
3769 | static struct platform_driver omap_dsi1hw_driver = { | ||
3770 | .probe = omap_dsi1hw_probe, | ||
3771 | .remove = omap_dsi1hw_remove, | ||
3772 | .driver = { | ||
3773 | .name = "omapdss_dsi1", | ||
3774 | .owner = THIS_MODULE, | ||
3775 | }, | ||
3776 | }; | ||
3777 | |||
3778 | int dsi_init_platform_driver(void) | ||
3779 | { | ||
3780 | return platform_driver_register(&omap_dsi1hw_driver); | ||
3781 | } | ||
3782 | |||
3783 | void dsi_uninit_platform_driver(void) | ||
3784 | { | ||
3785 | return platform_driver_unregister(&omap_dsi1hw_driver); | ||
3786 | } | ||