0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/module.h>
0016 #include <linux/moduleparam.h>
0017 #include <linux/kernel.h>
0018 #include <linux/firmware.h>
0019 #include <linux/slab.h>
0020 #include <linux/of.h>
0021 #include <linux/init.h>
0022 #include <linux/i2c.h>
0023 #include <linux/regmap.h>
0024 #include <linux/gpio/consumer.h>
0025 #include <linux/regulator/consumer.h>
0026 #include <linux/atomic.h>
0027 #include <linux/workqueue.h>
0028
0029 #include <sound/soc.h>
0030 #include <sound/pcm.h>
0031 #include <sound/initval.h>
0032
0033
0034 #define REG_PAGE 0x00
0035 #define REG_DEVICE_CTRL_1 0x02
0036 #define REG_DEVICE_CTRL_2 0x03
0037 #define REG_SIG_CH_CTRL 0x28
0038 #define REG_SAP_CTRL_1 0x33
0039 #define REG_FS_MON 0x37
0040 #define REG_BCK_MON 0x38
0041 #define REG_CLKDET_STATUS 0x39
0042 #define REG_VOL_CTL 0x4c
0043 #define REG_AGAIN 0x54
0044 #define REG_ADR_PIN_CTRL 0x60
0045 #define REG_ADR_PIN_CONFIG 0x61
0046 #define REG_CHAN_FAULT 0x70
0047 #define REG_GLOBAL_FAULT1 0x71
0048 #define REG_GLOBAL_FAULT2 0x72
0049 #define REG_FAULT 0x78
0050 #define REG_BOOK 0x7f
0051
0052
0053 #define DCTRL2_MODE_DEEP_SLEEP 0x00
0054 #define DCTRL2_MODE_SLEEP 0x01
0055 #define DCTRL2_MODE_HIZ 0x02
0056 #define DCTRL2_MODE_PLAY 0x03
0057
0058 #define DCTRL2_MUTE 0x08
0059 #define DCTRL2_DIS_DSP 0x10
0060
0061
0062
0063
0064 static const uint8_t dsp_cfg_preboot[] = {
0065 0x00, 0x00, 0x7f, 0x00, 0x03, 0x02, 0x01, 0x11,
0066 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0067 0x00, 0x00, 0x7f, 0x00, 0x03, 0x02,
0068 };
0069
0070 static const uint32_t tas5805m_volume[] = {
0071 0x0000001B, 0x0000001E,
0072 0x00000021, 0x00000025,
0073 0x0000002A, 0x0000002F,
0074 0x00000035, 0x0000003B,
0075 0x00000043, 0x0000004B,
0076 0x00000054, 0x0000005E,
0077 0x0000006A, 0x00000076,
0078 0x00000085, 0x00000095,
0079 0x000000A7, 0x000000BC,
0080 0x000000D3, 0x000000EC,
0081 0x00000109, 0x0000012A,
0082 0x0000014E, 0x00000177,
0083 0x000001A4, 0x000001D8,
0084 0x00000211, 0x00000252,
0085 0x0000029A, 0x000002EC,
0086 0x00000347, 0x000003AD,
0087 0x00000420, 0x000004A1,
0088 0x00000532, 0x000005D4,
0089 0x0000068A, 0x00000756,
0090 0x0000083B, 0x0000093C,
0091 0x00000A5D, 0x00000BA0,
0092 0x00000D0C, 0x00000EA3,
0093 0x0000106C, 0x0000126D,
0094 0x000014AD, 0x00001733,
0095 0x00001A07, 0x00001D34,
0096 0x000020C5, 0x000024C4,
0097 0x00002941, 0x00002E49,
0098 0x000033EF, 0x00003A45,
0099 0x00004161, 0x0000495C,
0100 0x0000524F, 0x00005C5A,
0101 0x0000679F, 0x00007444,
0102 0x00008274, 0x0000925F,
0103 0x0000A43B, 0x0000B845,
0104 0x0000CEC1, 0x0000E7FB,
0105 0x00010449, 0x0001240C,
0106 0x000147AE, 0x00016FAA,
0107 0x00019C86, 0x0001CEDC,
0108 0x00020756, 0x000246B5,
0109 0x00028DCF, 0x0002DD96,
0110 0x00033718, 0x00039B87,
0111 0x00040C37, 0x00048AA7,
0112 0x00051884, 0x0005B7B1,
0113 0x00066A4A, 0x000732AE,
0114 0x00081385, 0x00090FCC,
0115 0x000A2ADB, 0x000B6873,
0116 0x000CCCCD, 0x000E5CA1,
0117 0x00101D3F, 0x0012149A,
0118 0x00144961, 0x0016C311,
0119 0x00198A13, 0x001CA7D7,
0120 0x002026F3, 0x00241347,
0121 0x00287A27, 0x002D6A86,
0122 0x0032F52D, 0x00392CEE,
0123 0x004026E7, 0x0047FACD,
0124 0x0050C336, 0x005A9DF8,
0125 0x0065AC8C, 0x00721483,
0126 0x00800000, 0x008F9E4D,
0127 0x00A12478, 0x00B4CE08,
0128 0x00CADDC8, 0x00E39EA9,
0129 0x00FF64C1, 0x011E8E6A,
0130 0x0141857F, 0x0168C0C6,
0131 0x0194C584, 0x01C62940,
0132 0x01FD93C2, 0x023BC148,
0133 0x02818508, 0x02CFCC01,
0134 0x0327A01A, 0x038A2BAD,
0135 0x03F8BD7A, 0x0474CD1B,
0136 0x05000000, 0x059C2F02,
0137 0x064B6CAE, 0x07100C4D,
0138 0x07ECA9CD, 0x08E43299,
0139 0x09F9EF8E, 0x0B319025,
0140 0x0C8F36F2, 0x0E1787B8,
0141 0x0FCFB725, 0x11BD9C84,
0142 0x13E7C594, 0x16558CCB,
0143 0x190F3254, 0x1C1DF80E,
0144 0x1F8C4107, 0x2365B4BF,
0145 0x27B766C2, 0x2C900313,
0146 0x32000000, 0x3819D612,
0147 0x3EF23ECA, 0x46A07B07,
0148 0x4F3EA203, 0x58E9F9F9,
0149 0x63C35B8E, 0x6FEFA16D,
0150 0x7D982575,
0151 };
0152
0153 #define TAS5805M_VOLUME_MAX ((int)ARRAY_SIZE(tas5805m_volume) - 1)
0154 #define TAS5805M_VOLUME_MIN 0
0155
0156 struct tas5805m_priv {
0157 struct regulator *pvdd;
0158 struct gpio_desc *gpio_pdn_n;
0159
0160 uint8_t *dsp_cfg_data;
0161 int dsp_cfg_len;
0162
0163 struct regmap *regmap;
0164
0165 int vol[2];
0166 bool is_powered;
0167 bool is_muted;
0168 };
0169
0170 static void set_dsp_scale(struct regmap *rm, int offset, int vol)
0171 {
0172 uint8_t v[4];
0173 uint32_t x = tas5805m_volume[vol];
0174 int i;
0175
0176 for (i = 0; i < 4; i++) {
0177 v[3 - i] = x;
0178 x >>= 8;
0179 }
0180
0181 regmap_bulk_write(rm, offset, v, ARRAY_SIZE(v));
0182 }
0183
0184 static void tas5805m_refresh(struct snd_soc_component *component)
0185 {
0186 struct tas5805m_priv *tas5805m =
0187 snd_soc_component_get_drvdata(component);
0188 struct regmap *rm = tas5805m->regmap;
0189
0190 dev_dbg(component->dev, "refresh: is_muted=%d, vol=%d/%d\n",
0191 tas5805m->is_muted, tas5805m->vol[0], tas5805m->vol[1]);
0192
0193 regmap_write(rm, REG_PAGE, 0x00);
0194 regmap_write(rm, REG_BOOK, 0x8c);
0195 regmap_write(rm, REG_PAGE, 0x2a);
0196
0197
0198
0199
0200
0201 set_dsp_scale(rm, 0x24, tas5805m->vol[0]);
0202 set_dsp_scale(rm, 0x28, tas5805m->vol[1]);
0203
0204
0205 regmap_write(rm, REG_DEVICE_CTRL_2,
0206 (tas5805m->is_muted ? DCTRL2_MUTE : 0) |
0207 DCTRL2_MODE_PLAY);
0208 }
0209
0210 static int tas5805m_vol_info(struct snd_kcontrol *kcontrol,
0211 struct snd_ctl_elem_info *uinfo)
0212 {
0213 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0214 uinfo->count = 2;
0215
0216 uinfo->value.integer.min = TAS5805M_VOLUME_MIN;
0217 uinfo->value.integer.max = TAS5805M_VOLUME_MAX;
0218 return 0;
0219 }
0220
0221 static int tas5805m_vol_get(struct snd_kcontrol *kcontrol,
0222 struct snd_ctl_elem_value *ucontrol)
0223 {
0224 struct snd_soc_component *component =
0225 snd_soc_kcontrol_component(kcontrol);
0226 struct tas5805m_priv *tas5805m =
0227 snd_soc_component_get_drvdata(component);
0228
0229 ucontrol->value.integer.value[0] = tas5805m->vol[0];
0230 ucontrol->value.integer.value[1] = tas5805m->vol[1];
0231 return 0;
0232 }
0233
0234 static inline int volume_is_valid(int v)
0235 {
0236 return (v >= TAS5805M_VOLUME_MIN) && (v <= TAS5805M_VOLUME_MAX);
0237 }
0238
0239 static int tas5805m_vol_put(struct snd_kcontrol *kcontrol,
0240 struct snd_ctl_elem_value *ucontrol)
0241 {
0242 struct snd_soc_component *component =
0243 snd_soc_kcontrol_component(kcontrol);
0244 struct tas5805m_priv *tas5805m =
0245 snd_soc_component_get_drvdata(component);
0246
0247 if (!(volume_is_valid(ucontrol->value.integer.value[0]) &&
0248 volume_is_valid(ucontrol->value.integer.value[1])))
0249 return -EINVAL;
0250
0251 if (tas5805m->vol[0] != ucontrol->value.integer.value[0] ||
0252 tas5805m->vol[1] != ucontrol->value.integer.value[1]) {
0253 tas5805m->vol[0] = ucontrol->value.integer.value[0];
0254 tas5805m->vol[1] = ucontrol->value.integer.value[1];
0255 dev_dbg(component->dev, "set vol=%d/%d (is_powered=%d)\n",
0256 tas5805m->vol[0], tas5805m->vol[1],
0257 tas5805m->is_powered);
0258 if (tas5805m->is_powered)
0259 tas5805m_refresh(component);
0260 return 1;
0261 }
0262
0263 return 0;
0264 }
0265
0266 static const struct snd_kcontrol_new tas5805m_snd_controls[] = {
0267 {
0268 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0269 .name = "Master Playback Volume",
0270 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
0271 SNDRV_CTL_ELEM_ACCESS_READWRITE,
0272 .info = tas5805m_vol_info,
0273 .get = tas5805m_vol_get,
0274 .put = tas5805m_vol_put,
0275 },
0276 };
0277
0278 static void send_cfg(struct regmap *rm,
0279 const uint8_t *s, unsigned int len)
0280 {
0281 unsigned int i;
0282
0283 for (i = 0; i + 1 < len; i += 2)
0284 regmap_write(rm, s[i], s[i + 1]);
0285 }
0286
0287
0288
0289
0290
0291 static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd,
0292 struct snd_soc_dai *dai)
0293 {
0294 struct snd_soc_component *component = dai->component;
0295 struct tas5805m_priv *tas5805m =
0296 snd_soc_component_get_drvdata(component);
0297 struct regmap *rm = tas5805m->regmap;
0298 unsigned int chan, global1, global2;
0299
0300 switch (cmd) {
0301 case SNDRV_PCM_TRIGGER_START:
0302 case SNDRV_PCM_TRIGGER_RESUME:
0303 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0304 dev_dbg(component->dev, "DSP startup\n");
0305
0306
0307
0308
0309
0310
0311 usleep_range(5000, 10000);
0312 send_cfg(rm, dsp_cfg_preboot,
0313 ARRAY_SIZE(dsp_cfg_preboot));
0314 usleep_range(5000, 15000);
0315 send_cfg(rm, tas5805m->dsp_cfg_data,
0316 tas5805m->dsp_cfg_len);
0317
0318 tas5805m->is_powered = true;
0319 tas5805m_refresh(component);
0320 break;
0321
0322 case SNDRV_PCM_TRIGGER_STOP:
0323 case SNDRV_PCM_TRIGGER_SUSPEND:
0324 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0325 dev_dbg(component->dev, "DSP shutdown\n");
0326
0327 tas5805m->is_powered = false;
0328
0329 regmap_write(rm, REG_PAGE, 0x00);
0330 regmap_write(rm, REG_BOOK, 0x00);
0331
0332 regmap_read(rm, REG_CHAN_FAULT, &chan);
0333 regmap_read(rm, REG_GLOBAL_FAULT1, &global1);
0334 regmap_read(rm, REG_GLOBAL_FAULT2, &global2);
0335
0336 dev_dbg(component->dev,
0337 "fault regs: CHAN=%02x, GLOBAL1=%02x, GLOBAL2=%02x\n",
0338 chan, global1, global2);
0339
0340 regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ);
0341 break;
0342
0343 default:
0344 return -EINVAL;
0345 }
0346
0347 return 0;
0348 }
0349
0350 static const struct snd_soc_dapm_route tas5805m_audio_map[] = {
0351 { "DAC", NULL, "DAC IN" },
0352 { "OUT", NULL, "DAC" },
0353 };
0354
0355 static const struct snd_soc_dapm_widget tas5805m_dapm_widgets[] = {
0356 SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
0357 SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
0358 SND_SOC_DAPM_OUTPUT("OUT")
0359 };
0360
0361 static const struct snd_soc_component_driver soc_codec_dev_tas5805m = {
0362 .controls = tas5805m_snd_controls,
0363 .num_controls = ARRAY_SIZE(tas5805m_snd_controls),
0364 .dapm_widgets = tas5805m_dapm_widgets,
0365 .num_dapm_widgets = ARRAY_SIZE(tas5805m_dapm_widgets),
0366 .dapm_routes = tas5805m_audio_map,
0367 .num_dapm_routes = ARRAY_SIZE(tas5805m_audio_map),
0368 .use_pmdown_time = 1,
0369 .endianness = 1,
0370 };
0371
0372 static int tas5805m_mute(struct snd_soc_dai *dai, int mute, int direction)
0373 {
0374 struct snd_soc_component *component = dai->component;
0375 struct tas5805m_priv *tas5805m =
0376 snd_soc_component_get_drvdata(component);
0377
0378 dev_dbg(component->dev, "set mute=%d (is_powered=%d)\n",
0379 mute, tas5805m->is_powered);
0380 tas5805m->is_muted = mute;
0381 if (tas5805m->is_powered)
0382 tas5805m_refresh(component);
0383
0384 return 0;
0385 }
0386
0387 static const struct snd_soc_dai_ops tas5805m_dai_ops = {
0388 .trigger = tas5805m_trigger,
0389 .mute_stream = tas5805m_mute,
0390 .no_capture_mute = 1,
0391 };
0392
0393 static struct snd_soc_dai_driver tas5805m_dai = {
0394 .name = "tas5805m-amplifier",
0395 .playback = {
0396 .stream_name = "Playback",
0397 .channels_min = 2,
0398 .channels_max = 2,
0399 .rates = SNDRV_PCM_RATE_48000,
0400 .formats = SNDRV_PCM_FMTBIT_S32_LE,
0401 },
0402 .ops = &tas5805m_dai_ops,
0403 };
0404
0405 static const struct regmap_config tas5805m_regmap = {
0406 .reg_bits = 8,
0407 .val_bits = 8,
0408
0409
0410
0411
0412
0413 .cache_type = REGCACHE_NONE,
0414 };
0415
0416 static int tas5805m_i2c_probe(struct i2c_client *i2c)
0417 {
0418 struct device *dev = &i2c->dev;
0419 struct regmap *regmap;
0420 struct tas5805m_priv *tas5805m;
0421 char filename[128];
0422 const char *config_name;
0423 const struct firmware *fw;
0424 int ret;
0425
0426 regmap = devm_regmap_init_i2c(i2c, &tas5805m_regmap);
0427 if (IS_ERR(regmap)) {
0428 ret = PTR_ERR(regmap);
0429 dev_err(dev, "unable to allocate register map: %d\n", ret);
0430 return ret;
0431 }
0432
0433 tas5805m = devm_kzalloc(dev, sizeof(struct tas5805m_priv), GFP_KERNEL);
0434 if (!tas5805m)
0435 return -ENOMEM;
0436
0437 tas5805m->pvdd = devm_regulator_get(dev, "pvdd");
0438 if (IS_ERR(tas5805m->pvdd)) {
0439 dev_err(dev, "failed to get pvdd supply: %ld\n",
0440 PTR_ERR(tas5805m->pvdd));
0441 return PTR_ERR(tas5805m->pvdd);
0442 }
0443
0444 dev_set_drvdata(dev, tas5805m);
0445 tas5805m->regmap = regmap;
0446 tas5805m->gpio_pdn_n = devm_gpiod_get(dev, "pdn", GPIOD_OUT_LOW);
0447 if (IS_ERR(tas5805m->gpio_pdn_n)) {
0448 dev_err(dev, "error requesting PDN gpio: %ld\n",
0449 PTR_ERR(tas5805m->gpio_pdn_n));
0450 return PTR_ERR(tas5805m->gpio_pdn_n);
0451 }
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461 if (device_property_read_string(dev, "ti,dsp-config-name",
0462 &config_name))
0463 config_name = "default";
0464
0465 snprintf(filename, sizeof(filename), "tas5805m_dsp_%s.bin",
0466 config_name);
0467 ret = request_firmware(&fw, filename, dev);
0468 if (ret)
0469 return ret;
0470
0471 if ((fw->size < 2) || (fw->size & 1)) {
0472 dev_err(dev, "firmware is invalid\n");
0473 release_firmware(fw);
0474 return -EINVAL;
0475 }
0476
0477 tas5805m->dsp_cfg_len = fw->size;
0478 tas5805m->dsp_cfg_data = devm_kmalloc(dev, fw->size, GFP_KERNEL);
0479 if (!tas5805m->dsp_cfg_data) {
0480 release_firmware(fw);
0481 return -ENOMEM;
0482 }
0483 memcpy(tas5805m->dsp_cfg_data, fw->data, fw->size);
0484
0485 release_firmware(fw);
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497 tas5805m->vol[0] = TAS5805M_VOLUME_MIN;
0498 tas5805m->vol[1] = TAS5805M_VOLUME_MIN;
0499
0500 ret = regulator_enable(tas5805m->pvdd);
0501 if (ret < 0) {
0502 dev_err(dev, "failed to enable pvdd: %d\n", ret);
0503 return ret;
0504 }
0505
0506 usleep_range(100000, 150000);
0507 gpiod_set_value(tas5805m->gpio_pdn_n, 1);
0508 usleep_range(10000, 15000);
0509
0510
0511
0512
0513 ret = snd_soc_register_component(dev, &soc_codec_dev_tas5805m,
0514 &tas5805m_dai, 1);
0515 if (ret < 0) {
0516 dev_err(dev, "unable to register codec: %d\n", ret);
0517 gpiod_set_value(tas5805m->gpio_pdn_n, 0);
0518 regulator_disable(tas5805m->pvdd);
0519 return ret;
0520 }
0521
0522 return 0;
0523 }
0524
0525 static int tas5805m_i2c_remove(struct i2c_client *i2c)
0526 {
0527 struct device *dev = &i2c->dev;
0528 struct tas5805m_priv *tas5805m = dev_get_drvdata(dev);
0529
0530 snd_soc_unregister_component(dev);
0531 gpiod_set_value(tas5805m->gpio_pdn_n, 0);
0532 usleep_range(10000, 15000);
0533 regulator_disable(tas5805m->pvdd);
0534 return 0;
0535 }
0536
0537 static const struct i2c_device_id tas5805m_i2c_id[] = {
0538 { "tas5805m", },
0539 { }
0540 };
0541 MODULE_DEVICE_TABLE(i2c, tas5805m_i2c_id);
0542
0543 #if IS_ENABLED(CONFIG_OF)
0544 static const struct of_device_id tas5805m_of_match[] = {
0545 { .compatible = "ti,tas5805m", },
0546 { }
0547 };
0548 MODULE_DEVICE_TABLE(of, tas5805m_of_match);
0549 #endif
0550
0551 static struct i2c_driver tas5805m_i2c_driver = {
0552 .probe_new = tas5805m_i2c_probe,
0553 .remove = tas5805m_i2c_remove,
0554 .id_table = tas5805m_i2c_id,
0555 .driver = {
0556 .name = "tas5805m",
0557 .of_match_table = of_match_ptr(tas5805m_of_match),
0558 },
0559 };
0560
0561 module_i2c_driver(tas5805m_i2c_driver);
0562
0563 MODULE_AUTHOR("Andy Liu <andy-liu@ti.com>");
0564 MODULE_AUTHOR("Daniel Beer <daniel.beer@igorinstitute.com>");
0565 MODULE_DESCRIPTION("TAS5805M Audio Amplifier Driver");
0566 MODULE_LICENSE("GPL v2");