ASoC: ssm4567: Add support for setting the DAI format and TDM configuration
The SSM4567 has support for a couple of different DAI formats. In TDM mode it is also possible to select the TDM slot. This patch adds support for this by implementing the set_fmt and set_tdm_slot callbacks. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Родитель
feec843d6c
Коммит
ead99f89b7
|
@ -69,6 +69,22 @@
|
|||
#define SSM4567_DAC_FS_64000_96000 0x3
|
||||
#define SSM4567_DAC_FS_128000_192000 0x4
|
||||
|
||||
/* SAI_CTRL_1 */
|
||||
#define SSM4567_SAI_CTRL_1_BCLK BIT(6)
|
||||
#define SSM4567_SAI_CTRL_1_TDM_BLCKS_MASK (0x3 << 4)
|
||||
#define SSM4567_SAI_CTRL_1_TDM_BLCKS_32 (0x0 << 4)
|
||||
#define SSM4567_SAI_CTRL_1_TDM_BLCKS_48 (0x1 << 4)
|
||||
#define SSM4567_SAI_CTRL_1_TDM_BLCKS_64 (0x2 << 4)
|
||||
#define SSM4567_SAI_CTRL_1_FSYNC BIT(3)
|
||||
#define SSM4567_SAI_CTRL_1_LJ BIT(2)
|
||||
#define SSM4567_SAI_CTRL_1_TDM BIT(1)
|
||||
#define SSM4567_SAI_CTRL_1_PDM BIT(0)
|
||||
|
||||
/* SAI_CTRL_2 */
|
||||
#define SSM4567_SAI_CTRL_2_AUTO_SLOT BIT(3)
|
||||
#define SSM4567_SAI_CTRL_2_TDM_SLOT_MASK 0x7
|
||||
#define SSM4567_SAI_CTRL_2_TDM_SLOT(x) (x)
|
||||
|
||||
struct ssm4567 {
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
@ -194,6 +210,107 @@ static int ssm4567_mute(struct snd_soc_dai *dai, int mute)
|
|||
SSM4567_DAC_MUTE, val);
|
||||
}
|
||||
|
||||
static int ssm4567_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||
unsigned int rx_mask, int slots, int width)
|
||||
{
|
||||
struct ssm4567 *ssm4567 = snd_soc_dai_get_drvdata(dai);
|
||||
unsigned int blcks;
|
||||
int slot;
|
||||
int ret;
|
||||
|
||||
if (tx_mask == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (rx_mask && rx_mask != tx_mask)
|
||||
return -EINVAL;
|
||||
|
||||
slot = __ffs(tx_mask);
|
||||
if (tx_mask != BIT(slot))
|
||||
return -EINVAL;
|
||||
|
||||
switch (width) {
|
||||
case 32:
|
||||
blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_32;
|
||||
break;
|
||||
case 48:
|
||||
blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_48;
|
||||
break;
|
||||
case 64:
|
||||
blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_64;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_2,
|
||||
SSM4567_SAI_CTRL_2_AUTO_SLOT | SSM4567_SAI_CTRL_2_TDM_SLOT_MASK,
|
||||
SSM4567_SAI_CTRL_2_TDM_SLOT(slot));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1,
|
||||
SSM4567_SAI_CTRL_1_TDM_BLCKS_MASK, blcks);
|
||||
}
|
||||
|
||||
static int ssm4567_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
struct ssm4567 *ssm4567 = snd_soc_dai_get_drvdata(dai);
|
||||
unsigned int ctrl1 = 0;
|
||||
bool invert_fclk;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
invert_fclk = false;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
ctrl1 |= SSM4567_SAI_CTRL_1_BCLK;
|
||||
invert_fclk = false;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC;
|
||||
invert_fclk = true;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
ctrl1 |= SSM4567_SAI_CTRL_1_BCLK;
|
||||
invert_fclk = true;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
ctrl1 |= SSM4567_SAI_CTRL_1_LJ;
|
||||
invert_fclk = !invert_fclk;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
ctrl1 |= SSM4567_SAI_CTRL_1_TDM;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
ctrl1 |= SSM4567_SAI_CTRL_1_TDM | SSM4567_SAI_CTRL_1_LJ;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_PDM:
|
||||
ctrl1 |= SSM4567_SAI_CTRL_1_PDM;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (invert_fclk)
|
||||
ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC;
|
||||
|
||||
return regmap_write(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1, ctrl1);
|
||||
}
|
||||
|
||||
static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -248,6 +365,8 @@ static int ssm4567_set_bias_level(struct snd_soc_codec *codec,
|
|||
static const struct snd_soc_dai_ops ssm4567_dai_ops = {
|
||||
.hw_params = ssm4567_hw_params,
|
||||
.digital_mute = ssm4567_mute,
|
||||
.set_fmt = ssm4567_set_dai_fmt,
|
||||
.set_tdm_slot = ssm4567_set_tdm_slot,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver ssm4567_dai = {
|
||||
|
|
Загрузка…
Ссылка в новой задаче