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

Merge remote-tracking branches 'asoc/topic/sta350', 'asoc/topic/tas2552', 'asoc/topic/tas3a227e' and 'asoc/topic/tas571x' into asoc-next

+916 -122
+41
Documentation/devicetree/bindings/sound/tas571x.txt
··· 1 + Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers 2 + 3 + The codec is controlled through an I2C interface. It also has two other 4 + signals that can be wired up to GPIOs: reset (strongly recommended), and 5 + powerdown (optional). 6 + 7 + Required properties: 8 + 9 + - compatible: "ti,tas5711", "ti,tas5717", or "ti,tas5719" 10 + - reg: The I2C address of the device 11 + - #sound-dai-cells: must be equal to 0 12 + 13 + Optional properties: 14 + 15 + - reset-gpios: GPIO specifier for the TAS571x's active low reset line 16 + - pdn-gpios: GPIO specifier for the TAS571x's active low powerdown line 17 + - clocks: clock phandle for the MCLK input 18 + - clock-names: should be "mclk" 19 + - AVDD-supply: regulator phandle for the AVDD supply (all chips) 20 + - DVDD-supply: regulator phandle for the DVDD supply (all chips) 21 + - HPVDD-supply: regulator phandle for the HPVDD supply (5717/5719) 22 + - PVDD_AB-supply: regulator phandle for the PVDD_AB supply (5717/5719) 23 + - PVDD_CD-supply: regulator phandle for the PVDD_CD supply (5717/5719) 24 + - PVDD_A-supply: regulator phandle for the PVDD_A supply (5711) 25 + - PVDD_B-supply: regulator phandle for the PVDD_B supply (5711) 26 + - PVDD_C-supply: regulator phandle for the PVDD_C supply (5711) 27 + - PVDD_D-supply: regulator phandle for the PVDD_D supply (5711) 28 + 29 + Example: 30 + 31 + tas5717: audio-codec@2a { 32 + compatible = "ti,tas5717"; 33 + reg = <0x2a>; 34 + #sound-dai-cells = <0>; 35 + 36 + reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>; 37 + pdn-gpios = <&gpio5 2 GPIO_ACTIVE_LOW>; 38 + 39 + clocks = <&clk_core CLK_I2S>; 40 + clock-names = "mclk"; 41 + };
+6
MAINTAINERS
··· 9922 9922 S: Maintained 9923 9923 F: drivers/net/ethernet/ti/netcp* 9924 9924 9925 + TI TAS571X FAMILY ASoC CODEC DRIVER 9926 + M: Kevin Cernekee <cernekee@chromium.org> 9927 + L: alsa-devel@alsa-project.org (moderated for non-subscribers) 9928 + S: Odd Fixes 9929 + F: sound/soc/codecs/tas571x* 9930 + 9925 9931 TI TWL4030 SERIES SOC CODEC DRIVER 9926 9932 M: Peter Ujfalusi <peter.ujfalusi@ti.com> 9927 9933 L: alsa-devel@alsa-project.org (moderated for non-subscribers)
+18
include/dt-bindings/sound/tas2552.h
··· 1 + #ifndef __DT_TAS2552_H 2 + #define __DT_TAS2552_H 3 + 4 + #define TAS2552_PLL_CLKIN (0) 5 + #define TAS2552_PDM_CLK (1) 6 + #define TAS2552_CLK_TARGET_MASK (1) 7 + 8 + #define TAS2552_PLL_CLKIN_MCLK ((0 << 1) | TAS2552_PLL_CLKIN) 9 + #define TAS2552_PLL_CLKIN_BCLK ((1 << 1) | TAS2552_PLL_CLKIN) 10 + #define TAS2552_PLL_CLKIN_IVCLKIN ((2 << 1) | TAS2552_PLL_CLKIN) 11 + #define TAS2552_PLL_CLKIN_1_8_FIXED ((3 << 1) | TAS2552_PLL_CLKIN) 12 + 13 + #define TAS2552_PDM_CLK_PLL ((0 << 1) | TAS2552_PDM_CLK) 14 + #define TAS2552_PDM_CLK_IVCLKIN ((1 << 1) | TAS2552_PDM_CLK) 15 + #define TAS2552_PDM_CLK_BCLK ((2 << 1) | TAS2552_PDM_CLK) 16 + #define TAS2552_PDM_CLK_MCLK ((3 << 1) | TAS2552_PDM_CLK) 17 + 18 + #endif /* __DT_TAS2552_H */
+5
sound/soc/codecs/Kconfig
··· 104 104 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS 105 105 select SND_SOC_TAS2552 if I2C 106 106 select SND_SOC_TAS5086 if I2C 107 + select SND_SOC_TAS571X if I2C 107 108 select SND_SOC_TFA9879 if I2C 108 109 select SND_SOC_TLV320AIC23_I2C if I2C 109 110 select SND_SOC_TLV320AIC23_SPI if SPI_MASTER ··· 611 610 612 611 config SND_SOC_TAS5086 613 612 tristate "Texas Instruments TAS5086 speaker amplifier" 613 + depends on I2C 614 + 615 + config SND_SOC_TAS571X 616 + tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers" 614 617 depends on I2C 615 618 616 619 config SND_SOC_TFA9879
+2
sound/soc/codecs/Makefile
··· 106 106 snd-soc-sta529-objs := sta529.o 107 107 snd-soc-stac9766-objs := stac9766.o 108 108 snd-soc-tas5086-objs := tas5086.o 109 + snd-soc-tas571x-objs := tas571x.o 109 110 snd-soc-tfa9879-objs := tfa9879.o 110 111 snd-soc-tlv320aic23-objs := tlv320aic23.o 111 112 snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o ··· 289 288 obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o 290 289 obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o 291 290 obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o 291 + obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o 292 292 obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o 293 293 obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 294 294 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
+2 -2
sound/soc/codecs/sta350.c
··· 1217 1217 if (IS_ERR(sta350->gpiod_nreset)) 1218 1218 return PTR_ERR(sta350->gpiod_nreset); 1219 1219 1220 - sta350->gpiod_power_down = devm_gpiod_get(dev, "power-down", 1221 - GPIOD_OUT_LOW); 1220 + sta350->gpiod_power_down = devm_gpiod_get_optional(dev, "power-down", 1221 + GPIOD_OUT_LOW); 1222 1222 if (IS_ERR(sta350->gpiod_power_down)) 1223 1223 return PTR_ERR(sta350->gpiod_power_down); 1224 1224
+239 -73
sound/soc/codecs/tas2552.c
··· 34 34 #include <sound/soc-dapm.h> 35 35 #include <sound/tlv.h> 36 36 #include <sound/tas2552-plat.h> 37 + #include <dt-bindings/sound/tas2552.h> 37 38 38 39 #include "tas2552.h" 39 40 ··· 46 45 {TAS2552_PDM_CFG, 0x01}, 47 46 {TAS2552_PGA_GAIN, 0x00}, 48 47 {TAS2552_BOOST_PT_CTRL, 0x0f}, 49 - {TAS2552_RESERVED_0D, 0x00}, 48 + {TAS2552_RESERVED_0D, 0xbe}, 50 49 {TAS2552_LIMIT_RATE_HYS, 0x08}, 51 50 {TAS2552_CFG_2, 0xef}, 52 51 {TAS2552_SER_CTRL_1, 0x00}, ··· 76 75 struct regulator_bulk_data supplies[TAS2552_NUM_SUPPLIES]; 77 76 struct gpio_desc *enable_gpio; 78 77 unsigned char regs[TAS2552_VBAT_DATA]; 79 - unsigned int mclk; 78 + unsigned int pll_clkin; 79 + unsigned int pdm_clk; 80 + 81 + unsigned int dai_fmt; 82 + unsigned int tdm_delay; 80 83 }; 84 + 85 + static int tas2552_post_event(struct snd_soc_dapm_widget *w, 86 + struct snd_kcontrol *kcontrol, int event) 87 + { 88 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 89 + 90 + switch (event) { 91 + case SND_SOC_DAPM_POST_PMU: 92 + snd_soc_write(codec, TAS2552_RESERVED_0D, 0xc0); 93 + snd_soc_update_bits(codec, TAS2552_LIMIT_RATE_HYS, (1 << 5), 94 + (1 << 5)); 95 + snd_soc_update_bits(codec, TAS2552_CFG_2, 1, 0); 96 + snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_SWS, 0); 97 + break; 98 + case SND_SOC_DAPM_POST_PMD: 99 + snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_SWS, 100 + TAS2552_SWS); 101 + snd_soc_update_bits(codec, TAS2552_CFG_2, 1, 1); 102 + snd_soc_update_bits(codec, TAS2552_LIMIT_RATE_HYS, (1 << 5), 0); 103 + snd_soc_write(codec, TAS2552_RESERVED_0D, 0xbe); 104 + break; 105 + } 106 + return 0; 107 + } 81 108 82 109 /* Input mux controls */ 83 - static const char *tas2552_input_texts[] = { 84 - "Digital", "Analog" 85 - }; 86 - 110 + static const char * const tas2552_input_texts[] = { 111 + "Digital", "Analog" }; 87 112 static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum, TAS2552_CFG_3, 7, 88 113 tas2552_input_texts); 89 114 90 - static const struct snd_kcontrol_new tas2552_input_mux_control[] = { 91 - SOC_DAPM_ENUM("Input selection", tas2552_input_mux_enum) 92 - }; 115 + static const struct snd_kcontrol_new tas2552_input_mux_control = 116 + SOC_DAPM_ENUM("Route", tas2552_input_mux_enum); 93 117 94 118 static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] = 95 119 { ··· 122 96 123 97 /* MUX Controls */ 124 98 SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM, 0, 0, 125 - tas2552_input_mux_control), 99 + &tas2552_input_mux_control), 126 100 127 101 SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), 128 102 SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), 129 103 SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0), 130 104 SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0), 105 + SND_SOC_DAPM_POST("Post Event", tas2552_post_event), 131 106 132 107 SND_SOC_DAPM_OUTPUT("OUT") 133 108 }; ··· 145 118 #ifdef CONFIG_PM 146 119 static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown) 147 120 { 148 - u8 cfg1_reg; 121 + u8 cfg1_reg = 0; 122 + 123 + if (!tas_data->codec) 124 + return; 149 125 150 126 if (sw_shutdown) 151 - cfg1_reg = 0; 152 - else 153 - cfg1_reg = TAS2552_SWS_MASK; 127 + cfg1_reg = TAS2552_SWS; 154 128 155 - snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1, 156 - TAS2552_SWS_MASK, cfg1_reg); 129 + snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1, TAS2552_SWS, 130 + cfg1_reg); 157 131 } 158 132 #endif 159 133 ··· 166 138 struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); 167 139 int sample_rate, pll_clk; 168 140 int d; 141 + int cpf; 169 142 u8 p, j; 143 + u8 ser_ctrl1_reg, wclk_rate; 170 144 171 - if (!tas2552->mclk) 145 + switch (params_width(params)) { 146 + case 16: 147 + ser_ctrl1_reg = TAS2552_WORDLENGTH_16BIT; 148 + cpf = 32 + tas2552->tdm_delay; 149 + break; 150 + case 20: 151 + ser_ctrl1_reg = TAS2552_WORDLENGTH_20BIT; 152 + cpf = 64 + tas2552->tdm_delay; 153 + break; 154 + case 24: 155 + ser_ctrl1_reg = TAS2552_WORDLENGTH_24BIT; 156 + cpf = 64 + tas2552->tdm_delay; 157 + break; 158 + case 32: 159 + ser_ctrl1_reg = TAS2552_WORDLENGTH_32BIT; 160 + cpf = 64 + tas2552->tdm_delay; 161 + break; 162 + default: 163 + dev_err(codec->dev, "Not supported sample size: %d\n", 164 + params_width(params)); 165 + return -EINVAL; 166 + } 167 + 168 + if (cpf <= 32) 169 + ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_32; 170 + else if (cpf <= 64) 171 + ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_64; 172 + else if (cpf <= 128) 173 + ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_128; 174 + else 175 + ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_256; 176 + 177 + snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, 178 + TAS2552_WORDLENGTH_MASK | TAS2552_CLKSPERFRAME_MASK, 179 + ser_ctrl1_reg); 180 + 181 + switch (params_rate(params)) { 182 + case 8000: 183 + wclk_rate = TAS2552_WCLK_FREQ_8KHZ; 184 + break; 185 + case 11025: 186 + case 12000: 187 + wclk_rate = TAS2552_WCLK_FREQ_11_12KHZ; 188 + break; 189 + case 16000: 190 + wclk_rate = TAS2552_WCLK_FREQ_16KHZ; 191 + break; 192 + case 22050: 193 + case 24000: 194 + wclk_rate = TAS2552_WCLK_FREQ_22_24KHZ; 195 + break; 196 + case 32000: 197 + wclk_rate = TAS2552_WCLK_FREQ_32KHZ; 198 + break; 199 + case 44100: 200 + case 48000: 201 + wclk_rate = TAS2552_WCLK_FREQ_44_48KHZ; 202 + break; 203 + case 88200: 204 + case 96000: 205 + wclk_rate = TAS2552_WCLK_FREQ_88_96KHZ; 206 + break; 207 + case 176400: 208 + case 192000: 209 + wclk_rate = TAS2552_WCLK_FREQ_176_192KHZ; 210 + break; 211 + default: 212 + dev_err(codec->dev, "Not supported sample rate: %d\n", 213 + params_rate(params)); 214 + return -EINVAL; 215 + } 216 + 217 + snd_soc_update_bits(codec, TAS2552_CFG_3, TAS2552_WCLK_FREQ_MASK, 218 + wclk_rate); 219 + 220 + if (!tas2552->pll_clkin) 172 221 return -EINVAL; 173 222 174 223 snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0); 175 224 176 - if (tas2552->mclk == TAS2552_245MHZ_CLK || 177 - tas2552->mclk == TAS2552_225MHZ_CLK) { 225 + if (tas2552->pll_clkin == TAS2552_245MHZ_CLK || 226 + tas2552->pll_clkin == TAS2552_225MHZ_CLK) { 178 227 /* By pass the PLL configuration */ 179 228 snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2, 180 229 TAS2552_PLL_BYPASS_MASK, ··· 275 170 return -EINVAL; 276 171 } 277 172 278 - j = (pll_clk * 2 * (1 << p)) / tas2552->mclk; 279 - d = (pll_clk * 2 * (1 << p)) % tas2552->mclk; 173 + j = (pll_clk * 2 * (1 << p)) / tas2552->pll_clkin; 174 + d = (pll_clk * 2 * (1 << p)) % tas2552->pll_clkin; 280 175 281 176 snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1, 282 177 TAS2552_PLL_J_MASK, j); ··· 290 185 return 0; 291 186 } 292 187 188 + #define TAS2552_DAI_FMT_MASK (TAS2552_BCLKDIR | \ 189 + TAS2552_WCLKDIR | \ 190 + TAS2552_DATAFORMAT_MASK) 191 + static int tas2552_prepare(struct snd_pcm_substream *substream, 192 + struct snd_soc_dai *dai) 193 + { 194 + struct snd_soc_codec *codec = dai->codec; 195 + struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); 196 + int delay = 0; 197 + 198 + /* TDM slot selection only valid in DSP_A/_B mode */ 199 + if (tas2552->dai_fmt == SND_SOC_DAIFMT_DSP_A) 200 + delay += (tas2552->tdm_delay + 1); 201 + else if (tas2552->dai_fmt == SND_SOC_DAIFMT_DSP_B) 202 + delay += tas2552->tdm_delay; 203 + 204 + /* Configure data delay */ 205 + snd_soc_write(codec, TAS2552_SER_CTRL_2, delay); 206 + 207 + return 0; 208 + } 209 + 293 210 static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 294 211 { 295 212 struct snd_soc_codec *codec = dai->codec; 213 + struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); 296 214 u8 serial_format; 297 - u8 serial_control_mask; 298 215 299 216 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 300 217 case SND_SOC_DAIFMT_CBS_CFS: 301 218 serial_format = 0x00; 302 219 break; 303 220 case SND_SOC_DAIFMT_CBS_CFM: 304 - serial_format = TAS2552_WORD_CLK_MASK; 221 + serial_format = TAS2552_WCLKDIR; 305 222 break; 306 223 case SND_SOC_DAIFMT_CBM_CFS: 307 - serial_format = TAS2552_BIT_CLK_MASK; 224 + serial_format = TAS2552_BCLKDIR; 308 225 break; 309 226 case SND_SOC_DAIFMT_CBM_CFM: 310 - serial_format = (TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK); 227 + serial_format = (TAS2552_BCLKDIR | TAS2552_WCLKDIR); 311 228 break; 312 229 default: 313 230 dev_vdbg(codec->dev, "DAI Format master is not found\n"); 314 231 return -EINVAL; 315 232 } 316 233 317 - serial_control_mask = TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK; 318 - 319 - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 320 - case SND_SOC_DAIFMT_I2S: 321 - serial_format &= TAS2552_DAIFMT_I2S_MASK; 234 + switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | 235 + SND_SOC_DAIFMT_INV_MASK)) { 236 + case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): 322 237 break; 323 - case SND_SOC_DAIFMT_DSP_A: 324 - serial_format |= TAS2552_DAIFMT_DSP; 238 + case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF): 239 + case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF): 240 + serial_format |= TAS2552_DATAFORMAT_DSP; 325 241 break; 326 - case SND_SOC_DAIFMT_RIGHT_J: 327 - serial_format |= TAS2552_DAIFMT_RIGHT_J; 242 + case (SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_NB_NF): 243 + serial_format |= TAS2552_DATAFORMAT_RIGHT_J; 328 244 break; 329 - case SND_SOC_DAIFMT_LEFT_J: 330 - serial_format |= TAS2552_DAIFMT_LEFT_J; 245 + case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF): 246 + serial_format |= TAS2552_DATAFORMAT_LEFT_J; 331 247 break; 332 248 default: 333 249 dev_vdbg(codec->dev, "DAI Format is not found\n"); 334 250 return -EINVAL; 335 251 } 252 + tas2552->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 336 253 337 - if (fmt & SND_SOC_DAIFMT_FORMAT_MASK) 338 - serial_control_mask |= TAS2552_DATA_FORMAT_MASK; 339 - 340 - snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, serial_control_mask, 341 - serial_format); 342 - 254 + snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, TAS2552_DAI_FMT_MASK, 255 + serial_format); 343 256 return 0; 344 257 } 345 258 ··· 366 243 { 367 244 struct snd_soc_codec *codec = dai->codec; 368 245 struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); 246 + u8 reg, mask, val; 369 247 370 - tas2552->mclk = freq; 248 + switch (clk_id) { 249 + case TAS2552_PLL_CLKIN_MCLK: 250 + case TAS2552_PLL_CLKIN_BCLK: 251 + case TAS2552_PLL_CLKIN_IVCLKIN: 252 + case TAS2552_PLL_CLKIN_1_8_FIXED: 253 + mask = TAS2552_PLL_SRC_MASK; 254 + val = (clk_id << 3) & mask; /* bit 4:5 in the register */ 255 + reg = TAS2552_CFG_1; 256 + tas2552->pll_clkin = freq; 257 + break; 258 + case TAS2552_PDM_CLK_PLL: 259 + case TAS2552_PDM_CLK_IVCLKIN: 260 + case TAS2552_PDM_CLK_BCLK: 261 + case TAS2552_PDM_CLK_MCLK: 262 + mask = TAS2552_PDM_CLK_SEL_MASK; 263 + val = (clk_id >> 1) & mask; /* bit 0:1 in the register */ 264 + reg = TAS2552_PDM_CFG; 265 + tas2552->pdm_clk = freq; 266 + break; 267 + default: 268 + dev_err(codec->dev, "Invalid clk id: %d\n", clk_id); 269 + return -EINVAL; 270 + } 271 + 272 + snd_soc_update_bits(codec, reg, mask, val); 273 + 274 + return 0; 275 + } 276 + 277 + static int tas2552_set_dai_tdm_slot(struct snd_soc_dai *dai, 278 + unsigned int tx_mask, unsigned int rx_mask, 279 + int slots, int slot_width) 280 + { 281 + struct snd_soc_codec *codec = dai->codec; 282 + struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); 283 + unsigned int lsb; 284 + 285 + if (unlikely(!tx_mask)) { 286 + dev_err(codec->dev, "tx masks need to be non 0\n"); 287 + return -EINVAL; 288 + } 289 + 290 + /* TDM based on DSP mode requires slots to be adjacent */ 291 + lsb = __ffs(tx_mask); 292 + if ((lsb + 1) != __fls(tx_mask)) { 293 + dev_err(codec->dev, "Invalid mask, slots must be adjacent\n"); 294 + return -EINVAL; 295 + } 296 + 297 + tas2552->tdm_delay = lsb * slot_width; 298 + 299 + /* DOUT in high-impedance on inactive bit clocks */ 300 + snd_soc_update_bits(codec, TAS2552_DOUT, 301 + TAS2552_SDOUT_TRISTATE, TAS2552_SDOUT_TRISTATE); 371 302 372 303 return 0; 373 304 } 374 305 375 306 static int tas2552_mute(struct snd_soc_dai *dai, int mute) 376 307 { 377 - u8 cfg1_reg; 308 + u8 cfg1_reg = 0; 378 309 struct snd_soc_codec *codec = dai->codec; 379 310 380 311 if (mute) 381 - cfg1_reg = TAS2552_MUTE_MASK; 382 - else 383 - cfg1_reg = ~TAS2552_MUTE_MASK; 312 + cfg1_reg |= TAS2552_MUTE; 384 313 385 - snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK, cfg1_reg); 314 + snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE, cfg1_reg); 386 315 387 316 return 0; 388 317 } ··· 444 269 { 445 270 struct tas2552_data *tas2552 = dev_get_drvdata(dev); 446 271 447 - tas2552_sw_shutdown(tas2552, 0); 272 + tas2552_sw_shutdown(tas2552, 1); 448 273 449 274 regcache_cache_only(tas2552->regmap, true); 450 275 regcache_mark_dirty(tas2552->regmap); ··· 462 287 if (tas2552->enable_gpio) 463 288 gpiod_set_value(tas2552->enable_gpio, 1); 464 289 465 - tas2552_sw_shutdown(tas2552, 1); 290 + tas2552_sw_shutdown(tas2552, 0); 466 291 467 292 regcache_cache_only(tas2552->regmap, false); 468 293 regcache_sync(tas2552->regmap); ··· 478 303 479 304 static struct snd_soc_dai_ops tas2552_speaker_dai_ops = { 480 305 .hw_params = tas2552_hw_params, 306 + .prepare = tas2552_prepare, 481 307 .set_sysclk = tas2552_set_dai_sysclk, 482 308 .set_fmt = tas2552_set_dai_fmt, 309 + .set_tdm_slot = tas2552_set_dai_tdm_slot, 483 310 .digital_mute = tas2552_mute, 484 311 }; 485 312 ··· 507 330 /* 508 331 * DAC digital volumes. From -7 to 24 dB in 1 dB steps 509 332 */ 510 - static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24); 333 + static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 0); 511 334 512 335 static const struct snd_kcontrol_new tas2552_snd_controls[] = { 513 336 SOC_SINGLE_TLV("Speaker Driver Playback Volume", 514 - TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv), 515 - SOC_DAPM_SINGLE("Playback AMP", SND_SOC_NOPM, 0, 1, 0), 516 - }; 517 - 518 - static const struct reg_default tas2552_init_regs[] = { 519 - { TAS2552_RESERVED_0D, 0xc0 }, 337 + TAS2552_PGA_GAIN, 0, 0x1f, 0, dac_tlv), 520 338 }; 521 339 522 340 static int tas2552_codec_probe(struct snd_soc_codec *codec) ··· 540 368 goto probe_fail; 541 369 } 542 370 543 - snd_soc_write(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK | 544 - TAS2552_PLL_SRC_BCLK); 371 + snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE, TAS2552_MUTE); 545 372 snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL | 546 - TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ); 373 + TAS2552_DIN_SRC_SEL_AVG_L_R); 547 374 snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I); 548 375 snd_soc_write(codec, TAS2552_OUTPUT_DATA, TAS2552_PDM_DATA_V_I | 0x8); 549 - snd_soc_write(codec, TAS2552_PDM_CFG, TAS2552_PDM_BCLK_SEL); 550 376 snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 | 551 377 TAS2552_APT_THRESH_2_1_7); 552 - 553 - ret = regmap_register_patch(tas2552->regmap, tas2552_init_regs, 554 - ARRAY_SIZE(tas2552_init_regs)); 555 - if (ret != 0) { 556 - dev_err(codec->dev, "Failed to write init registers: %d\n", 557 - ret); 558 - goto patch_fail; 559 - } 560 378 561 379 snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN | 562 380 TAS2552_APT_EN | TAS2552_LIM_EN); 563 381 564 382 return 0; 565 383 566 - patch_fail: 567 - pm_runtime_put(codec->dev); 568 384 probe_fail: 569 385 if (tas2552->enable_gpio) 570 386 gpiod_set_value(tas2552->enable_gpio, 0); ··· 614 454 .remove = tas2552_codec_remove, 615 455 .suspend = tas2552_suspend, 616 456 .resume = tas2552_resume, 457 + .ignore_pmdown_time = true, 458 + 617 459 .controls = tas2552_snd_controls, 618 460 .num_controls = ARRAY_SIZE(tas2552_snd_controls), 619 461 .dapm_widgets = tas2552_dapm_widgets, ··· 648 486 return -ENOMEM; 649 487 650 488 data->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); 651 - if (IS_ERR(data->enable_gpio)) 652 - return PTR_ERR(data->enable_gpio); 489 + if (IS_ERR(data->enable_gpio)) { 490 + if (PTR_ERR(data->enable_gpio) == -EPROBE_DEFER) 491 + return -EPROBE_DEFER; 492 + 493 + data->enable_gpio = NULL;; 494 + } 653 495 654 496 data->tas2552_client = client; 655 497 data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config);
+49 -39
sound/soc/codecs/tas2552.h
··· 45 45 #define TAS2552_MAX_REG 0x20 46 46 47 47 /* CFG1 Register Masks */ 48 - #define TAS2552_MUTE_MASK (1 << 2) 49 - #define TAS2552_SWS_MASK (1 << 1) 50 - #define TAS2552_WCLK_MASK 0x07 51 - #define TAS2552_CLASSD_EN_MASK (1 << 7) 48 + #define TAS2552_DEV_RESET (1 << 0) 49 + #define TAS2552_SWS (1 << 1) 50 + #define TAS2552_MUTE (1 << 2) 51 + #define TAS2552_PLL_SRC_MCLK (0x0 << 4) 52 + #define TAS2552_PLL_SRC_BCLK (0x1 << 4) 53 + #define TAS2552_PLL_SRC_IVCLKIN (0x2 << 4) 54 + #define TAS2552_PLL_SRC_1_8_FIXED (0x3 << 4) 55 + #define TAS2552_PLL_SRC_MASK TAS2552_PLL_SRC_1_8_FIXED 52 56 53 57 /* CFG2 Register Masks */ 54 58 #define TAS2552_CLASSD_EN (1 << 7) ··· 63 59 #define TAS2552_IVSENSE_EN (1 << 1) 64 60 65 61 /* CFG3 Register Masks */ 66 - #define TAS2552_WORD_CLK_MASK (1 << 7) 67 - #define TAS2552_BIT_CLK_MASK (1 << 6) 68 - #define TAS2552_DATA_FORMAT_MASK (0x11 << 2) 69 - 70 - #define TAS2552_DAIFMT_I2S_MASK 0xf3 71 - #define TAS2552_DAIFMT_DSP (1 << 3) 72 - #define TAS2552_DAIFMT_RIGHT_J (1 << 4) 73 - #define TAS2552_DAIFMT_LEFT_J (0x11 << 3) 74 - 75 - #define TAS2552_PLL_SRC_MCLK 0x00 76 - #define TAS2552_PLL_SRC_BCLK (1 << 3) 77 - #define TAS2552_PLL_SRC_IVCLKIN (1 << 4) 78 - #define TAS2552_PLL_SRC_1_8_FIXED (0x11 << 3) 79 - 80 - #define TAS2552_DIN_SRC_SEL_MUTED 0x00 81 - #define TAS2552_DIN_SRC_SEL_LEFT (1 << 4) 82 - #define TAS2552_DIN_SRC_SEL_RIGHT (1 << 5) 83 - #define TAS2552_DIN_SRC_SEL_AVG_L_R (0x11 << 4) 84 - 62 + #define TAS2552_WCLK_FREQ_8KHZ (0x0 << 0) 63 + #define TAS2552_WCLK_FREQ_11_12KHZ (0x1 << 0) 64 + #define TAS2552_WCLK_FREQ_16KHZ (0x2 << 0) 65 + #define TAS2552_WCLK_FREQ_22_24KHZ (0x3 << 0) 66 + #define TAS2552_WCLK_FREQ_32KHZ (0x4 << 0) 67 + #define TAS2552_WCLK_FREQ_44_48KHZ (0x5 << 0) 68 + #define TAS2552_WCLK_FREQ_88_96KHZ (0x6 << 0) 69 + #define TAS2552_WCLK_FREQ_176_192KHZ (0x7 << 0) 70 + #define TAS2552_WCLK_FREQ_MASK TAS2552_WCLK_FREQ_176_192KHZ 71 + #define TAS2552_DIN_SRC_SEL_MUTED (0x0 << 3) 72 + #define TAS2552_DIN_SRC_SEL_LEFT (0x1 << 3) 73 + #define TAS2552_DIN_SRC_SEL_RIGHT (0x2 << 3) 74 + #define TAS2552_DIN_SRC_SEL_AVG_L_R (0x3 << 3) 85 75 #define TAS2552_PDM_IN_SEL (1 << 5) 86 76 #define TAS2552_I2S_OUT_SEL (1 << 6) 87 - #define TAS2552_ANALOG_IN_SEL (1 << 7) 77 + #define TAS2552_ANALOG_IN_SEL (1 << 7) 88 78 89 - /* CFG3 WCLK Dividers */ 90 - #define TAS2552_8KHZ 0x00 91 - #define TAS2552_11_12KHZ (1 << 1) 92 - #define TAS2552_16KHZ (1 << 2) 93 - #define TAS2552_22_24KHZ (1 << 3) 94 - #define TAS2552_32KHZ (1 << 4) 95 - #define TAS2552_44_48KHZ (1 << 5) 96 - #define TAS2552_88_96KHZ (1 << 6) 97 - #define TAS2552_176_192KHZ (1 << 7) 79 + /* DOUT Register Masks */ 80 + #define TAS2552_SDOUT_TRISTATE (1 << 2) 81 + 82 + /* Serial Interface Control Register Masks */ 83 + #define TAS2552_WORDLENGTH_16BIT (0x0 << 0) 84 + #define TAS2552_WORDLENGTH_20BIT (0x1 << 0) 85 + #define TAS2552_WORDLENGTH_24BIT (0x2 << 0) 86 + #define TAS2552_WORDLENGTH_32BIT (0x3 << 0) 87 + #define TAS2552_WORDLENGTH_MASK TAS2552_WORDLENGTH_32BIT 88 + #define TAS2552_DATAFORMAT_I2S (0x0 << 2) 89 + #define TAS2552_DATAFORMAT_DSP (0x1 << 2) 90 + #define TAS2552_DATAFORMAT_RIGHT_J (0x2 << 2) 91 + #define TAS2552_DATAFORMAT_LEFT_J (0x3 << 2) 92 + #define TAS2552_DATAFORMAT_MASK TAS2552_DATAFORMAT_LEFT_J 93 + #define TAS2552_CLKSPERFRAME_32 (0x0 << 4) 94 + #define TAS2552_CLKSPERFRAME_64 (0x1 << 4) 95 + #define TAS2552_CLKSPERFRAME_128 (0x2 << 4) 96 + #define TAS2552_CLKSPERFRAME_256 (0x3 << 4) 97 + #define TAS2552_CLKSPERFRAME_MASK TAS2552_CLKSPERFRAME_256 98 + #define TAS2552_BCLKDIR (1 << 6) 99 + #define TAS2552_WCLKDIR (1 << 7) 98 100 99 101 /* OUTPUT_DATA register */ 100 102 #define TAS2552_PDM_DATA_I 0x00 ··· 109 99 #define TAS2552_PDM_DATA_V_I (0x11 << 6) 110 100 111 101 /* PDM CFG Register */ 112 - #define TAS2552_PDM_DATA_ES_RISE 0x4 113 - 114 - #define TAS2552_PDM_PLL_CLK_SEL 0x00 115 - #define TAS2552_PDM_IV_CLK_SEL (1 << 1) 116 - #define TAS2552_PDM_BCLK_SEL (1 << 2) 117 - #define TAS2552_PDM_MCLK_SEL (1 << 3) 102 + #define TAS2552_PDM_CLK_SEL_PLL (0x0 << 0) 103 + #define TAS2552_PDM_CLK_SEL_IVCLKIN (0x1 << 0) 104 + #define TAS2552_PDM_CLK_SEL_BCLK (0x2 << 0) 105 + #define TAS2552_PDM_CLK_SEL_MCLK (0x3 << 0) 106 + #define TAS2552_PDM_CLK_SEL_MASK TAS2552_PDM_CLK_SEL_MCLK 107 + #define TAS2552_PDM_DATA_ES (1 << 2) 118 108 119 109 /* Boost pass-through register */ 120 110 #define TAS2552_APT_DELAY_50 0x00
+514
sound/soc/codecs/tas571x.c
··· 1 + /* 2 + * TAS571x amplifier audio driver 3 + * 4 + * Copyright (C) 2015 Google, Inc. 5 + * Copyright (c) 2013 Daniel Mack <zonque@gmail.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation; either version 2 of the License, or 10 + * (at your option) any later version. 11 + */ 12 + 13 + #include <linux/clk.h> 14 + #include <linux/delay.h> 15 + #include <linux/device.h> 16 + #include <linux/gpio/consumer.h> 17 + #include <linux/i2c.h> 18 + #include <linux/init.h> 19 + #include <linux/kernel.h> 20 + #include <linux/module.h> 21 + #include <linux/of_device.h> 22 + #include <linux/regmap.h> 23 + #include <linux/regulator/consumer.h> 24 + #include <linux/stddef.h> 25 + #include <sound/pcm_params.h> 26 + #include <sound/soc.h> 27 + #include <sound/tlv.h> 28 + 29 + #include "tas571x.h" 30 + 31 + #define TAS571X_MAX_SUPPLIES 6 32 + 33 + struct tas571x_chip { 34 + const char *const *supply_names; 35 + int num_supply_names; 36 + const struct snd_kcontrol_new *controls; 37 + int num_controls; 38 + const struct regmap_config *regmap_config; 39 + int vol_reg_size; 40 + }; 41 + 42 + struct tas571x_private { 43 + const struct tas571x_chip *chip; 44 + struct regmap *regmap; 45 + struct regulator_bulk_data supplies[TAS571X_MAX_SUPPLIES]; 46 + struct clk *mclk; 47 + unsigned int format; 48 + struct gpio_desc *reset_gpio; 49 + struct gpio_desc *pdn_gpio; 50 + struct snd_soc_codec_driver codec_driver; 51 + }; 52 + 53 + static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg) 54 + { 55 + switch (reg) { 56 + case TAS571X_MVOL_REG: 57 + case TAS571X_CH1_VOL_REG: 58 + case TAS571X_CH2_VOL_REG: 59 + return priv->chip->vol_reg_size; 60 + default: 61 + return 1; 62 + } 63 + } 64 + 65 + static int tas571x_reg_write(void *context, unsigned int reg, 66 + unsigned int value) 67 + { 68 + struct i2c_client *client = context; 69 + struct tas571x_private *priv = i2c_get_clientdata(client); 70 + unsigned int i, size; 71 + uint8_t buf[5]; 72 + int ret; 73 + 74 + size = tas571x_register_size(priv, reg); 75 + buf[0] = reg; 76 + 77 + for (i = size; i >= 1; --i) { 78 + buf[i] = value; 79 + value >>= 8; 80 + } 81 + 82 + ret = i2c_master_send(client, buf, size + 1); 83 + if (ret == size + 1) 84 + return 0; 85 + else if (ret < 0) 86 + return ret; 87 + else 88 + return -EIO; 89 + } 90 + 91 + static int tas571x_reg_read(void *context, unsigned int reg, 92 + unsigned int *value) 93 + { 94 + struct i2c_client *client = context; 95 + struct tas571x_private *priv = i2c_get_clientdata(client); 96 + uint8_t send_buf, recv_buf[4]; 97 + struct i2c_msg msgs[2]; 98 + unsigned int size; 99 + unsigned int i; 100 + int ret; 101 + 102 + size = tas571x_register_size(priv, reg); 103 + send_buf = reg; 104 + 105 + msgs[0].addr = client->addr; 106 + msgs[0].len = sizeof(send_buf); 107 + msgs[0].buf = &send_buf; 108 + msgs[0].flags = 0; 109 + 110 + msgs[1].addr = client->addr; 111 + msgs[1].len = size; 112 + msgs[1].buf = recv_buf; 113 + msgs[1].flags = I2C_M_RD; 114 + 115 + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 116 + if (ret < 0) 117 + return ret; 118 + else if (ret != ARRAY_SIZE(msgs)) 119 + return -EIO; 120 + 121 + *value = 0; 122 + 123 + for (i = 0; i < size; i++) { 124 + *value <<= 8; 125 + *value |= recv_buf[i]; 126 + } 127 + 128 + return 0; 129 + } 130 + 131 + static int tas571x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format) 132 + { 133 + struct tas571x_private *priv = snd_soc_codec_get_drvdata(dai->codec); 134 + 135 + priv->format = format; 136 + 137 + return 0; 138 + } 139 + 140 + static int tas571x_hw_params(struct snd_pcm_substream *substream, 141 + struct snd_pcm_hw_params *params, 142 + struct snd_soc_dai *dai) 143 + { 144 + struct tas571x_private *priv = snd_soc_codec_get_drvdata(dai->codec); 145 + u32 val; 146 + 147 + switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { 148 + case SND_SOC_DAIFMT_RIGHT_J: 149 + val = 0x00; 150 + break; 151 + case SND_SOC_DAIFMT_I2S: 152 + val = 0x03; 153 + break; 154 + case SND_SOC_DAIFMT_LEFT_J: 155 + val = 0x06; 156 + break; 157 + default: 158 + return -EINVAL; 159 + } 160 + 161 + if (params_width(params) >= 24) 162 + val += 2; 163 + else if (params_width(params) >= 20) 164 + val += 1; 165 + 166 + return regmap_update_bits(priv->regmap, TAS571X_SDI_REG, 167 + TAS571X_SDI_FMT_MASK, val); 168 + } 169 + 170 + static int tas571x_set_bias_level(struct snd_soc_codec *codec, 171 + enum snd_soc_bias_level level) 172 + { 173 + struct tas571x_private *priv = snd_soc_codec_get_drvdata(codec); 174 + int ret; 175 + 176 + switch (level) { 177 + case SND_SOC_BIAS_ON: 178 + break; 179 + case SND_SOC_BIAS_PREPARE: 180 + break; 181 + case SND_SOC_BIAS_STANDBY: 182 + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { 183 + if (!IS_ERR(priv->mclk)) { 184 + ret = clk_prepare_enable(priv->mclk); 185 + if (ret) { 186 + dev_err(codec->dev, 187 + "Failed to enable master clock: %d\n", 188 + ret); 189 + return ret; 190 + } 191 + } 192 + 193 + gpiod_set_value(priv->pdn_gpio, 0); 194 + usleep_range(5000, 6000); 195 + 196 + regcache_cache_only(priv->regmap, false); 197 + ret = regcache_sync(priv->regmap); 198 + if (ret) 199 + return ret; 200 + } 201 + break; 202 + case SND_SOC_BIAS_OFF: 203 + regcache_cache_only(priv->regmap, true); 204 + gpiod_set_value(priv->pdn_gpio, 1); 205 + 206 + if (!IS_ERR(priv->mclk)) 207 + clk_disable_unprepare(priv->mclk); 208 + break; 209 + } 210 + 211 + return 0; 212 + } 213 + 214 + static const struct snd_soc_dai_ops tas571x_dai_ops = { 215 + .set_fmt = tas571x_set_dai_fmt, 216 + .hw_params = tas571x_hw_params, 217 + }; 218 + 219 + static const char *const tas5711_supply_names[] = { 220 + "AVDD", 221 + "DVDD", 222 + "PVDD_A", 223 + "PVDD_B", 224 + "PVDD_C", 225 + "PVDD_D", 226 + }; 227 + 228 + static const DECLARE_TLV_DB_SCALE(tas5711_volume_tlv, -10350, 50, 1); 229 + 230 + static const struct snd_kcontrol_new tas5711_controls[] = { 231 + SOC_SINGLE_TLV("Master Volume", 232 + TAS571X_MVOL_REG, 233 + 0, 0xff, 1, tas5711_volume_tlv), 234 + SOC_DOUBLE_R_TLV("Speaker Volume", 235 + TAS571X_CH1_VOL_REG, 236 + TAS571X_CH2_VOL_REG, 237 + 0, 0xff, 1, tas5711_volume_tlv), 238 + SOC_DOUBLE("Speaker Switch", 239 + TAS571X_SOFT_MUTE_REG, 240 + TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, 241 + 1, 1), 242 + }; 243 + 244 + static const struct reg_default tas5711_reg_defaults[] = { 245 + { 0x04, 0x05 }, 246 + { 0x05, 0x40 }, 247 + { 0x06, 0x00 }, 248 + { 0x07, 0xff }, 249 + { 0x08, 0x30 }, 250 + { 0x09, 0x30 }, 251 + { 0x1b, 0x82 }, 252 + }; 253 + 254 + static const struct regmap_config tas5711_regmap_config = { 255 + .reg_bits = 8, 256 + .val_bits = 32, 257 + .max_register = 0xff, 258 + .reg_read = tas571x_reg_read, 259 + .reg_write = tas571x_reg_write, 260 + .reg_defaults = tas5711_reg_defaults, 261 + .num_reg_defaults = ARRAY_SIZE(tas5711_reg_defaults), 262 + .cache_type = REGCACHE_RBTREE, 263 + }; 264 + 265 + static const struct tas571x_chip tas5711_chip = { 266 + .supply_names = tas5711_supply_names, 267 + .num_supply_names = ARRAY_SIZE(tas5711_supply_names), 268 + .controls = tas5711_controls, 269 + .num_controls = ARRAY_SIZE(tas5711_controls), 270 + .regmap_config = &tas5711_regmap_config, 271 + .vol_reg_size = 1, 272 + }; 273 + 274 + static const char *const tas5717_supply_names[] = { 275 + "AVDD", 276 + "DVDD", 277 + "HPVDD", 278 + "PVDD_AB", 279 + "PVDD_CD", 280 + }; 281 + 282 + static const DECLARE_TLV_DB_SCALE(tas5717_volume_tlv, -10375, 25, 0); 283 + 284 + static const struct snd_kcontrol_new tas5717_controls[] = { 285 + /* MVOL LSB is ignored - see comments in tas571x_i2c_probe() */ 286 + SOC_SINGLE_TLV("Master Volume", 287 + TAS571X_MVOL_REG, 1, 0x1ff, 1, 288 + tas5717_volume_tlv), 289 + SOC_DOUBLE_R_TLV("Speaker Volume", 290 + TAS571X_CH1_VOL_REG, TAS571X_CH2_VOL_REG, 291 + 1, 0x1ff, 1, tas5717_volume_tlv), 292 + SOC_DOUBLE("Speaker Switch", 293 + TAS571X_SOFT_MUTE_REG, 294 + TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT, 295 + 1, 1), 296 + }; 297 + 298 + static const struct reg_default tas5717_reg_defaults[] = { 299 + { 0x04, 0x05 }, 300 + { 0x05, 0x40 }, 301 + { 0x06, 0x00 }, 302 + { 0x07, 0x03ff }, 303 + { 0x08, 0x00c0 }, 304 + { 0x09, 0x00c0 }, 305 + { 0x1b, 0x82 }, 306 + }; 307 + 308 + static const struct regmap_config tas5717_regmap_config = { 309 + .reg_bits = 8, 310 + .val_bits = 32, 311 + .max_register = 0xff, 312 + .reg_read = tas571x_reg_read, 313 + .reg_write = tas571x_reg_write, 314 + .reg_defaults = tas5717_reg_defaults, 315 + .num_reg_defaults = ARRAY_SIZE(tas5717_reg_defaults), 316 + .cache_type = REGCACHE_RBTREE, 317 + }; 318 + 319 + /* This entry is reused for tas5719 as the software interface is identical. */ 320 + static const struct tas571x_chip tas5717_chip = { 321 + .supply_names = tas5717_supply_names, 322 + .num_supply_names = ARRAY_SIZE(tas5717_supply_names), 323 + .controls = tas5717_controls, 324 + .num_controls = ARRAY_SIZE(tas5717_controls), 325 + .regmap_config = &tas5717_regmap_config, 326 + .vol_reg_size = 2, 327 + }; 328 + 329 + static const struct snd_soc_dapm_widget tas571x_dapm_widgets[] = { 330 + SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), 331 + SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), 332 + 333 + SND_SOC_DAPM_OUTPUT("OUT_A"), 334 + SND_SOC_DAPM_OUTPUT("OUT_B"), 335 + SND_SOC_DAPM_OUTPUT("OUT_C"), 336 + SND_SOC_DAPM_OUTPUT("OUT_D"), 337 + }; 338 + 339 + static const struct snd_soc_dapm_route tas571x_dapm_routes[] = { 340 + { "DACL", NULL, "Playback" }, 341 + { "DACR", NULL, "Playback" }, 342 + 343 + { "OUT_A", NULL, "DACL" }, 344 + { "OUT_B", NULL, "DACL" }, 345 + { "OUT_C", NULL, "DACR" }, 346 + { "OUT_D", NULL, "DACR" }, 347 + }; 348 + 349 + static const struct snd_soc_codec_driver tas571x_codec = { 350 + .set_bias_level = tas571x_set_bias_level, 351 + .idle_bias_off = true, 352 + 353 + .dapm_widgets = tas571x_dapm_widgets, 354 + .num_dapm_widgets = ARRAY_SIZE(tas571x_dapm_widgets), 355 + .dapm_routes = tas571x_dapm_routes, 356 + .num_dapm_routes = ARRAY_SIZE(tas571x_dapm_routes), 357 + }; 358 + 359 + static struct snd_soc_dai_driver tas571x_dai = { 360 + .name = "tas571x-hifi", 361 + .playback = { 362 + .stream_name = "Playback", 363 + .channels_min = 2, 364 + .channels_max = 2, 365 + .rates = SNDRV_PCM_RATE_8000_48000, 366 + .formats = SNDRV_PCM_FMTBIT_S32_LE | 367 + SNDRV_PCM_FMTBIT_S24_LE | 368 + SNDRV_PCM_FMTBIT_S16_LE, 369 + }, 370 + .ops = &tas571x_dai_ops, 371 + }; 372 + 373 + static const struct of_device_id tas571x_of_match[]; 374 + 375 + static int tas571x_i2c_probe(struct i2c_client *client, 376 + const struct i2c_device_id *id) 377 + { 378 + struct tas571x_private *priv; 379 + struct device *dev = &client->dev; 380 + const struct of_device_id *of_id; 381 + int i, ret; 382 + 383 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 384 + if (!priv) 385 + return -ENOMEM; 386 + i2c_set_clientdata(client, priv); 387 + 388 + of_id = of_match_device(tas571x_of_match, dev); 389 + if (!of_id) { 390 + dev_err(dev, "Unknown device type\n"); 391 + return -EINVAL; 392 + } 393 + priv->chip = of_id->data; 394 + 395 + priv->mclk = devm_clk_get(dev, "mclk"); 396 + if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) { 397 + dev_err(dev, "Failed to request mclk: %ld\n", 398 + PTR_ERR(priv->mclk)); 399 + return PTR_ERR(priv->mclk); 400 + } 401 + 402 + BUG_ON(priv->chip->num_supply_names > TAS571X_MAX_SUPPLIES); 403 + for (i = 0; i < priv->chip->num_supply_names; i++) 404 + priv->supplies[i].supply = priv->chip->supply_names[i]; 405 + 406 + ret = devm_regulator_bulk_get(dev, priv->chip->num_supply_names, 407 + priv->supplies); 408 + if (ret) { 409 + dev_err(dev, "Failed to get supplies: %d\n", ret); 410 + return ret; 411 + } 412 + ret = regulator_bulk_enable(priv->chip->num_supply_names, 413 + priv->supplies); 414 + if (ret) { 415 + dev_err(dev, "Failed to enable supplies: %d\n", ret); 416 + return ret; 417 + } 418 + 419 + priv->regmap = devm_regmap_init(dev, NULL, client, 420 + priv->chip->regmap_config); 421 + if (IS_ERR(priv->regmap)) 422 + return PTR_ERR(priv->regmap); 423 + 424 + priv->pdn_gpio = devm_gpiod_get_optional(dev, "pdn", GPIOD_OUT_LOW); 425 + if (IS_ERR(priv->pdn_gpio)) { 426 + dev_err(dev, "error requesting pdn_gpio: %ld\n", 427 + PTR_ERR(priv->pdn_gpio)); 428 + return PTR_ERR(priv->pdn_gpio); 429 + } 430 + 431 + priv->reset_gpio = devm_gpiod_get_optional(dev, "reset", 432 + GPIOD_OUT_HIGH); 433 + if (IS_ERR(priv->reset_gpio)) { 434 + dev_err(dev, "error requesting reset_gpio: %ld\n", 435 + PTR_ERR(priv->reset_gpio)); 436 + return PTR_ERR(priv->reset_gpio); 437 + } else if (priv->reset_gpio) { 438 + /* pulse the active low reset line for ~100us */ 439 + usleep_range(100, 200); 440 + gpiod_set_value(priv->reset_gpio, 0); 441 + usleep_range(12000, 20000); 442 + } 443 + 444 + ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0); 445 + if (ret) 446 + return ret; 447 + 448 + ret = regmap_update_bits(priv->regmap, TAS571X_SYS_CTRL_2_REG, 449 + TAS571X_SYS_CTRL_2_SDN_MASK, 0); 450 + if (ret) 451 + return ret; 452 + 453 + memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver)); 454 + priv->codec_driver.controls = priv->chip->controls; 455 + priv->codec_driver.num_controls = priv->chip->num_controls; 456 + 457 + if (priv->chip->vol_reg_size == 2) { 458 + /* 459 + * The master volume defaults to 0x3ff (mute), but we ignore 460 + * (zero) the LSB because the hardware step size is 0.125 dB 461 + * and TLV_DB_SCALE_ITEM has a resolution of 0.01 dB. 462 + */ 463 + ret = regmap_update_bits(priv->regmap, TAS571X_MVOL_REG, 1, 0); 464 + if (ret) 465 + return ret; 466 + } 467 + 468 + regcache_cache_only(priv->regmap, true); 469 + gpiod_set_value(priv->pdn_gpio, 1); 470 + 471 + return snd_soc_register_codec(&client->dev, &priv->codec_driver, 472 + &tas571x_dai, 1); 473 + } 474 + 475 + static int tas571x_i2c_remove(struct i2c_client *client) 476 + { 477 + struct tas571x_private *priv = i2c_get_clientdata(client); 478 + 479 + snd_soc_unregister_codec(&client->dev); 480 + regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies); 481 + 482 + return 0; 483 + } 484 + 485 + static const struct of_device_id tas571x_of_match[] = { 486 + { .compatible = "ti,tas5711", .data = &tas5711_chip, }, 487 + { .compatible = "ti,tas5717", .data = &tas5717_chip, }, 488 + { .compatible = "ti,tas5719", .data = &tas5717_chip, }, 489 + { } 490 + }; 491 + MODULE_DEVICE_TABLE(of, tas571x_of_match); 492 + 493 + static const struct i2c_device_id tas571x_i2c_id[] = { 494 + { "tas5711", 0 }, 495 + { "tas5717", 0 }, 496 + { "tas5719", 0 }, 497 + { } 498 + }; 499 + MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id); 500 + 501 + static struct i2c_driver tas571x_i2c_driver = { 502 + .driver = { 503 + .name = "tas571x", 504 + .of_match_table = of_match_ptr(tas571x_of_match), 505 + }, 506 + .probe = tas571x_i2c_probe, 507 + .remove = tas571x_i2c_remove, 508 + .id_table = tas571x_i2c_id, 509 + }; 510 + module_i2c_driver(tas571x_i2c_driver); 511 + 512 + MODULE_DESCRIPTION("ASoC TAS571x driver"); 513 + MODULE_AUTHOR("Kevin Cernekee <cernekee@chromium.org>"); 514 + MODULE_LICENSE("GPL");
+33
sound/soc/codecs/tas571x.h
··· 1 + /* 2 + * TAS571x amplifier audio driver 3 + * 4 + * Copyright (C) 2015 Google, Inc. 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 as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + */ 11 + 12 + #ifndef _TAS571X_H 13 + #define _TAS571X_H 14 + 15 + /* device registers */ 16 + #define TAS571X_SDI_REG 0x04 17 + #define TAS571X_SDI_FMT_MASK 0x0f 18 + 19 + #define TAS571X_SYS_CTRL_2_REG 0x05 20 + #define TAS571X_SYS_CTRL_2_SDN_MASK 0x40 21 + 22 + #define TAS571X_SOFT_MUTE_REG 0x06 23 + #define TAS571X_SOFT_MUTE_CH1_SHIFT 0 24 + #define TAS571X_SOFT_MUTE_CH2_SHIFT 1 25 + #define TAS571X_SOFT_MUTE_CH3_SHIFT 2 26 + 27 + #define TAS571X_MVOL_REG 0x07 28 + #define TAS571X_CH1_VOL_REG 0x08 29 + #define TAS571X_CH2_VOL_REG 0x09 30 + 31 + #define TAS571X_OSC_TRIM_REG 0x1b 32 + 33 + #endif /* _TAS571X_H */
+7 -8
sound/soc/codecs/ts3a227e.c
··· 254 254 .num_reg_defaults = ARRAY_SIZE(ts3a227e_reg_defaults), 255 255 }; 256 256 257 - static int ts3a227e_parse_dt(struct ts3a227e *ts3a227e, struct device_node *np) 257 + static int ts3a227e_parse_device_property(struct ts3a227e *ts3a227e, 258 + struct device *dev) 258 259 { 259 260 u32 micbias; 260 261 int err; 261 262 262 - err = of_property_read_u32(np, "ti,micbias", &micbias); 263 + err = device_property_read_u32(dev, "ti,micbias", &micbias); 263 264 if (!err) { 264 265 regmap_update_bits(ts3a227e->regmap, TS3A227E_REG_SETTING_3, 265 266 MICBIAS_SETTING_MASK, ··· 288 287 if (IS_ERR(ts3a227e->regmap)) 289 288 return PTR_ERR(ts3a227e->regmap); 290 289 291 - if (dev->of_node) { 292 - ret = ts3a227e_parse_dt(ts3a227e, dev->of_node); 293 - if (ret) { 294 - dev_err(dev, "Failed to parse device tree: %d\n", ret); 295 - return ret; 296 - } 290 + ret = ts3a227e_parse_device_property(ts3a227e, dev); 291 + if (ret) { 292 + dev_err(dev, "Failed to parse device property: %d\n", ret); 293 + return ret; 297 294 } 298 295 299 296 ret = devm_request_threaded_irq(dev, i2c->irq, NULL, ts3a227e_interrupt,