1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Socionext UniPhier EVEA ADC/DAC codec driver. 4 // 5 // Copyright (c) 2016-2017 Socionext Inc. 6 7 #include <linux/clk.h> 8 #include <linux/module.h> 9 #include <linux/of.h> 10 #include <linux/regmap.h> 11 #include <linux/reset.h> 12 #include <sound/pcm.h> 13 #include <sound/soc.h> 14 15 #define DRV_NAME "evea" 16 #define EVEA_RATES SNDRV_PCM_RATE_48000 17 #define EVEA_FORMATS SNDRV_PCM_FMTBIT_S32_LE 18 19 #define AADCPOW(n) (0x0078 + 0x04 * (n)) 20 #define AADCPOW_AADC_POWD BIT(0) 21 #define ALINSW1 0x0088 22 #define ALINSW1_SEL1_SHIFT 3 23 #define AHPOUTPOW 0x0098 24 #define AHPOUTPOW_HP_ON BIT(4) 25 #define ALINEPOW 0x009c 26 #define ALINEPOW_LIN2_POWD BIT(3) 27 #define ALINEPOW_LIN1_POWD BIT(4) 28 #define ALO1OUTPOW 0x00a8 29 #define ALO1OUTPOW_LO1_ON BIT(4) 30 #define ALO2OUTPOW 0x00ac 31 #define ALO2OUTPOW_ADAC2_MUTE BIT(0) 32 #define ALO2OUTPOW_LO2_ON BIT(4) 33 #define AANAPOW 0x00b8 34 #define AANAPOW_A_POWD BIT(4) 35 #define ADACSEQ1(n) (0x0144 + 0x40 * (n)) 36 #define ADACSEQ1_MMUTE BIT(1) 37 #define ADACSEQ2(n) (0x0160 + 0x40 * (n)) 38 #define ADACSEQ2_ADACIN_FIX BIT(0) 39 #define ADAC1ODC 0x0200 40 #define ADAC1ODC_HP_DIS_RES_MASK GENMASK(2, 1) 41 #define ADAC1ODC_HP_DIS_RES_OFF (0x0 << 1) 42 #define ADAC1ODC_HP_DIS_RES_ON (0x3 << 1) 43 #define ADAC1ODC_ADAC_RAMPCLT_MASK GENMASK(8, 7) 44 #define ADAC1ODC_ADAC_RAMPCLT_NORMAL (0x0 << 7) 45 #define ADAC1ODC_ADAC_RAMPCLT_REDUCE (0x1 << 7) 46 47 struct evea_priv { 48 struct clk *clk, *clk_exiv; 49 struct reset_control *rst, *rst_exiv, *rst_adamv; 50 struct regmap *regmap; 51 52 int switch_lin; 53 int switch_lo; 54 int switch_hp; 55 }; 56 57 static const char * const linsw1_sel1_text[] = { 58 "LIN1", "LIN2", "LIN3" 59 }; 60 61 static SOC_ENUM_SINGLE_DECL(linsw1_sel1_enum, 62 ALINSW1, ALINSW1_SEL1_SHIFT, 63 linsw1_sel1_text); 64 65 static const struct snd_kcontrol_new linesw1_mux[] = { 66 SOC_DAPM_ENUM("Line In 1 Source", linsw1_sel1_enum), 67 }; 68 69 static const struct snd_soc_dapm_widget evea_widgets[] = { 70 SND_SOC_DAPM_ADC("ADC", NULL, SND_SOC_NOPM, 0, 0), 71 SND_SOC_DAPM_MUX("Line In 1 Mux", SND_SOC_NOPM, 0, 0, linesw1_mux), 72 SND_SOC_DAPM_INPUT("LIN1_LP"), 73 SND_SOC_DAPM_INPUT("LIN1_RP"), 74 SND_SOC_DAPM_INPUT("LIN2_LP"), 75 SND_SOC_DAPM_INPUT("LIN2_RP"), 76 SND_SOC_DAPM_INPUT("LIN3_LP"), 77 SND_SOC_DAPM_INPUT("LIN3_RP"), 78 79 SND_SOC_DAPM_DAC("DAC HP", NULL, SND_SOC_NOPM, 0, 0), 80 SND_SOC_DAPM_DAC("DAC LO1", NULL, SND_SOC_NOPM, 0, 0), 81 SND_SOC_DAPM_DAC("DAC LO2", NULL, SND_SOC_NOPM, 0, 0), 82 SND_SOC_DAPM_OUTPUT("HP1_L"), 83 SND_SOC_DAPM_OUTPUT("HP1_R"), 84 SND_SOC_DAPM_OUTPUT("LO2_L"), 85 SND_SOC_DAPM_OUTPUT("LO2_R"), 86 }; 87 88 static const struct snd_soc_dapm_route evea_routes[] = { 89 { "Line In 1", NULL, "ADC" }, 90 { "ADC", NULL, "Line In 1 Mux" }, 91 { "Line In 1 Mux", "LIN1", "LIN1_LP" }, 92 { "Line In 1 Mux", "LIN1", "LIN1_RP" }, 93 { "Line In 1 Mux", "LIN2", "LIN2_LP" }, 94 { "Line In 1 Mux", "LIN2", "LIN2_RP" }, 95 { "Line In 1 Mux", "LIN3", "LIN3_LP" }, 96 { "Line In 1 Mux", "LIN3", "LIN3_RP" }, 97 98 { "DAC HP", NULL, "Headphone 1" }, 99 { "DAC LO1", NULL, "Line Out 1" }, 100 { "DAC LO2", NULL, "Line Out 2" }, 101 { "HP1_L", NULL, "DAC HP" }, 102 { "HP1_R", NULL, "DAC HP" }, 103 { "LO2_L", NULL, "DAC LO2" }, 104 { "LO2_R", NULL, "DAC LO2" }, 105 }; 106 107 static void evea_set_power_state_on(struct evea_priv *evea) 108 { 109 struct regmap *map = evea->regmap; 110 111 regmap_update_bits(map, AANAPOW, AANAPOW_A_POWD, 112 AANAPOW_A_POWD); 113 114 regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK, 115 ADAC1ODC_HP_DIS_RES_ON); 116 117 regmap_update_bits(map, ADAC1ODC, ADAC1ODC_ADAC_RAMPCLT_MASK, 118 ADAC1ODC_ADAC_RAMPCLT_REDUCE); 119 120 regmap_update_bits(map, ADACSEQ2(0), ADACSEQ2_ADACIN_FIX, 0); 121 regmap_update_bits(map, ADACSEQ2(1), ADACSEQ2_ADACIN_FIX, 0); 122 regmap_update_bits(map, ADACSEQ2(2), ADACSEQ2_ADACIN_FIX, 0); 123 } 124 125 static void evea_set_power_state_off(struct evea_priv *evea) 126 { 127 struct regmap *map = evea->regmap; 128 129 regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK, 130 ADAC1ODC_HP_DIS_RES_ON); 131 132 regmap_update_bits(map, ADACSEQ1(0), ADACSEQ1_MMUTE, 133 ADACSEQ1_MMUTE); 134 regmap_update_bits(map, ADACSEQ1(1), ADACSEQ1_MMUTE, 135 ADACSEQ1_MMUTE); 136 regmap_update_bits(map, ADACSEQ1(2), ADACSEQ1_MMUTE, 137 ADACSEQ1_MMUTE); 138 139 regmap_update_bits(map, ALO1OUTPOW, ALO1OUTPOW_LO1_ON, 0); 140 regmap_update_bits(map, ALO2OUTPOW, ALO2OUTPOW_LO2_ON, 0); 141 regmap_update_bits(map, AHPOUTPOW, AHPOUTPOW_HP_ON, 0); 142 } 143 144 static int evea_update_switch_lin(struct evea_priv *evea) 145 { 146 struct regmap *map = evea->regmap; 147 148 if (evea->switch_lin) { 149 regmap_update_bits(map, ALINEPOW, 150 ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD, 151 ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD); 152 153 regmap_update_bits(map, AADCPOW(0), AADCPOW_AADC_POWD, 154 AADCPOW_AADC_POWD); 155 regmap_update_bits(map, AADCPOW(1), AADCPOW_AADC_POWD, 156 AADCPOW_AADC_POWD); 157 } else { 158 regmap_update_bits(map, AADCPOW(0), AADCPOW_AADC_POWD, 0); 159 regmap_update_bits(map, AADCPOW(1), AADCPOW_AADC_POWD, 0); 160 161 regmap_update_bits(map, ALINEPOW, 162 ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD, 0); 163 } 164 165 return 0; 166 } 167 168 static int evea_update_switch_lo(struct evea_priv *evea) 169 { 170 struct regmap *map = evea->regmap; 171 172 if (evea->switch_lo) { 173 regmap_update_bits(map, ADACSEQ1(0), ADACSEQ1_MMUTE, 0); 174 regmap_update_bits(map, ADACSEQ1(2), ADACSEQ1_MMUTE, 0); 175 176 regmap_update_bits(map, ALO1OUTPOW, ALO1OUTPOW_LO1_ON, 177 ALO1OUTPOW_LO1_ON); 178 regmap_update_bits(map, ALO2OUTPOW, 179 ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON, 180 ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON); 181 } else { 182 regmap_update_bits(map, ADACSEQ1(0), ADACSEQ1_MMUTE, 183 ADACSEQ1_MMUTE); 184 regmap_update_bits(map, ADACSEQ1(2), ADACSEQ1_MMUTE, 185 ADACSEQ1_MMUTE); 186 187 regmap_update_bits(map, ALO1OUTPOW, ALO1OUTPOW_LO1_ON, 0); 188 regmap_update_bits(map, ALO2OUTPOW, 189 ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON, 190 0); 191 } 192 193 return 0; 194 } 195 196 static int evea_update_switch_hp(struct evea_priv *evea) 197 { 198 struct regmap *map = evea->regmap; 199 200 if (evea->switch_hp) { 201 regmap_update_bits(map, ADACSEQ1(1), ADACSEQ1_MMUTE, 0); 202 203 regmap_update_bits(map, AHPOUTPOW, AHPOUTPOW_HP_ON, 204 AHPOUTPOW_HP_ON); 205 206 regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK, 207 ADAC1ODC_HP_DIS_RES_OFF); 208 } else { 209 regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK, 210 ADAC1ODC_HP_DIS_RES_ON); 211 212 regmap_update_bits(map, ADACSEQ1(1), ADACSEQ1_MMUTE, 213 ADACSEQ1_MMUTE); 214 215 regmap_update_bits(map, AHPOUTPOW, AHPOUTPOW_HP_ON, 0); 216 } 217 218 return 0; 219 } 220 221 static void evea_update_switch_all(struct evea_priv *evea) 222 { 223 evea_update_switch_lin(evea); 224 evea_update_switch_lo(evea); 225 evea_update_switch_hp(evea); 226 } 227 228 static int evea_get_switch_lin(struct snd_kcontrol *kcontrol, 229 struct snd_ctl_elem_value *ucontrol) 230 { 231 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 232 struct evea_priv *evea = snd_soc_component_get_drvdata(component); 233 234 ucontrol->value.integer.value[0] = evea->switch_lin; 235 236 return 0; 237 } 238 239 static int evea_set_switch_lin(struct snd_kcontrol *kcontrol, 240 struct snd_ctl_elem_value *ucontrol) 241 { 242 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 243 struct evea_priv *evea = snd_soc_component_get_drvdata(component); 244 245 if (evea->switch_lin == ucontrol->value.integer.value[0]) 246 return 0; 247 248 evea->switch_lin = ucontrol->value.integer.value[0]; 249 250 return evea_update_switch_lin(evea); 251 } 252 253 static int evea_get_switch_lo(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 evea_priv *evea = snd_soc_component_get_drvdata(component); 258 259 ucontrol->value.integer.value[0] = evea->switch_lo; 260 261 return 0; 262 } 263 264 static int evea_set_switch_lo(struct snd_kcontrol *kcontrol, 265 struct snd_ctl_elem_value *ucontrol) 266 { 267 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 268 struct evea_priv *evea = snd_soc_component_get_drvdata(component); 269 270 if (evea->switch_lo == ucontrol->value.integer.value[0]) 271 return 0; 272 273 evea->switch_lo = ucontrol->value.integer.value[0]; 274 275 return evea_update_switch_lo(evea); 276 } 277 278 static int evea_get_switch_hp(struct snd_kcontrol *kcontrol, 279 struct snd_ctl_elem_value *ucontrol) 280 { 281 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 282 struct evea_priv *evea = snd_soc_component_get_drvdata(component); 283 284 ucontrol->value.integer.value[0] = evea->switch_hp; 285 286 return 0; 287 } 288 289 static int evea_set_switch_hp(struct snd_kcontrol *kcontrol, 290 struct snd_ctl_elem_value *ucontrol) 291 { 292 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 293 struct evea_priv *evea = snd_soc_component_get_drvdata(component); 294 295 if (evea->switch_hp == ucontrol->value.integer.value[0]) 296 return 0; 297 298 evea->switch_hp = ucontrol->value.integer.value[0]; 299 300 return evea_update_switch_hp(evea); 301 } 302 303 static const struct snd_kcontrol_new evea_controls[] = { 304 SOC_SINGLE_BOOL_EXT("Line Capture Switch", 0, 305 evea_get_switch_lin, evea_set_switch_lin), 306 SOC_SINGLE_BOOL_EXT("Line Playback Switch", 0, 307 evea_get_switch_lo, evea_set_switch_lo), 308 SOC_SINGLE_BOOL_EXT("Headphone Playback Switch", 0, 309 evea_get_switch_hp, evea_set_switch_hp), 310 }; 311 312 static int evea_codec_probe(struct snd_soc_component *component) 313 { 314 struct evea_priv *evea = snd_soc_component_get_drvdata(component); 315 316 evea->switch_lin = 1; 317 evea->switch_lo = 1; 318 evea->switch_hp = 1; 319 320 evea_set_power_state_on(evea); 321 evea_update_switch_all(evea); 322 323 return 0; 324 } 325 326 static int evea_codec_suspend(struct snd_soc_component *component) 327 { 328 struct evea_priv *evea = snd_soc_component_get_drvdata(component); 329 330 evea_set_power_state_off(evea); 331 332 reset_control_assert(evea->rst_adamv); 333 reset_control_assert(evea->rst_exiv); 334 reset_control_assert(evea->rst); 335 336 clk_disable_unprepare(evea->clk_exiv); 337 clk_disable_unprepare(evea->clk); 338 339 return 0; 340 } 341 342 static int evea_codec_resume(struct snd_soc_component *component) 343 { 344 struct evea_priv *evea = snd_soc_component_get_drvdata(component); 345 int ret; 346 347 ret = clk_prepare_enable(evea->clk); 348 if (ret) 349 return ret; 350 351 ret = clk_prepare_enable(evea->clk_exiv); 352 if (ret) 353 goto err_out_clock; 354 355 ret = reset_control_deassert(evea->rst); 356 if (ret) 357 goto err_out_clock_exiv; 358 359 ret = reset_control_deassert(evea->rst_exiv); 360 if (ret) 361 goto err_out_reset; 362 363 ret = reset_control_deassert(evea->rst_adamv); 364 if (ret) 365 goto err_out_reset_exiv; 366 367 evea_set_power_state_on(evea); 368 evea_update_switch_all(evea); 369 370 return 0; 371 372 err_out_reset_exiv: 373 reset_control_assert(evea->rst_exiv); 374 375 err_out_reset: 376 reset_control_assert(evea->rst); 377 378 err_out_clock_exiv: 379 clk_disable_unprepare(evea->clk_exiv); 380 381 err_out_clock: 382 clk_disable_unprepare(evea->clk); 383 384 return ret; 385 } 386 387 static struct snd_soc_component_driver soc_codec_evea = { 388 .probe = evea_codec_probe, 389 .suspend = evea_codec_suspend, 390 .resume = evea_codec_resume, 391 .dapm_widgets = evea_widgets, 392 .num_dapm_widgets = ARRAY_SIZE(evea_widgets), 393 .dapm_routes = evea_routes, 394 .num_dapm_routes = ARRAY_SIZE(evea_routes), 395 .controls = evea_controls, 396 .num_controls = ARRAY_SIZE(evea_controls), 397 .idle_bias_on = 1, 398 .use_pmdown_time = 1, 399 .endianness = 1, 400 }; 401 402 static struct snd_soc_dai_driver soc_dai_evea[] = { 403 { 404 .name = DRV_NAME "-line1", 405 .playback = { 406 .stream_name = "Line Out 1", 407 .formats = EVEA_FORMATS, 408 .rates = EVEA_RATES, 409 .channels_min = 2, 410 .channels_max = 2, 411 }, 412 .capture = { 413 .stream_name = "Line In 1", 414 .formats = EVEA_FORMATS, 415 .rates = EVEA_RATES, 416 .channels_min = 2, 417 .channels_max = 2, 418 }, 419 }, 420 { 421 .name = DRV_NAME "-hp1", 422 .playback = { 423 .stream_name = "Headphone 1", 424 .formats = EVEA_FORMATS, 425 .rates = EVEA_RATES, 426 .channels_min = 2, 427 .channels_max = 2, 428 }, 429 }, 430 { 431 .name = DRV_NAME "-lo2", 432 .playback = { 433 .stream_name = "Line Out 2", 434 .formats = EVEA_FORMATS, 435 .rates = EVEA_RATES, 436 .channels_min = 2, 437 .channels_max = 2, 438 }, 439 }, 440 }; 441 442 static const struct regmap_config evea_regmap_config = { 443 .reg_bits = 32, 444 .reg_stride = 4, 445 .val_bits = 32, 446 .max_register = 0xffc, 447 .cache_type = REGCACHE_NONE, 448 }; 449 450 static int evea_probe(struct platform_device *pdev) 451 { 452 struct evea_priv *evea; 453 void __iomem *preg; 454 int ret; 455 456 evea = devm_kzalloc(&pdev->dev, sizeof(struct evea_priv), GFP_KERNEL); 457 if (!evea) 458 return -ENOMEM; 459 460 evea->clk = devm_clk_get(&pdev->dev, "evea"); 461 if (IS_ERR(evea->clk)) 462 return PTR_ERR(evea->clk); 463 464 evea->clk_exiv = devm_clk_get(&pdev->dev, "exiv"); 465 if (IS_ERR(evea->clk_exiv)) 466 return PTR_ERR(evea->clk_exiv); 467 468 evea->rst = devm_reset_control_get_shared(&pdev->dev, "evea"); 469 if (IS_ERR(evea->rst)) 470 return PTR_ERR(evea->rst); 471 472 evea->rst_exiv = devm_reset_control_get_shared(&pdev->dev, "exiv"); 473 if (IS_ERR(evea->rst_exiv)) 474 return PTR_ERR(evea->rst_exiv); 475 476 preg = devm_platform_ioremap_resource(pdev, 0); 477 if (IS_ERR(preg)) 478 return PTR_ERR(preg); 479 480 evea->regmap = devm_regmap_init_mmio(&pdev->dev, preg, 481 &evea_regmap_config); 482 if (IS_ERR(evea->regmap)) 483 return PTR_ERR(evea->regmap); 484 485 ret = clk_prepare_enable(evea->clk); 486 if (ret) 487 return ret; 488 489 ret = clk_prepare_enable(evea->clk_exiv); 490 if (ret) 491 goto err_out_clock; 492 493 ret = reset_control_deassert(evea->rst); 494 if (ret) 495 goto err_out_clock_exiv; 496 497 ret = reset_control_deassert(evea->rst_exiv); 498 if (ret) 499 goto err_out_reset; 500 501 /* ADAMV will hangup if EXIV reset is asserted */ 502 evea->rst_adamv = devm_reset_control_get_shared(&pdev->dev, "adamv"); 503 if (IS_ERR(evea->rst_adamv)) { 504 ret = PTR_ERR(evea->rst_adamv); 505 goto err_out_reset_exiv; 506 } 507 508 ret = reset_control_deassert(evea->rst_adamv); 509 if (ret) 510 goto err_out_reset_exiv; 511 512 platform_set_drvdata(pdev, evea); 513 514 ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_evea, 515 soc_dai_evea, ARRAY_SIZE(soc_dai_evea)); 516 if (ret) 517 goto err_out_reset_adamv; 518 519 return 0; 520 521 err_out_reset_adamv: 522 reset_control_assert(evea->rst_adamv); 523 524 err_out_reset_exiv: 525 reset_control_assert(evea->rst_exiv); 526 527 err_out_reset: 528 reset_control_assert(evea->rst); 529 530 err_out_clock_exiv: 531 clk_disable_unprepare(evea->clk_exiv); 532 533 err_out_clock: 534 clk_disable_unprepare(evea->clk); 535 536 return ret; 537 } 538 539 static void evea_remove(struct platform_device *pdev) 540 { 541 struct evea_priv *evea = platform_get_drvdata(pdev); 542 543 reset_control_assert(evea->rst_adamv); 544 reset_control_assert(evea->rst_exiv); 545 reset_control_assert(evea->rst); 546 547 clk_disable_unprepare(evea->clk_exiv); 548 clk_disable_unprepare(evea->clk); 549 } 550 551 static const struct of_device_id evea_of_match[] __maybe_unused = { 552 { .compatible = "socionext,uniphier-evea", }, 553 {} 554 }; 555 MODULE_DEVICE_TABLE(of, evea_of_match); 556 557 static struct platform_driver evea_codec_driver = { 558 .driver = { 559 .name = DRV_NAME, 560 .of_match_table = of_match_ptr(evea_of_match), 561 }, 562 .probe = evea_probe, 563 .remove_new = evea_remove, 564 }; 565 module_platform_driver(evea_codec_driver); 566 567 MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>"); 568 MODULE_DESCRIPTION("UniPhier EVEA codec driver"); 569 MODULE_LICENSE("GPL v2"); 570
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.