976 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * TAS571x amplifier audio driver4 *5 * Copyright (C) 2015 Google, Inc.6 * Copyright (c) 2013 Daniel Mack <zonque@gmail.com>7 *8 * TAS5721 support:9 * Copyright (C) 2016 Petr Kulhavy, Barix AG <petr@barix.com>10 *11 * TAS5707 support:12 * Copyright (C) 2018 Jerome Brunet, Baylibre SAS <jbrunet@baylibre.com>13 */14 15#include <linux/clk.h>16#include <linux/delay.h>17#include <linux/device.h>18#include <linux/gpio/consumer.h>19#include <linux/i2c.h>20#include <linux/init.h>21#include <linux/kernel.h>22#include <linux/module.h>23#include <linux/of.h>24#include <linux/regmap.h>25#include <linux/regulator/consumer.h>26#include <linux/stddef.h>27#include <sound/pcm_params.h>28#include <sound/soc.h>29#include <sound/tlv.h>30#include <linux/unaligned.h>31 32#include "tas571x.h"33 34#define TAS571X_MAX_SUPPLIES 635 36struct tas571x_chip {37 const char *const *supply_names;38 int num_supply_names;39 const struct snd_kcontrol_new *controls;40 int num_controls;41 const struct regmap_config *regmap_config;42 int vol_reg_size;43};44 45struct tas571x_private {46 const struct tas571x_chip *chip;47 struct regmap *regmap;48 struct regulator_bulk_data supplies[TAS571X_MAX_SUPPLIES];49 struct clk *mclk;50 unsigned int format;51 struct gpio_desc *reset_gpio;52 struct gpio_desc *pdn_gpio;53 struct snd_soc_component_driver component_driver;54};55 56static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg)57{58 switch (reg) {59 case TAS571X_MVOL_REG:60 case TAS571X_CH1_VOL_REG:61 case TAS571X_CH2_VOL_REG:62 return priv->chip->vol_reg_size;63 case TAS571X_INPUT_MUX_REG:64 case TAS571X_CH4_SRC_SELECT_REG:65 case TAS571X_PWM_MUX_REG:66 case TAS5717_CH1_RIGHT_CH_MIX_REG:67 case TAS5717_CH1_LEFT_CH_MIX_REG:68 case TAS5717_CH2_LEFT_CH_MIX_REG:69 case TAS5717_CH2_RIGHT_CH_MIX_REG:70 return 4;71 default:72 return 1;73 }74}75 76static int tas571x_reg_write(void *context, unsigned int reg,77 unsigned int value)78{79 struct i2c_client *client = context;80 struct tas571x_private *priv = i2c_get_clientdata(client);81 unsigned int i, size;82 uint8_t buf[5];83 int ret;84 85 size = tas571x_register_size(priv, reg);86 buf[0] = reg;87 88 for (i = size; i >= 1; --i) {89 buf[i] = value;90 value >>= 8;91 }92 93 ret = i2c_master_send(client, buf, size + 1);94 if (ret == size + 1)95 return 0;96 else if (ret < 0)97 return ret;98 else99 return -EIO;100}101 102static int tas571x_reg_read(void *context, unsigned int reg,103 unsigned int *value)104{105 struct i2c_client *client = context;106 struct tas571x_private *priv = i2c_get_clientdata(client);107 uint8_t send_buf, recv_buf[4];108 struct i2c_msg msgs[2];109 unsigned int size;110 unsigned int i;111 int ret;112 113 size = tas571x_register_size(priv, reg);114 send_buf = reg;115 116 msgs[0].addr = client->addr;117 msgs[0].len = sizeof(send_buf);118 msgs[0].buf = &send_buf;119 msgs[0].flags = 0;120 121 msgs[1].addr = client->addr;122 msgs[1].len = size;123 msgs[1].buf = recv_buf;124 msgs[1].flags = I2C_M_RD;125 126 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));127 if (ret < 0)128 return ret;129 else if (ret != ARRAY_SIZE(msgs))130 return -EIO;131 132 *value = 0;133 134 for (i = 0; i < size; i++) {135 *value <<= 8;136 *value |= recv_buf[i];137 }138 139 return 0;140}141 142/*143 * register write for 8- and 20-byte registers144 */145static int tas571x_reg_write_multiword(struct i2c_client *client,146 unsigned int reg, const long values[], size_t len)147{148 size_t i;149 uint8_t *buf, *p;150 int ret;151 size_t send_size = 1 + len * sizeof(uint32_t);152 153 buf = kzalloc(send_size, GFP_KERNEL | GFP_DMA);154 if (!buf)155 return -ENOMEM;156 buf[0] = reg;157 158 for (i = 0, p = buf + 1; i < len; i++, p += sizeof(uint32_t))159 put_unaligned_be32(values[i], p);160 161 ret = i2c_master_send(client, buf, send_size);162 163 kfree(buf);164 165 if (ret == send_size)166 return 0;167 else if (ret < 0)168 return ret;169 else170 return -EIO;171}172 173/*174 * register read for 8- and 20-byte registers175 */176static int tas571x_reg_read_multiword(struct i2c_client *client,177 unsigned int reg, long values[], size_t len)178{179 unsigned int i;180 uint8_t send_buf;181 uint8_t *recv_buf, *p;182 struct i2c_msg msgs[2];183 unsigned int recv_size = len * sizeof(uint32_t);184 int ret;185 186 recv_buf = kzalloc(recv_size, GFP_KERNEL | GFP_DMA);187 if (!recv_buf)188 return -ENOMEM;189 190 send_buf = reg;191 192 msgs[0].addr = client->addr;193 msgs[0].len = sizeof(send_buf);194 msgs[0].buf = &send_buf;195 msgs[0].flags = 0;196 197 msgs[1].addr = client->addr;198 msgs[1].len = recv_size;199 msgs[1].buf = recv_buf;200 msgs[1].flags = I2C_M_RD;201 202 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));203 if (ret < 0)204 goto err_ret;205 else if (ret != ARRAY_SIZE(msgs)) {206 ret = -EIO;207 goto err_ret;208 }209 210 for (i = 0, p = recv_buf; i < len; i++, p += sizeof(uint32_t))211 values[i] = get_unaligned_be32(p);212 213err_ret:214 kfree(recv_buf);215 return ret;216}217 218/*219 * Integer array controls for setting biquad, mixer, DRC coefficients.220 * According to the datasheet each coefficient is effectively 26bits,221 * i.e. stored as 32bits, where bits [31:26] are ignored.222 * TI's TAS57xx Graphical Development Environment tool however produces223 * coefficients with more than 26 bits. For this reason we allow values224 * in the full 32-bits reange.225 * The coefficients are ordered as given in the TAS571x data sheet:226 * b0, b1, b2, a1, a2227 */228 229static int tas571x_coefficient_info(struct snd_kcontrol *kcontrol,230 struct snd_ctl_elem_info *uinfo)231{232 int numcoef = kcontrol->private_value >> 16;233 234 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;235 uinfo->count = numcoef;236 uinfo->value.integer.min = 0;237 uinfo->value.integer.max = 0xffffffff;238 return 0;239}240 241static int tas571x_coefficient_get(struct snd_kcontrol *kcontrol,242 struct snd_ctl_elem_value *ucontrol)243{244 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);245 struct i2c_client *i2c = to_i2c_client(component->dev);246 int numcoef = kcontrol->private_value >> 16;247 int index = kcontrol->private_value & 0xffff;248 249 return tas571x_reg_read_multiword(i2c, index,250 ucontrol->value.integer.value, numcoef);251}252 253static int tas571x_coefficient_put(struct snd_kcontrol *kcontrol,254 struct snd_ctl_elem_value *ucontrol)255{256 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);257 struct i2c_client *i2c = to_i2c_client(component->dev);258 int numcoef = kcontrol->private_value >> 16;259 int index = kcontrol->private_value & 0xffff;260 261 return tas571x_reg_write_multiword(i2c, index,262 ucontrol->value.integer.value, numcoef);263}264 265static int tas571x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)266{267 struct tas571x_private *priv = snd_soc_component_get_drvdata(dai->component);268 269 priv->format = format;270 271 return 0;272}273 274static int tas571x_hw_params(struct snd_pcm_substream *substream,275 struct snd_pcm_hw_params *params,276 struct snd_soc_dai *dai)277{278 struct tas571x_private *priv = snd_soc_component_get_drvdata(dai->component);279 u32 val;280 281 switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {282 case SND_SOC_DAIFMT_RIGHT_J:283 val = 0x00;284 break;285 case SND_SOC_DAIFMT_I2S:286 val = 0x03;287 break;288 case SND_SOC_DAIFMT_LEFT_J:289 val = 0x06;290 break;291 default:292 return -EINVAL;293 }294 295 if (params_width(params) >= 24)296 val += 2;297 else if (params_width(params) >= 20)298 val += 1;299 300 return regmap_update_bits(priv->regmap, TAS571X_SDI_REG,301 TAS571X_SDI_FMT_MASK, val);302}303 304static int tas571x_mute(struct snd_soc_dai *dai, int mute, int direction)305{306 struct snd_soc_component *component = dai->component;307 u8 sysctl2;308 int ret;309 310 sysctl2 = mute ? TAS571X_SYS_CTRL_2_SDN_MASK : 0;311 312 ret = snd_soc_component_update_bits(component,313 TAS571X_SYS_CTRL_2_REG,314 TAS571X_SYS_CTRL_2_SDN_MASK,315 sysctl2);316 usleep_range(1000, 2000);317 318 return ret;319}320 321static int tas571x_set_bias_level(struct snd_soc_component *component,322 enum snd_soc_bias_level level)323{324 struct tas571x_private *priv = snd_soc_component_get_drvdata(component);325 int ret;326 327 switch (level) {328 case SND_SOC_BIAS_ON:329 break;330 case SND_SOC_BIAS_PREPARE:331 break;332 case SND_SOC_BIAS_STANDBY:333 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {334 if (!IS_ERR(priv->mclk)) {335 ret = clk_prepare_enable(priv->mclk);336 if (ret) {337 dev_err(component->dev,338 "Failed to enable master clock: %d\n",339 ret);340 return ret;341 }342 }343 }344 break;345 case SND_SOC_BIAS_OFF:346 if (!IS_ERR(priv->mclk))347 clk_disable_unprepare(priv->mclk);348 break;349 }350 351 return 0;352}353 354static const struct snd_soc_dai_ops tas571x_dai_ops = {355 .set_fmt = tas571x_set_dai_fmt,356 .hw_params = tas571x_hw_params,357 .mute_stream = tas571x_mute,358 .no_capture_mute = 1,359};360 361 362#define BIQUAD_COEFS(xname, reg) \363{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \364 .info = tas571x_coefficient_info, \365 .get = tas571x_coefficient_get,\366 .put = tas571x_coefficient_put, \367 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \368 .private_value = reg | (5 << 16) }369 370static const char *const tas5711_supply_names[] = {371 "AVDD",372 "DVDD",373 "PVDD_A",374 "PVDD_B",375 "PVDD_C",376 "PVDD_D",377};378 379static const DECLARE_TLV_DB_SCALE(tas5711_volume_tlv, -10350, 50, 1);380 381static const struct snd_kcontrol_new tas5711_controls[] = {382 SOC_SINGLE_TLV("Master Volume",383 TAS571X_MVOL_REG,384 0, 0xff, 1, tas5711_volume_tlv),385 SOC_DOUBLE_R_TLV("Speaker Volume",386 TAS571X_CH1_VOL_REG,387 TAS571X_CH2_VOL_REG,388 0, 0xff, 1, tas5711_volume_tlv),389 SOC_DOUBLE("Speaker Switch",390 TAS571X_SOFT_MUTE_REG,391 TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,392 1, 1),393};394 395static const struct regmap_range tas571x_readonly_regs_range[] = {396 regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_DEV_ID_REG),397};398 399static const struct regmap_range tas571x_volatile_regs_range[] = {400 regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_ERR_STATUS_REG),401 regmap_reg_range(TAS571X_OSC_TRIM_REG, TAS571X_OSC_TRIM_REG),402};403 404static const struct regmap_access_table tas571x_write_regs = {405 .no_ranges = tas571x_readonly_regs_range,406 .n_no_ranges = ARRAY_SIZE(tas571x_readonly_regs_range),407};408 409static const struct regmap_access_table tas571x_volatile_regs = {410 .yes_ranges = tas571x_volatile_regs_range,411 .n_yes_ranges = ARRAY_SIZE(tas571x_volatile_regs_range),412 413};414 415static const struct reg_default tas5711_reg_defaults[] = {416 { 0x04, 0x05 },417 { 0x05, 0x40 },418 { 0x06, 0x00 },419 { 0x07, 0xff },420 { 0x08, 0x30 },421 { 0x09, 0x30 },422 { 0x1b, 0x82 },423};424 425static const struct regmap_config tas5711_regmap_config = {426 .reg_bits = 8,427 .val_bits = 32,428 .max_register = 0xff,429 .reg_read = tas571x_reg_read,430 .reg_write = tas571x_reg_write,431 .reg_defaults = tas5711_reg_defaults,432 .num_reg_defaults = ARRAY_SIZE(tas5711_reg_defaults),433 .cache_type = REGCACHE_RBTREE,434 .wr_table = &tas571x_write_regs,435 .volatile_table = &tas571x_volatile_regs,436};437 438static const struct tas571x_chip tas5711_chip = {439 .supply_names = tas5711_supply_names,440 .num_supply_names = ARRAY_SIZE(tas5711_supply_names),441 .controls = tas5711_controls,442 .num_controls = ARRAY_SIZE(tas5711_controls),443 .regmap_config = &tas5711_regmap_config,444 .vol_reg_size = 1,445};446 447static const struct regmap_range tas5707_volatile_regs_range[] = {448 regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_ERR_STATUS_REG),449 regmap_reg_range(TAS571X_OSC_TRIM_REG, TAS571X_OSC_TRIM_REG),450 regmap_reg_range(TAS5707_CH1_BQ0_REG, TAS5707_CH2_BQ6_REG),451};452 453static const struct regmap_access_table tas5707_volatile_regs = {454 .yes_ranges = tas5707_volatile_regs_range,455 .n_yes_ranges = ARRAY_SIZE(tas5707_volatile_regs_range),456 457};458 459static const DECLARE_TLV_DB_SCALE(tas5707_volume_tlv, -7900, 50, 1);460 461static const char * const tas5707_volume_slew_step_txt[] = {462 "256", "512", "1024", "2048",463};464 465static const unsigned int tas5707_volume_slew_step_values[] = {466 3, 0, 1, 2,467};468 469static SOC_VALUE_ENUM_SINGLE_DECL(tas5707_volume_slew_step_enum,470 TAS571X_VOL_CFG_REG, 0, 0x3,471 tas5707_volume_slew_step_txt,472 tas5707_volume_slew_step_values);473 474static const struct snd_kcontrol_new tas5707_controls[] = {475 SOC_SINGLE_TLV("Master Volume",476 TAS571X_MVOL_REG,477 0, 0xff, 1, tas5707_volume_tlv),478 SOC_DOUBLE_R_TLV("Speaker Volume",479 TAS571X_CH1_VOL_REG,480 TAS571X_CH2_VOL_REG,481 0, 0xff, 1, tas5707_volume_tlv),482 SOC_DOUBLE("Speaker Switch",483 TAS571X_SOFT_MUTE_REG,484 TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,485 1, 1),486 487 SOC_ENUM("Slew Rate Steps", tas5707_volume_slew_step_enum),488 489 BIQUAD_COEFS("CH1 - Biquad 0", TAS5707_CH1_BQ0_REG),490 BIQUAD_COEFS("CH1 - Biquad 1", TAS5707_CH1_BQ1_REG),491 BIQUAD_COEFS("CH1 - Biquad 2", TAS5707_CH1_BQ2_REG),492 BIQUAD_COEFS("CH1 - Biquad 3", TAS5707_CH1_BQ3_REG),493 BIQUAD_COEFS("CH1 - Biquad 4", TAS5707_CH1_BQ4_REG),494 BIQUAD_COEFS("CH1 - Biquad 5", TAS5707_CH1_BQ5_REG),495 BIQUAD_COEFS("CH1 - Biquad 6", TAS5707_CH1_BQ6_REG),496 497 BIQUAD_COEFS("CH2 - Biquad 0", TAS5707_CH2_BQ0_REG),498 BIQUAD_COEFS("CH2 - Biquad 1", TAS5707_CH2_BQ1_REG),499 BIQUAD_COEFS("CH2 - Biquad 2", TAS5707_CH2_BQ2_REG),500 BIQUAD_COEFS("CH2 - Biquad 3", TAS5707_CH2_BQ3_REG),501 BIQUAD_COEFS("CH2 - Biquad 4", TAS5707_CH2_BQ4_REG),502 BIQUAD_COEFS("CH2 - Biquad 5", TAS5707_CH2_BQ5_REG),503 BIQUAD_COEFS("CH2 - Biquad 6", TAS5707_CH2_BQ6_REG),504};505 506static const struct reg_default tas5707_reg_defaults[] = {507 {TAS571X_CLK_CTRL_REG, 0x6c},508 {TAS571X_DEV_ID_REG, 0x70},509 {TAS571X_ERR_STATUS_REG, 0x00},510 {TAS571X_SYS_CTRL_1_REG, 0xa0},511 {TAS571X_SDI_REG, 0x05},512 {TAS571X_SYS_CTRL_2_REG, 0x40},513 {TAS571X_SOFT_MUTE_REG, 0x00},514 {TAS571X_MVOL_REG, 0xff},515 {TAS571X_CH1_VOL_REG, 0x30},516 {TAS571X_CH2_VOL_REG, 0x30},517 {TAS571X_VOL_CFG_REG, 0x91},518 {TAS571X_MODULATION_LIMIT_REG, 0x02},519 {TAS571X_IC_DELAY_CH1_REG, 0xac},520 {TAS571X_IC_DELAY_CH2_REG, 0x54},521 {TAS571X_IC_DELAY_CH3_REG, 0xac},522 {TAS571X_IC_DELAY_CH4_REG, 0x54},523 {TAS571X_START_STOP_PERIOD_REG, 0x0f},524 {TAS571X_OSC_TRIM_REG, 0x82},525 {TAS571X_BKND_ERR_REG, 0x02},526 {TAS571X_INPUT_MUX_REG, 0x17772},527 {TAS571X_PWM_MUX_REG, 0x1021345},528};529 530static const struct regmap_config tas5707_regmap_config = {531 .reg_bits = 8,532 .val_bits = 32,533 .max_register = 0xff,534 .reg_read = tas571x_reg_read,535 .reg_write = tas571x_reg_write,536 .reg_defaults = tas5707_reg_defaults,537 .num_reg_defaults = ARRAY_SIZE(tas5707_reg_defaults),538 .cache_type = REGCACHE_RBTREE,539 .wr_table = &tas571x_write_regs,540 .volatile_table = &tas5707_volatile_regs,541};542 543static const struct tas571x_chip tas5707_chip = {544 .supply_names = tas5711_supply_names,545 .num_supply_names = ARRAY_SIZE(tas5711_supply_names),546 .controls = tas5707_controls,547 .num_controls = ARRAY_SIZE(tas5707_controls),548 .regmap_config = &tas5707_regmap_config,549 .vol_reg_size = 1,550};551 552static const char *const tas5717_supply_names[] = {553 "AVDD",554 "DVDD",555 "HPVDD",556 "PVDD_AB",557 "PVDD_CD",558};559 560static const DECLARE_TLV_DB_SCALE(tas5717_volume_tlv, -10375, 25, 0);561 562static const struct snd_kcontrol_new tas5717_controls[] = {563 /* MVOL LSB is ignored - see comments in tas571x_i2c_probe() */564 SOC_SINGLE_TLV("Master Volume",565 TAS571X_MVOL_REG, 1, 0x1ff, 1,566 tas5717_volume_tlv),567 SOC_DOUBLE_R_TLV("Speaker Volume",568 TAS571X_CH1_VOL_REG, TAS571X_CH2_VOL_REG,569 1, 0x1ff, 1, tas5717_volume_tlv),570 SOC_DOUBLE("Speaker Switch",571 TAS571X_SOFT_MUTE_REG,572 TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,573 1, 1),574 575 SOC_DOUBLE_R_RANGE("CH1 Mixer Volume",576 TAS5717_CH1_LEFT_CH_MIX_REG,577 TAS5717_CH1_RIGHT_CH_MIX_REG,578 16, 0, 0x80, 0),579 580 SOC_DOUBLE_R_RANGE("CH2 Mixer Volume",581 TAS5717_CH2_LEFT_CH_MIX_REG,582 TAS5717_CH2_RIGHT_CH_MIX_REG,583 16, 0, 0x80, 0),584 585 /*586 * The biquads are named according to the register names.587 * Please note that TI's TAS57xx Graphical Development Environment588 * tool names them different.589 */590 BIQUAD_COEFS("CH1 - Biquad 0", TAS5717_CH1_BQ0_REG),591 BIQUAD_COEFS("CH1 - Biquad 1", TAS5717_CH1_BQ1_REG),592 BIQUAD_COEFS("CH1 - Biquad 2", TAS5717_CH1_BQ2_REG),593 BIQUAD_COEFS("CH1 - Biquad 3", TAS5717_CH1_BQ3_REG),594 BIQUAD_COEFS("CH1 - Biquad 4", TAS5717_CH1_BQ4_REG),595 BIQUAD_COEFS("CH1 - Biquad 5", TAS5717_CH1_BQ5_REG),596 BIQUAD_COEFS("CH1 - Biquad 6", TAS5717_CH1_BQ6_REG),597 BIQUAD_COEFS("CH1 - Biquad 7", TAS5717_CH1_BQ7_REG),598 BIQUAD_COEFS("CH1 - Biquad 8", TAS5717_CH1_BQ8_REG),599 BIQUAD_COEFS("CH1 - Biquad 9", TAS5717_CH1_BQ9_REG),600 BIQUAD_COEFS("CH1 - Biquad 10", TAS5717_CH1_BQ10_REG),601 BIQUAD_COEFS("CH1 - Biquad 11", TAS5717_CH1_BQ11_REG),602 603 BIQUAD_COEFS("CH2 - Biquad 0", TAS5717_CH2_BQ0_REG),604 BIQUAD_COEFS("CH2 - Biquad 1", TAS5717_CH2_BQ1_REG),605 BIQUAD_COEFS("CH2 - Biquad 2", TAS5717_CH2_BQ2_REG),606 BIQUAD_COEFS("CH2 - Biquad 3", TAS5717_CH2_BQ3_REG),607 BIQUAD_COEFS("CH2 - Biquad 4", TAS5717_CH2_BQ4_REG),608 BIQUAD_COEFS("CH2 - Biquad 5", TAS5717_CH2_BQ5_REG),609 BIQUAD_COEFS("CH2 - Biquad 6", TAS5717_CH2_BQ6_REG),610 BIQUAD_COEFS("CH2 - Biquad 7", TAS5717_CH2_BQ7_REG),611 BIQUAD_COEFS("CH2 - Biquad 8", TAS5717_CH2_BQ8_REG),612 BIQUAD_COEFS("CH2 - Biquad 9", TAS5717_CH2_BQ9_REG),613 BIQUAD_COEFS("CH2 - Biquad 10", TAS5717_CH2_BQ10_REG),614 BIQUAD_COEFS("CH2 - Biquad 11", TAS5717_CH2_BQ11_REG),615 616 BIQUAD_COEFS("CH3 - Biquad 0", TAS5717_CH3_BQ0_REG),617 BIQUAD_COEFS("CH3 - Biquad 1", TAS5717_CH3_BQ1_REG),618 619 BIQUAD_COEFS("CH4 - Biquad 0", TAS5717_CH4_BQ0_REG),620 BIQUAD_COEFS("CH4 - Biquad 1", TAS5717_CH4_BQ1_REG),621};622 623static const struct reg_default tas5717_reg_defaults[] = {624 { 0x04, 0x05 },625 { 0x05, 0x40 },626 { 0x06, 0x00 },627 { 0x07, 0x03ff },628 { 0x08, 0x00c0 },629 { 0x09, 0x00c0 },630 { 0x1b, 0x82 },631 { TAS5717_CH1_RIGHT_CH_MIX_REG, 0x0 },632 { TAS5717_CH1_LEFT_CH_MIX_REG, 0x800000},633 { TAS5717_CH2_LEFT_CH_MIX_REG, 0x0 },634 { TAS5717_CH2_RIGHT_CH_MIX_REG, 0x800000},635};636 637static const struct regmap_config tas5717_regmap_config = {638 .reg_bits = 8,639 .val_bits = 32,640 .max_register = 0xff,641 .reg_read = tas571x_reg_read,642 .reg_write = tas571x_reg_write,643 .reg_defaults = tas5717_reg_defaults,644 .num_reg_defaults = ARRAY_SIZE(tas5717_reg_defaults),645 .cache_type = REGCACHE_RBTREE,646 .wr_table = &tas571x_write_regs,647 .volatile_table = &tas571x_volatile_regs,648};649 650/* This entry is reused for tas5719 as the software interface is identical. */651static const struct tas571x_chip tas5717_chip = {652 .supply_names = tas5717_supply_names,653 .num_supply_names = ARRAY_SIZE(tas5717_supply_names),654 .controls = tas5717_controls,655 .num_controls = ARRAY_SIZE(tas5717_controls),656 .regmap_config = &tas5717_regmap_config,657 .vol_reg_size = 2,658};659 660static const char *const tas5721_supply_names[] = {661 "AVDD",662 "DVDD",663 "DRVDD",664 "PVDD",665};666 667static const struct snd_kcontrol_new tas5721_controls[] = {668 SOC_SINGLE_TLV("Master Volume",669 TAS571X_MVOL_REG,670 0, 0xff, 1, tas5711_volume_tlv),671 SOC_DOUBLE_R_TLV("Speaker Volume",672 TAS571X_CH1_VOL_REG,673 TAS571X_CH2_VOL_REG,674 0, 0xff, 1, tas5711_volume_tlv),675 SOC_DOUBLE("Speaker Switch",676 TAS571X_SOFT_MUTE_REG,677 TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,678 1, 1),679};680 681static const struct reg_default tas5721_reg_defaults[] = {682 {TAS571X_CLK_CTRL_REG, 0x6c},683 {TAS571X_DEV_ID_REG, 0x00},684 {TAS571X_ERR_STATUS_REG, 0x00},685 {TAS571X_SYS_CTRL_1_REG, 0xa0},686 {TAS571X_SDI_REG, 0x05},687 {TAS571X_SYS_CTRL_2_REG, 0x40},688 {TAS571X_SOFT_MUTE_REG, 0x00},689 {TAS571X_MVOL_REG, 0xff},690 {TAS571X_CH1_VOL_REG, 0x30},691 {TAS571X_CH2_VOL_REG, 0x30},692 {TAS571X_CH3_VOL_REG, 0x30},693 {TAS571X_VOL_CFG_REG, 0x91},694 {TAS571X_MODULATION_LIMIT_REG, 0x02},695 {TAS571X_IC_DELAY_CH1_REG, 0xac},696 {TAS571X_IC_DELAY_CH2_REG, 0x54},697 {TAS571X_IC_DELAY_CH3_REG, 0xac},698 {TAS571X_IC_DELAY_CH4_REG, 0x54},699 {TAS571X_PWM_CH_SDN_GROUP_REG, 0x30},700 {TAS571X_START_STOP_PERIOD_REG, 0x0f},701 {TAS571X_OSC_TRIM_REG, 0x82},702 {TAS571X_BKND_ERR_REG, 0x02},703 {TAS571X_INPUT_MUX_REG, 0x17772},704 {TAS571X_CH4_SRC_SELECT_REG, 0x4303},705 {TAS571X_PWM_MUX_REG, 0x1021345},706};707 708static const struct regmap_config tas5721_regmap_config = {709 .reg_bits = 8,710 .val_bits = 32,711 .max_register = 0xff,712 .reg_read = tas571x_reg_read,713 .reg_write = tas571x_reg_write,714 .reg_defaults = tas5721_reg_defaults,715 .num_reg_defaults = ARRAY_SIZE(tas5721_reg_defaults),716 .cache_type = REGCACHE_RBTREE,717 .wr_table = &tas571x_write_regs,718 .volatile_table = &tas571x_volatile_regs,719};720 721static const char *const tas5733_supply_names[] = {722 "AVDD",723 "DVDD",724 "PVDD",725};726 727static const struct reg_default tas5733_reg_defaults[] = {728 {TAS571X_CLK_CTRL_REG, 0x6c},729 {TAS571X_DEV_ID_REG, 0x00},730 {TAS571X_ERR_STATUS_REG, 0x00},731 {TAS571X_SYS_CTRL_1_REG, 0xa0},732 {TAS571X_SDI_REG, 0x05},733 {TAS571X_SYS_CTRL_2_REG, 0x40},734 {TAS571X_SOFT_MUTE_REG, 0x07},735 {TAS571X_MVOL_REG, 0x03ff},736 {TAS571X_CH1_VOL_REG, 0x00c0},737 {TAS571X_CH2_VOL_REG, 0x00c0},738 {TAS571X_CH3_VOL_REG, 0x00c0},739 {TAS571X_VOL_CFG_REG, 0xf0},740 {TAS571X_MODULATION_LIMIT_REG, 0x07},741 {TAS571X_IC_DELAY_CH1_REG, 0xb8},742 {TAS571X_IC_DELAY_CH2_REG, 0x60},743 {TAS571X_IC_DELAY_CH3_REG, 0xa0},744 {TAS571X_IC_DELAY_CH4_REG, 0x48},745 {TAS571X_PWM_CH_SDN_GROUP_REG, 0x30},746 {TAS571X_START_STOP_PERIOD_REG, 0x68},747 {TAS571X_OSC_TRIM_REG, 0x82},748 {TAS571X_BKND_ERR_REG, 0x02},749 {TAS571X_INPUT_MUX_REG, 0x00897772},750 {TAS571X_PWM_MUX_REG, 0x01021345},751 {TAS5717_CH1_RIGHT_CH_MIX_REG, 0x00},752 {TAS5717_CH1_LEFT_CH_MIX_REG, 0x800000},753 {TAS5717_CH2_LEFT_CH_MIX_REG, 0x00},754 {TAS5717_CH2_RIGHT_CH_MIX_REG, 0x800000},755};756 757static const struct regmap_config tas5733_regmap_config = {758 .reg_bits = 8,759 .val_bits = 32,760 .max_register = 0xff,761 .reg_read = tas571x_reg_read,762 .reg_write = tas571x_reg_write,763 .reg_defaults = tas5733_reg_defaults,764 .num_reg_defaults = ARRAY_SIZE(tas5733_reg_defaults),765 .cache_type = REGCACHE_RBTREE,766 .wr_table = &tas571x_write_regs,767 .volatile_table = &tas571x_volatile_regs,768};769 770static const struct tas571x_chip tas5733_chip = {771 .supply_names = tas5733_supply_names,772 .num_supply_names = ARRAY_SIZE(tas5733_supply_names),773 .controls = tas5717_controls,774 .num_controls = ARRAY_SIZE(tas5717_controls),775 .regmap_config = &tas5733_regmap_config,776 .vol_reg_size = 2,777};778 779static const struct tas571x_chip tas5721_chip = {780 .supply_names = tas5721_supply_names,781 .num_supply_names = ARRAY_SIZE(tas5721_supply_names),782 .controls = tas5721_controls,783 .num_controls = ARRAY_SIZE(tas5721_controls),784 .regmap_config = &tas5721_regmap_config,785 .vol_reg_size = 1,786};787 788static const struct snd_soc_dapm_widget tas571x_dapm_widgets[] = {789 SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),790 SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),791 792 SND_SOC_DAPM_OUTPUT("OUT_A"),793 SND_SOC_DAPM_OUTPUT("OUT_B"),794 SND_SOC_DAPM_OUTPUT("OUT_C"),795 SND_SOC_DAPM_OUTPUT("OUT_D"),796};797 798static const struct snd_soc_dapm_route tas571x_dapm_routes[] = {799 { "DACL", NULL, "Playback" },800 { "DACR", NULL, "Playback" },801 802 { "OUT_A", NULL, "DACL" },803 { "OUT_B", NULL, "DACL" },804 { "OUT_C", NULL, "DACR" },805 { "OUT_D", NULL, "DACR" },806};807 808static const struct snd_soc_component_driver tas571x_component = {809 .set_bias_level = tas571x_set_bias_level,810 .dapm_widgets = tas571x_dapm_widgets,811 .num_dapm_widgets = ARRAY_SIZE(tas571x_dapm_widgets),812 .dapm_routes = tas571x_dapm_routes,813 .num_dapm_routes = ARRAY_SIZE(tas571x_dapm_routes),814 .use_pmdown_time = 1,815 .endianness = 1,816};817 818static struct snd_soc_dai_driver tas571x_dai = {819 .name = "tas571x-hifi",820 .playback = {821 .stream_name = "Playback",822 .channels_min = 2,823 .channels_max = 2,824 .rates = SNDRV_PCM_RATE_8000_48000,825 .formats = SNDRV_PCM_FMTBIT_S32_LE |826 SNDRV_PCM_FMTBIT_S24_LE |827 SNDRV_PCM_FMTBIT_S16_LE,828 },829 .ops = &tas571x_dai_ops,830};831 832static int tas571x_i2c_probe(struct i2c_client *client)833{834 struct tas571x_private *priv;835 struct device *dev = &client->dev;836 int i, ret;837 838 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);839 if (!priv)840 return -ENOMEM;841 i2c_set_clientdata(client, priv);842 843 priv->chip = i2c_get_match_data(client);844 845 priv->mclk = devm_clk_get(dev, "mclk");846 if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) {847 dev_err(dev, "Failed to request mclk: %ld\n",848 PTR_ERR(priv->mclk));849 return PTR_ERR(priv->mclk);850 }851 852 if (WARN_ON(priv->chip->num_supply_names > TAS571X_MAX_SUPPLIES))853 return -EINVAL;854 for (i = 0; i < priv->chip->num_supply_names; i++)855 priv->supplies[i].supply = priv->chip->supply_names[i];856 857 ret = devm_regulator_bulk_get(dev, priv->chip->num_supply_names,858 priv->supplies);859 if (ret) {860 dev_err(dev, "Failed to get supplies: %d\n", ret);861 return ret;862 }863 ret = regulator_bulk_enable(priv->chip->num_supply_names,864 priv->supplies);865 if (ret) {866 dev_err(dev, "Failed to enable supplies: %d\n", ret);867 return ret;868 }869 870 priv->regmap = devm_regmap_init(dev, NULL, client,871 priv->chip->regmap_config);872 if (IS_ERR(priv->regmap)) {873 ret = PTR_ERR(priv->regmap);874 goto disable_regs;875 }876 877 priv->pdn_gpio = devm_gpiod_get_optional(dev, "pdn", GPIOD_OUT_LOW);878 if (IS_ERR(priv->pdn_gpio)) {879 dev_err(dev, "error requesting pdn_gpio: %ld\n",880 PTR_ERR(priv->pdn_gpio));881 ret = PTR_ERR(priv->pdn_gpio);882 goto disable_regs;883 }884 885 priv->reset_gpio = devm_gpiod_get_optional(dev, "reset",886 GPIOD_OUT_HIGH);887 if (IS_ERR(priv->reset_gpio)) {888 dev_err(dev, "error requesting reset_gpio: %ld\n",889 PTR_ERR(priv->reset_gpio));890 ret = PTR_ERR(priv->reset_gpio);891 goto disable_regs;892 } else if (priv->reset_gpio) {893 /* pulse the active low reset line for ~100us */894 usleep_range(100, 200);895 gpiod_set_value(priv->reset_gpio, 0);896 usleep_range(13500, 20000);897 }898 899 ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0);900 if (ret)901 goto disable_regs;902 903 usleep_range(50000, 60000);904 905 memcpy(&priv->component_driver, &tas571x_component, sizeof(priv->component_driver));906 priv->component_driver.controls = priv->chip->controls;907 priv->component_driver.num_controls = priv->chip->num_controls;908 909 if (priv->chip->vol_reg_size == 2) {910 /*911 * The master volume defaults to 0x3ff (mute), but we ignore912 * (zero) the LSB because the hardware step size is 0.125 dB913 * and TLV_DB_SCALE_ITEM has a resolution of 0.01 dB.914 */915 ret = regmap_update_bits(priv->regmap, TAS571X_MVOL_REG, 1, 0);916 if (ret)917 goto disable_regs;918 }919 920 ret = devm_snd_soc_register_component(&client->dev,921 &priv->component_driver,922 &tas571x_dai, 1);923 if (ret)924 goto disable_regs;925 926 return ret;927 928disable_regs:929 regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies);930 return ret;931}932 933static void tas571x_i2c_remove(struct i2c_client *client)934{935 struct tas571x_private *priv = i2c_get_clientdata(client);936 937 regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies);938}939 940static const struct of_device_id tas571x_of_match[] __maybe_unused = {941 { .compatible = "ti,tas5707", .data = &tas5707_chip, },942 { .compatible = "ti,tas5711", .data = &tas5711_chip, },943 { .compatible = "ti,tas5717", .data = &tas5717_chip, },944 { .compatible = "ti,tas5719", .data = &tas5717_chip, },945 { .compatible = "ti,tas5721", .data = &tas5721_chip, },946 { .compatible = "ti,tas5733", .data = &tas5733_chip, },947 { }948};949MODULE_DEVICE_TABLE(of, tas571x_of_match);950 951static const struct i2c_device_id tas571x_i2c_id[] = {952 { "tas5707", (kernel_ulong_t) &tas5707_chip },953 { "tas5711", (kernel_ulong_t) &tas5711_chip },954 { "tas5717", (kernel_ulong_t) &tas5717_chip },955 { "tas5719", (kernel_ulong_t) &tas5717_chip },956 { "tas5721", (kernel_ulong_t) &tas5721_chip },957 { "tas5733", (kernel_ulong_t) &tas5733_chip },958 { }959};960MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id);961 962static struct i2c_driver tas571x_i2c_driver = {963 .driver = {964 .name = "tas571x",965 .of_match_table = of_match_ptr(tas571x_of_match),966 },967 .probe = tas571x_i2c_probe,968 .remove = tas571x_i2c_remove,969 .id_table = tas571x_i2c_id,970};971module_i2c_driver(tas571x_i2c_driver);972 973MODULE_DESCRIPTION("ASoC TAS571x driver");974MODULE_AUTHOR("Kevin Cernekee <cernekee@chromium.org>");975MODULE_LICENSE("GPL");976