ASoC: mchp-i2s-mcc: Add support to select TDM pins
SAMA7G5's I2S-MCC has 4 pairs of DIN/DOUT pins. Since TDM only uses a single pair of pins for synchronous capture and playback, the controller needs to be told which of the pair is connected. This can be mentioned using the "microchip,tdm-data-pair" property from DT. The property is optional, useful only if TDM is used. If it's missing, DIN/DOUT 0 pins will be used by default. Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com> Link: https://lore.kernel.org/r/20210301170905.835091-6-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
13c1629d75
commit
bfdca48975
@ -100,6 +100,8 @@
|
|||||||
#define MCHP_I2SMCC_MRA_DATALENGTH_8_BITS_COMPACT (7 << 1)
|
#define MCHP_I2SMCC_MRA_DATALENGTH_8_BITS_COMPACT (7 << 1)
|
||||||
|
|
||||||
#define MCHP_I2SMCC_MRA_WIRECFG_MASK GENMASK(5, 4)
|
#define MCHP_I2SMCC_MRA_WIRECFG_MASK GENMASK(5, 4)
|
||||||
|
#define MCHP_I2SMCC_MRA_WIRECFG_TDM(pin) (((pin) << 4) & \
|
||||||
|
MCHP_I2SMCC_MRA_WIRECFG_MASK)
|
||||||
#define MCHP_I2SMCC_MRA_WIRECFG_I2S_1_TDM_0 (0 << 4)
|
#define MCHP_I2SMCC_MRA_WIRECFG_I2S_1_TDM_0 (0 << 4)
|
||||||
#define MCHP_I2SMCC_MRA_WIRECFG_I2S_2_TDM_1 (1 << 4)
|
#define MCHP_I2SMCC_MRA_WIRECFG_I2S_2_TDM_1 (1 << 4)
|
||||||
#define MCHP_I2SMCC_MRA_WIRECFG_I2S_4_TDM_2 (2 << 4)
|
#define MCHP_I2SMCC_MRA_WIRECFG_I2S_4_TDM_2 (2 << 4)
|
||||||
@ -245,6 +247,7 @@ struct mchp_i2s_mcc_dev {
|
|||||||
unsigned int frame_length;
|
unsigned int frame_length;
|
||||||
int tdm_slots;
|
int tdm_slots;
|
||||||
int channels;
|
int channels;
|
||||||
|
u8 tdm_data_pair;
|
||||||
unsigned int gclk_use:1;
|
unsigned int gclk_use:1;
|
||||||
unsigned int gclk_running:1;
|
unsigned int gclk_running:1;
|
||||||
unsigned int tx_rdy:1;
|
unsigned int tx_rdy:1;
|
||||||
@ -589,6 +592,8 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
|
|||||||
if (!frame_length)
|
if (!frame_length)
|
||||||
frame_length = 2 * params_physical_width(params);
|
frame_length = 2 * params_physical_width(params);
|
||||||
} else if (dev->fmt & SND_SOC_DAIFMT_DSP_A) {
|
} else if (dev->fmt & SND_SOC_DAIFMT_DSP_A) {
|
||||||
|
mra |= MCHP_I2SMCC_MRA_WIRECFG_TDM(dev->tdm_data_pair);
|
||||||
|
|
||||||
if (dev->tdm_slots) {
|
if (dev->tdm_slots) {
|
||||||
if (channels % 2 && channels * 2 <= dev->tdm_slots) {
|
if (channels % 2 && channels * 2 <= dev->tdm_slots) {
|
||||||
/*
|
/*
|
||||||
@ -914,6 +919,45 @@ static const struct of_device_id mchp_i2s_mcc_dt_ids[] = {
|
|||||||
MODULE_DEVICE_TABLE(of, mchp_i2s_mcc_dt_ids);
|
MODULE_DEVICE_TABLE(of, mchp_i2s_mcc_dt_ids);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int mchp_i2s_mcc_soc_data_parse(struct platform_device *pdev,
|
||||||
|
struct mchp_i2s_mcc_dev *dev)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!dev->soc) {
|
||||||
|
dev_err(&pdev->dev, "failed to get soc data\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->soc->data_pin_pair_num == 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err = of_property_read_u8(pdev->dev.of_node, "microchip,tdm-data-pair",
|
||||||
|
&dev->tdm_data_pair);
|
||||||
|
if (err < 0 && err != -EINVAL) {
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"bad property data for 'microchip,tdm-data-pair': %d",
|
||||||
|
err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (err == -EINVAL) {
|
||||||
|
dev_info(&pdev->dev,
|
||||||
|
"'microchip,tdm-data-pair' not found; assuming DIN/DOUT 0 for TDM\n");
|
||||||
|
dev->tdm_data_pair = 0;
|
||||||
|
} else {
|
||||||
|
if (dev->tdm_data_pair > dev->soc->data_pin_pair_num - 1) {
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"invalid value for 'microchip,tdm-data-pair': %d\n",
|
||||||
|
dev->tdm_data_pair);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
dev_dbg(&pdev->dev, "TMD format on DIN/DOUT %d pins\n",
|
||||||
|
dev->tdm_data_pair);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mchp_i2s_mcc_probe(struct platform_device *pdev)
|
static int mchp_i2s_mcc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct mchp_i2s_mcc_dev *dev;
|
struct mchp_i2s_mcc_dev *dev;
|
||||||
@ -966,10 +1010,10 @@ static int mchp_i2s_mcc_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev->soc = of_device_get_match_data(&pdev->dev);
|
dev->soc = of_device_get_match_data(&pdev->dev);
|
||||||
if (!dev->soc) {
|
err = mchp_i2s_mcc_soc_data_parse(pdev, dev);
|
||||||
dev_err(&pdev->dev, "failed to get soc data\n");
|
if (err < 0)
|
||||||
return -ENODEV;
|
return err;
|
||||||
}
|
|
||||||
dev->dev = &pdev->dev;
|
dev->dev = &pdev->dev;
|
||||||
dev->regmap = regmap;
|
dev->regmap = regmap;
|
||||||
platform_set_drvdata(pdev, dev);
|
platform_set_drvdata(pdev, dev);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user