Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Support HDMI audio on NVIDIA Tegra20

Merge series from Dmitry Osipenko <digetx@gmail.com>:

This series revives Tegra20 S/PDIF driver which was upstreamed long time
ago, but never was used. It also turns Tegra DRM HDMI driver into HDMI
audio CODEC provider. Finally, HDMI audio is enabled in device-trees.
For now the audio is enable only for Acer A500 tablet and Toshiba AC100
netbook because they're already supported by upstream, later on ASUS TF101
tablet will join them.

I based S/PDIF patches on Arnd's Bergmann patch from a separate series [1]
that removes obsolete slave_id. This eases merging of the patches by
removing the merge conflict. This is a note for Mark Brown.

I also based this series on top of power management series [2]. I.e. [2]
should be applied first, otherwise "Add S/PDIF node to Tegra20 device-tree"
patch should have merge conflict. This is a note for Thierry.

[1] https://patchwork.ozlabs.org/project/linux-tegra/list/?series=273312
[2] https://patchwork.ozlabs.org/project/linux-tegra/list/?series=274534

Changelog:

v4: - Added patches that update multi_v7_defconfig with the enabled S/PDIF
and APB DMA drivers.

v3: - Renamed S/PDIF device-tree clocks as was suggested by Rob Herring.

- Added r-bs and acks that were given by Rob Herring to v2.

v2: - Corrected I2S yaml problem that was reported by the DT bot for v1
by removing the non-existent required clock-names property.

- Removed assigned-clocks property from S/PDIF yaml since this property
is now inherited from the clocks property.

- Reordered the "tegra20: spdif: Set FIFO trigger level" patch, making
it the first sound/soc patch in the series, like it was suggested by
Mark Brown in the comment to v1. Also reworded commit message of this
patch to *not* make it looks like it should be backported to stable
kernels.

Arnd Bergmann (1):
ASoC: tegra20-spdif: stop setting slave_id

Dmitry Osipenko (21):
ASoC: dt-bindings: Add binding for Tegra20 S/PDIF
ASoC: dt-bindings: tegra20-i2s: Convert to schema
ASoC: dt-bindings: tegra20-i2s: Document new nvidia,fixed-parent-rate
property
dt-bindings: host1x: Document optional HDMI sound-dai-cells
ASoC: tegra20: spdif: Set FIFO trigger level
ASoC: tegra20: spdif: Support device-tree
ASoC: tegra20: spdif: Improve driver's code
ASoC: tegra20: spdif: Use more resource-managed helpers
ASoC: tegra20: spdif: Reset hardware
ASoC: tegra20: spdif: Support system suspend
ASoC: tegra20: spdif: Filter out unsupported rates
ASoC: tegra20: i2s: Filter out unsupported rates
drm/tegra: hdmi: Unwind tegra_hdmi_init() errors
drm/tegra: hdmi: Register audio CODEC on Tegra20
ARM: tegra_defconfig: Enable S/PDIF driver
ARM: config: multi v7: Enable NVIDIA Tegra20 S/PDIF driver
ARM: config: multi v7: Enable NVIDIA Tegra20 APB DMA driver
ARM: tegra: Add S/PDIF node to Tegra20 device-tree
ARM: tegra: Add HDMI audio graph to Tegra20 device-tree
ARM: tegra: acer-a500: Enable S/PDIF and HDMI audio
ARM: tegra: paz00: Enable S/PDIF and HDMI audio

.../display/tegra/nvidia,tegra20-host1x.txt | 1 +
.../bindings/sound/nvidia,tegra20-i2s.txt | 30 ---
.../bindings/sound/nvidia,tegra20-i2s.yaml | 77 +++++++
.../bindings/sound/nvidia,tegra20-spdif.yaml | 85 ++++++++
.../boot/dts/tegra20-acer-a500-picasso.dts | 8 +
arch/arm/boot/dts/tegra20-paz00.dts | 8 +
arch/arm/boot/dts/tegra20.dtsi | 40 +++-
arch/arm/configs/multi_v7_defconfig | 2 +
arch/arm/configs/tegra_defconfig | 1 +
drivers/gpu/drm/tegra/Kconfig | 3 +
drivers/gpu/drm/tegra/hdmi.c | 168 +++++++++++++--
sound/soc/tegra/tegra20_i2s.c | 49 +++++
sound/soc/tegra/tegra20_spdif.c | 197 ++++++++++++------
sound/soc/tegra/tegra20_spdif.h | 1 +
sound/soc/tegra/tegra_pcm.c | 6 +
sound/soc/tegra/tegra_pcm.h | 1 +
16 files changed, 574 insertions(+), 103 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra20-i2s.txt
create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra20-i2s.yaml
create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml

--
2.33.1

