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

ASoC: Add rtq9128 audio amplifier

Merge series from cy_huang@richtek.com:

This patch series adds Richtek rtq9128 automotive audio amplifier
support. It can deliver up to 4x75W into 4Ohm speaker from a 25V
supply in automotive applications.

+837
+54
Documentation/devicetree/bindings/sound/richtek,rtq9128.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/sound/richtek,rtq9128.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Richtek RTQ9128 Automative Audio Power Amplifier 8 + 9 + maintainers: 10 + - ChiYuan Huang <cy_huang@richtek.com> 11 + 12 + description: 13 + The RTQ9128 is a ultra-low output noise, high-efficiency, four-channel 14 + class-D audio power amplifier and delivering 4x75W into 4OHm at 10% 15 + THD+N from a 25V supply in automotive applications. 16 + 17 + allOf: 18 + - $ref: dai-common.yaml# 19 + 20 + properties: 21 + compatible: 22 + enum: 23 + - richtek,rtq9128 24 + 25 + reg: 26 + maxItems: 1 27 + 28 + enable-gpios: 29 + maxItems: 1 30 + 31 + '#sound-dai-cells': 32 + const: 0 33 + 34 + required: 35 + - compatible 36 + - reg 37 + - '#sound-dai-cells' 38 + 39 + unevaluatedProperties: false 40 + 41 + examples: 42 + - | 43 + #include <dt-bindings/gpio/gpio.h> 44 + i2c { 45 + #address-cells = <1>; 46 + #size-cells = <0>; 47 + 48 + speaker@1a { 49 + compatible = "richtek,rtq9128"; 50 + reg = <0x1a>; 51 + enable-gpios = <&gpio 26 GPIO_ACTIVE_HIGH>; 52 + #sound-dai-cells = <0>; 53 + }; 54 + };
+15
sound/soc/codecs/Kconfig
··· 218 218 imply SND_SOC_RT1316_SDW 219 219 imply SND_SOC_RT1318_SDW 220 220 imply SND_SOC_RT9120 221 + imply SND_SOC_RTQ9128 221 222 imply SND_SOC_SDW_MOCKUP 222 223 imply SND_SOC_SGTL5000 223 224 imply SND_SOC_SI476X ··· 1636 1635 help 1637 1636 Enable support for Richtek RT9120 20W, stereo, inductor-less, 1638 1637 high-efficiency Class-D audio amplifier. 1638 + 1639 + config SND_SOC_RTQ9128 1640 + tristate "Richtek RTQ9128 45W Digital Input Amplifier" 1641 + depends on I2C 1642 + select REGMAP 1643 + help 1644 + Enable support for Richtek RTQ9128 digital input 4-channel 1645 + automotive audio amplifier. It is a ultra-low output noise, 1646 + high-efficiency, four-channel class-D audio power amplifier 1647 + that can deliver over 87% power efficienty at 4x75W into 4Ohm, 1648 + 25V supply in automotive applications. 1649 + 1650 + To compile this driver as a module, choose M here: the module 1651 + will be called snd-soc-rtq9128. 1639 1652 1640 1653 config SND_SOC_SDW_MOCKUP 1641 1654 tristate "SoundWire mockup codec"
+2
sound/soc/codecs/Makefile
··· 245 245 snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o 246 246 snd-soc-rt722-sdca-objs := rt722-sdca.o rt722-sdca-sdw.o 247 247 snd-soc-rt9120-objs := rt9120.o 248 + snd-soc-rtq9128-objs := rtq9128.o 248 249 snd-soc-sdw-mockup-objs := sdw-mockup.o 249 250 snd-soc-sgtl5000-objs := sgtl5000.o 250 251 snd-soc-alc5623-objs := alc5623.o ··· 628 627 obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o 629 628 obj-$(CONFIG_SND_SOC_RT722_SDCA_SDW) += snd-soc-rt722-sdca.o 630 629 obj-$(CONFIG_SND_SOC_RT9120) += snd-soc-rt9120.o 630 + obj-$(CONFIG_SND_SOC_RTQ9128) += snd-soc-rtq9128.o 631 631 obj-$(CONFIG_SND_SOC_SDW_MOCKUP) += snd-soc-sdw-mockup.o 632 632 obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o 633 633 obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
+766
sound/soc/codecs/rtq9128.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // Copyright (c) 2023 Richtek Technology Corp. 4 + // 5 + // Author: ChiYuan Huang <cy_huang@richtek.com> 6 + // 7 + 8 + #include <linux/bitfield.h> 9 + #include <linux/bits.h> 10 + #include <linux/delay.h> 11 + #include <linux/gpio/consumer.h> 12 + #include <linux/i2c.h> 13 + #include <linux/kernel.h> 14 + #include <linux/mod_devicetable.h> 15 + #include <linux/module.h> 16 + #include <linux/pm_runtime.h> 17 + #include <linux/regmap.h> 18 + #include <sound/pcm_params.h> 19 + #include <sound/soc.h> 20 + #include <sound/tlv.h> 21 + 22 + #define RTQ9128_REG_SDI_SEL 0x00 23 + #define RTQ9128_REG_SDO_SEL 0x01 24 + #define RTQ9128_REG_I2S_OPT 0x02 25 + #define RTQ9128_REG_MISC 0x03 26 + #define RTQ9128_REG_STATE_CTRL 0x04 27 + #define RTQ9128_REG_PLLTRI_GEN1 0x05 28 + #define RTQ9128_REG_PLLTRI_GEN2 0x06 29 + #define RTQ9128_REG_PWM_SS_OPT 0x07 30 + #define RTQ9128_REG_DSP_EN 0x08 31 + #define RTQ9128_REG_TDM_TX_CH1 0x21 32 + #define RTQ9128_REG_TDM_RX_CH1 0x25 33 + #define RTQ9128_REG_MS_VOL 0x30 34 + #define RTQ9128_REG_CH1_VOL 0x31 35 + #define RTQ9128_REG_CH2_VOL 0x32 36 + #define RTQ9128_REG_CH3_VOL 0x33 37 + #define RTQ9128_REG_CH4_VOL 0x34 38 + #define RTQ9128_REG_PROT_OPT 0x71 39 + #define RTQ9128_REG_EFUSE_DATA 0xE0 40 + #define RTQ9128_REG_VENDOR_ID 0xF9 41 + 42 + #define RTQ9128_CHSTAT_VAL_MASK GENMASK(1, 0) 43 + #define RTQ9128_DOLEN_MASK GENMASK(7, 6) 44 + #define RTQ9128_AUDBIT_MASK GENMASK(5, 4) 45 + #define RTQ9128_AUDFMT_MASK GENMASK(3, 0) 46 + #define RTQ9128_MSMUTE_MASK BIT(0) 47 + #define RTQ9128_DIE_CHECK_MASK GENMASK(4, 0) 48 + #define RTQ9128_VENDOR_ID_MASK GENMASK(19, 8) 49 + 50 + #define RTQ9128_SOFT_RESET_VAL 0x80 51 + #define RTQ9128_VENDOR_ID_VAL 0x470 52 + #define RTQ9128_ALLCH_HIZ_VAL 0x55 53 + #define RTQ9128_ALLCH_ULQM_VAL 0xFF 54 + #define RTQ9128_TKA470B_VAL 0 55 + #define RTQ9128_RTQ9128DH_VAL 0x0F 56 + #define RTQ9128_RTQ9128DL_VAL 0x10 57 + 58 + struct rtq9128_data { 59 + struct gpio_desc *enable; 60 + int tdm_slots; 61 + int tdm_slot_width; 62 + }; 63 + 64 + struct rtq9128_init_reg { 65 + unsigned int reg; 66 + unsigned int val; 67 + }; 68 + 69 + static int rtq9128_get_reg_size(unsigned int reg) 70 + { 71 + switch (reg) { 72 + case 0x5C ... 0x6F: 73 + case 0x98 ... 0x9F: 74 + case 0xC0 ... 0xC3: 75 + case 0xC8 ... 0xCF: 76 + case 0xDF ... 0xE5: 77 + case 0xF9: 78 + return 4; 79 + case 0x40 ... 0x4F: 80 + return 3; 81 + case 0x30 ... 0x35: 82 + case 0x8C ... 0x97: 83 + case 0xC4 ... 0xC7: 84 + case 0xD7 ... 0xDA: 85 + return 2; 86 + default: 87 + return 1; 88 + } 89 + } 90 + 91 + static int rtq9128_i2c_write(void *context, const void *data, size_t count) 92 + { 93 + struct device *dev = context; 94 + struct i2c_client *i2c = to_i2c_client(dev); 95 + u8 reg = *(u8 *)data; 96 + int rg_size; 97 + 98 + if (count != 5) { 99 + dev_err(dev, "Invalid write for data length (%d)\n", (int)count); 100 + return -EINVAL; 101 + } 102 + 103 + rg_size = rtq9128_get_reg_size(reg); 104 + return i2c_smbus_write_i2c_block_data(i2c, reg, rg_size, data + count - rg_size); 105 + } 106 + 107 + static int rtq9128_i2c_read(void *context, const void *reg_buf, size_t reg_size, void *val_buf, 108 + size_t val_size) 109 + { 110 + struct device *dev = context; 111 + struct i2c_client *i2c = to_i2c_client(dev); 112 + u8 reg = *(u8 *)reg_buf; 113 + u8 data_tmp[4] = {}; 114 + int rg_size, ret; 115 + 116 + if (reg_size != 1 || val_size != 4) { 117 + dev_err(dev, "Invalid read for reg_size (%d) or val_size (%d)\n", (int)reg_size, 118 + (int)val_size); 119 + return -EINVAL; 120 + } 121 + 122 + rg_size = rtq9128_get_reg_size(reg); 123 + ret = i2c_smbus_read_i2c_block_data(i2c, reg, rg_size, data_tmp); 124 + if (ret < 0) 125 + return ret; 126 + else if (ret != rg_size) 127 + return -EIO; 128 + 129 + memset(val_buf, 0, val_size - rg_size); 130 + memcpy(val_buf + val_size - rg_size, data_tmp, rg_size); 131 + 132 + return 0; 133 + } 134 + 135 + static const struct regmap_bus rtq9128_regmap_bus = { 136 + .write = rtq9128_i2c_write, 137 + .read = rtq9128_i2c_read, 138 + .max_raw_read = 4, 139 + .max_raw_write = 4, 140 + }; 141 + 142 + static bool rtq9128_is_readable_reg(struct device *dev, unsigned int reg) 143 + { 144 + switch (reg) { 145 + case 0x00 ... 0x2B: 146 + case 0x30 ... 0x35: 147 + case 0x40 ... 0x56: 148 + case 0x5C ... 0x76: 149 + case 0x80 ... 0xAD: 150 + case 0xB0 ... 0xBA: 151 + case 0xC0 ... 0xE5: 152 + case 0xF0 ... 0xFB: 153 + return true; 154 + default: 155 + return false; 156 + } 157 + } 158 + 159 + static bool rtq9128_is_writeable_reg(struct device *dev, unsigned int reg) 160 + { 161 + switch (reg) { 162 + case 0x00 ... 0x1F: 163 + case 0x21 ... 0x2B: 164 + case 0x30 ... 0x35: 165 + case 0x40 ... 0x56: 166 + case 0x5C ... 0x76: 167 + case 0x80 ... 0x8B: 168 + case 0xA0 ... 0xAD: 169 + case 0xB0 ... 0xBA: 170 + case 0xC0: 171 + case 0xD0 ... 0xDE: 172 + case 0xE0 ... 0xE5: 173 + case 0xF0 ... 0xF3: 174 + case 0xF6 ... 0xF8: 175 + case 0xFA ... 0xFB: 176 + return true; 177 + default: 178 + return false; 179 + } 180 + } 181 + 182 + static bool rtq9128_is_volatile_reg(struct device *dev, unsigned int reg) 183 + { 184 + switch (reg) { 185 + case 0x0F ... 0x17: 186 + case 0x20: 187 + case 0x53: 188 + case 0x55: 189 + case 0x5C ... 0x6F: 190 + case 0x8C ... 0x9F: 191 + case 0xC0 ... 0xCF: 192 + case 0xDF: 193 + case 0xF0 ... 0xF1: 194 + case 0xF4 ... 0xF5: 195 + return true; 196 + default: 197 + return false; 198 + } 199 + } 200 + 201 + static const struct regmap_config rtq9128_regmap_config = { 202 + .name = "rtq9128", 203 + .reg_bits = 8, 204 + .val_bits = 32, 205 + .val_format_endian = REGMAP_ENDIAN_BIG, 206 + .cache_type = REGCACHE_MAPLE, 207 + 208 + .readable_reg = rtq9128_is_readable_reg, 209 + .writeable_reg = rtq9128_is_writeable_reg, 210 + .volatile_reg = rtq9128_is_volatile_reg, 211 + .num_reg_defaults_raw = RTQ9128_REG_VENDOR_ID + 1, 212 + }; 213 + 214 + static const DECLARE_TLV_DB_SCALE(dig_tlv, -10375, 25, 0); 215 + 216 + static const DECLARE_TLV_DB_RANGE(spkgain_tlv, 217 + 0, 3, TLV_DB_SCALE_ITEM(-600, 600, 0), 218 + 4, 5, TLV_DB_SCALE_ITEM(1500, 300, 0), 219 + ); 220 + 221 + static const char * const source_select_text[] = { "CH1", "CH2", "CH3", "CH4" }; 222 + static const char * const pwmfreq_select_text[] = { "8fs", "10fs", "40fs", "44fs", "48fs" }; 223 + static const char * const phase_select_text[] = { 224 + "0 degree", "45 degree", "90 degree", "135 degree", 225 + "180 degree", "225 degree", "270 degree", "315 degree", 226 + }; 227 + static const char * const dvdduv_select_text[] = { "1P4V", "1P5V", "2P1V", "2P3V" }; 228 + 229 + static const struct soc_enum rtq9128_ch1_si_enum = 230 + SOC_ENUM_SINGLE(RTQ9128_REG_SDI_SEL, 6, ARRAY_SIZE(source_select_text), source_select_text); 231 + static const struct soc_enum rtq9128_ch2_si_enum = 232 + SOC_ENUM_SINGLE(RTQ9128_REG_SDI_SEL, 4, ARRAY_SIZE(source_select_text), source_select_text); 233 + static const struct soc_enum rtq9128_ch3_si_enum = 234 + SOC_ENUM_SINGLE(RTQ9128_REG_SDI_SEL, 2, ARRAY_SIZE(source_select_text), source_select_text); 235 + static const struct soc_enum rtq9128_ch4_si_enum = 236 + SOC_ENUM_SINGLE(RTQ9128_REG_SDI_SEL, 0, ARRAY_SIZE(source_select_text), source_select_text); 237 + static const struct soc_enum rtq9128_pwm_freq_enum = 238 + SOC_ENUM_SINGLE(RTQ9128_REG_PLLTRI_GEN1, 4, ARRAY_SIZE(pwmfreq_select_text), 239 + pwmfreq_select_text); 240 + static const struct soc_enum rtq9128_out2_phase_enum = 241 + SOC_ENUM_SINGLE(RTQ9128_REG_PLLTRI_GEN1, 0, ARRAY_SIZE(phase_select_text), 242 + phase_select_text); 243 + static const struct soc_enum rtq9128_out3_phase_enum = 244 + SOC_ENUM_SINGLE(RTQ9128_REG_PLLTRI_GEN2, 4, ARRAY_SIZE(phase_select_text), 245 + phase_select_text); 246 + static const struct soc_enum rtq9128_out4_phase_enum = 247 + SOC_ENUM_SINGLE(RTQ9128_REG_PLLTRI_GEN2, 0, ARRAY_SIZE(phase_select_text), 248 + phase_select_text); 249 + 250 + /* 251 + * In general usage, DVDD could be 1P8V, 3P0V or 3P3V. 252 + * This DVDD undervoltage protection is to prevent from the abnormal power 253 + * lose case while the amplifier is operating. Due to the different DVDD 254 + * application, treat this threshold as a user choosable option. 255 + */ 256 + static const struct soc_enum rtq9128_dvdduv_select_enum = 257 + SOC_ENUM_SINGLE(RTQ9128_REG_PROT_OPT, 6, ARRAY_SIZE(dvdduv_select_text), 258 + dvdduv_select_text); 259 + 260 + static const struct snd_kcontrol_new rtq9128_snd_ctrls[] = { 261 + SOC_SINGLE_TLV("MS Volume", RTQ9128_REG_MS_VOL, 2, 511, 1, dig_tlv), 262 + SOC_SINGLE_TLV("CH1 Volume", RTQ9128_REG_CH1_VOL, 2, 511, 1, dig_tlv), 263 + SOC_SINGLE_TLV("CH2 Volume", RTQ9128_REG_CH2_VOL, 2, 511, 1, dig_tlv), 264 + SOC_SINGLE_TLV("CH3 Volume", RTQ9128_REG_CH3_VOL, 2, 511, 1, dig_tlv), 265 + SOC_SINGLE_TLV("CH4 Volume", RTQ9128_REG_CH4_VOL, 2, 511, 1, dig_tlv), 266 + SOC_SINGLE_TLV("SPK Gain Volume", RTQ9128_REG_MISC, 0, 5, 0, spkgain_tlv), 267 + SOC_SINGLE("PBTL12 Switch", RTQ9128_REG_MISC, 5, 1, 0), 268 + SOC_SINGLE("PBTL34 Switch", RTQ9128_REG_MISC, 4, 1, 0), 269 + SOC_SINGLE("Spread Spectrum Switch", RTQ9128_REG_PWM_SS_OPT, 7, 1, 0), 270 + SOC_SINGLE("SDO Select", RTQ9128_REG_SDO_SEL, 0, 15, 0), 271 + SOC_ENUM("CH1 SI Select", rtq9128_ch1_si_enum), 272 + SOC_ENUM("CH2 SI Select", rtq9128_ch2_si_enum), 273 + SOC_ENUM("CH3 SI Select", rtq9128_ch3_si_enum), 274 + SOC_ENUM("CH4 SI Select", rtq9128_ch4_si_enum), 275 + SOC_ENUM("PWM FREQ Select", rtq9128_pwm_freq_enum), 276 + SOC_ENUM("OUT2 Phase Select", rtq9128_out2_phase_enum), 277 + SOC_ENUM("OUT3 Phase Select", rtq9128_out3_phase_enum), 278 + SOC_ENUM("OUT4 Phase Select", rtq9128_out4_phase_enum), 279 + SOC_ENUM("DVDD UV Threshold Select", rtq9128_dvdduv_select_enum), 280 + }; 281 + 282 + static int rtq9128_dac_power_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, 283 + int event) 284 + { 285 + struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm); 286 + unsigned int shift, mask; 287 + int ret; 288 + 289 + dev_dbg(comp->dev, "%s: %s event %d\n", __func__, w->name, event); 290 + 291 + if (strcmp(w->name, "DAC1") == 0) 292 + shift = 6; 293 + else if (strcmp(w->name, "DAC2") == 0) 294 + shift = 4; 295 + else if (strcmp(w->name, "DAC3") == 0) 296 + shift = 2; 297 + else 298 + shift = 0; 299 + 300 + mask = RTQ9128_CHSTAT_VAL_MASK << shift; 301 + 302 + /* Turn channel state to Normal or HiZ */ 303 + ret = snd_soc_component_write_field(comp, RTQ9128_REG_STATE_CTRL, mask, 304 + event != SND_SOC_DAPM_POST_PMU); 305 + if (ret < 0) 306 + return ret; 307 + 308 + /* 309 + * For each channel turns on, HW will trigger DC load detect and DC 310 + * offset calibration, the time is needed for all the actions done. 311 + */ 312 + if (event == SND_SOC_DAPM_POST_PMU) 313 + msleep(25); 314 + 315 + return 0; 316 + } 317 + 318 + static const struct snd_soc_dapm_widget rtq9128_dapm_widgets[] = { 319 + SND_SOC_DAPM_DAC_E("DAC1", NULL, SND_SOC_NOPM, 0, 0, rtq9128_dac_power_event, 320 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 321 + SND_SOC_DAPM_DAC_E("DAC2", NULL, SND_SOC_NOPM, 0, 0, rtq9128_dac_power_event, 322 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 323 + SND_SOC_DAPM_DAC_E("DAC3", NULL, SND_SOC_NOPM, 0, 0, rtq9128_dac_power_event, 324 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 325 + SND_SOC_DAPM_DAC_E("DAC4", NULL, SND_SOC_NOPM, 0, 0, rtq9128_dac_power_event, 326 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 327 + SND_SOC_DAPM_OUTPUT("OUT1"), 328 + SND_SOC_DAPM_OUTPUT("OUT2"), 329 + SND_SOC_DAPM_OUTPUT("OUT3"), 330 + SND_SOC_DAPM_OUTPUT("OUT4"), 331 + }; 332 + 333 + static const struct snd_soc_dapm_route rtq9128_dapm_routes[] = { 334 + { "DAC1", NULL, "Playback" }, 335 + { "DAC2", NULL, "Playback" }, 336 + { "DAC3", NULL, "Playback" }, 337 + { "DAC4", NULL, "Playback" }, 338 + { "OUT1", NULL, "DAC1" }, 339 + { "OUT2", NULL, "DAC2" }, 340 + { "OUT3", NULL, "DAC3" }, 341 + { "OUT4", NULL, "DAC4" }, 342 + { "Capture", NULL, "DAC1" }, 343 + { "Capture", NULL, "DAC2" }, 344 + { "Capture", NULL, "DAC3" }, 345 + { "Capture", NULL, "DAC4" }, 346 + }; 347 + 348 + static const struct rtq9128_init_reg rtq9128_tka470b_tables[] = { 349 + { 0xA0, 0xEF }, 350 + { 0x0D, 0x00 }, 351 + { 0x03, 0x05 }, 352 + { 0x05, 0x31 }, 353 + { 0x06, 0x23 }, 354 + { 0x70, 0x11 }, 355 + { 0x75, 0x1F }, 356 + { 0xB6, 0x03 }, 357 + { 0xB9, 0x03 }, 358 + { 0xB8, 0x03 }, 359 + { 0xC1, 0xFF }, 360 + { 0xF8, 0x72 }, 361 + { 0x30, 0x180 }, 362 + }; 363 + 364 + static const struct rtq9128_init_reg rtq9128_dh_tables[] = { 365 + { 0x0F, 0x00 }, 366 + { 0x03, 0x0D }, 367 + { 0xB2, 0xFF }, 368 + { 0xB3, 0xFF }, 369 + { 0x30, 0x180 }, 370 + { 0x8A, 0x55 }, 371 + { 0x72, 0x00 }, 372 + { 0xB1, 0xE3 }, 373 + }; 374 + 375 + static const struct rtq9128_init_reg rtq9128_dl_tables[] = { 376 + { 0x0F, 0x00 }, 377 + { 0x03, 0x0D }, 378 + { 0x30, 0x180 }, 379 + { 0x8A, 0x55 }, 380 + { 0x72, 0x00 }, 381 + { 0xB1, 0xE3 }, 382 + }; 383 + 384 + static int rtq9128_component_probe(struct snd_soc_component *comp) 385 + { 386 + const struct rtq9128_init_reg *table, *curr; 387 + size_t table_size; 388 + unsigned int val; 389 + int i, ret; 390 + 391 + pm_runtime_resume_and_get(comp->dev); 392 + 393 + val = snd_soc_component_read(comp, RTQ9128_REG_EFUSE_DATA); 394 + 395 + switch (FIELD_GET(RTQ9128_DIE_CHECK_MASK, val)) { 396 + case RTQ9128_TKA470B_VAL: 397 + table = rtq9128_tka470b_tables; 398 + table_size = ARRAY_SIZE(rtq9128_tka470b_tables); 399 + break; 400 + case RTQ9128_RTQ9128DH_VAL: 401 + table = rtq9128_dh_tables; 402 + table_size = ARRAY_SIZE(rtq9128_dh_tables); 403 + break; 404 + default: 405 + table = rtq9128_dl_tables; 406 + table_size = ARRAY_SIZE(rtq9128_dl_tables); 407 + break; 408 + } 409 + 410 + for (i = 0, curr = table; i < table_size; i++, curr++) { 411 + ret = snd_soc_component_write(comp, curr->reg, curr->val); 412 + if (ret < 0) 413 + return ret; 414 + } 415 + 416 + pm_runtime_mark_last_busy(comp->dev); 417 + pm_runtime_put(comp->dev); 418 + 419 + return 0; 420 + } 421 + 422 + static const struct snd_soc_component_driver rtq9128_comp_driver = { 423 + .probe = rtq9128_component_probe, 424 + .controls = rtq9128_snd_ctrls, 425 + .num_controls = ARRAY_SIZE(rtq9128_snd_ctrls), 426 + .dapm_widgets = rtq9128_dapm_widgets, 427 + .num_dapm_widgets = ARRAY_SIZE(rtq9128_dapm_widgets), 428 + .dapm_routes = rtq9128_dapm_routes, 429 + .num_dapm_routes = ARRAY_SIZE(rtq9128_dapm_routes), 430 + .use_pmdown_time = 1, 431 + .endianness = 1, 432 + }; 433 + 434 + static int rtq9128_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 435 + { 436 + struct rtq9128_data *data = snd_soc_dai_get_drvdata(dai); 437 + struct snd_soc_component *comp = dai->component; 438 + struct device *dev = dai->dev; 439 + unsigned int audfmt, fmtval; 440 + int ret; 441 + 442 + dev_dbg(dev, "%s: fmt 0x%8x\n", __func__, fmt); 443 + 444 + /* Only support bitclock & framesync as consumer */ 445 + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_BC_FC) { 446 + dev_err(dev, "Only support BCK and LRCK as consumer\n"); 447 + return -EINVAL; 448 + } 449 + 450 + fmtval = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 451 + if (data->tdm_slots && fmtval != SND_SOC_DAIFMT_DSP_A && fmtval != SND_SOC_DAIFMT_DSP_B) { 452 + dev_err(dev, "TDM is used, format only support DSP_A or DSP_B\n"); 453 + return -EINVAL; 454 + } 455 + 456 + switch (fmtval) { 457 + case SND_SOC_DAIFMT_I2S: 458 + audfmt = 8; 459 + break; 460 + case SND_SOC_DAIFMT_LEFT_J: 461 + audfmt = 9; 462 + break; 463 + case SND_SOC_DAIFMT_RIGHT_J: 464 + audfmt = 10; 465 + break; 466 + case SND_SOC_DAIFMT_DSP_A: 467 + audfmt = data->tdm_slots ? 12 : 11; 468 + break; 469 + case SND_SOC_DAIFMT_DSP_B: 470 + audfmt = data->tdm_slots ? 4 : 3; 471 + break; 472 + default: 473 + dev_err(dev, "Unsupported format 0x%8x\n", fmt); 474 + return -EINVAL; 475 + } 476 + 477 + ret = snd_soc_component_write_field(comp, RTQ9128_REG_I2S_OPT, RTQ9128_AUDFMT_MASK, audfmt); 478 + return ret < 0 ? ret : 0; 479 + } 480 + 481 + static int rtq9128_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 482 + unsigned int rx_mask, int slots, int slot_width) 483 + { 484 + struct rtq9128_data *data = snd_soc_dai_get_drvdata(dai); 485 + struct snd_soc_component *comp = dai->component; 486 + struct device *dev = dai->dev; 487 + unsigned int mask, start_loc; 488 + int i, frame_length, ret; 489 + 490 + dev_dbg(dev, "%s: slot %d slot_width %d, tx/rx mask 0x%x 0x%x\n", __func__, slots, 491 + slot_width, tx_mask, rx_mask); 492 + 493 + if (slots <= 0 || slot_width <= 0 || slot_width % 8) { 494 + dev_err(dev, "Invalid slot numbers (%d) or width (%d)\n", slots, slot_width); 495 + return -EINVAL; 496 + } 497 + 498 + /* HW supported maximum frame length 512 */ 499 + frame_length = slots * slot_width; 500 + if (frame_length > 512) { 501 + dev_err(dev, "frame length exceed the maximum (%d)\n", frame_length); 502 + return -EINVAL; 503 + } 504 + 505 + if (!rx_mask || hweight_long(tx_mask) > slots || hweight_long(rx_mask) > slots || 506 + fls(tx_mask) > slots || fls(rx_mask) > slots) { 507 + dev_err(dev, "Invalid tx/rx mask (0x%x/0x%x)\n", tx_mask, rx_mask); 508 + return -EINVAL; 509 + } 510 + 511 + for (mask = tx_mask, i = 0; i < 4 && mask; i++) { 512 + start_loc = (ffs(mask) - 1) * slot_width / 8; 513 + mask &= ~BIT(ffs(mask) - 1); 514 + 515 + ret = snd_soc_component_write(comp, RTQ9128_REG_TDM_TX_CH1 + i, start_loc); 516 + if (ret < 0) { 517 + dev_err(dev, "Failed to assign tx_loc %d (%d)\n", i, ret); 518 + return ret; 519 + } 520 + } 521 + 522 + for (mask = rx_mask, i = 0; i < 4 && mask; i++) { 523 + start_loc = (ffs(mask) - 1) * slot_width / 8; 524 + mask &= ~BIT(ffs(mask) - 1); 525 + 526 + ret = snd_soc_component_write(comp, RTQ9128_REG_TDM_RX_CH1 + i, start_loc); 527 + if (ret < 0) { 528 + dev_err(dev, "Failed to assign rx_loc %d (%d)\n", i, ret); 529 + return ret; 530 + } 531 + } 532 + 533 + data->tdm_slots = slots; 534 + data->tdm_slot_width = slot_width; 535 + 536 + return 0; 537 + } 538 + 539 + static int rtq9128_dai_hw_params(struct snd_pcm_substream *stream, struct snd_pcm_hw_params *param, 540 + struct snd_soc_dai *dai) 541 + { 542 + struct rtq9128_data *data = snd_soc_dai_get_drvdata(dai); 543 + unsigned int width, slot_width, bitrate, audbit, dolen; 544 + struct snd_soc_component *comp = dai->component; 545 + struct device *dev = dai->dev; 546 + int ret; 547 + 548 + dev_dbg(dev, "%s: width %d\n", __func__, params_width(param)); 549 + 550 + switch (width = params_width(param)) { 551 + case 16: 552 + audbit = 0; 553 + break; 554 + case 18: 555 + audbit = 1; 556 + break; 557 + case 20: 558 + audbit = 2; 559 + break; 560 + case 24: 561 + case 32: 562 + audbit = 3; 563 + break; 564 + default: 565 + dev_err(dev, "Unsupported width (%d)\n", width); 566 + return -EINVAL; 567 + } 568 + 569 + slot_width = params_physical_width(param); 570 + 571 + if (data->tdm_slots) { 572 + if (slot_width > data->tdm_slot_width) { 573 + dev_err(dev, "slot width is larger than TDM slot width\n"); 574 + return -EINVAL; 575 + } 576 + 577 + /* Check BCK not exceed the maximum supported rate 24.576MHz */ 578 + bitrate = data->tdm_slots * data->tdm_slot_width * params_rate(param); 579 + if (bitrate > 24576000) { 580 + dev_err(dev, "bitrate exceed the maximum (%d)\n", bitrate); 581 + return -EINVAL; 582 + } 583 + 584 + /* If TDM is used, configure slot width as TDM slot witdh */ 585 + slot_width = data->tdm_slot_width; 586 + } 587 + 588 + switch (slot_width) { 589 + case 16: 590 + dolen = 0; 591 + break; 592 + case 24: 593 + dolen = 1; 594 + break; 595 + case 32: 596 + dolen = 2; 597 + break; 598 + default: 599 + dev_err(dev, "Unsupported slot width (%d)\n", slot_width); 600 + return -EINVAL; 601 + } 602 + 603 + ret = snd_soc_component_write_field(comp, RTQ9128_REG_I2S_OPT, RTQ9128_AUDBIT_MASK, audbit); 604 + if (ret < 0) 605 + return ret; 606 + 607 + ret = snd_soc_component_write_field(comp, RTQ9128_REG_SDO_SEL, RTQ9128_DOLEN_MASK, dolen); 608 + return ret < 0 ? ret : 0; 609 + } 610 + 611 + static int rtq9128_dai_mute_stream(struct snd_soc_dai *dai, int mute, int stream) 612 + { 613 + struct snd_soc_component *comp = dai->component; 614 + struct device *dev = dai->dev; 615 + int ret; 616 + 617 + dev_dbg(dev, "%s: mute (%d), stream (%d)\n", __func__, mute, stream); 618 + 619 + ret = snd_soc_component_write_field(comp, RTQ9128_REG_DSP_EN, RTQ9128_MSMUTE_MASK, 620 + mute ? 1 : 0); 621 + return ret < 0 ? ret : 0; 622 + } 623 + 624 + static const struct snd_soc_dai_ops rtq9128_dai_ops = { 625 + .set_fmt = rtq9128_dai_set_fmt, 626 + .set_tdm_slot = rtq9128_dai_set_tdm_slot, 627 + .hw_params = rtq9128_dai_hw_params, 628 + .mute_stream = rtq9128_dai_mute_stream, 629 + .no_capture_mute = 1, 630 + }; 631 + 632 + #define RTQ9128_FMTS_MASK (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\ 633 + SNDRV_PCM_FMTBIT_S20_LE | SNDRV_PCM_FMTBIT_S24_LE |\ 634 + SNDRV_PCM_FMTBIT_S32_LE) 635 + 636 + static struct snd_soc_dai_driver rtq9128_dai = { 637 + .name = "rtq9128-aif", 638 + .playback = { 639 + .stream_name = "Playback", 640 + .rates = SNDRV_PCM_RATE_8000_192000, 641 + .formats = RTQ9128_FMTS_MASK, 642 + .channels_min = 1, 643 + .channels_max = 4, 644 + }, 645 + .capture = { 646 + .stream_name = "Capture", 647 + .rates = SNDRV_PCM_RATE_8000_192000, 648 + .formats = RTQ9128_FMTS_MASK, 649 + .channels_min = 1, 650 + .channels_max = 4, 651 + }, 652 + .ops = &rtq9128_dai_ops, 653 + .symmetric_rate = 1, 654 + .symmetric_sample_bits = 1, 655 + }; 656 + 657 + static int rtq9128_probe(struct i2c_client *i2c) 658 + { 659 + struct device *dev = &i2c->dev; 660 + struct rtq9128_data *data; 661 + struct regmap *regmap; 662 + unsigned int venid; 663 + int ret; 664 + 665 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 666 + if (!data) 667 + return -ENOMEM; 668 + 669 + data->enable = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); 670 + if (IS_ERR(data->enable)) 671 + return dev_err_probe(dev, PTR_ERR(data->enable), "Failed to get 'enable' gpio\n"); 672 + else if (data->enable) 673 + usleep_range(10000, 11000); 674 + 675 + i2c_set_clientdata(i2c, data); 676 + 677 + /* 678 + * Due to the bad design to combine SOFT_RESET bit with other function, 679 + * directly use generic i2c API to trigger SOFT_RESET. 680 + */ 681 + ret = i2c_smbus_write_byte_data(i2c, RTQ9128_REG_MISC, RTQ9128_SOFT_RESET_VAL); 682 + if (ret) 683 + return dev_err_probe(dev, ret, "Failed to trigger software reset\n"); 684 + 685 + /* After trigger soft reset, have to wait 10ms for digital reset done */ 686 + usleep_range(10000, 11000); 687 + 688 + regmap = devm_regmap_init(dev, &rtq9128_regmap_bus, dev, &rtq9128_regmap_config); 689 + if (IS_ERR(regmap)) 690 + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n"); 691 + 692 + ret = regmap_read(regmap, RTQ9128_REG_VENDOR_ID, &venid); 693 + if (ret) 694 + return dev_err_probe(dev, ret, "Failed to get vendor id\n"); 695 + 696 + venid = FIELD_GET(RTQ9128_VENDOR_ID_MASK, venid); 697 + if (venid != RTQ9128_VENDOR_ID_VAL) 698 + return dev_err_probe(dev, -ENODEV, "Vendor ID not match (0x%x)\n", venid); 699 + 700 + pm_runtime_set_active(dev); 701 + pm_runtime_mark_last_busy(dev); 702 + ret = devm_pm_runtime_enable(dev); 703 + if (ret) 704 + return dev_err_probe(dev, ret, "Failed to enable pm runtime\n"); 705 + 706 + return devm_snd_soc_register_component(dev, &rtq9128_comp_driver, &rtq9128_dai, 1); 707 + } 708 + 709 + static int __maybe_unused rtq9128_pm_runtime_suspend(struct device *dev) 710 + { 711 + struct rtq9128_data *data = dev_get_drvdata(dev); 712 + struct regmap *regmap = dev_get_regmap(dev, NULL); 713 + 714 + /* If 'enable' gpio not specified, change all channels to ultra low quiescent */ 715 + if (!data->enable) 716 + return regmap_write(regmap, RTQ9128_REG_STATE_CTRL, RTQ9128_ALLCH_ULQM_VAL); 717 + 718 + gpiod_set_value_cansleep(data->enable, 0); 719 + 720 + regcache_cache_only(regmap, true); 721 + regcache_mark_dirty(regmap); 722 + 723 + return 0; 724 + } 725 + 726 + static int __maybe_unused rtq9128_pm_runtime_resume(struct device *dev) 727 + { 728 + struct rtq9128_data *data = dev_get_drvdata(dev); 729 + struct regmap *regmap = dev_get_regmap(dev, NULL); 730 + 731 + /* If 'enable' gpio not specified, change all channels to default Hi-Z */ 732 + if (!data->enable) 733 + return regmap_write(regmap, RTQ9128_REG_STATE_CTRL, RTQ9128_ALLCH_HIZ_VAL); 734 + 735 + gpiod_set_value_cansleep(data->enable, 1); 736 + 737 + /* Wait digital block to be ready */ 738 + usleep_range(10000, 11000); 739 + 740 + regcache_cache_only(regmap, false); 741 + return regcache_sync(regmap); 742 + } 743 + 744 + static const struct dev_pm_ops __maybe_unused rtq9128_pm_ops = { 745 + SET_RUNTIME_PM_OPS(rtq9128_pm_runtime_suspend, rtq9128_pm_runtime_resume, NULL) 746 + }; 747 + 748 + static const struct of_device_id rtq9128_device_table[] = { 749 + { .compatible = "richtek,rtq9128" }, 750 + {} 751 + }; 752 + MODULE_DEVICE_TABLE(of, rtq9128_device_table); 753 + 754 + static struct i2c_driver rtq9128_driver = { 755 + .driver = { 756 + .name = "rtq9128", 757 + .of_match_table = rtq9128_device_table, 758 + .pm = pm_ptr(&rtq9128_pm_ops), 759 + }, 760 + .probe = rtq9128_probe, 761 + }; 762 + module_i2c_driver(rtq9128_driver); 763 + 764 + MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); 765 + MODULE_DESCRIPTION("RTQ9128 4CH Audio Amplifier Driver"); 766 + MODULE_LICENSE("GPL");