1724 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * This driver supports the digital controls for the internal codec4 * found in Allwinner's A33 SoCs.5 *6 * (C) Copyright 2010-20167 * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>8 * huangxin <huangxin@Reuuimllatech.com>9 * Mylène Josserand <mylene.josserand@free-electrons.com>10 */11 12#include <linux/module.h>13#include <linux/delay.h>14#include <linux/clk.h>15#include <linux/input.h>16#include <linux/io.h>17#include <linux/irq.h>18#include <linux/mutex.h>19#include <linux/of.h>20#include <linux/pm_runtime.h>21#include <linux/regmap.h>22#include <linux/log2.h>23 24#include <sound/jack.h>25#include <sound/pcm_params.h>26#include <sound/soc.h>27#include <sound/soc-dapm.h>28#include <sound/tlv.h>29 30#define SUN8I_SYSCLK_CTL 0x00c31#define SUN8I_SYSCLK_CTL_AIF1CLK_ENA 1132#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL (0x2 << 8)33#define SUN8I_SYSCLK_CTL_AIF2CLK_ENA 734#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL (0x2 << 4)35#define SUN8I_SYSCLK_CTL_SYSCLK_ENA 336#define SUN8I_SYSCLK_CTL_SYSCLK_SRC 037#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK (0x0 << 0)38#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK (0x1 << 0)39#define SUN8I_MOD_CLK_ENA 0x01040#define SUN8I_MOD_CLK_ENA_AIF1 1541#define SUN8I_MOD_CLK_ENA_AIF2 1442#define SUN8I_MOD_CLK_ENA_AIF3 1343#define SUN8I_MOD_CLK_ENA_ADC 344#define SUN8I_MOD_CLK_ENA_DAC 245#define SUN8I_MOD_RST_CTL 0x01446#define SUN8I_MOD_RST_CTL_AIF1 1547#define SUN8I_MOD_RST_CTL_AIF2 1448#define SUN8I_MOD_RST_CTL_AIF3 1349#define SUN8I_MOD_RST_CTL_ADC 350#define SUN8I_MOD_RST_CTL_DAC 251#define SUN8I_SYS_SR_CTRL 0x01852#define SUN8I_SYS_SR_CTRL_AIF1_FS 1253#define SUN8I_SYS_SR_CTRL_AIF2_FS 854#define SUN8I_AIF_CLK_CTRL(n) (0x040 * (1 + (n)))55#define SUN8I_AIF_CLK_CTRL_MSTR_MOD 1556#define SUN8I_AIF_CLK_CTRL_CLK_INV 1357#define SUN8I_AIF_CLK_CTRL_BCLK_DIV 958#define SUN8I_AIF_CLK_CTRL_LRCK_DIV 659#define SUN8I_AIF_CLK_CTRL_WORD_SIZ 460#define SUN8I_AIF_CLK_CTRL_DATA_FMT 261#define SUN8I_AIF1_ADCDAT_CTRL 0x04462#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA 1563#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA 1464#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC 1065#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC 866#define SUN8I_AIF1_DACDAT_CTRL 0x04867#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA 1568#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA 1469#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC 1070#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC 871#define SUN8I_AIF1_MXR_SRC 0x04c72#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L 1573#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL 1474#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL 1375#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR 1276#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R 1177#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR 1078#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR 979#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL 880#define SUN8I_AIF1_VOL_CTRL1 0x05081#define SUN8I_AIF1_VOL_CTRL1_AD0L_VOL 882#define SUN8I_AIF1_VOL_CTRL1_AD0R_VOL 083#define SUN8I_AIF1_VOL_CTRL3 0x05884#define SUN8I_AIF1_VOL_CTRL3_DA0L_VOL 885#define SUN8I_AIF1_VOL_CTRL3_DA0R_VOL 086#define SUN8I_AIF2_ADCDAT_CTRL 0x08487#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA 1588#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA 1489#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC 1090#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC 891#define SUN8I_AIF2_DACDAT_CTRL 0x08892#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA 1593#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA 1494#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC 1095#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC 896#define SUN8I_AIF2_MXR_SRC 0x08c97#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L 1598#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L 1499#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR 13100#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL 12101#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R 11102#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R 10103#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL 9104#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR 8105#define SUN8I_AIF2_VOL_CTRL1 0x090106#define SUN8I_AIF2_VOL_CTRL1_ADCL_VOL 8107#define SUN8I_AIF2_VOL_CTRL1_ADCR_VOL 0108#define SUN8I_AIF2_VOL_CTRL2 0x098109#define SUN8I_AIF2_VOL_CTRL2_DACL_VOL 8110#define SUN8I_AIF2_VOL_CTRL2_DACR_VOL 0111#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1 (0x0 << 0)112#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2 (0x1 << 0)113#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1CLK (0x2 << 0)114#define SUN8I_AIF3_PATH_CTRL 0x0cc115#define SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC 10116#define SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC 8117#define SUN8I_AIF3_PATH_CTRL_AIF3_PINS_TRI 7118#define SUN8I_ADC_DIG_CTRL 0x100119#define SUN8I_ADC_DIG_CTRL_ENAD 15120#define SUN8I_ADC_DIG_CTRL_ADOUT_DTS 2121#define SUN8I_ADC_DIG_CTRL_ADOUT_DLY 1122#define SUN8I_ADC_VOL_CTRL 0x104123#define SUN8I_ADC_VOL_CTRL_ADCL_VOL 8124#define SUN8I_ADC_VOL_CTRL_ADCR_VOL 0125#define SUN8I_HMIC_CTRL1 0x110126#define SUN8I_HMIC_CTRL1_HMIC_M 12127#define SUN8I_HMIC_CTRL1_HMIC_N 8128#define SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB 5129#define SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN 4130#define SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN 3131#define SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN 0132#define SUN8I_HMIC_CTRL2 0x114133#define SUN8I_HMIC_CTRL2_HMIC_SAMPLE 14134#define SUN8I_HMIC_CTRL2_HMIC_MDATA_THRESHOLD 8135#define SUN8I_HMIC_CTRL2_HMIC_SF 6136#define SUN8I_HMIC_STS 0x118137#define SUN8I_HMIC_STS_MDATA_DISCARD 13138#define SUN8I_HMIC_STS_HMIC_DATA 8139#define SUN8I_HMIC_STS_JACK_OUT_IRQ_ST 4140#define SUN8I_HMIC_STS_JACK_IN_IRQ_ST 3141#define SUN8I_HMIC_STS_HMIC_DATA_IRQ_ST 0142#define SUN8I_DAC_DIG_CTRL 0x120143#define SUN8I_DAC_DIG_CTRL_ENDA 15144#define SUN8I_DAC_VOL_CTRL 0x124145#define SUN8I_DAC_VOL_CTRL_DACL_VOL 8146#define SUN8I_DAC_VOL_CTRL_DACR_VOL 0147#define SUN8I_DAC_MXR_SRC 0x130148#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L 15149#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L 14150#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL 13151#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL 12152#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R 11153#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R 10154#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR 9155#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR 8156 157#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK GENMASK(9, 8)158#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK GENMASK(5, 4)159#define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12)160#define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8)161#define SUN8I_AIF_CLK_CTRL_CLK_INV_MASK GENMASK(14, 13)162#define SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK GENMASK(12, 9)163#define SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK GENMASK(8, 6)164#define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK GENMASK(5, 4)165#define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK GENMASK(3, 2)166#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK GENMASK(1, 0)167#define SUN8I_HMIC_CTRL1_HMIC_M_MASK GENMASK(15, 12)168#define SUN8I_HMIC_CTRL1_HMIC_N_MASK GENMASK(11, 8)169#define SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB_MASK GENMASK(6, 5)170#define SUN8I_HMIC_CTRL2_HMIC_SAMPLE_MASK GENMASK(15, 14)171#define SUN8I_HMIC_CTRL2_HMIC_SF_MASK GENMASK(7, 6)172#define SUN8I_HMIC_STS_HMIC_DATA_MASK GENMASK(12, 8)173 174#define SUN8I_CODEC_BUTTONS (SND_JACK_BTN_0|\175 SND_JACK_BTN_1|\176 SND_JACK_BTN_2|\177 SND_JACK_BTN_3)178 179#define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000180 181#define SUN8I_CODEC_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8 |\182 SNDRV_PCM_FMTBIT_S16_LE |\183 SNDRV_PCM_FMTBIT_S20_LE |\184 SNDRV_PCM_FMTBIT_S24_LE |\185 SNDRV_PCM_FMTBIT_S20_3LE|\186 SNDRV_PCM_FMTBIT_S24_3LE)187 188#define SUN8I_CODEC_PCM_RATES (SNDRV_PCM_RATE_8000_48000|\189 SNDRV_PCM_RATE_88200 |\190 SNDRV_PCM_RATE_96000 |\191 SNDRV_PCM_RATE_176400 |\192 SNDRV_PCM_RATE_192000 |\193 SNDRV_PCM_RATE_KNOT)194 195enum {196 SUN8I_CODEC_AIF1,197 SUN8I_CODEC_AIF2,198 SUN8I_CODEC_AIF3,199 SUN8I_CODEC_NAIFS200};201 202struct sun8i_codec_aif {203 unsigned int lrck_div_order;204 unsigned int sample_rate;205 unsigned int slots;206 unsigned int slot_width;207 unsigned int active_streams : 2;208 unsigned int open_streams : 2;209};210 211struct sun8i_codec_quirks {212 bool bus_clock : 1;213 bool jack_detection : 1;214 bool legacy_widgets : 1;215 bool lrck_inversion : 1;216};217 218enum {219 SUN8I_JACK_STATUS_DISCONNECTED,220 SUN8I_JACK_STATUS_WAITING_HBIAS,221 SUN8I_JACK_STATUS_CONNECTED,222};223 224struct sun8i_codec {225 struct snd_soc_component *component;226 struct regmap *regmap;227 struct clk *clk_bus;228 struct clk *clk_module;229 const struct sun8i_codec_quirks *quirks;230 struct sun8i_codec_aif aifs[SUN8I_CODEC_NAIFS];231 struct snd_soc_jack *jack;232 struct delayed_work jack_work;233 int jack_irq;234 int jack_status;235 int jack_type;236 int jack_last_sample;237 ktime_t jack_hbias_ready;238 struct mutex jack_mutex;239 int last_hmic_irq;240 unsigned int sysclk_rate;241 int sysclk_refcnt;242};243 244static struct snd_soc_dai_driver sun8i_codec_dais[];245 246static int sun8i_codec_runtime_resume(struct device *dev)247{248 struct sun8i_codec *scodec = dev_get_drvdata(dev);249 int ret;250 251 if (scodec->clk_bus) {252 ret = clk_prepare_enable(scodec->clk_bus);253 if (ret) {254 dev_err(dev, "Failed to enable the bus clock\n");255 return ret;256 }257 }258 259 regcache_cache_only(scodec->regmap, false);260 261 ret = regcache_sync(scodec->regmap);262 if (ret) {263 dev_err(dev, "Failed to sync regmap cache\n");264 return ret;265 }266 267 return 0;268}269 270static int sun8i_codec_runtime_suspend(struct device *dev)271{272 struct sun8i_codec *scodec = dev_get_drvdata(dev);273 274 regcache_cache_only(scodec->regmap, true);275 regcache_mark_dirty(scodec->regmap);276 277 if (scodec->clk_bus)278 clk_disable_unprepare(scodec->clk_bus);279 280 return 0;281}282 283static int sun8i_codec_get_hw_rate(unsigned int sample_rate)284{285 switch (sample_rate) {286 case 7350:287 case 8000:288 return 0x0;289 case 11025:290 return 0x1;291 case 12000:292 return 0x2;293 case 14700:294 case 16000:295 return 0x3;296 case 22050:297 return 0x4;298 case 24000:299 return 0x5;300 case 29400:301 case 32000:302 return 0x6;303 case 44100:304 return 0x7;305 case 48000:306 return 0x8;307 case 88200:308 case 96000:309 return 0x9;310 case 176400:311 case 192000:312 return 0xa;313 default:314 return -EINVAL;315 }316}317 318static int sun8i_codec_update_sample_rate(struct sun8i_codec *scodec)319{320 unsigned int max_rate = 0;321 int hw_rate, i;322 323 for (i = SUN8I_CODEC_AIF1; i < SUN8I_CODEC_NAIFS; ++i) {324 struct sun8i_codec_aif *aif = &scodec->aifs[i];325 326 if (aif->active_streams)327 max_rate = max(max_rate, aif->sample_rate);328 }329 330 /* Set the sample rate for ADC->DAC passthrough when no AIF is active. */331 if (!max_rate)332 max_rate = SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE;333 334 hw_rate = sun8i_codec_get_hw_rate(max_rate);335 if (hw_rate < 0)336 return hw_rate;337 338 regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,339 SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,340 hw_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);341 342 return 0;343}344 345static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)346{347 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);348 u32 dsp_format, format, invert, value;349 350 /* clock masters */351 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {352 case SND_SOC_DAIFMT_CBC_CFC: /* Codec slave, DAI master */353 value = 0x1;354 break;355 case SND_SOC_DAIFMT_CBP_CFP: /* Codec Master, DAI slave */356 value = 0x0;357 break;358 default:359 return -EINVAL;360 }361 362 if (dai->id == SUN8I_CODEC_AIF3) {363 /* AIF3 only supports master mode. */364 if (value)365 return -EINVAL;366 367 /* Use the AIF2 BCLK and LRCK for AIF3. */368 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),369 SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK,370 SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2);371 } else {372 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),373 BIT(SUN8I_AIF_CLK_CTRL_MSTR_MOD),374 value << SUN8I_AIF_CLK_CTRL_MSTR_MOD);375 }376 377 /* DAI format */378 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {379 case SND_SOC_DAIFMT_I2S:380 format = 0x0;381 break;382 case SND_SOC_DAIFMT_LEFT_J:383 format = 0x1;384 break;385 case SND_SOC_DAIFMT_RIGHT_J:386 format = 0x2;387 break;388 case SND_SOC_DAIFMT_DSP_A:389 format = 0x3;390 dsp_format = 0x0; /* Set LRCK_INV to 0 */391 break;392 case SND_SOC_DAIFMT_DSP_B:393 format = 0x3;394 dsp_format = 0x1; /* Set LRCK_INV to 1 */395 break;396 default:397 return -EINVAL;398 }399 400 if (dai->id == SUN8I_CODEC_AIF3) {401 /* AIF3 only supports DSP mode. */402 if (format != 3)403 return -EINVAL;404 } else {405 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),406 SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK,407 format << SUN8I_AIF_CLK_CTRL_DATA_FMT);408 }409 410 /* clock inversion */411 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {412 case SND_SOC_DAIFMT_NB_NF: /* Normal */413 invert = 0x0;414 break;415 case SND_SOC_DAIFMT_NB_IF: /* Inverted LRCK */416 invert = 0x1;417 break;418 case SND_SOC_DAIFMT_IB_NF: /* Inverted BCLK */419 invert = 0x2;420 break;421 case SND_SOC_DAIFMT_IB_IF: /* Both inverted */422 invert = 0x3;423 break;424 default:425 return -EINVAL;426 }427 428 if (format == 0x3) {429 /* Inverted LRCK is not available in DSP mode. */430 if (invert & BIT(0))431 return -EINVAL;432 433 /* Instead, the bit selects between DSP A/B formats. */434 invert |= dsp_format;435 } else {436 /*437 * It appears that the DAI and the codec in the A33 SoC don't438 * share the same polarity for the LRCK signal when they mean439 * 'normal' and 'inverted' in the datasheet.440 *441 * Since the DAI here is our regular i2s driver that have been442 * tested with way more codecs than just this one, it means443 * that the codec probably gets it backward, and we have to444 * invert the value here.445 */446 invert ^= scodec->quirks->lrck_inversion;447 }448 449 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),450 SUN8I_AIF_CLK_CTRL_CLK_INV_MASK,451 invert << SUN8I_AIF_CLK_CTRL_CLK_INV);452 453 return 0;454}455 456static int sun8i_codec_set_tdm_slot(struct snd_soc_dai *dai,457 unsigned int tx_mask, unsigned int rx_mask,458 int slots, int slot_width)459{460 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);461 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];462 463 if (slot_width && !is_power_of_2(slot_width))464 return -EINVAL;465 466 aif->slots = slots;467 aif->slot_width = slot_width;468 469 return 0;470}471 472static const unsigned int sun8i_codec_rates[] = {473 7350, 8000, 11025, 12000, 14700, 16000, 22050, 24000,474 29400, 32000, 44100, 48000, 88200, 96000, 176400, 192000,475};476 477static const struct snd_pcm_hw_constraint_list sun8i_codec_all_rates = {478 .list = sun8i_codec_rates,479 .count = ARRAY_SIZE(sun8i_codec_rates),480};481 482static const struct snd_pcm_hw_constraint_list sun8i_codec_22M_rates = {483 .list = sun8i_codec_rates,484 .count = ARRAY_SIZE(sun8i_codec_rates),485 .mask = 0x5555,486};487 488static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates = {489 .list = sun8i_codec_rates,490 .count = ARRAY_SIZE(sun8i_codec_rates),491 .mask = 0xaaaa,492};493 494static int sun8i_codec_startup(struct snd_pcm_substream *substream,495 struct snd_soc_dai *dai)496{497 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);498 const struct snd_pcm_hw_constraint_list *list;499 500 /* hw_constraints is not relevant for codec2codec DAIs. */501 if (dai->id != SUN8I_CODEC_AIF1)502 return 0;503 504 if (!scodec->sysclk_refcnt)505 list = &sun8i_codec_all_rates;506 else if (scodec->sysclk_rate == 22579200)507 list = &sun8i_codec_22M_rates;508 else if (scodec->sysclk_rate == 24576000)509 list = &sun8i_codec_24M_rates;510 else511 return -EINVAL;512 513 return snd_pcm_hw_constraint_list(substream->runtime, 0,514 SNDRV_PCM_HW_PARAM_RATE, list);515}516 517struct sun8i_codec_clk_div {518 u8 div;519 u8 val;520};521 522static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = {523 { .div = 1, .val = 0 },524 { .div = 2, .val = 1 },525 { .div = 4, .val = 2 },526 { .div = 6, .val = 3 },527 { .div = 8, .val = 4 },528 { .div = 12, .val = 5 },529 { .div = 16, .val = 6 },530 { .div = 24, .val = 7 },531 { .div = 32, .val = 8 },532 { .div = 48, .val = 9 },533 { .div = 64, .val = 10 },534 { .div = 96, .val = 11 },535 { .div = 128, .val = 12 },536 { .div = 192, .val = 13 },537};538 539static int sun8i_codec_get_bclk_div(unsigned int sysclk_rate,540 unsigned int lrck_div_order,541 unsigned int sample_rate)542{543 unsigned int div = sysclk_rate / sample_rate >> lrck_div_order;544 int i;545 546 for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) {547 const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i];548 549 if (bdiv->div == div)550 return bdiv->val;551 }552 553 return -EINVAL;554}555 556static int sun8i_codec_get_lrck_div_order(unsigned int slots,557 unsigned int slot_width)558{559 unsigned int div = slots * slot_width;560 561 if (div < 16 || div > 256)562 return -EINVAL;563 564 return order_base_2(div);565}566 567static unsigned int sun8i_codec_get_sysclk_rate(unsigned int sample_rate)568{569 return (sample_rate % 4000) ? 22579200 : 24576000;570}571 572static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,573 struct snd_pcm_hw_params *params,574 struct snd_soc_dai *dai)575{576 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);577 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];578 unsigned int sample_rate = params_rate(params);579 unsigned int slots = aif->slots ?: params_channels(params);580 unsigned int slot_width = aif->slot_width ?: params_width(params);581 unsigned int sysclk_rate = sun8i_codec_get_sysclk_rate(sample_rate);582 int bclk_div, lrck_div_order, ret, word_size;583 u32 clk_reg;584 585 /* word size */586 switch (params_width(params)) {587 case 8:588 word_size = 0x0;589 break;590 case 16:591 word_size = 0x1;592 break;593 case 20:594 word_size = 0x2;595 break;596 case 24:597 word_size = 0x3;598 break;599 default:600 return -EINVAL;601 }602 603 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),604 SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK,605 word_size << SUN8I_AIF_CLK_CTRL_WORD_SIZ);606 607 /* LRCK divider (BCLK/LRCK ratio) */608 lrck_div_order = sun8i_codec_get_lrck_div_order(slots, slot_width);609 if (lrck_div_order < 0)610 return lrck_div_order;611 612 if (dai->id == SUN8I_CODEC_AIF2 || dai->id == SUN8I_CODEC_AIF3) {613 /* AIF2 and AIF3 share AIF2's BCLK and LRCK generation circuitry. */614 int partner = (SUN8I_CODEC_AIF2 + SUN8I_CODEC_AIF3) - dai->id;615 const struct sun8i_codec_aif *partner_aif = &scodec->aifs[partner];616 const char *partner_name = sun8i_codec_dais[partner].name;617 618 if (partner_aif->open_streams &&619 (lrck_div_order != partner_aif->lrck_div_order ||620 sample_rate != partner_aif->sample_rate)) {621 dev_err(dai->dev,622 "%s sample and bit rates must match %s when both are used\n",623 dai->name, partner_name);624 return -EBUSY;625 }626 627 clk_reg = SUN8I_AIF_CLK_CTRL(SUN8I_CODEC_AIF2);628 } else {629 clk_reg = SUN8I_AIF_CLK_CTRL(dai->id);630 }631 632 regmap_update_bits(scodec->regmap, clk_reg,633 SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK,634 (lrck_div_order - 4) << SUN8I_AIF_CLK_CTRL_LRCK_DIV);635 636 /* BCLK divider (SYSCLK/BCLK ratio) */637 bclk_div = sun8i_codec_get_bclk_div(sysclk_rate, lrck_div_order, sample_rate);638 if (bclk_div < 0)639 return bclk_div;640 641 regmap_update_bits(scodec->regmap, clk_reg,642 SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK,643 bclk_div << SUN8I_AIF_CLK_CTRL_BCLK_DIV);644 645 /*646 * SYSCLK rate647 *648 * Clock rate protection is reference counted; but hw_params may be649 * called many times per substream, without matching calls to hw_free.650 * Protect the clock rate once per AIF, on the first hw_params call651 * for the first substream. clk_set_rate() will allow clock rate652 * changes on subsequent calls if only one AIF has open streams.653 */654 ret = (aif->open_streams ? clk_set_rate : clk_set_rate_exclusive)(scodec->clk_module,655 sysclk_rate);656 if (ret == -EBUSY)657 dev_err(dai->dev,658 "%s sample rate (%u Hz) conflicts with other audio streams\n",659 dai->name, sample_rate);660 if (ret < 0)661 return ret;662 663 if (!aif->open_streams)664 scodec->sysclk_refcnt++;665 scodec->sysclk_rate = sysclk_rate;666 667 aif->lrck_div_order = lrck_div_order;668 aif->sample_rate = sample_rate;669 aif->open_streams |= BIT(substream->stream);670 671 return sun8i_codec_update_sample_rate(scodec);672}673 674static int sun8i_codec_hw_free(struct snd_pcm_substream *substream,675 struct snd_soc_dai *dai)676{677 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);678 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];679 680 /* Drop references when the last substream for the AIF is freed. */681 if (aif->open_streams != BIT(substream->stream))682 goto done;683 684 clk_rate_exclusive_put(scodec->clk_module);685 scodec->sysclk_refcnt--;686 aif->lrck_div_order = 0;687 aif->sample_rate = 0;688 689done:690 aif->open_streams &= ~BIT(substream->stream);691 return 0;692}693 694static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {695 .set_fmt = sun8i_codec_set_fmt,696 .set_tdm_slot = sun8i_codec_set_tdm_slot,697 .startup = sun8i_codec_startup,698 .hw_params = sun8i_codec_hw_params,699 .hw_free = sun8i_codec_hw_free,700};701 702static struct snd_soc_dai_driver sun8i_codec_dais[] = {703 {704 .name = "sun8i-codec-aif1",705 .id = SUN8I_CODEC_AIF1,706 .ops = &sun8i_codec_dai_ops,707 /* capture capabilities */708 .capture = {709 .stream_name = "AIF1 Capture",710 .channels_min = 1,711 .channels_max = 2,712 .rates = SUN8I_CODEC_PCM_RATES,713 .formats = SUN8I_CODEC_PCM_FORMATS,714 .sig_bits = 24,715 },716 /* playback capabilities */717 .playback = {718 .stream_name = "AIF1 Playback",719 .channels_min = 1,720 .channels_max = 2,721 .rates = SUN8I_CODEC_PCM_RATES,722 .formats = SUN8I_CODEC_PCM_FORMATS,723 },724 .symmetric_rate = true,725 .symmetric_channels = true,726 .symmetric_sample_bits = true,727 },728 {729 .name = "sun8i-codec-aif2",730 .id = SUN8I_CODEC_AIF2,731 .ops = &sun8i_codec_dai_ops,732 /* capture capabilities */733 .capture = {734 .stream_name = "AIF2 Capture",735 .channels_min = 1,736 .channels_max = 2,737 .rates = SUN8I_CODEC_PCM_RATES,738 .formats = SUN8I_CODEC_PCM_FORMATS,739 .sig_bits = 24,740 },741 /* playback capabilities */742 .playback = {743 .stream_name = "AIF2 Playback",744 .channels_min = 1,745 .channels_max = 2,746 .rates = SUN8I_CODEC_PCM_RATES,747 .formats = SUN8I_CODEC_PCM_FORMATS,748 },749 .symmetric_rate = true,750 .symmetric_channels = true,751 .symmetric_sample_bits = true,752 },753 {754 .name = "sun8i-codec-aif3",755 .id = SUN8I_CODEC_AIF3,756 .ops = &sun8i_codec_dai_ops,757 /* capture capabilities */758 .capture = {759 .stream_name = "AIF3 Capture",760 .channels_min = 1,761 .channels_max = 1,762 .rates = SUN8I_CODEC_PCM_RATES,763 .formats = SUN8I_CODEC_PCM_FORMATS,764 .sig_bits = 24,765 },766 /* playback capabilities */767 .playback = {768 .stream_name = "AIF3 Playback",769 .channels_min = 1,770 .channels_max = 1,771 .rates = SUN8I_CODEC_PCM_RATES,772 .formats = SUN8I_CODEC_PCM_FORMATS,773 },774 .symmetric_rate = true,775 .symmetric_channels = true,776 .symmetric_sample_bits = true,777 },778};779 780static const DECLARE_TLV_DB_SCALE(sun8i_codec_vol_scale, -12000, 75, 1);781 782static const struct snd_kcontrol_new sun8i_codec_controls[] = {783 SOC_DOUBLE_TLV("AIF1 AD0 Capture Volume",784 SUN8I_AIF1_VOL_CTRL1,785 SUN8I_AIF1_VOL_CTRL1_AD0L_VOL,786 SUN8I_AIF1_VOL_CTRL1_AD0R_VOL,787 0xc0, 0, sun8i_codec_vol_scale),788 SOC_DOUBLE_TLV("AIF1 DA0 Playback Volume",789 SUN8I_AIF1_VOL_CTRL3,790 SUN8I_AIF1_VOL_CTRL3_DA0L_VOL,791 SUN8I_AIF1_VOL_CTRL3_DA0R_VOL,792 0xc0, 0, sun8i_codec_vol_scale),793 SOC_DOUBLE_TLV("AIF2 ADC Capture Volume",794 SUN8I_AIF2_VOL_CTRL1,795 SUN8I_AIF2_VOL_CTRL1_ADCL_VOL,796 SUN8I_AIF2_VOL_CTRL1_ADCR_VOL,797 0xc0, 0, sun8i_codec_vol_scale),798 SOC_DOUBLE_TLV("AIF2 DAC Playback Volume",799 SUN8I_AIF2_VOL_CTRL2,800 SUN8I_AIF2_VOL_CTRL2_DACL_VOL,801 SUN8I_AIF2_VOL_CTRL2_DACR_VOL,802 0xc0, 0, sun8i_codec_vol_scale),803 SOC_DOUBLE_TLV("ADC Capture Volume",804 SUN8I_ADC_VOL_CTRL,805 SUN8I_ADC_VOL_CTRL_ADCL_VOL,806 SUN8I_ADC_VOL_CTRL_ADCR_VOL,807 0xc0, 0, sun8i_codec_vol_scale),808 SOC_DOUBLE_TLV("DAC Playback Volume",809 SUN8I_DAC_VOL_CTRL,810 SUN8I_DAC_VOL_CTRL_DACL_VOL,811 SUN8I_DAC_VOL_CTRL_DACR_VOL,812 0xc0, 0, sun8i_codec_vol_scale),813};814 815static int sun8i_codec_aif_event(struct snd_soc_dapm_widget *w,816 struct snd_kcontrol *kcontrol, int event)817{818 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);819 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component);820 struct sun8i_codec_aif *aif = &scodec->aifs[w->sname[3] - '1'];821 int stream = w->id == snd_soc_dapm_aif_out;822 823 if (SND_SOC_DAPM_EVENT_ON(event))824 aif->active_streams |= BIT(stream);825 else826 aif->active_streams &= ~BIT(stream);827 828 return sun8i_codec_update_sample_rate(scodec);829}830 831static const char *const sun8i_aif_stereo_mux_enum_values[] = {832 "Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono"833};834 835static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum,836 SUN8I_AIF1_ADCDAT_CTRL,837 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC,838 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC,839 sun8i_aif_stereo_mux_enum_values);840 841static const struct snd_kcontrol_new sun8i_aif1_ad0_stereo_mux_control =842 SOC_DAPM_ENUM("AIF1 AD0 Stereo Capture Route",843 sun8i_aif1_ad0_stereo_mux_enum);844 845static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_adc_stereo_mux_enum,846 SUN8I_AIF2_ADCDAT_CTRL,847 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC,848 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC,849 sun8i_aif_stereo_mux_enum_values);850 851static const struct snd_kcontrol_new sun8i_aif2_adc_stereo_mux_control =852 SOC_DAPM_ENUM("AIF2 ADC Stereo Capture Route",853 sun8i_aif2_adc_stereo_mux_enum);854 855static const char *const sun8i_aif3_adc_mux_enum_values[] = {856 "None", "AIF2 ADCL", "AIF2 ADCR"857};858 859static SOC_ENUM_SINGLE_DECL(sun8i_aif3_adc_mux_enum,860 SUN8I_AIF3_PATH_CTRL,861 SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC,862 sun8i_aif3_adc_mux_enum_values);863 864static const struct snd_kcontrol_new sun8i_aif3_adc_mux_control =865 SOC_DAPM_ENUM("AIF3 ADC Source Capture Route",866 sun8i_aif3_adc_mux_enum);867 868static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls[] = {869 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",870 SUN8I_AIF1_MXR_SRC,871 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L,872 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0),873 SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch",874 SUN8I_AIF1_MXR_SRC,875 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL,876 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0),877 SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch",878 SUN8I_AIF1_MXR_SRC,879 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL,880 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0),881 SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",882 SUN8I_AIF1_MXR_SRC,883 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR,884 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0),885};886 887static const struct snd_kcontrol_new sun8i_aif2_adc_mixer_controls[] = {888 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA0 Capture Switch",889 SUN8I_AIF2_MXR_SRC,890 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L,891 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R, 1, 0),892 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA1 Capture Switch",893 SUN8I_AIF2_MXR_SRC,894 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L,895 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R, 1, 0),896 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF2 DAC Rev Capture Switch",897 SUN8I_AIF2_MXR_SRC,898 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR,899 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL, 1, 0),900 SOC_DAPM_DOUBLE("AIF2 ADC Mixer ADC Capture Switch",901 SUN8I_AIF2_MXR_SRC,902 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL,903 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR, 1, 0),904};905 906static const char *const sun8i_aif2_dac_mux_enum_values[] = {907 "AIF2", "AIF3+2", "AIF2+3"908};909 910static SOC_ENUM_SINGLE_DECL(sun8i_aif2_dac_mux_enum,911 SUN8I_AIF3_PATH_CTRL,912 SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC,913 sun8i_aif2_dac_mux_enum_values);914 915static const struct snd_kcontrol_new sun8i_aif2_dac_mux_control =916 SOC_DAPM_ENUM("AIF2 DAC Source Playback Route",917 sun8i_aif2_dac_mux_enum);918 919static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_da0_stereo_mux_enum,920 SUN8I_AIF1_DACDAT_CTRL,921 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC,922 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC,923 sun8i_aif_stereo_mux_enum_values);924 925static const struct snd_kcontrol_new sun8i_aif1_da0_stereo_mux_control =926 SOC_DAPM_ENUM("AIF1 DA0 Stereo Playback Route",927 sun8i_aif1_da0_stereo_mux_enum);928 929static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_dac_stereo_mux_enum,930 SUN8I_AIF2_DACDAT_CTRL,931 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC,932 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC,933 sun8i_aif_stereo_mux_enum_values);934 935static const struct snd_kcontrol_new sun8i_aif2_dac_stereo_mux_control =936 SOC_DAPM_ENUM("AIF2 DAC Stereo Playback Route",937 sun8i_aif2_dac_stereo_mux_enum);938 939static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = {940 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch",941 SUN8I_DAC_MXR_SRC,942 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L,943 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0),944 SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch",945 SUN8I_DAC_MXR_SRC,946 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L,947 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R, 1, 0),948 SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,949 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL,950 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0),951 SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,952 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL,953 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0),954};955 956static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {957 /* System Clocks */958 SND_SOC_DAPM_CLOCK_SUPPLY("mod"),959 960 SND_SOC_DAPM_SUPPLY("AIF1CLK",961 SUN8I_SYSCLK_CTL,962 SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0),963 SND_SOC_DAPM_SUPPLY("AIF2CLK",964 SUN8I_SYSCLK_CTL,965 SUN8I_SYSCLK_CTL_AIF2CLK_ENA, 0, NULL, 0),966 SND_SOC_DAPM_SUPPLY("SYSCLK",967 SUN8I_SYSCLK_CTL,968 SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0),969 970 /* Module Clocks */971 SND_SOC_DAPM_SUPPLY("CLK AIF1",972 SUN8I_MOD_CLK_ENA,973 SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0),974 SND_SOC_DAPM_SUPPLY("CLK AIF2",975 SUN8I_MOD_CLK_ENA,976 SUN8I_MOD_CLK_ENA_AIF2, 0, NULL, 0),977 SND_SOC_DAPM_SUPPLY("CLK AIF3",978 SUN8I_MOD_CLK_ENA,979 SUN8I_MOD_CLK_ENA_AIF3, 0, NULL, 0),980 SND_SOC_DAPM_SUPPLY("CLK ADC",981 SUN8I_MOD_CLK_ENA,982 SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0),983 SND_SOC_DAPM_SUPPLY("CLK DAC",984 SUN8I_MOD_CLK_ENA,985 SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0),986 987 /* Module Resets */988 SND_SOC_DAPM_SUPPLY("RST AIF1",989 SUN8I_MOD_RST_CTL,990 SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0),991 SND_SOC_DAPM_SUPPLY("RST AIF2",992 SUN8I_MOD_RST_CTL,993 SUN8I_MOD_RST_CTL_AIF2, 0, NULL, 0),994 SND_SOC_DAPM_SUPPLY("RST AIF3",995 SUN8I_MOD_RST_CTL,996 SUN8I_MOD_RST_CTL_AIF3, 0, NULL, 0),997 SND_SOC_DAPM_SUPPLY("RST ADC",998 SUN8I_MOD_RST_CTL,999 SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0),1000 SND_SOC_DAPM_SUPPLY("RST DAC",1001 SUN8I_MOD_RST_CTL,1002 SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0),1003 1004 /* Module Supplies */1005 SND_SOC_DAPM_SUPPLY("ADC",1006 SUN8I_ADC_DIG_CTRL,1007 SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0),1008 SND_SOC_DAPM_SUPPLY("DAC",1009 SUN8I_DAC_DIG_CTRL,1010 SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0),1011 1012 /* AIF "ADC" Outputs */1013 SND_SOC_DAPM_AIF_OUT_E("AIF1 AD0L", "AIF1 Capture", 0,1014 SUN8I_AIF1_ADCDAT_CTRL,1015 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0,1016 sun8i_codec_aif_event,1017 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),1018 SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "AIF1 Capture", 1,1019 SUN8I_AIF1_ADCDAT_CTRL,1020 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0),1021 1022 SND_SOC_DAPM_AIF_OUT_E("AIF2 ADCL", "AIF2 Capture", 0,1023 SUN8I_AIF2_ADCDAT_CTRL,1024 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA, 0,1025 sun8i_codec_aif_event,1026 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),1027 SND_SOC_DAPM_AIF_OUT("AIF2 ADCR", "AIF2 Capture", 1,1028 SUN8I_AIF2_ADCDAT_CTRL,1029 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA, 0),1030 1031 SND_SOC_DAPM_AIF_OUT_E("AIF3 ADC", "AIF3 Capture", 0,1032 SND_SOC_NOPM, 0, 0,1033 sun8i_codec_aif_event,1034 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),1035 1036 /* AIF "ADC" Mono/Stereo Muxes */1037 SND_SOC_DAPM_MUX("AIF1 AD0L Stereo Mux", SND_SOC_NOPM, 0, 0,1038 &sun8i_aif1_ad0_stereo_mux_control),1039 SND_SOC_DAPM_MUX("AIF1 AD0R Stereo Mux", SND_SOC_NOPM, 0, 0,1040 &sun8i_aif1_ad0_stereo_mux_control),1041 1042 SND_SOC_DAPM_MUX("AIF2 ADCL Stereo Mux", SND_SOC_NOPM, 0, 0,1043 &sun8i_aif2_adc_stereo_mux_control),1044 SND_SOC_DAPM_MUX("AIF2 ADCR Stereo Mux", SND_SOC_NOPM, 0, 0,1045 &sun8i_aif2_adc_stereo_mux_control),1046 1047 /* AIF "ADC" Output Muxes */1048 SND_SOC_DAPM_MUX("AIF3 ADC Source Capture Route", SND_SOC_NOPM, 0, 0,1049 &sun8i_aif3_adc_mux_control),1050 1051 /* AIF "ADC" Mixers */1052 SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM, 0, 0,1053 sun8i_aif1_ad0_mixer_controls),1054 SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM, 0, 0,1055 sun8i_aif1_ad0_mixer_controls),1056 1057 SOC_MIXER_ARRAY("AIF2 ADCL Mixer", SND_SOC_NOPM, 0, 0,1058 sun8i_aif2_adc_mixer_controls),1059 SOC_MIXER_ARRAY("AIF2 ADCR Mixer", SND_SOC_NOPM, 0, 0,1060 sun8i_aif2_adc_mixer_controls),1061 1062 /* AIF "DAC" Input Muxes */1063 SND_SOC_DAPM_MUX("AIF2 DACL Source", SND_SOC_NOPM, 0, 0,1064 &sun8i_aif2_dac_mux_control),1065 SND_SOC_DAPM_MUX("AIF2 DACR Source", SND_SOC_NOPM, 0, 0,1066 &sun8i_aif2_dac_mux_control),1067 1068 /* AIF "DAC" Mono/Stereo Muxes */1069 SND_SOC_DAPM_MUX("AIF1 DA0L Stereo Mux", SND_SOC_NOPM, 0, 0,1070 &sun8i_aif1_da0_stereo_mux_control),1071 SND_SOC_DAPM_MUX("AIF1 DA0R Stereo Mux", SND_SOC_NOPM, 0, 0,1072 &sun8i_aif1_da0_stereo_mux_control),1073 1074 SND_SOC_DAPM_MUX("AIF2 DACL Stereo Mux", SND_SOC_NOPM, 0, 0,1075 &sun8i_aif2_dac_stereo_mux_control),1076 SND_SOC_DAPM_MUX("AIF2 DACR Stereo Mux", SND_SOC_NOPM, 0, 0,1077 &sun8i_aif2_dac_stereo_mux_control),1078 1079 /* AIF "DAC" Inputs */1080 SND_SOC_DAPM_AIF_IN_E("AIF1 DA0L", "AIF1 Playback", 0,1081 SUN8I_AIF1_DACDAT_CTRL,1082 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0,1083 sun8i_codec_aif_event,1084 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),1085 SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "AIF1 Playback", 1,1086 SUN8I_AIF1_DACDAT_CTRL,1087 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0),1088 1089 SND_SOC_DAPM_AIF_IN_E("AIF2 DACL", "AIF2 Playback", 0,1090 SUN8I_AIF2_DACDAT_CTRL,1091 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA, 0,1092 sun8i_codec_aif_event,1093 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),1094 SND_SOC_DAPM_AIF_IN("AIF2 DACR", "AIF2 Playback", 1,1095 SUN8I_AIF2_DACDAT_CTRL,1096 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA, 0),1097 1098 SND_SOC_DAPM_AIF_IN_E("AIF3 DAC", "AIF3 Playback", 0,1099 SND_SOC_NOPM, 0, 0,1100 sun8i_codec_aif_event,1101 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),1102 1103 /* ADC Inputs (connected to analog codec DAPM context) */1104 SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 0, 0),1105 SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),1106 1107 /* DAC Outputs (connected to analog codec DAPM context) */1108 SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),1109 SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),1110 1111 /* DAC Mixers */1112 SOC_MIXER_ARRAY("DACL Mixer", SND_SOC_NOPM, 0, 0,1113 sun8i_dac_mixer_controls),1114 SOC_MIXER_ARRAY("DACR Mixer", SND_SOC_NOPM, 0, 0,1115 sun8i_dac_mixer_controls),1116};1117 1118static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {1119 /* Clock Routes */1120 { "AIF1CLK", NULL, "mod" },1121 1122 { "SYSCLK", NULL, "AIF1CLK" },1123 1124 { "CLK AIF1", NULL, "AIF1CLK" },1125 { "CLK AIF1", NULL, "SYSCLK" },1126 { "RST AIF1", NULL, "CLK AIF1" },1127 { "AIF1 AD0L", NULL, "RST AIF1" },1128 { "AIF1 AD0R", NULL, "RST AIF1" },1129 { "AIF1 DA0L", NULL, "RST AIF1" },1130 { "AIF1 DA0R", NULL, "RST AIF1" },1131 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" },1139 1140 { "CLK AIF3", NULL, "AIF1CLK" },1141 { "CLK AIF3", NULL, "SYSCLK" },1142 { "RST AIF3", NULL, "CLK AIF3" },1143 { "AIF3 ADC", NULL, "RST AIF3" },1144 { "AIF3 DAC", NULL, "RST AIF3" },1145 1146 { "CLK ADC", NULL, "SYSCLK" },1147 { "RST ADC", NULL, "CLK ADC" },1148 { "ADC", NULL, "RST ADC" },1149 { "ADCL", NULL, "ADC" },1150 { "ADCR", NULL, "ADC" },1151 1152 { "CLK DAC", NULL, "SYSCLK" },1153 { "RST DAC", NULL, "CLK DAC" },1154 { "DAC", NULL, "RST DAC" },1155 { "DACL", NULL, "DAC" },1156 { "DACR", NULL, "DAC" },1157 1158 /* AIF "ADC" Output Routes */1159 { "AIF1 AD0L", NULL, "AIF1 AD0L Stereo Mux" },1160 { "AIF1 AD0R", NULL, "AIF1 AD0R Stereo Mux" },1161 1162 { "AIF2 ADCL", NULL, "AIF2 ADCL Stereo Mux" },1163 { "AIF2 ADCR", NULL, "AIF2 ADCR Stereo Mux" },1164 1165 { "AIF3 ADC", NULL, "AIF3 ADC Source Capture Route" },1166 1167 /* AIF "ADC" Mono/Stereo Mux Routes */1168 { "AIF1 AD0L Stereo Mux", "Stereo", "AIF1 AD0L Mixer" },1169 { "AIF1 AD0L Stereo Mux", "Reverse Stereo", "AIF1 AD0R Mixer" },1170 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" },1171 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" },1172 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" },1173 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" },1174 1175 { "AIF1 AD0R Stereo Mux", "Stereo", "AIF1 AD0R Mixer" },1176 { "AIF1 AD0R Stereo Mux", "Reverse Stereo", "AIF1 AD0L Mixer" },1177 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" },1178 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" },1179 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" },1180 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" },1181 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" },1188 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" },1195 1196 /* AIF "ADC" Output Mux Routes */1197 { "AIF3 ADC Source Capture Route", "AIF2 ADCL", "AIF2 ADCL Mixer" },1198 { "AIF3 ADC Source Capture Route", "AIF2 ADCR", "AIF2 ADCR Mixer" },1199 1200 /* AIF "ADC" Mixer Routes */1201 { "AIF1 AD0L Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0L Stereo Mux" },1202 { "AIF1 AD0L Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACL Source" },1203 { "AIF1 AD0L Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCL" },1204 { "AIF1 AD0L Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACR Source" },1205 1206 { "AIF1 AD0R Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0R Stereo Mux" },1207 { "AIF1 AD0R Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACR Source" },1208 { "AIF1 AD0R Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCR" },1209 { "AIF1 AD0R Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACL Source" },1210 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" },1214 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" },1218 1219 /* AIF "DAC" Input Mux Routes */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" },1223 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" },1227 1228 /* AIF "DAC" Mono/Stereo Mux Routes */1229 { "AIF1 DA0L Stereo Mux", "Stereo", "AIF1 DA0L" },1230 { "AIF1 DA0L Stereo Mux", "Reverse Stereo", "AIF1 DA0R" },1231 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0L" },1232 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0R" },1233 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0L" },1234 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0R" },1235 1236 { "AIF1 DA0R Stereo Mux", "Stereo", "AIF1 DA0R" },1237 { "AIF1 DA0R Stereo Mux", "Reverse Stereo", "AIF1 DA0L" },1238 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0L" },1239 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0R" },1240 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0L" },1241 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0R" },1242 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" },1249 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" },1256 1257 /* DAC Output Routes */1258 { "DACL", NULL, "DACL Mixer" },1259 { "DACR", NULL, "DACR Mixer" },1260 1261 /* DAC Mixer Routes */1262 { "DACL Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0L Stereo Mux" },1263 { "DACL Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACL Source" },1264 { "DACL Mixer", "ADC Digital DAC Playback Switch", "ADCL" },1265 1266 { "DACR Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0R Stereo Mux" },1267 { "DACR Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACR Source" },1268 { "DACR Mixer", "ADC Digital DAC Playback Switch", "ADCR" },1269};1270 1271static const struct snd_soc_dapm_widget sun8i_codec_legacy_widgets[] = {1272 /* Legacy ADC Inputs (connected to analog codec DAPM context) */1273 SND_SOC_DAPM_ADC("AIF1 Slot 0 Left ADC", NULL, SND_SOC_NOPM, 0, 0),1274 SND_SOC_DAPM_ADC("AIF1 Slot 0 Right ADC", NULL, SND_SOC_NOPM, 0, 0),1275 1276 /* Legacy DAC Outputs (connected to analog codec DAPM context) */1277 SND_SOC_DAPM_DAC("AIF1 Slot 0 Left", NULL, SND_SOC_NOPM, 0, 0),1278 SND_SOC_DAPM_DAC("AIF1 Slot 0 Right", NULL, SND_SOC_NOPM, 0, 0),1279};1280 1281static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = {1282 /* Legacy ADC Routes */1283 { "ADCL", NULL, "AIF1 Slot 0 Left ADC" },1284 { "ADCR", NULL, "AIF1 Slot 0 Right ADC" },1285 1286 /* Legacy DAC Routes */1287 { "AIF1 Slot 0 Left", NULL, "DACL" },1288 { "AIF1 Slot 0 Right", NULL, "DACR" },1289};1290 1291static int sun8i_codec_component_probe(struct snd_soc_component *component)1292{1293 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);1294 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component);1295 int ret;1296 1297 scodec->component = component;1298 1299 /* Add widgets for backward compatibility with old device trees. */1300 if (scodec->quirks->legacy_widgets) {1301 ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_legacy_widgets,1302 ARRAY_SIZE(sun8i_codec_legacy_widgets));1303 if (ret)1304 return ret;1305 1306 ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_legacy_routes,1307 ARRAY_SIZE(sun8i_codec_legacy_routes));1308 if (ret)1309 return ret;1310 }1311 1312 /*1313 * AIF1CLK and AIF2CLK share a pair of clock parents: PLL_AUDIO ("mod")1314 * and MCLK (from the CPU DAI connected to AIF1). MCLK's parent is also1315 * PLL_AUDIO, so using it adds no additional flexibility. Use PLL_AUDIO1316 * directly to simplify the clock tree.1317 */1318 regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL,1319 SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK |1320 SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK,1321 SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL |1322 SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL);1323 1324 /* Use AIF1CLK as the SYSCLK parent since AIF1 is used most often. */1325 regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL,1326 BIT(SUN8I_SYSCLK_CTL_SYSCLK_SRC),1327 SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK);1328 1329 /* Program the default sample rate. */1330 sun8i_codec_update_sample_rate(scodec);1331 1332 return 0;1333}1334 1335static void sun8i_codec_set_hmic_bias(struct sun8i_codec *scodec, bool enable)1336{1337 struct snd_soc_dapm_context *dapm = &scodec->component->card->dapm;1338 int irq_mask = BIT(SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN);1339 1340 if (enable)1341 snd_soc_dapm_force_enable_pin(dapm, "HBIAS");1342 else1343 snd_soc_dapm_disable_pin(dapm, "HBIAS");1344 1345 snd_soc_dapm_sync(dapm);1346 1347 regmap_update_bits(scodec->regmap, SUN8I_HMIC_CTRL1,1348 irq_mask, enable ? irq_mask : 0);1349}1350 1351static void sun8i_codec_jack_work(struct work_struct *work)1352{1353 struct sun8i_codec *scodec = container_of(work, struct sun8i_codec,1354 jack_work.work);1355 unsigned int mdata;1356 int type;1357 1358 guard(mutex)(&scodec->jack_mutex);1359 1360 if (scodec->jack_status == SUN8I_JACK_STATUS_DISCONNECTED) {1361 if (scodec->last_hmic_irq != SUN8I_HMIC_STS_JACK_IN_IRQ_ST)1362 return;1363 1364 scodec->jack_last_sample = -1;1365 1366 if (scodec->jack_type & SND_JACK_MICROPHONE) {1367 /*1368 * If we were in disconnected state, we enable HBIAS and1369 * wait 600ms before reading initial HDATA value.1370 */1371 scodec->jack_hbias_ready = ktime_add_ms(ktime_get(), 600);1372 sun8i_codec_set_hmic_bias(scodec, true);1373 queue_delayed_work(system_power_efficient_wq,1374 &scodec->jack_work,1375 msecs_to_jiffies(610));1376 scodec->jack_status = SUN8I_JACK_STATUS_WAITING_HBIAS;1377 } else {1378 snd_soc_jack_report(scodec->jack, SND_JACK_HEADPHONE,1379 scodec->jack_type);1380 scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED;1381 }1382 } else if (scodec->jack_status == SUN8I_JACK_STATUS_WAITING_HBIAS) {1383 /*1384 * If we're waiting for HBIAS to stabilize, and we get plug-out1385 * interrupt and nothing more for > 100ms, just cancel the1386 * initialization.1387 */1388 if (scodec->last_hmic_irq == SUN8I_HMIC_STS_JACK_OUT_IRQ_ST) {1389 scodec->jack_status = SUN8I_JACK_STATUS_DISCONNECTED;1390 sun8i_codec_set_hmic_bias(scodec, false);1391 return;1392 }1393 1394 /*1395 * If we're not done waiting for HBIAS to stabilize, wait more.1396 */1397 if (!ktime_after(ktime_get(), scodec->jack_hbias_ready)) {1398 s64 msecs = ktime_ms_delta(scodec->jack_hbias_ready,1399 ktime_get());1400 1401 queue_delayed_work(system_power_efficient_wq,1402 &scodec->jack_work,1403 msecs_to_jiffies(msecs + 10));1404 return;1405 }1406 1407 /*1408 * Everything is stabilized, determine jack type and report it.1409 */1410 regmap_read(scodec->regmap, SUN8I_HMIC_STS, &mdata);1411 mdata &= SUN8I_HMIC_STS_HMIC_DATA_MASK;1412 mdata >>= SUN8I_HMIC_STS_HMIC_DATA;1413 1414 regmap_write(scodec->regmap, SUN8I_HMIC_STS, 0);1415 1416 type = mdata < 16 ? SND_JACK_HEADPHONE : SND_JACK_HEADSET;1417 if (type == SND_JACK_HEADPHONE)1418 sun8i_codec_set_hmic_bias(scodec, false);1419 1420 snd_soc_jack_report(scodec->jack, type, scodec->jack_type);1421 scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED;1422 } else if (scodec->jack_status == SUN8I_JACK_STATUS_CONNECTED) {1423 if (scodec->last_hmic_irq != SUN8I_HMIC_STS_JACK_OUT_IRQ_ST)1424 return;1425 1426 scodec->jack_status = SUN8I_JACK_STATUS_DISCONNECTED;1427 if (scodec->jack_type & SND_JACK_MICROPHONE)1428 sun8i_codec_set_hmic_bias(scodec, false);1429 1430 snd_soc_jack_report(scodec->jack, 0, scodec->jack_type);1431 }1432}1433 1434static irqreturn_t sun8i_codec_jack_irq(int irq, void *dev_id)1435{1436 struct sun8i_codec *scodec = dev_id;1437 int type = SND_JACK_HEADSET;1438 unsigned int status, value;1439 1440 guard(mutex)(&scodec->jack_mutex);1441 1442 regmap_read(scodec->regmap, SUN8I_HMIC_STS, &status);1443 regmap_write(scodec->regmap, SUN8I_HMIC_STS, status);1444 1445 /*1446 * De-bounce in/out interrupts via a delayed work re-scheduling to1447 * 100ms after each interrupt..1448 */1449 if (status & BIT(SUN8I_HMIC_STS_JACK_OUT_IRQ_ST)) {1450 /*1451 * Out interrupt has priority over in interrupt so that if1452 * we get both, we assume the disconnected state, which is1453 * safer.1454 */1455 scodec->last_hmic_irq = SUN8I_HMIC_STS_JACK_OUT_IRQ_ST;1456 mod_delayed_work(system_power_efficient_wq, &scodec->jack_work,1457 msecs_to_jiffies(100));1458 } else if (status & BIT(SUN8I_HMIC_STS_JACK_IN_IRQ_ST)) {1459 scodec->last_hmic_irq = SUN8I_HMIC_STS_JACK_IN_IRQ_ST;1460 mod_delayed_work(system_power_efficient_wq, &scodec->jack_work,1461 msecs_to_jiffies(100));1462 } else if (status & BIT(SUN8I_HMIC_STS_HMIC_DATA_IRQ_ST)) {1463 /*1464 * Ignore data interrupts until jack status turns to connected1465 * state, which is after HMIC enable stabilization is completed.1466 * Until then tha data are bogus.1467 */1468 if (scodec->jack_status != SUN8I_JACK_STATUS_CONNECTED)1469 return IRQ_HANDLED;1470 1471 value = (status & SUN8I_HMIC_STS_HMIC_DATA_MASK) >>1472 SUN8I_HMIC_STS_HMIC_DATA;1473 1474 /*1475 * Assumes 60 mV per ADC LSB increment, 2V bias voltage, 2.2kOhm1476 * bias resistor.1477 */1478 if (value == 0)1479 type |= SND_JACK_BTN_0;1480 else if (value == 1)1481 type |= SND_JACK_BTN_3;1482 else if (value <= 3)1483 type |= SND_JACK_BTN_1;1484 else if (value <= 8)1485 type |= SND_JACK_BTN_2;1486 1487 /*1488 * De-bounce. Only report button after two consecutive A/D1489 * samples are identical.1490 */1491 if (scodec->jack_last_sample >= 0 &&1492 scodec->jack_last_sample == value)1493 snd_soc_jack_report(scodec->jack, type,1494 scodec->jack_type);1495 1496 scodec->jack_last_sample = value;1497 }1498 1499 return IRQ_HANDLED;1500}1501 1502static int sun8i_codec_enable_jack_detect(struct snd_soc_component *component,1503 struct snd_soc_jack *jack, void *data)1504{1505 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component);1506 struct platform_device *pdev = to_platform_device(component->dev);1507 int ret;1508 1509 if (!scodec->quirks->jack_detection)1510 return 0;1511 1512 scodec->jack = jack;1513 1514 scodec->jack_irq = platform_get_irq(pdev, 0);1515 if (scodec->jack_irq < 0)1516 return scodec->jack_irq;1517 1518 /* Reserved value required for jack IRQs to trigger. */1519 regmap_write(scodec->regmap, SUN8I_HMIC_CTRL1,1520 0xf << SUN8I_HMIC_CTRL1_HMIC_N |1521 0x0 << SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB |1522 0x4 << SUN8I_HMIC_CTRL1_HMIC_M);1523 1524 /* Sample the ADC at 128 Hz; bypass smooth filter. */1525 regmap_write(scodec->regmap, SUN8I_HMIC_CTRL2,1526 0x0 << SUN8I_HMIC_CTRL2_HMIC_SAMPLE |1527 0x17 << SUN8I_HMIC_CTRL2_HMIC_MDATA_THRESHOLD |1528 0x0 << SUN8I_HMIC_CTRL2_HMIC_SF);1529 1530 /* Do not discard any MDATA, enable user written MDATA threshold. */1531 regmap_write(scodec->regmap, SUN8I_HMIC_STS, 0);1532 1533 regmap_set_bits(scodec->regmap, SUN8I_HMIC_CTRL1,1534 BIT(SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN) |1535 BIT(SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN));1536 1537 ret = devm_request_threaded_irq(&pdev->dev, scodec->jack_irq,1538 NULL, sun8i_codec_jack_irq,1539 IRQF_ONESHOT,1540 dev_name(&pdev->dev), scodec);1541 if (ret)1542 return ret;1543 1544 return 0;1545}1546 1547static void sun8i_codec_disable_jack_detect(struct snd_soc_component *component)1548{1549 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component);1550 1551 if (!scodec->quirks->jack_detection)1552 return;1553 1554 devm_free_irq(component->dev, scodec->jack_irq, scodec);1555 1556 cancel_delayed_work_sync(&scodec->jack_work);1557 1558 regmap_clear_bits(scodec->regmap, SUN8I_HMIC_CTRL1,1559 BIT(SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN) |1560 BIT(SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN) |1561 BIT(SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN));1562 1563 scodec->jack = NULL;1564}1565 1566static int sun8i_codec_component_set_jack(struct snd_soc_component *component,1567 struct snd_soc_jack *jack, void *data)1568{1569 int ret = 0;1570 1571 if (jack)1572 ret = sun8i_codec_enable_jack_detect(component, jack, data);1573 else1574 sun8i_codec_disable_jack_detect(component);1575 1576 return ret;1577}1578 1579static const struct snd_soc_component_driver sun8i_soc_component = {1580 .controls = sun8i_codec_controls,1581 .num_controls = ARRAY_SIZE(sun8i_codec_controls),1582 .dapm_widgets = sun8i_codec_dapm_widgets,1583 .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets),1584 .dapm_routes = sun8i_codec_dapm_routes,1585 .num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes),1586 .set_jack = sun8i_codec_component_set_jack,1587 .probe = sun8i_codec_component_probe,1588 .idle_bias_on = 1,1589 .suspend_bias_off = 1,1590 .endianness = 1,1591};1592 1593static bool sun8i_codec_volatile_reg(struct device *dev, unsigned int reg)1594{1595 return reg == SUN8I_HMIC_STS;1596}1597 1598static const struct regmap_config sun8i_codec_regmap_config = {1599 .reg_bits = 32,1600 .reg_stride = 4,1601 .val_bits = 32,1602 .volatile_reg = sun8i_codec_volatile_reg,1603 .max_register = SUN8I_DAC_MXR_SRC,1604 1605 .cache_type = REGCACHE_FLAT,1606};1607 1608static int sun8i_codec_probe(struct platform_device *pdev)1609{1610 struct sun8i_codec *scodec;1611 void __iomem *base;1612 int ret;1613 1614 scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);1615 if (!scodec)1616 return -ENOMEM;1617 1618 scodec->quirks = of_device_get_match_data(&pdev->dev);1619 INIT_DELAYED_WORK(&scodec->jack_work, sun8i_codec_jack_work);1620 mutex_init(&scodec->jack_mutex);1621 1622 platform_set_drvdata(pdev, scodec);1623 1624 if (scodec->quirks->bus_clock) {1625 scodec->clk_bus = devm_clk_get(&pdev->dev, "bus");1626 if (IS_ERR(scodec->clk_bus)) {1627 dev_err(&pdev->dev, "Failed to get the bus clock\n");1628 return PTR_ERR(scodec->clk_bus);1629 }1630 }1631 1632 scodec->clk_module = devm_clk_get(&pdev->dev, "mod");1633 if (IS_ERR(scodec->clk_module)) {1634 dev_err(&pdev->dev, "Failed to get the module clock\n");1635 return PTR_ERR(scodec->clk_module);1636 }1637 1638 base = devm_platform_ioremap_resource(pdev, 0);1639 if (IS_ERR(base)) {1640 dev_err(&pdev->dev, "Failed to map the registers\n");1641 return PTR_ERR(base);1642 }1643 1644 scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,1645 &sun8i_codec_regmap_config);1646 if (IS_ERR(scodec->regmap)) {1647 dev_err(&pdev->dev, "Failed to create our regmap\n");1648 return PTR_ERR(scodec->regmap);1649 }1650 1651 regcache_cache_only(scodec->regmap, true);1652 pm_runtime_enable(&pdev->dev);1653 if (!pm_runtime_enabled(&pdev->dev)) {1654 ret = sun8i_codec_runtime_resume(&pdev->dev);1655 if (ret)1656 goto err_pm_disable;1657 }1658 1659 ret = devm_snd_soc_register_component(&pdev->dev, &sun8i_soc_component,1660 sun8i_codec_dais,1661 ARRAY_SIZE(sun8i_codec_dais));1662 if (ret) {1663 dev_err(&pdev->dev, "Failed to register codec\n");1664 goto err_suspend;1665 }1666 1667 return ret;1668 1669err_suspend:1670 if (!pm_runtime_status_suspended(&pdev->dev))1671 sun8i_codec_runtime_suspend(&pdev->dev);1672 1673err_pm_disable:1674 pm_runtime_disable(&pdev->dev);1675 1676 return ret;1677}1678 1679static void sun8i_codec_remove(struct platform_device *pdev)1680{1681 pm_runtime_disable(&pdev->dev);1682 if (!pm_runtime_status_suspended(&pdev->dev))1683 sun8i_codec_runtime_suspend(&pdev->dev);1684}1685 1686static const struct sun8i_codec_quirks sun8i_a33_quirks = {1687 .bus_clock = true,1688 .legacy_widgets = true,1689 .lrck_inversion = true,1690};1691 1692static const struct sun8i_codec_quirks sun50i_a64_quirks = {1693 .bus_clock = true,1694 .jack_detection = true,1695};1696 1697static const struct of_device_id sun8i_codec_of_match[] = {1698 { .compatible = "allwinner,sun8i-a33-codec", .data = &sun8i_a33_quirks },1699 { .compatible = "allwinner,sun50i-a64-codec", .data = &sun50i_a64_quirks },1700 {}1701};1702MODULE_DEVICE_TABLE(of, sun8i_codec_of_match);1703 1704static const struct dev_pm_ops sun8i_codec_pm_ops = {1705 SET_RUNTIME_PM_OPS(sun8i_codec_runtime_suspend,1706 sun8i_codec_runtime_resume, NULL)1707};1708 1709static struct platform_driver sun8i_codec_driver = {1710 .driver = {1711 .name = "sun8i-codec",1712 .of_match_table = sun8i_codec_of_match,1713 .pm = &sun8i_codec_pm_ops,1714 },1715 .probe = sun8i_codec_probe,1716 .remove = sun8i_codec_remove,1717};1718module_platform_driver(sun8i_codec_driver);1719 1720MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver");1721MODULE_AUTHOR("Mylène Josserand <mylene.josserand@free-electrons.com>");1722MODULE_LICENSE("GPL");1723MODULE_ALIAS("platform:sun8i-codec");1724