Lines Matching +full:codec +full:- +full:aif2 +full:- +full:bclk

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * This driver supports the digital controls for the internal codec
6 * (C) Copyright 2010-2016
9 * Mylène Josserand <mylene.josserand@free-electrons.com>
27 #include <sound/soc-dapm.h>
251 if (scodec->clk_bus) { in sun8i_codec_runtime_resume()
252 ret = clk_prepare_enable(scodec->clk_bus); in sun8i_codec_runtime_resume()
259 regcache_cache_only(scodec->regmap, false); in sun8i_codec_runtime_resume()
261 ret = regcache_sync(scodec->regmap); in sun8i_codec_runtime_resume()
274 regcache_cache_only(scodec->regmap, true); in sun8i_codec_runtime_suspend()
275 regcache_mark_dirty(scodec->regmap); in sun8i_codec_runtime_suspend()
277 if (scodec->clk_bus) in sun8i_codec_runtime_suspend()
278 clk_disable_unprepare(scodec->clk_bus); in sun8i_codec_runtime_suspend()
314 return -EINVAL; in sun8i_codec_get_hw_rate()
324 struct sun8i_codec_aif *aif = &scodec->aifs[i]; in sun8i_codec_update_sample_rate()
326 if (aif->active_streams) in sun8i_codec_update_sample_rate()
327 max_rate = max(max_rate, aif->sample_rate); in sun8i_codec_update_sample_rate()
330 /* Set the sample rate for ADC->DAC passthrough when no AIF is active. */ in sun8i_codec_update_sample_rate()
338 regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, in sun8i_codec_update_sample_rate()
352 case SND_SOC_DAIFMT_CBC_CFC: /* Codec slave, DAI master */ in sun8i_codec_set_fmt()
355 case SND_SOC_DAIFMT_CBP_CFP: /* Codec Master, DAI slave */ in sun8i_codec_set_fmt()
359 return -EINVAL; in sun8i_codec_set_fmt()
362 if (dai->id == SUN8I_CODEC_AIF3) { in sun8i_codec_set_fmt()
365 return -EINVAL; in sun8i_codec_set_fmt()
367 /* Use the AIF2 BCLK and LRCK for AIF3. */ in sun8i_codec_set_fmt()
368 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), in sun8i_codec_set_fmt()
372 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), in sun8i_codec_set_fmt()
397 return -EINVAL; in sun8i_codec_set_fmt()
400 if (dai->id == SUN8I_CODEC_AIF3) { in sun8i_codec_set_fmt()
403 return -EINVAL; in sun8i_codec_set_fmt()
405 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), in sun8i_codec_set_fmt()
418 case SND_SOC_DAIFMT_IB_NF: /* Inverted BCLK */ in sun8i_codec_set_fmt()
425 return -EINVAL; in sun8i_codec_set_fmt()
431 return -EINVAL; in sun8i_codec_set_fmt()
437 * It appears that the DAI and the codec in the A33 SoC don't in sun8i_codec_set_fmt()
443 * that the codec probably gets it backward, and we have to in sun8i_codec_set_fmt()
446 invert ^= scodec->quirks->lrck_inversion; in sun8i_codec_set_fmt()
449 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), in sun8i_codec_set_fmt()
461 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; in sun8i_codec_set_tdm_slot()
464 return -EINVAL; in sun8i_codec_set_tdm_slot()
466 aif->slots = slots; in sun8i_codec_set_tdm_slot()
467 aif->slot_width = slot_width; in sun8i_codec_set_tdm_slot()
501 if (dai->id != SUN8I_CODEC_AIF1) in sun8i_codec_startup()
504 if (!scodec->sysclk_refcnt) in sun8i_codec_startup()
506 else if (scodec->sysclk_rate == 22579200) in sun8i_codec_startup()
508 else if (scodec->sysclk_rate == 24576000) in sun8i_codec_startup()
511 return -EINVAL; in sun8i_codec_startup()
513 return snd_pcm_hw_constraint_list(substream->runtime, 0, in sun8i_codec_startup()
549 if (bdiv->div == div) in sun8i_codec_get_bclk_div()
550 return bdiv->val; in sun8i_codec_get_bclk_div()
553 return -EINVAL; in sun8i_codec_get_bclk_div()
562 return -EINVAL; in sun8i_codec_get_lrck_div_order()
577 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; in sun8i_codec_hw_params()
579 unsigned int slots = aif->slots ?: params_channels(params); in sun8i_codec_hw_params()
580 unsigned int slot_width = aif->slot_width ?: params_width(params); in sun8i_codec_hw_params()
600 return -EINVAL; in sun8i_codec_hw_params()
603 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), in sun8i_codec_hw_params()
607 /* LRCK divider (BCLK/LRCK ratio) */ in sun8i_codec_hw_params()
612 if (dai->id == SUN8I_CODEC_AIF2 || dai->id == SUN8I_CODEC_AIF3) { in sun8i_codec_hw_params()
613 /* AIF2 and AIF3 share AIF2's BCLK and LRCK generation circuitry. */ in sun8i_codec_hw_params()
614 int partner = (SUN8I_CODEC_AIF2 + SUN8I_CODEC_AIF3) - dai->id; in sun8i_codec_hw_params()
615 const struct sun8i_codec_aif *partner_aif = &scodec->aifs[partner]; in sun8i_codec_hw_params()
618 if (partner_aif->open_streams && in sun8i_codec_hw_params()
619 (lrck_div_order != partner_aif->lrck_div_order || in sun8i_codec_hw_params()
620 sample_rate != partner_aif->sample_rate)) { in sun8i_codec_hw_params()
621 dev_err(dai->dev, in sun8i_codec_hw_params()
623 dai->name, partner_name); in sun8i_codec_hw_params()
624 return -EBUSY; in sun8i_codec_hw_params()
629 clk_reg = SUN8I_AIF_CLK_CTRL(dai->id); in sun8i_codec_hw_params()
632 regmap_update_bits(scodec->regmap, clk_reg, in sun8i_codec_hw_params()
634 (lrck_div_order - 4) << SUN8I_AIF_CLK_CTRL_LRCK_DIV); in sun8i_codec_hw_params()
636 /* BCLK divider (SYSCLK/BCLK ratio) */ in sun8i_codec_hw_params()
641 regmap_update_bits(scodec->regmap, clk_reg, in sun8i_codec_hw_params()
654 ret = (aif->open_streams ? clk_set_rate : clk_set_rate_exclusive)(scodec->clk_module, in sun8i_codec_hw_params()
656 if (ret == -EBUSY) in sun8i_codec_hw_params()
657 dev_err(dai->dev, in sun8i_codec_hw_params()
659 dai->name, sample_rate); in sun8i_codec_hw_params()
663 if (!aif->open_streams) in sun8i_codec_hw_params()
664 scodec->sysclk_refcnt++; in sun8i_codec_hw_params()
665 scodec->sysclk_rate = sysclk_rate; in sun8i_codec_hw_params()
667 aif->lrck_div_order = lrck_div_order; in sun8i_codec_hw_params()
668 aif->sample_rate = sample_rate; in sun8i_codec_hw_params()
669 aif->open_streams |= BIT(substream->stream); in sun8i_codec_hw_params()
678 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; in sun8i_codec_hw_free()
681 if (aif->open_streams != BIT(substream->stream)) in sun8i_codec_hw_free()
684 clk_rate_exclusive_put(scodec->clk_module); in sun8i_codec_hw_free()
685 scodec->sysclk_refcnt--; in sun8i_codec_hw_free()
686 aif->lrck_div_order = 0; in sun8i_codec_hw_free()
687 aif->sample_rate = 0; in sun8i_codec_hw_free()
690 aif->open_streams &= ~BIT(substream->stream); in sun8i_codec_hw_free()
704 .name = "sun8i-codec-aif1",
729 .name = "sun8i-codec-aif2",
734 .stream_name = "AIF2 Capture",
743 .stream_name = "AIF2 Playback",
754 .name = "sun8i-codec-aif3",
780 static const DECLARE_TLV_DB_SCALE(sun8i_codec_vol_scale, -12000, 75, 1);
793 SOC_DOUBLE_TLV("AIF2 ADC Capture Volume",
798 SOC_DOUBLE_TLV("AIF2 DAC Playback Volume",
818 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); in sun8i_codec_aif_event()
820 struct sun8i_codec_aif *aif = &scodec->aifs[w->sname[3] - '1']; in sun8i_codec_aif_event()
821 int stream = w->id == snd_soc_dapm_aif_out; in sun8i_codec_aif_event()
824 aif->active_streams |= BIT(stream); in sun8i_codec_aif_event()
826 aif->active_streams &= ~BIT(stream); in sun8i_codec_aif_event()
852 SOC_DAPM_ENUM("AIF2 ADC Stereo Capture Route",
856 "None", "AIF2 ADCL", "AIF2 ADCR"
873 SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch",
881 SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
888 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA0 Capture Switch",
892 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA1 Capture Switch",
896 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF2 DAC Rev Capture Switch",
900 SOC_DAPM_DOUBLE("AIF2 ADC Mixer ADC Capture Switch",
907 "AIF2", "AIF3+2", "AIF2+3"
916 SOC_DAPM_ENUM("AIF2 DAC Source Playback Route",
936 SOC_DAPM_ENUM("AIF2 DAC Stereo Playback Route",
948 SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
974 SND_SOC_DAPM_SUPPLY("CLK AIF2",
991 SND_SOC_DAPM_SUPPLY("RST AIF2",
1022 SND_SOC_DAPM_AIF_OUT_E("AIF2 ADCL", "AIF2 Capture", 0,
1027 SND_SOC_DAPM_AIF_OUT("AIF2 ADCR", "AIF2 Capture", 1,
1042 SND_SOC_DAPM_MUX("AIF2 ADCL Stereo Mux", SND_SOC_NOPM, 0, 0,
1044 SND_SOC_DAPM_MUX("AIF2 ADCR Stereo Mux", SND_SOC_NOPM, 0, 0,
1057 SOC_MIXER_ARRAY("AIF2 ADCL Mixer", SND_SOC_NOPM, 0, 0,
1059 SOC_MIXER_ARRAY("AIF2 ADCR Mixer", SND_SOC_NOPM, 0, 0,
1063 SND_SOC_DAPM_MUX("AIF2 DACL Source", SND_SOC_NOPM, 0, 0,
1065 SND_SOC_DAPM_MUX("AIF2 DACR Source", SND_SOC_NOPM, 0, 0,
1074 SND_SOC_DAPM_MUX("AIF2 DACL Stereo Mux", SND_SOC_NOPM, 0, 0,
1076 SND_SOC_DAPM_MUX("AIF2 DACR Stereo Mux", SND_SOC_NOPM, 0, 0,
1089 SND_SOC_DAPM_AIF_IN_E("AIF2 DACL", "AIF2 Playback", 0,
1094 SND_SOC_DAPM_AIF_IN("AIF2 DACR", "AIF2 Playback", 1,
1103 /* ADC Inputs (connected to analog codec DAPM context) */
1107 /* DAC Outputs (connected to analog codec DAPM context) */
1132 { "CLK AIF2", NULL, "AIF2CLK" },
1133 { "CLK AIF2", NULL, "SYSCLK" },
1134 { "RST AIF2", NULL, "CLK AIF2" },
1135 { "AIF2 ADCL", NULL, "RST AIF2" },
1136 { "AIF2 ADCR", NULL, "RST AIF2" },
1137 { "AIF2 DACL", NULL, "RST AIF2" },
1138 { "AIF2 DACR", NULL, "RST AIF2" },
1162 { "AIF2 ADCL", NULL, "AIF2 ADCL Stereo Mux" },
1163 { "AIF2 ADCR", NULL, "AIF2 ADCR Stereo Mux" },
1182 { "AIF2 ADCL Stereo Mux", "Stereo", "AIF2 ADCL Mixer" },
1183 { "AIF2 ADCL Stereo Mux", "Reverse Stereo", "AIF2 ADCR Mixer" },
1184 { "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" },
1185 { "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" },
1186 { "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" },
1187 { "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" },
1189 { "AIF2 ADCR Stereo Mux", "Stereo", "AIF2 ADCR Mixer" },
1190 { "AIF2 ADCR Stereo Mux", "Reverse Stereo", "AIF2 ADCL Mixer" },
1191 { "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" },
1192 { "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" },
1193 { "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" },
1194 { "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" },
1197 { "AIF3 ADC Source Capture Route", "AIF2 ADCL", "AIF2 ADCL Mixer" },
1198 { "AIF3 ADC Source Capture Route", "AIF2 ADCR", "AIF2 ADCR Mixer" },
1202 { "AIF1 AD0L Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACL Source" },
1204 { "AIF1 AD0L Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACR Source" },
1207 { "AIF1 AD0R Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACR Source" },
1209 { "AIF1 AD0R Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACL Source" },
1211 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0L Stereo Mux" },
1212 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACR Source" },
1213 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCL" },
1215 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0R Stereo Mux" },
1216 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACL Source" },
1217 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCR" },
1220 { "AIF2 DACL Source", "AIF2", "AIF2 DACL Stereo Mux" },
1221 { "AIF2 DACL Source", "AIF3+2", "AIF3 DAC" },
1222 { "AIF2 DACL Source", "AIF2+3", "AIF2 DACL Stereo Mux" },
1224 { "AIF2 DACR Source", "AIF2", "AIF2 DACR Stereo Mux" },
1225 { "AIF2 DACR Source", "AIF3+2", "AIF2 DACR Stereo Mux" },
1226 { "AIF2 DACR Source", "AIF2+3", "AIF3 DAC" },
1243 { "AIF2 DACL Stereo Mux", "Stereo", "AIF2 DACL" },
1244 { "AIF2 DACL Stereo Mux", "Reverse Stereo", "AIF2 DACR" },
1245 { "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACL" },
1246 { "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACR" },
1247 { "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACL" },
1248 { "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACR" },
1250 { "AIF2 DACR Stereo Mux", "Stereo", "AIF2 DACR" },
1251 { "AIF2 DACR Stereo Mux", "Reverse Stereo", "AIF2 DACL" },
1252 { "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACL" },
1253 { "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACR" },
1254 { "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACL" },
1255 { "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACR" },
1263 { "DACL Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACL Source" },
1267 { "DACR Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACR Source" },
1272 /* Legacy ADC Inputs (connected to analog codec DAPM context) */
1276 /* Legacy DAC Outputs (connected to analog codec DAPM context) */
1297 scodec->component = component; in sun8i_codec_component_probe()
1300 if (scodec->quirks->legacy_widgets) { in sun8i_codec_component_probe()
1318 regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL, in sun8i_codec_component_probe()
1325 regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL, in sun8i_codec_component_probe()
1337 struct snd_soc_dapm_context *dapm = &scodec->component->card->dapm; in sun8i_codec_set_hmic_bias()
1347 regmap_update_bits(scodec->regmap, SUN8I_HMIC_CTRL1, in sun8i_codec_set_hmic_bias()
1358 guard(mutex)(&scodec->jack_mutex); in sun8i_codec_jack_work()
1360 if (scodec->jack_status == SUN8I_JACK_STATUS_DISCONNECTED) { in sun8i_codec_jack_work()
1361 if (scodec->last_hmic_irq != SUN8I_HMIC_STS_JACK_IN_IRQ_ST) in sun8i_codec_jack_work()
1364 scodec->jack_last_sample = -1; in sun8i_codec_jack_work()
1366 if (scodec->jack_type & SND_JACK_MICROPHONE) { in sun8i_codec_jack_work()
1371 scodec->jack_hbias_ready = ktime_add_ms(ktime_get(), 600); in sun8i_codec_jack_work()
1374 &scodec->jack_work, in sun8i_codec_jack_work()
1376 scodec->jack_status = SUN8I_JACK_STATUS_WAITING_HBIAS; in sun8i_codec_jack_work()
1378 snd_soc_jack_report(scodec->jack, SND_JACK_HEADPHONE, in sun8i_codec_jack_work()
1379 scodec->jack_type); in sun8i_codec_jack_work()
1380 scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED; in sun8i_codec_jack_work()
1382 } else if (scodec->jack_status == SUN8I_JACK_STATUS_WAITING_HBIAS) { in sun8i_codec_jack_work()
1384 * If we're waiting for HBIAS to stabilize, and we get plug-out in sun8i_codec_jack_work()
1388 if (scodec->last_hmic_irq == SUN8I_HMIC_STS_JACK_OUT_IRQ_ST) { in sun8i_codec_jack_work()
1389 scodec->jack_status = SUN8I_JACK_STATUS_DISCONNECTED; in sun8i_codec_jack_work()
1397 if (!ktime_after(ktime_get(), scodec->jack_hbias_ready)) { in sun8i_codec_jack_work()
1398 s64 msecs = ktime_ms_delta(scodec->jack_hbias_ready, in sun8i_codec_jack_work()
1402 &scodec->jack_work, in sun8i_codec_jack_work()
1410 regmap_read(scodec->regmap, SUN8I_HMIC_STS, &mdata); in sun8i_codec_jack_work()
1414 regmap_write(scodec->regmap, SUN8I_HMIC_STS, 0); in sun8i_codec_jack_work()
1420 snd_soc_jack_report(scodec->jack, type, scodec->jack_type); in sun8i_codec_jack_work()
1421 scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED; in sun8i_codec_jack_work()
1422 } else if (scodec->jack_status == SUN8I_JACK_STATUS_CONNECTED) { in sun8i_codec_jack_work()
1423 if (scodec->last_hmic_irq != SUN8I_HMIC_STS_JACK_OUT_IRQ_ST) in sun8i_codec_jack_work()
1426 scodec->jack_status = SUN8I_JACK_STATUS_DISCONNECTED; in sun8i_codec_jack_work()
1427 if (scodec->jack_type & SND_JACK_MICROPHONE) in sun8i_codec_jack_work()
1430 snd_soc_jack_report(scodec->jack, 0, scodec->jack_type); in sun8i_codec_jack_work()
1440 guard(mutex)(&scodec->jack_mutex); in sun8i_codec_jack_irq()
1442 regmap_read(scodec->regmap, SUN8I_HMIC_STS, &status); in sun8i_codec_jack_irq()
1443 regmap_write(scodec->regmap, SUN8I_HMIC_STS, status); in sun8i_codec_jack_irq()
1446 * De-bounce in/out interrupts via a delayed work re-scheduling to in sun8i_codec_jack_irq()
1455 scodec->last_hmic_irq = SUN8I_HMIC_STS_JACK_OUT_IRQ_ST; in sun8i_codec_jack_irq()
1456 mod_delayed_work(system_power_efficient_wq, &scodec->jack_work, in sun8i_codec_jack_irq()
1459 scodec->last_hmic_irq = SUN8I_HMIC_STS_JACK_IN_IRQ_ST; in sun8i_codec_jack_irq()
1460 mod_delayed_work(system_power_efficient_wq, &scodec->jack_work, in sun8i_codec_jack_irq()
1468 if (scodec->jack_status != SUN8I_JACK_STATUS_CONNECTED) in sun8i_codec_jack_irq()
1488 * De-bounce. Only report button after two consecutive A/D in sun8i_codec_jack_irq()
1491 if (scodec->jack_last_sample >= 0 && in sun8i_codec_jack_irq()
1492 scodec->jack_last_sample == value) in sun8i_codec_jack_irq()
1493 snd_soc_jack_report(scodec->jack, type, in sun8i_codec_jack_irq()
1494 scodec->jack_type); in sun8i_codec_jack_irq()
1496 scodec->jack_last_sample = value; in sun8i_codec_jack_irq()
1506 struct platform_device *pdev = to_platform_device(component->dev); in sun8i_codec_enable_jack_detect()
1509 if (!scodec->quirks->jack_detection) in sun8i_codec_enable_jack_detect()
1512 scodec->jack = jack; in sun8i_codec_enable_jack_detect()
1514 scodec->jack_irq = platform_get_irq(pdev, 0); in sun8i_codec_enable_jack_detect()
1515 if (scodec->jack_irq < 0) in sun8i_codec_enable_jack_detect()
1516 return scodec->jack_irq; in sun8i_codec_enable_jack_detect()
1519 regmap_write(scodec->regmap, SUN8I_HMIC_CTRL1, in sun8i_codec_enable_jack_detect()
1525 regmap_write(scodec->regmap, SUN8I_HMIC_CTRL2, in sun8i_codec_enable_jack_detect()
1531 regmap_write(scodec->regmap, SUN8I_HMIC_STS, 0); in sun8i_codec_enable_jack_detect()
1533 regmap_set_bits(scodec->regmap, SUN8I_HMIC_CTRL1, in sun8i_codec_enable_jack_detect()
1537 ret = devm_request_threaded_irq(&pdev->dev, scodec->jack_irq, in sun8i_codec_enable_jack_detect()
1540 dev_name(&pdev->dev), scodec); in sun8i_codec_enable_jack_detect()
1551 if (!scodec->quirks->jack_detection) in sun8i_codec_disable_jack_detect()
1554 devm_free_irq(component->dev, scodec->jack_irq, scodec); in sun8i_codec_disable_jack_detect()
1556 cancel_delayed_work_sync(&scodec->jack_work); in sun8i_codec_disable_jack_detect()
1558 regmap_clear_bits(scodec->regmap, SUN8I_HMIC_CTRL1, in sun8i_codec_disable_jack_detect()
1563 scodec->jack = NULL; in sun8i_codec_disable_jack_detect()
1614 scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL); in sun8i_codec_probe()
1616 return -ENOMEM; in sun8i_codec_probe()
1618 scodec->quirks = of_device_get_match_data(&pdev->dev); in sun8i_codec_probe()
1619 INIT_DELAYED_WORK(&scodec->jack_work, sun8i_codec_jack_work); in sun8i_codec_probe()
1620 mutex_init(&scodec->jack_mutex); in sun8i_codec_probe()
1624 if (scodec->quirks->bus_clock) { in sun8i_codec_probe()
1625 scodec->clk_bus = devm_clk_get(&pdev->dev, "bus"); in sun8i_codec_probe()
1626 if (IS_ERR(scodec->clk_bus)) { in sun8i_codec_probe()
1627 dev_err(&pdev->dev, "Failed to get the bus clock\n"); in sun8i_codec_probe()
1628 return PTR_ERR(scodec->clk_bus); in sun8i_codec_probe()
1632 scodec->clk_module = devm_clk_get(&pdev->dev, "mod"); in sun8i_codec_probe()
1633 if (IS_ERR(scodec->clk_module)) { in sun8i_codec_probe()
1634 dev_err(&pdev->dev, "Failed to get the module clock\n"); in sun8i_codec_probe()
1635 return PTR_ERR(scodec->clk_module); in sun8i_codec_probe()
1640 dev_err(&pdev->dev, "Failed to map the registers\n"); in sun8i_codec_probe()
1644 scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base, in sun8i_codec_probe()
1646 if (IS_ERR(scodec->regmap)) { in sun8i_codec_probe()
1647 dev_err(&pdev->dev, "Failed to create our regmap\n"); in sun8i_codec_probe()
1648 return PTR_ERR(scodec->regmap); in sun8i_codec_probe()
1651 regcache_cache_only(scodec->regmap, true); in sun8i_codec_probe()
1652 pm_runtime_enable(&pdev->dev); in sun8i_codec_probe()
1653 if (!pm_runtime_enabled(&pdev->dev)) { in sun8i_codec_probe()
1654 ret = sun8i_codec_runtime_resume(&pdev->dev); in sun8i_codec_probe()
1659 ret = devm_snd_soc_register_component(&pdev->dev, &sun8i_soc_component, in sun8i_codec_probe()
1663 dev_err(&pdev->dev, "Failed to register codec\n"); in sun8i_codec_probe()
1670 if (!pm_runtime_status_suspended(&pdev->dev)) in sun8i_codec_probe()
1671 sun8i_codec_runtime_suspend(&pdev->dev); in sun8i_codec_probe()
1674 pm_runtime_disable(&pdev->dev); in sun8i_codec_probe()
1681 pm_runtime_disable(&pdev->dev); in sun8i_codec_remove()
1682 if (!pm_runtime_status_suspended(&pdev->dev)) in sun8i_codec_remove()
1683 sun8i_codec_runtime_suspend(&pdev->dev); in sun8i_codec_remove()
1698 { .compatible = "allwinner,sun8i-a33-codec", .data = &sun8i_a33_quirks },
1699 { .compatible = "allwinner,sun50i-a64-codec", .data = &sun50i_a64_quirks },
1711 .name = "sun8i-codec",
1720 MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver");
1721 MODULE_AUTHOR("Mylène Josserand <mylene.josserand@free-electrons.com>");
1723 MODULE_ALIAS("platform:sun8i-codec");