1 /* 2 * ALSA SoC TWL6040 codec driver 3 * 4 * Author: Misael Lopez Cruz <x0052729@ti.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * version 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18 * 02110-1301 USA 19 * 20 */ 21 22 #include <linux/module.h> 23 #include <linux/moduleparam.h> 24 #include <linux/init.h> 25 #include <linux/delay.h> 26 #include <linux/pm.h> 27 #include <linux/platform_device.h> 28 #include <linux/slab.h> 29 #include <linux/mfd/twl6040.h> 30 31 #include <sound/core.h> 32 #include <sound/pcm.h> 33 #include <sound/pcm_params.h> 34 #include <sound/soc.h> 35 #include <sound/soc-dapm.h> 36 #include <sound/initval.h> 37 #include <sound/tlv.h> 38 39 #include "twl6040.h" 40 41 enum twl6040_dai_id { 42 TWL6040_DAI_LEGACY = 0, 43 TWL6040_DAI_UL, 44 TWL6040_DAI_DL1, 45 TWL6040_DAI_DL2, 46 TWL6040_DAI_VIB, 47 }; 48 49 #define TWL6040_RATES SNDRV_PCM_RATE_8000_96000 50 #define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) 51 52 #define TWL6040_OUTHS_0dB 0x00 53 #define TWL6040_OUTHS_M30dB 0x0F 54 #define TWL6040_OUTHF_0dB 0x03 55 #define TWL6040_OUTHF_M52dB 0x1D 56 57 #define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1) 58 59 struct twl6040_jack_data { 60 struct snd_soc_jack *jack; 61 struct delayed_work work; 62 int report; 63 }; 64 65 /* codec private data */ 66 struct twl6040_data { 67 int plug_irq; 68 int codec_powered; 69 int pll; 70 int pll_power_mode; 71 int hs_power_mode; 72 int hs_power_mode_locked; 73 bool dl1_unmuted; 74 bool dl2_unmuted; 75 u8 dl12_cache[TWL6040_REG_HFRCTL - TWL6040_REG_HSLCTL + 1]; 76 unsigned int clk_in; 77 unsigned int sysclk; 78 struct twl6040_jack_data hs_jack; 79 struct snd_soc_codec *codec; 80 struct mutex mutex; 81 }; 82 83 /* set of rates for each pll: low-power and high-performance */ 84 static unsigned int lp_rates[] = { 85 8000, 86 11250, 87 16000, 88 22500, 89 32000, 90 44100, 91 48000, 92 88200, 93 96000, 94 }; 95 96 static unsigned int hp_rates[] = { 97 8000, 98 16000, 99 32000, 100 48000, 101 96000, 102 }; 103 104 static struct snd_pcm_hw_constraint_list sysclk_constraints[] = { 105 { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, }, 106 { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, 107 }; 108 109 static unsigned int twl6040_read(struct snd_soc_codec *codec, unsigned int reg) 110 { 111 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 112 struct twl6040 *twl6040 = codec->control_data; 113 u8 value; 114 115 if (reg >= TWL6040_CACHEREGNUM) 116 return -EIO; 117 118 switch (reg) { 119 case TWL6040_REG_HSLCTL: 120 case TWL6040_REG_HSRCTL: 121 case TWL6040_REG_EARCTL: 122 case TWL6040_REG_HFLCTL: 123 case TWL6040_REG_HFRCTL: 124 value = priv->dl12_cache[reg - TWL6040_REG_HSLCTL]; 125 break; 126 default: 127 value = twl6040_reg_read(twl6040, reg); 128 break; 129 } 130 131 return value; 132 } 133 134 static bool twl6040_can_write_to_chip(struct snd_soc_codec *codec, 135 unsigned int reg) 136 { 137 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 138 139 switch (reg) { 140 case TWL6040_REG_HSLCTL: 141 case TWL6040_REG_HSRCTL: 142 case TWL6040_REG_EARCTL: 143 /* DL1 path */ 144 return priv->dl1_unmuted; 145 case TWL6040_REG_HFLCTL: 146 case TWL6040_REG_HFRCTL: 147 return priv->dl2_unmuted; 148 default: 149 return 1; 150 } 151 } 152 153 static inline void twl6040_update_dl12_cache(struct snd_soc_codec *codec, 154 u8 reg, u8 value) 155 { 156 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 157 158 switch (reg) { 159 case TWL6040_REG_HSLCTL: 160 case TWL6040_REG_HSRCTL: 161 case TWL6040_REG_EARCTL: 162 case TWL6040_REG_HFLCTL: 163 case TWL6040_REG_HFRCTL: 164 priv->dl12_cache[reg - TWL6040_REG_HSLCTL] = value; 165 break; 166 default: 167 break; 168 } 169 } 170 171 static int twl6040_write(struct snd_soc_codec *codec, 172 unsigned int reg, unsigned int value) 173 { 174 struct twl6040 *twl6040 = codec->control_data; 175 176 if (reg >= TWL6040_CACHEREGNUM) 177 return -EIO; 178 179 twl6040_update_dl12_cache(codec, reg, value); 180 if (twl6040_can_write_to_chip(codec, reg)) 181 return twl6040_reg_write(twl6040, reg, value); 182 else 183 return 0; 184 } 185 186 static void twl6040_init_chip(struct snd_soc_codec *codec) 187 { 188 twl6040_read(codec, TWL6040_REG_TRIM1); 189 twl6040_read(codec, TWL6040_REG_TRIM2); 190 twl6040_read(codec, TWL6040_REG_TRIM3); 191 twl6040_read(codec, TWL6040_REG_HSOTRIM); 192 twl6040_read(codec, TWL6040_REG_HFOTRIM); 193 194 /* Change chip defaults */ 195 /* No imput selected for microphone amplifiers */ 196 twl6040_write(codec, TWL6040_REG_MICLCTL, 0x18); 197 twl6040_write(codec, TWL6040_REG_MICRCTL, 0x18); 198 199 /* 200 * We need to lower the default gain values, so the ramp code 201 * can work correctly for the first playback. 202 * This reduces the pop noise heard at the first playback. 203 */ 204 twl6040_write(codec, TWL6040_REG_HSGAIN, 0xff); 205 twl6040_write(codec, TWL6040_REG_EARCTL, 0x1e); 206 twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1d); 207 twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1d); 208 twl6040_write(codec, TWL6040_REG_LINEGAIN, 0); 209 } 210 211 /* set headset dac and driver power mode */ 212 static int headset_power_mode(struct snd_soc_codec *codec, int high_perf) 213 { 214 int hslctl, hsrctl; 215 int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE; 216 217 hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL); 218 hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL); 219 220 if (high_perf) { 221 hslctl &= ~mask; 222 hsrctl &= ~mask; 223 } else { 224 hslctl |= mask; 225 hsrctl |= mask; 226 } 227 228 twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl); 229 twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl); 230 231 return 0; 232 } 233 234 static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w, 235 struct snd_kcontrol *kcontrol, int event) 236 { 237 struct snd_soc_codec *codec = w->codec; 238 u8 hslctl, hsrctl; 239 240 /* 241 * Workaround for Headset DC offset caused pop noise: 242 * Both HS DAC need to be turned on (before the HS driver) and off at 243 * the same time. 244 */ 245 hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL); 246 hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL); 247 if (SND_SOC_DAPM_EVENT_ON(event)) { 248 hslctl |= TWL6040_HSDACENA; 249 hsrctl |= TWL6040_HSDACENA; 250 } else { 251 hslctl &= ~TWL6040_HSDACENA; 252 hsrctl &= ~TWL6040_HSDACENA; 253 } 254 twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl); 255 twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl); 256 257 msleep(1); 258 return 0; 259 } 260 261 static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w, 262 struct snd_kcontrol *kcontrol, int event) 263 { 264 struct snd_soc_codec *codec = w->codec; 265 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 266 int ret = 0; 267 268 if (SND_SOC_DAPM_EVENT_ON(event)) { 269 /* Earphone doesn't support low power mode */ 270 priv->hs_power_mode_locked = 1; 271 ret = headset_power_mode(codec, 1); 272 } else { 273 priv->hs_power_mode_locked = 0; 274 ret = headset_power_mode(codec, priv->hs_power_mode); 275 } 276 277 msleep(1); 278 279 return ret; 280 } 281 282 static void twl6040_hs_jack_report(struct snd_soc_codec *codec, 283 struct snd_soc_jack *jack, int report) 284 { 285 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 286 int status; 287 288 mutex_lock(&priv->mutex); 289 290 /* Sync status */ 291 status = twl6040_read(codec, TWL6040_REG_STATUS); 292 if (status & TWL6040_PLUGCOMP) 293 snd_soc_jack_report(jack, report, report); 294 else 295 snd_soc_jack_report(jack, 0, report); 296 297 mutex_unlock(&priv->mutex); 298 } 299 300 void twl6040_hs_jack_detect(struct snd_soc_codec *codec, 301 struct snd_soc_jack *jack, int report) 302 { 303 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 304 struct twl6040_jack_data *hs_jack = &priv->hs_jack; 305 306 hs_jack->jack = jack; 307 hs_jack->report = report; 308 309 twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report); 310 } 311 EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect); 312 313 static void twl6040_accessory_work(struct work_struct *work) 314 { 315 struct twl6040_data *priv = container_of(work, 316 struct twl6040_data, hs_jack.work.work); 317 struct snd_soc_codec *codec = priv->codec; 318 struct twl6040_jack_data *hs_jack = &priv->hs_jack; 319 320 twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report); 321 } 322 323 /* audio interrupt handler */ 324 static irqreturn_t twl6040_audio_handler(int irq, void *data) 325 { 326 struct snd_soc_codec *codec = data; 327 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 328 329 queue_delayed_work(system_power_efficient_wq, 330 &priv->hs_jack.work, msecs_to_jiffies(200)); 331 332 return IRQ_HANDLED; 333 } 334 335 static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol, 336 struct snd_ctl_elem_value *ucontrol) 337 { 338 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); 339 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 340 unsigned int val; 341 342 /* Do not allow changes while Input/FF efect is running */ 343 val = twl6040_read(codec, e->reg); 344 if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL)) 345 return -EBUSY; 346 347 return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); 348 } 349 350 /* 351 * MICATT volume control: 352 * from -6 to 0 dB in 6 dB steps 353 */ 354 static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0); 355 356 /* 357 * MICGAIN volume control: 358 * from 6 to 30 dB in 6 dB steps 359 */ 360 static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0); 361 362 /* 363 * AFMGAIN volume control: 364 * from -18 to 24 dB in 6 dB steps 365 */ 366 static DECLARE_TLV_DB_SCALE(afm_amp_tlv, -1800, 600, 0); 367 368 /* 369 * HSGAIN volume control: 370 * from -30 to 0 dB in 2 dB steps 371 */ 372 static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0); 373 374 /* 375 * HFGAIN volume control: 376 * from -52 to 6 dB in 2 dB steps 377 */ 378 static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0); 379 380 /* 381 * EPGAIN volume control: 382 * from -24 to 6 dB in 2 dB steps 383 */ 384 static DECLARE_TLV_DB_SCALE(ep_tlv, -2400, 200, 0); 385 386 /* Left analog microphone selection */ 387 static const char *twl6040_amicl_texts[] = 388 {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"}; 389 390 /* Right analog microphone selection */ 391 static const char *twl6040_amicr_texts[] = 392 {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"}; 393 394 static const struct soc_enum twl6040_enum[] = { 395 SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 4, twl6040_amicl_texts), 396 SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 4, twl6040_amicr_texts), 397 }; 398 399 static const char *twl6040_hs_texts[] = { 400 "Off", "HS DAC", "Line-In amp" 401 }; 402 403 static const struct soc_enum twl6040_hs_enum[] = { 404 SOC_ENUM_SINGLE(TWL6040_REG_HSLCTL, 5, ARRAY_SIZE(twl6040_hs_texts), 405 twl6040_hs_texts), 406 SOC_ENUM_SINGLE(TWL6040_REG_HSRCTL, 5, ARRAY_SIZE(twl6040_hs_texts), 407 twl6040_hs_texts), 408 }; 409 410 static const char *twl6040_hf_texts[] = { 411 "Off", "HF DAC", "Line-In amp" 412 }; 413 414 static const struct soc_enum twl6040_hf_enum[] = { 415 SOC_ENUM_SINGLE(TWL6040_REG_HFLCTL, 2, ARRAY_SIZE(twl6040_hf_texts), 416 twl6040_hf_texts), 417 SOC_ENUM_SINGLE(TWL6040_REG_HFRCTL, 2, ARRAY_SIZE(twl6040_hf_texts), 418 twl6040_hf_texts), 419 }; 420 421 static const char *twl6040_vibrapath_texts[] = { 422 "Input FF", "Audio PDM" 423 }; 424 425 static const struct soc_enum twl6040_vibra_enum[] = { 426 SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLL, 1, 427 ARRAY_SIZE(twl6040_vibrapath_texts), 428 twl6040_vibrapath_texts), 429 SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLR, 1, 430 ARRAY_SIZE(twl6040_vibrapath_texts), 431 twl6040_vibrapath_texts), 432 }; 433 434 static const struct snd_kcontrol_new amicl_control = 435 SOC_DAPM_ENUM("Route", twl6040_enum[0]); 436 437 static const struct snd_kcontrol_new amicr_control = 438 SOC_DAPM_ENUM("Route", twl6040_enum[1]); 439 440 /* Headset DAC playback switches */ 441 static const struct snd_kcontrol_new hsl_mux_controls = 442 SOC_DAPM_ENUM("Route", twl6040_hs_enum[0]); 443 444 static const struct snd_kcontrol_new hsr_mux_controls = 445 SOC_DAPM_ENUM("Route", twl6040_hs_enum[1]); 446 447 /* Handsfree DAC playback switches */ 448 static const struct snd_kcontrol_new hfl_mux_controls = 449 SOC_DAPM_ENUM("Route", twl6040_hf_enum[0]); 450 451 static const struct snd_kcontrol_new hfr_mux_controls = 452 SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]); 453 454 static const struct snd_kcontrol_new ep_path_enable_control = 455 SOC_DAPM_SINGLE_VIRT("Switch", 1); 456 457 static const struct snd_kcontrol_new auxl_switch_control = 458 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0); 459 460 static const struct snd_kcontrol_new auxr_switch_control = 461 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0); 462 463 /* Vibra playback switches */ 464 static const struct snd_kcontrol_new vibral_mux_controls = 465 SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[0], 466 snd_soc_dapm_get_enum_double, 467 twl6040_soc_dapm_put_vibra_enum); 468 469 static const struct snd_kcontrol_new vibrar_mux_controls = 470 SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[1], 471 snd_soc_dapm_get_enum_double, 472 twl6040_soc_dapm_put_vibra_enum); 473 474 /* Headset power mode */ 475 static const char *twl6040_power_mode_texts[] = { 476 "Low-Power", "High-Performance", 477 }; 478 479 static const struct soc_enum twl6040_power_mode_enum = 480 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_power_mode_texts), 481 twl6040_power_mode_texts); 482 483 static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol, 484 struct snd_ctl_elem_value *ucontrol) 485 { 486 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 487 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 488 489 ucontrol->value.enumerated.item[0] = priv->hs_power_mode; 490 491 return 0; 492 } 493 494 static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol, 495 struct snd_ctl_elem_value *ucontrol) 496 { 497 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 498 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 499 int high_perf = ucontrol->value.enumerated.item[0]; 500 int ret = 0; 501 502 if (!priv->hs_power_mode_locked) 503 ret = headset_power_mode(codec, high_perf); 504 505 if (!ret) 506 priv->hs_power_mode = high_perf; 507 508 return ret; 509 } 510 511 static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol, 512 struct snd_ctl_elem_value *ucontrol) 513 { 514 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 515 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 516 517 ucontrol->value.enumerated.item[0] = priv->pll_power_mode; 518 519 return 0; 520 } 521 522 static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol, 523 struct snd_ctl_elem_value *ucontrol) 524 { 525 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 526 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 527 528 priv->pll_power_mode = ucontrol->value.enumerated.item[0]; 529 530 return 0; 531 } 532 533 int twl6040_get_dl1_gain(struct snd_soc_codec *codec) 534 { 535 struct snd_soc_dapm_context *dapm = &codec->dapm; 536 537 if (snd_soc_dapm_get_pin_status(dapm, "EP")) 538 return -1; /* -1dB */ 539 540 if (snd_soc_dapm_get_pin_status(dapm, "HSOR") || 541 snd_soc_dapm_get_pin_status(dapm, "HSOL")) { 542 543 u8 val = snd_soc_read(codec, TWL6040_REG_HSLCTL); 544 if (val & TWL6040_HSDACMODE) 545 /* HSDACL in LP mode */ 546 return -8; /* -8dB */ 547 else 548 /* HSDACL in HP mode */ 549 return -1; /* -1dB */ 550 } 551 return 0; /* 0dB */ 552 } 553 EXPORT_SYMBOL_GPL(twl6040_get_dl1_gain); 554 555 int twl6040_get_clk_id(struct snd_soc_codec *codec) 556 { 557 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 558 559 return priv->pll_power_mode; 560 } 561 EXPORT_SYMBOL_GPL(twl6040_get_clk_id); 562 563 int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim) 564 { 565 if (unlikely(trim >= TWL6040_TRIM_INVAL)) 566 return -EINVAL; 567 568 return twl6040_read(codec, TWL6040_REG_TRIM1 + trim); 569 } 570 EXPORT_SYMBOL_GPL(twl6040_get_trim_value); 571 572 int twl6040_get_hs_step_size(struct snd_soc_codec *codec) 573 { 574 struct twl6040 *twl6040 = codec->control_data; 575 576 if (twl6040_get_revid(twl6040) < TWL6040_REV_ES1_3) 577 /* For ES under ES_1.3 HS step is 2 mV */ 578 return 2; 579 else 580 /* For ES_1.3 HS step is 1 mV */ 581 return 1; 582 } 583 EXPORT_SYMBOL_GPL(twl6040_get_hs_step_size); 584 585 static const struct snd_kcontrol_new twl6040_snd_controls[] = { 586 /* Capture gains */ 587 SOC_DOUBLE_TLV("Capture Preamplifier Volume", 588 TWL6040_REG_MICGAIN, 6, 7, 1, 1, mic_preamp_tlv), 589 SOC_DOUBLE_TLV("Capture Volume", 590 TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv), 591 592 /* AFM gains */ 593 SOC_DOUBLE_TLV("Aux FM Volume", 594 TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv), 595 596 /* Playback gains */ 597 SOC_DOUBLE_TLV("Headset Playback Volume", 598 TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv), 599 SOC_DOUBLE_R_TLV("Handsfree Playback Volume", 600 TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv), 601 SOC_SINGLE_TLV("Earphone Playback Volume", 602 TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv), 603 604 SOC_ENUM_EXT("Headset Power Mode", twl6040_power_mode_enum, 605 twl6040_headset_power_get_enum, 606 twl6040_headset_power_put_enum), 607 608 SOC_ENUM_EXT("PLL Selection", twl6040_power_mode_enum, 609 twl6040_pll_get_enum, twl6040_pll_put_enum), 610 }; 611 612 static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { 613 /* Inputs */ 614 SND_SOC_DAPM_INPUT("MAINMIC"), 615 SND_SOC_DAPM_INPUT("HSMIC"), 616 SND_SOC_DAPM_INPUT("SUBMIC"), 617 SND_SOC_DAPM_INPUT("AFML"), 618 SND_SOC_DAPM_INPUT("AFMR"), 619 620 /* Outputs */ 621 SND_SOC_DAPM_OUTPUT("HSOL"), 622 SND_SOC_DAPM_OUTPUT("HSOR"), 623 SND_SOC_DAPM_OUTPUT("HFL"), 624 SND_SOC_DAPM_OUTPUT("HFR"), 625 SND_SOC_DAPM_OUTPUT("EP"), 626 SND_SOC_DAPM_OUTPUT("AUXL"), 627 SND_SOC_DAPM_OUTPUT("AUXR"), 628 SND_SOC_DAPM_OUTPUT("VIBRAL"), 629 SND_SOC_DAPM_OUTPUT("VIBRAR"), 630 631 /* Analog input muxes for the capture amplifiers */ 632 SND_SOC_DAPM_MUX("Analog Left Capture Route", 633 SND_SOC_NOPM, 0, 0, &amicl_control), 634 SND_SOC_DAPM_MUX("Analog Right Capture Route", 635 SND_SOC_NOPM, 0, 0, &amicr_control), 636 637 /* Analog capture PGAs */ 638 SND_SOC_DAPM_PGA("MicAmpL", 639 TWL6040_REG_MICLCTL, 0, 0, NULL, 0), 640 SND_SOC_DAPM_PGA("MicAmpR", 641 TWL6040_REG_MICRCTL, 0, 0, NULL, 0), 642 643 /* Auxiliary FM PGAs */ 644 SND_SOC_DAPM_PGA("AFMAmpL", 645 TWL6040_REG_MICLCTL, 1, 0, NULL, 0), 646 SND_SOC_DAPM_PGA("AFMAmpR", 647 TWL6040_REG_MICRCTL, 1, 0, NULL, 0), 648 649 /* ADCs */ 650 SND_SOC_DAPM_ADC("ADC Left", NULL, TWL6040_REG_MICLCTL, 2, 0), 651 SND_SOC_DAPM_ADC("ADC Right", NULL, TWL6040_REG_MICRCTL, 2, 0), 652 653 /* Microphone bias */ 654 SND_SOC_DAPM_SUPPLY("Headset Mic Bias", 655 TWL6040_REG_AMICBCTL, 0, 0, NULL, 0), 656 SND_SOC_DAPM_SUPPLY("Main Mic Bias", 657 TWL6040_REG_AMICBCTL, 4, 0, NULL, 0), 658 SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias", 659 TWL6040_REG_DMICBCTL, 0, 0, NULL, 0), 660 SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias", 661 TWL6040_REG_DMICBCTL, 4, 0, NULL, 0), 662 663 /* DACs */ 664 SND_SOC_DAPM_DAC("HSDAC Left", NULL, SND_SOC_NOPM, 0, 0), 665 SND_SOC_DAPM_DAC("HSDAC Right", NULL, SND_SOC_NOPM, 0, 0), 666 SND_SOC_DAPM_DAC("HFDAC Left", NULL, TWL6040_REG_HFLCTL, 0, 0), 667 SND_SOC_DAPM_DAC("HFDAC Right", NULL, TWL6040_REG_HFRCTL, 0, 0), 668 /* Virtual DAC for vibra path (DL4 channel) */ 669 SND_SOC_DAPM_DAC("VIBRA DAC", NULL, SND_SOC_NOPM, 0, 0), 670 671 SND_SOC_DAPM_MUX("Handsfree Left Playback", 672 SND_SOC_NOPM, 0, 0, &hfl_mux_controls), 673 SND_SOC_DAPM_MUX("Handsfree Right Playback", 674 SND_SOC_NOPM, 0, 0, &hfr_mux_controls), 675 /* Analog playback Muxes */ 676 SND_SOC_DAPM_MUX("Headset Left Playback", 677 SND_SOC_NOPM, 0, 0, &hsl_mux_controls), 678 SND_SOC_DAPM_MUX("Headset Right Playback", 679 SND_SOC_NOPM, 0, 0, &hsr_mux_controls), 680 681 SND_SOC_DAPM_MUX("Vibra Left Playback", SND_SOC_NOPM, 0, 0, 682 &vibral_mux_controls), 683 SND_SOC_DAPM_MUX("Vibra Right Playback", SND_SOC_NOPM, 0, 0, 684 &vibrar_mux_controls), 685 686 SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0, 687 &ep_path_enable_control), 688 SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0, 689 &auxl_switch_control), 690 SND_SOC_DAPM_SWITCH("AUXR Playback", SND_SOC_NOPM, 0, 0, 691 &auxr_switch_control), 692 693 /* Analog playback drivers */ 694 SND_SOC_DAPM_OUT_DRV("HF Left Driver", 695 TWL6040_REG_HFLCTL, 4, 0, NULL, 0), 696 SND_SOC_DAPM_OUT_DRV("HF Right Driver", 697 TWL6040_REG_HFRCTL, 4, 0, NULL, 0), 698 SND_SOC_DAPM_OUT_DRV("HS Left Driver", 699 TWL6040_REG_HSLCTL, 2, 0, NULL, 0), 700 SND_SOC_DAPM_OUT_DRV("HS Right Driver", 701 TWL6040_REG_HSRCTL, 2, 0, NULL, 0), 702 SND_SOC_DAPM_OUT_DRV_E("Earphone Driver", 703 TWL6040_REG_EARCTL, 0, 0, NULL, 0, 704 twl6040_ep_drv_event, 705 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 706 SND_SOC_DAPM_OUT_DRV("Vibra Left Driver", 707 TWL6040_REG_VIBCTLL, 0, 0, NULL, 0), 708 SND_SOC_DAPM_OUT_DRV("Vibra Right Driver", 709 TWL6040_REG_VIBCTLR, 0, 0, NULL, 0), 710 711 SND_SOC_DAPM_SUPPLY("Vibra Left Control", TWL6040_REG_VIBCTLL, 2, 0, 712 NULL, 0), 713 SND_SOC_DAPM_SUPPLY("Vibra Right Control", TWL6040_REG_VIBCTLR, 2, 0, 714 NULL, 0), 715 SND_SOC_DAPM_SUPPLY_S("HSDAC Power", 1, SND_SOC_NOPM, 0, 0, 716 twl6040_hs_dac_event, 717 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 718 719 /* Analog playback PGAs */ 720 SND_SOC_DAPM_PGA("HF Left PGA", 721 TWL6040_REG_HFLCTL, 1, 0, NULL, 0), 722 SND_SOC_DAPM_PGA("HF Right PGA", 723 TWL6040_REG_HFRCTL, 1, 0, NULL, 0), 724 725 }; 726 727 static const struct snd_soc_dapm_route intercon[] = { 728 /* Stream -> DAC mapping */ 729 {"HSDAC Left", NULL, "Legacy Playback"}, 730 {"HSDAC Left", NULL, "Headset Playback"}, 731 {"HSDAC Right", NULL, "Legacy Playback"}, 732 {"HSDAC Right", NULL, "Headset Playback"}, 733 734 {"HFDAC Left", NULL, "Legacy Playback"}, 735 {"HFDAC Left", NULL, "Handsfree Playback"}, 736 {"HFDAC Right", NULL, "Legacy Playback"}, 737 {"HFDAC Right", NULL, "Handsfree Playback"}, 738 739 {"VIBRA DAC", NULL, "Legacy Playback"}, 740 {"VIBRA DAC", NULL, "Vibra Playback"}, 741 742 /* ADC -> Stream mapping */ 743 {"Legacy Capture" , NULL, "ADC Left"}, 744 {"Capture", NULL, "ADC Left"}, 745 {"Legacy Capture", NULL, "ADC Right"}, 746 {"Capture" , NULL, "ADC Right"}, 747 748 /* Capture path */ 749 {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, 750 {"Analog Left Capture Route", "Main Mic", "MAINMIC"}, 751 {"Analog Left Capture Route", "Aux/FM Left", "AFML"}, 752 753 {"Analog Right Capture Route", "Headset Mic", "HSMIC"}, 754 {"Analog Right Capture Route", "Sub Mic", "SUBMIC"}, 755 {"Analog Right Capture Route", "Aux/FM Right", "AFMR"}, 756 757 {"MicAmpL", NULL, "Analog Left Capture Route"}, 758 {"MicAmpR", NULL, "Analog Right Capture Route"}, 759 760 {"ADC Left", NULL, "MicAmpL"}, 761 {"ADC Right", NULL, "MicAmpR"}, 762 763 /* AFM path */ 764 {"AFMAmpL", NULL, "AFML"}, 765 {"AFMAmpR", NULL, "AFMR"}, 766 767 {"HSDAC Left", NULL, "HSDAC Power"}, 768 {"HSDAC Right", NULL, "HSDAC Power"}, 769 770 {"Headset Left Playback", "HS DAC", "HSDAC Left"}, 771 {"Headset Left Playback", "Line-In amp", "AFMAmpL"}, 772 773 {"Headset Right Playback", "HS DAC", "HSDAC Right"}, 774 {"Headset Right Playback", "Line-In amp", "AFMAmpR"}, 775 776 {"HS Left Driver", NULL, "Headset Left Playback"}, 777 {"HS Right Driver", NULL, "Headset Right Playback"}, 778 779 {"HSOL", NULL, "HS Left Driver"}, 780 {"HSOR", NULL, "HS Right Driver"}, 781 782 /* Earphone playback path */ 783 {"Earphone Playback", "Switch", "HSDAC Left"}, 784 {"Earphone Driver", NULL, "Earphone Playback"}, 785 {"EP", NULL, "Earphone Driver"}, 786 787 {"Handsfree Left Playback", "HF DAC", "HFDAC Left"}, 788 {"Handsfree Left Playback", "Line-In amp", "AFMAmpL"}, 789 790 {"Handsfree Right Playback", "HF DAC", "HFDAC Right"}, 791 {"Handsfree Right Playback", "Line-In amp", "AFMAmpR"}, 792 793 {"HF Left PGA", NULL, "Handsfree Left Playback"}, 794 {"HF Right PGA", NULL, "Handsfree Right Playback"}, 795 796 {"HF Left Driver", NULL, "HF Left PGA"}, 797 {"HF Right Driver", NULL, "HF Right PGA"}, 798 799 {"HFL", NULL, "HF Left Driver"}, 800 {"HFR", NULL, "HF Right Driver"}, 801 802 {"AUXL Playback", "Switch", "HF Left PGA"}, 803 {"AUXR Playback", "Switch", "HF Right PGA"}, 804 805 {"AUXL", NULL, "AUXL Playback"}, 806 {"AUXR", NULL, "AUXR Playback"}, 807 808 /* Vibrator paths */ 809 {"Vibra Left Playback", "Audio PDM", "VIBRA DAC"}, 810 {"Vibra Right Playback", "Audio PDM", "VIBRA DAC"}, 811 812 {"Vibra Left Driver", NULL, "Vibra Left Playback"}, 813 {"Vibra Right Driver", NULL, "Vibra Right Playback"}, 814 {"Vibra Left Driver", NULL, "Vibra Left Control"}, 815 {"Vibra Right Driver", NULL, "Vibra Right Control"}, 816 817 {"VIBRAL", NULL, "Vibra Left Driver"}, 818 {"VIBRAR", NULL, "Vibra Right Driver"}, 819 }; 820 821 static int twl6040_set_bias_level(struct snd_soc_codec *codec, 822 enum snd_soc_bias_level level) 823 { 824 struct twl6040 *twl6040 = codec->control_data; 825 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 826 int ret; 827 828 switch (level) { 829 case SND_SOC_BIAS_ON: 830 break; 831 case SND_SOC_BIAS_PREPARE: 832 break; 833 case SND_SOC_BIAS_STANDBY: 834 if (priv->codec_powered) 835 break; 836 837 ret = twl6040_power(twl6040, 1); 838 if (ret) 839 return ret; 840 841 priv->codec_powered = 1; 842 843 /* Set external boost GPO */ 844 twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); 845 break; 846 case SND_SOC_BIAS_OFF: 847 if (!priv->codec_powered) 848 break; 849 850 twl6040_power(twl6040, 0); 851 priv->codec_powered = 0; 852 break; 853 } 854 855 codec->dapm.bias_level = level; 856 857 return 0; 858 } 859 860 static int twl6040_startup(struct snd_pcm_substream *substream, 861 struct snd_soc_dai *dai) 862 { 863 struct snd_soc_codec *codec = dai->codec; 864 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 865 866 snd_pcm_hw_constraint_list(substream->runtime, 0, 867 SNDRV_PCM_HW_PARAM_RATE, 868 &sysclk_constraints[priv->pll_power_mode]); 869 870 return 0; 871 } 872 873 static int twl6040_hw_params(struct snd_pcm_substream *substream, 874 struct snd_pcm_hw_params *params, 875 struct snd_soc_dai *dai) 876 { 877 struct snd_soc_codec *codec = dai->codec; 878 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 879 int rate; 880 881 rate = params_rate(params); 882 switch (rate) { 883 case 11250: 884 case 22500: 885 case 44100: 886 case 88200: 887 /* These rates are not supported when HPPLL is in use */ 888 if (unlikely(priv->pll == TWL6040_SYSCLK_SEL_HPPLL)) { 889 dev_err(codec->dev, "HPPLL does not support rate %d\n", 890 rate); 891 return -EINVAL; 892 } 893 priv->sysclk = 17640000; 894 break; 895 case 8000: 896 case 16000: 897 case 32000: 898 case 48000: 899 case 96000: 900 priv->sysclk = 19200000; 901 break; 902 default: 903 dev_err(codec->dev, "unsupported rate %d\n", rate); 904 return -EINVAL; 905 } 906 907 return 0; 908 } 909 910 static int twl6040_prepare(struct snd_pcm_substream *substream, 911 struct snd_soc_dai *dai) 912 { 913 struct snd_soc_codec *codec = dai->codec; 914 struct twl6040 *twl6040 = codec->control_data; 915 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 916 int ret; 917 918 if (!priv->sysclk) { 919 dev_err(codec->dev, 920 "no mclk configured, call set_sysclk() on init\n"); 921 return -EINVAL; 922 } 923 924 ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk); 925 if (ret) { 926 dev_err(codec->dev, "Can not set PLL (%d)\n", ret); 927 return -EPERM; 928 } 929 930 return 0; 931 } 932 933 static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, 934 int clk_id, unsigned int freq, int dir) 935 { 936 struct snd_soc_codec *codec = codec_dai->codec; 937 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 938 939 switch (clk_id) { 940 case TWL6040_SYSCLK_SEL_LPPLL: 941 case TWL6040_SYSCLK_SEL_HPPLL: 942 priv->pll = clk_id; 943 priv->clk_in = freq; 944 break; 945 default: 946 dev_err(codec->dev, "unknown clk_id %d\n", clk_id); 947 return -EINVAL; 948 } 949 950 return 0; 951 } 952 953 static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id id, 954 int mute) 955 { 956 struct twl6040 *twl6040 = codec->control_data; 957 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 958 int hslctl, hsrctl, earctl; 959 int hflctl, hfrctl; 960 961 switch (id) { 962 case TWL6040_DAI_DL1: 963 hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL); 964 hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL); 965 earctl = twl6040_read(codec, TWL6040_REG_EARCTL); 966 967 if (mute) { 968 /* Power down drivers and DACs */ 969 earctl &= ~0x01; 970 hslctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA); 971 hsrctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA); 972 973 } 974 975 twl6040_reg_write(twl6040, TWL6040_REG_EARCTL, earctl); 976 twl6040_reg_write(twl6040, TWL6040_REG_HSLCTL, hslctl); 977 twl6040_reg_write(twl6040, TWL6040_REG_HSRCTL, hsrctl); 978 priv->dl1_unmuted = !mute; 979 break; 980 case TWL6040_DAI_DL2: 981 hflctl = twl6040_read(codec, TWL6040_REG_HFLCTL); 982 hfrctl = twl6040_read(codec, TWL6040_REG_HFRCTL); 983 984 if (mute) { 985 /* Power down drivers and DACs */ 986 hflctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | 987 TWL6040_HFDRVENA); 988 hfrctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | 989 TWL6040_HFDRVENA); 990 } 991 992 twl6040_reg_write(twl6040, TWL6040_REG_HFLCTL, hflctl); 993 twl6040_reg_write(twl6040, TWL6040_REG_HFRCTL, hfrctl); 994 priv->dl2_unmuted = !mute; 995 break; 996 default: 997 break; 998 } 999 } 1000 1001 static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute) 1002 { 1003 switch (dai->id) { 1004 case TWL6040_DAI_LEGACY: 1005 twl6040_mute_path(dai->codec, TWL6040_DAI_DL1, mute); 1006 twl6040_mute_path(dai->codec, TWL6040_DAI_DL2, mute); 1007 break; 1008 case TWL6040_DAI_DL1: 1009 case TWL6040_DAI_DL2: 1010 twl6040_mute_path(dai->codec, dai->id, mute); 1011 break; 1012 default: 1013 break; 1014 } 1015 1016 return 0; 1017 } 1018 1019 static const struct snd_soc_dai_ops twl6040_dai_ops = { 1020 .startup = twl6040_startup, 1021 .hw_params = twl6040_hw_params, 1022 .prepare = twl6040_prepare, 1023 .set_sysclk = twl6040_set_dai_sysclk, 1024 .digital_mute = twl6040_digital_mute, 1025 }; 1026 1027 static struct snd_soc_dai_driver twl6040_dai[] = { 1028 { 1029 .name = "twl6040-legacy", 1030 .id = TWL6040_DAI_LEGACY, 1031 .playback = { 1032 .stream_name = "Legacy Playback", 1033 .channels_min = 1, 1034 .channels_max = 5, 1035 .rates = TWL6040_RATES, 1036 .formats = TWL6040_FORMATS, 1037 }, 1038 .capture = { 1039 .stream_name = "Legacy Capture", 1040 .channels_min = 1, 1041 .channels_max = 2, 1042 .rates = TWL6040_RATES, 1043 .formats = TWL6040_FORMATS, 1044 }, 1045 .ops = &twl6040_dai_ops, 1046 }, 1047 { 1048 .name = "twl6040-ul", 1049 .id = TWL6040_DAI_UL, 1050 .capture = { 1051 .stream_name = "Capture", 1052 .channels_min = 1, 1053 .channels_max = 2, 1054 .rates = TWL6040_RATES, 1055 .formats = TWL6040_FORMATS, 1056 }, 1057 .ops = &twl6040_dai_ops, 1058 }, 1059 { 1060 .name = "twl6040-dl1", 1061 .id = TWL6040_DAI_DL1, 1062 .playback = { 1063 .stream_name = "Headset Playback", 1064 .channels_min = 1, 1065 .channels_max = 2, 1066 .rates = TWL6040_RATES, 1067 .formats = TWL6040_FORMATS, 1068 }, 1069 .ops = &twl6040_dai_ops, 1070 }, 1071 { 1072 .name = "twl6040-dl2", 1073 .id = TWL6040_DAI_DL2, 1074 .playback = { 1075 .stream_name = "Handsfree Playback", 1076 .channels_min = 1, 1077 .channels_max = 2, 1078 .rates = TWL6040_RATES, 1079 .formats = TWL6040_FORMATS, 1080 }, 1081 .ops = &twl6040_dai_ops, 1082 }, 1083 { 1084 .name = "twl6040-vib", 1085 .id = TWL6040_DAI_VIB, 1086 .playback = { 1087 .stream_name = "Vibra Playback", 1088 .channels_min = 1, 1089 .channels_max = 1, 1090 .rates = SNDRV_PCM_RATE_CONTINUOUS, 1091 .formats = TWL6040_FORMATS, 1092 }, 1093 .ops = &twl6040_dai_ops, 1094 }, 1095 }; 1096 1097 #ifdef CONFIG_PM 1098 static int twl6040_suspend(struct snd_soc_codec *codec) 1099 { 1100 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); 1101 1102 return 0; 1103 } 1104 1105 static int twl6040_resume(struct snd_soc_codec *codec) 1106 { 1107 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1108 1109 return 0; 1110 } 1111 #else 1112 #define twl6040_suspend NULL 1113 #define twl6040_resume NULL 1114 #endif 1115 1116 static int twl6040_probe(struct snd_soc_codec *codec) 1117 { 1118 struct twl6040_data *priv; 1119 struct twl6040 *twl6040 = dev_get_drvdata(codec->dev->parent); 1120 struct platform_device *pdev = container_of(codec->dev, 1121 struct platform_device, dev); 1122 int ret = 0; 1123 1124 priv = devm_kzalloc(codec->dev, sizeof(*priv), GFP_KERNEL); 1125 if (priv == NULL) 1126 return -ENOMEM; 1127 1128 snd_soc_codec_set_drvdata(codec, priv); 1129 1130 priv->codec = codec; 1131 codec->control_data = twl6040; 1132 1133 priv->plug_irq = platform_get_irq(pdev, 0); 1134 if (priv->plug_irq < 0) { 1135 dev_err(codec->dev, "invalid irq\n"); 1136 return -EINVAL; 1137 } 1138 1139 INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work); 1140 1141 mutex_init(&priv->mutex); 1142 1143 ret = request_threaded_irq(priv->plug_irq, NULL, 1144 twl6040_audio_handler, IRQF_NO_SUSPEND, 1145 "twl6040_irq_plug", codec); 1146 if (ret) { 1147 dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret); 1148 return ret; 1149 } 1150 1151 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1152 twl6040_init_chip(codec); 1153 1154 return 0; 1155 } 1156 1157 static int twl6040_remove(struct snd_soc_codec *codec) 1158 { 1159 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1160 1161 free_irq(priv->plug_irq, codec); 1162 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); 1163 1164 return 0; 1165 } 1166 1167 static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { 1168 .probe = twl6040_probe, 1169 .remove = twl6040_remove, 1170 .suspend = twl6040_suspend, 1171 .resume = twl6040_resume, 1172 .read = twl6040_read, 1173 .write = twl6040_write, 1174 .set_bias_level = twl6040_set_bias_level, 1175 .ignore_pmdown_time = true, 1176 1177 .controls = twl6040_snd_controls, 1178 .num_controls = ARRAY_SIZE(twl6040_snd_controls), 1179 .dapm_widgets = twl6040_dapm_widgets, 1180 .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets), 1181 .dapm_routes = intercon, 1182 .num_dapm_routes = ARRAY_SIZE(intercon), 1183 }; 1184 1185 static int twl6040_codec_probe(struct platform_device *pdev) 1186 { 1187 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl6040, 1188 twl6040_dai, ARRAY_SIZE(twl6040_dai)); 1189 } 1190 1191 static int twl6040_codec_remove(struct platform_device *pdev) 1192 { 1193 snd_soc_unregister_codec(&pdev->dev); 1194 return 0; 1195 } 1196 1197 static struct platform_driver twl6040_codec_driver = { 1198 .driver = { 1199 .name = "twl6040-codec", 1200 .owner = THIS_MODULE, 1201 }, 1202 .probe = twl6040_codec_probe, 1203 .remove = twl6040_codec_remove, 1204 }; 1205 1206 module_platform_driver(twl6040_codec_driver); 1207 1208 MODULE_DESCRIPTION("ASoC TWL6040 codec driver"); 1209 MODULE_AUTHOR("Misael Lopez Cruz"); 1210 MODULE_LICENSE("GPL"); 1211