diff --git a/tas2770-codec.c b/tas2770-codec.c
index 6efab7a14d7f67c411510bc1afe67c99fc57be96..ce05bc2172cb77d994b2350ed5e6cb115ea8b954 100644 (file)
--- a/tas2770-codec.c
+++ b/tas2770-codec.c
#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)
{
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)
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,
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,
};
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"},
struct snd_soc_codec *codec = dai->codec;
struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
+ int slot_width_tmp = 16;
dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__,
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_RXSLEN10_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_FORMAT_S24_LE:
snd_soc_update_bits(codec,
TAS2770_TDMConfigurationReg2,
- TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
- TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
- TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits |
- TAS2770_TDMConfigurationReg2_RXSLEN10_32Bits);
- pTAS2770->ch_size = 32;
+ 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_FORMAT_S32_LE:
snd_soc_update_bits(codec,
TAS2770_TDMConfigurationReg2,
- TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
- TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
- TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits |
- TAS2770_TDMConfigurationReg2_RXSLEN10_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;
+ default:
+ dev_dbg(pTAS2770->dev, "Not supported params format\n");
+ return -EINVAL;
}
- dev_dbg(pTAS2770->dev, "ch_size: %d\n", pTAS2770->ch_size);
+ /* 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->ch_size >> 3));
+ pTAS2770->mnVmon_slot_no);
snd_soc_update_bits(codec,
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));
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);
snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
(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 |\
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;
}
}
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("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),
};
static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {