aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-03-02 07:47:04 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-03-15 04:54:18 -0400
commit4ae2ddddf44cd9f73def2dbdb68c6859072262ff (patch)
treee35ffc1b9fbc8529d7e0f2702e7717caa7731b44 /drivers/video/omap2/dss
parent69b281a61442f97e8df14babc9bb6a28624886b1 (diff)
OMAP: DSS2: DSI: Add ISR support
Add generic ISR support for DSI interrupts. ISRs can be used instead of custom hooks in the interrupt handler. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2/dss')
-rw-r--r--drivers/video/omap2/dss/dsi.c329
1 files changed, 304 insertions, 25 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index b6c08a6f2da1..8613ec489410 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -185,6 +185,16 @@ struct dsi_reg { u16 idx; };
185#define DSI_DT_RX_SHORT_READ_1 0x21 185#define DSI_DT_RX_SHORT_READ_1 0x21
186#define DSI_DT_RX_SHORT_READ_2 0x22 186#define DSI_DT_RX_SHORT_READ_2 0x22
187 187
188typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
189
190#define DSI_MAX_NR_ISRS 2
191
192struct dsi_isr_data {
193 omap_dsi_isr_t isr;
194 void *arg;
195 u32 mask;
196};
197
188enum fifo_size { 198enum fifo_size {
189 DSI_FIFO_SIZE_0 = 0, 199 DSI_FIFO_SIZE_0 = 0,
190 DSI_FIFO_SIZE_32 = 1, 200 DSI_FIFO_SIZE_32 = 1,
@@ -211,6 +221,12 @@ struct dsi_irq_stats {
211 unsigned cio_irqs[32]; 221 unsigned cio_irqs[32];
212}; 222};
213 223
224struct 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
214static struct 230static struct
215{ 231{
216 struct platform_device *pdev; 232 struct platform_device *pdev;
@@ -236,6 +252,11 @@ static struct
236 struct completion bta_completion; 252 struct completion bta_completion;
237 void (*bta_callback)(void); 253 void (*bta_callback)(void);
238 254
255 spinlock_t irq_lock;
256 struct dsi_isr_tables isr_tables;
257 /* space for a copy used by the interrupt handler */
258 struct dsi_isr_tables isr_tables_copy;
259
239 int update_channel; 260 int update_channel;
240 struct dsi_update_region update_region; 261 struct dsi_update_region update_region;
241 262
@@ -532,16 +553,56 @@ static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus)
532 } 553 }
533} 554}
534 555
556static void dsi_call_isrs(struct dsi_isr_data *isr_array,
557 unsigned isr_array_size, u32 irqstatus)
558{
559 struct dsi_isr_data *isr_data;
560 int i;
561
562 for (i = 0; i < isr_array_size; i++) {
563 isr_data = &isr_array[i];
564 if (isr_data->isr && isr_data->mask & irqstatus)
565 isr_data->isr(isr_data->arg, irqstatus);
566 }
567}
568
569static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables,
570 u32 irqstatus, u32 *vcstatus, u32 ciostatus)
571{
572 int i;
573
574 dsi_call_isrs(isr_tables->isr_table,
575 ARRAY_SIZE(isr_tables->isr_table),
576 irqstatus);
577
578 for (i = 0; i < 4; ++i) {
579 if (vcstatus[i] == 0)
580 continue;
581 dsi_call_isrs(isr_tables->isr_table_vc[i],
582 ARRAY_SIZE(isr_tables->isr_table_vc[i]),
583 vcstatus[i]);
584 }
585
586 if (ciostatus != 0)
587 dsi_call_isrs(isr_tables->isr_table_cio,
588 ARRAY_SIZE(isr_tables->isr_table_cio),
589 ciostatus);
590}
591
535static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) 592static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
536{ 593{
537 u32 irqstatus, vcstatus[4], ciostatus; 594 u32 irqstatus, vcstatus[4], ciostatus;
538 int i; 595 int i;
539 596
597 spin_lock(&dsi.irq_lock);
598
540 irqstatus = dsi_read_reg(DSI_IRQSTATUS); 599 irqstatus = dsi_read_reg(DSI_IRQSTATUS);
541 600
542 /* IRQ is not for us */ 601 /* IRQ is not for us */
543 if (!irqstatus) 602 if (!irqstatus) {
603 spin_unlock(&dsi.irq_lock);
544 return IRQ_NONE; 604 return IRQ_NONE;
605 }
545 606
546 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); 607 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
547 /* flush posted write */ 608 /* flush posted write */
@@ -587,6 +648,14 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
587 } 648 }
588 } 649 }
589 650
651 /* make a copy and unlock, so that isrs can unregister
652 * themselves */
653 memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables));
654
655 spin_unlock(&dsi.irq_lock);
656
657 dsi_handle_isrs(&dsi.isr_tables_copy, irqstatus, vcstatus, ciostatus);
658
590 dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus); 659 dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus);
591 660
592 dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus); 661 dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus);
@@ -594,42 +663,251 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
594 return IRQ_HANDLED; 663 return IRQ_HANDLED;
595} 664}
596 665
597static void _dsi_initialize_irq(void) 666/* dsi.irq_lock has to be locked by the caller */
667static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array,
668 unsigned isr_array_size, u32 default_mask,
669 const struct dsi_reg enable_reg,
670 const struct dsi_reg status_reg)
598{ 671{
599 u32 l; 672 struct dsi_isr_data *isr_data;
673 u32 mask;
674 u32 old_mask;
600 int i; 675 int i;
601 676
602 /* disable all interrupts */ 677 mask = default_mask;
603 dsi_write_reg(DSI_IRQENABLE, 0);
604 for (i = 0; i < 4; ++i)
605 dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
606 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
607 678
608 /* clear interrupt status */ 679 for (i = 0; i < isr_array_size; i++) {
609 l = dsi_read_reg(DSI_IRQSTATUS); 680 isr_data = &isr_array[i];
610 dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
611 681
612 for (i = 0; i < 4; ++i) { 682 if (isr_data->isr == NULL)
613 l = dsi_read_reg(DSI_VC_IRQSTATUS(i)); 683 continue;
614 dsi_write_reg(DSI_VC_IRQSTATUS(i), l); 684
685 mask |= isr_data->mask;
615 } 686 }
616 687
617 l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); 688 old_mask = dsi_read_reg(enable_reg);
618 dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l); 689 /* clear the irqstatus for newly enabled irqs */
690 dsi_write_reg(status_reg, (mask ^ old_mask) & mask);
691 dsi_write_reg(enable_reg, mask);
692
693 /* flush posted writes */
694 dsi_read_reg(enable_reg);
695 dsi_read_reg(status_reg);
696}
619 697
620 /* enable error irqs */ 698/* dsi.irq_lock has to be locked by the caller */
621 l = DSI_IRQ_ERROR_MASK; 699static void _omap_dsi_set_irqs(void)
700{
701 u32 mask = DSI_IRQ_ERROR_MASK;
622#ifdef DSI_CATCH_MISSING_TE 702#ifdef DSI_CATCH_MISSING_TE
623 l |= DSI_IRQ_TE_TRIGGER; 703 mask |= DSI_IRQ_TE_TRIGGER;
624#endif 704#endif
625 dsi_write_reg(DSI_IRQENABLE, l); 705 _omap_dsi_configure_irqs(dsi.isr_tables.isr_table,
706 ARRAY_SIZE(dsi.isr_tables.isr_table), mask,
707 DSI_IRQENABLE, DSI_IRQSTATUS);
708}
626 709
627 l = DSI_VC_IRQ_ERROR_MASK; 710/* dsi.irq_lock has to be locked by the caller */
628 for (i = 0; i < 4; ++i) 711static void _omap_dsi_set_irqs_vc(int vc)
629 dsi_write_reg(DSI_VC_IRQENABLE(i), l); 712{
713 _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_vc[vc],
714 ARRAY_SIZE(dsi.isr_tables.isr_table_vc[vc]),
715 DSI_VC_IRQ_ERROR_MASK,
716 DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc));
717}
718
719/* dsi.irq_lock has to be locked by the caller */
720static void _omap_dsi_set_irqs_cio(void)
721{
722 _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_cio,
723 ARRAY_SIZE(dsi.isr_tables.isr_table_cio),
724 DSI_CIO_IRQ_ERROR_MASK,
725 DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS);
726}
727
728static void _dsi_initialize_irq(void)
729{
730 unsigned long flags;
731 int vc;
732
733 spin_lock_irqsave(&dsi.irq_lock, flags);
734
735 memset(&dsi.isr_tables, 0, sizeof(dsi.isr_tables));
736
737 _omap_dsi_set_irqs();
738 for (vc = 0; vc < 4; ++vc)
739 _omap_dsi_set_irqs_vc(vc);
740 _omap_dsi_set_irqs_cio();
741
742 spin_unlock_irqrestore(&dsi.irq_lock, flags);
743}
630 744
631 l = DSI_CIO_IRQ_ERROR_MASK; 745static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
632 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l); 746 struct dsi_isr_data *isr_array, unsigned isr_array_size)
747{
748 struct dsi_isr_data *isr_data;
749 int free_idx;
750 int i;
751
752 BUG_ON(isr == NULL);
753
754 /* check for duplicate entry and find a free slot */
755 free_idx = -1;
756 for (i = 0; i < isr_array_size; i++) {
757 isr_data = &isr_array[i];
758
759 if (isr_data->isr == isr && isr_data->arg == arg &&
760 isr_data->mask == mask) {
761 return -EINVAL;
762 }
763
764 if (isr_data->isr == NULL && free_idx == -1)
765 free_idx = i;
766 }
767
768 if (free_idx == -1)
769 return -EBUSY;
770
771 isr_data = &isr_array[free_idx];
772 isr_data->isr = isr;
773 isr_data->arg = arg;
774 isr_data->mask = mask;
775
776 return 0;
777}
778
779static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
780 struct dsi_isr_data *isr_array, unsigned isr_array_size)
781{
782 struct dsi_isr_data *isr_data;
783 int i;
784
785 for (i = 0; i < isr_array_size; i++) {
786 isr_data = &isr_array[i];
787 if (isr_data->isr != isr || isr_data->arg != arg ||
788 isr_data->mask != mask)
789 continue;
790
791 isr_data->isr = NULL;
792 isr_data->arg = NULL;
793 isr_data->mask = 0;
794
795 return 0;
796 }
797
798 return -EINVAL;
799}
800
801static int dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask)
802{
803 unsigned long flags;
804 int r;
805
806 spin_lock_irqsave(&dsi.irq_lock, flags);
807
808 r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table,
809 ARRAY_SIZE(dsi.isr_tables.isr_table));
810
811 if (r == 0)
812 _omap_dsi_set_irqs();
813
814 spin_unlock_irqrestore(&dsi.irq_lock, flags);
815
816 return r;
817}
818
819static int dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask)
820{
821 unsigned long flags;
822 int r;
823
824 spin_lock_irqsave(&dsi.irq_lock, flags);
825
826 r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table,
827 ARRAY_SIZE(dsi.isr_tables.isr_table));
828
829 if (r == 0)
830 _omap_dsi_set_irqs();
831
832 spin_unlock_irqrestore(&dsi.irq_lock, flags);
833
834 return r;
835}
836
837static int dsi_register_isr_vc(int channel, omap_dsi_isr_t isr, void *arg,
838 u32 mask)
839{
840 unsigned long flags;
841 int r;
842
843 spin_lock_irqsave(&dsi.irq_lock, flags);
844
845 r = _dsi_register_isr(isr, arg, mask,
846 dsi.isr_tables.isr_table_vc[channel],
847 ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel]));
848
849 if (r == 0)
850 _omap_dsi_set_irqs_vc(channel);
851
852 spin_unlock_irqrestore(&dsi.irq_lock, flags);
853
854 return r;
855}
856
857static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg,
858 u32 mask)
859{
860 unsigned long flags;
861 int r;
862
863 spin_lock_irqsave(&dsi.irq_lock, flags);
864
865 r = _dsi_unregister_isr(isr, arg, mask,
866 dsi.isr_tables.isr_table_vc[channel],
867 ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel]));
868
869 if (r == 0)
870 _omap_dsi_set_irqs_vc(channel);
871
872 spin_unlock_irqrestore(&dsi.irq_lock, flags);
873
874 return r;
875}
876
877static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask)
878{
879 unsigned long flags;
880 int r;
881
882 spin_lock_irqsave(&dsi.irq_lock, flags);
883
884 r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio,
885 ARRAY_SIZE(dsi.isr_tables.isr_table_cio));
886
887 if (r == 0)
888 _omap_dsi_set_irqs_cio();
889
890 spin_unlock_irqrestore(&dsi.irq_lock, flags);
891
892 return r;
893}
894
895static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask)
896{
897 unsigned long flags;
898 int r;
899
900 spin_lock_irqsave(&dsi.irq_lock, flags);
901
902 r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio,
903 ARRAY_SIZE(dsi.isr_tables.isr_table_cio));
904
905 if (r == 0)
906 _omap_dsi_set_irqs_cio();
907
908 spin_unlock_irqrestore(&dsi.irq_lock, flags);
909
910 return r;
633} 911}
634 912
635static u32 dsi_get_errors(void) 913static u32 dsi_get_errors(void)
@@ -3383,6 +3661,7 @@ static int dsi_init(struct platform_device *pdev)
3383 int r, i; 3661 int r, i;
3384 struct resource *dsi_mem; 3662 struct resource *dsi_mem;
3385 3663
3664 spin_lock_init(&dsi.irq_lock);
3386 spin_lock_init(&dsi.errors_lock); 3665 spin_lock_init(&dsi.errors_lock);
3387 dsi.errors = 0; 3666 dsi.errors = 0;
3388 3667