linux/sound/soc/uniphier/evea.c
<<
>>
Prefs
   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");
 573