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 base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 736 if (IS_ERR(base)) 737 return PTR_ERR(base); 738 739 spdif->base = base; 740 741 spdif->clk_sys = devm_clk_get(dev, "sys"); 742 if (IS_ERR(spdif->clk_sys)) { 743 if (PTR_ERR(spdif->clk_sys) != -EPROBE_DEFER) 744 dev_err(dev, "Failed to acquire clock 'sys'\n"); 745 return PTR_ERR(spdif->clk_sys); 746 } 747 748 pm_runtime_enable(&pdev->dev); 749 if (!pm_runtime_enabled(&pdev->dev)) { 750 ret = img_spdif_in_runtime_resume(&pdev->dev); 751 if (ret) 752 goto err_pm_disable; 753 } 754 ret = pm_runtime_get_sync(&pdev->dev); 755 if (ret < 0) { 756 pm_runtime_put_noidle(&pdev->dev); 757 goto err_suspend; 758 } 759 760 rst = devm_reset_control_get_exclusive(&pdev->dev, "rst"); 761 if (IS_ERR(rst)) { 762 if (PTR_ERR(rst) == -EPROBE_DEFER) { 763 ret = -EPROBE_DEFER; 764 goto err_pm_put; 765 } 766 dev_dbg(dev, "No top level reset found\n"); 767 img_spdif_in_writel(spdif, IMG_SPDIF_IN_SOFT_RESET_MASK, 768 IMG_SPDIF_IN_SOFT_RESET); 769 img_spdif_in_writel(spdif, 0, IMG_SPDIF_IN_SOFT_RESET); 770 } else { 771 reset_control_assert(rst); 772 reset_control_deassert(rst); 773 } 774 775 spin_lock_init(&spdif->lock); 776 777 spdif->dma_data.addr = res->start + IMG_SPDIF_IN_RX_FIFO_OFFSET; 778 spdif->dma_data.addr_width = 4; 779 spdif->dma_data.maxburst = 4; 780 spdif->trk = 0x80; 781 spdif->lock_acquire = 4; 782 spdif->lock_release = -128; 783 784 reg = (spdif->lock_acquire << IMG_SPDIF_IN_CTL_LOCKHI_SHIFT) & 785 IMG_SPDIF_IN_CTL_LOCKHI_MASK; 786 reg |= (spdif->lock_release << IMG_SPDIF_IN_CTL_LOCKLO_SHIFT) & 787 IMG_SPDIF_IN_CTL_LOCKLO_MASK; 788 reg |= (spdif->trk << IMG_SPDIF_IN_CTL_TRK_SHIFT) & 789 IMG_SPDIF_IN_CTL_TRK_MASK; 790 img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL); 791 792 pm_runtime_put(&pdev->dev); 793 794 ret = devm_snd_soc_register_component(&pdev->dev, 795 &img_spdif_in_component, &img_spdif_in_dai, 1); 796 if (ret) 797 goto err_suspend; 798 799 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 800 if (ret) 801 goto err_suspend; 802 803 return 0; 804 805 err_pm_put: 806 pm_runtime_put(&pdev->dev); 807 err_suspend: 808 if (!pm_runtime_enabled(&pdev->dev)) 809 img_spdif_in_runtime_suspend(&pdev->dev); 810 err_pm_disable: 811 pm_runtime_disable(&pdev->dev); 812 813 return ret; 814 } 815 816 static int img_spdif_in_dev_remove(struct platform_device *pdev) 817 { 818 pm_runtime_disable(&pdev->dev); 819 if (!pm_runtime_status_suspended(&pdev->dev)) 820 img_spdif_in_runtime_suspend(&pdev->dev); 821 822 return 0; 823 } 824 825 #ifdef CONFIG_PM_SLEEP 826 static int img_spdif_in_suspend(struct device *dev) 827 { 828 struct img_spdif_in *spdif = dev_get_drvdata(dev); 829 int ret; 830 831 if (pm_runtime_status_suspended(dev)) { 832 ret = img_spdif_in_runtime_resume(dev); 833 if (ret) 834 return ret; 835 } 836 837 spdif->suspend_clkgen = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CLKGEN); 838 spdif->suspend_ctl = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL); 839 840 img_spdif_in_runtime_suspend(dev); 841 842 return 0; 843 } 844 845 static int img_spdif_in_resume(struct device *dev) 846 { 847 struct img_spdif_in *spdif = dev_get_drvdata(dev); 848 int i, ret; 849 850 ret = img_spdif_in_runtime_resume(dev); 851 if (ret) 852 return ret; 853 854 for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++) 855 img_spdif_in_aclkgen_writel(spdif, i); 856 857 img_spdif_in_writel(spdif, spdif->suspend_clkgen, IMG_SPDIF_IN_CLKGEN); 858 img_spdif_in_writel(spdif, spdif->suspend_ctl, IMG_SPDIF_IN_CTL); 859 860 if (pm_runtime_status_suspended(dev)) 861 img_spdif_in_runtime_suspend(dev); 862 863 return 0; 864 } 865 #endif 866 867 static const struct of_device_id img_spdif_in_of_match[] = { 868 { .compatible = "img,spdif-in" }, 869 {} 870 }; 871 MODULE_DEVICE_TABLE(of, img_spdif_in_of_match); 872 873 static const struct dev_pm_ops img_spdif_in_pm_ops = { 874 SET_RUNTIME_PM_OPS(img_spdif_in_runtime_suspend, 875 img_spdif_in_runtime_resume, NULL) 876 SET_SYSTEM_SLEEP_PM_OPS(img_spdif_in_suspend, img_spdif_in_resume) 877 }; 878 879 static struct platform_driver img_spdif_in_driver = { 880 .driver = { 881 .name = "img-spdif-in", 882 .of_match_table = img_spdif_in_of_match, 883 .pm = &img_spdif_in_pm_ops 884 }, 885 .probe = img_spdif_in_probe, 886 .remove = img_spdif_in_dev_remove 887 }; 888 module_platform_driver(img_spdif_in_driver); 889 890 MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>"); 891 MODULE_DESCRIPTION("IMG SPDIF Input driver"); 892 MODULE_LICENSE("GPL v2"); 893