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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'sound-4.7-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull more sound updates from Takashi Iwai:
"This is the second update round for 4.7-rc1. Most of changes are
about the pending ASoC updates and fixes, including a few new drivers.
Below are some highlights:

ASoC:
- New drivers for MAX98371 and TAS5720
- SPI support for TLV320AIC32x4, along with the module split
- TDM support for STI Uniperf IPs
- Remaining topology API fixes / updates

HDA:
- A couple of Dell quirks and new Realtek codec support"

* tag 'sound-4.7-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (63 commits)
ALSA: hda - Fix headset mic detection problem for one Dell machine
spi: spi-ep93xx: Fix the PTR_ERR() argument
ALSA: hda/realtek - Add support for ALC295/ALC3254
ASoC: kirkwood: fix build failure
ALSA: hda - Fix headphone noise on Dell XPS 13 9360
ASoC: ak4642: Enable cache usage to fix crashes on resume
ASoC: twl6040: Disconnect AUX output pads on digital mute
ASoC: tlv320aic32x4: Properly implement the positive and negative pins into the mixers
rcar: src: skip disabled-SRC nodes
ASoC: max98371 Remove duplicate entry in max98371_reg
ASoC: twl6040: Select LPPLL during standby
ASoC: rsnd: don't use prohibited number to PDMACHCRn.SRS
ASoC: simple-card: Add pm callbacks to platform driver
ASoC: pxa: Fix module autoload for platform drivers
ASoC: topology: Fix memory leak in widget creation
ASoC: Add max98371 codec driver
ASoC: rsnd: count .probe/.remove for rsnd_mod_call()
ASoC: topology: Check size mismatch of ABI objects before parsing
ASoC: topology: Check failure to create a widget
ASoC: add support for TAS5720 digital amplifier
...

+2799 -330
+17
Documentation/devicetree/bindings/sound/max98371.txt
··· 1 + max98371 codec 2 + 3 + This device supports I2C mode only. 4 + 5 + Required properties: 6 + 7 + - compatible : "maxim,max98371" 8 + - reg : The chip select number on the I2C bus 9 + 10 + Example: 11 + 12 + &i2c { 13 + max98371: max98371@0x31 { 14 + compatible = "maxim,max98371"; 15 + reg = <0x31>; 16 + }; 17 + };
+3 -2
Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt
··· 1 - MT8173 with RT5650 RT5676 CODECS 1 + MT8173 with RT5650 RT5676 CODECS and HDMI via I2S 2 2 3 3 Required properties: 4 4 - compatible : "mediatek,mt8173-rt5650-rt5676" 5 5 - mediatek,audio-codec: the phandles of rt5650 and rt5676 codecs 6 + and of the hdmi encoder node 6 7 - mediatek,platform: the phandle of MT8173 ASoC platform 7 8 8 9 Example: 9 10 10 11 sound { 11 12 compatible = "mediatek,mt8173-rt5650-rt5676"; 12 - mediatek,audio-codec = <&rt5650 &rt5676>; 13 + mediatek,audio-codec = <&rt5650 &rt5676 &hdmi0>; 13 14 mediatek,platform = <&afe>; 14 15 }; 15 16
+10
Documentation/devicetree/bindings/sound/mt8173-rt5650.txt
··· 5 5 - mediatek,audio-codec: the phandles of rt5650 codecs 6 6 - mediatek,platform: the phandle of MT8173 ASoC platform 7 7 8 + Optional subnodes: 9 + - codec-capture : the subnode of rt5650 codec capture 10 + Required codec-capture subnode properties: 11 + - sound-dai: audio codec dai name on capture path 12 + <&rt5650 0> : Default setting. Connect rt5650 I2S1 for capture. (dai_name = rt5645-aif1) 13 + <&rt5650 1> : Connect rt5650 I2S2 for capture. (dai_name = rt5645-aif2) 14 + 8 15 Example: 9 16 10 17 sound { 11 18 compatible = "mediatek,mt8173-rt5650"; 12 19 mediatek,audio-codec = <&rt5650>; 13 20 mediatek,platform = <&afe>; 21 + codec-capture { 22 + sound-dai = <&rt5650 1>; 23 + }; 14 24 }; 15 25
+41 -7
Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt
··· 37 37 38 38 - dai-name: DAI name that describes the IP. 39 39 40 + - IP mode: IP working mode depending on associated codec. 41 + "HDMI" connected to HDMI codec and support IEC HDMI formats (player only). 42 + "SPDIF" connected to SPDIF codec and support SPDIF formats (player only). 43 + "PCM" PCM standard mode for I2S or TDM bus. 44 + "TDM" TDM mode for TDM bus. 45 + 40 46 Required properties ("st,sti-uni-player" compatibility only): 41 47 - clocks: CPU_DAI IP clock source, listed in the same order than the 42 48 CPU_DAI properties. 43 49 44 50 - uniperiph-id: internal SOC IP instance ID. 45 - 46 - - IP mode: IP working mode depending on associated codec. 47 - "HDMI" connected to HDMI codec IP and IEC HDMI formats. 48 - "SPDIF"connected to SPDIF codec and support SPDIF formats. 49 - "PCM" PCM standard mode for I2S or TDM bus. 50 51 51 52 Optional properties: 52 53 - pinctrl-0: defined for CPU_DAI@1 and CPU_DAI@4 to describe I2S PIOs for ··· 56 55 - pinctrl-names: should contain only one value - "default". 57 56 58 57 Example: 58 + 59 + sti_uni_player1: sti-uni-player@1 { 60 + compatible = "st,sti-uni-player"; 61 + status = "okay"; 62 + #sound-dai-cells = <0>; 63 + st,syscfg = <&syscfg_core>; 64 + clocks = <&clk_s_d0_flexgen CLK_PCM_1>; 65 + reg = <0x8D81000 0x158>; 66 + interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>; 67 + dmas = <&fdma0 3 0 1>; 68 + st,dai-name = "Uni Player #1 (I2S)"; 69 + dma-names = "tx"; 70 + st,uniperiph-id = <1>; 71 + st,version = <5>; 72 + st,mode = "TDM"; 73 + }; 59 74 60 75 sti_uni_player2: sti-uni-player@2 { 61 76 compatible = "st,sti-uni-player"; ··· 82 65 reg = <0x8D82000 0x158>; 83 66 interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>; 84 67 dmas = <&fdma0 4 0 1>; 85 - dai-name = "Uni Player #1 (DAC)"; 68 + dai-name = "Uni Player #2 (DAC)"; 86 69 dma-names = "tx"; 87 70 uniperiph-id = <2>; 88 71 version = <5>; ··· 99 82 interrupts = <GIC_SPI 89 IRQ_TYPE_NONE>; 100 83 dmas = <&fdma0 7 0 1>; 101 84 dma-names = "tx"; 102 - dai-name = "Uni Player #1 (PIO)"; 85 + dai-name = "Uni Player #3 (SPDIF)"; 103 86 uniperiph-id = <3>; 104 87 version = <5>; 105 88 mode = "SPDIF"; ··· 116 99 dma-names = "rx"; 117 100 dai-name = "Uni Reader #1 (HDMI RX)"; 118 101 version = <3>; 102 + st,mode = "PCM"; 119 103 }; 120 104 121 105 2) sti-sas-codec: internal audio codec IPs driver ··· 168 150 169 151 codec { 170 152 sound-dai = <&sti_sasg_codec 0>; 153 + }; 154 + }; 155 + simple-audio-card,dai-link@2 { 156 + /* TDM playback */ 157 + format = "left_j"; 158 + frame-inversion = <1>; 159 + cpu { 160 + sound-dai = <&sti_uni_player1>; 161 + dai-tdm-slot-num = <16>; 162 + dai-tdm-slot-width = <16>; 163 + dai-tdm-slot-tx-mask = 164 + <1 1 1 1 0 0 0 0 0 0 1 1 0 0 1 1>; 165 + }; 166 + 167 + codec { 168 + sound-dai = <&sti_sasg_codec 3>; 171 169 }; 172 170 }; 173 171 };
+8 -2
Documentation/devicetree/bindings/sound/tas571x.txt
··· 1 - Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers 1 + Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 stereo power amplifiers 2 2 3 3 The codec is controlled through an I2C interface. It also has two other 4 4 signals that can be wired up to GPIOs: reset (strongly recommended), and ··· 6 6 7 7 Required properties: 8 8 9 - - compatible: "ti,tas5711", "ti,tas5717", or "ti,tas5719" 9 + - compatible: should be one of the following: 10 + - "ti,tas5711", 11 + - "ti,tas5717", 12 + - "ti,tas5719", 13 + - "ti,tas5721" 10 14 - reg: The I2C address of the device 11 15 - #sound-dai-cells: must be equal to 0 12 16 ··· 29 25 - PVDD_B-supply: regulator phandle for the PVDD_B supply (5711) 30 26 - PVDD_C-supply: regulator phandle for the PVDD_C supply (5711) 31 27 - PVDD_D-supply: regulator phandle for the PVDD_D supply (5711) 28 + - DRVDD-supply: regulator phandle for the DRVDD supply (5721) 29 + - PVDD-supply: regulator phandle for the PVDD supply (5721) 32 30 33 31 Example: 34 32
+25
Documentation/devicetree/bindings/sound/tas5720.txt
··· 1 + Texas Instruments TAS5720 Mono Audio amplifier 2 + 3 + The TAS5720 serial control bus communicates through the I2C protocol only. The 4 + serial bus is also used for periodic codec fault checking/reporting during 5 + audio playback. For more product information please see the links below: 6 + 7 + http://www.ti.com/product/TAS5720L 8 + http://www.ti.com/product/TAS5720M 9 + 10 + Required properties: 11 + 12 + - compatible : "ti,tas5720" 13 + - reg : I2C slave address 14 + - dvdd-supply : phandle to a 3.3-V supply for the digital circuitry 15 + - pvdd-supply : phandle to a supply used for the Class-D amp and the analog 16 + 17 + Example: 18 + 19 + tas5720: tas5720@6c { 20 + status = "okay"; 21 + compatible = "ti,tas5720"; 22 + reg = <0x6c>; 23 + dvdd-supply = <&vdd_3v3_reg>; 24 + pvdd-supply = <&amp_supply_reg>; 25 + };
+1 -1
drivers/spi/spi-ep93xx.c
··· 567 567 txd = ep93xx_spi_dma_prepare(espi, DMA_MEM_TO_DEV); 568 568 if (IS_ERR(txd)) { 569 569 ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM); 570 - dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd)); 570 + dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(txd)); 571 571 msg->status = PTR_ERR(txd); 572 572 return; 573 573 }
+1
include/linux/mfd/twl6040.h
··· 134 134 #define TWL6040_HFDACENA (1 << 0) 135 135 #define TWL6040_HFPGAENA (1 << 1) 136 136 #define TWL6040_HFDRVENA (1 << 4) 137 + #define TWL6040_HFSWENA (1 << 6) 137 138 138 139 /* VIBCTLL/R (0x18/0x1A) fields */ 139 140
+42 -2
include/uapi/sound/asoc.h
··· 116 116 #define SND_SOC_TPLG_STREAM_PLAYBACK 0 117 117 #define SND_SOC_TPLG_STREAM_CAPTURE 1 118 118 119 + /* vendor tuple types */ 120 + #define SND_SOC_TPLG_TUPLE_TYPE_UUID 0 121 + #define SND_SOC_TPLG_TUPLE_TYPE_STRING 1 122 + #define SND_SOC_TPLG_TUPLE_TYPE_BOOL 2 123 + #define SND_SOC_TPLG_TUPLE_TYPE_BYTE 3 124 + #define SND_SOC_TPLG_TUPLE_TYPE_WORD 4 125 + #define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5 126 + 119 127 /* 120 128 * Block Header. 121 129 * This header precedes all object and object arrays below. ··· 140 132 __le32 count; /* number of elements in block */ 141 133 } __attribute__((packed)); 142 134 135 + /* vendor tuple for uuid */ 136 + struct snd_soc_tplg_vendor_uuid_elem { 137 + __le32 token; 138 + char uuid[16]; 139 + } __attribute__((packed)); 140 + 141 + /* vendor tuple for a bool/byte/short/word value */ 142 + struct snd_soc_tplg_vendor_value_elem { 143 + __le32 token; 144 + __le32 value; 145 + } __attribute__((packed)); 146 + 147 + /* vendor tuple for string */ 148 + struct snd_soc_tplg_vendor_string_elem { 149 + __le32 token; 150 + char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 151 + } __attribute__((packed)); 152 + 153 + struct snd_soc_tplg_vendor_array { 154 + __le32 size; /* size in bytes of the array, including all elements */ 155 + __le32 type; /* SND_SOC_TPLG_TUPLE_TYPE_ */ 156 + __le32 num_elems; /* number of elements in array */ 157 + union { 158 + struct snd_soc_tplg_vendor_uuid_elem uuid[0]; 159 + struct snd_soc_tplg_vendor_value_elem value[0]; 160 + struct snd_soc_tplg_vendor_string_elem string[0]; 161 + }; 162 + } __attribute__((packed)); 163 + 143 164 /* 144 165 * Private data. 145 166 * All topology objects may have private data that can be used by the driver or ··· 176 139 */ 177 140 struct snd_soc_tplg_private { 178 141 __le32 size; /* in bytes of private data */ 179 - char data[0]; 142 + union { 143 + char data[0]; 144 + struct snd_soc_tplg_vendor_array array[0]; 145 + }; 180 146 } __attribute__((packed)); 181 147 182 148 /* ··· 423 383 __le32 size; /* in bytes of this structure */ 424 384 char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 425 385 char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 426 - __le32 pcm_id; /* unique ID - used to match */ 386 + __le32 pcm_id; /* unique ID - used to match with DAI link */ 427 387 __le32 dai_id; /* unique ID - used to match */ 428 388 __le32 playback; /* supports playback mode */ 429 389 __le32 capture; /* supports capture mode */
+15 -1
sound/pci/hda/patch_realtek.c
··· 335 335 case 0x10ec0283: 336 336 case 0x10ec0286: 337 337 case 0x10ec0288: 338 + case 0x10ec0295: 338 339 case 0x10ec0298: 339 340 alc_update_coef_idx(codec, 0x10, 1<<9, 0); 340 341 break; ··· 908 907 { 0x10ec0298, 0x1028, 0, "ALC3266" }, 909 908 { 0x10ec0256, 0x1028, 0, "ALC3246" }, 910 909 { 0x10ec0225, 0x1028, 0, "ALC3253" }, 910 + { 0x10ec0295, 0x1028, 0, "ALC3254" }, 911 911 { 0x10ec0670, 0x1025, 0, "ALC669X" }, 912 912 { 0x10ec0676, 0x1025, 0, "ALC679X" }, 913 913 { 0x10ec0282, 0x1043, 0, "ALC3229" }, ··· 3699 3697 alc_process_coef_fw(codec, coef0668); 3700 3698 break; 3701 3699 case 0x10ec0225: 3700 + case 0x10ec0295: 3702 3701 alc_process_coef_fw(codec, coef0225); 3703 3702 break; 3704 3703 } ··· 3800 3797 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); 3801 3798 break; 3802 3799 case 0x10ec0225: 3800 + case 0x10ec0295: 3803 3801 alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10); 3804 3802 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); 3805 3803 alc_process_coef_fw(codec, coef0225); ··· 3858 3854 3859 3855 switch (codec->core.vendor_id) { 3860 3856 case 0x10ec0225: 3857 + case 0x10ec0295: 3861 3858 alc_process_coef_fw(codec, coef0225); 3862 3859 break; 3863 3860 case 0x10ec0255: ··· 3962 3957 alc_process_coef_fw(codec, coef0688); 3963 3958 break; 3964 3959 case 0x10ec0225: 3960 + case 0x10ec0295: 3965 3961 alc_process_coef_fw(codec, coef0225); 3966 3962 break; 3967 3963 } ··· 4044 4038 alc_process_coef_fw(codec, coef0688); 4045 4039 break; 4046 4040 case 0x10ec0225: 4041 + case 0x10ec0295: 4047 4042 alc_process_coef_fw(codec, coef0225); 4048 4043 break; 4049 4044 } ··· 4128 4121 is_ctia = (val & 0x1c02) == 0x1c02; 4129 4122 break; 4130 4123 case 0x10ec0225: 4124 + case 0x10ec0295: 4131 4125 alc_process_coef_fw(codec, coef0225); 4132 4126 msleep(800); 4133 4127 val = alc_read_coef_idx(codec, 0x46); ··· 5474 5466 SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), 5475 5467 SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), 5476 5468 SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), 5477 - SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), 5469 + SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), 5478 5470 SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE), 5471 + SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), 5479 5472 SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), 5480 5473 SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), 5481 5474 SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), ··· 5719 5710 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, 5720 5711 {0x14, 0x90170110}, 5721 5712 {0x21, 0x02211020}), 5713 + SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, 5714 + {0x14, 0x90170130}, 5715 + {0x21, 0x02211040}), 5722 5716 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, 5723 5717 {0x12, 0x90a60140}, 5724 5718 {0x14, 0x90170110}, ··· 6045 6033 alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/ 6046 6034 break; 6047 6035 case 0x10ec0225: 6036 + case 0x10ec0295: 6048 6037 spec->codec_variant = ALC269_TYPE_ALC225; 6049 6038 break; 6050 6039 case 0x10ec0234: ··· 6992 6979 HDA_CODEC_ENTRY(0x10ec0292, "ALC292", patch_alc269), 6993 6980 HDA_CODEC_ENTRY(0x10ec0293, "ALC293", patch_alc269), 6994 6981 HDA_CODEC_ENTRY(0x10ec0294, "ALC294", patch_alc269), 6982 + HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269), 6995 6983 HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269), 6996 6984 HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861), 6997 6985 HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
+31 -7
sound/soc/codecs/Kconfig
··· 43 43 select SND_SOC_AK5386 44 44 select SND_SOC_ALC5623 if I2C 45 45 select SND_SOC_ALC5632 if I2C 46 + select SND_SOC_BT_SCO 46 47 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC 47 48 select SND_SOC_CS35L32 if I2C 48 49 select SND_SOC_CS42L51_I2C if I2C ··· 65 64 select SND_SOC_DA732X if I2C 66 65 select SND_SOC_DA9055 if I2C 67 66 select SND_SOC_DMIC 68 - select SND_SOC_BT_SCO 69 67 select SND_SOC_ES8328_SPI if SPI_MASTER 70 68 select SND_SOC_ES8328_I2C if I2C 71 69 select SND_SOC_GTM601 ··· 79 79 select SND_SOC_MAX98090 if I2C 80 80 select SND_SOC_MAX98095 if I2C 81 81 select SND_SOC_MAX98357A if GPIOLIB 82 + select SND_SOC_MAX98371 if I2C 82 83 select SND_SOC_MAX9867 if I2C 83 84 select SND_SOC_MAX98925 if I2C 84 85 select SND_SOC_MAX98926 if I2C ··· 127 126 select SND_SOC_TAS2552 if I2C 128 127 select SND_SOC_TAS5086 if I2C 129 128 select SND_SOC_TAS571X if I2C 129 + select SND_SOC_TAS5720 if I2C 130 130 select SND_SOC_TFA9879 if I2C 131 131 select SND_SOC_TLV320AIC23_I2C if I2C 132 132 select SND_SOC_TLV320AIC23_SPI if SPI_MASTER 133 133 select SND_SOC_TLV320AIC26 if SPI_MASTER 134 134 select SND_SOC_TLV320AIC31XX if I2C 135 - select SND_SOC_TLV320AIC32X4 if I2C 135 + select SND_SOC_TLV320AIC32X4_I2C if I2C 136 + select SND_SOC_TLV320AIC32X4_SPI if SPI_MASTER 136 137 select SND_SOC_TLV320AIC3X if I2C 137 138 select SND_SOC_TPA6130A2 if I2C 138 139 select SND_SOC_TLV320DAC33 if I2C ··· 370 367 config SND_SOC_ALC5632 371 368 tristate 372 369 370 + config SND_SOC_BT_SCO 371 + tristate 372 + 373 373 config SND_SOC_CQ0093VC 374 374 tristate 375 375 ··· 479 473 config SND_SOC_DA9055 480 474 tristate 481 475 482 - config SND_SOC_BT_SCO 483 - tristate 484 - 485 476 config SND_SOC_DMIC 486 477 tristate 487 478 ··· 530 527 tristate 531 528 532 529 config SND_SOC_MAX98357A 530 + tristate 531 + 532 + config SND_SOC_MAX98371 533 533 tristate 534 534 535 535 config SND_SOC_MAX9867 ··· 754 748 depends on I2C 755 749 756 750 config SND_SOC_TAS571X 757 - tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers" 751 + tristate "Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 power amplifiers" 758 752 depends on I2C 753 + 754 + config SND_SOC_TAS5720 755 + tristate "Texas Instruments TAS5720 Mono Audio amplifier" 756 + depends on I2C 757 + help 758 + Enable support for Texas Instruments TAS5720L/M high-efficiency mono 759 + Class-D audio power amplifiers. 759 760 760 761 config SND_SOC_TFA9879 761 762 tristate "NXP Semiconductors TFA9879 amplifier" ··· 792 779 793 780 config SND_SOC_TLV320AIC32X4 794 781 tristate 782 + 783 + config SND_SOC_TLV320AIC32X4_I2C 784 + tristate 785 + depends on I2C 786 + select SND_SOC_TLV320AIC32X4 787 + 788 + config SND_SOC_TLV320AIC32X4_SPI 789 + tristate 790 + depends on SPI_MASTER 791 + select SND_SOC_TLV320AIC32X4 795 792 796 793 config SND_SOC_TLV320AIC3X 797 794 tristate "Texas Instruments TLV320AIC3x CODECs" ··· 943 920 tristate 944 921 945 922 config SND_SOC_WM8960 946 - tristate 923 + tristate "Wolfson Microelectronics WM8960 CODEC" 924 + depends on I2C 947 925 948 926 config SND_SOC_WM8961 949 927 tristate
+9 -2
sound/soc/codecs/Makefile
··· 32 32 snd-soc-ak4671-objs := ak4671.o 33 33 snd-soc-ak5386-objs := ak5386.o 34 34 snd-soc-arizona-objs := arizona.o 35 + snd-soc-bt-sco-objs := bt-sco.o 35 36 snd-soc-cq93vc-objs := cq93vc.o 36 37 snd-soc-cs35l32-objs := cs35l32.o 37 38 snd-soc-cs42l51-objs := cs42l51.o ··· 56 55 snd-soc-da7219-objs := da7219.o da7219-aad.o 57 56 snd-soc-da732x-objs := da732x.o 58 57 snd-soc-da9055-objs := da9055.o 59 - snd-soc-bt-sco-objs := bt-sco.o 60 58 snd-soc-dmic-objs := dmic.o 61 59 snd-soc-es8328-objs := es8328.o 62 60 snd-soc-es8328-i2c-objs := es8328-i2c.o ··· 74 74 snd-soc-max98090-objs := max98090.o 75 75 snd-soc-max98095-objs := max98095.o 76 76 snd-soc-max98357a-objs := max98357a.o 77 + snd-soc-max98371-objs := max98371.o 77 78 snd-soc-max9867-objs := max9867.o 78 79 snd-soc-max98925-objs := max98925.o 79 80 snd-soc-max98926-objs := max98926.o ··· 132 131 snd-soc-sti-sas-objs := sti-sas.o 133 132 snd-soc-tas5086-objs := tas5086.o 134 133 snd-soc-tas571x-objs := tas571x.o 134 + snd-soc-tas5720-objs := tas5720.o 135 135 snd-soc-tfa9879-objs := tfa9879.o 136 136 snd-soc-tlv320aic23-objs := tlv320aic23.o 137 137 snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o ··· 140 138 snd-soc-tlv320aic26-objs := tlv320aic26.o 141 139 snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o 142 140 snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o 141 + snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o 142 + snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o 143 143 snd-soc-tlv320aic3x-objs := tlv320aic3x.o 144 144 snd-soc-tlv320dac33-objs := tlv320dac33.o 145 145 snd-soc-ts3a227e-objs := ts3a227e.o ··· 247 243 obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o 248 244 obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o 249 245 obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o 246 + obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o 250 247 obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o 251 248 obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o 252 249 obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o ··· 271 266 obj-$(CONFIG_SND_SOC_DA7219) += snd-soc-da7219.o 272 267 obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o 273 268 obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o 274 - obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o 275 269 obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o 276 270 obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o 277 271 obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o ··· 343 339 obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o 344 340 obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o 345 341 obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o 342 + obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o 346 343 obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o 347 344 obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 348 345 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o ··· 351 346 obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 352 347 obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o 353 348 obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o 349 + obj-$(CONFIG_SND_SOC_TLV320AIC32X4_I2C) += snd-soc-tlv320aic32x4-i2c.o 350 + obj-$(CONFIG_SND_SOC_TLV320AIC32X4_SPI) += snd-soc-tlv320aic32x4-spi.o 354 351 obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 355 352 obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o 356 353 obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o
+3
sound/soc/codecs/ak4642.c
··· 560 560 .max_register = FIL1_3, 561 561 .reg_defaults = ak4642_reg, 562 562 .num_reg_defaults = NUM_AK4642_REG_DEFAULTS, 563 + .cache_type = REGCACHE_RBTREE, 563 564 }; 564 565 565 566 static const struct regmap_config ak4643_regmap = { ··· 569 568 .max_register = SPK_MS, 570 569 .reg_defaults = ak4643_reg, 571 570 .num_reg_defaults = ARRAY_SIZE(ak4643_reg), 571 + .cache_type = REGCACHE_RBTREE, 572 572 }; 573 573 574 574 static const struct regmap_config ak4648_regmap = { ··· 578 576 .max_register = EQ_FBEQE, 579 577 .reg_defaults = ak4648_reg, 580 578 .num_reg_defaults = ARRAY_SIZE(ak4648_reg), 579 + .cache_type = REGCACHE_RBTREE, 581 580 }; 582 581 583 582 static const struct ak4642_drvdata ak4642_drvdata = {
+441
sound/soc/codecs/max98371.c
··· 1 + /* 2 + * max98371.c -- ALSA SoC Stereo MAX98371 driver 3 + * 4 + * Copyright 2015-16 Maxim Integrated Products 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + #include <linux/i2c.h> 12 + #include <linux/module.h> 13 + #include <linux/regmap.h> 14 + #include <linux/slab.h> 15 + #include <sound/pcm.h> 16 + #include <sound/pcm_params.h> 17 + #include <sound/soc.h> 18 + #include <sound/tlv.h> 19 + #include "max98371.h" 20 + 21 + static const char *const monomix_text[] = { 22 + "Left", "Right", "LeftRightDiv2", 23 + }; 24 + 25 + static const char *const hpf_cutoff_txt[] = { 26 + "Disable", "DC Block", "50Hz", 27 + "100Hz", "200Hz", "400Hz", "800Hz", 28 + }; 29 + 30 + static SOC_ENUM_SINGLE_DECL(max98371_monomix, MAX98371_MONOMIX_CFG, 0, 31 + monomix_text); 32 + 33 + static SOC_ENUM_SINGLE_DECL(max98371_hpf_cutoff, MAX98371_HPF, 0, 34 + hpf_cutoff_txt); 35 + 36 + static const DECLARE_TLV_DB_RANGE(max98371_dht_min_gain, 37 + 0, 1, TLV_DB_SCALE_ITEM(537, 66, 0), 38 + 2, 3, TLV_DB_SCALE_ITEM(677, 82, 0), 39 + 4, 5, TLV_DB_SCALE_ITEM(852, 104, 0), 40 + 6, 7, TLV_DB_SCALE_ITEM(1072, 131, 0), 41 + 8, 9, TLV_DB_SCALE_ITEM(1350, 165, 0), 42 + 10, 11, TLV_DB_SCALE_ITEM(1699, 101, 0), 43 + ); 44 + 45 + static const DECLARE_TLV_DB_RANGE(max98371_dht_max_gain, 46 + 0, 1, TLV_DB_SCALE_ITEM(537, 66, 0), 47 + 2, 3, TLV_DB_SCALE_ITEM(677, 82, 0), 48 + 4, 5, TLV_DB_SCALE_ITEM(852, 104, 0), 49 + 6, 7, TLV_DB_SCALE_ITEM(1072, 131, 0), 50 + 8, 9, TLV_DB_SCALE_ITEM(1350, 165, 0), 51 + 10, 11, TLV_DB_SCALE_ITEM(1699, 208, 0), 52 + ); 53 + 54 + static const DECLARE_TLV_DB_RANGE(max98371_dht_rot_gain, 55 + 0, 1, TLV_DB_SCALE_ITEM(-50, -50, 0), 56 + 2, 6, TLV_DB_SCALE_ITEM(-100, -100, 0), 57 + 7, 8, TLV_DB_SCALE_ITEM(-800, -200, 0), 58 + 9, 11, TLV_DB_SCALE_ITEM(-1200, -300, 0), 59 + 12, 13, TLV_DB_SCALE_ITEM(-2000, -200, 0), 60 + 14, 15, TLV_DB_SCALE_ITEM(-2500, -500, 0), 61 + ); 62 + 63 + static const struct reg_default max98371_reg[] = { 64 + { 0x01, 0x00 }, 65 + { 0x02, 0x00 }, 66 + { 0x03, 0x00 }, 67 + { 0x04, 0x00 }, 68 + { 0x05, 0x00 }, 69 + { 0x06, 0x00 }, 70 + { 0x07, 0x00 }, 71 + { 0x08, 0x00 }, 72 + { 0x09, 0x00 }, 73 + { 0x0A, 0x00 }, 74 + { 0x10, 0x06 }, 75 + { 0x11, 0x08 }, 76 + { 0x14, 0x80 }, 77 + { 0x15, 0x00 }, 78 + { 0x16, 0x00 }, 79 + { 0x18, 0x00 }, 80 + { 0x19, 0x00 }, 81 + { 0x1C, 0x00 }, 82 + { 0x1D, 0x00 }, 83 + { 0x1E, 0x00 }, 84 + { 0x1F, 0x00 }, 85 + { 0x20, 0x00 }, 86 + { 0x21, 0x00 }, 87 + { 0x22, 0x00 }, 88 + { 0x23, 0x00 }, 89 + { 0x24, 0x00 }, 90 + { 0x25, 0x00 }, 91 + { 0x26, 0x00 }, 92 + { 0x27, 0x00 }, 93 + { 0x28, 0x00 }, 94 + { 0x29, 0x00 }, 95 + { 0x2A, 0x00 }, 96 + { 0x2B, 0x00 }, 97 + { 0x2C, 0x00 }, 98 + { 0x2D, 0x00 }, 99 + { 0x2E, 0x0B }, 100 + { 0x31, 0x00 }, 101 + { 0x32, 0x18 }, 102 + { 0x33, 0x00 }, 103 + { 0x34, 0x00 }, 104 + { 0x36, 0x00 }, 105 + { 0x37, 0x00 }, 106 + { 0x38, 0x00 }, 107 + { 0x39, 0x00 }, 108 + { 0x3A, 0x00 }, 109 + { 0x3B, 0x00 }, 110 + { 0x3C, 0x00 }, 111 + { 0x3D, 0x00 }, 112 + { 0x3E, 0x00 }, 113 + { 0x3F, 0x00 }, 114 + { 0x40, 0x00 }, 115 + { 0x41, 0x00 }, 116 + { 0x42, 0x00 }, 117 + { 0x43, 0x00 }, 118 + { 0x4A, 0x00 }, 119 + { 0x4B, 0x00 }, 120 + { 0x4C, 0x00 }, 121 + { 0x4D, 0x00 }, 122 + { 0x4E, 0x00 }, 123 + { 0x50, 0x00 }, 124 + { 0x51, 0x00 }, 125 + { 0x55, 0x00 }, 126 + { 0x58, 0x00 }, 127 + { 0x59, 0x00 }, 128 + { 0x5C, 0x00 }, 129 + { 0xFF, 0x43 }, 130 + }; 131 + 132 + static bool max98371_volatile_register(struct device *dev, unsigned int reg) 133 + { 134 + switch (reg) { 135 + case MAX98371_IRQ_CLEAR1: 136 + case MAX98371_IRQ_CLEAR2: 137 + case MAX98371_IRQ_CLEAR3: 138 + case MAX98371_VERSION: 139 + return true; 140 + default: 141 + return false; 142 + } 143 + } 144 + 145 + static bool max98371_readable_register(struct device *dev, unsigned int reg) 146 + { 147 + switch (reg) { 148 + case MAX98371_SOFT_RESET: 149 + return false; 150 + default: 151 + return true; 152 + } 153 + }; 154 + 155 + static const DECLARE_TLV_DB_RANGE(max98371_gain_tlv, 156 + 0, 7, TLV_DB_SCALE_ITEM(0, 50, 0), 157 + 8, 10, TLV_DB_SCALE_ITEM(400, 100, 0) 158 + ); 159 + 160 + static const DECLARE_TLV_DB_RANGE(max98371_noload_gain_tlv, 161 + 0, 11, TLV_DB_SCALE_ITEM(950, 100, 0), 162 + ); 163 + 164 + static const DECLARE_TLV_DB_SCALE(digital_tlv, -6300, 50, 1); 165 + 166 + static const struct snd_kcontrol_new max98371_snd_controls[] = { 167 + SOC_SINGLE_TLV("Speaker Volume", MAX98371_GAIN, 168 + MAX98371_GAIN_SHIFT, (1<<MAX98371_GAIN_WIDTH)-1, 0, 169 + max98371_gain_tlv), 170 + SOC_SINGLE_TLV("Digital Volume", MAX98371_DIGITAL_GAIN, 0, 171 + (1<<MAX98371_DIGITAL_GAIN_WIDTH)-1, 1, digital_tlv), 172 + SOC_SINGLE_TLV("Speaker DHT Max Volume", MAX98371_GAIN, 173 + 0, (1<<MAX98371_DHT_MAX_WIDTH)-1, 0, 174 + max98371_dht_max_gain), 175 + SOC_SINGLE_TLV("Speaker DHT Min Volume", MAX98371_DHT_GAIN, 176 + 0, (1<<MAX98371_DHT_GAIN_WIDTH)-1, 0, 177 + max98371_dht_min_gain), 178 + SOC_SINGLE_TLV("Speaker DHT Rotation Volume", MAX98371_DHT_GAIN, 179 + 0, (1<<MAX98371_DHT_ROT_WIDTH)-1, 0, 180 + max98371_dht_rot_gain), 181 + SOC_SINGLE("DHT Attack Step", MAX98371_DHT, MAX98371_DHT_STEP, 3, 0), 182 + SOC_SINGLE("DHT Attack Rate", MAX98371_DHT, 0, 7, 0), 183 + SOC_ENUM("Monomix Select", max98371_monomix), 184 + SOC_ENUM("HPF Cutoff", max98371_hpf_cutoff), 185 + }; 186 + 187 + static int max98371_dai_set_fmt(struct snd_soc_dai *codec_dai, 188 + unsigned int fmt) 189 + { 190 + struct snd_soc_codec *codec = codec_dai->codec; 191 + struct max98371_priv *max98371 = snd_soc_codec_get_drvdata(codec); 192 + unsigned int val = 0; 193 + 194 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 195 + case SND_SOC_DAIFMT_CBS_CFS: 196 + break; 197 + default: 198 + dev_err(codec->dev, "DAI clock mode unsupported"); 199 + return -EINVAL; 200 + } 201 + 202 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 203 + case SND_SOC_DAIFMT_I2S: 204 + val |= 0; 205 + break; 206 + case SND_SOC_DAIFMT_RIGHT_J: 207 + val |= MAX98371_DAI_RIGHT; 208 + break; 209 + case SND_SOC_DAIFMT_LEFT_J: 210 + val |= MAX98371_DAI_LEFT; 211 + break; 212 + default: 213 + dev_err(codec->dev, "DAI wrong mode unsupported"); 214 + return -EINVAL; 215 + } 216 + regmap_update_bits(max98371->regmap, MAX98371_FMT, 217 + MAX98371_FMT_MODE_MASK, val); 218 + return 0; 219 + } 220 + 221 + static int max98371_dai_hw_params(struct snd_pcm_substream *substream, 222 + struct snd_pcm_hw_params *params, 223 + struct snd_soc_dai *dai) 224 + { 225 + struct snd_soc_codec *codec = dai->codec; 226 + struct max98371_priv *max98371 = snd_soc_codec_get_drvdata(codec); 227 + int blr_clk_ratio, ch_size, channels = params_channels(params); 228 + int rate = params_rate(params); 229 + 230 + switch (params_format(params)) { 231 + case SNDRV_PCM_FORMAT_S8: 232 + regmap_update_bits(max98371->regmap, MAX98371_FMT, 233 + MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_16); 234 + ch_size = 8; 235 + break; 236 + case SNDRV_PCM_FORMAT_S16_LE: 237 + regmap_update_bits(max98371->regmap, MAX98371_FMT, 238 + MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_16); 239 + ch_size = 16; 240 + break; 241 + case SNDRV_PCM_FORMAT_S24_LE: 242 + regmap_update_bits(max98371->regmap, MAX98371_FMT, 243 + MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_32); 244 + ch_size = 24; 245 + break; 246 + case SNDRV_PCM_FORMAT_S32_LE: 247 + regmap_update_bits(max98371->regmap, MAX98371_FMT, 248 + MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_32); 249 + ch_size = 32; 250 + break; 251 + default: 252 + return -EINVAL; 253 + } 254 + 255 + /* BCLK/LRCLK ratio calculation */ 256 + blr_clk_ratio = channels * ch_size; 257 + switch (blr_clk_ratio) { 258 + case 32: 259 + regmap_update_bits(max98371->regmap, 260 + MAX98371_DAI_CLK, 261 + MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_32); 262 + break; 263 + case 48: 264 + regmap_update_bits(max98371->regmap, 265 + MAX98371_DAI_CLK, 266 + MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_48); 267 + break; 268 + case 64: 269 + regmap_update_bits(max98371->regmap, 270 + MAX98371_DAI_CLK, 271 + MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_64); 272 + break; 273 + default: 274 + return -EINVAL; 275 + } 276 + 277 + switch (rate) { 278 + case 32000: 279 + regmap_update_bits(max98371->regmap, 280 + MAX98371_SPK_SR, 281 + MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_32); 282 + break; 283 + case 44100: 284 + regmap_update_bits(max98371->regmap, 285 + MAX98371_SPK_SR, 286 + MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_44); 287 + break; 288 + case 48000: 289 + regmap_update_bits(max98371->regmap, 290 + MAX98371_SPK_SR, 291 + MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_48); 292 + break; 293 + case 88200: 294 + regmap_update_bits(max98371->regmap, 295 + MAX98371_SPK_SR, 296 + MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_88); 297 + break; 298 + case 96000: 299 + regmap_update_bits(max98371->regmap, 300 + MAX98371_SPK_SR, 301 + MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_96); 302 + break; 303 + default: 304 + return -EINVAL; 305 + } 306 + 307 + /* enabling both the RX channels*/ 308 + regmap_update_bits(max98371->regmap, MAX98371_MONOMIX_SRC, 309 + MAX98371_MONOMIX_SRC_MASK, MONOMIX_RX_0_1); 310 + regmap_update_bits(max98371->regmap, MAX98371_DAI_CHANNEL, 311 + MAX98371_CHANNEL_MASK, MAX98371_CHANNEL_MASK); 312 + return 0; 313 + } 314 + 315 + static const struct snd_soc_dapm_widget max98371_dapm_widgets[] = { 316 + SND_SOC_DAPM_DAC("DAC", NULL, MAX98371_SPK_ENABLE, 0, 0), 317 + SND_SOC_DAPM_SUPPLY("Global Enable", MAX98371_GLOBAL_ENABLE, 318 + 0, 0, NULL, 0), 319 + SND_SOC_DAPM_OUTPUT("SPK_OUT"), 320 + }; 321 + 322 + static const struct snd_soc_dapm_route max98371_audio_map[] = { 323 + {"DAC", NULL, "HiFi Playback"}, 324 + {"SPK_OUT", NULL, "DAC"}, 325 + {"SPK_OUT", NULL, "Global Enable"}, 326 + }; 327 + 328 + #define MAX98371_RATES SNDRV_PCM_RATE_8000_48000 329 + #define MAX98371_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \ 330 + SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE) 331 + 332 + static const struct snd_soc_dai_ops max98371_dai_ops = { 333 + .set_fmt = max98371_dai_set_fmt, 334 + .hw_params = max98371_dai_hw_params, 335 + }; 336 + 337 + static struct snd_soc_dai_driver max98371_dai[] = { 338 + { 339 + .name = "max98371-aif1", 340 + .playback = { 341 + .stream_name = "HiFi Playback", 342 + .channels_min = 1, 343 + .channels_max = 2, 344 + .rates = SNDRV_PCM_RATE_8000_48000, 345 + .formats = MAX98371_FORMATS, 346 + }, 347 + .ops = &max98371_dai_ops, 348 + } 349 + }; 350 + 351 + static const struct snd_soc_codec_driver max98371_codec = { 352 + .controls = max98371_snd_controls, 353 + .num_controls = ARRAY_SIZE(max98371_snd_controls), 354 + .dapm_routes = max98371_audio_map, 355 + .num_dapm_routes = ARRAY_SIZE(max98371_audio_map), 356 + .dapm_widgets = max98371_dapm_widgets, 357 + .num_dapm_widgets = ARRAY_SIZE(max98371_dapm_widgets), 358 + }; 359 + 360 + static const struct regmap_config max98371_regmap = { 361 + .reg_bits = 8, 362 + .val_bits = 8, 363 + .max_register = MAX98371_VERSION, 364 + .reg_defaults = max98371_reg, 365 + .num_reg_defaults = ARRAY_SIZE(max98371_reg), 366 + .volatile_reg = max98371_volatile_register, 367 + .readable_reg = max98371_readable_register, 368 + .cache_type = REGCACHE_RBTREE, 369 + }; 370 + 371 + static int max98371_i2c_probe(struct i2c_client *i2c, 372 + const struct i2c_device_id *id) 373 + { 374 + struct max98371_priv *max98371; 375 + int ret, reg; 376 + 377 + max98371 = devm_kzalloc(&i2c->dev, 378 + sizeof(*max98371), GFP_KERNEL); 379 + if (!max98371) 380 + return -ENOMEM; 381 + 382 + i2c_set_clientdata(i2c, max98371); 383 + max98371->regmap = devm_regmap_init_i2c(i2c, &max98371_regmap); 384 + if (IS_ERR(max98371->regmap)) { 385 + ret = PTR_ERR(max98371->regmap); 386 + dev_err(&i2c->dev, 387 + "Failed to allocate regmap: %d\n", ret); 388 + return ret; 389 + } 390 + 391 + ret = regmap_read(max98371->regmap, MAX98371_VERSION, &reg); 392 + if (ret < 0) { 393 + dev_info(&i2c->dev, "device error %d\n", ret); 394 + return ret; 395 + } 396 + dev_info(&i2c->dev, "device version %x\n", reg); 397 + 398 + ret = snd_soc_register_codec(&i2c->dev, &max98371_codec, 399 + max98371_dai, ARRAY_SIZE(max98371_dai)); 400 + if (ret < 0) { 401 + dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); 402 + return ret; 403 + } 404 + return ret; 405 + } 406 + 407 + static int max98371_i2c_remove(struct i2c_client *client) 408 + { 409 + snd_soc_unregister_codec(&client->dev); 410 + return 0; 411 + } 412 + 413 + static const struct i2c_device_id max98371_i2c_id[] = { 414 + { "max98371", 0 }, 415 + }; 416 + 417 + MODULE_DEVICE_TABLE(i2c, max98371_i2c_id); 418 + 419 + static const struct of_device_id max98371_of_match[] = { 420 + { .compatible = "maxim,max98371", }, 421 + { } 422 + }; 423 + MODULE_DEVICE_TABLE(of, max98371_of_match); 424 + 425 + static struct i2c_driver max98371_i2c_driver = { 426 + .driver = { 427 + .name = "max98371", 428 + .owner = THIS_MODULE, 429 + .pm = NULL, 430 + .of_match_table = of_match_ptr(max98371_of_match), 431 + }, 432 + .probe = max98371_i2c_probe, 433 + .remove = max98371_i2c_remove, 434 + .id_table = max98371_i2c_id, 435 + }; 436 + 437 + module_i2c_driver(max98371_i2c_driver); 438 + 439 + MODULE_AUTHOR("anish kumar <yesanishhere@gmail.com>"); 440 + MODULE_DESCRIPTION("ALSA SoC MAX98371 driver"); 441 + MODULE_LICENSE("GPL");
+67
sound/soc/codecs/max98371.h
··· 1 + /* 2 + * max98371.h -- MAX98371 ALSA SoC Audio driver 3 + * 4 + * Copyright 2011-2012 Maxim Integrated Products 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + #ifndef _MAX98371_H 12 + #define _MAX98371_H 13 + 14 + #define MAX98371_IRQ_CLEAR1 0x01 15 + #define MAX98371_IRQ_CLEAR2 0x02 16 + #define MAX98371_IRQ_CLEAR3 0x03 17 + #define MAX98371_DAI_CLK 0x10 18 + #define MAX98371_DAI_BSEL_MASK 0xF 19 + #define MAX98371_DAI_BSEL_32 2 20 + #define MAX98371_DAI_BSEL_48 3 21 + #define MAX98371_DAI_BSEL_64 4 22 + #define MAX98371_SPK_SR 0x11 23 + #define MAX98371_SPK_SR_MASK 0xF 24 + #define MAX98371_SPK_SR_32 6 25 + #define MAX98371_SPK_SR_44 7 26 + #define MAX98371_SPK_SR_48 8 27 + #define MAX98371_SPK_SR_88 10 28 + #define MAX98371_SPK_SR_96 11 29 + #define MAX98371_DAI_CHANNEL 0x15 30 + #define MAX98371_CHANNEL_MASK 0x3 31 + #define MAX98371_MONOMIX_SRC 0x18 32 + #define MAX98371_MONOMIX_CFG 0x19 33 + #define MAX98371_HPF 0x1C 34 + #define MAX98371_MONOMIX_SRC_MASK 0xFF 35 + #define MONOMIX_RX_0_1 ((0x1)<<(4)) 36 + #define M98371_DAI_CHANNEL_I2S 0x3 37 + #define MAX98371_DIGITAL_GAIN 0x2D 38 + #define MAX98371_DIGITAL_GAIN_WIDTH 0x7 39 + #define MAX98371_GAIN 0x2E 40 + #define MAX98371_GAIN_SHIFT 0x4 41 + #define MAX98371_GAIN_WIDTH 0x4 42 + #define MAX98371_DHT_MAX_WIDTH 4 43 + #define MAX98371_FMT 0x14 44 + #define MAX98371_CHANSZ_WIDTH 6 45 + #define MAX98371_FMT_MASK ((0x3)<<(MAX98371_CHANSZ_WIDTH)) 46 + #define MAX98371_FMT_MODE_MASK ((0x7)<<(3)) 47 + #define MAX98371_DAI_LEFT ((0x1)<<(3)) 48 + #define MAX98371_DAI_RIGHT ((0x2)<<(3)) 49 + #define MAX98371_DAI_CHANSZ_16 ((1)<<(MAX98371_CHANSZ_WIDTH)) 50 + #define MAX98371_DAI_CHANSZ_24 ((2)<<(MAX98371_CHANSZ_WIDTH)) 51 + #define MAX98371_DAI_CHANSZ_32 ((3)<<(MAX98371_CHANSZ_WIDTH)) 52 + #define MAX98371_DHT 0x32 53 + #define MAX98371_DHT_STEP 0x3 54 + #define MAX98371_DHT_GAIN 0x31 55 + #define MAX98371_DHT_GAIN_WIDTH 0x4 56 + #define MAX98371_DHT_ROT_WIDTH 0x4 57 + #define MAX98371_SPK_ENABLE 0x4A 58 + #define MAX98371_GLOBAL_ENABLE 0x50 59 + #define MAX98371_SOFT_RESET 0x51 60 + #define MAX98371_VERSION 0xFF 61 + 62 + 63 + struct max98371_priv { 64 + struct regmap *regmap; 65 + struct snd_soc_codec *codec; 66 + }; 67 + #endif
+23 -28
sound/soc/codecs/rt298.c
··· 276 276 } else { 277 277 *mic = false; 278 278 regmap_write(rt298->regmap, RT298_SET_MIC1, 0x20); 279 + regmap_update_bits(rt298->regmap, 280 + RT298_CBJ_CTRL1, 0x0400, 0x0000); 279 281 } 280 282 } else { 281 283 regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); ··· 484 482 snd_soc_update_bits(codec, 485 483 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), 486 484 0x7080, 0x7000); 485 + /* If MCLK doesn't exist, reset AD filter */ 486 + if (!(snd_soc_read(codec, RT298_VAD_CTRL) & 0x200)) { 487 + pr_info("NO MCLK\n"); 488 + switch (nid) { 489 + case RT298_ADC_IN1: 490 + snd_soc_update_bits(codec, 491 + RT298_D_FILTER_CTRL, 0x2, 0x2); 492 + mdelay(10); 493 + snd_soc_update_bits(codec, 494 + RT298_D_FILTER_CTRL, 0x2, 0x0); 495 + break; 496 + case RT298_ADC_IN2: 497 + snd_soc_update_bits(codec, 498 + RT298_D_FILTER_CTRL, 0x4, 0x4); 499 + mdelay(10); 500 + snd_soc_update_bits(codec, 501 + RT298_D_FILTER_CTRL, 0x4, 0x0); 502 + break; 503 + } 504 + } 487 505 break; 488 506 case SND_SOC_DAPM_PRE_PMD: 489 507 snd_soc_update_bits(codec, ··· 542 520 return 0; 543 521 } 544 522 545 - static int rt298_vref_event(struct snd_soc_dapm_widget *w, 546 - struct snd_kcontrol *kcontrol, int event) 547 - { 548 - struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 549 - 550 - switch (event) { 551 - case SND_SOC_DAPM_PRE_PMU: 552 - snd_soc_update_bits(codec, 553 - RT298_CBJ_CTRL1, 0x0400, 0x0000); 554 - mdelay(50); 555 - break; 556 - default: 557 - return 0; 558 - } 559 - 560 - return 0; 561 - } 562 - 563 523 static const struct snd_soc_dapm_widget rt298_dapm_widgets[] = { 564 524 565 525 SND_SOC_DAPM_SUPPLY_S("HV", 1, RT298_POWER_CTRL1, 566 526 12, 1, NULL, 0), 567 527 SND_SOC_DAPM_SUPPLY("VREF", RT298_POWER_CTRL1, 568 - 0, 1, rt298_vref_event, SND_SOC_DAPM_PRE_PMU), 528 + 0, 1, NULL, 0), 569 529 SND_SOC_DAPM_SUPPLY_S("BG_MBIAS", 1, RT298_POWER_CTRL2, 570 530 1, 0, NULL, 0), 571 531 SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT298_POWER_CTRL2, ··· 938 934 } 939 935 break; 940 936 941 - case SND_SOC_BIAS_ON: 942 - mdelay(30); 943 - snd_soc_update_bits(codec, 944 - RT298_CBJ_CTRL1, 0x0400, 0x0400); 945 - 946 - break; 947 - 948 937 case SND_SOC_BIAS_STANDBY: 949 938 snd_soc_write(codec, 950 939 RT298_SET_AUDIO_POWER, AC_PWRST_D3); 951 - snd_soc_update_bits(codec, 952 - RT298_CBJ_CTRL1, 0x0400, 0x0000); 953 940 break; 954 941 955 942 default:
+2
sound/soc/codecs/rt298.h
··· 137 137 #define RT298_A_BIAS_CTRL2 0x02 138 138 #define RT298_POWER_CTRL1 0x03 139 139 #define RT298_A_BIAS_CTRL3 0x04 140 + #define RT298_D_FILTER_CTRL 0x05 140 141 #define RT298_POWER_CTRL2 0x08 141 142 #define RT298_I2S_CTRL1 0x09 142 143 #define RT298_I2S_CTRL2 0x0a ··· 149 148 #define RT298_IRQ_CTRL 0x33 150 149 #define RT298_WIND_FILTER_CTRL 0x46 151 150 #define RT298_PLL_CTRL1 0x49 151 + #define RT298_VAD_CTRL 0x4e 152 152 #define RT298_CBJ_CTRL1 0x4f 153 153 #define RT298_CBJ_CTRL2 0x50 154 154 #define RT298_PLL_CTRL 0x63
+5 -19
sound/soc/codecs/rt5677.c
··· 1241 1241 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); 1242 1242 asrc_setting = (asrc_setting & RT5677_AD_STO1_CLK_SEL_MASK) >> 1243 1243 RT5677_AD_STO1_CLK_SEL_SFT; 1244 - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && 1245 - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) 1246 - return 1; 1247 1244 break; 1248 1245 1249 1246 case 10: 1250 1247 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); 1251 1248 asrc_setting = (asrc_setting & RT5677_AD_STO2_CLK_SEL_MASK) >> 1252 1249 RT5677_AD_STO2_CLK_SEL_SFT; 1253 - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && 1254 - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) 1255 - return 1; 1256 1250 break; 1257 1251 1258 1252 case 9: 1259 1253 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); 1260 1254 asrc_setting = (asrc_setting & RT5677_AD_STO3_CLK_SEL_MASK) >> 1261 1255 RT5677_AD_STO3_CLK_SEL_SFT; 1262 - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && 1263 - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) 1264 - return 1; 1265 1256 break; 1266 1257 1267 1258 case 8: 1268 1259 regmap_read(rt5677->regmap, RT5677_ASRC_5, &asrc_setting); 1269 1260 asrc_setting = (asrc_setting & RT5677_AD_STO4_CLK_SEL_MASK) >> 1270 1261 RT5677_AD_STO4_CLK_SEL_SFT; 1271 - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && 1272 - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) 1273 - return 1; 1274 1262 break; 1275 1263 1276 1264 case 7: 1277 1265 regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting); 1278 1266 asrc_setting = (asrc_setting & RT5677_AD_MONOL_CLK_SEL_MASK) >> 1279 1267 RT5677_AD_MONOL_CLK_SEL_SFT; 1280 - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && 1281 - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) 1282 - return 1; 1283 1268 break; 1284 1269 1285 1270 case 6: 1286 1271 regmap_read(rt5677->regmap, RT5677_ASRC_6, &asrc_setting); 1287 1272 asrc_setting = (asrc_setting & RT5677_AD_MONOR_CLK_SEL_MASK) >> 1288 1273 RT5677_AD_MONOR_CLK_SEL_SFT; 1289 - if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && 1290 - asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) 1291 - return 1; 1292 1274 break; 1293 1275 1294 1276 default: 1295 - break; 1277 + return 0; 1296 1278 } 1279 + 1280 + if (asrc_setting >= RT5677_CLK_SEL_I2S1_ASRC && 1281 + asrc_setting <= RT5677_CLK_SEL_I2S6_ASRC) 1282 + return 1; 1297 1283 1298 1284 return 0; 1299 1285 }
+129 -12
sound/soc/codecs/tas571x.c
··· 4 4 * Copyright (C) 2015 Google, Inc. 5 5 * Copyright (c) 2013 Daniel Mack <zonque@gmail.com> 6 6 * 7 + * TAS5721 support: 8 + * Copyright (C) 2016 Petr Kulhavy, Barix AG <petr@barix.com> 9 + * 7 10 * This program is free software; you can redistribute it and/or modify 8 11 * it under the terms of the GNU General Public License as published by 9 12 * the Free Software Foundation; either version 2 of the License, or ··· 60 57 case TAS571X_CH1_VOL_REG: 61 58 case TAS571X_CH2_VOL_REG: 62 59 return priv->chip->vol_reg_size; 60 + case TAS571X_INPUT_MUX_REG: 61 + case TAS571X_CH4_SRC_SELECT_REG: 62 + case TAS571X_PWM_MUX_REG: 63 + return 4; 63 64 default: 64 65 return 1; 65 66 } ··· 174 167 TAS571X_SDI_FMT_MASK, val); 175 168 } 176 169 170 + static int tas571x_mute(struct snd_soc_dai *dai, int mute) 171 + { 172 + struct snd_soc_codec *codec = dai->codec; 173 + u8 sysctl2; 174 + int ret; 175 + 176 + sysctl2 = mute ? TAS571X_SYS_CTRL_2_SDN_MASK : 0; 177 + 178 + ret = snd_soc_update_bits(codec, 179 + TAS571X_SYS_CTRL_2_REG, 180 + TAS571X_SYS_CTRL_2_SDN_MASK, 181 + sysctl2); 182 + usleep_range(1000, 2000); 183 + 184 + return ret; 185 + } 186 + 177 187 static int tas571x_set_bias_level(struct snd_soc_codec *codec, 178 188 enum snd_soc_bias_level level) 179 189 { ··· 238 214 static const struct snd_soc_dai_ops tas571x_dai_ops = { 239 215 .set_fmt = tas571x_set_dai_fmt, 240 216 .hw_params = tas571x_hw_params, 217 + .digital_mute = tas571x_mute, 241 218 }; 242 219 243 220 static const char *const tas5711_supply_names[] = { ··· 266 241 1, 1), 267 242 }; 268 243 244 + static const struct regmap_range tas571x_readonly_regs_range[] = { 245 + regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_DEV_ID_REG), 246 + }; 247 + 248 + static const struct regmap_range tas571x_volatile_regs_range[] = { 249 + regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_ERR_STATUS_REG), 250 + regmap_reg_range(TAS571X_OSC_TRIM_REG, TAS571X_OSC_TRIM_REG), 251 + }; 252 + 253 + static const struct regmap_access_table tas571x_write_regs = { 254 + .no_ranges = tas571x_readonly_regs_range, 255 + .n_no_ranges = ARRAY_SIZE(tas571x_readonly_regs_range), 256 + }; 257 + 258 + static const struct regmap_access_table tas571x_volatile_regs = { 259 + .yes_ranges = tas571x_volatile_regs_range, 260 + .n_yes_ranges = ARRAY_SIZE(tas571x_volatile_regs_range), 261 + 262 + }; 263 + 269 264 static const struct reg_default tas5711_reg_defaults[] = { 270 265 { 0x04, 0x05 }, 271 266 { 0x05, 0x40 }, ··· 305 260 .reg_defaults = tas5711_reg_defaults, 306 261 .num_reg_defaults = ARRAY_SIZE(tas5711_reg_defaults), 307 262 .cache_type = REGCACHE_RBTREE, 263 + .wr_table = &tas571x_write_regs, 264 + .volatile_table = &tas571x_volatile_regs, 308 265 }; 309 266 310 267 static const struct tas571x_chip tas5711_chip = { ··· 361 314 .reg_defaults = tas5717_reg_defaults, 362 315 .num_reg_defaults = ARRAY_SIZE(tas5717_reg_defaults), 363 316 .cache_type = REGCACHE_RBTREE, 317 + .wr_table = &tas571x_write_regs, 318 + .volatile_table = &tas571x_volatile_regs, 364 319 }; 365 320 366 321 /* This entry is reused for tas5719 as the software interface is identical. */ ··· 373 324 .num_controls = ARRAY_SIZE(tas5717_controls), 374 325 .regmap_config = &tas5717_regmap_config, 375 326 .vol_reg_size = 2, 327 + }; 328 + 329 + static const char *const tas5721_supply_names[] = { 330 + "AVDD", 331 + "DVDD", 332 + "DRVDD", 333 + "PVDD", 334 + }; 335 + 336 + static const struct snd_kcontrol_new tas5721_controls[] = { 337 + SOC_SINGLE_TLV("Master Volume", 338 + TAS571X_MVOL_REG, 339 + 0, 0xff, 1, tas5711_volume_tlv), 340 + SOC_DOUBLE_R_TLV("Speaker Volume", 341 + TAS571X_CH1_VOL_REG, 342 + TAS571X_CH2_VOL_REG, 343 + 0, 0xff, 1, tas5711_volume_tlv), 344 + SOC_DOUBLE("Speaker Switch", 345 + TAS571X_SOFT_MUTE_REG, 346 + TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, 347 + 1, 1), 348 + }; 349 + 350 + static const struct reg_default tas5721_reg_defaults[] = { 351 + {TAS571X_CLK_CTRL_REG, 0x6c}, 352 + {TAS571X_DEV_ID_REG, 0x00}, 353 + {TAS571X_ERR_STATUS_REG, 0x00}, 354 + {TAS571X_SYS_CTRL_1_REG, 0xa0}, 355 + {TAS571X_SDI_REG, 0x05}, 356 + {TAS571X_SYS_CTRL_2_REG, 0x40}, 357 + {TAS571X_SOFT_MUTE_REG, 0x00}, 358 + {TAS571X_MVOL_REG, 0xff}, 359 + {TAS571X_CH1_VOL_REG, 0x30}, 360 + {TAS571X_CH2_VOL_REG, 0x30}, 361 + {TAS571X_CH3_VOL_REG, 0x30}, 362 + {TAS571X_VOL_CFG_REG, 0x91}, 363 + {TAS571X_MODULATION_LIMIT_REG, 0x02}, 364 + {TAS571X_IC_DELAY_CH1_REG, 0xac}, 365 + {TAS571X_IC_DELAY_CH2_REG, 0x54}, 366 + {TAS571X_IC_DELAY_CH3_REG, 0xac}, 367 + {TAS571X_IC_DELAY_CH4_REG, 0x54}, 368 + {TAS571X_PWM_CH_SDN_GROUP_REG, 0x30}, 369 + {TAS571X_START_STOP_PERIOD_REG, 0x0f}, 370 + {TAS571X_OSC_TRIM_REG, 0x82}, 371 + {TAS571X_BKND_ERR_REG, 0x02}, 372 + {TAS571X_INPUT_MUX_REG, 0x17772}, 373 + {TAS571X_CH4_SRC_SELECT_REG, 0x4303}, 374 + {TAS571X_PWM_MUX_REG, 0x1021345}, 375 + }; 376 + 377 + static const struct regmap_config tas5721_regmap_config = { 378 + .reg_bits = 8, 379 + .val_bits = 32, 380 + .max_register = 0xff, 381 + .reg_read = tas571x_reg_read, 382 + .reg_write = tas571x_reg_write, 383 + .reg_defaults = tas5721_reg_defaults, 384 + .num_reg_defaults = ARRAY_SIZE(tas5721_reg_defaults), 385 + .cache_type = REGCACHE_RBTREE, 386 + .wr_table = &tas571x_write_regs, 387 + .volatile_table = &tas571x_volatile_regs, 388 + }; 389 + 390 + 391 + static const struct tas571x_chip tas5721_chip = { 392 + .supply_names = tas5721_supply_names, 393 + .num_supply_names = ARRAY_SIZE(tas5721_supply_names), 394 + .controls = tas5711_controls, 395 + .num_controls = ARRAY_SIZE(tas5711_controls), 396 + .regmap_config = &tas5721_regmap_config, 397 + .vol_reg_size = 1, 376 398 }; 377 399 378 400 static const struct snd_soc_dapm_widget tas571x_dapm_widgets[] = { ··· 506 386 i2c_set_clientdata(client, priv); 507 387 508 388 of_id = of_match_device(tas571x_of_match, dev); 509 - if (!of_id) { 510 - dev_err(dev, "Unknown device type\n"); 511 - return -EINVAL; 512 - } 513 - priv->chip = of_id->data; 389 + if (of_id) 390 + priv->chip = of_id->data; 391 + else 392 + priv->chip = (void *) id->driver_data; 514 393 515 394 priv->mclk = devm_clk_get(dev, "mclk"); 516 395 if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) { ··· 564 445 if (ret) 565 446 return ret; 566 447 567 - ret = regmap_update_bits(priv->regmap, TAS571X_SYS_CTRL_2_REG, 568 - TAS571X_SYS_CTRL_2_SDN_MASK, 0); 569 - if (ret) 570 - return ret; 571 448 572 449 memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver)); 573 450 priv->codec_driver.controls = priv->chip->controls; ··· 601 486 { .compatible = "ti,tas5711", .data = &tas5711_chip, }, 602 487 { .compatible = "ti,tas5717", .data = &tas5717_chip, }, 603 488 { .compatible = "ti,tas5719", .data = &tas5717_chip, }, 489 + { .compatible = "ti,tas5721", .data = &tas5721_chip, }, 604 490 { } 605 491 }; 606 492 MODULE_DEVICE_TABLE(of, tas571x_of_match); 607 493 608 494 static const struct i2c_device_id tas571x_i2c_id[] = { 609 - { "tas5711", 0 }, 610 - { "tas5717", 0 }, 611 - { "tas5719", 0 }, 495 + { "tas5711", (kernel_ulong_t) &tas5711_chip }, 496 + { "tas5717", (kernel_ulong_t) &tas5717_chip }, 497 + { "tas5719", (kernel_ulong_t) &tas5717_chip }, 498 + { "tas5721", (kernel_ulong_t) &tas5721_chip }, 612 499 { } 613 500 }; 614 501 MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id);
+22
sound/soc/codecs/tas571x.h
··· 13 13 #define _TAS571X_H 14 14 15 15 /* device registers */ 16 + #define TAS571X_CLK_CTRL_REG 0x00 17 + #define TAS571X_DEV_ID_REG 0x01 18 + #define TAS571X_ERR_STATUS_REG 0x02 19 + #define TAS571X_SYS_CTRL_1_REG 0x03 16 20 #define TAS571X_SDI_REG 0x04 17 21 #define TAS571X_SDI_FMT_MASK 0x0f 18 22 ··· 31 27 #define TAS571X_MVOL_REG 0x07 32 28 #define TAS571X_CH1_VOL_REG 0x08 33 29 #define TAS571X_CH2_VOL_REG 0x09 30 + #define TAS571X_CH3_VOL_REG 0x0a 31 + #define TAS571X_VOL_CFG_REG 0x0e 32 + #define TAS571X_MODULATION_LIMIT_REG 0x10 33 + #define TAS571X_IC_DELAY_CH1_REG 0x11 34 + #define TAS571X_IC_DELAY_CH2_REG 0x12 35 + #define TAS571X_IC_DELAY_CH3_REG 0x13 36 + #define TAS571X_IC_DELAY_CH4_REG 0x14 34 37 38 + #define TAS571X_PWM_CH_SDN_GROUP_REG 0x19 /* N/A on TAS5717, TAS5719 */ 39 + #define TAS571X_PWM_CH1_SDN_MASK (1<<0) 40 + #define TAS571X_PWM_CH2_SDN_SHIFT (1<<1) 41 + #define TAS571X_PWM_CH3_SDN_SHIFT (1<<2) 42 + #define TAS571X_PWM_CH4_SDN_SHIFT (1<<3) 43 + 44 + #define TAS571X_START_STOP_PERIOD_REG 0x1a 35 45 #define TAS571X_OSC_TRIM_REG 0x1b 46 + #define TAS571X_BKND_ERR_REG 0x1c 47 + #define TAS571X_INPUT_MUX_REG 0x20 48 + #define TAS571X_CH4_SRC_SELECT_REG 0x21 49 + #define TAS571X_PWM_MUX_REG 0x25 36 50 37 51 #endif /* _TAS571X_H */
+620
sound/soc/codecs/tas5720.c
··· 1 + /* 2 + * tas5720.c - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier 3 + * 4 + * Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com 5 + * 6 + * Author: Andreas Dannenberg <dannenberg@ti.com> 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License 10 + * version 2 as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, but 13 + * WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + */ 17 + 18 + #include <linux/module.h> 19 + #include <linux/errno.h> 20 + #include <linux/device.h> 21 + #include <linux/i2c.h> 22 + #include <linux/pm_runtime.h> 23 + #include <linux/regmap.h> 24 + #include <linux/slab.h> 25 + #include <linux/regulator/consumer.h> 26 + #include <linux/delay.h> 27 + 28 + #include <sound/pcm.h> 29 + #include <sound/pcm_params.h> 30 + #include <sound/soc.h> 31 + #include <sound/soc-dapm.h> 32 + #include <sound/tlv.h> 33 + 34 + #include "tas5720.h" 35 + 36 + /* Define how often to check (and clear) the fault status register (in ms) */ 37 + #define TAS5720_FAULT_CHECK_INTERVAL 200 38 + 39 + static const char * const tas5720_supply_names[] = { 40 + "dvdd", /* Digital power supply. Connect to 3.3-V supply. */ 41 + "pvdd", /* Class-D amp and analog power supply (connected). */ 42 + }; 43 + 44 + #define TAS5720_NUM_SUPPLIES ARRAY_SIZE(tas5720_supply_names) 45 + 46 + struct tas5720_data { 47 + struct snd_soc_codec *codec; 48 + struct regmap *regmap; 49 + struct i2c_client *tas5720_client; 50 + struct regulator_bulk_data supplies[TAS5720_NUM_SUPPLIES]; 51 + struct delayed_work fault_check_work; 52 + unsigned int last_fault; 53 + }; 54 + 55 + static int tas5720_hw_params(struct snd_pcm_substream *substream, 56 + struct snd_pcm_hw_params *params, 57 + struct snd_soc_dai *dai) 58 + { 59 + struct snd_soc_codec *codec = dai->codec; 60 + unsigned int rate = params_rate(params); 61 + bool ssz_ds; 62 + int ret; 63 + 64 + switch (rate) { 65 + case 44100: 66 + case 48000: 67 + ssz_ds = false; 68 + break; 69 + case 88200: 70 + case 96000: 71 + ssz_ds = true; 72 + break; 73 + default: 74 + dev_err(codec->dev, "unsupported sample rate: %u\n", rate); 75 + return -EINVAL; 76 + } 77 + 78 + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG, 79 + TAS5720_SSZ_DS, ssz_ds); 80 + if (ret < 0) { 81 + dev_err(codec->dev, "error setting sample rate: %d\n", ret); 82 + return ret; 83 + } 84 + 85 + return 0; 86 + } 87 + 88 + static int tas5720_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 89 + { 90 + struct snd_soc_codec *codec = dai->codec; 91 + u8 serial_format; 92 + int ret; 93 + 94 + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { 95 + dev_vdbg(codec->dev, "DAI Format master is not found\n"); 96 + return -EINVAL; 97 + } 98 + 99 + switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | 100 + SND_SOC_DAIFMT_INV_MASK)) { 101 + case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): 102 + /* 1st data bit occur one BCLK cycle after the frame sync */ 103 + serial_format = TAS5720_SAIF_I2S; 104 + break; 105 + case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF): 106 + /* 107 + * Note that although the TAS5720 does not have a dedicated DSP 108 + * mode it doesn't care about the LRCLK duty cycle during TDM 109 + * operation. Therefore we can use the device's I2S mode with 110 + * its delaying of the 1st data bit to receive DSP_A formatted 111 + * data. See device datasheet for additional details. 112 + */ 113 + serial_format = TAS5720_SAIF_I2S; 114 + break; 115 + case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF): 116 + /* 117 + * Similar to DSP_A, we can use the fact that the TAS5720 does 118 + * not care about the LRCLK duty cycle during TDM to receive 119 + * DSP_B formatted data in LEFTJ mode (no delaying of the 1st 120 + * data bit). 121 + */ 122 + serial_format = TAS5720_SAIF_LEFTJ; 123 + break; 124 + case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF): 125 + /* No delay after the frame sync */ 126 + serial_format = TAS5720_SAIF_LEFTJ; 127 + break; 128 + default: 129 + dev_vdbg(codec->dev, "DAI Format is not found\n"); 130 + return -EINVAL; 131 + } 132 + 133 + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG, 134 + TAS5720_SAIF_FORMAT_MASK, 135 + serial_format); 136 + if (ret < 0) { 137 + dev_err(codec->dev, "error setting SAIF format: %d\n", ret); 138 + return ret; 139 + } 140 + 141 + return 0; 142 + } 143 + 144 + static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai, 145 + unsigned int tx_mask, unsigned int rx_mask, 146 + int slots, int slot_width) 147 + { 148 + struct snd_soc_codec *codec = dai->codec; 149 + unsigned int first_slot; 150 + int ret; 151 + 152 + if (!tx_mask) { 153 + dev_err(codec->dev, "tx masks must not be 0\n"); 154 + return -EINVAL; 155 + } 156 + 157 + /* 158 + * Determine the first slot that is being requested. We will only 159 + * use the first slot that is found since the TAS5720 is a mono 160 + * amplifier. 161 + */ 162 + first_slot = __ffs(tx_mask); 163 + 164 + if (first_slot > 7) { 165 + dev_err(codec->dev, "slot selection out of bounds (%u)\n", 166 + first_slot); 167 + return -EINVAL; 168 + } 169 + 170 + /* Enable manual TDM slot selection (instead of I2C ID based) */ 171 + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG, 172 + TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC); 173 + if (ret < 0) 174 + goto error_snd_soc_update_bits; 175 + 176 + /* Configure the TDM slot to process audio from */ 177 + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, 178 + TAS5720_TDM_SLOT_SEL_MASK, first_slot); 179 + if (ret < 0) 180 + goto error_snd_soc_update_bits; 181 + 182 + return 0; 183 + 184 + error_snd_soc_update_bits: 185 + dev_err(codec->dev, "error configuring TDM mode: %d\n", ret); 186 + return ret; 187 + } 188 + 189 + static int tas5720_mute(struct snd_soc_dai *dai, int mute) 190 + { 191 + struct snd_soc_codec *codec = dai->codec; 192 + int ret; 193 + 194 + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, 195 + TAS5720_MUTE, mute ? TAS5720_MUTE : 0); 196 + if (ret < 0) { 197 + dev_err(codec->dev, "error (un-)muting device: %d\n", ret); 198 + return ret; 199 + } 200 + 201 + return 0; 202 + } 203 + 204 + static void tas5720_fault_check_work(struct work_struct *work) 205 + { 206 + struct tas5720_data *tas5720 = container_of(work, struct tas5720_data, 207 + fault_check_work.work); 208 + struct device *dev = tas5720->codec->dev; 209 + unsigned int curr_fault; 210 + int ret; 211 + 212 + ret = regmap_read(tas5720->regmap, TAS5720_FAULT_REG, &curr_fault); 213 + if (ret < 0) { 214 + dev_err(dev, "failed to read FAULT register: %d\n", ret); 215 + goto out; 216 + } 217 + 218 + /* Check/handle all errors except SAIF clock errors */ 219 + curr_fault &= TAS5720_OCE | TAS5720_DCE | TAS5720_OTE; 220 + 221 + /* 222 + * Only flag errors once for a given occurrence. This is needed as 223 + * the TAS5720 will take time clearing the fault condition internally 224 + * during which we don't want to bombard the system with the same 225 + * error message over and over. 226 + */ 227 + if ((curr_fault & TAS5720_OCE) && !(tas5720->last_fault & TAS5720_OCE)) 228 + dev_crit(dev, "experienced an over current hardware fault\n"); 229 + 230 + if ((curr_fault & TAS5720_DCE) && !(tas5720->last_fault & TAS5720_DCE)) 231 + dev_crit(dev, "experienced a DC detection fault\n"); 232 + 233 + if ((curr_fault & TAS5720_OTE) && !(tas5720->last_fault & TAS5720_OTE)) 234 + dev_crit(dev, "experienced an over temperature fault\n"); 235 + 236 + /* Store current fault value so we can detect any changes next time */ 237 + tas5720->last_fault = curr_fault; 238 + 239 + if (!curr_fault) 240 + goto out; 241 + 242 + /* 243 + * Periodically toggle SDZ (shutdown bit) H->L->H to clear any latching 244 + * faults as long as a fault condition persists. Always going through 245 + * the full sequence no matter the first return value to minimizes 246 + * chances for the device to end up in shutdown mode. 247 + */ 248 + ret = regmap_write_bits(tas5720->regmap, TAS5720_POWER_CTRL_REG, 249 + TAS5720_SDZ, 0); 250 + if (ret < 0) 251 + dev_err(dev, "failed to write POWER_CTRL register: %d\n", ret); 252 + 253 + ret = regmap_write_bits(tas5720->regmap, TAS5720_POWER_CTRL_REG, 254 + TAS5720_SDZ, TAS5720_SDZ); 255 + if (ret < 0) 256 + dev_err(dev, "failed to write POWER_CTRL register: %d\n", ret); 257 + 258 + out: 259 + /* Schedule the next fault check at the specified interval */ 260 + schedule_delayed_work(&tas5720->fault_check_work, 261 + msecs_to_jiffies(TAS5720_FAULT_CHECK_INTERVAL)); 262 + } 263 + 264 + static int tas5720_codec_probe(struct snd_soc_codec *codec) 265 + { 266 + struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); 267 + unsigned int device_id; 268 + int ret; 269 + 270 + tas5720->codec = codec; 271 + 272 + ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies), 273 + tas5720->supplies); 274 + if (ret != 0) { 275 + dev_err(codec->dev, "failed to enable supplies: %d\n", ret); 276 + return ret; 277 + } 278 + 279 + ret = regmap_read(tas5720->regmap, TAS5720_DEVICE_ID_REG, &device_id); 280 + if (ret < 0) { 281 + dev_err(codec->dev, "failed to read device ID register: %d\n", 282 + ret); 283 + goto probe_fail; 284 + } 285 + 286 + if (device_id != TAS5720_DEVICE_ID) { 287 + dev_err(codec->dev, "wrong device ID. expected: %u read: %u\n", 288 + TAS5720_DEVICE_ID, device_id); 289 + ret = -ENODEV; 290 + goto probe_fail; 291 + } 292 + 293 + /* Set device to mute */ 294 + ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, 295 + TAS5720_MUTE, TAS5720_MUTE); 296 + if (ret < 0) 297 + goto error_snd_soc_update_bits; 298 + 299 + /* 300 + * Enter shutdown mode - our default when not playing audio - to 301 + * minimize current consumption. On the TAS5720 there is no real down 302 + * side doing so as all device registers are preserved and the wakeup 303 + * of the codec is rather quick which we do using a dapm widget. 304 + */ 305 + ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG, 306 + TAS5720_SDZ, 0); 307 + if (ret < 0) 308 + goto error_snd_soc_update_bits; 309 + 310 + INIT_DELAYED_WORK(&tas5720->fault_check_work, tas5720_fault_check_work); 311 + 312 + return 0; 313 + 314 + error_snd_soc_update_bits: 315 + dev_err(codec->dev, "error configuring device registers: %d\n", ret); 316 + 317 + probe_fail: 318 + regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), 319 + tas5720->supplies); 320 + return ret; 321 + } 322 + 323 + static int tas5720_codec_remove(struct snd_soc_codec *codec) 324 + { 325 + struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); 326 + int ret; 327 + 328 + cancel_delayed_work_sync(&tas5720->fault_check_work); 329 + 330 + ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), 331 + tas5720->supplies); 332 + if (ret < 0) 333 + dev_err(codec->dev, "failed to disable supplies: %d\n", ret); 334 + 335 + return ret; 336 + }; 337 + 338 + static int tas5720_dac_event(struct snd_soc_dapm_widget *w, 339 + struct snd_kcontrol *kcontrol, int event) 340 + { 341 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 342 + struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); 343 + int ret; 344 + 345 + if (event & SND_SOC_DAPM_POST_PMU) { 346 + /* Take TAS5720 out of shutdown mode */ 347 + ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG, 348 + TAS5720_SDZ, TAS5720_SDZ); 349 + if (ret < 0) { 350 + dev_err(codec->dev, "error waking codec: %d\n", ret); 351 + return ret; 352 + } 353 + 354 + /* 355 + * Observe codec shutdown-to-active time. The datasheet only 356 + * lists a nominal value however just use-it as-is without 357 + * additional padding to minimize the delay introduced in 358 + * starting to play audio (actually there is other setup done 359 + * by the ASoC framework that will provide additional delays, 360 + * so we should always be safe). 361 + */ 362 + msleep(25); 363 + 364 + /* Turn on TAS5720 periodic fault checking/handling */ 365 + tas5720->last_fault = 0; 366 + schedule_delayed_work(&tas5720->fault_check_work, 367 + msecs_to_jiffies(TAS5720_FAULT_CHECK_INTERVAL)); 368 + } else if (event & SND_SOC_DAPM_PRE_PMD) { 369 + /* Disable TAS5720 periodic fault checking/handling */ 370 + cancel_delayed_work_sync(&tas5720->fault_check_work); 371 + 372 + /* Place TAS5720 in shutdown mode to minimize current draw */ 373 + ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG, 374 + TAS5720_SDZ, 0); 375 + if (ret < 0) { 376 + dev_err(codec->dev, "error shutting down codec: %d\n", 377 + ret); 378 + return ret; 379 + } 380 + } 381 + 382 + return 0; 383 + } 384 + 385 + #ifdef CONFIG_PM 386 + static int tas5720_suspend(struct snd_soc_codec *codec) 387 + { 388 + struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); 389 + int ret; 390 + 391 + regcache_cache_only(tas5720->regmap, true); 392 + regcache_mark_dirty(tas5720->regmap); 393 + 394 + ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), 395 + tas5720->supplies); 396 + if (ret < 0) 397 + dev_err(codec->dev, "failed to disable supplies: %d\n", ret); 398 + 399 + return ret; 400 + } 401 + 402 + static int tas5720_resume(struct snd_soc_codec *codec) 403 + { 404 + struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); 405 + int ret; 406 + 407 + ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies), 408 + tas5720->supplies); 409 + if (ret < 0) { 410 + dev_err(codec->dev, "failed to enable supplies: %d\n", ret); 411 + return ret; 412 + } 413 + 414 + regcache_cache_only(tas5720->regmap, false); 415 + 416 + ret = regcache_sync(tas5720->regmap); 417 + if (ret < 0) { 418 + dev_err(codec->dev, "failed to sync regcache: %d\n", ret); 419 + return ret; 420 + } 421 + 422 + return 0; 423 + } 424 + #else 425 + #define tas5720_suspend NULL 426 + #define tas5720_resume NULL 427 + #endif 428 + 429 + static bool tas5720_is_volatile_reg(struct device *dev, unsigned int reg) 430 + { 431 + switch (reg) { 432 + case TAS5720_DEVICE_ID_REG: 433 + case TAS5720_FAULT_REG: 434 + return true; 435 + default: 436 + return false; 437 + } 438 + } 439 + 440 + static const struct regmap_config tas5720_regmap_config = { 441 + .reg_bits = 8, 442 + .val_bits = 8, 443 + 444 + .max_register = TAS5720_MAX_REG, 445 + .cache_type = REGCACHE_RBTREE, 446 + .volatile_reg = tas5720_is_volatile_reg, 447 + }; 448 + 449 + /* 450 + * DAC analog gain. There are four discrete values to select from, ranging 451 + * from 19.2 dB to 26.3dB. 452 + */ 453 + static const DECLARE_TLV_DB_RANGE(dac_analog_tlv, 454 + 0x0, 0x0, TLV_DB_SCALE_ITEM(1920, 0, 0), 455 + 0x1, 0x1, TLV_DB_SCALE_ITEM(2070, 0, 0), 456 + 0x2, 0x2, TLV_DB_SCALE_ITEM(2350, 0, 0), 457 + 0x3, 0x3, TLV_DB_SCALE_ITEM(2630, 0, 0), 458 + ); 459 + 460 + /* 461 + * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that 462 + * setting the gain below -100 dB (register value <0x7) is effectively a MUTE 463 + * as per device datasheet. 464 + */ 465 + static DECLARE_TLV_DB_SCALE(dac_tlv, -10350, 50, 0); 466 + 467 + static const struct snd_kcontrol_new tas5720_snd_controls[] = { 468 + SOC_SINGLE_TLV("Speaker Driver Playback Volume", 469 + TAS5720_VOLUME_CTRL_REG, 0, 0xff, 0, dac_tlv), 470 + SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG, 471 + TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv), 472 + }; 473 + 474 + static const struct snd_soc_dapm_widget tas5720_dapm_widgets[] = { 475 + SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0), 476 + SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas5720_dac_event, 477 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 478 + SND_SOC_DAPM_OUTPUT("OUT") 479 + }; 480 + 481 + static const struct snd_soc_dapm_route tas5720_audio_map[] = { 482 + { "DAC", NULL, "DAC IN" }, 483 + { "OUT", NULL, "DAC" }, 484 + }; 485 + 486 + static struct snd_soc_codec_driver soc_codec_dev_tas5720 = { 487 + .probe = tas5720_codec_probe, 488 + .remove = tas5720_codec_remove, 489 + .suspend = tas5720_suspend, 490 + .resume = tas5720_resume, 491 + 492 + .controls = tas5720_snd_controls, 493 + .num_controls = ARRAY_SIZE(tas5720_snd_controls), 494 + .dapm_widgets = tas5720_dapm_widgets, 495 + .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), 496 + .dapm_routes = tas5720_audio_map, 497 + .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), 498 + }; 499 + 500 + /* PCM rates supported by the TAS5720 driver */ 501 + #define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ 502 + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 503 + 504 + /* Formats supported by TAS5720 driver */ 505 + #define TAS5720_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\ 506 + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) 507 + 508 + static struct snd_soc_dai_ops tas5720_speaker_dai_ops = { 509 + .hw_params = tas5720_hw_params, 510 + .set_fmt = tas5720_set_dai_fmt, 511 + .set_tdm_slot = tas5720_set_dai_tdm_slot, 512 + .digital_mute = tas5720_mute, 513 + }; 514 + 515 + /* 516 + * TAS5720 DAI structure 517 + * 518 + * Note that were are advertising .playback.channels_max = 2 despite this being 519 + * a mono amplifier. The reason for that is that some serial ports such as TI's 520 + * McASP module have a minimum number of channels (2) that they can output. 521 + * Advertising more channels than we have will allow us to interface with such 522 + * a serial port without really any negative side effects as the TAS5720 will 523 + * simply ignore any extra channel(s) asides from the one channel that is 524 + * configured to be played back. 525 + */ 526 + static struct snd_soc_dai_driver tas5720_dai[] = { 527 + { 528 + .name = "tas5720-amplifier", 529 + .playback = { 530 + .stream_name = "Playback", 531 + .channels_min = 1, 532 + .channels_max = 2, 533 + .rates = TAS5720_RATES, 534 + .formats = TAS5720_FORMATS, 535 + }, 536 + .ops = &tas5720_speaker_dai_ops, 537 + }, 538 + }; 539 + 540 + static int tas5720_probe(struct i2c_client *client, 541 + const struct i2c_device_id *id) 542 + { 543 + struct device *dev = &client->dev; 544 + struct tas5720_data *data; 545 + int ret; 546 + int i; 547 + 548 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 549 + if (!data) 550 + return -ENOMEM; 551 + 552 + data->tas5720_client = client; 553 + data->regmap = devm_regmap_init_i2c(client, &tas5720_regmap_config); 554 + if (IS_ERR(data->regmap)) { 555 + ret = PTR_ERR(data->regmap); 556 + dev_err(dev, "failed to allocate register map: %d\n", ret); 557 + return ret; 558 + } 559 + 560 + for (i = 0; i < ARRAY_SIZE(data->supplies); i++) 561 + data->supplies[i].supply = tas5720_supply_names[i]; 562 + 563 + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), 564 + data->supplies); 565 + if (ret != 0) { 566 + dev_err(dev, "failed to request supplies: %d\n", ret); 567 + return ret; 568 + } 569 + 570 + dev_set_drvdata(dev, data); 571 + 572 + ret = snd_soc_register_codec(&client->dev, 573 + &soc_codec_dev_tas5720, 574 + tas5720_dai, ARRAY_SIZE(tas5720_dai)); 575 + if (ret < 0) { 576 + dev_err(dev, "failed to register codec: %d\n", ret); 577 + return ret; 578 + } 579 + 580 + return 0; 581 + } 582 + 583 + static int tas5720_remove(struct i2c_client *client) 584 + { 585 + struct device *dev = &client->dev; 586 + 587 + snd_soc_unregister_codec(dev); 588 + 589 + return 0; 590 + } 591 + 592 + static const struct i2c_device_id tas5720_id[] = { 593 + { "tas5720", 0 }, 594 + { } 595 + }; 596 + MODULE_DEVICE_TABLE(i2c, tas5720_id); 597 + 598 + #if IS_ENABLED(CONFIG_OF) 599 + static const struct of_device_id tas5720_of_match[] = { 600 + { .compatible = "ti,tas5720", }, 601 + { }, 602 + }; 603 + MODULE_DEVICE_TABLE(of, tas5720_of_match); 604 + #endif 605 + 606 + static struct i2c_driver tas5720_i2c_driver = { 607 + .driver = { 608 + .name = "tas5720", 609 + .of_match_table = of_match_ptr(tas5720_of_match), 610 + }, 611 + .probe = tas5720_probe, 612 + .remove = tas5720_remove, 613 + .id_table = tas5720_id, 614 + }; 615 + 616 + module_i2c_driver(tas5720_i2c_driver); 617 + 618 + MODULE_AUTHOR("Andreas Dannenberg <dannenberg@ti.com>"); 619 + MODULE_DESCRIPTION("TAS5720 Audio amplifier driver"); 620 + MODULE_LICENSE("GPL");
+90
sound/soc/codecs/tas5720.h
··· 1 + /* 2 + * tas5720.h - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier 3 + * 4 + * Copyright (C)2015-2016 Texas Instruments Incorporated - http://www.ti.com 5 + * 6 + * Author: Andreas Dannenberg <dannenberg@ti.com> 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License 10 + * version 2 as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, but 13 + * WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + */ 17 + 18 + #ifndef __TAS5720_H__ 19 + #define __TAS5720_H__ 20 + 21 + /* Register Address Map */ 22 + #define TAS5720_DEVICE_ID_REG 0x00 23 + #define TAS5720_POWER_CTRL_REG 0x01 24 + #define TAS5720_DIGITAL_CTRL1_REG 0x02 25 + #define TAS5720_DIGITAL_CTRL2_REG 0x03 26 + #define TAS5720_VOLUME_CTRL_REG 0x04 27 + #define TAS5720_ANALOG_CTRL_REG 0x06 28 + #define TAS5720_FAULT_REG 0x08 29 + #define TAS5720_DIGITAL_CLIP2_REG 0x10 30 + #define TAS5720_DIGITAL_CLIP1_REG 0x11 31 + #define TAS5720_MAX_REG TAS5720_DIGITAL_CLIP1_REG 32 + 33 + /* TAS5720_DEVICE_ID_REG */ 34 + #define TAS5720_DEVICE_ID 0x01 35 + 36 + /* TAS5720_POWER_CTRL_REG */ 37 + #define TAS5720_DIG_CLIP_MASK GENMASK(7, 2) 38 + #define TAS5720_SLEEP BIT(1) 39 + #define TAS5720_SDZ BIT(0) 40 + 41 + /* TAS5720_DIGITAL_CTRL1_REG */ 42 + #define TAS5720_HPF_BYPASS BIT(7) 43 + #define TAS5720_TDM_CFG_SRC BIT(6) 44 + #define TAS5720_SSZ_DS BIT(3) 45 + #define TAS5720_SAIF_RIGHTJ_24BIT (0x0) 46 + #define TAS5720_SAIF_RIGHTJ_20BIT (0x1) 47 + #define TAS5720_SAIF_RIGHTJ_18BIT (0x2) 48 + #define TAS5720_SAIF_RIGHTJ_16BIT (0x3) 49 + #define TAS5720_SAIF_I2S (0x4) 50 + #define TAS5720_SAIF_LEFTJ (0x5) 51 + #define TAS5720_SAIF_FORMAT_MASK GENMASK(2, 0) 52 + 53 + /* TAS5720_DIGITAL_CTRL2_REG */ 54 + #define TAS5720_MUTE BIT(4) 55 + #define TAS5720_TDM_SLOT_SEL_MASK GENMASK(2, 0) 56 + 57 + /* TAS5720_ANALOG_CTRL_REG */ 58 + #define TAS5720_PWM_RATE_6_3_FSYNC (0x0 << 4) 59 + #define TAS5720_PWM_RATE_8_4_FSYNC (0x1 << 4) 60 + #define TAS5720_PWM_RATE_10_5_FSYNC (0x2 << 4) 61 + #define TAS5720_PWM_RATE_12_6_FSYNC (0x3 << 4) 62 + #define TAS5720_PWM_RATE_14_7_FSYNC (0x4 << 4) 63 + #define TAS5720_PWM_RATE_16_8_FSYNC (0x5 << 4) 64 + #define TAS5720_PWM_RATE_20_10_FSYNC (0x6 << 4) 65 + #define TAS5720_PWM_RATE_24_12_FSYNC (0x7 << 4) 66 + #define TAS5720_PWM_RATE_MASK GENMASK(6, 4) 67 + #define TAS5720_ANALOG_GAIN_19_2DBV (0x0 << 2) 68 + #define TAS5720_ANALOG_GAIN_20_7DBV (0x1 << 2) 69 + #define TAS5720_ANALOG_GAIN_23_5DBV (0x2 << 2) 70 + #define TAS5720_ANALOG_GAIN_26_3DBV (0x3 << 2) 71 + #define TAS5720_ANALOG_GAIN_MASK GENMASK(3, 2) 72 + #define TAS5720_ANALOG_GAIN_SHIFT (0x2) 73 + 74 + /* TAS5720_FAULT_REG */ 75 + #define TAS5720_OC_THRESH_100PCT (0x0 << 4) 76 + #define TAS5720_OC_THRESH_75PCT (0x1 << 4) 77 + #define TAS5720_OC_THRESH_50PCT (0x2 << 4) 78 + #define TAS5720_OC_THRESH_25PCT (0x3 << 4) 79 + #define TAS5720_OC_THRESH_MASK GENMASK(5, 4) 80 + #define TAS5720_CLKE BIT(3) 81 + #define TAS5720_OCE BIT(2) 82 + #define TAS5720_DCE BIT(1) 83 + #define TAS5720_OTE BIT(0) 84 + #define TAS5720_FAULT_MASK GENMASK(3, 0) 85 + 86 + /* TAS5720_DIGITAL_CLIP1_REG */ 87 + #define TAS5720_CLIP1_MASK GENMASK(7, 2) 88 + #define TAS5720_CLIP1_SHIFT (0x2) 89 + 90 + #endif /* __TAS5720_H__ */
+10
sound/soc/codecs/tlv320aic31xx.c
··· 28 28 #include <linux/i2c.h> 29 29 #include <linux/gpio.h> 30 30 #include <linux/regulator/consumer.h> 31 + #include <linux/acpi.h> 31 32 #include <linux/of.h> 32 33 #include <linux/of_gpio.h> 33 34 #include <linux/slab.h> ··· 1281 1280 }; 1282 1281 MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); 1283 1282 1283 + #ifdef CONFIG_ACPI 1284 + static const struct acpi_device_id aic31xx_acpi_match[] = { 1285 + { "10TI3100", 0 }, 1286 + { } 1287 + }; 1288 + MODULE_DEVICE_TABLE(acpi, aic31xx_acpi_match); 1289 + #endif 1290 + 1284 1291 static struct i2c_driver aic31xx_i2c_driver = { 1285 1292 .driver = { 1286 1293 .name = "tlv320aic31xx-codec", 1287 1294 .of_match_table = of_match_ptr(tlv320aic31xx_of_match), 1295 + .acpi_match_table = ACPI_PTR(aic31xx_acpi_match), 1288 1296 }, 1289 1297 .probe = aic31xx_i2c_probe, 1290 1298 .remove = aic31xx_i2c_remove,
+74
sound/soc/codecs/tlv320aic32x4-i2c.c
··· 1 + /* 2 + * linux/sound/soc/codecs/tlv320aic32x4-i2c.c 3 + * 4 + * Copyright 2011 NW Digital Radio 5 + * 6 + * Author: Jeremy McDermond <nh6z@nh6z.net> 7 + * 8 + * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27. 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + */ 20 + 21 + #include <linux/i2c.h> 22 + #include <linux/module.h> 23 + #include <linux/of.h> 24 + #include <linux/regmap.h> 25 + #include <sound/soc.h> 26 + 27 + #include "tlv320aic32x4.h" 28 + 29 + static int aic32x4_i2c_probe(struct i2c_client *i2c, 30 + const struct i2c_device_id *id) 31 + { 32 + struct regmap *regmap; 33 + struct regmap_config config; 34 + 35 + config = aic32x4_regmap_config; 36 + config.reg_bits = 8; 37 + config.val_bits = 8; 38 + 39 + regmap = devm_regmap_init_i2c(i2c, &config); 40 + return aic32x4_probe(&i2c->dev, regmap); 41 + } 42 + 43 + static int aic32x4_i2c_remove(struct i2c_client *i2c) 44 + { 45 + return aic32x4_remove(&i2c->dev); 46 + } 47 + 48 + static const struct i2c_device_id aic32x4_i2c_id[] = { 49 + { "tlv320aic32x4", 0 }, 50 + { /* sentinel */ } 51 + }; 52 + MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); 53 + 54 + static const struct of_device_id aic32x4_of_id[] = { 55 + { .compatible = "ti,tlv320aic32x4", }, 56 + { /* senitel */ } 57 + }; 58 + MODULE_DEVICE_TABLE(of, aic32x4_of_id); 59 + 60 + static struct i2c_driver aic32x4_i2c_driver = { 61 + .driver = { 62 + .name = "tlv320aic32x4", 63 + .of_match_table = aic32x4_of_id, 64 + }, 65 + .probe = aic32x4_i2c_probe, 66 + .remove = aic32x4_i2c_remove, 67 + .id_table = aic32x4_i2c_id, 68 + }; 69 + 70 + module_i2c_driver(aic32x4_i2c_driver); 71 + 72 + MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver I2C"); 73 + MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>"); 74 + MODULE_LICENSE("GPL");
+76
sound/soc/codecs/tlv320aic32x4-spi.c
··· 1 + /* 2 + * linux/sound/soc/codecs/tlv320aic32x4-spi.c 3 + * 4 + * Copyright 2011 NW Digital Radio 5 + * 6 + * Author: Jeremy McDermond <nh6z@nh6z.net> 7 + * 8 + * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27. 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + */ 20 + 21 + #include <linux/spi/spi.h> 22 + #include <linux/module.h> 23 + #include <linux/of.h> 24 + #include <linux/regmap.h> 25 + #include <sound/soc.h> 26 + 27 + #include "tlv320aic32x4.h" 28 + 29 + static int aic32x4_spi_probe(struct spi_device *spi) 30 + { 31 + struct regmap *regmap; 32 + struct regmap_config config; 33 + 34 + config = aic32x4_regmap_config; 35 + config.reg_bits = 7; 36 + config.pad_bits = 1; 37 + config.val_bits = 8; 38 + config.read_flag_mask = 0x01; 39 + 40 + regmap = devm_regmap_init_spi(spi, &config); 41 + return aic32x4_probe(&spi->dev, regmap); 42 + } 43 + 44 + static int aic32x4_spi_remove(struct spi_device *spi) 45 + { 46 + return aic32x4_remove(&spi->dev); 47 + } 48 + 49 + static const struct spi_device_id aic32x4_spi_id[] = { 50 + { "tlv320aic32x4", 0 }, 51 + { /* sentinel */ } 52 + }; 53 + MODULE_DEVICE_TABLE(spi, aic32x4_spi_id); 54 + 55 + static const struct of_device_id aic32x4_of_id[] = { 56 + { .compatible = "ti,tlv320aic32x4", }, 57 + { /* senitel */ } 58 + }; 59 + MODULE_DEVICE_TABLE(of, aic32x4_of_id); 60 + 61 + static struct spi_driver aic32x4_spi_driver = { 62 + .driver = { 63 + .name = "tlv320aic32x4", 64 + .owner = THIS_MODULE, 65 + .of_match_table = aic32x4_of_id, 66 + }, 67 + .probe = aic32x4_spi_probe, 68 + .remove = aic32x4_spi_remove, 69 + .id_table = aic32x4_spi_id, 70 + }; 71 + 72 + module_spi_driver(aic32x4_spi_driver); 73 + 74 + MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver SPI"); 75 + MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>"); 76 + MODULE_LICENSE("GPL");
+195 -82
sound/soc/codecs/tlv320aic32x4.c
··· 30 30 #include <linux/pm.h> 31 31 #include <linux/gpio.h> 32 32 #include <linux/of_gpio.h> 33 - #include <linux/i2c.h> 34 33 #include <linux/cdev.h> 35 34 #include <linux/slab.h> 36 35 #include <linux/clk.h> ··· 159 160 /* 48k rate */ 160 161 {AIC32X4_FREQ_12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4}, 161 162 {AIC32X4_FREQ_24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4}, 162 - {AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4} 163 + {AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4}, 164 + 165 + /* 96k rate */ 166 + {AIC32X4_FREQ_25000000, 96000, 2, 7, 8643, 64, 4, 4, 64, 4, 4, 1}, 163 167 }; 164 168 165 169 static const struct snd_kcontrol_new hpl_output_mixer_controls[] = { ··· 183 181 SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_LORROUTE, 3, 1, 0), 184 182 }; 185 183 186 - static const struct snd_kcontrol_new left_input_mixer_controls[] = { 187 - SOC_DAPM_SINGLE("IN1_L P Switch", AIC32X4_LMICPGAPIN, 6, 1, 0), 188 - SOC_DAPM_SINGLE("IN2_L P Switch", AIC32X4_LMICPGAPIN, 4, 1, 0), 189 - SOC_DAPM_SINGLE("IN3_L P Switch", AIC32X4_LMICPGAPIN, 2, 1, 0), 184 + static const char * const resistor_text[] = { 185 + "Off", "10 kOhm", "20 kOhm", "40 kOhm", 190 186 }; 191 187 192 - static const struct snd_kcontrol_new right_input_mixer_controls[] = { 193 - SOC_DAPM_SINGLE("IN1_R P Switch", AIC32X4_RMICPGAPIN, 6, 1, 0), 194 - SOC_DAPM_SINGLE("IN2_R P Switch", AIC32X4_RMICPGAPIN, 4, 1, 0), 195 - SOC_DAPM_SINGLE("IN3_R P Switch", AIC32X4_RMICPGAPIN, 2, 1, 0), 188 + /* Left mixer pins */ 189 + static SOC_ENUM_SINGLE_DECL(in1l_lpga_p_enum, AIC32X4_LMICPGAPIN, 6, resistor_text); 190 + static SOC_ENUM_SINGLE_DECL(in2l_lpga_p_enum, AIC32X4_LMICPGAPIN, 4, resistor_text); 191 + static SOC_ENUM_SINGLE_DECL(in3l_lpga_p_enum, AIC32X4_LMICPGAPIN, 2, resistor_text); 192 + static SOC_ENUM_SINGLE_DECL(in1r_lpga_p_enum, AIC32X4_LMICPGAPIN, 0, resistor_text); 193 + 194 + static SOC_ENUM_SINGLE_DECL(cml_lpga_n_enum, AIC32X4_LMICPGANIN, 6, resistor_text); 195 + static SOC_ENUM_SINGLE_DECL(in2r_lpga_n_enum, AIC32X4_LMICPGANIN, 4, resistor_text); 196 + static SOC_ENUM_SINGLE_DECL(in3r_lpga_n_enum, AIC32X4_LMICPGANIN, 2, resistor_text); 197 + 198 + static const struct snd_kcontrol_new in1l_to_lmixer_controls[] = { 199 + SOC_DAPM_ENUM("IN1_L L+ Switch", in1l_lpga_p_enum), 200 + }; 201 + static const struct snd_kcontrol_new in2l_to_lmixer_controls[] = { 202 + SOC_DAPM_ENUM("IN2_L L+ Switch", in2l_lpga_p_enum), 203 + }; 204 + static const struct snd_kcontrol_new in3l_to_lmixer_controls[] = { 205 + SOC_DAPM_ENUM("IN3_L L+ Switch", in3l_lpga_p_enum), 206 + }; 207 + static const struct snd_kcontrol_new in1r_to_lmixer_controls[] = { 208 + SOC_DAPM_ENUM("IN1_R L+ Switch", in1r_lpga_p_enum), 209 + }; 210 + static const struct snd_kcontrol_new cml_to_lmixer_controls[] = { 211 + SOC_DAPM_ENUM("CM_L L- Switch", cml_lpga_n_enum), 212 + }; 213 + static const struct snd_kcontrol_new in2r_to_lmixer_controls[] = { 214 + SOC_DAPM_ENUM("IN2_R L- Switch", in2r_lpga_n_enum), 215 + }; 216 + static const struct snd_kcontrol_new in3r_to_lmixer_controls[] = { 217 + SOC_DAPM_ENUM("IN3_R L- Switch", in3r_lpga_n_enum), 218 + }; 219 + 220 + /* Right mixer pins */ 221 + static SOC_ENUM_SINGLE_DECL(in1r_rpga_p_enum, AIC32X4_RMICPGAPIN, 6, resistor_text); 222 + static SOC_ENUM_SINGLE_DECL(in2r_rpga_p_enum, AIC32X4_RMICPGAPIN, 4, resistor_text); 223 + static SOC_ENUM_SINGLE_DECL(in3r_rpga_p_enum, AIC32X4_RMICPGAPIN, 2, resistor_text); 224 + static SOC_ENUM_SINGLE_DECL(in2l_rpga_p_enum, AIC32X4_RMICPGAPIN, 0, resistor_text); 225 + static SOC_ENUM_SINGLE_DECL(cmr_rpga_n_enum, AIC32X4_RMICPGANIN, 6, resistor_text); 226 + static SOC_ENUM_SINGLE_DECL(in1l_rpga_n_enum, AIC32X4_RMICPGANIN, 4, resistor_text); 227 + static SOC_ENUM_SINGLE_DECL(in3l_rpga_n_enum, AIC32X4_RMICPGANIN, 2, resistor_text); 228 + 229 + static const struct snd_kcontrol_new in1r_to_rmixer_controls[] = { 230 + SOC_DAPM_ENUM("IN1_R R+ Switch", in1r_rpga_p_enum), 231 + }; 232 + static const struct snd_kcontrol_new in2r_to_rmixer_controls[] = { 233 + SOC_DAPM_ENUM("IN2_R R+ Switch", in2r_rpga_p_enum), 234 + }; 235 + static const struct snd_kcontrol_new in3r_to_rmixer_controls[] = { 236 + SOC_DAPM_ENUM("IN3_R R+ Switch", in3r_rpga_p_enum), 237 + }; 238 + static const struct snd_kcontrol_new in2l_to_rmixer_controls[] = { 239 + SOC_DAPM_ENUM("IN2_L R+ Switch", in2l_rpga_p_enum), 240 + }; 241 + static const struct snd_kcontrol_new cmr_to_rmixer_controls[] = { 242 + SOC_DAPM_ENUM("CM_R R- Switch", cmr_rpga_n_enum), 243 + }; 244 + static const struct snd_kcontrol_new in1l_to_rmixer_controls[] = { 245 + SOC_DAPM_ENUM("IN1_L R- Switch", in1l_rpga_n_enum), 246 + }; 247 + static const struct snd_kcontrol_new in3l_to_rmixer_controls[] = { 248 + SOC_DAPM_ENUM("IN3_L R- Switch", in3l_rpga_n_enum), 196 249 }; 197 250 198 251 static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { ··· 271 214 &lor_output_mixer_controls[0], 272 215 ARRAY_SIZE(lor_output_mixer_controls)), 273 216 SND_SOC_DAPM_PGA("LOR Power", AIC32X4_OUTPWRCTL, 2, 0, NULL, 0), 274 - SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0, 275 - &left_input_mixer_controls[0], 276 - ARRAY_SIZE(left_input_mixer_controls)), 277 - SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0, 278 - &right_input_mixer_controls[0], 279 - ARRAY_SIZE(right_input_mixer_controls)), 280 - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", AIC32X4_ADCSETUP, 7, 0), 217 + 281 218 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", AIC32X4_ADCSETUP, 6, 0), 219 + SND_SOC_DAPM_MUX("IN1_R to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0, 220 + in1r_to_rmixer_controls), 221 + SND_SOC_DAPM_MUX("IN2_R to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0, 222 + in2r_to_rmixer_controls), 223 + SND_SOC_DAPM_MUX("IN3_R to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0, 224 + in3r_to_rmixer_controls), 225 + SND_SOC_DAPM_MUX("IN2_L to Right Mixer Positive Resistor", SND_SOC_NOPM, 0, 0, 226 + in2l_to_rmixer_controls), 227 + SND_SOC_DAPM_MUX("CM_R to Right Mixer Negative Resistor", SND_SOC_NOPM, 0, 0, 228 + cmr_to_rmixer_controls), 229 + SND_SOC_DAPM_MUX("IN1_L to Right Mixer Negative Resistor", SND_SOC_NOPM, 0, 0, 230 + in1l_to_rmixer_controls), 231 + SND_SOC_DAPM_MUX("IN3_L to Right Mixer Negative Resistor", SND_SOC_NOPM, 0, 0, 232 + in3l_to_rmixer_controls), 233 + 234 + SND_SOC_DAPM_ADC("Left ADC", "Left Capture", AIC32X4_ADCSETUP, 7, 0), 235 + SND_SOC_DAPM_MUX("IN1_L to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0, 236 + in1l_to_lmixer_controls), 237 + SND_SOC_DAPM_MUX("IN2_L to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0, 238 + in2l_to_lmixer_controls), 239 + SND_SOC_DAPM_MUX("IN3_L to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0, 240 + in3l_to_lmixer_controls), 241 + SND_SOC_DAPM_MUX("IN1_R to Left Mixer Positive Resistor", SND_SOC_NOPM, 0, 0, 242 + in1r_to_lmixer_controls), 243 + SND_SOC_DAPM_MUX("CM_L to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0, 244 + cml_to_lmixer_controls), 245 + SND_SOC_DAPM_MUX("IN2_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0, 246 + in2r_to_lmixer_controls), 247 + SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0, 248 + in3r_to_lmixer_controls), 249 + 282 250 SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0), 283 251 284 252 SND_SOC_DAPM_OUTPUT("HPL"), ··· 343 261 {"LOR Power", NULL, "LOR Output Mixer"}, 344 262 {"LOR", NULL, "LOR Power"}, 345 263 346 - /* Left input */ 347 - {"Left Input Mixer", "IN1_L P Switch", "IN1_L"}, 348 - {"Left Input Mixer", "IN2_L P Switch", "IN2_L"}, 349 - {"Left Input Mixer", "IN3_L P Switch", "IN3_L"}, 350 - 351 - {"Left ADC", NULL, "Left Input Mixer"}, 352 - 353 264 /* Right Input */ 354 - {"Right Input Mixer", "IN1_R P Switch", "IN1_R"}, 355 - {"Right Input Mixer", "IN2_R P Switch", "IN2_R"}, 356 - {"Right Input Mixer", "IN3_R P Switch", "IN3_R"}, 265 + {"Right ADC", NULL, "IN1_R to Right Mixer Positive Resistor"}, 266 + {"IN1_R to Right Mixer Positive Resistor", "10 kOhm", "IN1_R"}, 267 + {"IN1_R to Right Mixer Positive Resistor", "20 kOhm", "IN1_R"}, 268 + {"IN1_R to Right Mixer Positive Resistor", "40 kOhm", "IN1_R"}, 357 269 358 - {"Right ADC", NULL, "Right Input Mixer"}, 270 + {"Right ADC", NULL, "IN2_R to Right Mixer Positive Resistor"}, 271 + {"IN2_R to Right Mixer Positive Resistor", "10 kOhm", "IN2_R"}, 272 + {"IN2_R to Right Mixer Positive Resistor", "20 kOhm", "IN2_R"}, 273 + {"IN2_R to Right Mixer Positive Resistor", "40 kOhm", "IN2_R"}, 274 + 275 + {"Right ADC", NULL, "IN3_R to Right Mixer Positive Resistor"}, 276 + {"IN3_R to Right Mixer Positive Resistor", "10 kOhm", "IN3_R"}, 277 + {"IN3_R to Right Mixer Positive Resistor", "20 kOhm", "IN3_R"}, 278 + {"IN3_R to Right Mixer Positive Resistor", "40 kOhm", "IN3_R"}, 279 + 280 + {"Right ADC", NULL, "IN2_L to Right Mixer Positive Resistor"}, 281 + {"IN2_L to Right Mixer Positive Resistor", "10 kOhm", "IN2_L"}, 282 + {"IN2_L to Right Mixer Positive Resistor", "20 kOhm", "IN2_L"}, 283 + {"IN2_L to Right Mixer Positive Resistor", "40 kOhm", "IN2_L"}, 284 + 285 + {"Right ADC", NULL, "CM_R to Right Mixer Negative Resistor"}, 286 + {"CM_R to Right Mixer Negative Resistor", "10 kOhm", "CM_R"}, 287 + {"CM_R to Right Mixer Negative Resistor", "20 kOhm", "CM_R"}, 288 + {"CM_R to Right Mixer Negative Resistor", "40 kOhm", "CM_R"}, 289 + 290 + {"Right ADC", NULL, "IN1_L to Right Mixer Negative Resistor"}, 291 + {"IN1_L to Right Mixer Negative Resistor", "10 kOhm", "IN1_L"}, 292 + {"IN1_L to Right Mixer Negative Resistor", "20 kOhm", "IN1_L"}, 293 + {"IN1_L to Right Mixer Negative Resistor", "40 kOhm", "IN1_L"}, 294 + 295 + {"Right ADC", NULL, "IN3_L to Right Mixer Negative Resistor"}, 296 + {"IN3_L to Right Mixer Negative Resistor", "10 kOhm", "IN3_L"}, 297 + {"IN3_L to Right Mixer Negative Resistor", "20 kOhm", "IN3_L"}, 298 + {"IN3_L to Right Mixer Negative Resistor", "40 kOhm", "IN3_L"}, 299 + 300 + /* Left Input */ 301 + {"Left ADC", NULL, "IN1_L to Left Mixer Positive Resistor"}, 302 + {"IN1_L to Left Mixer Positive Resistor", "10 kOhm", "IN1_L"}, 303 + {"IN1_L to Left Mixer Positive Resistor", "20 kOhm", "IN1_L"}, 304 + {"IN1_L to Left Mixer Positive Resistor", "40 kOhm", "IN1_L"}, 305 + 306 + {"Left ADC", NULL, "IN2_L to Left Mixer Positive Resistor"}, 307 + {"IN2_L to Left Mixer Positive Resistor", "10 kOhm", "IN2_L"}, 308 + {"IN2_L to Left Mixer Positive Resistor", "20 kOhm", "IN2_L"}, 309 + {"IN2_L to Left Mixer Positive Resistor", "40 kOhm", "IN2_L"}, 310 + 311 + {"Left ADC", NULL, "IN3_L to Left Mixer Positive Resistor"}, 312 + {"IN3_L to Left Mixer Positive Resistor", "10 kOhm", "IN3_L"}, 313 + {"IN3_L to Left Mixer Positive Resistor", "20 kOhm", "IN3_L"}, 314 + {"IN3_L to Left Mixer Positive Resistor", "40 kOhm", "IN3_L"}, 315 + 316 + {"Left ADC", NULL, "IN1_R to Left Mixer Positive Resistor"}, 317 + {"IN1_R to Left Mixer Positive Resistor", "10 kOhm", "IN1_R"}, 318 + {"IN1_R to Left Mixer Positive Resistor", "20 kOhm", "IN1_R"}, 319 + {"IN1_R to Left Mixer Positive Resistor", "40 kOhm", "IN1_R"}, 320 + 321 + {"Left ADC", NULL, "CM_L to Left Mixer Negative Resistor"}, 322 + {"CM_L to Left Mixer Negative Resistor", "10 kOhm", "CM_L"}, 323 + {"CM_L to Left Mixer Negative Resistor", "20 kOhm", "CM_L"}, 324 + {"CM_L to Left Mixer Negative Resistor", "40 kOhm", "CM_L"}, 325 + 326 + {"Left ADC", NULL, "IN2_R to Left Mixer Negative Resistor"}, 327 + {"IN2_R to Left Mixer Negative Resistor", "10 kOhm", "IN2_R"}, 328 + {"IN2_R to Left Mixer Negative Resistor", "20 kOhm", "IN2_R"}, 329 + {"IN2_R to Left Mixer Negative Resistor", "40 kOhm", "IN2_R"}, 330 + 331 + {"Left ADC", NULL, "IN3_R to Left Mixer Negative Resistor"}, 332 + {"IN3_R to Left Mixer Negative Resistor", "10 kOhm", "IN3_R"}, 333 + {"IN3_R to Left Mixer Negative Resistor", "20 kOhm", "IN3_R"}, 334 + {"IN3_R to Left Mixer Negative Resistor", "40 kOhm", "IN3_R"}, 359 335 }; 360 336 361 337 static const struct regmap_range_cfg aic32x4_regmap_pages[] = { ··· 427 287 }, 428 288 }; 429 289 430 - static const struct regmap_config aic32x4_regmap = { 431 - .reg_bits = 8, 432 - .val_bits = 8, 433 - 290 + const struct regmap_config aic32x4_regmap_config = { 434 291 .max_register = AIC32X4_RMICPGAVOL, 435 292 .ranges = aic32x4_regmap_pages, 436 293 .num_ranges = ARRAY_SIZE(aic32x4_regmap_pages), 437 294 }; 295 + EXPORT_SYMBOL(aic32x4_regmap_config); 438 296 439 297 static inline int aic32x4_get_divs(int mclk, int rate) 440 298 { ··· 705 567 return 0; 706 568 } 707 569 708 - #define AIC32X4_RATES SNDRV_PCM_RATE_8000_48000 570 + #define AIC32X4_RATES SNDRV_PCM_RATE_8000_96000 709 571 #define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ 710 572 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) 711 573 ··· 734 596 .symmetric_rates = 1, 735 597 }; 736 598 737 - static int aic32x4_probe(struct snd_soc_codec *codec) 599 + static int aic32x4_codec_probe(struct snd_soc_codec *codec) 738 600 { 739 601 struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); 740 602 u32 tmp_reg; ··· 793 655 } 794 656 795 657 static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { 796 - .probe = aic32x4_probe, 658 + .probe = aic32x4_codec_probe, 797 659 .set_bias_level = aic32x4_set_bias_level, 798 660 .suspend_bias_off = true, 799 661 ··· 915 777 return ret; 916 778 } 917 779 918 - static int aic32x4_i2c_probe(struct i2c_client *i2c, 919 - const struct i2c_device_id *id) 780 + int aic32x4_probe(struct device *dev, struct regmap *regmap) 920 781 { 921 - struct aic32x4_pdata *pdata = i2c->dev.platform_data; 922 782 struct aic32x4_priv *aic32x4; 923 - struct device_node *np = i2c->dev.of_node; 783 + struct aic32x4_pdata *pdata = dev->platform_data; 784 + struct device_node *np = dev->of_node; 924 785 int ret; 925 786 926 - aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), 787 + if (IS_ERR(regmap)) 788 + return PTR_ERR(regmap); 789 + 790 + aic32x4 = devm_kzalloc(dev, sizeof(struct aic32x4_priv), 927 791 GFP_KERNEL); 928 792 if (aic32x4 == NULL) 929 793 return -ENOMEM; 930 794 931 - aic32x4->regmap = devm_regmap_init_i2c(i2c, &aic32x4_regmap); 932 - if (IS_ERR(aic32x4->regmap)) 933 - return PTR_ERR(aic32x4->regmap); 934 - 935 - i2c_set_clientdata(i2c, aic32x4); 795 + dev_set_drvdata(dev, aic32x4); 936 796 937 797 if (pdata) { 938 798 aic32x4->power_cfg = pdata->power_cfg; ··· 940 804 } else if (np) { 941 805 ret = aic32x4_parse_dt(aic32x4, np); 942 806 if (ret) { 943 - dev_err(&i2c->dev, "Failed to parse DT node\n"); 807 + dev_err(dev, "Failed to parse DT node\n"); 944 808 return ret; 945 809 } 946 810 } else { ··· 950 814 aic32x4->rstn_gpio = -1; 951 815 } 952 816 953 - aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk"); 817 + aic32x4->mclk = devm_clk_get(dev, "mclk"); 954 818 if (IS_ERR(aic32x4->mclk)) { 955 - dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); 819 + dev_err(dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); 956 820 return PTR_ERR(aic32x4->mclk); 957 821 } 958 822 959 823 if (gpio_is_valid(aic32x4->rstn_gpio)) { 960 - ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, 824 + ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio, 961 825 GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); 962 826 if (ret != 0) 963 827 return ret; 964 828 } 965 829 966 - ret = aic32x4_setup_regulators(&i2c->dev, aic32x4); 830 + ret = aic32x4_setup_regulators(dev, aic32x4); 967 831 if (ret) { 968 - dev_err(&i2c->dev, "Failed to setup regulators\n"); 832 + dev_err(dev, "Failed to setup regulators\n"); 969 833 return ret; 970 834 } 971 835 972 - ret = snd_soc_register_codec(&i2c->dev, 836 + ret = snd_soc_register_codec(dev, 973 837 &soc_codec_dev_aic32x4, &aic32x4_dai, 1); 974 838 if (ret) { 975 - dev_err(&i2c->dev, "Failed to register codec\n"); 839 + dev_err(dev, "Failed to register codec\n"); 976 840 aic32x4_disable_regulators(aic32x4); 977 841 return ret; 978 842 } 979 843 980 - i2c_set_clientdata(i2c, aic32x4); 981 - 982 844 return 0; 983 845 } 846 + EXPORT_SYMBOL(aic32x4_probe); 984 847 985 - static int aic32x4_i2c_remove(struct i2c_client *client) 848 + int aic32x4_remove(struct device *dev) 986 849 { 987 - struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client); 850 + struct aic32x4_priv *aic32x4 = dev_get_drvdata(dev); 988 851 989 852 aic32x4_disable_regulators(aic32x4); 990 853 991 - snd_soc_unregister_codec(&client->dev); 854 + snd_soc_unregister_codec(dev); 855 + 992 856 return 0; 993 857 } 994 - 995 - static const struct i2c_device_id aic32x4_i2c_id[] = { 996 - { "tlv320aic32x4", 0 }, 997 - { } 998 - }; 999 - MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); 1000 - 1001 - static const struct of_device_id aic32x4_of_id[] = { 1002 - { .compatible = "ti,tlv320aic32x4", }, 1003 - { /* senitel */ } 1004 - }; 1005 - MODULE_DEVICE_TABLE(of, aic32x4_of_id); 1006 - 1007 - static struct i2c_driver aic32x4_i2c_driver = { 1008 - .driver = { 1009 - .name = "tlv320aic32x4", 1010 - .of_match_table = aic32x4_of_id, 1011 - }, 1012 - .probe = aic32x4_i2c_probe, 1013 - .remove = aic32x4_i2c_remove, 1014 - .id_table = aic32x4_i2c_id, 1015 - }; 1016 - 1017 - module_i2c_driver(aic32x4_i2c_driver); 858 + EXPORT_SYMBOL(aic32x4_remove); 1018 859 1019 860 MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); 1020 861 MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
+7
sound/soc/codecs/tlv320aic32x4.h
··· 10 10 #ifndef _TLV320AIC32X4_H 11 11 #define _TLV320AIC32X4_H 12 12 13 + struct device; 14 + struct regmap_config; 15 + 16 + extern const struct regmap_config aic32x4_regmap_config; 17 + int aic32x4_probe(struct device *dev, struct regmap *regmap); 18 + int aic32x4_remove(struct device *dev); 19 + 13 20 /* tlv320aic32x4 register space (in decimal to match datasheet) */ 14 21 15 22 #define AIC32X4_PAGE1 128
+10 -6
sound/soc/codecs/twl6040.c
··· 824 824 { 825 825 struct twl6040 *twl6040 = codec->control_data; 826 826 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 827 - int ret; 827 + int ret = 0; 828 828 829 829 switch (level) { 830 830 case SND_SOC_BIAS_ON: ··· 832 832 case SND_SOC_BIAS_PREPARE: 833 833 break; 834 834 case SND_SOC_BIAS_STANDBY: 835 - if (priv->codec_powered) 835 + if (priv->codec_powered) { 836 + /* Select low power PLL in standby */ 837 + ret = twl6040_set_pll(twl6040, TWL6040_SYSCLK_SEL_LPPLL, 838 + 32768, 19200000); 836 839 break; 840 + } 837 841 838 842 ret = twl6040_power(twl6040, 1); 839 843 if (ret) 840 - return ret; 844 + break; 841 845 842 846 priv->codec_powered = 1; 843 847 ··· 857 853 break; 858 854 } 859 855 860 - return 0; 856 + return ret; 861 857 } 862 858 863 859 static int twl6040_startup(struct snd_pcm_substream *substream, ··· 987 983 if (mute) { 988 984 /* Power down drivers and DACs */ 989 985 hflctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | 990 - TWL6040_HFDRVENA); 986 + TWL6040_HFDRVENA | TWL6040_HFSWENA); 991 987 hfrctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | 992 - TWL6040_HFDRVENA); 988 + TWL6040_HFDRVENA | TWL6040_HFSWENA); 993 989 } 994 990 995 991 twl6040_reg_write(twl6040, TWL6040_REG_HFLCTL, hflctl);
+6 -3
sound/soc/codecs/wm8962.c
··· 3793 3793 ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), 3794 3794 wm8962->supplies); 3795 3795 if (ret != 0) { 3796 - dev_err(dev, 3797 - "Failed to enable supplies: %d\n", ret); 3798 - return ret; 3796 + dev_err(dev, "Failed to enable supplies: %d\n", ret); 3797 + goto disable_clock; 3799 3798 } 3800 3799 3801 3800 regcache_cache_only(wm8962->regmap, false); ··· 3832 3833 msleep(5); 3833 3834 3834 3835 return 0; 3836 + 3837 + disable_clock: 3838 + clk_disable_unprepare(wm8962->pdata.mclk); 3839 + return ret; 3835 3840 } 3836 3841 3837 3842 static int wm8962_runtime_suspend(struct device *dev)
+3 -3
sound/soc/codecs/wm8962.h
··· 16 16 #include <asm/types.h> 17 17 #include <sound/soc.h> 18 18 19 - #define WM8962_SYSCLK_MCLK 1 20 - #define WM8962_SYSCLK_FLL 2 21 - #define WM8962_SYSCLK_PLL3 3 19 + #define WM8962_SYSCLK_MCLK 0 20 + #define WM8962_SYSCLK_FLL 1 21 + #define WM8962_SYSCLK_PLL3 2 22 22 23 23 #define WM8962_FLL 1 24 24
+1
sound/soc/generic/simple-card.c
··· 643 643 static struct platform_driver asoc_simple_card = { 644 644 .driver = { 645 645 .name = "asoc-simple-card", 646 + .pm = &snd_soc_pm_ops, 646 647 .of_match_table = asoc_simple_of_match, 647 648 }, 648 649 .probe = asoc_simple_card_probe,
+1
sound/soc/kirkwood/Kconfig
··· 1 1 config SND_KIRKWOOD_SOC 2 2 tristate "SoC Audio for the Marvell Kirkwood and Dove chips" 3 3 depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST 4 + depends on HAS_DMA 4 5 help 5 6 Say Y or M if you want to add support for codecs attached to 6 7 the Kirkwood I2S interface. You will also need to select the
+1
sound/soc/mediatek/Kconfig
··· 43 43 depends on SND_SOC_MEDIATEK && I2C 44 44 select SND_SOC_RT5645 45 45 select SND_SOC_RT5677 46 + select SND_SOC_HDMI_CODEC 46 47 help 47 48 This adds ASoC driver for Mediatek MT8173 boards 48 49 with the RT5650 and RT5676 codecs.
+27
sound/soc/mediatek/mt8173-rt5650-rt5676.c
··· 134 134 enum { 135 135 DAI_LINK_PLAYBACK, 136 136 DAI_LINK_CAPTURE, 137 + DAI_LINK_HDMI, 137 138 DAI_LINK_CODEC_I2S, 139 + DAI_LINK_HDMI_I2S, 138 140 DAI_LINK_INTERCODEC 139 141 }; 140 142 ··· 163 161 .dynamic = 1, 164 162 .dpcm_capture = 1, 165 163 }, 164 + [DAI_LINK_HDMI] = { 165 + .name = "HDMI", 166 + .stream_name = "HDMI PCM", 167 + .cpu_dai_name = "HDMI", 168 + .codec_name = "snd-soc-dummy", 169 + .codec_dai_name = "snd-soc-dummy-dai", 170 + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 171 + .dynamic = 1, 172 + .dpcm_playback = 1, 173 + }, 166 174 167 175 /* Back End DAI links */ 168 176 [DAI_LINK_CODEC_I2S] = { ··· 188 176 .ignore_pmdown_time = 1, 189 177 .dpcm_playback = 1, 190 178 .dpcm_capture = 1, 179 + }, 180 + [DAI_LINK_HDMI_I2S] = { 181 + .name = "HDMI BE", 182 + .cpu_dai_name = "HDMIO", 183 + .no_pcm = 1, 184 + .codec_dai_name = "i2s-hifi", 185 + .dpcm_playback = 1, 191 186 }, 192 187 /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */ 193 188 [DAI_LINK_INTERCODEC] = { ··· 269 250 270 251 mt8173_rt5650_rt5676_dais[DAI_LINK_INTERCODEC].codec_of_node = 271 252 mt8173_rt5650_rt5676_codecs[1].of_node; 253 + 254 + mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codec_of_node = 255 + of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 2); 256 + if (!mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codec_of_node) { 257 + dev_err(&pdev->dev, 258 + "Property 'audio-codec' missing or invalid\n"); 259 + return -EINVAL; 260 + } 272 261 273 262 card->dev = &pdev->dev; 274 263 platform_set_drvdata(pdev, card);
+47 -3
sound/soc/mediatek/mt8173-rt5650.c
··· 85 85 { 86 86 struct snd_soc_card *card = runtime->card; 87 87 struct snd_soc_codec *codec = runtime->codec_dais[0]->codec; 88 + const char *codec_capture_dai = runtime->codec_dais[1]->name; 88 89 int ret; 89 90 90 91 rt5645_sel_asrc_clk_src(codec, 91 - RT5645_DA_STEREO_FILTER | 92 - RT5645_AD_STEREO_FILTER, 92 + RT5645_DA_STEREO_FILTER, 93 93 RT5645_CLK_SEL_I2S1_ASRC); 94 + 95 + if (!strcmp(codec_capture_dai, "rt5645-aif1")) { 96 + rt5645_sel_asrc_clk_src(codec, 97 + RT5645_AD_STEREO_FILTER, 98 + RT5645_CLK_SEL_I2S1_ASRC); 99 + } else if (!strcmp(codec_capture_dai, "rt5645-aif2")) { 100 + rt5645_sel_asrc_clk_src(codec, 101 + RT5645_AD_STEREO_FILTER, 102 + RT5645_CLK_SEL_I2S2_ASRC); 103 + } else { 104 + dev_warn(card->dev, 105 + "Only one dai codec found in DTS, enabled rt5645 AD filter\n"); 106 + rt5645_sel_asrc_clk_src(codec, 107 + RT5645_AD_STEREO_FILTER, 108 + RT5645_CLK_SEL_I2S1_ASRC); 109 + } 110 + 94 111 /* enable jack detection */ 95 112 ret = snd_soc_card_jack_new(card, "Headset Jack", 96 113 SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | ··· 127 110 128 111 static struct snd_soc_dai_link_component mt8173_rt5650_codecs[] = { 129 112 { 113 + /* Playback */ 114 + .dai_name = "rt5645-aif1", 115 + }, 116 + { 117 + /* Capture */ 130 118 .dai_name = "rt5645-aif1", 131 119 }, 132 120 }; ··· 171 149 .cpu_dai_name = "I2S", 172 150 .no_pcm = 1, 173 151 .codecs = mt8173_rt5650_codecs, 174 - .num_codecs = 1, 152 + .num_codecs = 2, 175 153 .init = mt8173_rt5650_init, 176 154 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 177 155 SND_SOC_DAIFMT_CBS_CFS, ··· 199 177 { 200 178 struct snd_soc_card *card = &mt8173_rt5650_card; 201 179 struct device_node *platform_node; 180 + struct device_node *np; 181 + const char *codec_capture_dai; 202 182 int i, ret; 203 183 204 184 platform_node = of_parse_phandle(pdev->dev.of_node, ··· 223 199 "Property 'audio-codec' missing or invalid\n"); 224 200 return -EINVAL; 225 201 } 202 + mt8173_rt5650_codecs[1].of_node = mt8173_rt5650_codecs[0].of_node; 203 + 204 + if (of_find_node_by_name(platform_node, "codec-capture")) { 205 + np = of_get_child_by_name(pdev->dev.of_node, "codec-capture"); 206 + if (!np) { 207 + dev_err(&pdev->dev, 208 + "%s: Can't find codec-capture DT node\n", 209 + __func__); 210 + return -EINVAL; 211 + } 212 + ret = snd_soc_of_get_dai_name(np, &codec_capture_dai); 213 + if (ret < 0) { 214 + dev_err(&pdev->dev, 215 + "%s codec_capture_dai name fail %d\n", 216 + __func__, ret); 217 + return ret; 218 + } 219 + mt8173_rt5650_codecs[1].dai_name = codec_capture_dai; 220 + } 221 + 226 222 card->dev = &pdev->dev; 227 223 platform_set_drvdata(pdev, card); 228 224
+2
sound/soc/mediatek/mtk-afe-pcm.c
··· 123 123 #define AFE_TDM_CON1_WLEN_32BIT (0x2 << 8) 124 124 #define AFE_TDM_CON1_MSB_ALIGNED (0x1 << 4) 125 125 #define AFE_TDM_CON1_1_BCK_DELAY (0x1 << 3) 126 + #define AFE_TDM_CON1_LRCK_INV (0x1 << 2) 126 127 #define AFE_TDM_CON1_BCK_INV (0x1 << 1) 127 128 #define AFE_TDM_CON1_EN (0x1 << 0) 128 129 ··· 450 449 runtime->rate * runtime->channels * 32); 451 450 452 451 val = AFE_TDM_CON1_BCK_INV | 452 + AFE_TDM_CON1_LRCK_INV | 453 453 AFE_TDM_CON1_1_BCK_DELAY | 454 454 AFE_TDM_CON1_MSB_ALIGNED | /* I2S mode */ 455 455 AFE_TDM_CON1_WLEN_32BIT |
+8
sound/soc/omap/mcbsp.c
··· 260 260 if (mcbsp->pdata->enable_st_clock) 261 261 mcbsp->pdata->enable_st_clock(mcbsp->id, 1); 262 262 263 + /* Disable Sidetone clock auto-gating for normal operation */ 264 + w = MCBSP_ST_READ(mcbsp, SYSCONFIG); 265 + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE)); 266 + 263 267 /* Enable McBSP Sidetone */ 264 268 w = MCBSP_READ(mcbsp, SSELCR); 265 269 MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN); ··· 282 278 283 279 w = MCBSP_READ(mcbsp, SSELCR); 284 280 MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN)); 281 + 282 + /* Enable Sidetone clock auto-gating to reduce power consumption */ 283 + w = MCBSP_ST_READ(mcbsp, SYSCONFIG); 284 + MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w | ST_AUTOIDLE); 285 285 286 286 if (mcbsp->pdata->enable_st_clock) 287 287 mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
+2
sound/soc/omap/omap-pcm.c
··· 82 82 struct dma_chan *chan; 83 83 int err = 0; 84 84 85 + memset(&config, 0x00, sizeof(config)); 86 + 85 87 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 86 88 87 89 /* return if this is a bufferless transfer e.g.
+1
sound/soc/pxa/brownstone.c
··· 133 133 MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); 134 134 MODULE_DESCRIPTION("ALSA SoC Brownstone"); 135 135 MODULE_LICENSE("GPL"); 136 + MODULE_ALIAS("platform:brownstone-audio");
+1
sound/soc/pxa/mioa701_wm9713.c
··· 207 207 MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)"); 208 208 MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701"); 209 209 MODULE_LICENSE("GPL"); 210 + MODULE_ALIAS("platform:mioa701-wm9713");
+1
sound/soc/pxa/mmp-pcm.c
··· 248 248 MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); 249 249 MODULE_DESCRIPTION("MMP Soc Audio DMA module"); 250 250 MODULE_LICENSE("GPL"); 251 + MODULE_ALIAS("platform:mmp-pcm-audio");
+1
sound/soc/pxa/mmp-sspa.c
··· 482 482 MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); 483 483 MODULE_DESCRIPTION("MMP SSPA SoC Interface"); 484 484 MODULE_LICENSE("GPL"); 485 + MODULE_ALIAS("platform:mmp-sspa-dai");
+1
sound/soc/pxa/palm27x.c
··· 161 161 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); 162 162 MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive"); 163 163 MODULE_LICENSE("GPL"); 164 + MODULE_ALIAS("platform:palm27x-asoc");
+1
sound/soc/pxa/pxa-ssp.c
··· 833 833 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 834 834 MODULE_DESCRIPTION("PXA SSP/PCM SoC Interface"); 835 835 MODULE_LICENSE("GPL"); 836 + MODULE_ALIAS("platform:pxa-ssp-dai");
+1
sound/soc/pxa/pxa2xx-ac97.c
··· 287 287 MODULE_AUTHOR("Nicolas Pitre"); 288 288 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); 289 289 MODULE_LICENSE("GPL"); 290 + MODULE_ALIAS("platform:pxa2xx-ac97");
+1
sound/soc/pxa/pxa2xx-pcm.c
··· 117 117 MODULE_AUTHOR("Nicolas Pitre"); 118 118 MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); 119 119 MODULE_LICENSE("GPL"); 120 + MODULE_ALIAS("platform:pxa-pcm-audio");
+4 -2
sound/soc/qcom/lpass-platform.c
··· 474 474 struct lpass_data *drvdata = 475 475 snd_soc_platform_get_drvdata(soc_runtime->platform); 476 476 struct lpass_variant *v = drvdata->variant; 477 - int ret; 477 + int ret = -EINVAL; 478 478 struct lpass_pcm_data *data; 479 479 size_t size = lpass_platform_pcm_hardware.buffer_bytes_max; 480 480 ··· 518 518 data->wrdma_ch = v->alloc_dma_channel(drvdata, 519 519 SNDRV_PCM_STREAM_CAPTURE); 520 520 521 - if (data->wrdma_ch < 0) 521 + if (data->wrdma_ch < 0) { 522 + ret = data->wrdma_ch; 522 523 goto capture_alloc_err; 524 + } 523 525 524 526 drvdata->substream[data->wrdma_ch] = csubstream; 525 527
+2 -6
sound/soc/sh/rcar/adg.c
··· 492 492 */ 493 493 if (!count) { 494 494 clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT], 495 - parent_clk_name, 496 - (parent_clk_name) ? 497 - 0 : CLK_IS_ROOT, req_rate); 495 + parent_clk_name, 0, req_rate); 498 496 if (!IS_ERR(clk)) { 499 497 adg->clkout[CLKOUT] = clk; 500 498 of_clk_add_provider(np, of_clk_src_simple_get, clk); ··· 504 506 else { 505 507 for (i = 0; i < CLKOUTMAX; i++) { 506 508 clk = clk_register_fixed_rate(dev, clkout_name[i], 507 - parent_clk_name, 508 - (parent_clk_name) ? 509 - 0 : CLK_IS_ROOT, 509 + parent_clk_name, 0, 510 510 req_rate); 511 511 if (!IS_ERR(clk)) { 512 512 adg->onecell.clks = adg->clkout;
+8 -4
sound/soc/sh/rcar/dma.c
··· 316 316 size = ARRAY_SIZE(gen2_id_table_cmd); 317 317 } 318 318 319 - if (!entry) 320 - return 0xFF; 319 + if ((!entry) || (size <= id)) { 320 + struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io)); 321 321 322 - if (size <= id) 323 - return 0xFF; 322 + dev_err(dev, "unknown connection (%s[%d])\n", 323 + rsnd_mod_name(mod), rsnd_mod_id(mod)); 324 + 325 + /* use non-prohibited SRS number as error */ 326 + return 0x00; /* SSI00 */ 327 + } 324 328 325 329 return entry[id]; 326 330 }
+7 -6
sound/soc/sh/rcar/rsnd.h
··· 276 276 /* 277 277 * status 278 278 * 279 - * 0xH0000CB0 279 + * 0xH0000CBA 280 280 * 281 + * A 0: probe 1: remove 281 282 * B 0: init 1: quit 282 283 * C 0: start 1: stop 283 284 * ··· 288 287 * H 0: fallback 289 288 * H 0: hw_params 290 289 */ 290 + #define __rsnd_mod_shift_probe 0 291 + #define __rsnd_mod_shift_remove 0 291 292 #define __rsnd_mod_shift_init 4 292 293 #define __rsnd_mod_shift_quit 4 293 294 #define __rsnd_mod_shift_start 8 294 295 #define __rsnd_mod_shift_stop 8 295 - #define __rsnd_mod_shift_probe 28 /* always called */ 296 - #define __rsnd_mod_shift_remove 28 /* always called */ 297 296 #define __rsnd_mod_shift_irq 28 /* always called */ 298 297 #define __rsnd_mod_shift_pcm_new 28 /* always called */ 299 298 #define __rsnd_mod_shift_fallback 28 /* always called */ 300 299 #define __rsnd_mod_shift_hw_params 28 /* always called */ 301 300 302 - #define __rsnd_mod_add_probe 0 303 - #define __rsnd_mod_add_remove 0 301 + #define __rsnd_mod_add_probe 1 302 + #define __rsnd_mod_add_remove -1 304 303 #define __rsnd_mod_add_init 1 305 304 #define __rsnd_mod_add_quit -1 306 305 #define __rsnd_mod_add_start 1 ··· 311 310 #define __rsnd_mod_add_hw_params 0 312 311 313 312 #define __rsnd_mod_call_probe 0 314 - #define __rsnd_mod_call_remove 0 313 + #define __rsnd_mod_call_remove 1 315 314 #define __rsnd_mod_call_init 0 316 315 #define __rsnd_mod_call_quit 1 317 316 #define __rsnd_mod_call_start 0
+4
sound/soc/sh/rcar/src.c
··· 572 572 573 573 i = 0; 574 574 for_each_child_of_node(node, np) { 575 + if (!of_device_is_available(np)) 576 + goto skip; 577 + 575 578 src = rsnd_src_get(priv, i); 576 579 577 580 snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d", ··· 598 595 if (ret) 599 596 goto rsnd_src_probe_done; 600 597 598 + skip: 601 599 i++; 602 600 } 603 601
+45 -3
sound/soc/soc-topology.c
··· 1023 1023 1024 1024 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; 1025 1025 1026 + if (control_hdr->size != sizeof(*control_hdr)) { 1027 + dev_err(tplg->dev, "ASoC: invalid control size\n"); 1028 + return -EINVAL; 1029 + } 1030 + 1026 1031 switch (control_hdr->ops.info) { 1027 1032 case SND_SOC_TPLG_CTL_VOLSW: 1028 1033 case SND_SOC_TPLG_CTL_STROBE: ··· 1481 1476 widget->dobj.type = SND_SOC_DOBJ_WIDGET; 1482 1477 widget->dobj.ops = tplg->ops; 1483 1478 widget->dobj.index = tplg->index; 1479 + kfree(template.sname); 1480 + kfree(template.name); 1484 1481 list_add(&widget->dobj.list, &tplg->comp->dobj_list); 1485 1482 return 0; 1486 1483 ··· 1506 1499 1507 1500 for (i = 0; i < count; i++) { 1508 1501 widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; 1502 + if (widget->size != sizeof(*widget)) { 1503 + dev_err(tplg->dev, "ASoC: invalid widget size\n"); 1504 + return -EINVAL; 1505 + } 1506 + 1509 1507 ret = soc_tplg_dapm_widget_create(tplg, widget); 1510 - if (ret < 0) 1508 + if (ret < 0) { 1511 1509 dev_err(tplg->dev, "ASoC: failed to load widget %s\n", 1512 1510 widget->name); 1511 + return ret; 1512 + } 1513 1513 } 1514 1514 1515 1515 return 0; ··· 1600 1586 return snd_soc_register_dai(tplg->comp, dai_drv); 1601 1587 } 1602 1588 1589 + /* create the FE DAI link */ 1603 1590 static int soc_tplg_link_create(struct soc_tplg *tplg, 1604 1591 struct snd_soc_tplg_pcm *pcm) 1605 1592 { ··· 1613 1598 1614 1599 link->name = pcm->pcm_name; 1615 1600 link->stream_name = pcm->pcm_name; 1601 + link->id = pcm->pcm_id; 1602 + 1603 + link->cpu_dai_name = pcm->dai_name; 1604 + link->codec_name = "snd-soc-dummy"; 1605 + link->codec_dai_name = "snd-soc-dummy-dai"; 1606 + 1607 + /* enable DPCM */ 1608 + link->dynamic = 1; 1609 + link->dpcm_playback = pcm->playback; 1610 + link->dpcm_capture = pcm->capture; 1616 1611 1617 1612 /* pass control to component driver for optional further init */ 1618 1613 ret = soc_tplg_dai_link_load(tplg, link); ··· 1664 1639 if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) 1665 1640 return 0; 1666 1641 1667 - pcm = (struct snd_soc_tplg_pcm *)tplg->pos; 1668 - 1669 1642 if (soc_tplg_check_elem_count(tplg, 1670 1643 sizeof(struct snd_soc_tplg_pcm), count, 1671 1644 hdr->payload_size, "PCM DAI")) { ··· 1673 1650 } 1674 1651 1675 1652 /* create the FE DAIs and DAI links */ 1653 + pcm = (struct snd_soc_tplg_pcm *)tplg->pos; 1676 1654 for (i = 0; i < count; i++) { 1655 + if (pcm->size != sizeof(*pcm)) { 1656 + dev_err(tplg->dev, "ASoC: invalid pcm size\n"); 1657 + return -EINVAL; 1658 + } 1659 + 1677 1660 soc_tplg_pcm_create(tplg, pcm); 1678 1661 pcm++; 1679 1662 } ··· 1699 1670 return 0; 1700 1671 1701 1672 manifest = (struct snd_soc_tplg_manifest *)tplg->pos; 1673 + if (manifest->size != sizeof(*manifest)) { 1674 + dev_err(tplg->dev, "ASoC: invalid manifest size\n"); 1675 + return -EINVAL; 1676 + } 1677 + 1702 1678 tplg->pos += sizeof(struct snd_soc_tplg_manifest); 1703 1679 1704 1680 if (tplg->comp && tplg->ops && tplg->ops->manifest) ··· 1719 1685 { 1720 1686 if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) 1721 1687 return 0; 1688 + 1689 + if (hdr->size != sizeof(*hdr)) { 1690 + dev_err(tplg->dev, 1691 + "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n", 1692 + hdr->type, soc_tplg_get_hdr_offset(tplg), 1693 + tplg->fw->size); 1694 + return -EINVAL; 1695 + } 1722 1696 1723 1697 /* big endian firmware objects not supported atm */ 1724 1698 if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) {
+143 -1
sound/soc/sti/sti_uniperif.c
··· 11 11 #include "uniperif.h" 12 12 13 13 /* 14 + * User frame size shall be 2, 4, 6 or 8 32-bits words length 15 + * (i.e. 8, 16, 24 or 32 bytes) 16 + * This constraint comes from allowed values for 17 + * UNIPERIF_I2S_FMT_NUM_CH register 18 + */ 19 + #define UNIPERIF_MAX_FRAME_SZ 0x20 20 + #define UNIPERIF_ALLOWED_FRAME_SZ (0x08 | 0x10 | 0x18 | UNIPERIF_MAX_FRAME_SZ) 21 + 22 + int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 23 + unsigned int rx_mask, int slots, 24 + int slot_width) 25 + { 26 + struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 27 + struct uniperif *uni = priv->dai_data.uni; 28 + int i, frame_size, avail_slots; 29 + 30 + if (!UNIPERIF_TYPE_IS_TDM(uni)) { 31 + dev_err(uni->dev, "cpu dai not in tdm mode\n"); 32 + return -EINVAL; 33 + } 34 + 35 + /* store info in unip context */ 36 + uni->tdm_slot.slots = slots; 37 + uni->tdm_slot.slot_width = slot_width; 38 + /* unip is unidirectionnal */ 39 + uni->tdm_slot.mask = (tx_mask != 0) ? tx_mask : rx_mask; 40 + 41 + /* number of available timeslots */ 42 + for (i = 0, avail_slots = 0; i < uni->tdm_slot.slots; i++) { 43 + if ((uni->tdm_slot.mask >> i) & 0x01) 44 + avail_slots++; 45 + } 46 + uni->tdm_slot.avail_slots = avail_slots; 47 + 48 + /* frame size in bytes */ 49 + frame_size = uni->tdm_slot.avail_slots * uni->tdm_slot.slot_width / 8; 50 + 51 + /* check frame size is allowed */ 52 + if ((frame_size > UNIPERIF_MAX_FRAME_SZ) || 53 + (frame_size & ~(int)UNIPERIF_ALLOWED_FRAME_SZ)) { 54 + dev_err(uni->dev, "frame size not allowed: %d bytes\n", 55 + frame_size); 56 + return -EINVAL; 57 + } 58 + 59 + return 0; 60 + } 61 + 62 + int sti_uniperiph_fix_tdm_chan(struct snd_pcm_hw_params *params, 63 + struct snd_pcm_hw_rule *rule) 64 + { 65 + struct uniperif *uni = rule->private; 66 + struct snd_interval t; 67 + 68 + t.min = uni->tdm_slot.avail_slots; 69 + t.max = uni->tdm_slot.avail_slots; 70 + t.openmin = 0; 71 + t.openmax = 0; 72 + t.integer = 0; 73 + 74 + return snd_interval_refine(hw_param_interval(params, rule->var), &t); 75 + } 76 + 77 + int sti_uniperiph_fix_tdm_format(struct snd_pcm_hw_params *params, 78 + struct snd_pcm_hw_rule *rule) 79 + { 80 + struct uniperif *uni = rule->private; 81 + struct snd_mask *maskp = hw_param_mask(params, rule->var); 82 + u64 format; 83 + 84 + switch (uni->tdm_slot.slot_width) { 85 + case 16: 86 + format = SNDRV_PCM_FMTBIT_S16_LE; 87 + break; 88 + case 32: 89 + format = SNDRV_PCM_FMTBIT_S32_LE; 90 + break; 91 + default: 92 + dev_err(uni->dev, "format not supported: %d bits\n", 93 + uni->tdm_slot.slot_width); 94 + return -EINVAL; 95 + } 96 + 97 + maskp->bits[0] &= (u_int32_t)format; 98 + maskp->bits[1] &= (u_int32_t)(format >> 32); 99 + /* clear remaining indexes */ 100 + memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX - 64) / 8); 101 + 102 + if (!maskp->bits[0] && !maskp->bits[1]) 103 + return -EINVAL; 104 + 105 + return 0; 106 + } 107 + 108 + int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni, 109 + unsigned int *word_pos) 110 + { 111 + int slot_width = uni->tdm_slot.slot_width / 8; 112 + int slots_num = uni->tdm_slot.slots; 113 + unsigned int slots_mask = uni->tdm_slot.mask; 114 + int i, j, k; 115 + unsigned int word16_pos[4]; 116 + 117 + /* word16_pos: 118 + * word16_pos[0] = WORDX_LSB 119 + * word16_pos[1] = WORDX_MSB, 120 + * word16_pos[2] = WORDX+1_LSB 121 + * word16_pos[3] = WORDX+1_MSB 122 + */ 123 + 124 + /* set unip word position */ 125 + for (i = 0, j = 0, k = 0; (i < slots_num) && (k < WORD_MAX); i++) { 126 + if ((slots_mask >> i) & 0x01) { 127 + word16_pos[j] = i * slot_width; 128 + 129 + if (slot_width == 4) { 130 + word16_pos[j + 1] = word16_pos[j] + 2; 131 + j++; 132 + } 133 + j++; 134 + 135 + if (j > 3) { 136 + word_pos[k] = word16_pos[1] | 137 + (word16_pos[0] << 8) | 138 + (word16_pos[3] << 16) | 139 + (word16_pos[2] << 24); 140 + j = 0; 141 + k++; 142 + } 143 + } 144 + } 145 + 146 + return 0; 147 + } 148 + 149 + /* 14 150 * sti_uniperiph_dai_create_ctrl 15 151 * This function is used to create Ctrl associated to DAI but also pcm device. 16 152 * Request is done by front end to associate ctrl with pcm device id ··· 181 45 struct snd_pcm_hw_params *params, 182 46 struct snd_soc_dai *dai) 183 47 { 48 + struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 49 + struct uniperif *uni = priv->dai_data.uni; 184 50 struct snd_dmaengine_dai_dma_data *dma_data; 185 51 int transfer_size; 186 52 187 - transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES; 53 + if (uni->info->type == SND_ST_UNIPERIF_TYPE_TDM) 54 + /* transfer size = user frame size (in 32-bits FIFO cell) */ 55 + transfer_size = snd_soc_params_to_frame_size(params) / 32; 56 + else 57 + transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES; 188 58 189 59 dma_data = snd_soc_dai_get_dma_data(dai, substream); 190 60 dma_data->maxburst = transfer_size;
+204 -16
sound/soc/sti/uniperif.h
··· 25 25 writel_relaxed((((value) & mask) << shift), ip->base + offset) 26 26 27 27 /* 28 - * AUD_UNIPERIF_SOFT_RST reg 28 + * UNIPERIF_SOFT_RST reg 29 29 */ 30 30 31 31 #define UNIPERIF_SOFT_RST_OFFSET(ip) 0x0000 ··· 50 50 UNIPERIF_SOFT_RST_SOFT_RST_MASK(ip)) 51 51 52 52 /* 53 - * AUD_UNIPERIF_FIFO_DATA reg 53 + * UNIPERIF_FIFO_DATA reg 54 54 */ 55 55 56 56 #define UNIPERIF_FIFO_DATA_OFFSET(ip) 0x0004 ··· 58 58 writel_relaxed(value, ip->base + UNIPERIF_FIFO_DATA_OFFSET(ip)) 59 59 60 60 /* 61 - * AUD_UNIPERIF_CHANNEL_STA_REGN reg 61 + * UNIPERIF_CHANNEL_STA_REGN reg 62 62 */ 63 63 64 64 #define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n)) ··· 105 105 writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG5_OFFSET(ip)) 106 106 107 107 /* 108 - * AUD_UNIPERIF_ITS reg 108 + * UNIPERIF_ITS reg 109 109 */ 110 110 111 111 #define UNIPERIF_ITS_OFFSET(ip) 0x000C ··· 143 143 0 : (BIT(UNIPERIF_ITS_UNDERFLOW_REC_FAILED_SHIFT(ip)))) 144 144 145 145 /* 146 - * AUD_UNIPERIF_ITS_BCLR reg 146 + * UNIPERIF_ITS_BCLR reg 147 147 */ 148 148 149 149 /* FIFO_ERROR */ ··· 160 160 writel_relaxed(value, ip->base + UNIPERIF_ITS_BCLR_OFFSET(ip)) 161 161 162 162 /* 163 - * AUD_UNIPERIF_ITM reg 163 + * UNIPERIF_ITM reg 164 164 */ 165 165 166 166 #define UNIPERIF_ITM_OFFSET(ip) 0x0018 ··· 188 188 0 : (BIT(UNIPERIF_ITM_UNDERFLOW_REC_FAILED_SHIFT(ip)))) 189 189 190 190 /* 191 - * AUD_UNIPERIF_ITM_BCLR reg 191 + * UNIPERIF_ITM_BCLR reg 192 192 */ 193 193 194 194 #define UNIPERIF_ITM_BCLR_OFFSET(ip) 0x001c ··· 213 213 UNIPERIF_ITM_BCLR_DMA_ERROR_MASK(ip)) 214 214 215 215 /* 216 - * AUD_UNIPERIF_ITM_BSET reg 216 + * UNIPERIF_ITM_BSET reg 217 217 */ 218 218 219 219 #define UNIPERIF_ITM_BSET_OFFSET(ip) 0x0020 ··· 767 767 SET_UNIPERIF_REG(ip, \ 768 768 UNIPERIF_CTRL_OFFSET(ip), \ 769 769 UNIPERIF_CTRL_READER_OUT_SEL_SHIFT(ip), \ 770 - CORAUD_UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip), 1) 770 + UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip), 1) 771 771 772 772 /* UNDERFLOW_REC_WINDOW */ 773 773 #define UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_SHIFT(ip) 20 ··· 1046 1046 UNIPERIF_STATUS_1_UNDERFLOW_DURATION_MASK(ip), value) 1047 1047 1048 1048 /* 1049 - * AUD_UNIPERIF_CHANNEL_STA_REGN reg 1049 + * UNIPERIF_CHANNEL_STA_REGN reg 1050 1050 */ 1051 1051 1052 1052 #define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n)) ··· 1057 1057 UNIPERIF_CHANNEL_STA_REGN(ip, n)) 1058 1058 1059 1059 /* 1060 - * AUD_UNIPERIF_USER_VALIDITY reg 1060 + * UNIPERIF_USER_VALIDITY reg 1061 1061 */ 1062 1062 1063 1063 #define UNIPERIF_USER_VALIDITY_OFFSET(ip) 0x0090 ··· 1101 1101 UNIPERIF_DBG_STANDBY_LEFT_SP_MASK(ip), value) 1102 1102 1103 1103 /* 1104 + * UNIPERIF_TDM_ENABLE 1105 + */ 1106 + #define UNIPERIF_TDM_ENABLE_OFFSET(ip) 0x0118 1107 + #define GET_UNIPERIF_TDM_ENABLE(ip) \ 1108 + readl_relaxed(ip->base + UNIPERIF_TDM_ENABLE_OFFSET(ip)) 1109 + #define SET_UNIPERIF_TDM_ENABLE(ip, value) \ 1110 + writel_relaxed(value, ip->base + UNIPERIF_TDM_ENABLE_OFFSET(ip)) 1111 + 1112 + /* TDM_ENABLE */ 1113 + #define UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip) 0x0 1114 + #define UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip) 0x1 1115 + #define GET_UNIPERIF_TDM_ENABLE_EN_TDM(ip) \ 1116 + GET_UNIPERIF_REG(ip, \ 1117 + UNIPERIF_TDM_ENABLE_OFFSET(ip), \ 1118 + UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \ 1119 + UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip)) 1120 + #define SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(ip) \ 1121 + SET_UNIPERIF_REG(ip, \ 1122 + UNIPERIF_TDM_ENABLE_OFFSET(ip), \ 1123 + UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \ 1124 + UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip), 1) 1125 + #define SET_UNIPERIF_TDM_ENABLE_TDM_DISABLE(ip) \ 1126 + SET_UNIPERIF_REG(ip, \ 1127 + UNIPERIF_TDM_ENABLE_OFFSET(ip), \ 1128 + UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \ 1129 + UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip), 0) 1130 + 1131 + /* 1132 + * UNIPERIF_TDM_FS_REF_FREQ 1133 + */ 1134 + #define UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip) 0x011c 1135 + #define GET_UNIPERIF_TDM_FS_REF_FREQ(ip) \ 1136 + readl_relaxed(ip->base + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip)) 1137 + #define SET_UNIPERIF_TDM_FS_REF_FREQ(ip, value) \ 1138 + writel_relaxed(value, ip->base + \ 1139 + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip)) 1140 + 1141 + /* REF_FREQ */ 1142 + #define UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip) 0x0 1143 + #define VALUE_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip) 0 1144 + #define VALUE_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip) 1 1145 + #define VALUE_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip) 2 1146 + #define VALUE_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip) 3 1147 + #define UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip) 0x3 1148 + #define GET_UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ(ip) \ 1149 + GET_UNIPERIF_REG(ip, \ 1150 + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \ 1151 + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \ 1152 + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip)) 1153 + #define SET_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip) \ 1154 + SET_UNIPERIF_REG(ip, \ 1155 + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \ 1156 + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \ 1157 + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \ 1158 + VALUE_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip)) 1159 + #define SET_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip) \ 1160 + SET_UNIPERIF_REG(ip, \ 1161 + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \ 1162 + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \ 1163 + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \ 1164 + VALUE_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip)) 1165 + #define SET_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip) \ 1166 + SET_UNIPERIF_REG(ip, \ 1167 + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \ 1168 + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \ 1169 + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \ 1170 + VALUE_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip)) 1171 + #define SET_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip) \ 1172 + SET_UNIPERIF_REG(ip, \ 1173 + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \ 1174 + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \ 1175 + UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \ 1176 + VALUE_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip)) 1177 + 1178 + /* 1179 + * UNIPERIF_TDM_FS_REF_DIV 1180 + */ 1181 + #define UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip) 0x0120 1182 + #define GET_UNIPERIF_TDM_FS_REF_DIV(ip) \ 1183 + readl_relaxed(ip->base + UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip)) 1184 + #define SET_UNIPERIF_TDM_FS_REF_DIV(ip, value) \ 1185 + writel_relaxed(value, ip->base + \ 1186 + UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip)) 1187 + 1188 + /* NUM_TIMESLOT */ 1189 + #define UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip) 0x0 1190 + #define UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip) 0xff 1191 + #define GET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(ip) \ 1192 + GET_UNIPERIF_REG(ip, \ 1193 + UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip), \ 1194 + UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip), \ 1195 + UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip)) 1196 + #define SET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(ip, value) \ 1197 + SET_UNIPERIF_REG(ip, \ 1198 + UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip), \ 1199 + UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip), \ 1200 + UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip), value) 1201 + 1202 + /* 1203 + * UNIPERIF_TDM_WORD_POS_X_Y 1204 + * 32 bits of UNIPERIF_TDM_WORD_POS_X_Y register shall be set in 1 shot 1205 + */ 1206 + #define UNIPERIF_TDM_WORD_POS_1_2_OFFSET(ip) 0x013c 1207 + #define UNIPERIF_TDM_WORD_POS_3_4_OFFSET(ip) 0x0140 1208 + #define UNIPERIF_TDM_WORD_POS_5_6_OFFSET(ip) 0x0144 1209 + #define UNIPERIF_TDM_WORD_POS_7_8_OFFSET(ip) 0x0148 1210 + #define GET_UNIPERIF_TDM_WORD_POS(ip, words) \ 1211 + readl_relaxed(ip->base + UNIPERIF_TDM_WORD_POS_##words##_OFFSET(ip)) 1212 + #define SET_UNIPERIF_TDM_WORD_POS(ip, words, value) \ 1213 + writel_relaxed(value, ip->base + \ 1214 + UNIPERIF_TDM_WORD_POS_##words##_OFFSET(ip)) 1215 + /* 1104 1216 * uniperipheral IP capabilities 1105 1217 */ 1106 1218 1107 1219 #define UNIPERIF_FIFO_SIZE 70 /* FIFO is 70 cells deep */ 1108 1220 #define UNIPERIF_FIFO_FRAMES 4 /* FDMA trigger limit in frames */ 1221 + 1222 + #define UNIPERIF_TYPE_IS_HDMI(p) \ 1223 + ((p)->info->type == SND_ST_UNIPERIF_TYPE_HDMI) 1224 + #define UNIPERIF_TYPE_IS_PCM(p) \ 1225 + ((p)->info->type == SND_ST_UNIPERIF_TYPE_PCM) 1226 + #define UNIPERIF_TYPE_IS_SPDIF(p) \ 1227 + ((p)->info->type == SND_ST_UNIPERIF_TYPE_SPDIF) 1228 + #define UNIPERIF_TYPE_IS_IEC958(p) \ 1229 + (UNIPERIF_TYPE_IS_HDMI(p) || \ 1230 + UNIPERIF_TYPE_IS_SPDIF(p)) 1231 + #define UNIPERIF_TYPE_IS_TDM(p) \ 1232 + ((p)->info->type == SND_ST_UNIPERIF_TYPE_TDM) 1109 1233 1110 1234 /* 1111 1235 * Uniperipheral IP revisions ··· 1249 1125 }; 1250 1126 1251 1127 enum uniperif_type { 1252 - SND_ST_UNIPERIF_PLAYER_TYPE_NONE, 1253 - SND_ST_UNIPERIF_PLAYER_TYPE_HDMI, 1254 - SND_ST_UNIPERIF_PLAYER_TYPE_PCM, 1255 - SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF 1128 + SND_ST_UNIPERIF_TYPE_NONE, 1129 + SND_ST_UNIPERIF_TYPE_HDMI, 1130 + SND_ST_UNIPERIF_TYPE_PCM, 1131 + SND_ST_UNIPERIF_TYPE_SPDIF, 1132 + SND_ST_UNIPERIF_TYPE_TDM 1256 1133 }; 1257 1134 1258 1135 enum uniperif_state { ··· 1270 1145 UNIPERIF_IEC958_ENCODING_MODE_ENCODED 1271 1146 }; 1272 1147 1148 + enum uniperif_word_pos { 1149 + WORD_1_2, 1150 + WORD_3_4, 1151 + WORD_5_6, 1152 + WORD_7_8, 1153 + WORD_MAX 1154 + }; 1155 + 1273 1156 struct uniperif_info { 1274 1157 int id; /* instance value of the uniperipheral IP */ 1275 - enum uniperif_type player_type; 1158 + enum uniperif_type type; 1276 1159 int underflow_enabled; /* Underflow recovery mode */ 1277 1160 }; 1278 1161 ··· 1289 1156 struct snd_aes_iec958 iec958; 1290 1157 }; 1291 1158 1159 + struct dai_tdm_slot { 1160 + unsigned int mask; 1161 + int slots; 1162 + int slot_width; 1163 + unsigned int avail_slots; 1164 + }; 1165 + 1292 1166 struct uniperif { 1293 1167 /* System information */ 1294 1168 struct uniperif_info *info; 1295 1169 struct device *dev; 1296 1170 int ver; /* IP version, used by register access macros */ 1297 1171 struct regmap_field *clk_sel; 1172 + struct regmap_field *valid_sel; 1298 1173 1299 1174 /* capabilities */ 1300 1175 const struct snd_pcm_hardware *hw; ··· 1333 1192 1334 1193 /* dai properties */ 1335 1194 unsigned int daifmt; 1195 + struct dai_tdm_slot tdm_slot; 1336 1196 1337 1197 /* DAI callbacks */ 1338 1198 const struct snd_soc_dai_ops *dai_ops; ··· 1349 1207 struct platform_device *pdev; 1350 1208 struct snd_soc_dai_driver *dai; 1351 1209 struct sti_uniperiph_dai dai_data; 1210 + }; 1211 + 1212 + static const struct snd_pcm_hardware uni_tdm_hw = { 1213 + .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 1214 + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP | 1215 + SNDRV_PCM_INFO_MMAP_VALID, 1216 + 1217 + .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE, 1218 + 1219 + .rates = SNDRV_PCM_RATE_CONTINUOUS, 1220 + .rate_min = 8000, 1221 + .rate_max = 48000, 1222 + 1223 + .channels_min = 1, 1224 + .channels_max = 32, 1225 + 1226 + .periods_min = 2, 1227 + .periods_max = 10, 1228 + 1229 + .period_bytes_min = 128, 1230 + .period_bytes_max = 64 * PAGE_SIZE, 1231 + .buffer_bytes_max = 256 * PAGE_SIZE 1352 1232 }; 1353 1233 1354 1234 /* uniperiph player*/ ··· 1389 1225 int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream, 1390 1226 struct snd_pcm_hw_params *params, 1391 1227 struct snd_soc_dai *dai); 1228 + 1229 + static inline int sti_uniperiph_get_user_frame_size( 1230 + struct snd_pcm_runtime *runtime) 1231 + { 1232 + return (runtime->channels * snd_pcm_format_width(runtime->format) / 8); 1233 + } 1234 + 1235 + static inline int sti_uniperiph_get_unip_tdm_frame_size(struct uniperif *uni) 1236 + { 1237 + return (uni->tdm_slot.slots * uni->tdm_slot.slot_width / 8); 1238 + } 1239 + 1240 + int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 1241 + unsigned int rx_mask, int slots, 1242 + int slot_width); 1243 + 1244 + int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni, 1245 + unsigned int *word_pos); 1246 + 1247 + int sti_uniperiph_fix_tdm_chan(struct snd_pcm_hw_params *params, 1248 + struct snd_pcm_hw_rule *rule); 1249 + 1250 + int sti_uniperiph_fix_tdm_format(struct snd_pcm_hw_params *params, 1251 + struct snd_pcm_hw_rule *rule); 1392 1252 1393 1253 #endif
+131 -51
sound/soc/sti/uniperif_player.c
··· 21 21 22 22 /* sys config registers definitions */ 23 23 #define SYS_CFG_AUDIO_GLUE 0xA4 24 - #define SYS_CFG_AUDI0_GLUE_PCM_CLKX 8 25 24 26 25 /* 27 26 * Driver specific types. 28 27 */ 29 - #define UNIPERIF_PLAYER_TYPE_IS_HDMI(p) \ 30 - ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_HDMI) 31 - #define UNIPERIF_PLAYER_TYPE_IS_PCM(p) \ 32 - ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_PCM) 33 - #define UNIPERIF_PLAYER_TYPE_IS_SPDIF(p) \ 34 - ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF) 35 - #define UNIPERIF_PLAYER_TYPE_IS_IEC958(p) \ 36 - (UNIPERIF_PLAYER_TYPE_IS_HDMI(p) || \ 37 - UNIPERIF_PLAYER_TYPE_IS_SPDIF(p)) 38 28 39 29 #define UNIPERIF_PLAYER_CLK_ADJ_MIN -999999 40 30 #define UNIPERIF_PLAYER_CLK_ADJ_MAX 1000000 31 + #define UNIPERIF_PLAYER_I2S_OUT 1 /* player id connected to I2S/TDM TX bus */ 41 32 42 33 /* 43 34 * Note: snd_pcm_hardware is linked to DMA controller but is declared here to ··· 435 444 436 445 /* Force slot width to 32 in I2S mode (HW constraint) */ 437 446 if ((player->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == 438 - SND_SOC_DAIFMT_I2S) { 447 + SND_SOC_DAIFMT_I2S) 439 448 slot_width = 32; 440 - } else { 441 - switch (runtime->format) { 442 - case SNDRV_PCM_FORMAT_S16_LE: 443 - slot_width = 16; 444 - break; 445 - default: 446 - slot_width = 32; 447 - break; 448 - } 449 - } 449 + else 450 + slot_width = snd_pcm_format_width(runtime->format); 451 + 450 452 output_frame_size = slot_width * runtime->channels; 451 453 452 454 clk_div = player->mclk / runtime->rate; ··· 514 530 SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player); 515 531 516 532 SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); 517 - SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(player); 518 533 519 534 /* No iec958 formatting as outputting to DAC */ 520 535 SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player); 536 + 537 + return 0; 538 + } 539 + 540 + static int uni_player_prepare_tdm(struct uniperif *player, 541 + struct snd_pcm_runtime *runtime) 542 + { 543 + int tdm_frame_size; /* unip tdm frame size in bytes */ 544 + int user_frame_size; /* user tdm frame size in bytes */ 545 + /* default unip TDM_WORD_POS_X_Y */ 546 + unsigned int word_pos[4] = { 547 + 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A}; 548 + int freq, ret; 549 + 550 + tdm_frame_size = 551 + sti_uniperiph_get_unip_tdm_frame_size(player); 552 + user_frame_size = 553 + sti_uniperiph_get_user_frame_size(runtime); 554 + 555 + /* fix 16/0 format */ 556 + SET_UNIPERIF_CONFIG_MEM_FMT_16_0(player); 557 + SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(player); 558 + 559 + /* number of words inserted on the TDM line */ 560 + SET_UNIPERIF_I2S_FMT_NUM_CH(player, user_frame_size / 4 / 2); 561 + 562 + SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); 563 + SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(player); 564 + 565 + /* Enable the tdm functionality */ 566 + SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(player); 567 + 568 + /* number of 8 bits timeslots avail in unip tdm frame */ 569 + SET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(player, tdm_frame_size); 570 + 571 + /* set the timeslot allocation for words in FIFO */ 572 + sti_uniperiph_get_tdm_word_pos(player, word_pos); 573 + SET_UNIPERIF_TDM_WORD_POS(player, 1_2, word_pos[WORD_1_2]); 574 + SET_UNIPERIF_TDM_WORD_POS(player, 3_4, word_pos[WORD_3_4]); 575 + SET_UNIPERIF_TDM_WORD_POS(player, 5_6, word_pos[WORD_5_6]); 576 + SET_UNIPERIF_TDM_WORD_POS(player, 7_8, word_pos[WORD_7_8]); 577 + 578 + /* set unip clk rate (not done vai set_sysclk ops) */ 579 + freq = runtime->rate * tdm_frame_size * 8; 580 + mutex_lock(&player->ctrl_lock); 581 + ret = uni_player_clk_set_rate(player, freq); 582 + if (!ret) 583 + player->mclk = freq; 584 + mutex_unlock(&player->ctrl_lock); 521 585 522 586 return 0; 523 587 } ··· 700 668 { 701 669 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 702 670 struct uniperif *player = priv->dai_data.uni; 671 + int ret; 672 + 703 673 player->substream = substream; 704 674 705 675 player->clk_adj = 0; 706 676 707 - return 0; 677 + if (!UNIPERIF_TYPE_IS_TDM(player)) 678 + return 0; 679 + 680 + /* refine hw constraint in tdm mode */ 681 + ret = snd_pcm_hw_rule_add(substream->runtime, 0, 682 + SNDRV_PCM_HW_PARAM_CHANNELS, 683 + sti_uniperiph_fix_tdm_chan, 684 + player, SNDRV_PCM_HW_PARAM_CHANNELS, 685 + -1); 686 + if (ret < 0) 687 + return ret; 688 + 689 + return snd_pcm_hw_rule_add(substream->runtime, 0, 690 + SNDRV_PCM_HW_PARAM_FORMAT, 691 + sti_uniperiph_fix_tdm_format, 692 + player, SNDRV_PCM_HW_PARAM_FORMAT, 693 + -1); 708 694 } 709 695 710 696 static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id, ··· 732 682 struct uniperif *player = priv->dai_data.uni; 733 683 int ret; 734 684 735 - if (dir == SND_SOC_CLOCK_IN) 685 + if (UNIPERIF_TYPE_IS_TDM(player) || (dir == SND_SOC_CLOCK_IN)) 736 686 return 0; 737 687 738 688 if (clk_id != 0) ··· 764 714 } 765 715 766 716 /* Calculate transfer size (in fifo cells and bytes) for frame count */ 767 - transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; 717 + if (player->info->type == SND_ST_UNIPERIF_TYPE_TDM) { 718 + /* transfer size = user frame size (in 32 bits FIFO cell) */ 719 + transfer_size = 720 + sti_uniperiph_get_user_frame_size(runtime) / 4; 721 + } else { 722 + transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; 723 + } 768 724 769 725 /* Calculate number of empty cells available before asserting DREQ */ 770 726 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) { ··· 794 738 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(player, trigger_limit); 795 739 796 740 /* Uniperipheral setup depends on player type */ 797 - switch (player->info->player_type) { 798 - case SND_ST_UNIPERIF_PLAYER_TYPE_HDMI: 741 + switch (player->info->type) { 742 + case SND_ST_UNIPERIF_TYPE_HDMI: 799 743 ret = uni_player_prepare_iec958(player, runtime); 800 744 break; 801 - case SND_ST_UNIPERIF_PLAYER_TYPE_PCM: 745 + case SND_ST_UNIPERIF_TYPE_PCM: 802 746 ret = uni_player_prepare_pcm(player, runtime); 803 747 break; 804 - case SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF: 748 + case SND_ST_UNIPERIF_TYPE_SPDIF: 805 749 ret = uni_player_prepare_iec958(player, runtime); 750 + break; 751 + case SND_ST_UNIPERIF_TYPE_TDM: 752 + ret = uni_player_prepare_tdm(player, runtime); 806 753 break; 807 754 default: 808 755 dev_err(player->dev, "invalid player type"); ··· 911 852 * will not take affect and hang the player. 912 853 */ 913 854 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) 914 - if (UNIPERIF_PLAYER_TYPE_IS_IEC958(player)) 915 - SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player); 855 + if (UNIPERIF_TYPE_IS_IEC958(player)) 856 + SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player); 916 857 917 858 /* Force channel status update (no update if clk disable) */ 918 859 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) ··· 1013 954 player->substream = NULL; 1014 955 } 1015 956 1016 - static int uni_player_parse_dt_clk_glue(struct platform_device *pdev, 1017 - struct uniperif *player) 957 + static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, 958 + struct uniperif *player) 1018 959 { 1019 - int bit_offset; 1020 960 struct device_node *node = pdev->dev.of_node; 1021 961 struct regmap *regmap; 1022 - 1023 - bit_offset = SYS_CFG_AUDI0_GLUE_PCM_CLKX + player->info->id; 962 + struct reg_field regfield[2] = { 963 + /* PCM_CLK_SEL */ 964 + REG_FIELD(SYS_CFG_AUDIO_GLUE, 965 + 8 + player->info->id, 966 + 8 + player->info->id), 967 + /* PCMP_VALID_SEL */ 968 + REG_FIELD(SYS_CFG_AUDIO_GLUE, 0, 1) 969 + }; 1024 970 1025 971 regmap = syscon_regmap_lookup_by_phandle(node, "st,syscfg"); 1026 972 1027 - if (regmap) { 1028 - struct reg_field regfield = 1029 - REG_FIELD(SYS_CFG_AUDIO_GLUE, bit_offset, bit_offset); 1030 - 1031 - player->clk_sel = regmap_field_alloc(regmap, regfield); 1032 - } else { 973 + if (!regmap) { 1033 974 dev_err(&pdev->dev, "sti-audio-clk-glue syscf not found\n"); 1034 975 return -EINVAL; 1035 976 } 977 + 978 + player->clk_sel = regmap_field_alloc(regmap, regfield[0]); 979 + player->valid_sel = regmap_field_alloc(regmap, regfield[1]); 1036 980 1037 981 return 0; 1038 982 } ··· 1074 1012 } 1075 1013 1076 1014 if (strcasecmp(mode, "hdmi") == 0) 1077 - info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_HDMI; 1015 + info->type = SND_ST_UNIPERIF_TYPE_HDMI; 1078 1016 else if (strcasecmp(mode, "pcm") == 0) 1079 - info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_PCM; 1017 + info->type = SND_ST_UNIPERIF_TYPE_PCM; 1080 1018 else if (strcasecmp(mode, "spdif") == 0) 1081 - info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF; 1019 + info->type = SND_ST_UNIPERIF_TYPE_SPDIF; 1020 + else if (strcasecmp(mode, "tdm") == 0) 1021 + info->type = SND_ST_UNIPERIF_TYPE_TDM; 1082 1022 else 1083 - info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_NONE; 1023 + info->type = SND_ST_UNIPERIF_TYPE_NONE; 1084 1024 1085 1025 /* Save the info structure */ 1086 1026 player->info = info; 1087 1027 1088 - /* Get the PCM_CLK_SEL bit from audio-glue-ctrl SoC register */ 1089 - if (uni_player_parse_dt_clk_glue(pdev, player)) 1028 + /* Get PCM_CLK_SEL & PCMP_VALID_SEL from audio-glue-ctrl SoC reg */ 1029 + if (uni_player_parse_dt_audio_glue(pdev, player)) 1090 1030 return -EINVAL; 1091 1031 1092 1032 return 0; ··· 1101 1037 .trigger = uni_player_trigger, 1102 1038 .hw_params = sti_uniperiph_dai_hw_params, 1103 1039 .set_fmt = sti_uniperiph_dai_set_fmt, 1104 - .set_sysclk = uni_player_set_sysclk 1040 + .set_sysclk = uni_player_set_sysclk, 1041 + .set_tdm_slot = sti_uniperiph_set_tdm_slot 1105 1042 }; 1106 1043 1107 1044 int uni_player_init(struct platform_device *pdev, ··· 1112 1047 1113 1048 player->dev = &pdev->dev; 1114 1049 player->state = UNIPERIF_STATE_STOPPED; 1115 - player->hw = &uni_player_pcm_hw; 1116 1050 player->dai_ops = &uni_player_dai_ops; 1117 1051 1118 1052 ret = uni_player_parse_dt(pdev, player); ··· 1120 1056 dev_err(player->dev, "Failed to parse DeviceTree"); 1121 1057 return ret; 1122 1058 } 1059 + 1060 + if (UNIPERIF_TYPE_IS_TDM(player)) 1061 + player->hw = &uni_tdm_hw; 1062 + else 1063 + player->hw = &uni_player_pcm_hw; 1123 1064 1124 1065 /* Get uniperif resource */ 1125 1066 player->clk = of_clk_get(pdev->dev.of_node, 0); ··· 1138 1069 dev_err(player->dev, 1139 1070 "%s: Failed to select freq synth clock", 1140 1071 __func__); 1072 + return ret; 1073 + } 1074 + } 1075 + 1076 + /* connect to I2S/TDM TX bus */ 1077 + if (player->valid_sel && 1078 + (player->info->id == UNIPERIF_PLAYER_I2S_OUT)) { 1079 + ret = regmap_field_write(player->valid_sel, player->info->id); 1080 + if (ret) { 1081 + dev_err(player->dev, 1082 + "%s: unable to connect to tdm bus", __func__); 1141 1083 return ret; 1142 1084 } 1143 1085 } ··· 1167 1087 SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player); 1168 1088 SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(player); 1169 1089 1170 - if (UNIPERIF_PLAYER_TYPE_IS_IEC958(player)) { 1090 + if (UNIPERIF_TYPE_IS_IEC958(player)) { 1171 1091 /* Set default iec958 status bits */ 1172 1092 1173 1093 /* Consumer, PCM, copyright, 2ch, mode 0 */
+168 -61
sound/soc/sti/uniperif_reader.c
··· 73 73 return ret; 74 74 } 75 75 76 - static int uni_reader_prepare(struct snd_pcm_substream *substream, 77 - struct snd_soc_dai *dai) 76 + static int uni_reader_prepare_pcm(struct snd_pcm_runtime *runtime, 77 + struct uniperif *reader) 78 78 { 79 - struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 80 - struct uniperif *reader = priv->dai_data.uni; 81 - struct snd_pcm_runtime *runtime = substream->runtime; 82 - int transfer_size, trigger_limit; 83 79 int slot_width; 84 - int count = 10; 85 - 86 - /* The reader should be stopped */ 87 - if (reader->state != UNIPERIF_STATE_STOPPED) { 88 - dev_err(reader->dev, "%s: invalid reader state %d", __func__, 89 - reader->state); 90 - return -EINVAL; 91 - } 92 - 93 - /* Calculate transfer size (in fifo cells and bytes) for frame count */ 94 - transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; 95 - 96 - /* Calculate number of empty cells available before asserting DREQ */ 97 - if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) 98 - trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size; 99 - else 100 - /* 101 - * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 102 - * FDMA_TRIGGER_LIMIT also controls when the state switches 103 - * from OFF or STANDBY to AUDIO DATA. 104 - */ 105 - trigger_limit = transfer_size; 106 - 107 - /* Trigger limit must be an even number */ 108 - if ((!trigger_limit % 2) || 109 - (trigger_limit != 1 && transfer_size % 2) || 110 - (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) { 111 - dev_err(reader->dev, "invalid trigger limit %d", trigger_limit); 112 - return -EINVAL; 113 - } 114 - 115 - SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit); 116 - 117 - switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) { 118 - case SND_SOC_DAIFMT_IB_IF: 119 - case SND_SOC_DAIFMT_NB_IF: 120 - SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader); 121 - break; 122 - default: 123 - SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader); 124 - } 125 80 126 81 /* Force slot width to 32 in I2S mode */ 127 82 if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) ··· 128 173 return -EINVAL; 129 174 } 130 175 176 + /* Number of channels must be even */ 177 + if ((runtime->channels % 2) || (runtime->channels < 2) || 178 + (runtime->channels > 10)) { 179 + dev_err(reader->dev, "%s: invalid nb of channels", __func__); 180 + return -EINVAL; 181 + } 182 + 183 + SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2); 184 + SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); 185 + 186 + return 0; 187 + } 188 + 189 + static int uni_reader_prepare_tdm(struct snd_pcm_runtime *runtime, 190 + struct uniperif *reader) 191 + { 192 + int frame_size; /* user tdm frame size in bytes */ 193 + /* default unip TDM_WORD_POS_X_Y */ 194 + unsigned int word_pos[4] = { 195 + 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A}; 196 + 197 + frame_size = sti_uniperiph_get_user_frame_size(runtime); 198 + 199 + /* fix 16/0 format */ 200 + SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader); 201 + SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader); 202 + 203 + /* number of words inserted on the TDM line */ 204 + SET_UNIPERIF_I2S_FMT_NUM_CH(reader, frame_size / 4 / 2); 205 + 206 + SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); 207 + SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); 208 + SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(reader); 209 + 210 + /* 211 + * set the timeslots allocation for words in FIFO 212 + * 213 + * HW bug: (LSB word < MSB word) => this config is not possible 214 + * So if we want (LSB word < MSB) word, then it shall be 215 + * handled by user 216 + */ 217 + sti_uniperiph_get_tdm_word_pos(reader, word_pos); 218 + SET_UNIPERIF_TDM_WORD_POS(reader, 1_2, word_pos[WORD_1_2]); 219 + SET_UNIPERIF_TDM_WORD_POS(reader, 3_4, word_pos[WORD_3_4]); 220 + SET_UNIPERIF_TDM_WORD_POS(reader, 5_6, word_pos[WORD_5_6]); 221 + SET_UNIPERIF_TDM_WORD_POS(reader, 7_8, word_pos[WORD_7_8]); 222 + 223 + return 0; 224 + } 225 + 226 + static int uni_reader_prepare(struct snd_pcm_substream *substream, 227 + struct snd_soc_dai *dai) 228 + { 229 + struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 230 + struct uniperif *reader = priv->dai_data.uni; 231 + struct snd_pcm_runtime *runtime = substream->runtime; 232 + int transfer_size, trigger_limit, ret; 233 + int count = 10; 234 + 235 + /* The reader should be stopped */ 236 + if (reader->state != UNIPERIF_STATE_STOPPED) { 237 + dev_err(reader->dev, "%s: invalid reader state %d", __func__, 238 + reader->state); 239 + return -EINVAL; 240 + } 241 + 242 + /* Calculate transfer size (in fifo cells and bytes) for frame count */ 243 + if (reader->info->type == SND_ST_UNIPERIF_TYPE_TDM) { 244 + /* transfer size = unip frame size (in 32 bits FIFO cell) */ 245 + transfer_size = 246 + sti_uniperiph_get_user_frame_size(runtime) / 4; 247 + } else { 248 + transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; 249 + } 250 + 251 + /* Calculate number of empty cells available before asserting DREQ */ 252 + if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) 253 + trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size; 254 + else 255 + /* 256 + * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 257 + * FDMA_TRIGGER_LIMIT also controls when the state switches 258 + * from OFF or STANDBY to AUDIO DATA. 259 + */ 260 + trigger_limit = transfer_size; 261 + 262 + /* Trigger limit must be an even number */ 263 + if ((!trigger_limit % 2) || 264 + (trigger_limit != 1 && transfer_size % 2) || 265 + (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) { 266 + dev_err(reader->dev, "invalid trigger limit %d", trigger_limit); 267 + return -EINVAL; 268 + } 269 + 270 + SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit); 271 + 272 + if (UNIPERIF_TYPE_IS_TDM(reader)) 273 + ret = uni_reader_prepare_tdm(runtime, reader); 274 + else 275 + ret = uni_reader_prepare_pcm(runtime, reader); 276 + if (ret) 277 + return ret; 278 + 131 279 switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { 132 280 case SND_SOC_DAIFMT_I2S: 133 281 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); ··· 249 191 return -EINVAL; 250 192 } 251 193 252 - SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); 253 - 254 - /* Data clocking (changing) on the rising edge */ 255 - SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); 256 - 257 - /* Number of channels must be even */ 258 - 259 - if ((runtime->channels % 2) || (runtime->channels < 2) || 260 - (runtime->channels > 10)) { 261 - dev_err(reader->dev, "%s: invalid nb of channels", __func__); 262 - return -EINVAL; 194 + /* Data clocking (changing) on the rising/falling edge */ 195 + switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) { 196 + case SND_SOC_DAIFMT_NB_NF: 197 + SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader); 198 + SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); 199 + break; 200 + case SND_SOC_DAIFMT_NB_IF: 201 + SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader); 202 + SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); 203 + break; 204 + case SND_SOC_DAIFMT_IB_NF: 205 + SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader); 206 + SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader); 207 + break; 208 + case SND_SOC_DAIFMT_IB_IF: 209 + SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader); 210 + SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader); 211 + break; 263 212 } 264 - 265 - SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2); 266 213 267 214 /* Clear any pending interrupts */ 268 215 SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader)); ··· 356 293 } 357 294 } 358 295 296 + static int uni_reader_startup(struct snd_pcm_substream *substream, 297 + struct snd_soc_dai *dai) 298 + { 299 + struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 300 + struct uniperif *reader = priv->dai_data.uni; 301 + int ret; 302 + 303 + if (!UNIPERIF_TYPE_IS_TDM(reader)) 304 + return 0; 305 + 306 + /* refine hw constraint in tdm mode */ 307 + ret = snd_pcm_hw_rule_add(substream->runtime, 0, 308 + SNDRV_PCM_HW_PARAM_CHANNELS, 309 + sti_uniperiph_fix_tdm_chan, 310 + reader, SNDRV_PCM_HW_PARAM_CHANNELS, 311 + -1); 312 + if (ret < 0) 313 + return ret; 314 + 315 + return snd_pcm_hw_rule_add(substream->runtime, 0, 316 + SNDRV_PCM_HW_PARAM_FORMAT, 317 + sti_uniperiph_fix_tdm_format, 318 + reader, SNDRV_PCM_HW_PARAM_FORMAT, 319 + -1); 320 + } 321 + 359 322 static void uni_reader_shutdown(struct snd_pcm_substream *substream, 360 323 struct snd_soc_dai *dai) 361 324 { ··· 399 310 { 400 311 struct uniperif_info *info; 401 312 struct device_node *node = pdev->dev.of_node; 313 + const char *mode; 402 314 403 315 /* Allocate memory for the info structure */ 404 316 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); ··· 412 322 return -EINVAL; 413 323 } 414 324 325 + /* Read the device mode property */ 326 + if (of_property_read_string(node, "st,mode", &mode)) { 327 + dev_err(&pdev->dev, "uniperipheral mode not defined"); 328 + return -EINVAL; 329 + } 330 + 331 + if (strcasecmp(mode, "tdm") == 0) 332 + info->type = SND_ST_UNIPERIF_TYPE_TDM; 333 + else 334 + info->type = SND_ST_UNIPERIF_TYPE_PCM; 335 + 415 336 /* Save the info structure */ 416 337 reader->info = info; 417 338 ··· 430 329 } 431 330 432 331 static const struct snd_soc_dai_ops uni_reader_dai_ops = { 332 + .startup = uni_reader_startup, 433 333 .shutdown = uni_reader_shutdown, 434 334 .prepare = uni_reader_prepare, 435 335 .trigger = uni_reader_trigger, 436 336 .hw_params = sti_uniperiph_dai_hw_params, 437 337 .set_fmt = sti_uniperiph_dai_set_fmt, 338 + .set_tdm_slot = sti_uniperiph_set_tdm_slot 438 339 }; 439 340 440 341 int uni_reader_init(struct platform_device *pdev, ··· 446 343 447 344 reader->dev = &pdev->dev; 448 345 reader->state = UNIPERIF_STATE_STOPPED; 449 - reader->hw = &uni_reader_pcm_hw; 450 346 reader->dai_ops = &uni_reader_dai_ops; 451 347 452 348 ret = uni_reader_parse_dt(pdev, reader); ··· 453 351 dev_err(reader->dev, "Failed to parse DeviceTree"); 454 352 return ret; 455 353 } 354 + 355 + if (UNIPERIF_TYPE_IS_TDM(reader)) 356 + reader->hw = &uni_tdm_hw; 357 + else 358 + reader->hw = &uni_reader_pcm_hw; 456 359 457 360 ret = devm_request_irq(&pdev->dev, reader->irq, 458 361 uni_reader_irq_handler, IRQF_SHARED,