root/sound/soc/img/img-spdif-in.c

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

DEFINITIONS

This source file includes following definitions.
  1. img_spdif_in_runtime_suspend
  2. img_spdif_in_runtime_resume
  3. img_spdif_in_writel
  4. img_spdif_in_readl
  5. img_spdif_in_aclkgen_writel
  6. img_spdif_in_check_max_rate
  7. img_spdif_in_do_clkgen_calc
  8. img_spdif_in_do_clkgen_single
  9. img_spdif_in_do_clkgen_multi
  10. img_spdif_in_iec958_info
  11. img_spdif_in_get_status_mask
  12. img_spdif_in_get_status
  13. img_spdif_in_info_multi_freq
  14. img_spdif_in_get_multi_freq
  15. img_spdif_in_set_multi_freq
  16. img_spdif_in_info_lock_freq
  17. img_spdif_in_get_lock_freq
  18. img_spdif_in_info_trk
  19. img_spdif_in_get_trk
  20. img_spdif_in_set_trk
  21. img_spdif_in_info_lock
  22. img_spdif_in_get_lock_acquire
  23. img_spdif_in_set_lock_acquire
  24. img_spdif_in_get_lock_release
  25. img_spdif_in_set_lock_release
  26. img_spdif_in_trigger
  27. img_spdif_in_hw_params
  28. img_spdif_in_dai_probe
  29. img_spdif_in_probe
  30. img_spdif_in_dev_remove
  31. img_spdif_in_suspend
  32. img_spdif_in_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * IMG SPDIF input controller driver
   4  *
   5  * Copyright (C) 2015 Imagination Technologies Ltd.
   6  *
   7  * Author: Damien Horsley <Damien.Horsley@imgtec.com>
   8  */
   9 
  10 #include <linux/clk.h>
  11 #include <linux/init.h>
  12 #include <linux/kernel.h>
  13 #include <linux/module.h>
  14 #include <linux/of.h>
  15 #include <linux/platform_device.h>
  16 #include <linux/pm_runtime.h>
  17 #include <linux/reset.h>
  18 
  19 #include <sound/core.h>
  20 #include <sound/dmaengine_pcm.h>
  21 #include <sound/initval.h>
  22 #include <sound/pcm.h>
  23 #include <sound/pcm_params.h>
  24 #include <sound/soc.h>
  25 
  26 #define IMG_SPDIF_IN_RX_FIFO_OFFSET             0
  27 
  28 #define IMG_SPDIF_IN_CTL                        0x4
  29 #define IMG_SPDIF_IN_CTL_LOCKLO_MASK            0xff
  30 #define IMG_SPDIF_IN_CTL_LOCKLO_SHIFT           0
  31 #define IMG_SPDIF_IN_CTL_LOCKHI_MASK            0xff00
  32 #define IMG_SPDIF_IN_CTL_LOCKHI_SHIFT           8
  33 #define IMG_SPDIF_IN_CTL_TRK_MASK               0xff0000
  34 #define IMG_SPDIF_IN_CTL_TRK_SHIFT              16
  35 #define IMG_SPDIF_IN_CTL_SRD_MASK               0x70000000
  36 #define IMG_SPDIF_IN_CTL_SRD_SHIFT              28
  37 #define IMG_SPDIF_IN_CTL_SRT_MASK               BIT(31)
  38 
  39 #define IMG_SPDIF_IN_STATUS                     0x8
  40 #define IMG_SPDIF_IN_STATUS_SAM_MASK            0x7000
  41 #define IMG_SPDIF_IN_STATUS_SAM_SHIFT           12
  42 #define IMG_SPDIF_IN_STATUS_LOCK_MASK           BIT(15)
  43 #define IMG_SPDIF_IN_STATUS_LOCK_SHIFT          15
  44 
  45 #define IMG_SPDIF_IN_CLKGEN                     0x1c
  46 #define IMG_SPDIF_IN_CLKGEN_NOM_MASK            0x3ff
  47 #define IMG_SPDIF_IN_CLKGEN_NOM_SHIFT           0
  48 #define IMG_SPDIF_IN_CLKGEN_HLD_MASK            0x3ff0000
  49 #define IMG_SPDIF_IN_CLKGEN_HLD_SHIFT           16
  50 
  51 #define IMG_SPDIF_IN_CSL                        0x20
  52 
  53 #define IMG_SPDIF_IN_CSH                        0x24
  54 #define IMG_SPDIF_IN_CSH_MASK                   0xff
  55 #define IMG_SPDIF_IN_CSH_SHIFT                  0
  56 
  57 #define IMG_SPDIF_IN_SOFT_RESET                 0x28
  58 #define IMG_SPDIF_IN_SOFT_RESET_MASK            BIT(0)
  59 
  60 #define IMG_SPDIF_IN_ACLKGEN_START              0x2c
  61 #define IMG_SPDIF_IN_ACLKGEN_NOM_MASK           0x3ff
  62 #define IMG_SPDIF_IN_ACLKGEN_NOM_SHIFT          0
  63 #define IMG_SPDIF_IN_ACLKGEN_HLD_MASK           0xffc00
  64 #define IMG_SPDIF_IN_ACLKGEN_HLD_SHIFT          10
  65 #define IMG_SPDIF_IN_ACLKGEN_TRK_MASK           0xff00000
  66 #define IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT          20
  67 
  68 #define IMG_SPDIF_IN_NUM_ACLKGEN                4
  69 
  70 struct img_spdif_in {
  71         spinlock_t lock;
  72         void __iomem *base;
  73         struct clk *clk_sys;
  74         struct snd_dmaengine_dai_dma_data dma_data;
  75         struct device *dev;
  76         unsigned int trk;
  77         bool multi_freq;
  78         int lock_acquire;
  79         int lock_release;
  80         unsigned int single_freq;
  81         unsigned int multi_freqs[IMG_SPDIF_IN_NUM_ACLKGEN];
  82         bool active;
  83         u32 suspend_clkgen;
  84         u32 suspend_ctl;
  85 
  86         /* Write-only registers */
  87         unsigned int aclkgen_regs[IMG_SPDIF_IN_NUM_ACLKGEN];
  88 };
  89 
  90 static int img_spdif_in_runtime_suspend(struct device *dev)
  91 {
  92         struct img_spdif_in *spdif = dev_get_drvdata(dev);
  93 
  94         clk_disable_unprepare(spdif->clk_sys);
  95 
  96         return 0;
  97 }
  98 
  99 static int img_spdif_in_runtime_resume(struct device *dev)
 100 {
 101         struct img_spdif_in *spdif = dev_get_drvdata(dev);
 102         int ret;
 103 
 104         ret = clk_prepare_enable(spdif->clk_sys);
 105         if (ret) {
 106                 dev_err(dev, "Unable to enable sys clock\n");
 107                 return ret;
 108         }
 109 
 110         return 0;
 111 }
 112 
 113 static inline void img_spdif_in_writel(struct img_spdif_in *spdif,
 114                                         u32 val, u32 reg)
 115 {
 116         writel(val, spdif->base + reg);
 117 }
 118 
 119 static inline u32 img_spdif_in_readl(struct img_spdif_in *spdif, u32 reg)
 120 {
 121         return readl(spdif->base + reg);
 122 }
 123 
 124 static inline void img_spdif_in_aclkgen_writel(struct img_spdif_in *spdif,
 125                                                 u32 index)
 126 {
 127         img_spdif_in_writel(spdif, spdif->aclkgen_regs[index],
 128                         IMG_SPDIF_IN_ACLKGEN_START + (index * 0x4));
 129 }
 130 
 131 static int img_spdif_in_check_max_rate(struct img_spdif_in *spdif,
 132                 unsigned int sample_rate, unsigned long *actual_freq)
 133 {
 134         unsigned long min_freq, freq_t;
 135 
 136         /* Clock rate must be at least 24x the bit rate */
 137         min_freq = sample_rate * 2 * 32 * 24;
 138 
 139         freq_t = clk_get_rate(spdif->clk_sys);
 140 
 141         if (freq_t < min_freq)
 142                 return -EINVAL;
 143 
 144         *actual_freq = freq_t;
 145 
 146         return 0;
 147 }
 148 
 149 static int img_spdif_in_do_clkgen_calc(unsigned int rate, unsigned int *pnom,
 150                 unsigned int *phld, unsigned long clk_rate)
 151 {
 152         unsigned int ori, nom, hld;
 153 
 154         /*
 155          * Calculate oversampling ratio, nominal phase increment and hold
 156          * increment for the given rate / frequency
 157          */
 158 
 159         if (!rate)
 160                 return -EINVAL;
 161 
 162         ori = clk_rate / (rate * 64);
 163 
 164         if (!ori)
 165                 return -EINVAL;
 166 
 167         nom = (4096 / ori) + 1;
 168         do
 169                 hld = 4096 - (--nom * (ori - 1));
 170         while (hld < 120);
 171 
 172         *pnom = nom;
 173         *phld = hld;
 174 
 175         return 0;
 176 }
 177 
 178 static int img_spdif_in_do_clkgen_single(struct img_spdif_in *spdif,
 179                 unsigned int rate)
 180 {
 181         unsigned int nom, hld;
 182         unsigned long flags, clk_rate;
 183         int ret = 0;
 184         u32 reg;
 185 
 186         ret = img_spdif_in_check_max_rate(spdif, rate, &clk_rate);
 187         if (ret)
 188                 return ret;
 189 
 190         ret = img_spdif_in_do_clkgen_calc(rate, &nom, &hld, clk_rate);
 191         if (ret)
 192                 return ret;
 193 
 194         reg = (nom << IMG_SPDIF_IN_CLKGEN_NOM_SHIFT) &
 195                 IMG_SPDIF_IN_CLKGEN_NOM_MASK;
 196         reg |= (hld << IMG_SPDIF_IN_CLKGEN_HLD_SHIFT) &
 197                 IMG_SPDIF_IN_CLKGEN_HLD_MASK;
 198 
 199         spin_lock_irqsave(&spdif->lock, flags);
 200 
 201         if (spdif->active) {
 202                 spin_unlock_irqrestore(&spdif->lock, flags);
 203                 return -EBUSY;
 204         }
 205 
 206         img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CLKGEN);
 207 
 208         spdif->single_freq = rate;
 209 
 210         spin_unlock_irqrestore(&spdif->lock, flags);
 211 
 212         return 0;
 213 }
 214 
 215 static int img_spdif_in_do_clkgen_multi(struct img_spdif_in *spdif,
 216                 unsigned int multi_freqs[])
 217 {
 218         unsigned int nom, hld, rate, max_rate = 0;
 219         unsigned long flags, clk_rate;
 220         int i, ret = 0;
 221         u32 reg, trk_reg, temp_regs[IMG_SPDIF_IN_NUM_ACLKGEN];
 222 
 223         for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++)
 224                 if (multi_freqs[i] > max_rate)
 225                         max_rate = multi_freqs[i];
 226 
 227         ret = img_spdif_in_check_max_rate(spdif, max_rate, &clk_rate);
 228         if (ret)
 229                 return ret;
 230 
 231         for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++) {
 232                 rate = multi_freqs[i];
 233 
 234                 ret = img_spdif_in_do_clkgen_calc(rate, &nom, &hld, clk_rate);
 235                 if (ret)
 236                         return ret;
 237 
 238                 reg = (nom << IMG_SPDIF_IN_ACLKGEN_NOM_SHIFT) &
 239                         IMG_SPDIF_IN_ACLKGEN_NOM_MASK;
 240                 reg |= (hld << IMG_SPDIF_IN_ACLKGEN_HLD_SHIFT) &
 241                         IMG_SPDIF_IN_ACLKGEN_HLD_MASK;
 242                 temp_regs[i] = reg;
 243         }
 244 
 245         spin_lock_irqsave(&spdif->lock, flags);
 246 
 247         if (spdif->active) {
 248                 spin_unlock_irqrestore(&spdif->lock, flags);
 249                 return -EBUSY;
 250         }
 251 
 252         trk_reg = spdif->trk << IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT;
 253 
 254         for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++) {
 255                 spdif->aclkgen_regs[i] = temp_regs[i] | trk_reg;
 256                 img_spdif_in_aclkgen_writel(spdif, i);
 257         }
 258 
 259         spdif->multi_freq = true;
 260         spdif->multi_freqs[0] = multi_freqs[0];
 261         spdif->multi_freqs[1] = multi_freqs[1];
 262         spdif->multi_freqs[2] = multi_freqs[2];
 263         spdif->multi_freqs[3] = multi_freqs[3];
 264 
 265         spin_unlock_irqrestore(&spdif->lock, flags);
 266 
 267         return 0;
 268 }
 269 
 270 static int img_spdif_in_iec958_info(struct snd_kcontrol *kcontrol,
 271                 struct snd_ctl_elem_info *uinfo)
 272 {
 273         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
 274         uinfo->count = 1;
 275 
 276         return 0;
 277 }
 278 
 279 static int img_spdif_in_get_status_mask(struct snd_kcontrol *kcontrol,
 280                                        struct snd_ctl_elem_value *ucontrol)
 281 {
 282         ucontrol->value.iec958.status[0] = 0xff;
 283         ucontrol->value.iec958.status[1] = 0xff;
 284         ucontrol->value.iec958.status[2] = 0xff;
 285         ucontrol->value.iec958.status[3] = 0xff;
 286         ucontrol->value.iec958.status[4] = 0xff;
 287 
 288         return 0;
 289 }
 290 
 291 static int img_spdif_in_get_status(struct snd_kcontrol *kcontrol,
 292                                   struct snd_ctl_elem_value *ucontrol)
 293 {
 294         struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 295         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
 296         u32 reg;
 297 
 298         reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CSL);
 299         ucontrol->value.iec958.status[0] = reg & 0xff;
 300         ucontrol->value.iec958.status[1] = (reg >> 8) & 0xff;
 301         ucontrol->value.iec958.status[2] = (reg >> 16) & 0xff;
 302         ucontrol->value.iec958.status[3] = (reg >> 24) & 0xff;
 303         reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CSH);
 304         ucontrol->value.iec958.status[4] = (reg & IMG_SPDIF_IN_CSH_MASK)
 305                 >> IMG_SPDIF_IN_CSH_SHIFT;
 306 
 307         return 0;
 308 }
 309 
 310 static int img_spdif_in_info_multi_freq(struct snd_kcontrol *kcontrol,
 311                 struct snd_ctl_elem_info *uinfo)
 312 {
 313         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 314         uinfo->count = IMG_SPDIF_IN_NUM_ACLKGEN;
 315         uinfo->value.integer.min = 0;
 316         uinfo->value.integer.max = LONG_MAX;
 317 
 318         return 0;
 319 }
 320 
 321 static int img_spdif_in_get_multi_freq(struct snd_kcontrol *kcontrol,
 322                                   struct snd_ctl_elem_value *ucontrol)
 323 {
 324         struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 325         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
 326         unsigned long flags;
 327 
 328         spin_lock_irqsave(&spdif->lock, flags);
 329         if (spdif->multi_freq) {
 330                 ucontrol->value.integer.value[0] = spdif->multi_freqs[0];
 331                 ucontrol->value.integer.value[1] = spdif->multi_freqs[1];
 332                 ucontrol->value.integer.value[2] = spdif->multi_freqs[2];
 333                 ucontrol->value.integer.value[3] = spdif->multi_freqs[3];
 334         } else {
 335                 ucontrol->value.integer.value[0] = 0;
 336                 ucontrol->value.integer.value[1] = 0;
 337                 ucontrol->value.integer.value[2] = 0;
 338                 ucontrol->value.integer.value[3] = 0;
 339         }
 340         spin_unlock_irqrestore(&spdif->lock, flags);
 341 
 342         return 0;
 343 }
 344 
 345 static int img_spdif_in_set_multi_freq(struct snd_kcontrol *kcontrol,
 346                                   struct snd_ctl_elem_value *ucontrol)
 347 {
 348         struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 349         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
 350         unsigned int multi_freqs[IMG_SPDIF_IN_NUM_ACLKGEN];
 351         bool multi_freq;
 352         unsigned long flags;
 353 
 354         if ((ucontrol->value.integer.value[0] == 0) &&
 355                         (ucontrol->value.integer.value[1] == 0) &&
 356                         (ucontrol->value.integer.value[2] == 0) &&
 357                         (ucontrol->value.integer.value[3] == 0)) {
 358                 multi_freq = false;
 359         } else {
 360                 multi_freqs[0] = ucontrol->value.integer.value[0];
 361                 multi_freqs[1] = ucontrol->value.integer.value[1];
 362                 multi_freqs[2] = ucontrol->value.integer.value[2];
 363                 multi_freqs[3] = ucontrol->value.integer.value[3];
 364                 multi_freq = true;
 365         }
 366 
 367         if (multi_freq)
 368                 return img_spdif_in_do_clkgen_multi(spdif, multi_freqs);
 369 
 370         spin_lock_irqsave(&spdif->lock, flags);
 371 
 372         if (spdif->active) {
 373                 spin_unlock_irqrestore(&spdif->lock, flags);
 374                 return -EBUSY;
 375         }
 376 
 377         spdif->multi_freq = false;
 378 
 379         spin_unlock_irqrestore(&spdif->lock, flags);
 380 
 381         return 0;
 382 }
 383 
 384 static int img_spdif_in_info_lock_freq(struct snd_kcontrol *kcontrol,
 385                 struct snd_ctl_elem_info *uinfo)
 386 {
 387         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 388         uinfo->count = 1;
 389         uinfo->value.integer.min = 0;
 390         uinfo->value.integer.max = LONG_MAX;
 391 
 392         return 0;
 393 }
 394 
 395 static int img_spdif_in_get_lock_freq(struct snd_kcontrol *kcontrol,
 396                                   struct snd_ctl_elem_value *uc)
 397 {
 398         struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 399         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
 400         u32 reg;
 401         int i;
 402         unsigned long flags;
 403 
 404         spin_lock_irqsave(&spdif->lock, flags);
 405 
 406         reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_STATUS);
 407         if (reg & IMG_SPDIF_IN_STATUS_LOCK_MASK) {
 408                 if (spdif->multi_freq) {
 409                         i = ((reg & IMG_SPDIF_IN_STATUS_SAM_MASK) >>
 410                                         IMG_SPDIF_IN_STATUS_SAM_SHIFT) - 1;
 411                         uc->value.integer.value[0] = spdif->multi_freqs[i];
 412                 } else {
 413                         uc->value.integer.value[0] = spdif->single_freq;
 414                 }
 415         } else {
 416                 uc->value.integer.value[0] = 0;
 417         }
 418 
 419         spin_unlock_irqrestore(&spdif->lock, flags);
 420 
 421         return 0;
 422 }
 423 
 424 static int img_spdif_in_info_trk(struct snd_kcontrol *kcontrol,
 425                 struct snd_ctl_elem_info *uinfo)
 426 {
 427         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 428         uinfo->count = 1;
 429         uinfo->value.integer.min = 0;
 430         uinfo->value.integer.max = 255;
 431 
 432         return 0;
 433 }
 434 
 435 static int img_spdif_in_get_trk(struct snd_kcontrol *kcontrol,
 436                                   struct snd_ctl_elem_value *ucontrol)
 437 {
 438         struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 439         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
 440 
 441         ucontrol->value.integer.value[0] = spdif->trk;
 442 
 443         return 0;
 444 }
 445 
 446 static int img_spdif_in_set_trk(struct snd_kcontrol *kcontrol,
 447                                   struct snd_ctl_elem_value *ucontrol)
 448 {
 449         struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 450         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
 451         unsigned long flags;
 452         int i;
 453         u32 reg;
 454 
 455         spin_lock_irqsave(&spdif->lock, flags);
 456 
 457         if (spdif->active) {
 458                 spin_unlock_irqrestore(&spdif->lock, flags);
 459                 return -EBUSY;
 460         }
 461 
 462         spdif->trk = ucontrol->value.integer.value[0];
 463 
 464         reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
 465         reg &= ~IMG_SPDIF_IN_CTL_TRK_MASK;
 466         reg |= spdif->trk << IMG_SPDIF_IN_CTL_TRK_SHIFT;
 467         img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
 468 
 469         for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++) {
 470                 spdif->aclkgen_regs[i] = (spdif->aclkgen_regs[i] &
 471                         ~IMG_SPDIF_IN_ACLKGEN_TRK_MASK) |
 472                         (spdif->trk << IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT);
 473 
 474                 img_spdif_in_aclkgen_writel(spdif, i);
 475         }
 476 
 477         spin_unlock_irqrestore(&spdif->lock, flags);
 478 
 479         return 0;
 480 }
 481 
 482 static int img_spdif_in_info_lock(struct snd_kcontrol *kcontrol,
 483                 struct snd_ctl_elem_info *uinfo)
 484 {
 485         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 486         uinfo->count = 1;
 487         uinfo->value.integer.min = -128;
 488         uinfo->value.integer.max = 127;
 489 
 490         return 0;
 491 }
 492 
 493 static int img_spdif_in_get_lock_acquire(struct snd_kcontrol *kcontrol,
 494                                   struct snd_ctl_elem_value *ucontrol)
 495 {
 496         struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 497         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
 498 
 499         ucontrol->value.integer.value[0] = spdif->lock_acquire;
 500 
 501         return 0;
 502 }
 503 
 504 static int img_spdif_in_set_lock_acquire(struct snd_kcontrol *kcontrol,
 505                                   struct snd_ctl_elem_value *ucontrol)
 506 {
 507         struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 508         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
 509         unsigned long flags;
 510         u32 reg;
 511 
 512         spin_lock_irqsave(&spdif->lock, flags);
 513 
 514         if (spdif->active) {
 515                 spin_unlock_irqrestore(&spdif->lock, flags);
 516                 return -EBUSY;
 517         }
 518 
 519         spdif->lock_acquire = ucontrol->value.integer.value[0];
 520 
 521         reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
 522         reg &= ~IMG_SPDIF_IN_CTL_LOCKHI_MASK;
 523         reg |= (spdif->lock_acquire << IMG_SPDIF_IN_CTL_LOCKHI_SHIFT) &
 524                 IMG_SPDIF_IN_CTL_LOCKHI_MASK;
 525         img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
 526 
 527         spin_unlock_irqrestore(&spdif->lock, flags);
 528 
 529         return 0;
 530 }
 531 
 532 static int img_spdif_in_get_lock_release(struct snd_kcontrol *kcontrol,
 533                                   struct snd_ctl_elem_value *ucontrol)
 534 {
 535         struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 536         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
 537 
 538         ucontrol->value.integer.value[0] = spdif->lock_release;
 539 
 540         return 0;
 541 }
 542 
 543 static int img_spdif_in_set_lock_release(struct snd_kcontrol *kcontrol,
 544                                   struct snd_ctl_elem_value *ucontrol)
 545 {
 546         struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
 547         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
 548         unsigned long flags;
 549         u32 reg;
 550 
 551         spin_lock_irqsave(&spdif->lock, flags);
 552 
 553         if (spdif->active) {
 554                 spin_unlock_irqrestore(&spdif->lock, flags);
 555                 return -EBUSY;
 556         }
 557 
 558         spdif->lock_release = ucontrol->value.integer.value[0];
 559 
 560         reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
 561         reg &= ~IMG_SPDIF_IN_CTL_LOCKLO_MASK;
 562         reg |= (spdif->lock_release << IMG_SPDIF_IN_CTL_LOCKLO_SHIFT) &
 563                 IMG_SPDIF_IN_CTL_LOCKLO_MASK;
 564         img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
 565 
 566         spin_unlock_irqrestore(&spdif->lock, flags);
 567 
 568         return 0;
 569 }
 570 
 571 static struct snd_kcontrol_new img_spdif_in_controls[] = {
 572         {
 573                 .access = SNDRV_CTL_ELEM_ACCESS_READ,
 574                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
 575                 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
 576                 .info = img_spdif_in_iec958_info,
 577                 .get = img_spdif_in_get_status_mask
 578         },
 579         {
 580                 .access = SNDRV_CTL_ELEM_ACCESS_READ |
 581                         SNDRV_CTL_ELEM_ACCESS_VOLATILE,
 582                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
 583                 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
 584                 .info = img_spdif_in_iec958_info,
 585                 .get = img_spdif_in_get_status
 586         },
 587         {
 588                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
 589                 .name = "SPDIF In Multi Frequency Acquire",
 590                 .info = img_spdif_in_info_multi_freq,
 591                 .get = img_spdif_in_get_multi_freq,
 592                 .put = img_spdif_in_set_multi_freq
 593         },
 594         {
 595                 .access = SNDRV_CTL_ELEM_ACCESS_READ |
 596                         SNDRV_CTL_ELEM_ACCESS_VOLATILE,
 597                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
 598                 .name = "SPDIF In Lock Frequency",
 599                 .info = img_spdif_in_info_lock_freq,
 600                 .get = img_spdif_in_get_lock_freq
 601         },
 602         {
 603                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
 604                 .name = "SPDIF In Lock TRK",
 605                 .info = img_spdif_in_info_trk,
 606                 .get = img_spdif_in_get_trk,
 607                 .put = img_spdif_in_set_trk
 608         },
 609         {
 610                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
 611                 .name = "SPDIF In Lock Acquire Threshold",
 612                 .info = img_spdif_in_info_lock,
 613                 .get = img_spdif_in_get_lock_acquire,
 614                 .put = img_spdif_in_set_lock_acquire
 615         },
 616         {
 617                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
 618                 .name = "SPDIF In Lock Release Threshold",
 619                 .info = img_spdif_in_info_lock,
 620                 .get = img_spdif_in_get_lock_release,
 621                 .put = img_spdif_in_set_lock_release
 622         }
 623 };
 624 
 625 static int img_spdif_in_trigger(struct snd_pcm_substream *substream, int cmd,
 626         struct snd_soc_dai *dai)
 627 {
 628         unsigned long flags;
 629         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai);
 630         int ret = 0;
 631         u32 reg;
 632 
 633         spin_lock_irqsave(&spdif->lock, flags);
 634 
 635         switch (cmd) {
 636         case SNDRV_PCM_TRIGGER_START:
 637         case SNDRV_PCM_TRIGGER_RESUME:
 638         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 639                 reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
 640                 if (spdif->multi_freq)
 641                         reg &= ~IMG_SPDIF_IN_CTL_SRD_MASK;
 642                 else
 643                         reg |= (1UL << IMG_SPDIF_IN_CTL_SRD_SHIFT);
 644                 reg |= IMG_SPDIF_IN_CTL_SRT_MASK;
 645                 img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
 646                 spdif->active = true;
 647                 break;
 648         case SNDRV_PCM_TRIGGER_STOP:
 649         case SNDRV_PCM_TRIGGER_SUSPEND:
 650         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 651                 reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
 652                 reg &= ~IMG_SPDIF_IN_CTL_SRT_MASK;
 653                 img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
 654                 spdif->active = false;
 655                 break;
 656         default:
 657                 ret = -EINVAL;
 658         }
 659 
 660         spin_unlock_irqrestore(&spdif->lock, flags);
 661 
 662         return ret;
 663 }
 664 
 665 static int img_spdif_in_hw_params(struct snd_pcm_substream *substream,
 666         struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 667 {
 668         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai);
 669         unsigned int rate, channels;
 670         snd_pcm_format_t format;
 671 
 672         rate = params_rate(params);
 673         channels = params_channels(params);
 674         format = params_format(params);
 675 
 676         if (format != SNDRV_PCM_FORMAT_S32_LE)
 677                 return -EINVAL;
 678 
 679         if (channels != 2)
 680                 return -EINVAL;
 681 
 682         return img_spdif_in_do_clkgen_single(spdif, rate);
 683 }
 684 
 685 static const struct snd_soc_dai_ops img_spdif_in_dai_ops = {
 686         .trigger = img_spdif_in_trigger,
 687         .hw_params = img_spdif_in_hw_params
 688 };
 689 
 690 static int img_spdif_in_dai_probe(struct snd_soc_dai *dai)
 691 {
 692         struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai);
 693 
 694         snd_soc_dai_init_dma_data(dai, NULL, &spdif->dma_data);
 695 
 696         snd_soc_add_dai_controls(dai, img_spdif_in_controls,
 697                         ARRAY_SIZE(img_spdif_in_controls));
 698 
 699         return 0;
 700 }
 701 
 702 static struct snd_soc_dai_driver img_spdif_in_dai = {
 703         .probe = img_spdif_in_dai_probe,
 704         .capture = {
 705                 .channels_min = 2,
 706                 .channels_max = 2,
 707                 .rates = SNDRV_PCM_RATE_8000_192000,
 708                 .formats = SNDRV_PCM_FMTBIT_S32_LE
 709         },
 710         .ops = &img_spdif_in_dai_ops
 711 };
 712 
 713 static const struct snd_soc_component_driver img_spdif_in_component = {
 714         .name = "img-spdif-in"
 715 };
 716 
 717 static int img_spdif_in_probe(struct platform_device *pdev)
 718 {
 719         struct img_spdif_in *spdif;
 720         struct resource *res;
 721         void __iomem *base;
 722         int ret;
 723         struct reset_control *rst;
 724         u32 reg;
 725         struct device *dev = &pdev->dev;
 726 
 727         spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL);
 728         if (!spdif)
 729                 return -ENOMEM;
 730 
 731         platform_set_drvdata(pdev, spdif);
 732 
 733         spdif->dev = &pdev->dev;
 734 
 735         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 736         base = devm_ioremap_resource(&pdev->dev, res);
 737         if (IS_ERR(base))
 738                 return PTR_ERR(base);
 739 
 740         spdif->base = base;
 741 
 742         spdif->clk_sys = devm_clk_get(dev, "sys");
 743         if (IS_ERR(spdif->clk_sys)) {
 744                 if (PTR_ERR(spdif->clk_sys) != -EPROBE_DEFER)
 745                         dev_err(dev, "Failed to acquire clock 'sys'\n");
 746                 return PTR_ERR(spdif->clk_sys);
 747         }
 748 
 749         pm_runtime_enable(&pdev->dev);
 750         if (!pm_runtime_enabled(&pdev->dev)) {
 751                 ret = img_spdif_in_runtime_resume(&pdev->dev);
 752                 if (ret)
 753                         goto err_pm_disable;
 754         }
 755         ret = pm_runtime_get_sync(&pdev->dev);
 756         if (ret < 0)
 757                 goto err_suspend;
 758 
 759         rst = devm_reset_control_get_exclusive(&pdev->dev, "rst");
 760         if (IS_ERR(rst)) {
 761                 if (PTR_ERR(rst) == -EPROBE_DEFER) {
 762                         ret = -EPROBE_DEFER;
 763                         goto err_pm_put;
 764                 }
 765                 dev_dbg(dev, "No top level reset found\n");
 766                 img_spdif_in_writel(spdif, IMG_SPDIF_IN_SOFT_RESET_MASK,
 767                                 IMG_SPDIF_IN_SOFT_RESET);
 768                 img_spdif_in_writel(spdif, 0, IMG_SPDIF_IN_SOFT_RESET);
 769         } else {
 770                 reset_control_assert(rst);
 771                 reset_control_deassert(rst);
 772         }
 773 
 774         spin_lock_init(&spdif->lock);
 775 
 776         spdif->dma_data.addr = res->start + IMG_SPDIF_IN_RX_FIFO_OFFSET;
 777         spdif->dma_data.addr_width = 4;
 778         spdif->dma_data.maxburst = 4;
 779         spdif->trk = 0x80;
 780         spdif->lock_acquire = 4;
 781         spdif->lock_release = -128;
 782 
 783         reg = (spdif->lock_acquire << IMG_SPDIF_IN_CTL_LOCKHI_SHIFT) &
 784                 IMG_SPDIF_IN_CTL_LOCKHI_MASK;
 785         reg |= (spdif->lock_release << IMG_SPDIF_IN_CTL_LOCKLO_SHIFT) &
 786                 IMG_SPDIF_IN_CTL_LOCKLO_MASK;
 787         reg |= (spdif->trk << IMG_SPDIF_IN_CTL_TRK_SHIFT) &
 788                 IMG_SPDIF_IN_CTL_TRK_MASK;
 789         img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
 790 
 791         pm_runtime_put(&pdev->dev);
 792 
 793         ret = devm_snd_soc_register_component(&pdev->dev,
 794                         &img_spdif_in_component, &img_spdif_in_dai, 1);
 795         if (ret)
 796                 goto err_suspend;
 797 
 798         ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
 799         if (ret)
 800                 goto err_suspend;
 801 
 802         return 0;
 803 
 804 err_pm_put:
 805         pm_runtime_put(&pdev->dev);
 806 err_suspend:
 807         if (!pm_runtime_enabled(&pdev->dev))
 808                 img_spdif_in_runtime_suspend(&pdev->dev);
 809 err_pm_disable:
 810         pm_runtime_disable(&pdev->dev);
 811 
 812         return ret;
 813 }
 814 
 815 static int img_spdif_in_dev_remove(struct platform_device *pdev)
 816 {
 817         pm_runtime_disable(&pdev->dev);
 818         if (!pm_runtime_status_suspended(&pdev->dev))
 819                 img_spdif_in_runtime_suspend(&pdev->dev);
 820 
 821         return 0;
 822 }
 823 
 824 #ifdef CONFIG_PM_SLEEP
 825 static int img_spdif_in_suspend(struct device *dev)
 826 {
 827         struct img_spdif_in *spdif = dev_get_drvdata(dev);
 828         int ret;
 829 
 830         if (pm_runtime_status_suspended(dev)) {
 831                 ret = img_spdif_in_runtime_resume(dev);
 832                 if (ret)
 833                         return ret;
 834         }
 835 
 836         spdif->suspend_clkgen = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CLKGEN);
 837         spdif->suspend_ctl = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
 838 
 839         img_spdif_in_runtime_suspend(dev);
 840 
 841         return 0;
 842 }
 843 
 844 static int img_spdif_in_resume(struct device *dev)
 845 {
 846         struct img_spdif_in *spdif = dev_get_drvdata(dev);
 847         int i, ret;
 848 
 849         ret = img_spdif_in_runtime_resume(dev);
 850         if (ret)
 851                 return ret;
 852 
 853         for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++)
 854                 img_spdif_in_aclkgen_writel(spdif, i);
 855 
 856         img_spdif_in_writel(spdif, spdif->suspend_clkgen, IMG_SPDIF_IN_CLKGEN);
 857         img_spdif_in_writel(spdif, spdif->suspend_ctl, IMG_SPDIF_IN_CTL);
 858 
 859         if (pm_runtime_status_suspended(dev))
 860                 img_spdif_in_runtime_suspend(dev);
 861 
 862         return 0;
 863 }
 864 #endif
 865 
 866 static const struct of_device_id img_spdif_in_of_match[] = {
 867         { .compatible = "img,spdif-in" },
 868         {}
 869 };
 870 MODULE_DEVICE_TABLE(of, img_spdif_in_of_match);
 871 
 872 static const struct dev_pm_ops img_spdif_in_pm_ops = {
 873         SET_RUNTIME_PM_OPS(img_spdif_in_runtime_suspend,
 874                            img_spdif_in_runtime_resume, NULL)
 875         SET_SYSTEM_SLEEP_PM_OPS(img_spdif_in_suspend, img_spdif_in_resume)
 876 };
 877 
 878 static struct platform_driver img_spdif_in_driver = {
 879         .driver = {
 880                 .name = "img-spdif-in",
 881                 .of_match_table = img_spdif_in_of_match,
 882                 .pm = &img_spdif_in_pm_ops
 883         },
 884         .probe = img_spdif_in_probe,
 885         .remove = img_spdif_in_dev_remove
 886 };
 887 module_platform_driver(img_spdif_in_driver);
 888 
 889 MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
 890 MODULE_DESCRIPTION("IMG SPDIF Input driver");
 891 MODULE_LICENSE("GPL v2");

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