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

ASoC: codecs: tas5720: add support for TAS5720A-Q1 (automotive) variant

This change adds support the TAS5720A-Q1 audio codec, in the same driver as
tas5720.

Functionally, this driver is pretty similar to it's TAS5720x variant.

The first 3 registers are the same, so the main control and device
identification can happen with these registers.

The next registers differ.
This variant offers control (in the registers) for 2 speakers, which is
implemented here (in a basic manner).

Signed-off-by: Steffen Aschbacher <steffen.aschbacher@stihl.de>
Signed-off-by: Alexandru Ardelean <alex@shruggie.ro>
Link: https://lore.kernel.org/r/20230128082744.41849-2-alex@shruggie.ro
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Steffen Aschbacher and committed by
Mark Brown
c24a62be 879142be

+106 -13
+92 -12
sound/soc/codecs/tas5720.c
··· 30 30 31 31 enum tas572x_type { 32 32 TAS5720, 33 + TAS5720A_Q1, 33 34 TAS5722, 34 35 }; 35 36 ··· 167 166 return -EINVAL; 168 167 } 169 168 170 - /* Enable manual TDM slot selection (instead of I2C ID based) */ 171 - ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL1_REG, 172 - TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC); 173 - if (ret < 0) 174 - goto error_snd_soc_component_update_bits; 169 + /* 170 + * Enable manual TDM slot selection (instead of I2C ID based). 171 + * This is not applicable to TAS5720A-Q1. 172 + */ 173 + switch (tas5720->devtype) { 174 + case TAS5720A_Q1: 175 + break; 176 + default: 177 + ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL1_REG, 178 + TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC); 179 + if (ret < 0) 180 + goto error_snd_soc_component_update_bits; 175 181 176 - /* Configure the TDM slot to process audio from */ 177 - ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG, 178 - TAS5720_TDM_SLOT_SEL_MASK, first_slot); 179 - if (ret < 0) 180 - goto error_snd_soc_component_update_bits; 182 + /* Configure the TDM slot to process audio from */ 183 + ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG, 184 + TAS5720_TDM_SLOT_SEL_MASK, first_slot); 185 + if (ret < 0) 186 + goto error_snd_soc_component_update_bits; 187 + break; 188 + } 181 189 182 190 /* Configure TDM slot width. This is only applicable to TAS5722. */ 183 191 switch (tas5720->devtype) { ··· 211 201 212 202 static int tas5720_mute_soc_component(struct snd_soc_component *component, int mute) 213 203 { 204 + struct tas5720_data *tas5720 = snd_soc_component_get_drvdata(component); 205 + unsigned int reg, mask; 214 206 int ret; 215 207 216 - ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG, 217 - TAS5720_MUTE, mute ? TAS5720_MUTE : 0); 208 + switch (tas5720->devtype) { 209 + case TAS5720A_Q1: 210 + reg = TAS5720_Q1_VOLUME_CTRL_CFG_REG; 211 + mask = TAS5720_Q1_MUTE; 212 + break; 213 + default: 214 + reg = TAS5720_DIGITAL_CTRL2_REG; 215 + mask = TAS5720_MUTE; 216 + break; 217 + } 218 + 219 + ret = snd_soc_component_update_bits(component, reg, mask, mute ? mask : 0); 218 220 if (ret < 0) { 219 221 dev_err(component->dev, "error (un-)muting device: %d\n", ret); 220 222 return ret; ··· 330 308 switch (tas5720->devtype) { 331 309 case TAS5720: 332 310 expected_device_id = TAS5720_DEVICE_ID; 311 + break; 312 + case TAS5720A_Q1: 313 + expected_device_id = TAS5720A_Q1_DEVICE_ID; 333 314 break; 334 315 case TAS5722: 335 316 expected_device_id = TAS5722_DEVICE_ID; ··· 499 474 .volatile_reg = tas5720_is_volatile_reg, 500 475 }; 501 476 477 + static const struct regmap_config tas5720a_q1_regmap_config = { 478 + .reg_bits = 8, 479 + .val_bits = 8, 480 + 481 + .max_register = TAS5720_MAX_REG, 482 + .cache_type = REGCACHE_RBTREE, 483 + .volatile_reg = tas5720_is_volatile_reg, 484 + }; 485 + 502 486 static const struct regmap_config tas5722_regmap_config = { 503 487 .reg_bits = 8, 504 488 .val_bits = 8, ··· 526 492 0x1, 0x1, TLV_DB_SCALE_ITEM(2070, 0, 0), 527 493 0x2, 0x2, TLV_DB_SCALE_ITEM(2350, 0, 0), 528 494 0x3, 0x3, TLV_DB_SCALE_ITEM(2630, 0, 0), 495 + ); 496 + 497 + /* 498 + * DAC analog gain for TAS5720A-Q1. There are three discrete values to select from, ranging 499 + * from 19.2 dB to 25.0dB. 500 + */ 501 + static const DECLARE_TLV_DB_RANGE(dac_analog_tlv_a_q1, 502 + 0x0, 0x0, TLV_DB_SCALE_ITEM(1920, 0, 0), 503 + 0x1, 0x1, TLV_DB_SCALE_ITEM(2260, 0, 0), 504 + 0x2, 0x2, TLV_DB_SCALE_ITEM(2500, 0, 0), 529 505 ); 530 506 531 507 /* ··· 584 540 TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv), 585 541 }; 586 542 543 + static const struct snd_kcontrol_new tas5720a_q1_snd_controls[] = { 544 + SOC_DOUBLE_R_TLV("Speaker Driver Playback Volume", 545 + TAS5720_Q1_VOLUME_CTRL_LEFT_REG, 546 + TAS5720_Q1_VOLUME_CTRL_RIGHT_REG, 547 + 0, 0xff, 0, tas5720_dac_tlv), 548 + SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG, 549 + TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv_a_q1), 550 + }; 551 + 587 552 static const struct snd_kcontrol_new tas5722_snd_controls[] = { 588 553 SOC_SINGLE_EXT_TLV("Speaker Driver Playback Volume", 589 554 0, 0, 511, 0, ··· 621 568 .resume = tas5720_resume, 622 569 .controls = tas5720_snd_controls, 623 570 .num_controls = ARRAY_SIZE(tas5720_snd_controls), 571 + .dapm_widgets = tas5720_dapm_widgets, 572 + .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), 573 + .dapm_routes = tas5720_audio_map, 574 + .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), 575 + .idle_bias_on = 1, 576 + .use_pmdown_time = 1, 577 + .endianness = 1, 578 + }; 579 + 580 + static const struct snd_soc_component_driver soc_component_dev_tas5720_a_q1 = { 581 + .probe = tas5720_codec_probe, 582 + .remove = tas5720_codec_remove, 583 + .suspend = tas5720_suspend, 584 + .resume = tas5720_resume, 585 + .controls = tas5720a_q1_snd_controls, 586 + .num_controls = ARRAY_SIZE(tas5720a_q1_snd_controls), 624 587 .dapm_widgets = tas5720_dapm_widgets, 625 588 .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), 626 589 .dapm_routes = tas5720_audio_map, ··· 705 636 706 637 static const struct i2c_device_id tas5720_id[] = { 707 638 { "tas5720", TAS5720 }, 639 + { "tas5720a-q1", TAS5720A_Q1 }, 708 640 { "tas5722", TAS5722 }, 709 641 { } 710 642 }; ··· 731 661 switch (id->driver_data) { 732 662 case TAS5720: 733 663 regmap_config = &tas5720_regmap_config; 664 + break; 665 + case TAS5720A_Q1: 666 + regmap_config = &tas5720a_q1_regmap_config; 734 667 break; 735 668 case TAS5722: 736 669 regmap_config = &tas5722_regmap_config; ··· 768 695 tas5720_dai, 769 696 ARRAY_SIZE(tas5720_dai)); 770 697 break; 698 + case TAS5720A_Q1: 699 + ret = devm_snd_soc_register_component(&client->dev, 700 + &soc_component_dev_tas5720_a_q1, 701 + tas5720_dai, 702 + ARRAY_SIZE(tas5720_dai)); 703 + break; 771 704 case TAS5722: 772 705 ret = devm_snd_soc_register_component(&client->dev, 773 706 &soc_component_dev_tas5722, ··· 795 716 #if IS_ENABLED(CONFIG_OF) 796 717 static const struct of_device_id tas5720_of_match[] = { 797 718 { .compatible = "ti,tas5720", }, 719 + { .compatible = "ti,tas5720a-q1", }, 798 720 { .compatible = "ti,tas5722", }, 799 721 { }, 800 722 };
+14 -1
sound/soc/codecs/tas5720.h
··· 10 10 #ifndef __TAS5720_H__ 11 11 #define __TAS5720_H__ 12 12 13 - /* Register Address Map */ 13 + /* Register Address Map - first 3 regs are common for all variants */ 14 14 #define TAS5720_DEVICE_ID_REG 0x00 15 15 #define TAS5720_POWER_CTRL_REG 0x01 16 16 #define TAS5720_DIGITAL_CTRL1_REG 0x02 ··· 27 27 #define TAS5722_ANALOG_CTRL2_REG 0x14 28 28 #define TAS5722_MAX_REG TAS5722_ANALOG_CTRL2_REG 29 29 30 + /* Register Address Map - volume controls for the TAS5720-Q1 variant */ 31 + #define TAS5720_Q1_VOLUME_CTRL_CFG_REG 0x03 32 + #define TAS5720_Q1_VOLUME_CTRL_LEFT_REG 0x04 33 + #define TAS5720_Q1_VOLUME_CTRL_RIGHT_REG 0x05 34 + 30 35 /* TAS5720_DEVICE_ID_REG */ 36 + #define TAS5720A_Q1_DEVICE_ID 0x00 31 37 #define TAS5720_DEVICE_ID 0x01 32 38 #define TAS5722_DEVICE_ID 0x12 33 39 ··· 59 53 #define TAS5720_MUTE BIT(4) 60 54 #define TAS5720_TDM_SLOT_SEL_MASK GENMASK(2, 0) 61 55 56 + /* TAS5720_Q1_VOLUME_CTRL_CFG_REG */ 57 + #define TAS5720_Q1_FADE BIT(7) 58 + #define TAS5720_Q1_MUTE GENMASK(1, 0) 59 + 62 60 /* TAS5720_ANALOG_CTRL_REG */ 63 61 #define TAS5720_PWM_RATE_6_3_FSYNC (0x0 << 4) 64 62 #define TAS5720_PWM_RATE_8_4_FSYNC (0x1 << 4) ··· 79 69 #define TAS5720_ANALOG_GAIN_26_3DBV (0x3 << 2) 80 70 #define TAS5720_ANALOG_GAIN_MASK GENMASK(3, 2) 81 71 #define TAS5720_ANALOG_GAIN_SHIFT (0x2) 72 + 73 + /* TAS5720_Q1_ANALOG_CTRL_REG */ 74 + #define TAS5720_Q1_CHAN_SEL BIT(1) 82 75 83 76 /* TAS5720_FAULT_REG */ 84 77 #define TAS5720_OC_THRESH_100PCT (0x0 << 4)