evea.c (15524B)
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 47struct 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 57static const char * const linsw1_sel1_text[] = { 58 "LIN1", "LIN2", "LIN3" 59}; 60 61static SOC_ENUM_SINGLE_DECL(linsw1_sel1_enum, 62 ALINSW1, ALINSW1_SEL1_SHIFT, 63 linsw1_sel1_text); 64 65static const struct snd_kcontrol_new linesw1_mux[] = { 66 SOC_DAPM_ENUM("Line In 1 Source", linsw1_sel1_enum), 67}; 68 69static 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 88static 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 107static 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 125static 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 144static 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 168static 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 196static 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 221static 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 228static 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 239static 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 253static 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 264static 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 278static 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 289static 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 303static 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 312static 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 326static 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 342static 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 372err_out_reset_exiv: 373 reset_control_assert(evea->rst_exiv); 374 375err_out_reset: 376 reset_control_assert(evea->rst); 377 378err_out_clock_exiv: 379 clk_disable_unprepare(evea->clk_exiv); 380 381err_out_clock: 382 clk_disable_unprepare(evea->clk); 383 384 return ret; 385} 386 387static 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 .non_legacy_dai_naming = 1, 401}; 402 403static struct snd_soc_dai_driver soc_dai_evea[] = { 404 { 405 .name = DRV_NAME "-line1", 406 .playback = { 407 .stream_name = "Line Out 1", 408 .formats = EVEA_FORMATS, 409 .rates = EVEA_RATES, 410 .channels_min = 2, 411 .channels_max = 2, 412 }, 413 .capture = { 414 .stream_name = "Line In 1", 415 .formats = EVEA_FORMATS, 416 .rates = EVEA_RATES, 417 .channels_min = 2, 418 .channels_max = 2, 419 }, 420 }, 421 { 422 .name = DRV_NAME "-hp1", 423 .playback = { 424 .stream_name = "Headphone 1", 425 .formats = EVEA_FORMATS, 426 .rates = EVEA_RATES, 427 .channels_min = 2, 428 .channels_max = 2, 429 }, 430 }, 431 { 432 .name = DRV_NAME "-lo2", 433 .playback = { 434 .stream_name = "Line Out 2", 435 .formats = EVEA_FORMATS, 436 .rates = EVEA_RATES, 437 .channels_min = 2, 438 .channels_max = 2, 439 }, 440 }, 441}; 442 443static const struct regmap_config evea_regmap_config = { 444 .reg_bits = 32, 445 .reg_stride = 4, 446 .val_bits = 32, 447 .max_register = 0xffc, 448 .cache_type = REGCACHE_NONE, 449}; 450 451static int evea_probe(struct platform_device *pdev) 452{ 453 struct evea_priv *evea; 454 void __iomem *preg; 455 int ret; 456 457 evea = devm_kzalloc(&pdev->dev, sizeof(struct evea_priv), GFP_KERNEL); 458 if (!evea) 459 return -ENOMEM; 460 461 evea->clk = devm_clk_get(&pdev->dev, "evea"); 462 if (IS_ERR(evea->clk)) 463 return PTR_ERR(evea->clk); 464 465 evea->clk_exiv = devm_clk_get(&pdev->dev, "exiv"); 466 if (IS_ERR(evea->clk_exiv)) 467 return PTR_ERR(evea->clk_exiv); 468 469 evea->rst = devm_reset_control_get_shared(&pdev->dev, "evea"); 470 if (IS_ERR(evea->rst)) 471 return PTR_ERR(evea->rst); 472 473 evea->rst_exiv = devm_reset_control_get_shared(&pdev->dev, "exiv"); 474 if (IS_ERR(evea->rst_exiv)) 475 return PTR_ERR(evea->rst_exiv); 476 477 preg = devm_platform_ioremap_resource(pdev, 0); 478 if (IS_ERR(preg)) 479 return PTR_ERR(preg); 480 481 evea->regmap = devm_regmap_init_mmio(&pdev->dev, preg, 482 &evea_regmap_config); 483 if (IS_ERR(evea->regmap)) 484 return PTR_ERR(evea->regmap); 485 486 ret = clk_prepare_enable(evea->clk); 487 if (ret) 488 return ret; 489 490 ret = clk_prepare_enable(evea->clk_exiv); 491 if (ret) 492 goto err_out_clock; 493 494 ret = reset_control_deassert(evea->rst); 495 if (ret) 496 goto err_out_clock_exiv; 497 498 ret = reset_control_deassert(evea->rst_exiv); 499 if (ret) 500 goto err_out_reset; 501 502 /* ADAMV will hangup if EXIV reset is asserted */ 503 evea->rst_adamv = devm_reset_control_get_shared(&pdev->dev, "adamv"); 504 if (IS_ERR(evea->rst_adamv)) { 505 ret = PTR_ERR(evea->rst_adamv); 506 goto err_out_reset_exiv; 507 } 508 509 ret = reset_control_deassert(evea->rst_adamv); 510 if (ret) 511 goto err_out_reset_exiv; 512 513 platform_set_drvdata(pdev, evea); 514 515 ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_evea, 516 soc_dai_evea, ARRAY_SIZE(soc_dai_evea)); 517 if (ret) 518 goto err_out_reset_adamv; 519 520 return 0; 521 522err_out_reset_adamv: 523 reset_control_assert(evea->rst_adamv); 524 525err_out_reset_exiv: 526 reset_control_assert(evea->rst_exiv); 527 528err_out_reset: 529 reset_control_assert(evea->rst); 530 531err_out_clock_exiv: 532 clk_disable_unprepare(evea->clk_exiv); 533 534err_out_clock: 535 clk_disable_unprepare(evea->clk); 536 537 return ret; 538} 539 540static int evea_remove(struct platform_device *pdev) 541{ 542 struct evea_priv *evea = platform_get_drvdata(pdev); 543 544 reset_control_assert(evea->rst_adamv); 545 reset_control_assert(evea->rst_exiv); 546 reset_control_assert(evea->rst); 547 548 clk_disable_unprepare(evea->clk_exiv); 549 clk_disable_unprepare(evea->clk); 550 551 return 0; 552} 553 554static const struct of_device_id evea_of_match[] __maybe_unused = { 555 { .compatible = "socionext,uniphier-evea", }, 556 {} 557}; 558MODULE_DEVICE_TABLE(of, evea_of_match); 559 560static struct platform_driver evea_codec_driver = { 561 .driver = { 562 .name = DRV_NAME, 563 .of_match_table = of_match_ptr(evea_of_match), 564 }, 565 .probe = evea_probe, 566 .remove = evea_remove, 567}; 568module_platform_driver(evea_codec_driver); 569 570MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>"); 571MODULE_DESCRIPTION("UniPhier EVEA codec driver"); 572MODULE_LICENSE("GPL v2");