+475 -150
-30
Documentation/devicetree/bindings/sound/nvidia,tegra20-i2s.txt
··· 1 - NVIDIA Tegra 20 I2S controller 2 - 3 - Required properties: 4 - - compatible : "nvidia,tegra20-i2s" 5 - - reg : Should contain I2S registers location and length 6 - - interrupts : Should contain I2S interrupt 7 - - resets : Must contain an entry for each entry in reset-names. 8 - See ../reset/reset.txt for details. 9 - - reset-names : Must include the following entries: 10 - - i2s 11 - - dmas : Must contain an entry for each entry in clock-names. 12 - See ../dma/dma.txt for details. 13 - - dma-names : Must include the following entries: 14 - - rx 15 - - tx 16 - - clocks : Must contain one entry, for the module clock. 17 - See ../clocks/clock-bindings.txt for details. 18 - 19 - Example: 20 - 21 - i2s@70002800 { 22 - compatible = "nvidia,tegra20-i2s"; 23 - reg = <0x70002800 0x200>; 24 - interrupts = < 45 >; 25 - clocks = <&tegra_car 11>; 26 - resets = <&tegra_car 11>; 27 - reset-names = "i2s"; 28 - dmas = <&apbdma 21>, <&apbdma 21>; 29 - dma-names = "rx", "tx"; 30 - };
+77
Documentation/devicetree/bindings/sound/nvidia,tegra20-i2s.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/sound/nvidia,tegra20-i2s.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: NVIDIA Tegra20 I2S Controller 8 + 9 + description: | 10 + The I2S Controller streams synchronous serial audio data between system 11 + memory and an external audio device. The controller supports the I2S Left 12 + Justified Mode, Right Justified Mode, and DSP mode formats. 13 + 14 + maintainers: 15 + - Thierry Reding <treding@nvidia.com> 16 + - Jon Hunter <jonathanh@nvidia.com> 17 + 18 + properties: 19 + compatible: 20 + const: nvidia,tegra20-i2s 21 + 22 + reg: 23 + maxItems: 1 24 + 25 + resets: 26 + maxItems: 1 27 + 28 + reset-names: 29 + const: i2s 30 + 31 + interrupts: 32 + maxItems: 1 33 + 34 + clocks: 35 + minItems: 1 36 + 37 + dmas: 38 + minItems: 2 39 + 40 + dma-names: 41 + items: 42 + - const: rx 43 + - const: tx 44 + 45 + nvidia,fixed-parent-rate: 46 + description: | 47 + Specifies whether board prefers parent clock to stay at a fixed rate. 48 + This allows multiple Tegra20 audio components work simultaneously by 49 + limiting number of supportable audio rates. 50 + type: boolean 51 + 52 + required: 53 + - compatible 54 + - reg 55 + - resets 56 + - reset-names 57 + - interrupts 58 + - clocks 59 + - dmas 60 + - dma-names 61 + 62 + additionalProperties: false 63 + 64 + examples: 65 + - | 66 + i2s@70002800 { 67 + compatible = "nvidia,tegra20-i2s"; 68 + reg = <0x70002800 0x200>; 69 + interrupts = <45>; 70 + clocks = <&tegra_car 11>; 71 + resets = <&tegra_car 11>; 72 + reset-names = "i2s"; 73 + dmas = <&apbdma 21>, <&apbdma 21>; 74 + dma-names = "rx", "tx"; 75 + }; 76 + 77 + ...
+85
Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/sound/nvidia,tegra20-spdif.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: NVIDIA Tegra20 S/PDIF Controller 8 + 9 + description: | 10 + The S/PDIF controller supports both input and output in serial audio 11 + digital interface format. The input controller can digitally recover 12 + a clock from the received stream. The S/PDIF controller is also used 13 + to generate the embedded audio for HDMI output channel. 14 + 15 + maintainers: 16 + - Thierry Reding <treding@nvidia.com> 17 + - Jon Hunter <jonathanh@nvidia.com> 18 + 19 + properties: 20 + compatible: 21 + const: nvidia,tegra20-spdif 22 + 23 + reg: 24 + maxItems: 1 25 + 26 + resets: 27 + maxItems: 1 28 + 29 + interrupts: 30 + maxItems: 1 31 + 32 + clocks: 33 + minItems: 2 34 + 35 + clock-names: 36 + items: 37 + - const: out 38 + - const: in 39 + 40 + dmas: 41 + minItems: 2 42 + 43 + dma-names: 44 + items: 45 + - const: rx 46 + - const: tx 47 + 48 + "#sound-dai-cells": 49 + const: 0 50 + 51 + nvidia,fixed-parent-rate: 52 + description: | 53 + Specifies whether board prefers parent clock to stay at a fixed rate. 54 + This allows multiple Tegra20 audio components work simultaneously by 55 + limiting number of supportable audio rates. 56 + type: boolean 57 + 58 + required: 59 + - compatible 60 + - reg 61 + - resets 62 + - interrupts 63 + - clocks 64 + - clock-names 65 + - dmas 66 + - dma-names 67 + - "#sound-dai-cells" 68 + 69 + additionalProperties: false 70 + 71 + examples: 72 + - | 73 + spdif@70002400 { 74 + compatible = "nvidia,tegra20-spdif"; 75 + reg = <0x70002400 0x200>; 76 + interrupts = <77>; 77 + clocks = <&clk 99>, <&clk 98>; 78 + clock-names = "out", "in"; 79 + resets = <&rst 10>; 80 + dmas = <&apbdma 3>, <&apbdma 3>; 81 + dma-names = "rx", "tx"; 82 + #sound-dai-cells = <0>; 83 + }; 84 + 85 + ...
-6
drivers/dma/mmp_pdma.c
··· 727 727 728 728 chan->dir = direction; 729 729 chan->dev_addr = addr; 730 - /* FIXME: drivers should be ported over to use the filter 731 - * function. Once that's done, the following two lines can 732 - * be removed. 733 - */ 734 - if (cfg->slave_id) 735 - chan->drcmr = cfg->slave_id; 736 730 737 731 return 0; 738 732 }
-7
drivers/dma/pxa_dma.c
··· 909 909 *dcmd |= PXA_DCMD_BURST16; 910 910 else if (maxburst == 32) 911 911 *dcmd |= PXA_DCMD_BURST32; 912 - 913 - /* FIXME: drivers should be ported over to use the filter 914 - * function. Once that's done, the following two lines can 915 - * be removed. 916 - */ 917 - if (chan->cfg.slave_id) 918 - chan->drcmr = chan->cfg.slave_id; 919 912 } 920 913 921 914 static struct dma_async_tx_descriptor *
+49 -7
drivers/dma/qcom/qcom_adm.c
··· 8 8 #include <linux/device.h> 9 9 #include <linux/dmaengine.h> 10 10 #include <linux/dma-mapping.h> 11 + #include <linux/dma/qcom_adm.h> 11 12 #include <linux/init.h> 12 13 #include <linux/interrupt.h> 13 14 #include <linux/io.h> ··· 141 140 142 141 struct adm_async_desc *curr_txd; 143 142 struct dma_slave_config slave; 143 + u32 crci; 144 + u32 mux; 144 145 struct list_head node; 145 146 146 147 int error; ··· 382 379 return ERR_PTR(-EINVAL); 383 380 } 384 381 385 - crci = achan->slave.slave_id & 0xf; 386 - if (!crci || achan->slave.slave_id > 0x1f) { 382 + crci = achan->crci & 0xf; 383 + if (!crci || achan->crci > 0x1f) { 387 384 dev_err(adev->dev, "invalid crci value\n"); 388 385 return ERR_PTR(-EINVAL); 389 386 } ··· 406 403 if (!async_desc) 407 404 return ERR_PTR(-ENOMEM); 408 405 409 - if (crci) 410 - async_desc->mux = achan->slave.slave_id & ADM_CRCI_MUX_SEL ? 411 - ADM_CRCI_CTL_MUX_SEL : 0; 406 + async_desc->mux = achan->mux ? ADM_CRCI_CTL_MUX_SEL : 0; 412 407 async_desc->crci = crci; 413 408 async_desc->blk_size = blk_size; 414 409 async_desc->dma_len = single_count * sizeof(struct adm_desc_hw_single) + ··· 489 488 static int adm_slave_config(struct dma_chan *chan, struct dma_slave_config *cfg) 490 489 { 491 490 struct adm_chan *achan = to_adm_chan(chan); 491 + struct qcom_adm_peripheral_config *config = cfg->peripheral_config; 492 492 unsigned long flag; 493 493 494 494 spin_lock_irqsave(&achan->vc.lock, flag); 495 495 memcpy(&achan->slave, cfg, sizeof(struct dma_slave_config)); 496 + if (cfg->peripheral_size == sizeof(config)) 497 + achan->crci = config->crci; 496 498 spin_unlock_irqrestore(&achan->vc.lock, flag); 497 499 498 500 return 0; ··· 698 694 achan->vc.desc_free = adm_dma_free_desc; 699 695 } 700 696 697 + /** 698 + * adm_dma_xlate 699 + * @dma_spec: pointer to DMA specifier as found in the device tree 700 + * @ofdma: pointer to DMA controller data 701 + * 702 + * This can use either 1-cell or 2-cell formats, the first cell 703 + * identifies the slave device, while the optional second cell 704 + * contains the crci value. 705 + * 706 + * Returns pointer to appropriate dma channel on success or NULL on error. 707 + */ 708 + static struct dma_chan *adm_dma_xlate(struct of_phandle_args *dma_spec, 709 + struct of_dma *ofdma) 710 + { 711 + struct dma_device *dev = ofdma->of_dma_data; 712 + struct dma_chan *chan, *candidate = NULL; 713 + struct adm_chan *achan; 714 + 715 + if (!dev || dma_spec->args_count > 2) 716 + return NULL; 717 + 718 + list_for_each_entry(chan, &dev->channels, device_node) 719 + if (chan->chan_id == dma_spec->args[0]) { 720 + candidate = chan; 721 + break; 722 + } 723 + 724 + if (!candidate) 725 + return NULL; 726 + 727 + achan = to_adm_chan(candidate); 728 + if (dma_spec->args_count == 2) 729 + achan->crci = dma_spec->args[1]; 730 + else 731 + achan->crci = 0; 732 + 733 + return dma_get_slave_channel(candidate); 734 + } 735 + 701 736 static int adm_dma_probe(struct platform_device *pdev) 702 737 { 703 738 struct adm_device *adev; ··· 881 838 goto err_disable_clks; 882 839 } 883 840 884 - ret = of_dma_controller_register(pdev->dev.of_node, 885 - of_dma_xlate_by_chan_id, 841 + ret = of_dma_controller_register(pdev->dev.of_node, adm_dma_xlate, 886 842 &adev->common); 887 843 if (ret) 888 844 goto err_unregister_dma;
-8
drivers/dma/sh/shdma-base.c
··· 787 787 return -EINVAL; 788 788 789 789 /* 790 - * overriding the slave_id through dma_slave_config is deprecated, 791 - * but possibly some out-of-tree drivers still do it. 792 - */ 793 - if (WARN_ON_ONCE(config->slave_id && 794 - config->slave_id != schan->real_slave_id)) 795 - schan->real_slave_id = config->slave_id; 796 - 797 - /* 798 790 * We could lock this, but you shouldn't be configuring the 799 791 * channel, while using it... 800 792 */
-3
drivers/dma/sprd-dma.c
··· 795 795 return dst_datawidth; 796 796 } 797 797 798 - if (slave_cfg->slave_id) 799 - schan->dev_id = slave_cfg->slave_id; 800 - 801 798 hw->cfg = SPRD_DMA_DONOT_WAIT_BDONE << SPRD_DMA_WAIT_BDONE_OFFSET; 802 799 803 800 /*
-6
drivers/dma/tegra20-apb-dma.c
··· 343 343 } 344 344 345 345 memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig)); 346 - if (tdc->slave_id == TEGRA_APBDMA_SLAVE_ID_INVALID && 347 - sconfig->device_fc) { 348 - if (sconfig->slave_id > TEGRA_APBDMA_CSR_REQ_SEL_MASK) 349 - return -EINVAL; 350 - tdc->slave_id = sconfig->slave_id; 351 - } 352 346 tdc->config_init = true; 353 347 354 348 return 0;
+11 -6
drivers/dma/xilinx/xilinx_dpdma.c
··· 12 12 #include <linux/clk.h> 13 13 #include <linux/debugfs.h> 14 14 #include <linux/delay.h> 15 + #include <linux/dma/xilinx_dpdma.h> 15 16 #include <linux/dmaengine.h> 16 17 #include <linux/dmapool.h> 17 18 #include <linux/interrupt.h> ··· 1274 1273 struct dma_slave_config *config) 1275 1274 { 1276 1275 struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan); 1276 + struct xilinx_dpdma_peripheral_config *pconfig; 1277 1277 unsigned long flags; 1278 1278 1279 1279 /* ··· 1284 1282 * fixed both on the DPDMA side and on the DP controller side. 1285 1283 */ 1286 1284 1287 - spin_lock_irqsave(&chan->lock, flags); 1288 - 1289 1285 /* 1290 - * Abuse the slave_id to indicate that the channel is part of a video 1291 - * group. 1286 + * Use the peripheral_config to indicate that the channel is part 1287 + * of a video group. This requires matching use of the custom 1288 + * structure in each driver. 1292 1289 */ 1293 - if (chan->id <= ZYNQMP_DPDMA_VIDEO2) 1294 - chan->video_group = config->slave_id != 0; 1290 + pconfig = config->peripheral_config; 1291 + if (WARN_ON(pconfig && config->peripheral_size != sizeof(*pconfig))) 1292 + return -EINVAL; 1295 1293 1294 + spin_lock_irqsave(&chan->lock, flags); 1295 + if (chan->id <= ZYNQMP_DPDMA_VIDEO2 && pconfig) 1296 + chan->video_group = pconfig->video_group; 1296 1297 spin_unlock_irqrestore(&chan->lock, flags); 1297 1298 1298 1299 return 0;
+7 -2
drivers/gpu/drm/xlnx/zynqmp_disp.c
··· 24 24 25 25 #include <linux/clk.h> 26 26 #include <linux/delay.h> 27 + #include <linux/dma/xilinx_dpdma.h> 27 28 #include <linux/dma-mapping.h> 28 29 #include <linux/dmaengine.h> 29 30 #include <linux/module.h> ··· 1059 1058 zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt); 1060 1059 1061 1060 /* 1062 - * Set slave_id for each DMA channel to indicate they're part of a 1061 + * Set pconfig for each DMA channel to indicate they're part of a 1063 1062 * video group. 1064 1063 */ 1065 1064 for (i = 0; i < info->num_planes; i++) { 1066 1065 struct zynqmp_disp_layer_dma *dma = &layer->dmas[i]; 1066 + struct xilinx_dpdma_peripheral_config pconfig = { 1067 + .video_group = true, 1068 + }; 1067 1069 struct dma_slave_config config = { 1068 1070 .direction = DMA_MEM_TO_DEV, 1069 - .slave_id = 1, 1071 + .peripheral_config = &pconfig, 1072 + .peripheral_size = sizeof(pconfig), 1070 1073 }; 1071 1074 1072 1075 dmaengine_slave_config(dma->chan, &config);
-2
drivers/mmc/host/bcm2835.c
··· 1293 1293 1294 1294 host->dma_cfg_tx.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 1295 1295 host->dma_cfg_tx.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 1296 - host->dma_cfg_tx.slave_id = 13; /* DREQ channel */ 1297 1296 host->dma_cfg_tx.direction = DMA_MEM_TO_DEV; 1298 1297 host->dma_cfg_tx.src_addr = 0; 1299 1298 host->dma_cfg_tx.dst_addr = host->phys_addr + SDDATA; 1300 1299 1301 1300 host->dma_cfg_rx.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 1302 1301 host->dma_cfg_rx.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 1303 - host->dma_cfg_rx.slave_id = 13; /* DREQ channel */ 1304 1302 host->dma_cfg_rx.direction = DMA_DEV_TO_MEM; 1305 1303 host->dma_cfg_rx.src_addr = host->phys_addr + SDDATA; 1306 1304 host->dma_cfg_rx.dst_addr = 0;
+12 -2
drivers/mtd/nand/raw/qcom_nandc.c
··· 6 6 #include <linux/clk.h> 7 7 #include <linux/slab.h> 8 8 #include <linux/bitops.h> 9 + #include <linux/dma/qcom_adm.h> 9 10 #include <linux/dma-mapping.h> 10 11 #include <linux/dmaengine.h> 11 12 #include <linux/module.h> ··· 953 952 struct dma_async_tx_descriptor *dma_desc; 954 953 struct scatterlist *sgl; 955 954 struct dma_slave_config slave_conf; 955 + struct qcom_adm_peripheral_config periph_conf = {}; 956 956 enum dma_transfer_direction dir_eng; 957 957 int ret; 958 958 ··· 985 983 if (read) { 986 984 slave_conf.src_maxburst = 16; 987 985 slave_conf.src_addr = nandc->base_dma + reg_off; 988 - slave_conf.slave_id = nandc->data_crci; 986 + if (nandc->data_crci) { 987 + periph_conf.crci = nandc->data_crci; 988 + slave_conf.peripheral_config = &periph_conf; 989 + slave_conf.peripheral_size = sizeof(periph_conf); 990 + } 989 991 } else { 990 992 slave_conf.dst_maxburst = 16; 991 993 slave_conf.dst_addr = nandc->base_dma + reg_off; 992 - slave_conf.slave_id = nandc->cmd_crci; 994 + if (nandc->cmd_crci) { 995 + periph_conf.crci = nandc->cmd_crci; 996 + slave_conf.peripheral_config = &periph_conf; 997 + slave_conf.peripheral_size = sizeof(periph_conf); 998 + } 993 999 } 994 1000 995 1001 ret = dmaengine_slave_config(nandc->chan, &slave_conf);
-2
drivers/spi/spi-pic32.c
··· 370 370 cfg.src_addr_width = dma_width; 371 371 cfg.dst_addr_width = dma_width; 372 372 /* tx channel */ 373 - cfg.slave_id = pic32s->tx_irq; 374 373 cfg.direction = DMA_MEM_TO_DEV; 375 374 ret = dmaengine_slave_config(master->dma_tx, &cfg); 376 375 if (ret) { ··· 377 378 return ret; 378 379 } 379 380 /* rx channel */ 380 - cfg.slave_id = pic32s->rx_irq; 381 381 cfg.direction = DMA_DEV_TO_MEM; 382 382 ret = dmaengine_slave_config(master->dma_rx, &cfg); 383 383 if (ret)
+13 -2
drivers/tty/serial/msm_serial.c
··· 9 9 10 10 #include <linux/kernel.h> 11 11 #include <linux/atomic.h> 12 + #include <linux/dma/qcom_adm.h> 12 13 #include <linux/dma-mapping.h> 13 14 #include <linux/dmaengine.h> 14 15 #include <linux/module.h> ··· 291 290 { 292 291 struct device *dev = msm_port->uart.dev; 293 292 struct dma_slave_config conf; 293 + struct qcom_adm_peripheral_config periph_conf = {}; 294 294 struct msm_dma *dma; 295 295 u32 crci = 0; 296 296 int ret; ··· 310 308 conf.device_fc = true; 311 309 conf.dst_addr = base + UARTDM_TF; 312 310 conf.dst_maxburst = UARTDM_BURST_SIZE; 313 - conf.slave_id = crci; 311 + if (crci) { 312 + conf.peripheral_config = &periph_conf; 313 + conf.peripheral_size = sizeof(periph_conf); 314 + periph_conf.crci = crci; 315 + } 314 316 315 317 ret = dmaengine_slave_config(dma->chan, &conf); 316 318 if (ret) ··· 339 333 { 340 334 struct device *dev = msm_port->uart.dev; 341 335 struct dma_slave_config conf; 336 + struct qcom_adm_peripheral_config periph_conf = {}; 342 337 struct msm_dma *dma; 343 338 u32 crci = 0; 344 339 int ret; ··· 362 355 conf.device_fc = true; 363 356 conf.src_addr = base + UARTDM_RF; 364 357 conf.src_maxburst = UARTDM_BURST_SIZE; 365 - conf.slave_id = crci; 358 + if (crci) { 359 + conf.peripheral_config = &periph_conf; 360 + conf.peripheral_size = sizeof(periph_conf); 361 + periph_conf.crci = crci; 362 + } 366 363 367 364 ret = dmaengine_slave_config(dma->chan, &conf); 368 365 if (ret)
+12
include/linux/dma/qcom_adm.h
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + #ifndef __LINUX_DMA_QCOM_ADM_H 3 + #define __LINUX_DMA_QCOM_ADM_H 4 + 5 + #include <linux/types.h> 6 + 7 + struct qcom_adm_peripheral_config { 8 + u32 crci; 9 + u32 mux; 10 + }; 11 + 12 + #endif /* __LINUX_DMA_QCOM_ADM_H */
+11
include/linux/dma/xilinx_dpdma.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #ifndef __LINUX_DMA_XILINX_DPDMA_H 3 + #define __LINUX_DMA_XILINX_DPDMA_H 4 + 5 + #include <linux/types.h> 6 + 7 + struct xilinx_dpdma_peripheral_config { 8 + bool video_group; 9 + }; 10 + 11 + #endif /* __LINUX_DMA_XILINX_DPDMA_H */
-4
include/linux/dmaengine.h
··· 418 418 * @device_fc: Flow Controller Settings. Only valid for slave channels. Fill 419 419 * with 'true' if peripheral should be flow controller. Direction will be 420 420 * selected at Runtime. 421 - * @slave_id: Slave requester id. Only valid for slave channels. The dma 422 - * slave peripheral will have unique id as dma requester which need to be 423 - * pass as slave config. 424 421 * @peripheral_config: peripheral configuration for programming peripheral 425 422 * for dmaengine transfer 426 423 * @peripheral_size: peripheral configuration buffer size ··· 445 448 u32 src_port_window_size; 446 449 u32 dst_port_window_size; 447 450 bool device_fc; 448 - unsigned int slave_id; 449 451 void *peripheral_config; 450 452 size_t peripheral_size; 451 453 };
-2
include/sound/dmaengine_pcm.h
··· 60 60 * @maxburst: Maximum number of words(note: words, as in units of the 61 61 * src_addr_width member, not bytes) that can be send to or received from the 62 62 * DAI in one burst. 63 - * @slave_id: Slave requester id for the DMA channel. 64 63 * @filter_data: Custom DMA channel filter data, this will usually be used when 65 64 * requesting the DMA channel. 66 65 * @chan_name: Custom channel name to use when requesting DMA channel. ··· 73 74 dma_addr_t addr; 74 75 enum dma_slave_buswidth addr_width; 75 76 u32 maxburst; 76 - unsigned int slave_id; 77 77 void *filter_data; 78 78 const char *chan_name; 79 79 unsigned int fifo_size;
+2 -3
sound/core/pcm_dmaengine.c
··· 91 91 * @dma_data: DAI DMA data 92 92 * @slave_config: DMA slave configuration 93 93 * 94 - * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and 95 - * slave_id fields of the DMA slave config from the same fields of the DAI DMA 94 + * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width 95 + * fields of the DMA slave config from the same fields of the DAI DMA 96 96 * data struct. The src and dst fields will be initialized depending on the 97 97 * direction of the substream. If the substream is a playback stream the dst 98 98 * fields will be initialized, if it is a capture stream the src fields will be ··· 124 124 slave_config->src_addr_width = dma_data->addr_width; 125 125 } 126 126 127 - slave_config->slave_id = dma_data->slave_id; 128 127 slave_config->peripheral_config = dma_data->peripheral_config; 129 128 slave_config->peripheral_size = dma_data->peripheral_size; 130 129 }
+49
sound/soc/tegra/tegra20_i2s.c
··· 262 262 return 0; 263 263 } 264 264 265 + static const unsigned int tegra20_i2s_rates[] = { 266 + 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000 267 + }; 268 + 269 + static int tegra20_i2s_filter_rates(struct snd_pcm_hw_params *params, 270 + struct snd_pcm_hw_rule *rule) 271 + { 272 + struct snd_interval *r = hw_param_interval(params, rule->var); 273 + struct snd_soc_dai *dai = rule->private; 274 + struct tegra20_i2s *i2s = dev_get_drvdata(dai->dev); 275 + struct clk *parent = clk_get_parent(i2s->clk_i2s); 276 + long i, parent_rate, valid_rates = 0; 277 + 278 + parent_rate = clk_get_rate(parent); 279 + if (parent_rate <= 0) { 280 + dev_err(dai->dev, "Can't get parent clock rate: %ld\n", 281 + parent_rate); 282 + return parent_rate ?: -EINVAL; 283 + } 284 + 285 + for (i = 0; i < ARRAY_SIZE(tegra20_i2s_rates); i++) { 286 + if (parent_rate % (tegra20_i2s_rates[i] * 128) == 0) 287 + valid_rates |= BIT(i); 288 + } 289 + 290 + /* 291 + * At least one rate must be valid, otherwise the parent clock isn't 292 + * audio PLL. Nothing should be filtered in this case. 293 + */ 294 + if (!valid_rates) 295 + valid_rates = BIT(ARRAY_SIZE(tegra20_i2s_rates)) - 1; 296 + 297 + return snd_interval_list(r, ARRAY_SIZE(tegra20_i2s_rates), 298 + tegra20_i2s_rates, valid_rates); 299 + } 300 + 301 + static int tegra20_i2s_startup(struct snd_pcm_substream *substream, 302 + struct snd_soc_dai *dai) 303 + { 304 + if (!device_property_read_bool(dai->dev, "nvidia,fixed-parent-rate")) 305 + return 0; 306 + 307 + return snd_pcm_hw_rule_add(substream->runtime, 0, 308 + SNDRV_PCM_HW_PARAM_RATE, 309 + tegra20_i2s_filter_rates, dai, 310 + SNDRV_PCM_HW_PARAM_RATE, -1); 311 + } 312 + 265 313 static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = { 266 314 .set_fmt = tegra20_i2s_set_fmt, 267 315 .hw_params = tegra20_i2s_hw_params, 268 316 .trigger = tegra20_i2s_trigger, 317 + .startup = tegra20_i2s_startup, 269 318 }; 270 319 271 320 static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
+139 -58
sound/soc/tegra/tegra20_spdif.c
··· 7 7 */ 8 8 9 9 #include <linux/clk.h> 10 + #include <linux/delay.h> 10 11 #include <linux/device.h> 11 12 #include <linux/io.h> 12 13 #include <linux/module.h> 14 + #include <linux/of_device.h> 13 15 #include <linux/platform_device.h> 14 16 #include <linux/pm_runtime.h> 15 17 #include <linux/regmap.h> 18 + #include <linux/reset.h> 16 19 #include <linux/slab.h> 17 20 #include <sound/core.h> 18 21 #include <sound/pcm.h> ··· 25 22 26 23 #include "tegra20_spdif.h" 27 24 28 - #define DRV_NAME "tegra20-spdif" 29 - 30 25 static __maybe_unused int tegra20_spdif_runtime_suspend(struct device *dev) 31 26 { 32 27 struct tegra20_spdif *spdif = dev_get_drvdata(dev); 28 + 29 + regcache_cache_only(spdif->regmap, true); 33 30 34 31 clk_disable_unprepare(spdif->clk_spdif_out); 35 32 ··· 41 38 struct tegra20_spdif *spdif = dev_get_drvdata(dev); 42 39 int ret; 43 40 41 + ret = reset_control_assert(spdif->reset); 42 + if (ret) 43 + return ret; 44 + 44 45 ret = clk_prepare_enable(spdif->clk_spdif_out); 45 46 if (ret) { 46 47 dev_err(dev, "clk_enable failed: %d\n", ret); 47 48 return ret; 48 49 } 49 50 51 + usleep_range(10, 100); 52 + 53 + ret = reset_control_deassert(spdif->reset); 54 + if (ret) 55 + goto disable_clocks; 56 + 57 + regcache_cache_only(spdif->regmap, false); 58 + regcache_mark_dirty(spdif->regmap); 59 + 60 + ret = regcache_sync(spdif->regmap); 61 + if (ret) 62 + goto disable_clocks; 63 + 50 64 return 0; 65 + 66 + disable_clocks: 67 + clk_disable_unprepare(spdif->clk_spdif_out); 68 + 69 + return ret; 51 70 } 52 71 53 72 static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, 54 - struct snd_pcm_hw_params *params, 55 - struct snd_soc_dai *dai) 73 + struct snd_pcm_hw_params *params, 74 + struct snd_soc_dai *dai) 56 75 { 57 - struct device *dev = dai->dev; 58 - struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); 76 + struct tegra20_spdif *spdif = dev_get_drvdata(dai->dev); 59 77 unsigned int mask = 0, val = 0; 60 78 int ret, spdifclock; 79 + long rate; 61 80 62 81 mask |= TEGRA20_SPDIF_CTRL_PACK | 63 82 TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; ··· 93 68 } 94 69 95 70 regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, mask, val); 71 + 72 + /* 73 + * FIFO trigger level must be bigger than DMA burst or equal to it, 74 + * otherwise data is discarded on overflow. 75 + */ 76 + regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_DATA_FIFO_CSR, 77 + TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_MASK, 78 + TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU4_WORD_FULL); 96 79 97 80 switch (params_rate(params)) { 98 81 case 32000: ··· 130 97 131 98 ret = clk_set_rate(spdif->clk_spdif_out, spdifclock); 132 99 if (ret) { 133 - dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret); 100 + dev_err(dai->dev, "Can't set SPDIF clock rate: %d\n", ret); 134 101 return ret; 135 102 } 103 + 104 + rate = clk_get_rate(spdif->clk_spdif_out); 105 + if (rate != spdifclock) 106 + dev_warn_once(dai->dev, 107 + "SPDIF clock rate %d doesn't match requested rate %lu\n", 108 + spdifclock, rate); 136 109 137 110 return 0; 138 111 } ··· 157 118 } 158 119 159 120 static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd, 160 - struct snd_soc_dai *dai) 121 + struct snd_soc_dai *dai) 161 122 { 162 - struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); 123 + struct tegra20_spdif *spdif = dev_get_drvdata(dai->dev); 163 124 164 125 switch (cmd) { 165 126 case SNDRV_PCM_TRIGGER_START: ··· 179 140 return 0; 180 141 } 181 142 143 + static int tegra20_spdif_filter_rates(struct snd_pcm_hw_params *params, 144 + struct snd_pcm_hw_rule *rule) 145 + { 146 + struct snd_interval *r = hw_param_interval(params, rule->var); 147 + struct snd_soc_dai *dai = rule->private; 148 + struct tegra20_spdif *spdif = dev_get_drvdata(dai->dev); 149 + struct clk *parent = clk_get_parent(spdif->clk_spdif_out); 150 + const unsigned int rates[] = { 32000, 44100, 48000 }; 151 + long i, parent_rate, valid_rates = 0; 152 + 153 + parent_rate = clk_get_rate(parent); 154 + if (parent_rate <= 0) { 155 + dev_err(dai->dev, "Can't get parent clock rate: %ld\n", 156 + parent_rate); 157 + return parent_rate ?: -EINVAL; 158 + } 159 + 160 + for (i = 0; i < ARRAY_SIZE(rates); i++) { 161 + if (parent_rate % (rates[i] * 128) == 0) 162 + valid_rates |= BIT(i); 163 + } 164 + 165 + /* 166 + * At least one rate must be valid, otherwise the parent clock isn't 167 + * audio PLL. Nothing should be filtered in this case. 168 + */ 169 + if (!valid_rates) 170 + valid_rates = BIT(ARRAY_SIZE(rates)) - 1; 171 + 172 + return snd_interval_list(r, ARRAY_SIZE(rates), rates, valid_rates); 173 + } 174 + 175 + static int tegra20_spdif_startup(struct snd_pcm_substream *substream, 176 + struct snd_soc_dai *dai) 177 + { 178 + if (!device_property_read_bool(dai->dev, "nvidia,fixed-parent-rate")) 179 + return 0; 180 + 181 + /* 182 + * SPDIF and I2S share audio PLL. HDMI takes audio packets from SPDIF 183 + * and audio may not work on some TVs if clock rate isn't precise. 184 + * 185 + * PLL rate is controlled by I2S side. Filter out audio rates that 186 + * don't match PLL rate at the start of stream to allow both SPDIF 187 + * and I2S work simultaneously, assuming that PLL rate won't be 188 + * changed later on. 189 + */ 190 + return snd_pcm_hw_rule_add(substream->runtime, 0, 191 + SNDRV_PCM_HW_PARAM_RATE, 192 + tegra20_spdif_filter_rates, dai, 193 + SNDRV_PCM_HW_PARAM_RATE, -1); 194 + } 195 + 182 196 static int tegra20_spdif_probe(struct snd_soc_dai *dai) 183 197 { 184 - struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); 198 + struct tegra20_spdif *spdif = dev_get_drvdata(dai->dev); 185 199 186 200 dai->capture_dma_data = NULL; 187 201 dai->playback_dma_data = &spdif->playback_dma_data; ··· 243 151 } 244 152 245 153 static const struct snd_soc_dai_ops tegra20_spdif_dai_ops = { 246 - .hw_params = tegra20_spdif_hw_params, 247 - .trigger = tegra20_spdif_trigger, 154 + .hw_params = tegra20_spdif_hw_params, 155 + .trigger = tegra20_spdif_trigger, 156 + .startup = tegra20_spdif_startup, 248 157 }; 249 158 250 159 static struct snd_soc_dai_driver tegra20_spdif_dai = { 251 - .name = DRV_NAME, 160 + .name = "tegra20-spdif", 252 161 .probe = tegra20_spdif_probe, 253 162 .playback = { 254 163 .stream_name = "Playback", 255 164 .channels_min = 2, 256 165 .channels_max = 2, 257 166 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 258 - SNDRV_PCM_RATE_48000, 167 + SNDRV_PCM_RATE_48000, 259 168 .formats = SNDRV_PCM_FMTBIT_S16_LE, 260 169 }, 261 170 .ops = &tegra20_spdif_dai_ops, 262 171 }; 263 172 264 173 static const struct snd_soc_component_driver tegra20_spdif_component = { 265 - .name = DRV_NAME, 174 + .name = "tegra20-spdif", 266 175 }; 267 176 268 177 static bool tegra20_spdif_wr_rd_reg(struct device *dev, unsigned int reg) ··· 344 251 static int tegra20_spdif_platform_probe(struct platform_device *pdev) 345 252 { 346 253 struct tegra20_spdif *spdif; 347 - struct resource *mem, *dmareq; 254 + struct resource *mem; 348 255 void __iomem *regs; 349 256 int ret; 350 257 ··· 355 262 356 263 dev_set_drvdata(&pdev->dev, spdif); 357 264 358 - spdif->clk_spdif_out = devm_clk_get(&pdev->dev, "spdif_out"); 265 + spdif->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); 266 + if (IS_ERR(spdif->reset)) { 267 + dev_err(&pdev->dev, "Can't retrieve spdif reset\n"); 268 + return PTR_ERR(spdif->reset); 269 + } 270 + 271 + spdif->clk_spdif_out = devm_clk_get(&pdev->dev, "out"); 359 272 if (IS_ERR(spdif->clk_spdif_out)) { 360 - pr_err("Can't retrieve spdif clock\n"); 361 - ret = PTR_ERR(spdif->clk_spdif_out); 362 - return ret; 273 + dev_err(&pdev->dev, "Could not retrieve spdif clock\n"); 274 + return PTR_ERR(spdif->clk_spdif_out); 363 275 } 364 276 365 277 regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); 366 278 if (IS_ERR(regs)) 367 279 return PTR_ERR(regs); 368 280 369 - dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0); 370 - if (!dmareq) { 371 - dev_err(&pdev->dev, "No DMA resource\n"); 372 - return -ENODEV; 373 - } 374 - 375 281 spdif->regmap = devm_regmap_init_mmio(&pdev->dev, regs, 376 - &tegra20_spdif_regmap_config); 282 + &tegra20_spdif_regmap_config); 377 283 if (IS_ERR(spdif->regmap)) { 378 284 dev_err(&pdev->dev, "regmap init failed\n"); 379 - ret = PTR_ERR(spdif->regmap); 380 - return ret; 285 + return PTR_ERR(spdif->regmap); 381 286 } 382 287 383 288 spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT; 384 289 spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 385 290 spdif->playback_dma_data.maxburst = 4; 386 - spdif->playback_dma_data.slave_id = dmareq->start; 387 291 388 - pm_runtime_enable(&pdev->dev); 292 + ret = devm_pm_runtime_enable(&pdev->dev); 293 + if (ret) 294 + return ret; 389 295 390 - ret = snd_soc_register_component(&pdev->dev, &tegra20_spdif_component, 391 - &tegra20_spdif_dai, 1); 296 + ret = devm_snd_soc_register_component(&pdev->dev, 297 + &tegra20_spdif_component, 298 + &tegra20_spdif_dai, 1); 392 299 if (ret) { 393 300 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); 394 - ret = -ENOMEM; 395 - goto err_pm_disable; 301 + return ret; 396 302 } 397 303 398 - ret = tegra_pcm_platform_register(&pdev->dev); 304 + ret = devm_tegra_pcm_platform_register(&pdev->dev); 399 305 if (ret) { 400 306 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); 401 - goto err_unregister_component; 307 + return ret; 402 308 } 403 - 404 - return 0; 405 - 406 - err_unregister_component: 407 - snd_soc_unregister_component(&pdev->dev); 408 - err_pm_disable: 409 - pm_runtime_disable(&pdev->dev); 410 - 411 - return ret; 412 - } 413 - 414 - static int tegra20_spdif_platform_remove(struct platform_device *pdev) 415 - { 416 - tegra_pcm_platform_unregister(&pdev->dev); 417 - snd_soc_unregister_component(&pdev->dev); 418 - 419 - pm_runtime_disable(&pdev->dev); 420 309 421 310 return 0; 422 311 } ··· 406 331 static const struct dev_pm_ops tegra20_spdif_pm_ops = { 407 332 SET_RUNTIME_PM_OPS(tegra20_spdif_runtime_suspend, 408 333 tegra20_spdif_runtime_resume, NULL) 334 + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 335 + pm_runtime_force_resume) 409 336 }; 337 + 338 + static const struct of_device_id tegra20_spdif_of_match[] = { 339 + { .compatible = "nvidia,tegra20-spdif", }, 340 + {}, 341 + }; 342 + MODULE_DEVICE_TABLE(of, tegra20_spdif_of_match); 410 343 411 344 static struct platform_driver tegra20_spdif_driver = { 412 345 .driver = { 413 - .name = DRV_NAME, 346 + .name = "tegra20-spdif", 414 347 .pm = &tegra20_spdif_pm_ops, 348 + .of_match_table = tegra20_spdif_of_match, 415 349 }, 416 350 .probe = tegra20_spdif_platform_probe, 417 - .remove = tegra20_spdif_platform_remove, 418 351 }; 419 - 420 352 module_platform_driver(tegra20_spdif_driver); 421 353 422 354 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 423 355 MODULE_DESCRIPTION("Tegra20 SPDIF ASoC driver"); 424 356 MODULE_LICENSE("GPL"); 425 - MODULE_ALIAS("platform:" DRV_NAME);
+1
sound/soc/tegra/tegra20_spdif.h
··· 451 451 struct snd_dmaengine_dai_dma_data capture_dma_data; 452 452 struct snd_dmaengine_dai_dma_data playback_dma_data; 453 453 struct regmap *regmap; 454 + struct reset_control *reset; 454 455 }; 455 456 456 457 #endif
+6
sound/soc/tegra/tegra_pcm.c
··· 48 48 } 49 49 EXPORT_SYMBOL_GPL(tegra_pcm_platform_register); 50 50 51 + int devm_tegra_pcm_platform_register(struct device *dev) 52 + { 53 + return devm_snd_dmaengine_pcm_register(dev, &tegra_dmaengine_pcm_config, 0); 54 + } 55 + EXPORT_SYMBOL_GPL(devm_tegra_pcm_platform_register); 56 + 51 57 int tegra_pcm_platform_register_with_chan_names(struct device *dev, 52 58 struct snd_dmaengine_pcm_config *config, 53 59 char *txdmachan, char *rxdmachan)
+1
sound/soc/tegra/tegra_pcm.h
··· 32 32 snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component, 33 33 struct snd_pcm_substream *substream); 34 34 int tegra_pcm_platform_register(struct device *dev); 35 + int devm_tegra_pcm_platform_register(struct device *dev); 35 36 int tegra_pcm_platform_register_with_chan_names(struct device *dev, 36 37 struct snd_dmaengine_pcm_config *config, 37 38 char *txdmachan, char *rxdmachan);