linux/sound/soc/uniphier/aio-cpu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Socionext UniPhier AIO ALSA CPU DAI driver.
   4//
   5// Copyright (c) 2016-2018 Socionext Inc.
   6
   7#include <linux/clk.h>
   8#include <linux/errno.h>
   9#include <linux/kernel.h>
  10#include <linux/mfd/syscon.h>
  11#include <linux/module.h>
  12#include <linux/of.h>
  13#include <linux/of_platform.h>
  14#include <linux/platform_device.h>
  15#include <linux/reset.h>
  16#include <sound/core.h>
  17#include <sound/pcm.h>
  18#include <sound/pcm_params.h>
  19#include <sound/soc.h>
  20
  21#include "aio.h"
  22
  23static bool is_valid_pll(struct uniphier_aio_chip *chip, int pll_id)
  24{
  25        struct device *dev = &chip->pdev->dev;
  26
  27        if (pll_id < 0 || chip->num_plls <= pll_id) {
  28                dev_err(dev, "PLL(%d) is not supported\n", pll_id);
  29                return false;
  30        }
  31
  32        return chip->plls[pll_id].enable;
  33}
  34
  35/**
  36 * find_volume - find volume supported HW port by HW port number
  37 * @chip: the AIO chip pointer
  38 * @oport_hw: HW port number, one of AUD_HW_XXXX
  39 *
  40 * Find AIO device from device list by HW port number. Volume feature is
  41 * available only in Output and PCM ports, this limitation comes from HW
  42 * specifications.
  43 *
  44 * Return: The pointer of AIO substream if successful, otherwise NULL on error.
  45 */
  46static struct uniphier_aio_sub *find_volume(struct uniphier_aio_chip *chip,
  47                                            int oport_hw)
  48{
  49        int i;
  50
  51        for (i = 0; i < chip->num_aios; i++) {
  52                struct uniphier_aio_sub *sub = &chip->aios[i].sub[0];
  53
  54                if (!sub->swm)
  55                        continue;
  56
  57                if (sub->swm->oport.hw == oport_hw)
  58                        return sub;
  59        }
  60
  61        return NULL;
  62}
  63
  64static bool match_spec(const struct uniphier_aio_spec *spec,
  65                       const char *name, int dir)
  66{
  67        if (dir == SNDRV_PCM_STREAM_PLAYBACK &&
  68            spec->swm.dir != PORT_DIR_OUTPUT) {
  69                return false;
  70        }
  71
  72        if (dir == SNDRV_PCM_STREAM_CAPTURE &&
  73            spec->swm.dir != PORT_DIR_INPUT) {
  74                return false;
  75        }
  76
  77        if (spec->name && strcmp(spec->name, name) == 0)
  78                return true;
  79
  80        if (spec->gname && strcmp(spec->gname, name) == 0)
  81                return true;
  82
  83        return false;
  84}
  85
  86/**
  87 * find_spec - find HW specification info by name
  88 * @aio: the AIO device pointer
  89 * @name: name of device
  90 * @direction: the direction of substream, SNDRV_PCM_STREAM_*
  91 *
  92 * Find hardware specification information from list by device name. This
  93 * information is used for telling the difference of SoCs to driver.
  94 *
  95 * Specification list is array of 'struct uniphier_aio_spec' which is defined
  96 * in each drivers (see: aio-i2s.c).
  97 *
  98 * Return: The pointer of hardware specification of AIO if successful,
  99 * otherwise NULL on error.
 100 */
 101static const struct uniphier_aio_spec *find_spec(struct uniphier_aio *aio,
 102                                                 const char *name,
 103                                                 int direction)
 104{
 105        const struct uniphier_aio_chip_spec *chip_spec = aio->chip->chip_spec;
 106        int i;
 107
 108        for (i = 0; i < chip_spec->num_specs; i++) {
 109                const struct uniphier_aio_spec *spec = &chip_spec->specs[i];
 110
 111                if (match_spec(spec, name, direction))
 112                        return spec;
 113        }
 114
 115        return NULL;
 116}
 117
 118/**
 119 * find_divider - find clock divider by frequency
 120 * @aio: the AIO device pointer
 121 * @pll_id: PLL ID, should be AUD_PLL_XX
 122 * @freq: required frequency
 123 *
 124 * Find suitable clock divider by frequency.
 125 *
 126 * Return: The ID of PLL if successful, otherwise negative error value.
 127 */
 128static int find_divider(struct uniphier_aio *aio, int pll_id, unsigned int freq)
 129{
 130        struct uniphier_aio_pll *pll;
 131        static const int mul[] = { 1, 1, 1, 2, };
 132        static const int div[] = { 2, 3, 1, 3, };
 133        int i;
 134
 135        if (!is_valid_pll(aio->chip, pll_id))
 136                return -EINVAL;
 137
 138        pll = &aio->chip->plls[pll_id];
 139        for (i = 0; i < ARRAY_SIZE(mul); i++)
 140                if (pll->freq * mul[i] / div[i] == freq)
 141                        return i;
 142
 143        return -ENOTSUPP;
 144}
 145
 146static int uniphier_aio_set_sysclk(struct snd_soc_dai *dai, int clk_id,
 147                                   unsigned int freq, int dir)
 148{
 149        struct uniphier_aio *aio = uniphier_priv(dai);
 150        struct device *dev = &aio->chip->pdev->dev;
 151        bool pll_auto = false;
 152        int pll_id, div_id;
 153
 154        switch (clk_id) {
 155        case AUD_CLK_IO:
 156                return -ENOTSUPP;
 157        case AUD_CLK_A1:
 158                pll_id = AUD_PLL_A1;
 159                break;
 160        case AUD_CLK_F1:
 161                pll_id = AUD_PLL_F1;
 162                break;
 163        case AUD_CLK_A2:
 164                pll_id = AUD_PLL_A2;
 165                break;
 166        case AUD_CLK_F2:
 167                pll_id = AUD_PLL_F2;
 168                break;
 169        case AUD_CLK_A:
 170                pll_id = AUD_PLL_A1;
 171                pll_auto = true;
 172                break;
 173        case AUD_CLK_F:
 174                pll_id = AUD_PLL_F1;
 175                pll_auto = true;
 176                break;
 177        case AUD_CLK_APLL:
 178                pll_id = AUD_PLL_APLL;
 179                break;
 180        case AUD_CLK_RX0:
 181                pll_id = AUD_PLL_RX0;
 182                break;
 183        case AUD_CLK_USB0:
 184                pll_id = AUD_PLL_USB0;
 185                break;
 186        case AUD_CLK_HSC0:
 187                pll_id = AUD_PLL_HSC0;
 188                break;
 189        default:
 190                dev_err(dev, "Sysclk(%d) is not supported\n", clk_id);
 191                return -EINVAL;
 192        }
 193
 194        if (pll_auto) {
 195                for (pll_id = 0; pll_id < aio->chip->num_plls; pll_id++) {
 196                        div_id = find_divider(aio, pll_id, freq);
 197                        if (div_id >= 0) {
 198                                aio->plldiv = div_id;
 199                                break;
 200                        }
 201                }
 202                if (pll_id == aio->chip->num_plls) {
 203                        dev_err(dev, "Sysclk frequency is not supported(%d)\n",
 204                                freq);
 205                        return -EINVAL;
 206                }
 207        }
 208
 209        if (dir == SND_SOC_CLOCK_OUT)
 210                aio->pll_out = pll_id;
 211        else
 212                aio->pll_in = pll_id;
 213
 214        return 0;
 215}
 216
 217static int uniphier_aio_set_pll(struct snd_soc_dai *dai, int pll_id,
 218                                int source, unsigned int freq_in,
 219                                unsigned int freq_out)
 220{
 221        struct uniphier_aio *aio = uniphier_priv(dai);
 222        int ret;
 223
 224        if (!is_valid_pll(aio->chip, pll_id))
 225                return -EINVAL;
 226
 227        ret = aio_chip_set_pll(aio->chip, pll_id, freq_out);
 228        if (ret < 0)
 229                return ret;
 230
 231        return 0;
 232}
 233
 234static int uniphier_aio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 235{
 236        struct uniphier_aio *aio = uniphier_priv(dai);
 237        struct device *dev = &aio->chip->pdev->dev;
 238
 239        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 240        case SND_SOC_DAIFMT_LEFT_J:
 241        case SND_SOC_DAIFMT_RIGHT_J:
 242        case SND_SOC_DAIFMT_I2S:
 243                aio->fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
 244                break;
 245        default:
 246                dev_err(dev, "Format is not supported(%d)\n",
 247                        fmt & SND_SOC_DAIFMT_FORMAT_MASK);
 248                return -EINVAL;
 249        }
 250
 251        return 0;
 252}
 253
 254static int uniphier_aio_startup(struct snd_pcm_substream *substream,
 255                                struct snd_soc_dai *dai)
 256{
 257        struct uniphier_aio *aio = uniphier_priv(dai);
 258        struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
 259
 260        sub->substream = substream;
 261        sub->pass_through = 0;
 262        sub->use_mmap = true;
 263
 264        return aio_init(sub);
 265}
 266
 267static void uniphier_aio_shutdown(struct snd_pcm_substream *substream,
 268                                  struct snd_soc_dai *dai)
 269{
 270        struct uniphier_aio *aio = uniphier_priv(dai);
 271        struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
 272
 273        sub->substream = NULL;
 274}
 275
 276static int uniphier_aio_hw_params(struct snd_pcm_substream *substream,
 277                                  struct snd_pcm_hw_params *params,
 278                                  struct snd_soc_dai *dai)
 279{
 280        struct uniphier_aio *aio = uniphier_priv(dai);
 281        struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
 282        struct device *dev = &aio->chip->pdev->dev;
 283        int freq, ret;
 284
 285        switch (params_rate(params)) {
 286        case 48000:
 287        case 32000:
 288        case 24000:
 289                freq = 12288000;
 290                break;
 291        case 44100:
 292        case 22050:
 293                freq = 11289600;
 294                break;
 295        default:
 296                dev_err(dev, "Rate is not supported(%d)\n",
 297                        params_rate(params));
 298                return -EINVAL;
 299        }
 300        ret = snd_soc_dai_set_sysclk(dai, AUD_CLK_A,
 301                                     freq, SND_SOC_CLOCK_OUT);
 302        if (ret)
 303                return ret;
 304
 305        sub->params = *params;
 306        sub->setting = 1;
 307
 308        aio_port_reset(sub);
 309        aio_port_set_volume(sub, sub->vol);
 310        aio_src_reset(sub);
 311
 312        return 0;
 313}
 314
 315static int uniphier_aio_hw_free(struct snd_pcm_substream *substream,
 316                                struct snd_soc_dai *dai)
 317{
 318        struct uniphier_aio *aio = uniphier_priv(dai);
 319        struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
 320
 321        sub->setting = 0;
 322
 323        return 0;
 324}
 325
 326static int uniphier_aio_prepare(struct snd_pcm_substream *substream,
 327                                struct snd_soc_dai *dai)
 328{
 329        struct uniphier_aio *aio = uniphier_priv(dai);
 330        struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
 331        int ret;
 332
 333        ret = aio_port_set_param(sub, sub->pass_through, &sub->params);
 334        if (ret)
 335                return ret;
 336        ret = aio_src_set_param(sub, &sub->params);
 337        if (ret)
 338                return ret;
 339        aio_port_set_enable(sub, 1);
 340
 341        ret = aio_if_set_param(sub, sub->pass_through);
 342        if (ret)
 343                return ret;
 344
 345        if (sub->swm->type == PORT_TYPE_CONV) {
 346                ret = aio_srcif_set_param(sub);
 347                if (ret)
 348                        return ret;
 349                ret = aio_srcch_set_param(sub);
 350                if (ret)
 351                        return ret;
 352                aio_srcch_set_enable(sub, 1);
 353        }
 354
 355        return 0;
 356}
 357
 358static int uniphier_aio_dai_probe(struct snd_soc_dai *dai)
 359{
 360        struct uniphier_aio *aio = uniphier_priv(dai);
 361        int i;
 362
 363        for (i = 0; i < ARRAY_SIZE(aio->sub); i++) {
 364                struct uniphier_aio_sub *sub = &aio->sub[i];
 365                const struct uniphier_aio_spec *spec;
 366
 367                spec = find_spec(aio, dai->name, i);
 368                if (!spec)
 369                        continue;
 370
 371                sub->swm = &spec->swm;
 372                sub->spec = spec;
 373
 374                sub->vol = AUD_VOL_INIT;
 375        }
 376
 377        aio_iecout_set_enable(aio->chip, true);
 378        aio_chip_init(aio->chip);
 379        aio->chip->active = 1;
 380
 381        return 0;
 382}
 383
 384static int uniphier_aio_dai_remove(struct snd_soc_dai *dai)
 385{
 386        struct uniphier_aio *aio = uniphier_priv(dai);
 387
 388        aio->chip->active = 0;
 389
 390        return 0;
 391}
 392
 393static int uniphier_aio_ld11_probe(struct snd_soc_dai *dai)
 394{
 395        int ret;
 396
 397        ret = uniphier_aio_dai_probe(dai);
 398        if (ret < 0)
 399                return ret;
 400
 401        ret = snd_soc_dai_set_pll(dai, AUD_PLL_A1, 0, 0, 36864000);
 402        if (ret < 0)
 403                return ret;
 404        ret = snd_soc_dai_set_pll(dai, AUD_PLL_F1, 0, 0, 36864000);
 405        if (ret < 0)
 406                return ret;
 407
 408        ret = snd_soc_dai_set_pll(dai, AUD_PLL_A2, 0, 0, 33868800);
 409        if (ret < 0)
 410                return ret;
 411        ret = snd_soc_dai_set_pll(dai, AUD_PLL_F2, 0, 0, 33868800);
 412        if (ret < 0)
 413                return ret;
 414
 415        return 0;
 416}
 417
 418static int uniphier_aio_pxs2_probe(struct snd_soc_dai *dai)
 419{
 420        int ret;
 421
 422        ret = uniphier_aio_dai_probe(dai);
 423        if (ret < 0)
 424                return ret;
 425
 426        ret = snd_soc_dai_set_pll(dai, AUD_PLL_A1, 0, 0, 36864000);
 427        if (ret < 0)
 428                return ret;
 429        ret = snd_soc_dai_set_pll(dai, AUD_PLL_F1, 0, 0, 36864000);
 430        if (ret < 0)
 431                return ret;
 432
 433        ret = snd_soc_dai_set_pll(dai, AUD_PLL_A2, 0, 0, 33868800);
 434        if (ret < 0)
 435                return ret;
 436        ret = snd_soc_dai_set_pll(dai, AUD_PLL_F2, 0, 0, 33868800);
 437        if (ret < 0)
 438                return ret;
 439
 440        return 0;
 441}
 442
 443const struct snd_soc_dai_ops uniphier_aio_i2s_ld11_ops = {
 444        .probe          = uniphier_aio_ld11_probe,
 445        .remove         = uniphier_aio_dai_remove,
 446        .set_sysclk     = uniphier_aio_set_sysclk,
 447        .set_pll        = uniphier_aio_set_pll,
 448        .set_fmt        = uniphier_aio_set_fmt,
 449        .startup        = uniphier_aio_startup,
 450        .shutdown       = uniphier_aio_shutdown,
 451        .hw_params      = uniphier_aio_hw_params,
 452        .hw_free        = uniphier_aio_hw_free,
 453        .prepare        = uniphier_aio_prepare,
 454};
 455EXPORT_SYMBOL_GPL(uniphier_aio_i2s_ld11_ops);
 456
 457const struct snd_soc_dai_ops uniphier_aio_spdif_ld11_ops = {
 458        .probe          = uniphier_aio_ld11_probe,
 459        .remove         = uniphier_aio_dai_remove,
 460        .set_sysclk     = uniphier_aio_set_sysclk,
 461        .set_pll        = uniphier_aio_set_pll,
 462        .startup        = uniphier_aio_startup,
 463        .shutdown       = uniphier_aio_shutdown,
 464        .hw_params      = uniphier_aio_hw_params,
 465        .hw_free        = uniphier_aio_hw_free,
 466        .prepare        = uniphier_aio_prepare,
 467};
 468EXPORT_SYMBOL_GPL(uniphier_aio_spdif_ld11_ops);
 469
 470const struct snd_soc_dai_ops uniphier_aio_spdif_ld11_ops2 = {
 471        .probe          = uniphier_aio_ld11_probe,
 472        .remove         = uniphier_aio_dai_remove,
 473        .set_sysclk     = uniphier_aio_set_sysclk,
 474        .set_pll        = uniphier_aio_set_pll,
 475        .startup        = uniphier_aio_startup,
 476        .shutdown       = uniphier_aio_shutdown,
 477        .hw_params      = uniphier_aio_hw_params,
 478        .hw_free        = uniphier_aio_hw_free,
 479        .prepare        = uniphier_aio_prepare,
 480        .compress_new   = snd_soc_new_compress,
 481};
 482EXPORT_SYMBOL_GPL(uniphier_aio_spdif_ld11_ops2);
 483
 484const struct snd_soc_dai_ops uniphier_aio_i2s_pxs2_ops = {
 485        .probe          = uniphier_aio_pxs2_probe,
 486        .remove         = uniphier_aio_dai_remove,
 487        .set_sysclk     = uniphier_aio_set_sysclk,
 488        .set_pll        = uniphier_aio_set_pll,
 489        .set_fmt        = uniphier_aio_set_fmt,
 490        .startup        = uniphier_aio_startup,
 491        .shutdown       = uniphier_aio_shutdown,
 492        .hw_params      = uniphier_aio_hw_params,
 493        .hw_free        = uniphier_aio_hw_free,
 494        .prepare        = uniphier_aio_prepare,
 495};
 496EXPORT_SYMBOL_GPL(uniphier_aio_i2s_pxs2_ops);
 497
 498const struct snd_soc_dai_ops uniphier_aio_spdif_pxs2_ops = {
 499        .probe          = uniphier_aio_pxs2_probe,
 500        .remove         = uniphier_aio_dai_remove,
 501        .set_sysclk     = uniphier_aio_set_sysclk,
 502        .set_pll        = uniphier_aio_set_pll,
 503        .startup        = uniphier_aio_startup,
 504        .shutdown       = uniphier_aio_shutdown,
 505        .hw_params      = uniphier_aio_hw_params,
 506        .hw_free        = uniphier_aio_hw_free,
 507        .prepare        = uniphier_aio_prepare,
 508};
 509EXPORT_SYMBOL_GPL(uniphier_aio_spdif_pxs2_ops);
 510
 511const struct snd_soc_dai_ops uniphier_aio_spdif_pxs2_ops2 = {
 512        .probe          = uniphier_aio_pxs2_probe,
 513        .remove         = uniphier_aio_dai_remove,
 514        .set_sysclk     = uniphier_aio_set_sysclk,
 515        .set_pll        = uniphier_aio_set_pll,
 516        .startup        = uniphier_aio_startup,
 517        .shutdown       = uniphier_aio_shutdown,
 518        .hw_params      = uniphier_aio_hw_params,
 519        .hw_free        = uniphier_aio_hw_free,
 520        .prepare        = uniphier_aio_prepare,
 521        .compress_new   = snd_soc_new_compress,
 522};
 523EXPORT_SYMBOL_GPL(uniphier_aio_spdif_pxs2_ops2);
 524
 525static void uniphier_aio_dai_suspend(struct snd_soc_dai *dai)
 526{
 527        struct uniphier_aio *aio = uniphier_priv(dai);
 528
 529        if (!snd_soc_dai_active(dai))
 530                return;
 531
 532        aio->chip->num_wup_aios--;
 533        if (!aio->chip->num_wup_aios) {
 534                reset_control_assert(aio->chip->rst);
 535                clk_disable_unprepare(aio->chip->clk);
 536        }
 537}
 538
 539static int uniphier_aio_suspend(struct snd_soc_component *component)
 540{
 541        struct snd_soc_dai *dai;
 542
 543        for_each_component_dais(component, dai)
 544                uniphier_aio_dai_suspend(dai);
 545        return 0;
 546}
 547
 548static int uniphier_aio_dai_resume(struct snd_soc_dai *dai)
 549{
 550        struct uniphier_aio *aio = uniphier_priv(dai);
 551        int ret, i;
 552
 553        if (!snd_soc_dai_active(dai))
 554                return 0;
 555
 556        if (!aio->chip->active)
 557                return 0;
 558
 559        if (!aio->chip->num_wup_aios) {
 560                ret = clk_prepare_enable(aio->chip->clk);
 561                if (ret)
 562                        return ret;
 563
 564                ret = reset_control_deassert(aio->chip->rst);
 565                if (ret)
 566                        goto err_out_clock;
 567        }
 568
 569        aio_iecout_set_enable(aio->chip, true);
 570        aio_chip_init(aio->chip);
 571
 572        for (i = 0; i < ARRAY_SIZE(aio->sub); i++) {
 573                struct uniphier_aio_sub *sub = &aio->sub[i];
 574
 575                if (!sub->spec || !sub->substream)
 576                        continue;
 577
 578                ret = aio_init(sub);
 579                if (ret)
 580                        goto err_out_reset;
 581
 582                if (!sub->setting)
 583                        continue;
 584
 585                aio_port_reset(sub);
 586                aio_src_reset(sub);
 587        }
 588        aio->chip->num_wup_aios++;
 589
 590        return 0;
 591
 592err_out_reset:
 593        if (!aio->chip->num_wup_aios)
 594                reset_control_assert(aio->chip->rst);
 595err_out_clock:
 596        if (!aio->chip->num_wup_aios)
 597                clk_disable_unprepare(aio->chip->clk);
 598
 599        return ret;
 600}
 601
 602static int uniphier_aio_resume(struct snd_soc_component *component)
 603{
 604        struct snd_soc_dai *dai;
 605        int ret = 0;
 606
 607        for_each_component_dais(component, dai)
 608                ret |= uniphier_aio_dai_resume(dai);
 609        return ret;
 610}
 611
 612static int uniphier_aio_vol_info(struct snd_kcontrol *kcontrol,
 613                                 struct snd_ctl_elem_info *uinfo)
 614{
 615        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 616        uinfo->count = 1;
 617        uinfo->value.integer.min = 0;
 618        uinfo->value.integer.max = AUD_VOL_MAX;
 619
 620        return 0;
 621}
 622
 623static int uniphier_aio_vol_get(struct snd_kcontrol *kcontrol,
 624                                struct snd_ctl_elem_value *ucontrol)
 625{
 626        struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
 627        struct uniphier_aio_chip *chip = snd_soc_component_get_drvdata(comp);
 628        struct uniphier_aio_sub *sub;
 629        int oport_hw = kcontrol->private_value;
 630
 631        sub = find_volume(chip, oport_hw);
 632        if (!sub)
 633                return 0;
 634
 635        ucontrol->value.integer.value[0] = sub->vol;
 636
 637        return 0;
 638}
 639
 640static int uniphier_aio_vol_put(struct snd_kcontrol *kcontrol,
 641                                struct snd_ctl_elem_value *ucontrol)
 642{
 643        struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
 644        struct uniphier_aio_chip *chip = snd_soc_component_get_drvdata(comp);
 645        struct uniphier_aio_sub *sub;
 646        int oport_hw = kcontrol->private_value;
 647
 648        sub = find_volume(chip, oport_hw);
 649        if (!sub)
 650                return 0;
 651
 652        if (sub->vol == ucontrol->value.integer.value[0])
 653                return 0;
 654        sub->vol = ucontrol->value.integer.value[0];
 655
 656        aio_port_set_volume(sub, sub->vol);
 657
 658        return 0;
 659}
 660
 661static const struct snd_kcontrol_new uniphier_aio_controls[] = {
 662        {
 663                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 664                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 665                .name = "HPCMOUT1 Volume",
 666                .info = uniphier_aio_vol_info,
 667                .get = uniphier_aio_vol_get,
 668                .put = uniphier_aio_vol_put,
 669                .private_value = AUD_HW_HPCMOUT1,
 670        },
 671        {
 672                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 673                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 674                .name = "PCMOUT1 Volume",
 675                .info = uniphier_aio_vol_info,
 676                .get = uniphier_aio_vol_get,
 677                .put = uniphier_aio_vol_put,
 678                .private_value = AUD_HW_PCMOUT1,
 679        },
 680        {
 681                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 682                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 683                .name = "PCMOUT2 Volume",
 684                .info = uniphier_aio_vol_info,
 685                .get = uniphier_aio_vol_get,
 686                .put = uniphier_aio_vol_put,
 687                .private_value = AUD_HW_PCMOUT2,
 688        },
 689        {
 690                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 691                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 692                .name = "PCMOUT3 Volume",
 693                .info = uniphier_aio_vol_info,
 694                .get = uniphier_aio_vol_get,
 695                .put = uniphier_aio_vol_put,
 696                .private_value = AUD_HW_PCMOUT3,
 697        },
 698        {
 699                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 700                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 701                .name = "HIECOUT1 Volume",
 702                .info = uniphier_aio_vol_info,
 703                .get = uniphier_aio_vol_get,
 704                .put = uniphier_aio_vol_put,
 705                .private_value = AUD_HW_HIECOUT1,
 706        },
 707        {
 708                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 709                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 710                .name = "IECOUT1 Volume",
 711                .info = uniphier_aio_vol_info,
 712                .get = uniphier_aio_vol_get,
 713                .put = uniphier_aio_vol_put,
 714                .private_value = AUD_HW_IECOUT1,
 715        },
 716};
 717
 718static const struct snd_soc_component_driver uniphier_aio_component = {
 719        .name = "uniphier-aio",
 720        .controls = uniphier_aio_controls,
 721        .num_controls = ARRAY_SIZE(uniphier_aio_controls),
 722        .suspend = uniphier_aio_suspend,
 723        .resume  = uniphier_aio_resume,
 724};
 725
 726int uniphier_aio_probe(struct platform_device *pdev)
 727{
 728        struct uniphier_aio_chip *chip;
 729        struct device *dev = &pdev->dev;
 730        int ret, i, j;
 731
 732        chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
 733        if (!chip)
 734                return -ENOMEM;
 735
 736        chip->chip_spec = of_device_get_match_data(dev);
 737        if (!chip->chip_spec)
 738                return -EINVAL;
 739
 740        chip->regmap_sg = syscon_regmap_lookup_by_phandle(dev->of_node,
 741                                                          "socionext,syscon");
 742        if (IS_ERR(chip->regmap_sg)) {
 743                if (PTR_ERR(chip->regmap_sg) == -EPROBE_DEFER)
 744                        return -EPROBE_DEFER;
 745                chip->regmap_sg = NULL;
 746        }
 747
 748        chip->clk = devm_clk_get(dev, "aio");
 749        if (IS_ERR(chip->clk))
 750                return PTR_ERR(chip->clk);
 751
 752        chip->rst = devm_reset_control_get_shared(dev, "aio");
 753        if (IS_ERR(chip->rst))
 754                return PTR_ERR(chip->rst);
 755
 756        chip->num_aios = chip->chip_spec->num_dais;
 757        chip->num_wup_aios = chip->num_aios;
 758        chip->aios = devm_kcalloc(dev,
 759                                  chip->num_aios, sizeof(struct uniphier_aio),
 760                                  GFP_KERNEL);
 761        if (!chip->aios)
 762                return -ENOMEM;
 763
 764        chip->num_plls = chip->chip_spec->num_plls;
 765        chip->plls = devm_kmemdup_array(dev, chip->chip_spec->plls, chip->num_plls,
 766                                        sizeof(*chip->chip_spec->plls), GFP_KERNEL);
 767        if (!chip->plls)
 768                return -ENOMEM;
 769
 770        for (i = 0; i < chip->num_aios; i++) {
 771                struct uniphier_aio *aio = &chip->aios[i];
 772
 773                aio->chip = chip;
 774                aio->fmt = SND_SOC_DAIFMT_I2S;
 775
 776                for (j = 0; j < ARRAY_SIZE(aio->sub); j++) {
 777                        struct uniphier_aio_sub *sub = &aio->sub[j];
 778
 779                        sub->aio = aio;
 780                        spin_lock_init(&sub->lock);
 781                }
 782        }
 783
 784        chip->pdev = pdev;
 785        platform_set_drvdata(pdev, chip);
 786
 787        ret = clk_prepare_enable(chip->clk);
 788        if (ret)
 789                return ret;
 790
 791        ret = reset_control_deassert(chip->rst);
 792        if (ret)
 793                goto err_out_clock;
 794
 795        ret = devm_snd_soc_register_component(dev, &uniphier_aio_component,
 796                                              chip->chip_spec->dais,
 797                                              chip->chip_spec->num_dais);
 798        if (ret) {
 799                dev_err(dev, "Register component failed.\n");
 800                goto err_out_reset;
 801        }
 802
 803        ret = uniphier_aiodma_soc_register_platform(pdev);
 804        if (ret) {
 805                dev_err(dev, "Register platform failed.\n");
 806                goto err_out_reset;
 807        }
 808
 809        return 0;
 810
 811err_out_reset:
 812        reset_control_assert(chip->rst);
 813
 814err_out_clock:
 815        clk_disable_unprepare(chip->clk);
 816
 817        return ret;
 818}
 819EXPORT_SYMBOL_GPL(uniphier_aio_probe);
 820
 821void uniphier_aio_remove(struct platform_device *pdev)
 822{
 823        struct uniphier_aio_chip *chip = platform_get_drvdata(pdev);
 824
 825        reset_control_assert(chip->rst);
 826        clk_disable_unprepare(chip->clk);
 827}
 828EXPORT_SYMBOL_GPL(uniphier_aio_remove);
 829
 830MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
 831MODULE_DESCRIPTION("UniPhier AIO CPU DAI driver.");
 832MODULE_LICENSE("GPL v2");
 833