1/* 2 * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier 3 * 4 * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com 5 * 6 * Author: Dan Murphy <dmurphy@ti.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 */ 17 18#include <linux/module.h> 19#include <linux/errno.h> 20#include <linux/device.h> 21#include <linux/i2c.h> 22#include <linux/gpio.h> 23#include <linux/of_gpio.h> 24#include <linux/pm_runtime.h> 25#include <linux/regmap.h> 26#include <linux/slab.h> 27 28#include <linux/gpio/consumer.h> 29#include <linux/regulator/consumer.h> 30 31#include <sound/pcm.h> 32#include <sound/pcm_params.h> 33#include <sound/soc.h> 34#include <sound/soc-dapm.h> 35#include <sound/tlv.h> 36#include <sound/tas2552-plat.h> 37 38#include "tas2552.h" 39 40static struct reg_default tas2552_reg_defs[] = { 41 {TAS2552_CFG_1, 0x22}, 42 {TAS2552_CFG_3, 0x80}, 43 {TAS2552_DOUT, 0x00}, 44 {TAS2552_OUTPUT_DATA, 0xc0}, 45 {TAS2552_PDM_CFG, 0x01}, 46 {TAS2552_PGA_GAIN, 0x00}, 47 {TAS2552_BOOST_PT_CTRL, 0x0f}, 48 {TAS2552_RESERVED_0D, 0x00}, 49 {TAS2552_LIMIT_RATE_HYS, 0x08}, 50 {TAS2552_CFG_2, 0xef}, 51 {TAS2552_SER_CTRL_1, 0x00}, 52 {TAS2552_SER_CTRL_2, 0x00}, 53 {TAS2552_PLL_CTRL_1, 0x10}, 54 {TAS2552_PLL_CTRL_2, 0x00}, 55 {TAS2552_PLL_CTRL_3, 0x00}, 56 {TAS2552_BTIP, 0x8f}, 57 {TAS2552_BTS_CTRL, 0x80}, 58 {TAS2552_LIMIT_RELEASE, 0x04}, 59 {TAS2552_LIMIT_INT_COUNT, 0x00}, 60 {TAS2552_EDGE_RATE_CTRL, 0x40}, 61 {TAS2552_VBAT_DATA, 0x00}, 62}; 63 64#define TAS2552_NUM_SUPPLIES 3 65static const char *tas2552_supply_names[TAS2552_NUM_SUPPLIES] = { 66 "vbat", /* vbat voltage */ 67 "iovdd", /* I/O Voltage */ 68 "avdd", /* Analog DAC Voltage */ 69}; 70 71struct tas2552_data { 72 struct snd_soc_codec *codec; 73 struct regmap *regmap; 74 struct i2c_client *tas2552_client; 75 struct regulator_bulk_data supplies[TAS2552_NUM_SUPPLIES]; 76 struct gpio_desc *enable_gpio; 77 unsigned char regs[TAS2552_VBAT_DATA]; 78 unsigned int mclk; 79}; 80 81/* Input mux controls */ 82static const char *tas2552_input_texts[] = { 83 "Digital", "Analog" 84}; 85 86static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum, TAS2552_CFG_3, 7, 87 tas2552_input_texts); 88 89static const struct snd_kcontrol_new tas2552_input_mux_control[] = { 90 SOC_DAPM_ENUM("Input selection", tas2552_input_mux_enum) 91}; 92 93static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] = 94{ 95 SND_SOC_DAPM_INPUT("IN"), 96 97 /* MUX Controls */ 98 SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM, 0, 0, 99 tas2552_input_mux_control), 100 101 SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), 102 SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), 103 SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0), 104 SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0), 105 106 SND_SOC_DAPM_OUTPUT("OUT") 107}; 108 109static const struct snd_soc_dapm_route tas2552_audio_map[] = { 110 {"DAC", NULL, "DAC IN"}, 111 {"Input selection", "Digital", "DAC"}, 112 {"Input selection", "Analog", "IN"}, 113 {"ClassD", NULL, "Input selection"}, 114 {"OUT", NULL, "ClassD"}, 115 {"ClassD", NULL, "PLL"}, 116}; 117 118#ifdef CONFIG_PM 119static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown) 120{ 121 u8 cfg1_reg; 122 123 if (!tas_data->codec) 124 return; 125 126 if (sw_shutdown) 127 cfg1_reg = 0; 128 else 129 cfg1_reg = TAS2552_SWS_MASK; 130 131 snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1, 132 TAS2552_SWS_MASK, cfg1_reg); 133} 134#endif 135 136static int tas2552_hw_params(struct snd_pcm_substream *substream, 137 struct snd_pcm_hw_params *params, 138 struct snd_soc_dai *dai) 139{ 140 struct snd_soc_codec *codec = dai->codec; 141 struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); 142 int sample_rate, pll_clk; 143 int d; 144 u8 p, j; 145 146 if (!tas2552->mclk) 147 return -EINVAL; 148 149 snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0); 150 151 if (tas2552->mclk == TAS2552_245MHZ_CLK || 152 tas2552->mclk == TAS2552_225MHZ_CLK) { 153 /* By pass the PLL configuration */ 154 snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2, 155 TAS2552_PLL_BYPASS_MASK, 156 TAS2552_PLL_BYPASS); 157 } else { 158 /* Fill in the PLL control registers for J & D 159 * PLL_CLK = (.5 * freq * J.D) / 2^p 160 * Need to fill in J and D here based on incoming freq 161 */ 162 p = snd_soc_read(codec, TAS2552_PLL_CTRL_1); 163 p = (p >> 7); 164 sample_rate = params_rate(params); 165 166 if (sample_rate == 48000) 167 pll_clk = TAS2552_245MHZ_CLK; 168 else if (sample_rate == 44100) 169 pll_clk = TAS2552_225MHZ_CLK; 170 else { 171 dev_vdbg(codec->dev, "Substream sample rate is not found %i\n", 172 params_rate(params)); 173 return -EINVAL; 174 } 175 176 j = (pll_clk * 2 * (1 << p)) / tas2552->mclk; 177 d = (pll_clk * 2 * (1 << p)) % tas2552->mclk; 178 179 snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1, 180 TAS2552_PLL_J_MASK, j); 181 snd_soc_write(codec, TAS2552_PLL_CTRL_2, 182 (d >> 7) & TAS2552_PLL_D_UPPER_MASK); 183 snd_soc_write(codec, TAS2552_PLL_CTRL_3, 184 d & TAS2552_PLL_D_LOWER_MASK); 185 186 } 187 188 return 0; 189} 190 191static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 192{ 193 struct snd_soc_codec *codec = dai->codec; 194 u8 serial_format; 195 u8 serial_control_mask; 196 197 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 198 case SND_SOC_DAIFMT_CBS_CFS: 199 serial_format = 0x00; 200 break; 201 case SND_SOC_DAIFMT_CBS_CFM: 202 serial_format = TAS2552_WORD_CLK_MASK; 203 break; 204 case SND_SOC_DAIFMT_CBM_CFS: 205 serial_format = TAS2552_BIT_CLK_MASK; 206 break; 207 case SND_SOC_DAIFMT_CBM_CFM: 208 serial_format = (TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK); 209 break; 210 default: 211 dev_vdbg(codec->dev, "DAI Format master is not found\n"); 212 return -EINVAL; 213 } 214 215 serial_control_mask = TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK; 216 217 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 218 case SND_SOC_DAIFMT_I2S: 219 serial_format &= TAS2552_DAIFMT_I2S_MASK; 220 break; 221 case SND_SOC_DAIFMT_DSP_A: 222 serial_format |= TAS2552_DAIFMT_DSP; 223 break; 224 case SND_SOC_DAIFMT_RIGHT_J: 225 serial_format |= TAS2552_DAIFMT_RIGHT_J; 226 break; 227 case SND_SOC_DAIFMT_LEFT_J: 228 serial_format |= TAS2552_DAIFMT_LEFT_J; 229 break; 230 default: 231 dev_vdbg(codec->dev, "DAI Format is not found\n"); 232 return -EINVAL; 233 } 234 235 if (fmt & SND_SOC_DAIFMT_FORMAT_MASK) 236 serial_control_mask |= TAS2552_DATA_FORMAT_MASK; 237 238 snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, serial_control_mask, 239 serial_format); 240 241 return 0; 242} 243 244static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, 245 unsigned int freq, int dir) 246{ 247 struct snd_soc_codec *codec = dai->codec; 248 struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev); 249 250 tas2552->mclk = freq; 251 252 return 0; 253} 254 255static int tas2552_mute(struct snd_soc_dai *dai, int mute) 256{ 257 u8 cfg1_reg; 258 struct snd_soc_codec *codec = dai->codec; 259 260 if (mute) 261 cfg1_reg = TAS2552_MUTE_MASK; 262 else 263 cfg1_reg = ~TAS2552_MUTE_MASK; 264 265 snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK, cfg1_reg); 266 267 return 0; 268} 269 270#ifdef CONFIG_PM 271static int tas2552_runtime_suspend(struct device *dev) 272{ 273 struct tas2552_data *tas2552 = dev_get_drvdata(dev); 274 275 tas2552_sw_shutdown(tas2552, 0); 276 277 regcache_cache_only(tas2552->regmap, true); 278 regcache_mark_dirty(tas2552->regmap); 279 280 if (tas2552->enable_gpio) 281 gpiod_set_value(tas2552->enable_gpio, 0); 282 283 return 0; 284} 285 286static int tas2552_runtime_resume(struct device *dev) 287{ 288 struct tas2552_data *tas2552 = dev_get_drvdata(dev); 289 290 if (tas2552->enable_gpio) 291 gpiod_set_value(tas2552->enable_gpio, 1); 292 293 tas2552_sw_shutdown(tas2552, 1); 294 295 regcache_cache_only(tas2552->regmap, false); 296 regcache_sync(tas2552->regmap); 297 298 return 0; 299} 300#endif 301 302static const struct dev_pm_ops tas2552_pm = { 303 SET_RUNTIME_PM_OPS(tas2552_runtime_suspend, tas2552_runtime_resume, 304 NULL) 305}; 306 307static struct snd_soc_dai_ops tas2552_speaker_dai_ops = { 308 .hw_params = tas2552_hw_params, 309 .set_sysclk = tas2552_set_dai_sysclk, 310 .set_fmt = tas2552_set_dai_fmt, 311 .digital_mute = tas2552_mute, 312}; 313 314/* Formats supported by TAS2552 driver. */ 315#define TAS2552_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 316 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 317 318/* TAS2552 dai structure. */ 319static struct snd_soc_dai_driver tas2552_dai[] = { 320 { 321 .name = "tas2552-amplifier", 322 .playback = { 323 .stream_name = "Playback", 324 .channels_min = 2, 325 .channels_max = 2, 326 .rates = SNDRV_PCM_RATE_8000_192000, 327 .formats = TAS2552_FORMATS, 328 }, 329 .ops = &tas2552_speaker_dai_ops, 330 }, 331}; 332 333/* 334 * DAC digital volumes. From -7 to 24 dB in 1 dB steps 335 */ 336static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24); 337 338static const struct snd_kcontrol_new tas2552_snd_controls[] = { 339 SOC_SINGLE_TLV("Speaker Driver Playback Volume", 340 TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv), 341}; 342 343static const struct reg_default tas2552_init_regs[] = { 344 { TAS2552_RESERVED_0D, 0xc0 }, 345}; 346 347static int tas2552_codec_probe(struct snd_soc_codec *codec) 348{ 349 struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); 350 int ret; 351 352 tas2552->codec = codec; 353 354 ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies), 355 tas2552->supplies); 356 357 if (ret != 0) { 358 dev_err(codec->dev, "Failed to enable supplies: %d\n", 359 ret); 360 return ret; 361 } 362 363 if (tas2552->enable_gpio) 364 gpiod_set_value(tas2552->enable_gpio, 1); 365 366 ret = pm_runtime_get_sync(codec->dev); 367 if (ret < 0) { 368 dev_err(codec->dev, "Enabling device failed: %d\n", 369 ret); 370 goto probe_fail; 371 } 372 373 snd_soc_write(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK | 374 TAS2552_PLL_SRC_BCLK); 375 snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL | 376 TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ); 377 snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I); 378 snd_soc_write(codec, TAS2552_OUTPUT_DATA, TAS2552_PDM_DATA_V_I | 0x8); 379 snd_soc_write(codec, TAS2552_PDM_CFG, TAS2552_PDM_BCLK_SEL); 380 snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 | 381 TAS2552_APT_THRESH_2_1_7); 382 383 ret = regmap_register_patch(tas2552->regmap, tas2552_init_regs, 384 ARRAY_SIZE(tas2552_init_regs)); 385 if (ret != 0) { 386 dev_err(codec->dev, "Failed to write init registers: %d\n", 387 ret); 388 goto patch_fail; 389 } 390 391 snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN | 392 TAS2552_APT_EN | TAS2552_LIM_EN); 393 394 return 0; 395 396patch_fail: 397 pm_runtime_put(codec->dev); 398probe_fail: 399 if (tas2552->enable_gpio) 400 gpiod_set_value(tas2552->enable_gpio, 0); 401 402 regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies), 403 tas2552->supplies); 404 return -EIO; 405} 406 407static int tas2552_codec_remove(struct snd_soc_codec *codec) 408{ 409 struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); 410 411 pm_runtime_put(codec->dev); 412 413 if (tas2552->enable_gpio) 414 gpiod_set_value(tas2552->enable_gpio, 0); 415 416 return 0; 417}; 418 419#ifdef CONFIG_PM 420static int tas2552_suspend(struct snd_soc_codec *codec) 421{ 422 struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); 423 int ret; 424 425 ret = regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies), 426 tas2552->supplies); 427 428 if (ret != 0) 429 dev_err(codec->dev, "Failed to disable supplies: %d\n", 430 ret); 431 return 0; 432} 433 434static int tas2552_resume(struct snd_soc_codec *codec) 435{ 436 struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec); 437 int ret; 438 439 ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies), 440 tas2552->supplies); 441 442 if (ret != 0) { 443 dev_err(codec->dev, "Failed to enable supplies: %d\n", 444 ret); 445 } 446 447 return 0; 448} 449#else 450#define tas2552_suspend NULL 451#define tas2552_resume NULL 452#endif 453 454static struct snd_soc_codec_driver soc_codec_dev_tas2552 = { 455 .probe = tas2552_codec_probe, 456 .remove = tas2552_codec_remove, 457 .suspend = tas2552_suspend, 458 .resume = tas2552_resume, 459 .controls = tas2552_snd_controls, 460 .num_controls = ARRAY_SIZE(tas2552_snd_controls), 461 .dapm_widgets = tas2552_dapm_widgets, 462 .num_dapm_widgets = ARRAY_SIZE(tas2552_dapm_widgets), 463 .dapm_routes = tas2552_audio_map, 464 .num_dapm_routes = ARRAY_SIZE(tas2552_audio_map), 465}; 466 467static const struct regmap_config tas2552_regmap_config = { 468 .reg_bits = 8, 469 .val_bits = 8, 470 471 .max_register = TAS2552_MAX_REG, 472 .reg_defaults = tas2552_reg_defs, 473 .num_reg_defaults = ARRAY_SIZE(tas2552_reg_defs), 474 .cache_type = REGCACHE_RBTREE, 475}; 476 477static int tas2552_probe(struct i2c_client *client, 478 const struct i2c_device_id *id) 479{ 480 struct device *dev; 481 struct tas2552_data *data; 482 int ret; 483 int i; 484 485 dev = &client->dev; 486 data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 487 if (data == NULL) 488 return -ENOMEM; 489 490 data->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); 491 if (IS_ERR(data->enable_gpio)) 492 return PTR_ERR(data->enable_gpio); 493 494 data->tas2552_client = client; 495 data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config); 496 if (IS_ERR(data->regmap)) { 497 ret = PTR_ERR(data->regmap); 498 dev_err(&client->dev, "Failed to allocate register map: %d\n", 499 ret); 500 return ret; 501 } 502 503 for (i = 0; i < ARRAY_SIZE(data->supplies); i++) 504 data->supplies[i].supply = tas2552_supply_names[i]; 505 506 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), 507 data->supplies); 508 if (ret != 0) { 509 dev_err(dev, "Failed to request supplies: %d\n", ret); 510 return ret; 511 } 512 513 pm_runtime_set_active(&client->dev); 514 pm_runtime_set_autosuspend_delay(&client->dev, 1000); 515 pm_runtime_use_autosuspend(&client->dev); 516 pm_runtime_enable(&client->dev); 517 pm_runtime_mark_last_busy(&client->dev); 518 pm_runtime_put_sync_autosuspend(&client->dev); 519 520 dev_set_drvdata(&client->dev, data); 521 522 ret = snd_soc_register_codec(&client->dev, 523 &soc_codec_dev_tas2552, 524 tas2552_dai, ARRAY_SIZE(tas2552_dai)); 525 if (ret < 0) 526 dev_err(&client->dev, "Failed to register codec: %d\n", ret); 527 528 return ret; 529} 530 531static int tas2552_i2c_remove(struct i2c_client *client) 532{ 533 snd_soc_unregister_codec(&client->dev); 534 return 0; 535} 536 537static const struct i2c_device_id tas2552_id[] = { 538 { "tas2552", 0 }, 539 { } 540}; 541MODULE_DEVICE_TABLE(i2c, tas2552_id); 542 543#if IS_ENABLED(CONFIG_OF) 544static const struct of_device_id tas2552_of_match[] = { 545 { .compatible = "ti,tas2552", }, 546 {}, 547}; 548MODULE_DEVICE_TABLE(of, tas2552_of_match); 549#endif 550 551static struct i2c_driver tas2552_i2c_driver = { 552 .driver = { 553 .name = "tas2552", 554 .owner = THIS_MODULE, 555 .of_match_table = of_match_ptr(tas2552_of_match), 556 .pm = &tas2552_pm, 557 }, 558 .probe = tas2552_probe, 559 .remove = tas2552_i2c_remove, 560 .id_table = tas2552_id, 561}; 562 563module_i2c_driver(tas2552_i2c_driver); 564 565MODULE_AUTHOR("Dan Muprhy <dmurphy@ti.com>"); 566MODULE_DESCRIPTION("TAS2552 Audio amplifier driver"); 567MODULE_LICENSE("GPL"); 568