7
7
* https://www.mipi.org/mipi-sdca-v1-0-download
8
8
*/
9
9
10
+ #include <linux/bitmap.h>
10
11
#include <linux/bits.h>
11
12
#include <linux/cleanup.h>
12
13
#include <linux/device.h>
18
19
#include <sound/sdca_function.h>
19
20
#include <sound/sdca_interrupts.h>
20
21
#include <sound/soc-component.h>
22
+ #include <sound/soc.h>
21
23
22
24
#define IRQ_SDCA (number ) REGMAP_IRQ_REG(number, ((number) / BITS_PER_BYTE), \
23
25
SDW_SCP_SDCA_INTMASK_SDCA_##number)
@@ -80,6 +82,143 @@ static irqreturn_t base_handler(int irq, void *data)
80
82
return IRQ_HANDLED ;
81
83
}
82
84
85
+ static irqreturn_t function_status_handler (int irq , void * data )
86
+ {
87
+ struct sdca_interrupt * interrupt = data ;
88
+ struct device * dev = interrupt -> component -> dev ;
89
+ unsigned int reg , val ;
90
+ unsigned long status ;
91
+ unsigned int mask ;
92
+ int ret ;
93
+
94
+ reg = SDW_SDCA_CTL (interrupt -> function -> desc -> adr , interrupt -> entity -> id ,
95
+ interrupt -> control -> sel , 0 );
96
+
97
+ ret = regmap_read (interrupt -> component -> regmap , reg , & val );
98
+ if (ret < 0 ) {
99
+ dev_err (dev , "failed to read function status: %d\n" , ret );
100
+ return IRQ_NONE ;
101
+ }
102
+
103
+ dev_dbg (dev , "function status: %#x\n" , val );
104
+
105
+ status = val ;
106
+ for_each_set_bit (mask , & status , BITS_PER_BYTE ) {
107
+ mask = 1 << mask ;
108
+
109
+ switch (mask ) {
110
+ case SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION :
111
+ //FIXME: Add init writes
112
+ break ;
113
+ case SDCA_CTL_ENTITY_0_FUNCTION_FAULT :
114
+ dev_err (dev , "function fault\n" );
115
+ break ;
116
+ case SDCA_CTL_ENTITY_0_UMP_SEQUENCE_FAULT :
117
+ dev_err (dev , "ump sequence fault\n" );
118
+ break ;
119
+ case SDCA_CTL_ENTITY_0_FUNCTION_BUSY :
120
+ dev_info (dev , "unexpected function busy\n" );
121
+ break ;
122
+ case SDCA_CTL_ENTITY_0_DEVICE_NEWLY_ATTACHED :
123
+ case SDCA_CTL_ENTITY_0_INTS_DISABLED_ABNORMALLY :
124
+ case SDCA_CTL_ENTITY_0_STREAMING_STOPPED_ABNORMALLY :
125
+ case SDCA_CTL_ENTITY_0_FUNCTION_HAS_BEEN_RESET :
126
+ break ;
127
+ }
128
+ }
129
+
130
+ ret = regmap_write (interrupt -> component -> regmap , reg , val );
131
+ if (ret < 0 ) {
132
+ dev_err (dev , "failed to clear function status: %d\n" , ret );
133
+ return IRQ_NONE ;
134
+ }
135
+
136
+ return IRQ_HANDLED ;
137
+ }
138
+
139
+ static irqreturn_t detected_mode_handler (int irq , void * data )
140
+ {
141
+ struct sdca_interrupt * interrupt = data ;
142
+ struct snd_soc_component * component = interrupt -> component ;
143
+ struct device * dev = component -> dev ;
144
+ struct snd_soc_card * card = component -> card ;
145
+ struct rw_semaphore * rwsem = & card -> snd_card -> controls_rwsem ;
146
+ struct snd_kcontrol * kctl = interrupt -> priv ;
147
+ struct snd_ctl_elem_value ucontrol ;
148
+ struct soc_enum * soc_enum ;
149
+ unsigned int reg , val ;
150
+ int ret ;
151
+
152
+ if (!kctl ) {
153
+ const char * name __free (kfree ) = kasprintf (GFP_KERNEL , "%s %s" ,
154
+ interrupt -> entity -> label ,
155
+ SDCA_CTL_SELECTED_MODE_NAME );
156
+
157
+ if (!name )
158
+ return - ENOMEM ;
159
+
160
+ kctl = snd_soc_component_get_kcontrol (component , name );
161
+ if (!kctl ) {
162
+ dev_dbg (dev , "control not found: %s\n" , name );
163
+ return IRQ_NONE ;
164
+ }
165
+
166
+ interrupt -> priv = kctl ;
167
+ }
168
+
169
+ soc_enum = (struct soc_enum * )kctl -> private_value ;
170
+
171
+ reg = SDW_SDCA_CTL (interrupt -> function -> desc -> adr , interrupt -> entity -> id ,
172
+ interrupt -> control -> sel , 0 );
173
+
174
+ ret = regmap_read (component -> regmap , reg , & val );
175
+ if (ret < 0 ) {
176
+ dev_err (dev , "failed to read detected mode: %d\n" , ret );
177
+ return IRQ_NONE ;
178
+ }
179
+
180
+ switch (val ) {
181
+ case SDCA_DETECTED_MODE_DETECTION_IN_PROGRESS :
182
+ case SDCA_DETECTED_MODE_JACK_UNKNOWN :
183
+ reg = SDW_SDCA_CTL (interrupt -> function -> desc -> adr ,
184
+ interrupt -> entity -> id ,
185
+ SDCA_CTL_GE_SELECTED_MODE , 0 );
186
+
187
+ /*
188
+ * Selected mode is not normally marked as volatile register
189
+ * (RW), but here force a read from the hardware. If the
190
+ * detected mode is unknown we need to see what the device
191
+ * selected as a "safe" option.
192
+ */
193
+ regcache_drop_region (component -> regmap , reg , reg );
194
+
195
+ ret = regmap_read (component -> regmap , reg , & val );
196
+ if (ret ) {
197
+ dev_err (dev , "failed to re-check selected mode: %d\n" , ret );
198
+ return IRQ_NONE ;
199
+ }
200
+ break ;
201
+ default :
202
+ break ;
203
+ }
204
+
205
+ dev_dbg (dev , "%s: %#x\n" , interrupt -> name , val );
206
+
207
+ ucontrol .value .enumerated .item [0 ] = snd_soc_enum_val_to_item (soc_enum , val );
208
+
209
+ down_write (rwsem );
210
+ ret = kctl -> put (kctl , & ucontrol );
211
+ up_write (rwsem );
212
+ if (ret < 0 ) {
213
+ dev_err (dev , "failed to update selected mode: %d\n" , ret );
214
+ return IRQ_NONE ;
215
+ }
216
+
217
+ snd_ctl_notify (card -> snd_card , SNDRV_CTL_EVENT_MASK_VALUE , & kctl -> id );
218
+
219
+ return IRQ_HANDLED ;
220
+ }
221
+
83
222
static int sdca_irq_request_locked (struct device * dev ,
84
223
struct sdca_interrupt_info * info ,
85
224
int sdca_irq , const char * name ,
@@ -202,6 +341,7 @@ int sdca_irq_populate(struct sdca_function_data *function,
202
341
struct sdca_control * control = & entity -> controls [j ];
203
342
int irq = control -> interrupt_position ;
204
343
struct sdca_interrupt * interrupt ;
344
+ irq_handler_t handler ;
205
345
const char * name ;
206
346
int ret ;
207
347
@@ -226,8 +366,23 @@ int sdca_irq_populate(struct sdca_function_data *function,
226
366
if (ret )
227
367
return ret ;
228
368
369
+ handler = base_handler ;
370
+
371
+ switch (entity -> type ) {
372
+ case SDCA_ENTITY_TYPE_ENTITY_0 :
373
+ if (control -> sel == SDCA_CTL_ENTITY_0_FUNCTION_STATUS )
374
+ handler = function_status_handler ;
375
+ break ;
376
+ case SDCA_ENTITY_TYPE_GE :
377
+ if (control -> sel == SDCA_CTL_GE_DETECTED_MODE )
378
+ handler = detected_mode_handler ;
379
+ break ;
380
+ default :
381
+ break ;
382
+ }
383
+
229
384
ret = sdca_irq_request_locked (dev , info , irq , interrupt -> name ,
230
- base_handler , interrupt );
385
+ handler , interrupt );
231
386
if (ret ) {
232
387
dev_err (dev , "failed to request irq %s: %d\n" ,
233
388
name , ret );
0 commit comments