diff --git a/tas2770-codec.c b/tas2770-codec.c
index c15c4195552f72cd64a4ce01dfc717f46edc12e8..1e4e852969d68c5ef37128e5396c0a8574de207f 100644 (file)
--- a/tas2770-codec.c
+++ b/tas2770-codec.c
** tas2770-codec.c
**
** Description:
** tas2770-codec.c
**
** Description:
-** ALSA SoC driver for Texas Instruments TAS2770 High Performance 4W Smart
-** Amplifier
+** ALSA SoC driver for TAS2770 20-W Digital Input Mono Class-D Audio Amplifier
+** with Speaker I/V Sense
**
** =============================================================================
*/
**
** =============================================================================
*/
#define TAS2770_MDELAY 0xFFFFFFFE
#define TAS2770_MDELAY 0xFFFFFFFE
+static int tas2770_set_slot(struct snd_soc_codec *codec, int slot_width);
+
static unsigned int tas2770_codec_read(struct snd_soc_codec *codec,
unsigned int reg)
{
static unsigned int tas2770_codec_read(struct snd_soc_codec *codec,
unsigned int reg)
{
mutex_lock(&pTAS2770->codec_lock);
dev_dbg(pTAS2770->dev, "%s\n", __func__);
mutex_lock(&pTAS2770->codec_lock);
dev_dbg(pTAS2770->dev, "%s\n", __func__);
- pTAS2770->runtime_suspend(pTAS2770);
mutex_unlock(&pTAS2770->codec_lock);
return ret;
mutex_unlock(&pTAS2770->codec_lock);
return ret;
mutex_lock(&pTAS2770->codec_lock);
dev_dbg(pTAS2770->dev, "%s\n", __func__);
mutex_lock(&pTAS2770->codec_lock);
dev_dbg(pTAS2770->dev, "%s\n", __func__);
- pTAS2770->runtime_resume(pTAS2770);
mutex_unlock(&pTAS2770->codec_lock);
return ret;
}
mutex_unlock(&pTAS2770->codec_lock);
return ret;
}
-static const struct snd_kcontrol_new tas2770_asi_controls[] = {
- SOC_DAPM_SINGLE("Left", TAS2770_TDMConfigurationReg2,
- 4, 1, 0),
- SOC_DAPM_SINGLE("Right", TAS2770_TDMConfigurationReg2,
- 4, 2, 0),
- SOC_DAPM_SINGLE("LeftRightDiv2", TAS2770_TDMConfigurationReg2,
- 4, 3, 0),
+static const char * const tas2770_ASI1_src[] = {
+ "I2C offset", "Left", "Right", "LeftRightDiv2",
};
};
+static SOC_ENUM_SINGLE_DECL(
+ tas2770_ASI1_src_enum, TAS2770_TDMConfigurationReg2,
+ 4, tas2770_ASI1_src);
-static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
+static const struct snd_kcontrol_new tas2770_asi1_mux =
+ SOC_DAPM_ENUM("ASI1 Source", tas2770_ASI1_src_enum);
+
+static int tas2770_set_power_state(struct tas2770_priv *pTAS2770, int state)
{
{
- struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct snd_soc_codec *codec = pTAS2770->codec;
- switch (event) {
- case SND_SOC_DAPM_POST_PMU:
+ switch (state) {
+ case TAS2770_POWER_ACTIVE:
snd_soc_update_bits(codec, TAS2770_PowerControl,
TAS2770_PowerControl_OperationalMode10_Mask,
TAS2770_PowerControl_OperationalMode10_Active);
break;
snd_soc_update_bits(codec, TAS2770_PowerControl,
TAS2770_PowerControl_OperationalMode10_Mask,
TAS2770_PowerControl_OperationalMode10_Active);
break;
- case SND_SOC_DAPM_PRE_PMD:
+
+ case TAS2770_POWER_MUTE:
+ snd_soc_update_bits(codec, TAS2770_PowerControl,
+ TAS2770_PowerControl_OperationalMode10_Mask,
+ TAS2770_PowerControl_OperationalMode10_Mute);
+ break;
+
+ case TAS2770_POWER_SHUTDOWN:
snd_soc_update_bits(codec, TAS2770_PowerControl,
TAS2770_PowerControl_OperationalMode10_Mask,
TAS2770_PowerControl_OperationalMode10_Shutdown);
break;
snd_soc_update_bits(codec, TAS2770_PowerControl,
TAS2770_PowerControl_OperationalMode10_Mask,
TAS2770_PowerControl_OperationalMode10_Shutdown);
break;
+ default:
+ dev_err(pTAS2770->dev, "wrong power state setting %d\n", state);
+
}
}
+
+ pTAS2770->mnPowerState = state;
return 0;
return 0;
+}
+static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
+
+ mutex_lock(&pTAS2770->codec_lock);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ tas2770_set_power_state(pTAS2770, TAS2770_POWER_MUTE);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ tas2770_set_power_state(pTAS2770, TAS2770_POWER_SHUTDOWN);
+ break;
+
+ }
+
+ mutex_unlock(&pTAS2770->codec_lock);
+ return 0;
}
static const struct snd_kcontrol_new isense_switch =
}
static const struct snd_kcontrol_new isense_switch =
static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
- SND_SOC_DAPM_MIXER("ASI1 Sel",
- TAS2770_TDMConfigurationReg2, 4, 0,
- &tas2770_asi_controls[0],
- ARRAY_SIZE(tas2770_asi_controls)),
+ SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0,
+ &tas2770_asi1_mux),
SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PowerControl, 3, 1,
&isense_switch),
SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PowerControl, 2, 1,
SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PowerControl, 3, 1,
&isense_switch),
SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PowerControl, 2, 1,
};
static const struct snd_soc_dapm_route tas2770_audio_map[] = {
};
static const struct snd_soc_dapm_route tas2770_audio_map[] = {
+ {"ASI1 Sel", "I2C offset", "ASI1"},
{"ASI1 Sel", "Left", "ASI1"},
{"ASI1 Sel", "Right", "ASI1"},
{"ASI1 Sel", "LeftRightDiv2", "ASI1"},
{"ASI1 Sel", "Left", "ASI1"},
{"ASI1 Sel", "Right", "ASI1"},
{"ASI1 Sel", "LeftRightDiv2", "ASI1"},
mutex_lock(&pTAS2770->codec_lock);
if (mute) {
mutex_lock(&pTAS2770->codec_lock);
if (mute) {
- snd_soc_update_bits(codec, TAS2770_PowerControl,
- TAS2770_PowerControl_OperationalMode10_Mask,
- TAS2770_PowerControl_OperationalMode10_Mute);
+ tas2770_set_power_state(pTAS2770, TAS2770_POWER_MUTE);
} else {
} else {
- snd_soc_update_bits(codec, TAS2770_PowerControl,
- TAS2770_PowerControl_OperationalMode10_Mask,
- TAS2770_PowerControl_OperationalMode10_Active);
+ tas2770_set_power_state(pTAS2770, TAS2770_POWER_ACTIVE);
}
mutex_unlock(&pTAS2770->codec_lock);
return 0;
}
}
mutex_unlock(&pTAS2770->codec_lock);
return 0;
}
-static int tas2770_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+static int tas2770_set_bitwidth(struct tas2770_priv *pTAS2770, int bitwidth)
{
{
- struct snd_soc_codec *codec = dai->codec;
- struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
- int ret = 0;
-
- dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__,
- params_format(params));
-
- switch (params_format(params)) {
+ switch (bitwidth) {
case SNDRV_PCM_FORMAT_S16_LE:
case SNDRV_PCM_FORMAT_S16_LE:
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg2,
TAS2770_TDMConfigurationReg2,
- TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
- TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
- TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits |
+ TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits);
TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits);
- pTAS2770->ch_size = 16;
+ /* If machine driver did not call set slot width */
+ if (pTAS2770->mnSlot_width == 0)
+ tas2770_set_slot(pTAS2770->codec, 16);
+ pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 2;
break;
case SNDRV_PCM_FORMAT_S24_LE:
break;
case SNDRV_PCM_FORMAT_S24_LE:
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg2,
TAS2770_TDMConfigurationReg2,
- TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
- TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
- TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits |
+ TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits);
TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits);
- pTAS2770->ch_size = 32;
+ if (pTAS2770->mnSlot_width == 0)
+ tas2770_set_slot(pTAS2770->codec, 32);
+ pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 4;
break;
case SNDRV_PCM_FORMAT_S32_LE:
break;
case SNDRV_PCM_FORMAT_S32_LE:
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg2,
TAS2770_TDMConfigurationReg2,
- TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
- TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
- TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits |
+ TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits);
TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits);
- pTAS2770->ch_size = 32;
+ if (pTAS2770->mnSlot_width == 0)
+ tas2770_set_slot(pTAS2770->codec, 32);
+ pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 4;
break;
break;
+ default:
+ dev_dbg(pTAS2770->dev, "Not supported params format\n");
+ return -EINVAL;
}
}
- dev_dbg(pTAS2770->dev, "ch_size: %d\n", pTAS2770->ch_size);
- snd_soc_update_bits(codec,
+ pTAS2770->mnCh_size = bitwidth;
+ dev_dbg(pTAS2770->dev, "mnCh_size: %d\n", pTAS2770->mnCh_size);
+
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg5,
TAS2770_TDMConfigurationReg5_VSNSTX_Mask |
TAS2770_TDMConfigurationReg5_VSNSSLOT50_Mask,
TAS2770_TDMConfigurationReg5_VSNSTX_Enable |
TAS2770_TDMConfigurationReg5,
TAS2770_TDMConfigurationReg5_VSNSTX_Mask |
TAS2770_TDMConfigurationReg5_VSNSSLOT50_Mask,
TAS2770_TDMConfigurationReg5_VSNSTX_Enable |
- (pTAS2770->ch_size >> 3));
- snd_soc_update_bits(codec,
+ pTAS2770->mnVmon_slot_no);
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg6,
TAS2770_TDMConfigurationReg6_ISNSTX_Mask |
TAS2770_TDMConfigurationReg6_ISNSSLOT50_Mask,
TAS2770_TDMConfigurationReg6,
TAS2770_TDMConfigurationReg6_ISNSTX_Mask |
TAS2770_TDMConfigurationReg6_ISNSSLOT50_Mask,
- TAS2770_TDMConfigurationReg6_ISNSTX_Enable);
+ TAS2770_TDMConfigurationReg6_ISNSTX_Enable |
+ pTAS2770->mnImon_slot_no);
- dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__,
- params_rate(params));
- switch (params_rate(params)) {
+ return 0;
+}
+
+static int tas2770_set_samplerate(struct tas2770_priv *pTAS2770, int samplerate)
+{
+ switch (samplerate) {
case 48000:
case 48000:
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
break;
case 44100:
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
break;
case 44100:
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
break;
case 96000:
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
break;
case 96000:
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
+ TAS2770_TDMConfigurationReg0,
+ TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
+ TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
+ break;
+ case 88200:
+ snd_soc_update_bits(pTAS2770->codec,
+ TAS2770_TDMConfigurationReg0,
+ TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
+ TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
break;
case 19200:
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
break;
case 19200:
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
- snd_soc_update_bits(codec,
+ snd_soc_update_bits(pTAS2770->codec,
+ TAS2770_TDMConfigurationReg0,
+ TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
+ TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
+ break;
+ case 17640:
+ snd_soc_update_bits(pTAS2770->codec,
+ TAS2770_TDMConfigurationReg0,
+ TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
+ TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
+ snd_soc_update_bits(pTAS2770->codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
}
dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
}
- return ret;
+
+ pTAS2770->mnSamplingRate = samplerate;
+ return 0;
}
}
-static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+static int tas2770_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
{
- u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
struct snd_soc_codec *codec = dai->codec;
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
struct snd_soc_codec *codec = dai->codec;
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
- dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
+ dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__,
+ params_format(params));
+
+ mutex_lock(&pTAS2770->codec_lock);
+
+ ret = tas2770_set_bitwidth(pTAS2770, params_format(params));
+ if(ret < 0)
+ return ret;
+
+ dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__,
+ params_rate(params));
+
+ ret = tas2770_set_samplerate(pTAS2770, params_rate(params));
+
+ mutex_unlock(&pTAS2770->codec_lock);
+ return ret;
+}
+
+static int tas2770_set_fmt(struct tas2770_priv *pTAS2770, unsigned int fmt)
+{
+ u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
+ int ret = 0;
+ int value = 0;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
ret = -EINVAL;
}
ret = -EINVAL;
}
- snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
+ snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg1,
TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
asi_cfg_1);
TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
asi_cfg_1);
break;
}
break;
}
- snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
+ snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg1,
TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
(tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
(tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
+
+ snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg3,
+ TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Mask,
+ (pTAS2770->mnLeftSlot << TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Shift));
+ snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg3,
+ TAS2770_TDMConfigurationReg3_RXSLOTRight74_Mask,
+ (pTAS2770->mnRightSlot << TAS2770_TDMConfigurationReg3_RXSLOTRight74_Shift));
+
+ value = snd_soc_read(pTAS2770->codec, TAS2770_TDMConfigurationReg3);
+ dev_dbg(pTAS2770->dev, "slot value: 0x%x", value);
+
+ pTAS2770->mnASIFormat = fmt;
+
+ return 0;
+}
+
+static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
+ mutex_lock(&pTAS2770->codec_lock);
+
+ ret = tas2770_set_fmt(pTAS2770, fmt);
+
+ mutex_unlock(&pTAS2770->codec_lock);
+ return ret;
+}
+
+static int tas2770_set_slot(struct snd_soc_codec *codec, int slot_width)
+{
+ int ret = 0;
+ struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
+
+ switch (slot_width) {
+ case 16:
+ ret = snd_soc_update_bits(codec,
+ TAS2770_TDMConfigurationReg2,
+ TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
+ TAS2770_TDMConfigurationReg2_RXSLEN10_16Bits);
+ break;
+
+ case 24:
+ ret = snd_soc_update_bits(codec,
+ TAS2770_TDMConfigurationReg2,
+ TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
+ TAS2770_TDMConfigurationReg2_RXSLEN10_24Bits);
+ break;
+
+ case 32:
+ ret = snd_soc_update_bits(codec,
+ TAS2770_TDMConfigurationReg2,
+ TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
+ TAS2770_TDMConfigurationReg2_RXSLEN10_32Bits);
+ break;
+
+ case 0:
+ /* Do not change slot width */
+ break;
+
+ default:
+ dev_dbg(pTAS2770->dev, "slot width not supported");
+ ret = -EINVAL;
+ }
+
+ if (ret >= 0)
+ pTAS2770->mnSlot_width = slot_width;
+
+ return ret;
+}
+
+static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask,
+ int slots, int slot_width)
+{
+ int ret = 0;
+ struct snd_soc_codec *codec = dai->codec;
+ struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(pTAS2770->dev, "%s, tx_mask:%d, rx_mask:%d, slots:%d, slot_width:%d",
+ __func__, tx_mask, rx_mask, slots, slot_width);
+
+ mutex_lock(&pTAS2770->codec_lock);
+ ret = tas2770_set_slot(codec, slot_width);
+ mutex_unlock(&pTAS2770->codec_lock);
+
return ret;
}
return ret;
}
.digital_mute = tas2770_mute,
.hw_params = tas2770_hw_params,
.set_fmt = tas2770_set_dai_fmt,
.digital_mute = tas2770_mute,
.hw_params = tas2770_hw_params,
.set_fmt = tas2770_set_dai_fmt,
+ .set_tdm_slot = tas2770_set_dai_tdm_slot,
};
#define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
};
#define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
dev_err(pTAS2770->dev, "%s\n", __func__);
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
dev_err(pTAS2770->dev, "%s\n", __func__);
+ pTAS2770->codec = codec;
return 0;
}
return 0;
}
}
static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
}
static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
+static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -12750, 50, 0);
static const struct snd_kcontrol_new tas2770_snd_controls[] = {
SOC_SINGLE_TLV("Amp Output Level", TAS2770_PlaybackConfigurationReg0,
static const struct snd_kcontrol_new tas2770_snd_controls[] = {
SOC_SINGLE_TLV("Amp Output Level", TAS2770_PlaybackConfigurationReg0,
- 0, TAS2770_PlaybackConfigurationReg0_AmplifierLevel40_Mask, 0,
+ 0, 0x14, 0,
tas2770_digital_tlv),
tas2770_digital_tlv),
+ SOC_SINGLE_TLV("Playback Volume", TAS2770_PlaybackConfigurationReg2,
+ 0, TAS2770_PlaybackConfigurationReg2_VOLMAX, 1,
+ tas2770_playback_volume),
};
static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
};
static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
return 0;
}
return 0;
}
+void tas2770_LoadConfig(struct tas2770_priv *pTAS2770)
+{
+ int ret = 0;
+
+ pTAS2770->hw_reset(pTAS2770);
+ snd_soc_write(pTAS2770->codec, TAS2770_SoftwareReset,
+ TAS2770_SoftwareReset_SoftwareReset_Reset);
+
+ ret = tas2770_set_slot(pTAS2770->codec, pTAS2770->mnSlot_width);
+ if (ret < 0)
+ goto end;
+
+ ret = tas2770_set_fmt(pTAS2770, pTAS2770->mnASIFormat);
+ if (ret < 0)
+ goto end;
+
+ ret = tas2770_set_bitwidth(pTAS2770, pTAS2770->mnCh_size);
+ if (ret < 0)
+ goto end;
+
+ ret = tas2770_set_samplerate(pTAS2770, pTAS2770->mnSamplingRate);
+ if (ret < 0)
+ goto end;
+
+ ret = tas2770_set_power_state(pTAS2770, pTAS2770->mnPowerState);
+
+end:
+/* power up failed, restart later */
+ if (ret < 0)
+ schedule_delayed_work(&pTAS2770->irq_work,
+ msecs_to_jiffies(1000));
+}
+
MODULE_AUTHOR("Texas Instruments Inc.");
MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Texas Instruments Inc.");
MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
MODULE_LICENSE("GPL v2");