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