aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/at91/patches-5.10/152-ASoC-mchp-i2s-mcc-Add-support-to-select-TDM-pins.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/at91/patches-5.10/152-ASoC-mchp-i2s-mcc-Add-support-to-select-TDM-pins.patch')
-rw-r--r--target/linux/at91/patches-5.10/152-ASoC-mchp-i2s-mcc-Add-support-to-select-TDM-pins.patch113
1 files changed, 113 insertions, 0 deletions
diff --git a/target/linux/at91/patches-5.10/152-ASoC-mchp-i2s-mcc-Add-support-to-select-TDM-pins.patch b/target/linux/at91/patches-5.10/152-ASoC-mchp-i2s-mcc-Add-support-to-select-TDM-pins.patch
new file mode 100644
index 0000000000..b4f1635e68
--- /dev/null
+++ b/target/linux/at91/patches-5.10/152-ASoC-mchp-i2s-mcc-Add-support-to-select-TDM-pins.patch
@@ -0,0 +1,113 @@
+From 2bbdc5b38603384996271a8817b0578a2360af2f Mon Sep 17 00:00:00 2001
+From: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
+Date: Mon, 1 Mar 2021 19:09:03 +0200
+Subject: [PATCH 152/247] 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>
+---
+ sound/soc/atmel/mchp-i2s-mcc.c | 52 +++++++++++++++++++++++++++++++---
+ 1 file changed, 48 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
+index dca4fd1e2dfd..0818fa864f0e 100644
+--- a/sound/soc/atmel/mchp-i2s-mcc.c
++++ b/sound/soc/atmel/mchp-i2s-mcc.c
+@@ -100,6 +100,8 @@
+ #define MCHP_I2SMCC_MRA_DATALENGTH_8_BITS_COMPACT (7 << 1)
+
+ #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_2_TDM_1 (1 << 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;
+ int tdm_slots;
+ int channels;
++ u8 tdm_data_pair;
+ unsigned int gclk_use:1;
+ unsigned int gclk_running: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)
+ frame_length = 2 * params_physical_width(params);
+ } else if (dev->fmt & SND_SOC_DAIFMT_DSP_A) {
++ mra |= MCHP_I2SMCC_MRA_WIRECFG_TDM(dev->tdm_data_pair);
++
+ if (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);
+ #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)
+ {
+ 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);
+- if (!dev->soc) {
+- dev_err(&pdev->dev, "failed to get soc data\n");
+- return -ENODEV;
+- }
++ err = mchp_i2s_mcc_soc_data_parse(pdev, dev);
++ if (err < 0)
++ return err;
++
+ dev->dev = &pdev->dev;
+ dev->regmap = regmap;
+ platform_set_drvdata(pdev, dev);
+--
+2.32.0
+