.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. |
---|
2 | | - * |
---|
3 | | - * This program is free software; you can redistribute it and/or modify |
---|
4 | | - * it under the terms of the GNU General Public License version 2 and |
---|
5 | | - * only version 2 as published by the Free Software Foundation. |
---|
6 | | - * |
---|
7 | | - * This program is distributed in the hope that it will be useful, |
---|
8 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
9 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
10 | | - * GNU General Public License for more details. |
---|
11 | 3 | */ |
---|
12 | 4 | |
---|
13 | 5 | #include <linux/bitops.h> |
---|
.. | .. |
---|
170 | 162 | /** |
---|
171 | 163 | * AD4 interrupt status bit definitions |
---|
172 | 164 | */ |
---|
173 | | -#define DPU_INTR_BRIGHTPR_UPDATED BIT(4) |
---|
174 | | -#define DPU_INTR_DARKENH_UPDATED BIT(3) |
---|
175 | | -#define DPU_INTR_STREN_OUTROI_UPDATED BIT(2) |
---|
176 | | -#define DPU_INTR_STREN_INROI_UPDATED BIT(1) |
---|
177 | 165 | #define DPU_INTR_BACKLIGHT_UPDATED BIT(0) |
---|
178 | 166 | /** |
---|
179 | 167 | * struct dpu_intr_reg - array of DPU register sets |
---|
.. | .. |
---|
782 | 770 | return -EINVAL; |
---|
783 | 771 | } |
---|
784 | 772 | |
---|
785 | | -static void dpu_hw_intr_set_mask(struct dpu_hw_intr *intr, uint32_t reg_off, |
---|
786 | | - uint32_t mask) |
---|
787 | | -{ |
---|
788 | | - if (!intr) |
---|
789 | | - return; |
---|
790 | | - |
---|
791 | | - DPU_REG_WRITE(&intr->hw, reg_off, mask); |
---|
792 | | - |
---|
793 | | - /* ensure register writes go through */ |
---|
794 | | - wmb(); |
---|
795 | | -} |
---|
796 | | - |
---|
797 | 773 | static void dpu_hw_intr_dispatch_irq(struct dpu_hw_intr *intr, |
---|
798 | 774 | void (*cbfunc)(void *, int), |
---|
799 | 775 | void *arg) |
---|
.. | .. |
---|
824 | 800 | start_idx = reg_idx * 32; |
---|
825 | 801 | end_idx = start_idx + 32; |
---|
826 | 802 | |
---|
827 | | - if (start_idx >= ARRAY_SIZE(dpu_irq_map) || |
---|
828 | | - end_idx > ARRAY_SIZE(dpu_irq_map)) |
---|
| 803 | + if (!test_bit(reg_idx, &intr->irq_mask) || |
---|
| 804 | + start_idx >= ARRAY_SIZE(dpu_irq_map)) |
---|
829 | 805 | continue; |
---|
830 | 806 | |
---|
831 | 807 | /* |
---|
.. | .. |
---|
979 | 955 | if (!intr) |
---|
980 | 956 | return -EINVAL; |
---|
981 | 957 | |
---|
982 | | - for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) |
---|
983 | | - DPU_REG_WRITE(&intr->hw, dpu_intr_set[i].clr_off, 0xffffffff); |
---|
| 958 | + for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) { |
---|
| 959 | + if (test_bit(i, &intr->irq_mask)) |
---|
| 960 | + DPU_REG_WRITE(&intr->hw, |
---|
| 961 | + dpu_intr_set[i].clr_off, 0xffffffff); |
---|
| 962 | + } |
---|
984 | 963 | |
---|
985 | 964 | /* ensure register writes go through */ |
---|
986 | 965 | wmb(); |
---|
.. | .. |
---|
995 | 974 | if (!intr) |
---|
996 | 975 | return -EINVAL; |
---|
997 | 976 | |
---|
998 | | - for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) |
---|
999 | | - DPU_REG_WRITE(&intr->hw, dpu_intr_set[i].en_off, 0x00000000); |
---|
| 977 | + for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) { |
---|
| 978 | + if (test_bit(i, &intr->irq_mask)) |
---|
| 979 | + DPU_REG_WRITE(&intr->hw, |
---|
| 980 | + dpu_intr_set[i].en_off, 0x00000000); |
---|
| 981 | + } |
---|
1000 | 982 | |
---|
1001 | 983 | /* ensure register writes go through */ |
---|
1002 | 984 | wmb(); |
---|
1003 | | - |
---|
1004 | | - return 0; |
---|
1005 | | -} |
---|
1006 | | - |
---|
1007 | | -static int dpu_hw_intr_get_valid_interrupts(struct dpu_hw_intr *intr, |
---|
1008 | | - uint32_t *mask) |
---|
1009 | | -{ |
---|
1010 | | - if (!intr || !mask) |
---|
1011 | | - return -EINVAL; |
---|
1012 | | - |
---|
1013 | | - *mask = IRQ_SOURCE_MDP | IRQ_SOURCE_DSI0 | IRQ_SOURCE_DSI1 |
---|
1014 | | - | IRQ_SOURCE_HDMI | IRQ_SOURCE_EDP; |
---|
1015 | 985 | |
---|
1016 | 986 | return 0; |
---|
1017 | 987 | } |
---|
.. | .. |
---|
1027 | 997 | |
---|
1028 | 998 | spin_lock_irqsave(&intr->irq_lock, irq_flags); |
---|
1029 | 999 | for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) { |
---|
| 1000 | + if (!test_bit(i, &intr->irq_mask)) |
---|
| 1001 | + continue; |
---|
| 1002 | + |
---|
1030 | 1003 | /* Read interrupt status */ |
---|
1031 | 1004 | intr->save_irq_status[i] = DPU_REG_READ(&intr->hw, |
---|
1032 | 1005 | dpu_intr_set[i].status_off); |
---|
.. | .. |
---|
1065 | 1038 | wmb(); |
---|
1066 | 1039 | } |
---|
1067 | 1040 | |
---|
1068 | | -static void dpu_hw_intr_clear_interrupt_status(struct dpu_hw_intr *intr, |
---|
1069 | | - int irq_idx) |
---|
1070 | | -{ |
---|
1071 | | - unsigned long irq_flags; |
---|
1072 | | - |
---|
1073 | | - if (!intr) |
---|
1074 | | - return; |
---|
1075 | | - |
---|
1076 | | - spin_lock_irqsave(&intr->irq_lock, irq_flags); |
---|
1077 | | - dpu_hw_intr_clear_intr_status_nolock(intr, irq_idx); |
---|
1078 | | - spin_unlock_irqrestore(&intr->irq_lock, irq_flags); |
---|
1079 | | -} |
---|
1080 | | - |
---|
1081 | 1041 | static u32 dpu_hw_intr_get_interrupt_status(struct dpu_hw_intr *intr, |
---|
1082 | 1042 | int irq_idx, bool clear) |
---|
1083 | 1043 | { |
---|
.. | .. |
---|
1113 | 1073 | |
---|
1114 | 1074 | static void __setup_intr_ops(struct dpu_hw_intr_ops *ops) |
---|
1115 | 1075 | { |
---|
1116 | | - ops->set_mask = dpu_hw_intr_set_mask; |
---|
1117 | 1076 | ops->irq_idx_lookup = dpu_hw_intr_irqidx_lookup; |
---|
1118 | 1077 | ops->enable_irq = dpu_hw_intr_enable_irq; |
---|
1119 | 1078 | ops->disable_irq = dpu_hw_intr_disable_irq; |
---|
1120 | 1079 | ops->dispatch_irqs = dpu_hw_intr_dispatch_irq; |
---|
1121 | 1080 | ops->clear_all_irqs = dpu_hw_intr_clear_irqs; |
---|
1122 | 1081 | ops->disable_all_irqs = dpu_hw_intr_disable_irqs; |
---|
1123 | | - ops->get_valid_interrupts = dpu_hw_intr_get_valid_interrupts; |
---|
1124 | 1082 | ops->get_interrupt_statuses = dpu_hw_intr_get_interrupt_statuses; |
---|
1125 | | - ops->clear_interrupt_status = dpu_hw_intr_clear_interrupt_status; |
---|
1126 | 1083 | ops->clear_intr_status_nolock = dpu_hw_intr_clear_intr_status_nolock; |
---|
1127 | 1084 | ops->get_interrupt_status = dpu_hw_intr_get_interrupt_status; |
---|
1128 | 1085 | } |
---|
.. | .. |
---|
1167 | 1124 | return ERR_PTR(-ENOMEM); |
---|
1168 | 1125 | } |
---|
1169 | 1126 | |
---|
| 1127 | + intr->irq_mask = m->mdss_irqs; |
---|
1170 | 1128 | spin_lock_init(&intr->irq_lock); |
---|
1171 | 1129 | |
---|
1172 | 1130 | return intr; |
---|