root/sound/soc/uniphier/aio-cpu.c

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

DEFINITIONS

This source file includes following definitions.
  1. is_valid_pll
  2. find_volume
  3. match_spec
  4. find_spec
  5. find_divider
  6. uniphier_aio_set_sysclk
  7. uniphier_aio_set_pll
  8. uniphier_aio_set_fmt
  9. uniphier_aio_startup
  10. uniphier_aio_shutdown
  11. uniphier_aio_hw_params
  12. uniphier_aio_hw_free
  13. uniphier_aio_prepare
  14. uniphier_aio_dai_probe
  15. uniphier_aio_dai_remove
  16. uniphier_aio_dai_suspend
  17. uniphier_aio_dai_resume
  18. uniphier_aio_vol_info
  19. uniphier_aio_vol_get
  20. uniphier_aio_vol_put
  21. uniphier_aio_probe
  22. uniphier_aio_remove

   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 
  23 static 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  */
  46 static 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 
  64 static 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  */
 101 static 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  */
 128 static int find_divider(struct uniphier_aio *aio, int pll_id, unsigned int freq)
 129 {
 130         struct uniphier_aio_pll *pll;
 131         int mul[] = { 1, 1, 1, 2, };
 132         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 
 146 static 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 
 217 static 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 
 234 static 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 
 254 static 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         int ret;
 260 
 261         sub->substream = substream;
 262         sub->pass_through = 0;
 263         sub->use_mmap = true;
 264 
 265         ret = aio_init(sub);
 266         if (ret)
 267                 return ret;
 268 
 269         return 0;
 270 }
 271 
 272 static void uniphier_aio_shutdown(struct snd_pcm_substream *substream,
 273                                   struct snd_soc_dai *dai)
 274 {
 275         struct uniphier_aio *aio = uniphier_priv(dai);
 276         struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
 277 
 278         sub->substream = NULL;
 279 }
 280 
 281 static int uniphier_aio_hw_params(struct snd_pcm_substream *substream,
 282                                   struct snd_pcm_hw_params *params,
 283                                   struct snd_soc_dai *dai)
 284 {
 285         struct uniphier_aio *aio = uniphier_priv(dai);
 286         struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
 287         struct device *dev = &aio->chip->pdev->dev;
 288         int freq, ret;
 289 
 290         switch (params_rate(params)) {
 291         case 48000:
 292         case 32000:
 293         case 24000:
 294                 freq = 12288000;
 295                 break;
 296         case 44100:
 297         case 22050:
 298                 freq = 11289600;
 299                 break;
 300         default:
 301                 dev_err(dev, "Rate is not supported(%d)\n",
 302                         params_rate(params));
 303                 return -EINVAL;
 304         }
 305         ret = snd_soc_dai_set_sysclk(dai, AUD_CLK_A,
 306                                      freq, SND_SOC_CLOCK_OUT);
 307         if (ret)
 308                 return ret;
 309 
 310         sub->params = *params;
 311         sub->setting = 1;
 312 
 313         aio_port_reset(sub);
 314         aio_port_set_volume(sub, sub->vol);
 315         aio_src_reset(sub);
 316 
 317         return 0;
 318 }
 319 
 320 static int uniphier_aio_hw_free(struct snd_pcm_substream *substream,
 321                                 struct snd_soc_dai *dai)
 322 {
 323         struct uniphier_aio *aio = uniphier_priv(dai);
 324         struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
 325 
 326         sub->setting = 0;
 327 
 328         return 0;
 329 }
 330 
 331 static int uniphier_aio_prepare(struct snd_pcm_substream *substream,
 332                                 struct snd_soc_dai *dai)
 333 {
 334         struct uniphier_aio *aio = uniphier_priv(dai);
 335         struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
 336         int ret;
 337 
 338         ret = aio_port_set_param(sub, sub->pass_through, &sub->params);
 339         if (ret)
 340                 return ret;
 341         ret = aio_src_set_param(sub, &sub->params);
 342         if (ret)
 343                 return ret;
 344         aio_port_set_enable(sub, 1);
 345 
 346         ret = aio_if_set_param(sub, sub->pass_through);
 347         if (ret)
 348                 return ret;
 349 
 350         if (sub->swm->type == PORT_TYPE_CONV) {
 351                 ret = aio_srcif_set_param(sub);
 352                 if (ret)
 353                         return ret;
 354                 ret = aio_srcch_set_param(sub);
 355                 if (ret)
 356                         return ret;
 357                 aio_srcch_set_enable(sub, 1);
 358         }
 359 
 360         return 0;
 361 }
 362 
 363 const struct snd_soc_dai_ops uniphier_aio_i2s_ops = {
 364         .set_sysclk  = uniphier_aio_set_sysclk,
 365         .set_pll     = uniphier_aio_set_pll,
 366         .set_fmt     = uniphier_aio_set_fmt,
 367         .startup     = uniphier_aio_startup,
 368         .shutdown    = uniphier_aio_shutdown,
 369         .hw_params   = uniphier_aio_hw_params,
 370         .hw_free     = uniphier_aio_hw_free,
 371         .prepare     = uniphier_aio_prepare,
 372 };
 373 EXPORT_SYMBOL_GPL(uniphier_aio_i2s_ops);
 374 
 375 const struct snd_soc_dai_ops uniphier_aio_spdif_ops = {
 376         .set_sysclk  = uniphier_aio_set_sysclk,
 377         .set_pll     = uniphier_aio_set_pll,
 378         .startup     = uniphier_aio_startup,
 379         .shutdown    = uniphier_aio_shutdown,
 380         .hw_params   = uniphier_aio_hw_params,
 381         .hw_free     = uniphier_aio_hw_free,
 382         .prepare     = uniphier_aio_prepare,
 383 };
 384 EXPORT_SYMBOL_GPL(uniphier_aio_spdif_ops);
 385 
 386 int uniphier_aio_dai_probe(struct snd_soc_dai *dai)
 387 {
 388         struct uniphier_aio *aio = uniphier_priv(dai);
 389         int i;
 390 
 391         for (i = 0; i < ARRAY_SIZE(aio->sub); i++) {
 392                 struct uniphier_aio_sub *sub = &aio->sub[i];
 393                 const struct uniphier_aio_spec *spec;
 394 
 395                 spec = find_spec(aio, dai->name, i);
 396                 if (!spec)
 397                         continue;
 398 
 399                 sub->swm = &spec->swm;
 400                 sub->spec = spec;
 401 
 402                 sub->vol = AUD_VOL_INIT;
 403         }
 404 
 405         aio_iecout_set_enable(aio->chip, true);
 406         aio_chip_init(aio->chip);
 407         aio->chip->active = 1;
 408 
 409         return 0;
 410 }
 411 EXPORT_SYMBOL_GPL(uniphier_aio_dai_probe);
 412 
 413 int uniphier_aio_dai_remove(struct snd_soc_dai *dai)
 414 {
 415         struct uniphier_aio *aio = uniphier_priv(dai);
 416 
 417         aio->chip->active = 0;
 418 
 419         return 0;
 420 }
 421 EXPORT_SYMBOL_GPL(uniphier_aio_dai_remove);
 422 
 423 int uniphier_aio_dai_suspend(struct snd_soc_dai *dai)
 424 {
 425         struct uniphier_aio *aio = uniphier_priv(dai);
 426 
 427         aio->chip->num_wup_aios--;
 428         if (!aio->chip->num_wup_aios) {
 429                 reset_control_assert(aio->chip->rst);
 430                 clk_disable_unprepare(aio->chip->clk);
 431         }
 432 
 433         return 0;
 434 }
 435 EXPORT_SYMBOL_GPL(uniphier_aio_dai_suspend);
 436 
 437 int uniphier_aio_dai_resume(struct snd_soc_dai *dai)
 438 {
 439         struct uniphier_aio *aio = uniphier_priv(dai);
 440         int ret, i;
 441 
 442         if (!aio->chip->active)
 443                 return 0;
 444 
 445         if (!aio->chip->num_wup_aios) {
 446                 ret = clk_prepare_enable(aio->chip->clk);
 447                 if (ret)
 448                         return ret;
 449 
 450                 ret = reset_control_deassert(aio->chip->rst);
 451                 if (ret)
 452                         goto err_out_clock;
 453         }
 454 
 455         aio_iecout_set_enable(aio->chip, true);
 456         aio_chip_init(aio->chip);
 457 
 458         for (i = 0; i < ARRAY_SIZE(aio->sub); i++) {
 459                 struct uniphier_aio_sub *sub = &aio->sub[i];
 460 
 461                 if (!sub->spec || !sub->substream)
 462                         continue;
 463 
 464                 ret = aio_init(sub);
 465                 if (ret)
 466                         goto err_out_reset;
 467 
 468                 if (!sub->setting)
 469                         continue;
 470 
 471                 aio_port_reset(sub);
 472                 aio_src_reset(sub);
 473         }
 474         aio->chip->num_wup_aios++;
 475 
 476         return 0;
 477 
 478 err_out_reset:
 479         if (!aio->chip->num_wup_aios)
 480                 reset_control_assert(aio->chip->rst);
 481 err_out_clock:
 482         if (!aio->chip->num_wup_aios)
 483                 clk_disable_unprepare(aio->chip->clk);
 484 
 485         return ret;
 486 }
 487 EXPORT_SYMBOL_GPL(uniphier_aio_dai_resume);
 488 
 489 static int uniphier_aio_vol_info(struct snd_kcontrol *kcontrol,
 490                                  struct snd_ctl_elem_info *uinfo)
 491 {
 492         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 493         uinfo->count = 1;
 494         uinfo->value.integer.min = 0;
 495         uinfo->value.integer.max = AUD_VOL_MAX;
 496 
 497         return 0;
 498 }
 499 
 500 static int uniphier_aio_vol_get(struct snd_kcontrol *kcontrol,
 501                                 struct snd_ctl_elem_value *ucontrol)
 502 {
 503         struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
 504         struct uniphier_aio_chip *chip = snd_soc_component_get_drvdata(comp);
 505         struct uniphier_aio_sub *sub;
 506         int oport_hw = kcontrol->private_value;
 507 
 508         sub = find_volume(chip, oport_hw);
 509         if (!sub)
 510                 return 0;
 511 
 512         ucontrol->value.integer.value[0] = sub->vol;
 513 
 514         return 0;
 515 }
 516 
 517 static int uniphier_aio_vol_put(struct snd_kcontrol *kcontrol,
 518                                 struct snd_ctl_elem_value *ucontrol)
 519 {
 520         struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
 521         struct uniphier_aio_chip *chip = snd_soc_component_get_drvdata(comp);
 522         struct uniphier_aio_sub *sub;
 523         int oport_hw = kcontrol->private_value;
 524 
 525         sub = find_volume(chip, oport_hw);
 526         if (!sub)
 527                 return 0;
 528 
 529         if (sub->vol == ucontrol->value.integer.value[0])
 530                 return 0;
 531         sub->vol = ucontrol->value.integer.value[0];
 532 
 533         aio_port_set_volume(sub, sub->vol);
 534 
 535         return 0;
 536 }
 537 
 538 static const struct snd_kcontrol_new uniphier_aio_controls[] = {
 539         {
 540                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 541                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 542                 .name = "HPCMOUT1 Volume",
 543                 .info = uniphier_aio_vol_info,
 544                 .get = uniphier_aio_vol_get,
 545                 .put = uniphier_aio_vol_put,
 546                 .private_value = AUD_HW_HPCMOUT1,
 547         },
 548         {
 549                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 550                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 551                 .name = "PCMOUT1 Volume",
 552                 .info = uniphier_aio_vol_info,
 553                 .get = uniphier_aio_vol_get,
 554                 .put = uniphier_aio_vol_put,
 555                 .private_value = AUD_HW_PCMOUT1,
 556         },
 557         {
 558                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 559                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 560                 .name = "PCMOUT2 Volume",
 561                 .info = uniphier_aio_vol_info,
 562                 .get = uniphier_aio_vol_get,
 563                 .put = uniphier_aio_vol_put,
 564                 .private_value = AUD_HW_PCMOUT2,
 565         },
 566         {
 567                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 568                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 569                 .name = "PCMOUT3 Volume",
 570                 .info = uniphier_aio_vol_info,
 571                 .get = uniphier_aio_vol_get,
 572                 .put = uniphier_aio_vol_put,
 573                 .private_value = AUD_HW_PCMOUT3,
 574         },
 575         {
 576                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 577                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 578                 .name = "HIECOUT1 Volume",
 579                 .info = uniphier_aio_vol_info,
 580                 .get = uniphier_aio_vol_get,
 581                 .put = uniphier_aio_vol_put,
 582                 .private_value = AUD_HW_HIECOUT1,
 583         },
 584         {
 585                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 586                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 587                 .name = "IECOUT1 Volume",
 588                 .info = uniphier_aio_vol_info,
 589                 .get = uniphier_aio_vol_get,
 590                 .put = uniphier_aio_vol_put,
 591                 .private_value = AUD_HW_IECOUT1,
 592         },
 593 };
 594 
 595 static const struct snd_soc_component_driver uniphier_aio_component = {
 596         .name = "uniphier-aio",
 597         .controls = uniphier_aio_controls,
 598         .num_controls = ARRAY_SIZE(uniphier_aio_controls),
 599 };
 600 
 601 int uniphier_aio_probe(struct platform_device *pdev)
 602 {
 603         struct uniphier_aio_chip *chip;
 604         struct device *dev = &pdev->dev;
 605         int ret, i, j;
 606 
 607         chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
 608         if (!chip)
 609                 return -ENOMEM;
 610 
 611         chip->chip_spec = of_device_get_match_data(dev);
 612         if (!chip->chip_spec)
 613                 return -EINVAL;
 614 
 615         chip->regmap_sg = syscon_regmap_lookup_by_phandle(dev->of_node,
 616                                                           "socionext,syscon");
 617         if (IS_ERR(chip->regmap_sg)) {
 618                 if (PTR_ERR(chip->regmap_sg) == -EPROBE_DEFER)
 619                         return -EPROBE_DEFER;
 620                 chip->regmap_sg = NULL;
 621         }
 622 
 623         chip->clk = devm_clk_get(dev, "aio");
 624         if (IS_ERR(chip->clk))
 625                 return PTR_ERR(chip->clk);
 626 
 627         chip->rst = devm_reset_control_get_shared(dev, "aio");
 628         if (IS_ERR(chip->rst))
 629                 return PTR_ERR(chip->rst);
 630 
 631         chip->num_aios = chip->chip_spec->num_dais;
 632         chip->num_wup_aios = chip->num_aios;
 633         chip->aios = devm_kcalloc(dev,
 634                                   chip->num_aios, sizeof(struct uniphier_aio),
 635                                   GFP_KERNEL);
 636         if (!chip->aios)
 637                 return -ENOMEM;
 638 
 639         chip->num_plls = chip->chip_spec->num_plls;
 640         chip->plls = devm_kcalloc(dev,
 641                                   chip->num_plls,
 642                                   sizeof(struct uniphier_aio_pll),
 643                                   GFP_KERNEL);
 644         if (!chip->plls)
 645                 return -ENOMEM;
 646         memcpy(chip->plls, chip->chip_spec->plls,
 647                sizeof(struct uniphier_aio_pll) * chip->num_plls);
 648 
 649         for (i = 0; i < chip->num_aios; i++) {
 650                 struct uniphier_aio *aio = &chip->aios[i];
 651 
 652                 aio->chip = chip;
 653                 aio->fmt = SND_SOC_DAIFMT_I2S;
 654 
 655                 for (j = 0; j < ARRAY_SIZE(aio->sub); j++) {
 656                         struct uniphier_aio_sub *sub = &aio->sub[j];
 657 
 658                         sub->aio = aio;
 659                         spin_lock_init(&sub->lock);
 660                 }
 661         }
 662 
 663         chip->pdev = pdev;
 664         platform_set_drvdata(pdev, chip);
 665 
 666         ret = clk_prepare_enable(chip->clk);
 667         if (ret)
 668                 return ret;
 669 
 670         ret = reset_control_deassert(chip->rst);
 671         if (ret)
 672                 goto err_out_clock;
 673 
 674         ret = devm_snd_soc_register_component(dev, &uniphier_aio_component,
 675                                               chip->chip_spec->dais,
 676                                               chip->chip_spec->num_dais);
 677         if (ret) {
 678                 dev_err(dev, "Register component failed.\n");
 679                 goto err_out_reset;
 680         }
 681 
 682         ret = uniphier_aiodma_soc_register_platform(pdev);
 683         if (ret) {
 684                 dev_err(dev, "Register platform failed.\n");
 685                 goto err_out_reset;
 686         }
 687 
 688         return 0;
 689 
 690 err_out_reset:
 691         reset_control_assert(chip->rst);
 692 
 693 err_out_clock:
 694         clk_disable_unprepare(chip->clk);
 695 
 696         return ret;
 697 }
 698 EXPORT_SYMBOL_GPL(uniphier_aio_probe);
 699 
 700 int uniphier_aio_remove(struct platform_device *pdev)
 701 {
 702         struct uniphier_aio_chip *chip = platform_get_drvdata(pdev);
 703 
 704         reset_control_assert(chip->rst);
 705         clk_disable_unprepare(chip->clk);
 706 
 707         return 0;
 708 }
 709 EXPORT_SYMBOL_GPL(uniphier_aio_remove);
 710 
 711 MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
 712 MODULE_DESCRIPTION("UniPhier AIO CPU DAI driver.");
 713 MODULE_LICENSE("GPL v2");

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