Other Parts Discussed in Thread: TLV320ADC5140
Hi,
We are developing a custom carrier for the NVIDIA TX2 which will include a 3140 in TDM mode. I note that the ALSA driver TI have produced is written for the 5.0 series kernel, but the latest JetPack release only supports the 4.9 kernel. I have gone through the driver and modified various ALSA calls so that the driver now compiles for the TX2. When the TX2 boots, I see that adcx140_i2c_probe() executes without error, but I have not managed to register the driver yet. I am wondering if any driver experts there (and particularly any who might be familiar with the Jetson or earlier kernel) could take a look at the diff I've attahced to see what I might have broken in the process of porting the tlv320adcx140 driver to the 4.9 kernel. We would be happy to make the new code available to open up the Jetson market if we can get it working.
Cheers,
David.
diff --git a/./orig/tlv320adcx140.c b/tlv320adcx140.c index 714fc63..b6b34be 100644 --- a/./orig/tlv320adcx140.c +++ b/tlv320adcx140.c @@ -24,7 +24,7 @@ #include "tlv320adcx140.h" struct adcx140_priv { - struct snd_soc_component *component; + struct snd_soc_codec *codec; struct regulator *supply_areg; struct gpio_desc *gpio_reset; struct regmap *regmap; @@ -108,7 +108,7 @@ static const struct reg_default adcx140_reg_defaults[] = { { ADCX140_DSP_CFG0, 0x01 }, { ADCX140_DSP_CFG1, 0x40 }, { ADCX140_DRE_CFG0, 0x7b }, - { ADCX140_AGC_CFG0, 0xe7 ], + { ADCX140_AGC_CFG0, 0xe7 }, { ADCX140_IN_CH_EN, 0xf0 }, { ADCX140_ASI_OUT_CH_EN, 0x00 }, { ADCX140_PWR_CFG, 0x00 }, @@ -570,7 +570,7 @@ static int adcx140_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 snd_soc_codec *codec = dai->codec; u8 data = 0; switch (params_width(params)) { @@ -587,12 +587,12 @@ static int adcx140_hw_params(struct snd_pcm_substream *substream, data = ADCX140_32_BIT_WORD; break; default: - dev_err(component->dev, "%s: Unsupported width %d\n", + dev_err(codec->dev, "%s: Unsupported width %d\n", __func__, params_width(params)); return -EINVAL; } - snd_soc_component_update_bits(component, ADCX140_ASI_CFG0, + snd_soc_update_bits(codec, ADCX140_ASI_CFG0, ADCX140_WORD_LEN_MSK, data); return 0; @@ -601,8 +601,8 @@ static int adcx140_hw_params(struct snd_pcm_substream *substream, static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { - struct snd_soc_component *component = codec_dai->component; - struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); + struct snd_soc_codec *codec = codec_dai->codec; + struct adcx140_priv *adcx140 = snd_soc_codec_get_drvdata(codec); u8 iface_reg1 = 0; u8 iface_reg2 = 0; @@ -616,7 +616,7 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, case SND_SOC_DAIFMT_CBS_CFM: case SND_SOC_DAIFMT_CBM_CFS: default: - dev_err(component->dev, "Invalid DAI master/slave interface\n"); + dev_err(codec->dev, "Invalid DAI master/slave interface\n"); return -EINVAL; } @@ -634,7 +634,7 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, case SND_SOC_DAIFMT_NB_NF: break; default: - dev_err(component->dev, "Invalid DAI clock signal polarity\n"); + dev_err(codec->dev, "Invalid DAI clock signal polarity\n"); return -EINVAL; } @@ -650,18 +650,18 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, case SND_SOC_DAIFMT_DSP_B: break; default: - dev_err(component->dev, "Invalid DAI interface format\n"); + dev_err(codec->dev, "Invalid DAI interface format\n"); return -EINVAL; } adcx140->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; - snd_soc_component_update_bits(component, ADCX140_ASI_CFG0, + snd_soc_update_bits(codec, ADCX140_ASI_CFG0, ADCX140_FSYNCINV_BIT | ADCX140_BCLKINV_BIT | ADCX140_ASI_FORMAT_MSK, iface_reg1); - snd_soc_component_update_bits(component, ADCX140_MST_CFG0, + snd_soc_update_bits(codec, ADCX140_MST_CFG0, ADCX140_BCLK_FSYNC_MASTER, iface_reg2); return 0; @@ -671,19 +671,19 @@ static int adcx140_set_dai_tdm_slot(struct snd_soc_dai *codec_dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { - struct snd_soc_component *component = codec_dai->component; - struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); + struct snd_soc_codec *codec = codec_dai->codec; + struct adcx140_priv *adcx140 = snd_soc_codec_get_drvdata(codec); unsigned int lsb; if (tx_mask != rx_mask) { - dev_err(component->dev, "tx and rx masks must be symmetric\n"); + dev_err(codec->dev, "tx and rx masks must be symmetric\n"); return -EINVAL; } /* TDM based on DSP mode requires slots to be adjacent */ lsb = __ffs(tx_mask); if ((lsb + 1) != __fls(tx_mask)) { - dev_err(component->dev, "Invalid mask, slots must be adjacent\n"); + dev_err(codec->dev, "Invalid mask, slots must be adjacent\n"); return -EINVAL; } @@ -694,7 +694,7 @@ static int adcx140_set_dai_tdm_slot(struct snd_soc_dai *codec_dai, case 32: break; default: - dev_err(component->dev, "Unsupported slot width %d\n", slot_width); + dev_err(codec->dev, "Unsupported slot width %d\n", slot_width); return -EINVAL; } @@ -707,8 +707,8 @@ static int adcx140_set_dai_tdm_slot(struct snd_soc_dai *codec_dai, static int adcx140_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_component *component = dai->component; - struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); + struct snd_soc_codec *codec = dai->codec; + struct adcx140_priv *adcx140 = snd_soc_codec_get_drvdata(codec); int offset = 0; int width = adcx140->slot_width; @@ -722,7 +722,7 @@ static int adcx140_prepare(struct snd_pcm_substream *substream, offset += adcx140->tdm_delay * width; /* Configure data offset */ - snd_soc_component_update_bits(component, ADCX140_ASI_CFG1, + snd_soc_update_bits(codec, ADCX140_ASI_CFG1, ADCX140_TX_OFFSET_MASK, offset); return 0; @@ -735,9 +735,9 @@ static const struct snd_soc_dai_ops adcx140_dai_ops = { .set_tdm_slot = adcx140_set_dai_tdm_slot, }; -static int adcx140_codec_probe(struct snd_soc_component *component) +static int adcx140_codec_probe(struct snd_soc_codec *codec) { - struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); + struct adcx140_priv *adcx140 = snd_soc_codec_get_drvdata(codec); int sleep_cfg_val = ADCX140_WAKE_DEV; u8 bias_source; u8 vref_source; @@ -748,9 +748,8 @@ static int adcx140_codec_probe(struct snd_soc_component *component) if (ret) bias_source = ADCX140_MIC_BIAS_VAL_VREF; - if (bias_source != ADCX140_MIC_BIAS_VAL_VREF && - bias_source != ADCX140_MIC_BIAS_VAL_VREF_1096 && - bias_source != ADCX140_MIC_BIAS_VAL_AVDD) { + if (bias_source < ADCX140_MIC_BIAS_VAL_VREF || + bias_source > ADCX140_MIC_BIAS_VAL_AVDD) { dev_err(adcx140->dev, "Mic Bias source value is invalid\n"); return -EINVAL; } @@ -760,9 +759,8 @@ static int adcx140_codec_probe(struct snd_soc_component *component) if (ret) vref_source = ADCX140_MIC_BIAS_VREF_275V; - if (vref_source != ADCX140_MIC_BIAS_VREF_275V && - vref_source != ADCX140_MIC_BIAS_VREF_25V && - vref_source != ADCX140_MIC_BIAS_VREF_1375V) { + if (vref_source < ADCX140_MIC_BIAS_VREF_275V || + vref_source > ADCX140_MIC_BIAS_VREF_1375V) { dev_err(adcx140->dev, "Mic Bias source value is invalid\n"); return -EINVAL; } @@ -794,10 +792,10 @@ out: return ret; } -static int adcx140_set_bias_level(struct snd_soc_component *component, +static int adcx140_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); + struct adcx140_priv *adcx140 = snd_soc_codec_get_drvdata(codec); int pwr_cfg = 0; switch (level) { @@ -815,20 +813,22 @@ static int adcx140_set_bias_level(struct snd_soc_component *component, return regmap_write(adcx140->regmap, ADCX140_PWR_CFG, pwr_cfg); } -static const struct snd_soc_component_driver soc_codec_driver_adcx140 = { - .probe = adcx140_codec_probe, - .set_bias_level = adcx140_set_bias_level, - .controls = adcx140_snd_controls, - .num_controls = ARRAY_SIZE(adcx140_snd_controls), - .dapm_widgets = adcx140_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adcx140_dapm_widgets), - .dapm_routes = adcx140_audio_map, - .num_dapm_routes = ARRAY_SIZE(adcx140_audio_map), - .suspend_bias_off = 1, - .idle_bias_on = 0, - .use_pmdown_time = 1, - .endianness = 1, - .non_legacy_dai_naming = 1, +static const struct snd_soc_codec_driver soc_codec_driver_adcx140 = { + .probe = adcx140_codec_probe, + .set_bias_level = adcx140_set_bias_level, + .suspend_bias_off = true, + .idle_bias_off = true, + .ignore_pmdown_time = false, +/* .endianness = true,*/ +/* .non_legacy_dai_naming = true,*/ + .component_driver = { + .controls = adcx140_snd_controls, + .num_controls = ARRAY_SIZE(adcx140_snd_controls), + .dapm_widgets = adcx140_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adcx140_dapm_widgets), + .dapm_routes = adcx140_audio_map, + .num_dapm_routes = ARRAY_SIZE(adcx140_audio_map), + }, }; static struct snd_soc_dai_driver adcx140_dai_driver[] = { @@ -838,8 +838,8 @@ static struct snd_soc_dai_driver adcx140_dai_driver[] = { .stream_name = "Capture", .channels_min = 2, .channels_max = ADCX140_MAX_CHANNELS, - .rates = ADCX140_RATES, - .formats = ADCX140_FORMATS, + .rates = ADCX140_RATES, + .formats = ADCX140_FORMATS, }, .ops = &adcx140_dai_ops, .symmetric_rates = 1, @@ -894,7 +894,7 @@ static int adcx140_i2c_probe(struct i2c_client *i2c, adcx140->dev = &i2c->dev; i2c_set_clientdata(i2c, adcx140); - return devm_snd_soc_register_component(&i2c->dev, + return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_adcx140, adcx140_dai_driver, 1); }