diff --git a/tas2770-codec.c b/tas2770-codec.c
index 9d75894a67f915645170ed87ef17b6edd6050c0f..e736c9d34c3fd8928f1a21098d0d17783965f713 100644 (file)
--- a/tas2770-codec.c
+++ b/tas2770-codec.c
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+** FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details.
**
** File:
** 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
**
** =============================================================================
*/
#ifdef CONFIG_TAS2770_CODEC
-
#define DEBUG
#include <linux/module.h>
#include <linux/moduleparam.h>
#define TAS2770_MDELAY 0xFFFFFFFE
-//#define KCONTROL_CODEC
-static unsigned int tas2770_codec_read(struct snd_soc_codec *codec, unsigned int reg)
+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)
{
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
int nResult = 0;
- unsigned int value = 0;
-
- mutex_lock(&pTAS2770->dev_lock);
-
- nResult = regmap_read(pTAS2770->regmap, reg, &value);
+ unsigned int value;
+ nResult = tas2770_read(pTAS2770, reg);
if (nResult < 0)
dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
__func__, reg, nResult);
- else
- dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, value: 0x%x\n", __func__, reg, value);
+ else {
+ value = nResult;
+ dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, value: 0x%x\n",
+ __func__, reg, value);
+ }
+ return nResult;
+}
+
+int tas2770_read(struct tas2770_priv *pTAS2770, unsigned int reg)
+{
+ int nResult = 0;
+ struct i2c_msg msg_buf[2];
+ unsigned char data1, data2;
+ data2 = (unsigned char)reg;
+ msg_buf[0].addr = pTAS2770->mnAddr;
+ msg_buf[0].len = 1;
+ msg_buf[0].flags = 0;
+ msg_buf[0].buf = &data2;
+
+ msg_buf[1].addr = pTAS2770->mnAddr;
+ msg_buf[1].len = 1;
+ msg_buf[1].flags = I2C_M_RD;
+ msg_buf[1].buf = &data1;
+
+ mutex_lock(&pTAS2770->dev_lock);
+ nResult = i2c_transfer(pTAS2770->adapter, msg_buf, 2);
mutex_unlock(&pTAS2770->dev_lock);
- if(nResult >= 0)
- return value;
+ if (nResult >= 0)
+ return data1;
else
return nResult;
}
static int tas2770_codec_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
+ unsigned int value)
{
- struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
-
int nResult = 0;
+ struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
- mutex_lock(&pTAS2770->dev_lock);
+ nResult = tas2770_write(pTAS2770, reg, value);
- nResult = regmap_write(pTAS2770->regmap, reg, value);
- if(nResult < 0)
+ if (nResult < 0)
dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
__func__, reg, nResult);
else
- dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, 0x%x\n", __func__, reg, value);
+ dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, 0x%x\n",
+ __func__, reg, value);
+ return nResult;
+}
+int tas2770_write(struct tas2770_priv *pTAS2770, unsigned int reg, unsigned int value)
+{
+ int nResult = 0;
+ struct i2c_msg msg;
+ unsigned char data[2];
+
+ msg.addr = pTAS2770->mnAddr;
+ msg.len = 2;
+ msg.flags = 0;
+ msg.buf = data;
+
+ data[0] = (unsigned char)reg;
+ data[1] = (unsigned char)value;
+
+ mutex_lock(&pTAS2770->dev_lock);
+ nResult = i2c_transfer(pTAS2770->adapter, &msg, 1);
mutex_unlock(&pTAS2770->dev_lock);
return nResult;
-
}
-
static int tas2770_codec_suspend(struct snd_soc_codec *codec)
{
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
mutex_lock(&pTAS2770->codec_lock);
dev_dbg(pTAS2770->dev, "%s\n", __func__);
-// pTAS2770->runtime_suspend(pTAS2770);
mutex_unlock(&pTAS2770->codec_lock);
return ret;
mutex_lock(&pTAS2770->codec_lock);
dev_dbg(pTAS2770->dev, "%s\n", __func__);
-// pTAS2770->runtime_resume(pTAS2770);
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 const struct snd_kcontrol_new tas2770_asi1_mux =
+ SOC_DAPM_ENUM("ASI1 Source", tas2770_ASI1_src_enum);
+
static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
+ struct snd_kcontrol *kcontrol, int event)
{
-#if 1
- struct snd_soc_codec *codec = w->codec;
-// struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(codec, TAS2770_PowerControl,
TAS2770_PowerControl_OperationalMode10_Mask,
- TAS2770_PowerControl_OperationalMode10_Active);
+ TAS2770_PowerControl_OperationalMode10_Mute);
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_update_bits(codec, TAS2770_PowerControl,
TAS2770_PowerControl_OperationalMode10_Mask,
TAS2770_PowerControl_OperationalMode10_Shutdown);
break;
-
+
}
-#endif
return 0;
}
+static const struct snd_kcontrol_new isense_switch =
+ SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 3, 1, 1);
+static const struct snd_kcontrol_new vsense_switch =
+ SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 2, 1, 1);
+
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_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
- tas2770_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_OUTPUT("OUT")
-
+ 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,
+ &vsense_switch),
+ SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_OUTPUT("OUT"),
+ SND_SOC_DAPM_SIGGEN("VMON"),
+ SND_SOC_DAPM_SIGGEN("IMON")
};
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"},
{"DAC", NULL, "ASI1 Sel"},
{"OUT", NULL, "DAC"},
+ {"ISENSE", "Switch", "IMON"},
+ {"VSENSE", "Switch", "VMON"},
};
static int tas2770_mute(struct snd_soc_dai *dai, int mute)
{
-#if 1
struct snd_soc_codec *codec = dai->codec;
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
+ dev_dbg(pTAS2770->dev, "%s\n", __func__);
mutex_lock(&pTAS2770->codec_lock);
- if(mute) {
+ if (mute) {
snd_soc_update_bits(codec, TAS2770_PowerControl,
TAS2770_PowerControl_OperationalMode10_Mask,
- TAS2770_PowerControl_OperationalMode10_Mute);
+ TAS2770_PowerControl_OperationalMode10_Mute);
} else {
snd_soc_update_bits(codec, TAS2770_PowerControl,
TAS2770_PowerControl_OperationalMode10_Mask,
- TAS2770_PowerControl_OperationalMode10_Active);
+ TAS2770_PowerControl_OperationalMode10_Active);
}
mutex_unlock(&pTAS2770->codec_lock);
-#endif
return 0;
}
-
-
static int tas2770_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
- int blr_clk_ratio;
int ret = 0;
+ int slot_width_tmp = 16;
- dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__, params_format(params));
+ dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__,
+ params_format(params));
- switch(params_format(params)) {
+ switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
snd_soc_update_bits(codec,
TAS2770_TDMConfigurationReg2,
- TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
- TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
- TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits |
- TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits );
- pTAS2770->ch_size = 16;
+ TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
+ TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits);
+ pTAS2770->mnCh_size = 16;
+ if (pTAS2770->mnSlot_width == 0)
+ slot_width_tmp = 16;
break;
- case SNDRV_PCM_FMTBIT_S24_LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
snd_soc_update_bits(codec,
TAS2770_TDMConfigurationReg2,
- TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
- TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
- TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits |
- TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits );
- pTAS2770->ch_size = 24;
+ TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
+ TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits);
+ pTAS2770->mnCh_size = 24;
+ if (pTAS2770->mnSlot_width == 0)
+ slot_width_tmp = 32;
break;
- case SNDRV_PCM_FMTBIT_S32_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
snd_soc_update_bits(codec,
TAS2770_TDMConfigurationReg2,
- TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
- TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
- TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits |
- TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits );
- pTAS2770->ch_size = 32;
+ TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
+ TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits);
+ pTAS2770->mnCh_size = 32;
+ if (pTAS2770->mnSlot_width == 0)
+ slot_width_tmp = 32;
break;
- }
-
- blr_clk_ratio = params_channels(params) * pTAS2770->ch_size;
- dev_dbg(pTAS2770->dev, "blr_clk_ratio: %d\n", blr_clk_ratio);
-
- switch(blr_clk_ratio) {
- case 16:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_16);
- break;
- case 24:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_24);
- break;
- case 32:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_32);
- break;
- case 48:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_48);
- break;
- case 64:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_64);
- break;
- case 96:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_96);
- break;
- case 128:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_128);
- break;
- case 192:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_192);
- break;
- case 256:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_256);
- break;
- case 384:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_384);
- break;
- case 512:
- snd_soc_update_bits(codec,
- TAS2770_ClockConfiguration,
- TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
- TAS2770_ClockConfiguration_SBCLKtoFS52_512);
- break;
default:
- dev_err(pTAS2770->dev, "Invalid BCLK to FSYNC ratio\n");
- ret = -EINVAL;
+ dev_dbg(pTAS2770->dev, "Not supported params format\n");
+ return -EINVAL;
}
- dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__, params_rate(params));
- switch(params_rate(params))
- {
- case 48000:
+ /* If machine driver did not call set slot width */
+ if (pTAS2770->mnSlot_width == 0)
+ tas2770_set_slot(codec, slot_width_tmp);
+
+ dev_dbg(pTAS2770->dev, "mnCh_size: %d\n", pTAS2770->mnCh_size);
+ snd_soc_update_bits(codec,
+ TAS2770_TDMConfigurationReg5,
+ TAS2770_TDMConfigurationReg5_VSNSTX_Mask |
+ TAS2770_TDMConfigurationReg5_VSNSSLOT50_Mask,
+ TAS2770_TDMConfigurationReg5_VSNSTX_Enable |
+ pTAS2770->mnVmon_slot_no);
+ snd_soc_update_bits(codec,
+ TAS2770_TDMConfigurationReg6,
+ TAS2770_TDMConfigurationReg6_ISNSTX_Mask |
+ TAS2770_TDMConfigurationReg6_ISNSSLOT50_Mask,
+ 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)) {
+ case 48000:
snd_soc_update_bits(codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
break;
- case 44100:
+ case 44100:
snd_soc_update_bits(codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
break;
- case 96000:
+ case 96000:
snd_soc_update_bits(codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
break;
- case 88200:
- snd_soc_update_bits(codec,
- TAS2770_TDMConfigurationReg0,
- TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
- TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
- snd_soc_update_bits(codec,
- TAS2770_TDMConfigurationReg0,
- TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
- TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
- break;
- case 19200:
+ case 19200:
snd_soc_update_bits(codec,
TAS2770_TDMConfigurationReg0,
TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
break;
- case 17640:
- snd_soc_update_bits(codec,
- TAS2770_TDMConfigurationReg0,
- TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
- TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
- snd_soc_update_bits(codec,
- TAS2770_TDMConfigurationReg0,
- TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
- TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
- break;
- default:
+ default:
dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
-
+
}
return ret;
}
struct snd_soc_codec *codec = dai->codec;
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
+ int value = 0;
dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
-#if 1
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBS_CFS:
+ case SND_SOC_DAIFMT_CBS_CFS:
asi_cfg_1 = 0x00;
break;
default:
ret = -EINVAL;
}
- snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
+ snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
asi_cfg_1);
tdm_rx_start_slot = 0;
break;
default:
- dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
- ret = -EINVAL;
+ dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
+ ret = -EINVAL;
break;
}
- snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
+ snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
- (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
-#endif
+ (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
+
+ snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg3,
+ TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Mask,
+ (pTAS2770->mnLeftSlot << TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Shift));
+ snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg3,
+ TAS2770_TDMConfigurationReg3_RXSLOTRight74_Mask,
+ (pTAS2770->mnRightSlot << TAS2770_TDMConfigurationReg3_RXSLOTRight74_Shift));
+
+ value = snd_soc_read(codec, TAS2770_TDMConfigurationReg3);
+ dev_dbg(pTAS2770->dev, "slot value: 0x%x", value);
+
+ 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);
+
+ ret = tas2770_set_slot(codec, slot_width);
+
return ret;
}
.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 |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-#define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 \
- SNDRV_PCM_RATE_88200 |\
+#define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
SNDRV_PCM_RATE_96000 |\
- SNDRV_PCM_RATE_176400 |\
SNDRV_PCM_RATE_192000\
)
.stream_name = "ASI1 Playback",
.channels_min = 2,
.channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_192000,
+ .rates = TAS2770_RATES,
.formats = TAS2770_FORMATS,
},
.capture = {
.stream_name = "ASI1 Capture",
.channels_min = 0,
.channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = TAS2770_FORMATS,
+ .rates = TAS2770_RATES,
+ .formats = TAS2770_FORMATS,
},
.ops = &tas2770_dai_ops,
.symmetric_rates = 1,
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
dev_err(pTAS2770->dev, "%s\n", __func__);
+ snd_soc_codec_init_regmap(codec, pTAS2770->regmap);
return 0;
}
return 0;
}
-#if 0
-
-/*
- * DAC digital volumes. From 0 to 31 dB in 1 dB steps
- */
-static DECLARE_TLV_DB_SCALE(dac_tlv, 0, 100, 0);
+static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
+static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -10000, 50, 0);
static const struct snd_kcontrol_new tas2770_snd_controls[] = {
- SOC_SINGLE_TLV("DAC Playback Volume", TAS2770_PlaybackConfigurationReg0, 0, 0x1f, 0,
- dac_tlv),
-// SOC_SINGLE_EXT("TAS2770 PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0,
-// tas2770_power_ctrl_get, tas2770_power_ctrl_put),
+ SOC_SINGLE_TLV("Amp Output Level", TAS2770_PlaybackConfigurationReg0,
+ 0, TAS2770_PlaybackConfigurationReg0_AmplifierLevel40_Mask, 0,
+ tas2770_digital_tlv),
+ SOC_SINGLE_TLV("Playback Volume", TAS2770_PlaybackConfigurationReg2,
+ 0, TAS2770_PlaybackConfigurationReg2_DVCPCM70_Mask, 1,
+ tas2770_playback_volume),
};
-#endif
static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
.probe = tas2770_codec_probe,
.suspend = tas2770_codec_suspend,
.resume = tas2770_codec_resume,
.component_driver = {
-// .controls = tas2770_snd_controls,
-// .num_controls = ARRAY_SIZE(tas2770_snd_controls),
+ .controls = tas2770_snd_controls,
+ .num_controls = ARRAY_SIZE(tas2770_snd_controls),
.dapm_widgets = tas2770_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tas2770_dapm_widgets),
.dapm_routes = tas2770_audio_map,