Skip to content

Commit b9ab3b6

Browse files
charleskeepaxbroonie
authored andcommitted
ASoC: SDCA: Add some initial IRQ handlers
Add basic IRQ handlers for the function status and jack detection interrupts. Reviewed-by: Bard Liao <[email protected]> Signed-off-by: Charles Keepax <[email protected]> Reviewed-by: Pierre-Louis Bossart <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent b126394 commit b9ab3b6

File tree

2 files changed

+159
-1
lines changed

2 files changed

+159
-1
lines changed

include/sound/sdca_interrupts.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ struct sdca_function_data;
2727
* @function: Pointer to the Function that the interrupt is associated with.
2828
* @entity: Pointer to the Entity that the interrupt is associated with.
2929
* @control: Pointer to the Control that the interrupt is associated with.
30+
* @priv: Pointer to private data for use by the handler.
3031
* @externally_requested: Internal flag used to check if a client driver has
3132
* already requested the interrupt, for custom handling, allowing the core to
3233
* skip handling this interrupt.
@@ -39,6 +40,8 @@ struct sdca_interrupt {
3940
struct sdca_entity *entity;
4041
struct sdca_control *control;
4142

43+
void *priv;
44+
4245
bool externally_requested;
4346
};
4447

sound/soc/sdca/sdca_interrupts.c

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* https://www.mipi.org/mipi-sdca-v1-0-download
88
*/
99

10+
#include <linux/bitmap.h>
1011
#include <linux/bits.h>
1112
#include <linux/cleanup.h>
1213
#include <linux/device.h>
@@ -18,6 +19,7 @@
1819
#include <sound/sdca_function.h>
1920
#include <sound/sdca_interrupts.h>
2021
#include <sound/soc-component.h>
22+
#include <sound/soc.h>
2123

2224
#define IRQ_SDCA(number) REGMAP_IRQ_REG(number, ((number) / BITS_PER_BYTE), \
2325
SDW_SCP_SDCA_INTMASK_SDCA_##number)
@@ -80,6 +82,143 @@ static irqreturn_t base_handler(int irq, void *data)
8082
return IRQ_HANDLED;
8183
}
8284

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+
83222
static int sdca_irq_request_locked(struct device *dev,
84223
struct sdca_interrupt_info *info,
85224
int sdca_irq, const char *name,
@@ -202,6 +341,7 @@ int sdca_irq_populate(struct sdca_function_data *function,
202341
struct sdca_control *control = &entity->controls[j];
203342
int irq = control->interrupt_position;
204343
struct sdca_interrupt *interrupt;
344+
irq_handler_t handler;
205345
const char *name;
206346
int ret;
207347

@@ -226,8 +366,23 @@ int sdca_irq_populate(struct sdca_function_data *function,
226366
if (ret)
227367
return ret;
228368

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+
229384
ret = sdca_irq_request_locked(dev, info, irq, interrupt->name,
230-
base_handler, interrupt);
385+
handler, interrupt);
231386
if (ret) {
232387
dev_err(dev, "failed to request irq %s: %d\n",
233388
name, ret);

0 commit comments

Comments
 (0)