int adau17x1_add_widgets(struct snd_soc_component *component) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct adau *adau = snd_soc_component_get_drvdata(component); int ret; ret = snd_soc_add_component_controls(component, adau17x1_controls, ARRAY_SIZE(adau17x1_controls)); if (ret) return ret; ret = snd_soc_dapm_new_controls(dapm, adau17x1_dapm_widgets, ARRAY_SIZE(adau17x1_dapm_widgets)); if (ret) return ret; if (adau17x1_has_dsp(adau)) { ret = snd_soc_dapm_new_controls(dapm, adau17x1_dsp_dapm_widgets, ARRAY_SIZE(adau17x1_dsp_dapm_widgets)); if (ret) return ret; if (!adau->sigmadsp) return 0; ret = sigmadsp_attach(adau->sigmadsp, component); if (ret) { dev_err(component->dev, "Failed to attach firmware: %d\n", ret); return ret; } } return 0; }
int adau17x1_add_routes(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct adau *adau = snd_soc_codec_get_drvdata(codec); int ret; ret = snd_soc_dapm_add_routes(dapm, adau17x1_dapm_routes, ARRAY_SIZE(adau17x1_dapm_routes)); if (ret) return ret; if (adau17x1_has_dsp(adau)) { ret = snd_soc_dapm_add_routes(dapm, adau17x1_dsp_dapm_routes, ARRAY_SIZE(adau17x1_dsp_dapm_routes)); } else { ret = snd_soc_dapm_add_routes(dapm, adau17x1_no_dsp_dapm_routes, ARRAY_SIZE(adau17x1_no_dsp_dapm_routes)); } return ret; }
int adau17x1_add_routes(struct snd_soc_component *component) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct adau *adau = snd_soc_component_get_drvdata(component); int ret; ret = snd_soc_dapm_add_routes(dapm, adau17x1_dapm_routes, ARRAY_SIZE(adau17x1_dapm_routes)); if (ret) return ret; if (adau17x1_has_dsp(adau)) { ret = snd_soc_dapm_add_routes(dapm, adau17x1_dsp_dapm_routes, ARRAY_SIZE(adau17x1_dsp_dapm_routes)); } else { ret = snd_soc_dapm_add_routes(dapm, adau17x1_no_dsp_dapm_routes, ARRAY_SIZE(adau17x1_no_dsp_dapm_routes)); } if (adau->clk_src != ADAU17X1_CLK_SRC_MCLK) snd_soc_dapm_add_routes(dapm, &adau17x1_dapm_pll_route, 1); return ret; }
static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { struct adau *adau = snd_soc_component_get_drvdata(dai->component); unsigned int ser_ctrl0, ser_ctrl1; unsigned int conv_ctrl0, conv_ctrl1; /* I2S mode */ if (slots == 0) { slots = 2; rx_mask = 3; tx_mask = 3; slot_width = 32; } switch (slots) { case 2: ser_ctrl0 = ADAU17X1_SERIAL_PORT0_STEREO; break; case 4: ser_ctrl0 = ADAU17X1_SERIAL_PORT0_TDM4; break; case 8: if (adau->type == ADAU1361) return -EINVAL; ser_ctrl0 = ADAU17X1_SERIAL_PORT0_TDM8; break; default: return -EINVAL; } switch (slot_width * slots) { case 32: if (adau->type == ADAU1761) return -EINVAL; ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK32; break; case 64: ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK64; break; case 48: ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK48; break; case 128: ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK128; break; case 256: if (adau->type == ADAU1361) return -EINVAL; ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK256; break; default: return -EINVAL; } switch (rx_mask) { case 0x03: conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(1); adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 0; break; case 0x0c: conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(2); adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 1; break; case 0x30: conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(3); adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 2; break; case 0xc0: conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(4); adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 3; break; default: return -EINVAL; } switch (tx_mask) { case 0x03: conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(1); adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 0; break; case 0x0c: conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(2); adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 1; break; case 0x30: conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(3); adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 2; break; case 0xc0: conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(4); adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 3; break; default: return -EINVAL; } regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, ADAU17X1_CONVERTER0_DAC_PAIR_MASK, conv_ctrl0); regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER1, ADAU17X1_CONVERTER1_ADC_PAIR_MASK, conv_ctrl1); regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT0, ADAU17X1_SERIAL_PORT0_TDM_MASK, ser_ctrl0); regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1, ADAU17X1_SERIAL_PORT1_BCLK_MASK, ser_ctrl1); if (!adau17x1_has_dsp(adau)) return 0; if (adau->dsp_bypass[SNDRV_PCM_STREAM_PLAYBACK]) { regmap_write(adau->regmap, ADAU17X1_SERIAL_INPUT_ROUTE, (adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] * 2) + 1); } if (adau->dsp_bypass[SNDRV_PCM_STREAM_CAPTURE]) { regmap_write(adau->regmap, ADAU17X1_SERIAL_OUTPUT_ROUTE, (adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] * 2) + 1); } return 0; }
static int adau17x1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; struct adau *adau = snd_soc_component_get_drvdata(component); unsigned int val, div, dsp_div; unsigned int freq; int ret; switch (adau->clk_src) { case ADAU17X1_CLK_SRC_PLL_AUTO: ret = adau17x1_auto_pll(dai, params); if (ret) return ret; /* Fall-through */ case ADAU17X1_CLK_SRC_PLL: freq = adau->pll_freq; break; default: freq = adau->sysclk; break; } if (freq % params_rate(params) != 0) return -EINVAL; switch (freq / params_rate(params)) { case 1024: /* fs */ div = 0; dsp_div = 1; break; case 6144: /* fs / 6 */ div = 1; dsp_div = 6; break; case 4096: /* fs / 4 */ div = 2; dsp_div = 5; break; case 3072: /* fs / 3 */ div = 3; dsp_div = 4; break; case 2048: /* fs / 2 */ div = 4; dsp_div = 3; break; case 1536: /* fs / 1.5 */ div = 5; dsp_div = 2; break; case 512: /* fs / 0.5 */ div = 6; dsp_div = 0; break; default: return -EINVAL; } regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, ADAU17X1_CONVERTER0_CONVSR_MASK, div); if (adau17x1_has_dsp(adau)) { regmap_write(adau->regmap, ADAU17X1_SERIAL_SAMPLING_RATE, div); regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div); } if (adau->sigmadsp) { ret = adau17x1_setup_firmware(component, params_rate(params)); if (ret < 0) return ret; } if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) return 0; switch (params_width(params)) { case 16: val = ADAU17X1_SERIAL_PORT1_DELAY16; break; case 24: val = ADAU17X1_SERIAL_PORT1_DELAY8; break; case 32: val = ADAU17X1_SERIAL_PORT1_DELAY0; break; default: return -EINVAL; } return regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1, ADAU17X1_SERIAL_PORT1_DELAY_MASK, val); }