diff options
author | Yangbo Lu <yangbo.lu@nxp.com> | 2020-04-10 10:47:05 +0800 |
---|---|---|
committer | Petr Štetiar <ynezz@true.cz> | 2020-05-07 12:53:06 +0200 |
commit | cddd4591404fb4c53dc0b3c0b15b942cdbed4356 (patch) | |
tree | 392c1179de46b0f804e3789edca19069b64e6b44 /target/linux/layerscape/patches-5.4/801-audio-0037-MLK-16224-4-ASoC-fsl_sai-support-multi-fifo-and-DSD.patch | |
parent | d1d2c0b5579ea4f69a42246c9318539d61ba1999 (diff) | |
download | upstream-cddd4591404fb4c53dc0b3c0b15b942cdbed4356.tar.gz upstream-cddd4591404fb4c53dc0b3c0b15b942cdbed4356.tar.bz2 upstream-cddd4591404fb4c53dc0b3c0b15b942cdbed4356.zip |
layerscape: add patches-5.4
Add patches for linux-5.4. The patches are from NXP LSDK-20.04 release
which was tagged LSDK-20.04-V5.4.
https://source.codeaurora.org/external/qoriq/qoriq-components/linux/
For boards LS1021A-IOT, and Traverse-LS1043 which are not involved in
LSDK, port the dts patches from 4.14.
The patches are sorted into the following categories:
301-arch-xxxx
302-dts-xxxx
303-core-xxxx
701-net-xxxx
801-audio-xxxx
802-can-xxxx
803-clock-xxxx
804-crypto-xxxx
805-display-xxxx
806-dma-xxxx
807-gpio-xxxx
808-i2c-xxxx
809-jailhouse-xxxx
810-keys-xxxx
811-kvm-xxxx
812-pcie-xxxx
813-pm-xxxx
814-qe-xxxx
815-sata-xxxx
816-sdhc-xxxx
817-spi-xxxx
818-thermal-xxxx
819-uart-xxxx
820-usb-xxxx
821-vfio-xxxx
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Diffstat (limited to 'target/linux/layerscape/patches-5.4/801-audio-0037-MLK-16224-4-ASoC-fsl_sai-support-multi-fifo-and-DSD.patch')
-rw-r--r-- | target/linux/layerscape/patches-5.4/801-audio-0037-MLK-16224-4-ASoC-fsl_sai-support-multi-fifo-and-DSD.patch | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/801-audio-0037-MLK-16224-4-ASoC-fsl_sai-support-multi-fifo-and-DSD.patch b/target/linux/layerscape/patches-5.4/801-audio-0037-MLK-16224-4-ASoC-fsl_sai-support-multi-fifo-and-DSD.patch new file mode 100644 index 0000000000..033ab0d06b --- /dev/null +++ b/target/linux/layerscape/patches-5.4/801-audio-0037-MLK-16224-4-ASoC-fsl_sai-support-multi-fifo-and-DSD.patch @@ -0,0 +1,326 @@ +From 87f734fa8214b4ddbfdac9b7ac5dc75a3d86badb Mon Sep 17 00:00:00 2001 +From: Shengjiu Wang <shengjiu.wang@nxp.com> +Date: Tue, 23 Jan 2018 13:26:37 +0800 +Subject: [PATCH] MLK-16224-4: ASoC: fsl_sai: support multi fifo and DSD + +The codec always mux the LRCLK pin to DSD data line, so when +we want to support DSD, the pinmux is different. For two channel +DSD, the DSDL is mapped to TX0, but the DSDR is mapped to TX4, +there is address offset for the fifo address of TX0 and TX4, TX4's +fifo is not adjacent to TX0's. + +Usually, if mapping is TX0 and TX1, that will be easy for SAI +and SDMA to handle, that SAI can use the FIFO combine mode, SDMA +can use the normal script. + +so for DSD: +1. The SDMA should use the multi-fifo script, and SAI can't +use the FIFO combine mode. +2. driver should to check the dts configuration(fsl,dataline) for +which dataline is used corrently +3. maxburst is the multiply of datalines +4. each channel of DSD occupy one data lane +5. according to data lane, set TRCE bits + +Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> +Reviewed-by: Viorel Suman <viorel.suman@nxp.com> +--- + sound/soc/fsl/fsl_sai.c | 162 +++++++++++++++++++++++++++++++++++++++++++++--- + sound/soc/fsl/fsl_sai.h | 12 +++- + 2 files changed, 164 insertions(+), 10 deletions(-) + +--- a/sound/soc/fsl/fsl_sai.c ++++ b/sound/soc/fsl/fsl_sai.c +@@ -267,6 +267,7 @@ static int fsl_sai_set_dai_fmt_tr(struct + if (!sai->is_lsb_first) + val_cr4 |= FSL_SAI_CR4_MF; + ++ sai->is_dsp_mode = false; + /* DAI mode */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: +@@ -305,6 +306,11 @@ static int fsl_sai_set_dai_fmt_tr(struct + val_cr2 |= FSL_SAI_CR2_BCP; + sai->is_dsp_mode = true; + break; ++ case SND_SOC_DAIFMT_PDM: ++ val_cr2 |= FSL_SAI_CR2_BCP; ++ val_cr4 &= ~FSL_SAI_CR4_MF; ++ sai->is_dsp_mode = true; ++ break; + case SND_SOC_DAIFMT_RIGHT_J: + /* To be done */ + default: +@@ -492,12 +498,38 @@ static int fsl_sai_hw_params(struct snd_ + u32 slot_width = word_width; + u32 pins; + int ret; ++ int i; ++ int trce_mask = 0; ++ snd_pcm_format_t format = params_format(params); + + if (sai->slots) + slots = sai->slots; + + pins = DIV_ROUND_UP(channels, slots); + ++ if (format == SNDRV_PCM_FORMAT_DSD_U8 || ++ format == SNDRV_PCM_FORMAT_DSD_U16_LE || ++ format == SNDRV_PCM_FORMAT_DSD_U16_BE || ++ format == SNDRV_PCM_FORMAT_DSD_U32_LE || ++ format == SNDRV_PCM_FORMAT_DSD_U32_BE) { ++ sai->is_dsd = true; ++ ++ if (!IS_ERR_OR_NULL(sai->pins_dsd)) { ++ ret = pinctrl_select_state(sai->pinctrl, sai->pins_dsd); ++ if (ret) { ++ dev_err(cpu_dai->dev, ++ "failed to set proper pins state: %d\n", ret); ++ return ret; ++ } ++ } ++ } else { ++ pinctrl_pm_select_default_state(cpu_dai->dev); ++ sai->is_dsd = false; ++ } ++ ++ if (sai->is_dsd) ++ pins = channels; ++ + if (sai->slot_width) + slot_width = sai->slot_width; + +@@ -527,7 +559,7 @@ static int fsl_sai_hw_params(struct snd_ + val_cr5 |= FSL_SAI_CR5_WNW(slot_width); + val_cr5 |= FSL_SAI_CR5_W0W(slot_width); + +- if (sai->is_lsb_first) ++ if (sai->is_lsb_first || sai->is_dsd) + val_cr5 |= FSL_SAI_CR5_FBT(0); + else + val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1); +@@ -560,17 +592,71 @@ static int fsl_sai_hw_params(struct snd_ + } + + if (sai->soc->dataline != 0x1) { +- if (sai->dataline[tx] <= 1) ++ ++ if (sai->dataline[tx] <= 1 || sai->is_multi_lane) + regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, offset), + FSL_SAI_CR4_FCOMB_MASK, 0); + else + regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, offset), + FSL_SAI_CR4_FCOMB_MASK, FSL_SAI_CR4_FCOMB_SOFT); ++ ++ if (sai->is_multi_lane) { ++ if (tx) { ++ sai->dma_params_tx.maxburst = ++ FSL_SAI_MAXBURST_TX * pins; ++ if (sai->is_dsd) ++ sai->dma_params_tx.fifo_num = pins + ++ (sai->dataline_off_dsd[tx] << 8); ++ else ++ sai->dma_params_tx.fifo_num = pins + ++ (sai->dataline_off[tx] << 8); ++ } else { ++ sai->dma_params_rx.maxburst = ++ FSL_SAI_MAXBURST_RX * pins; ++ if (sai->is_dsd) ++ sai->dma_params_rx.fifo_num = pins + ++ (sai->dataline_off_dsd[tx] << 8); ++ else ++ sai->dma_params_rx.fifo_num = pins + ++ (sai->dataline_off[tx] << 8); ++ } ++ } ++ ++ snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, ++ &sai->dma_params_rx); + } + +- regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, offset), ++ if (sai->is_dsd) { ++ if (__sw_hweight8(sai->dataline_dsd[tx] & 0xFF) < pins) { ++ dev_err(cpu_dai->dev, "channel not supported\n"); ++ return -EINVAL; ++ } ++ /*find a proper tcre setting*/ ++ for (i = 0; i < 8; i++) { ++ trce_mask = (1 << (i + 1)) - 1; ++ if (__sw_hweight8(sai->dataline_dsd[tx] & trce_mask) == pins) ++ break; ++ } ++ ++ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, offset), + FSL_SAI_CR3_TRCE_MASK, +- FSL_SAI_CR3_TRCE((sai->dataline[tx] & ((1 << pins) - 1)))); ++ FSL_SAI_CR3_TRCE((sai->dataline_dsd[tx] & trce_mask))); ++ } else { ++ if (__sw_hweight8(sai->dataline[tx] & 0xFF) < pins) { ++ dev_err(cpu_dai->dev, "channel not supported\n"); ++ return -EINVAL; ++ } ++ /*find a proper tcre setting*/ ++ for (i = 0; i < 8; i++) { ++ trce_mask = (1 << (i + 1)) - 1; ++ if (__sw_hweight8(sai->dataline[tx] & trce_mask) == pins) ++ break; ++ } ++ ++ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, offset), ++ FSL_SAI_CR3_TRCE_MASK, ++ FSL_SAI_CR3_TRCE((sai->dataline[tx] & trce_mask))); ++ } + + regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, offset), + FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, +@@ -610,9 +696,18 @@ static int fsl_sai_trigger(struct snd_pc + unsigned char offset = sai->soc->reg_offset; + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + u8 channels = substream->runtime->channels; ++ u32 slots = (channels == 1) ? 2 : channels; + u32 xcsr, count = 100; +- int i; ++ u32 pins; ++ int i = 0, j = 0, k = 0; ++ ++ if (sai->slots) ++ slots = sai->slots; ++ ++ pins = DIV_ROUND_UP(channels, slots); + ++ if (sai->is_dsd) ++ pins = channels; + /* + * Asynchronous mode: Clear SYNC for both Tx and Rx. + * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx. +@@ -631,10 +726,19 @@ static int fsl_sai_trigger(struct snd_pc + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: +- for (i = 0; tx && i < channels; i++) +- regmap_write(sai->regmap, FSL_SAI_TDR0, 0x0); +- if (tx) +- udelay(10); ++ ++ for (i = 0; tx && i < channels; i++) { ++ while (tx && i < channels) ++ if (sai->dataline[tx] & (1 << j)) { ++ regmap_write(sai->regmap, FSL_SAI_TDR0 + j * 0x4, 0x0); ++ i++; ++ k++; ++ } ++ j++; ++ ++ if (k%pins == 0) ++ j = 0; ++ } + + regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, offset), + FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); +@@ -994,6 +1098,7 @@ static int fsl_sai_probe(struct platform + char tmp[8]; + int irq, ret, i; + int index; ++ int firstbitidx, nextbitidx; + struct regmap_config fsl_sai_regmap_config = fsl_sai_v2_regmap_config; + unsigned long irqflags = 0; + +@@ -1048,6 +1153,9 @@ static int fsl_sai_probe(struct platform + } + } + ++ if (of_find_property(np, "fsl,sai-multi-lane", NULL)) ++ sai->is_multi_lane = true; ++ + /*dataline mask for rx and tx*/ + ret = of_property_read_u32_index(np, "fsl,dataline", 0, &sai->dataline[0]); + if (ret) +@@ -1062,6 +1170,37 @@ static int fsl_sai_probe(struct platform + return -EINVAL; + } + ++ for (i = 0; i < 2; i++) { ++ firstbitidx = find_first_bit((const unsigned long *)&sai->dataline[i], 8); ++ nextbitidx = find_next_bit((const unsigned long *)&sai->dataline[i], 8, firstbitidx+1); ++ sai->dataline_off[i] = nextbitidx - firstbitidx - 1; ++ ++ if (sai->dataline_off[i] < 0 || sai->dataline_off[i] >= 7) ++ sai->dataline_off[i] = 0; ++ } ++ ++ ret = of_property_read_u32_index(np, "fsl,dataline,dsd", 0, &sai->dataline_dsd[0]); ++ if (ret) ++ sai->dataline_dsd[0] = 1; ++ ++ ret = of_property_read_u32_index(np, "fsl,dataline,dsd", 1, &sai->dataline_dsd[1]); ++ if (ret) ++ sai->dataline_dsd[1] = 1; ++ ++ if ((sai->dataline_dsd[0] & (~sai->soc->dataline)) || sai->dataline_dsd[1] & (~sai->soc->dataline)) { ++ dev_err(&pdev->dev, "dataline setting error, Mask is 0x%x\n", sai->soc->dataline); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < 2; i++) { ++ firstbitidx = find_first_bit((const unsigned long *)&sai->dataline_dsd[i], 8); ++ nextbitidx = find_next_bit((const unsigned long *)&sai->dataline_dsd[i], 8, firstbitidx+1); ++ sai->dataline_off_dsd[i] = nextbitidx - firstbitidx - 1; ++ ++ if (sai->dataline_off_dsd[i] < 0 || sai->dataline_off_dsd[i] >= 7) ++ sai->dataline_off_dsd[i] = 0; ++ } ++ + if ((of_find_property(np, "fsl,i2s-xtor", NULL) != NULL) || + (of_find_property(np, "fsl,txm-rxs", NULL) != NULL)) + { +@@ -1143,6 +1282,11 @@ static int fsl_sai_probe(struct platform + sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; + sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; + ++ sai->pinctrl = devm_pinctrl_get(&pdev->dev); ++ ++ if (!IS_ERR_OR_NULL(sai->pinctrl)) ++ sai->pins_dsd = pinctrl_lookup_state(sai->pinctrl, "dsd"); ++ + platform_set_drvdata(pdev, sai); + + pm_runtime_enable(&pdev->dev); +--- a/sound/soc/fsl/fsl_sai.h ++++ b/sound/soc/fsl/fsl_sai.h +@@ -11,7 +11,10 @@ + + #define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ +- SNDRV_PCM_FMTBIT_S32_LE) ++ SNDRV_PCM_FMTBIT_S32_LE |\ ++ SNDRV_PCM_FMTBIT_DSD_U8 |\ ++ SNDRV_PCM_FMTBIT_DSD_U16_LE |\ ++ SNDRV_PCM_FMTBIT_DSD_U32_LE) + + /* SAI Register Map Register */ + #define FSL_SAI_TCSR(offset) (0x00 + offset) /* SAI Transmit Control */ +@@ -172,9 +175,14 @@ struct fsl_sai { + bool slave_mode[2]; + bool is_lsb_first; + bool is_dsp_mode; ++ bool is_multi_lane; + bool synchronous[2]; + bool is_stream_opened[2]; ++ bool is_dsd; + unsigned int dataline[2]; ++ unsigned int dataline_dsd[2]; ++ unsigned int dataline_off[2]; ++ unsigned int dataline_off_dsd[2]; + unsigned int masterflag[2]; + + unsigned int mclk_id[2]; +@@ -187,6 +195,8 @@ struct fsl_sai { + struct snd_dmaengine_dai_dma_data dma_params_tx; + const struct fsl_sai_soc_data *soc; + struct pm_qos_request pm_qos_req; ++ struct pinctrl *pinctrl; ++ struct pinctrl_state *pins_dsd; + }; + + #define TX 1 |