int arizona_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; struct snd_soc_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val, mux, change; unsigned int mask; struct snd_soc_dapm_update update; int wi; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; mux = ucontrol->value.enumerated.item[0]; val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { if (ucontrol->value.enumerated.item[1] > e->max - 1) return -EINVAL; val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; mask |= e->mask << e->shift_r; } change = snd_soc_test_bits(widget->codec, e->reg, mask, val); if (change) { for (wi = 0; wi < wlist->num_widgets; wi++) { widget = wlist->widgets[wi]; widget->value = val; update.kcontrol = kcontrol; update.widget = widget; update.reg = e->reg; update.mask = mask; update.val = val; widget->dapm->update = &update; snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e); widget->dapm->update = NULL; } } return change; }
/* * The MUX register for the Capture and Playback MUXs selects either DSP as * source/destination or one of the TDM slots. The TDM slot is selected via * snd_soc_dai_set_tdm_slot(), so we only expose whether to go to the DSP or * directly to the DAI interface with this control. */ static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct adau *adau = snd_soc_component_get_drvdata(component); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct snd_soc_dapm_update update = {}; unsigned int stream = e->shift_l; unsigned int val, change; int reg; if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; switch (ucontrol->value.enumerated.item[0]) { case 0: val = 0; adau->dsp_bypass[stream] = false; break; default: val = (adau->tdm_slot[stream] * 2) + 1; adau->dsp_bypass[stream] = true; break; } if (stream == SNDRV_PCM_STREAM_PLAYBACK) reg = ADAU17X1_SERIAL_INPUT_ROUTE; else reg = ADAU17X1_SERIAL_OUTPUT_ROUTE; change = snd_soc_component_test_bits(component, reg, 0xff, val); if (change) { update.kcontrol = kcontrol; update.mask = 0xff; update.reg = reg; update.val = val; snd_soc_dapm_mux_update_power(dapm, kcontrol, ucontrol->value.enumerated.item[0], e, &update); } return change; }
static int ul_mux_put_route(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_platform *platform = widget->platform; struct omap_abe *abe = snd_soc_platform_get_drvdata(platform); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int mux = ucontrol->value.enumerated.item[0]; int reg = e->reg - OMAP_ABE_MUX(0); if (mux > OMAP_ABE_ROUTES_UL) { pr_err("inavlid mux %d\n", mux); return 0; } abe_dsp_pm_get(abe); /* TODO: remove the gap */ if (reg < 8) { /* 0 .. 9 = MM_UL */ abe->mixer.route_ul[reg] = router[mux]; } else if (reg < 12) { /* 10 .. 11 = MM_UL2 */ /* 12 .. 13 = VX_UL */ abe->mixer.route_ul[reg + 2] = router[mux]; } /* 2nd arg here is unused */ omap_aess_set_router_configuration(abe->aess, UPROUTE, 0, (u32 *)abe->mixer.route_ul); if (router[mux] != ZERO_labelID) abe->opp.widget[e->reg] = e->shift_l; else abe->opp.widget[e->reg] = 0; snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e); pm_runtime_put_sync(abe->dev); return 1; }