root/sound/soc/uniphier/evea.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. evea_set_power_state_on
  2. evea_set_power_state_off
  3. evea_update_switch_lin
  4. evea_update_switch_lo
  5. evea_update_switch_hp
  6. evea_update_switch_all
  7. evea_get_switch_lin
  8. evea_set_switch_lin
  9. evea_get_switch_lo
  10. evea_set_switch_lo
  11. evea_get_switch_hp
  12. evea_set_switch_hp
  13. evea_codec_probe
  14. evea_codec_suspend
  15. evea_codec_resume
  16. evea_probe
  17. evea_remove

   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         .non_legacy_dai_naming  = 1,
 401 };
 402 
 403 static 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 
 443 static 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 
 451 static 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 
 522 err_out_reset_adamv:
 523         reset_control_assert(evea->rst_adamv);
 524 
 525 err_out_reset_exiv:
 526         reset_control_assert(evea->rst_exiv);
 527 
 528 err_out_reset:
 529         reset_control_assert(evea->rst);
 530 
 531 err_out_clock_exiv:
 532         clk_disable_unprepare(evea->clk_exiv);
 533 
 534 err_out_clock:
 535         clk_disable_unprepare(evea->clk);
 536 
 537         return ret;
 538 }
 539 
 540 static 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 
 554 static const struct of_device_id evea_of_match[] = {
 555         { .compatible = "socionext,uniphier-evea", },
 556         {}
 557 };
 558 MODULE_DEVICE_TABLE(of, evea_of_match);
 559 
 560 static 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 };
 568 module_platform_driver(evea_codec_driver);
 569 
 570 MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
 571 MODULE_DESCRIPTION("UniPhier EVEA codec driver");
 572 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */