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
 358const struct snd_soc_dai_ops uniphier_aio_i2s_ops = {
 359        .set_sysclk  = uniphier_aio_set_sysclk,
 360        .set_pll     = uniphier_aio_set_pll,
 361        .set_fmt     = uniphier_aio_set_fmt,
 362        .startup     = uniphier_aio_startup,
 363        .shutdown    = uniphier_aio_shutdown,
 364        .hw_params   = uniphier_aio_hw_params,
 365        .hw_free     = uniphier_aio_hw_free,
 366        .prepare     = uniphier_aio_prepare,
 367};
 368EXPORT_SYMBOL_GPL(uniphier_aio_i2s_ops);
 369
 370const struct snd_soc_dai_ops uniphier_aio_spdif_ops = {
 371        .set_sysclk  = uniphier_aio_set_sysclk,
 372        .set_pll     = uniphier_aio_set_pll,
 373        .startup     = uniphier_aio_startup,
 374        .shutdown    = uniphier_aio_shutdown,
 375        .hw_params   = uniphier_aio_hw_params,
 376        .hw_free     = uniphier_aio_hw_free,
 377        .prepare     = uniphier_aio_prepare,
 378};
 379EXPORT_SYMBOL_GPL(uniphier_aio_spdif_ops);
 380
 381int uniphier_aio_dai_probe(struct snd_soc_dai *dai)
 382{
 383        struct uniphier_aio *aio = uniphier_priv(dai);
 384        int i;
 385
 386        for (i = 0; i < ARRAY_SIZE(aio->sub); i++) {
 387                struct uniphier_aio_sub *sub = &aio->sub[i];
 388                const struct uniphier_aio_spec *spec;
 389
 390                spec = find_spec(aio, dai->name, i);
 391                if (!spec)
 392                        continue;
 393
 394                sub->swm = &spec->swm;
 395                sub->spec = spec;
 396
 397                sub->vol = AUD_VOL_INIT;
 398        }
 399
 400        aio_iecout_set_enable(aio->chip, true);
 401        aio_chip_init(aio->chip);
 402        aio->chip->active = 1;
 403
 404        return 0;
 405}
 406EXPORT_SYMBOL_GPL(uniphier_aio_dai_probe);
 407
 408int uniphier_aio_dai_remove(struct snd_soc_dai *dai)
 409{
 410        struct uniphier_aio *aio = uniphier_priv(dai);
 411
 412        aio->chip->active = 0;
 413
 414        return 0;
 415}
 416EXPORT_SYMBOL_GPL(uniphier_aio_dai_remove);
 417
 418static void uniphier_aio_dai_suspend(struct snd_soc_dai *dai)
 419{
 420        struct uniphier_aio *aio = uniphier_priv(dai);
 421
 422        if (!snd_soc_dai_active(dai))
 423                return;
 424
 425        aio->chip->num_wup_aios--;
 426        if (!aio->chip->num_wup_aios) {
 427                reset_control_assert(aio->chip->rst);
 428                clk_disable_unprepare(aio->chip->clk);
 429        }
 430}
 431
 432static int uniphier_aio_suspend(struct snd_soc_component *component)
 433{
 434        struct snd_soc_dai *dai;
 435
 436        for_each_component_dais(component, dai)
 437                uniphier_aio_dai_suspend(dai);
 438        return 0;
 439}
 440
 441static int uniphier_aio_dai_resume(struct snd_soc_dai *dai)
 442{
 443        struct uniphier_aio *aio = uniphier_priv(dai);
 444        int ret, i;
 445
 446        if (!snd_soc_dai_active(dai))
 447                return 0;
 448
 449        if (!aio->chip->active)
 450                return 0;
 451
 452        if (!aio->chip->num_wup_aios) {
 453                ret = clk_prepare_enable(aio->chip->clk);
 454                if (ret)
 455                        return ret;
 456
 457                ret = reset_control_deassert(aio->chip->rst);
 458                if (ret)
 459                        goto err_out_clock;
 460        }
 461
 462        aio_iecout_set_enable(aio->chip, true);
 463        aio_chip_init(aio->chip);
 464
 465        for (i = 0; i < ARRAY_SIZE(aio->sub); i++) {
 466                struct uniphier_aio_sub *sub = &aio->sub[i];
 467
 468                if (!sub->spec || !sub->substream)
 469                        continue;
 470
 471                ret = aio_init(sub);
 472                if (ret)
 473                        goto err_out_reset;
 474
 475                if (!sub->setting)
 476                        continue;
 477
 478                aio_port_reset(sub);
 479                aio_src_reset(sub);
 480        }
 481        aio->chip->num_wup_aios++;
 482
 483        return 0;
 484
 485err_out_reset:
 486        if (!aio->chip->num_wup_aios)
 487                reset_control_assert(aio->chip->rst);
 488err_out_clock:
 489        if (!aio->chip->num_wup_aios)
 490                clk_disable_unprepare(aio->chip->clk);
 491
 492        return ret;
 493}
 494
 495static int uniphier_aio_resume(struct snd_soc_component *component)
 496{
 497        struct snd_soc_dai *dai;
 498        int ret = 0;
 499
 500        for_each_component_dais(component, dai)
 501                ret |= uniphier_aio_dai_resume(dai);
 502        return ret;
 503}
 504
 505static int uniphier_aio_vol_info(struct snd_kcontrol *kcontrol,
 506                                 struct snd_ctl_elem_info *uinfo)
 507{
 508        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 509        uinfo->count = 1;
 510        uinfo->value.integer.min = 0;
 511        uinfo->value.integer.max = AUD_VOL_MAX;
 512
 513        return 0;
 514}
 515
 516static int uniphier_aio_vol_get(struct snd_kcontrol *kcontrol,
 517                                struct snd_ctl_elem_value *ucontrol)
 518{
 519        struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
 520        struct uniphier_aio_chip *chip = snd_soc_component_get_drvdata(comp);
 521        struct uniphier_aio_sub *sub;
 522        int oport_hw = kcontrol->private_value;
 523
 524        sub = find_volume(chip, oport_hw);
 525        if (!sub)
 526                return 0;
 527
 528        ucontrol->value.integer.value[0] = sub->vol;
 529
 530        return 0;
 531}
 532
 533static int uniphier_aio_vol_put(struct snd_kcontrol *kcontrol,
 534                                struct snd_ctl_elem_value *ucontrol)
 535{
 536        struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
 537        struct uniphier_aio_chip *chip = snd_soc_component_get_drvdata(comp);
 538        struct uniphier_aio_sub *sub;
 539        int oport_hw = kcontrol->private_value;
 540
 541        sub = find_volume(chip, oport_hw);
 542        if (!sub)
 543                return 0;
 544
 545        if (sub->vol == ucontrol->value.integer.value[0])
 546                return 0;
 547        sub->vol = ucontrol->value.integer.value[0];
 548
 549        aio_port_set_volume(sub, sub->vol);
 550
 551        return 0;
 552}
 553
 554static const struct snd_kcontrol_new uniphier_aio_controls[] = {
 555        {
 556                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 557                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 558                .name = "HPCMOUT1 Volume",
 559                .info = uniphier_aio_vol_info,
 560                .get = uniphier_aio_vol_get,
 561                .put = uniphier_aio_vol_put,
 562                .private_value = AUD_HW_HPCMOUT1,
 563        },
 564        {
 565                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 566                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 567                .name = "PCMOUT1 Volume",
 568                .info = uniphier_aio_vol_info,
 569                .get = uniphier_aio_vol_get,
 570                .put = uniphier_aio_vol_put,
 571                .private_value = AUD_HW_PCMOUT1,
 572        },
 573        {
 574                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 575                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 576                .name = "PCMOUT2 Volume",
 577                .info = uniphier_aio_vol_info,
 578                .get = uniphier_aio_vol_get,
 579                .put = uniphier_aio_vol_put,
 580                .private_value = AUD_HW_PCMOUT2,
 581        },
 582        {
 583                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 584                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 585                .name = "PCMOUT3 Volume",
 586                .info = uniphier_aio_vol_info,
 587                .get = uniphier_aio_vol_get,
 588                .put = uniphier_aio_vol_put,
 589                .private_value = AUD_HW_PCMOUT3,
 590        },
 591        {
 592                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 593                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 594                .name = "HIECOUT1 Volume",
 595                .info = uniphier_aio_vol_info,
 596                .get = uniphier_aio_vol_get,
 597                .put = uniphier_aio_vol_put,
 598                .private_value = AUD_HW_HIECOUT1,
 599        },
 600        {
 601                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 602                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 603                .name = "IECOUT1 Volume",
 604                .info = uniphier_aio_vol_info,
 605                .get = uniphier_aio_vol_get,
 606                .put = uniphier_aio_vol_put,
 607                .private_value = AUD_HW_IECOUT1,
 608        },
 609};
 610
 611static const struct snd_soc_component_driver uniphier_aio_component = {
 612        .name = "uniphier-aio",
 613        .controls = uniphier_aio_controls,
 614        .num_controls = ARRAY_SIZE(uniphier_aio_controls),
 615        .suspend = uniphier_aio_suspend,
 616        .resume  = uniphier_aio_resume,
 617};
 618
 619int uniphier_aio_probe(struct platform_device *pdev)
 620{
 621        struct uniphier_aio_chip *chip;
 622        struct device *dev = &pdev->dev;
 623        int ret, i, j;
 624
 625        chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
 626        if (!chip)
 627                return -ENOMEM;
 628
 629        chip->chip_spec = of_device_get_match_data(dev);
 630        if (!chip->chip_spec)
 631                return -EINVAL;
 632
 633        chip->regmap_sg = syscon_regmap_lookup_by_phandle(dev->of_node,
 634                                                          "socionext,syscon");
 635        if (IS_ERR(chip->regmap_sg)) {
 636                if (PTR_ERR(chip->regmap_sg) == -EPROBE_DEFER)
 637                        return -EPROBE_DEFER;
 638                chip->regmap_sg = NULL;
 639        }
 640
 641        chip->clk = devm_clk_get(dev, "aio");
 642        if (IS_ERR(chip->clk))
 643                return PTR_ERR(chip->clk);
 644
 645        chip->rst = devm_reset_control_get_shared(dev, "aio");
 646        if (IS_ERR(chip->rst))
 647                return PTR_ERR(chip->rst);
 648
 649        chip->num_aios = chip->chip_spec->num_dais;
 650        chip->num_wup_aios = chip->num_aios;
 651        chip->aios = devm_kcalloc(dev,
 652                                  chip->num_aios, sizeof(struct uniphier_aio),
 653                                  GFP_KERNEL);
 654        if (!chip->aios)
 655                return -ENOMEM;
 656
 657        chip->num_plls = chip->chip_spec->num_plls;
 658        chip->plls = devm_kcalloc(dev,
 659                                  chip->num_plls,
 660                                  sizeof(struct uniphier_aio_pll),
 661                                  GFP_KERNEL);
 662        if (!chip->plls)
 663                return -ENOMEM;
 664        memcpy(chip->plls, chip->chip_spec->plls,
 665               sizeof(struct uniphier_aio_pll) * chip->num_plls);
 666
 667        for (i = 0; i < chip->num_aios; i++) {
 668                struct uniphier_aio *aio = &chip->aios[i];
 669
 670                aio->chip = chip;
 671                aio->fmt = SND_SOC_DAIFMT_I2S;
 672
 673                for (j = 0; j < ARRAY_SIZE(aio->sub); j++) {
 674                        struct uniphier_aio_sub *sub = &aio->sub[j];
 675
 676                        sub->aio = aio;
 677                        spin_lock_init(&sub->lock);
 678                }
 679        }
 680
 681        chip->pdev = pdev;
 682        platform_set_drvdata(pdev, chip);
 683
 684        ret = clk_prepare_enable(chip->clk);
 685        if (ret)
 686                return ret;
 687
 688        ret = reset_control_deassert(chip->rst);
 689        if (ret)
 690                goto err_out_clock;
 691
 692        ret = devm_snd_soc_register_component(dev, &uniphier_aio_component,
 693                                              chip->chip_spec->dais,
 694                                              chip->chip_spec->num_dais);
 695        if (ret) {
 696                dev_err(dev, "Register component failed.\n");
 697                goto err_out_reset;
 698        }
 699
 700        ret = uniphier_aiodma_soc_register_platform(pdev);
 701        if (ret) {
 702                dev_err(dev, "Register platform failed.\n");
 703                goto err_out_reset;
 704        }
 705
 706        return 0;
 707
 708err_out_reset:
 709        reset_control_assert(chip->rst);
 710
 711err_out_clock:
 712        clk_disable_unprepare(chip->clk);
 713
 714        return ret;
 715}
 716EXPORT_SYMBOL_GPL(uniphier_aio_probe);
 717
 718int uniphier_aio_remove(struct platform_device *pdev)
 719{
 720        struct uniphier_aio_chip *chip = platform_get_drvdata(pdev);
 721
 722        reset_control_assert(chip->rst);
 723        clk_disable_unprepare(chip->clk);
 724
 725        return 0;
 726}
 727EXPORT_SYMBOL_GPL(uniphier_aio_remove);
 728
 729MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
 730MODULE_DESCRIPTION("UniPhier AIO CPU DAI driver.");
 731MODULE_LICENSE("GPL v2");
 732