1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Hewlett-Packard Harmony audio driver 3 * 4 * This is a driver for the Harmony audio chipset found 5 * on the LASI ASIC of various early HP PA-RISC workstations. 6 * 7 * Copyright (C) 2004, Kyle McMartin <kyle@{debian.org,parisc-linux.org}> 8 * 9 * Based on the previous Harmony incarnations by, 10 * Copyright 2000 (c) Linuxcare Canada, Alex deVries 11 * Copyright 2000-2003 (c) Helge Deller 12 * Copyright 2001 (c) Matthieu Delahaye 13 * Copyright 2001 (c) Jean-Christophe Vaugeois 14 * Copyright 2003 (c) Laurent Canet 15 * Copyright 2004 (c) Stuart Brady 16 * 17 * Notes: 18 * - graveyard and silence buffers last for lifetime of 19 * the driver. playback and capture buffers are allocated 20 * per _open()/_close(). 21 * 22 * TODO: 23 */ 24 25 #include <linux/init.h> 26 #include <linux/slab.h> 27 #include <linux/time.h> 28 #include <linux/wait.h> 29 #include <linux/delay.h> 30 #include <linux/module.h> 31 #include <linux/interrupt.h> 32 #include <linux/spinlock.h> 33 #include <linux/dma-mapping.h> 34 #include <linux/io.h> 35 36 #include <sound/core.h> 37 #include <sound/pcm.h> 38 #include <sound/control.h> 39 #include <sound/rawmidi.h> 40 #include <sound/initval.h> 41 #include <sound/info.h> 42 43 #include <asm/hardware.h> 44 #include <asm/parisc-device.h> 45 46 #include "harmony.h" 47 48 static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ 49 static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ 50 module_param(index, int, 0444); 51 MODULE_PARM_DESC(index, "Index value for Harmony driver."); 52 module_param(id, charp, 0444); 53 MODULE_PARM_DESC(id, "ID string for Harmony driver."); 54 55 56 static const struct parisc_device_id snd_harmony_devtable[] __initconst = { 57 /* bushmaster / flounder */ 58 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, 59 /* 712 / 715 */ 60 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, 61 /* pace */ 62 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, 63 /* outfield / coral II */ 64 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F }, 65 { 0, } 66 }; 67 68 MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable); 69 70 #define NAME "harmony" 71 #define PFX NAME ": " 72 73 static const unsigned int snd_harmony_rates[] = { 74 5512, 6615, 8000, 9600, 75 11025, 16000, 18900, 22050, 76 27428, 32000, 33075, 37800, 77 44100, 48000 78 }; 79 80 static const unsigned int rate_bits[14] = { 81 HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ, 82 HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ, 83 HARMONY_SR_18KHZ, HARMONY_SR_22KHZ, HARMONY_SR_27KHZ, 84 HARMONY_SR_32KHZ, HARMONY_SR_33KHZ, HARMONY_SR_37KHZ, 85 HARMONY_SR_44KHZ, HARMONY_SR_48KHZ 86 }; 87 88 static const struct snd_pcm_hw_constraint_list hw_constraint_rates = { 89 .count = ARRAY_SIZE(snd_harmony_rates), 90 .list = snd_harmony_rates, 91 .mask = 0, 92 }; 93 94 static inline unsigned long 95 harmony_read(struct snd_harmony *h, unsigned r) 96 { 97 return __raw_readl(h->iobase + r); 98 } 99 100 static inline void 101 harmony_write(struct snd_harmony *h, unsigned r, unsigned long v) 102 { 103 __raw_writel(v, h->iobase + r); 104 } 105 106 static inline void 107 harmony_wait_for_control(struct snd_harmony *h) 108 { 109 while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ; 110 } 111 112 static inline void 113 harmony_reset(struct snd_harmony *h) 114 { 115 harmony_write(h, HARMONY_RESET, 1); 116 mdelay(50); 117 harmony_write(h, HARMONY_RESET, 0); 118 } 119 120 static void 121 harmony_disable_interrupts(struct snd_harmony *h) 122 { 123 u32 dstatus; 124 harmony_wait_for_control(h); 125 dstatus = harmony_read(h, HARMONY_DSTATUS); 126 dstatus &= ~HARMONY_DSTATUS_IE; 127 harmony_write(h, HARMONY_DSTATUS, dstatus); 128 } 129 130 static void 131 harmony_enable_interrupts(struct snd_harmony *h) 132 { 133 u32 dstatus; 134 harmony_wait_for_control(h); 135 dstatus = harmony_read(h, HARMONY_DSTATUS); 136 dstatus |= HARMONY_DSTATUS_IE; 137 harmony_write(h, HARMONY_DSTATUS, dstatus); 138 } 139 140 static void 141 harmony_mute(struct snd_harmony *h) 142 { 143 unsigned long flags; 144 145 spin_lock_irqsave(&h->mixer_lock, flags); 146 harmony_wait_for_control(h); 147 harmony_write(h, HARMONY_GAINCTL, HARMONY_GAIN_SILENCE); 148 spin_unlock_irqrestore(&h->mixer_lock, flags); 149 } 150 151 static void 152 harmony_unmute(struct snd_harmony *h) 153 { 154 unsigned long flags; 155 156 spin_lock_irqsave(&h->mixer_lock, flags); 157 harmony_wait_for_control(h); 158 harmony_write(h, HARMONY_GAINCTL, h->st.gain); 159 spin_unlock_irqrestore(&h->mixer_lock, flags); 160 } 161 162 static void 163 harmony_set_control(struct snd_harmony *h) 164 { 165 u32 ctrl; 166 unsigned long flags; 167 168 spin_lock_irqsave(&h->lock, flags); 169 170 ctrl = (HARMONY_CNTL_C | 171 (h->st.format << 6) | 172 (h->st.stereo << 5) | 173 (h->st.rate)); 174 175 harmony_wait_for_control(h); 176 harmony_write(h, HARMONY_CNTL, ctrl); 177 178 spin_unlock_irqrestore(&h->lock, flags); 179 } 180 181 static irqreturn_t 182 snd_harmony_interrupt(int irq, void *dev) 183 { 184 u32 dstatus; 185 struct snd_harmony *h = dev; 186 187 spin_lock(&h->lock); 188 harmony_disable_interrupts(h); 189 harmony_wait_for_control(h); 190 dstatus = harmony_read(h, HARMONY_DSTATUS); 191 spin_unlock(&h->lock); 192 193 if (dstatus & HARMONY_DSTATUS_PN) { 194 if (h->psubs && h->st.playing) { 195 spin_lock(&h->lock); 196 h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */ 197 h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */ 198 199 harmony_write(h, HARMONY_PNXTADD, 200 h->pbuf.addr + h->pbuf.buf); 201 h->stats.play_intr++; 202 spin_unlock(&h->lock); 203 snd_pcm_period_elapsed(h->psubs); 204 } else { 205 spin_lock(&h->lock); 206 harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); 207 h->stats.silence_intr++; 208 spin_unlock(&h->lock); 209 } 210 } 211 212 if (dstatus & HARMONY_DSTATUS_RN) { 213 if (h->csubs && h->st.capturing) { 214 spin_lock(&h->lock); 215 h->cbuf.buf += h->cbuf.count; 216 h->cbuf.buf %= h->cbuf.size; 217 218 harmony_write(h, HARMONY_RNXTADD, 219 h->cbuf.addr + h->cbuf.buf); 220 h->stats.rec_intr++; 221 spin_unlock(&h->lock); 222 snd_pcm_period_elapsed(h->csubs); 223 } else { 224 spin_lock(&h->lock); 225 harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); 226 h->stats.graveyard_intr++; 227 spin_unlock(&h->lock); 228 } 229 } 230 231 spin_lock(&h->lock); 232 harmony_enable_interrupts(h); 233 spin_unlock(&h->lock); 234 235 return IRQ_HANDLED; 236 } 237 238 static unsigned int 239 snd_harmony_rate_bits(int rate) 240 { 241 unsigned int i; 242 243 for (i = 0; i < ARRAY_SIZE(snd_harmony_rates); i++) 244 if (snd_harmony_rates[i] == rate) 245 return rate_bits[i]; 246 247 return HARMONY_SR_44KHZ; 248 } 249 250 static const struct snd_pcm_hardware snd_harmony_playback = 251 { 252 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 253 SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID | 254 SNDRV_PCM_INFO_BLOCK_TRANSFER), 255 .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW | 256 SNDRV_PCM_FMTBIT_A_LAW), 257 .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 | 258 SNDRV_PCM_RATE_KNOT), 259 .rate_min = 5512, 260 .rate_max = 48000, 261 .channels_min = 1, 262 .channels_max = 2, 263 .buffer_bytes_max = MAX_BUF_SIZE, 264 .period_bytes_min = BUF_SIZE, 265 .period_bytes_max = BUF_SIZE, 266 .periods_min = 1, 267 .periods_max = MAX_BUFS, 268 .fifo_size = 0, 269 }; 270 271 static const struct snd_pcm_hardware snd_harmony_capture = 272 { 273 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 274 SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID | 275 SNDRV_PCM_INFO_BLOCK_TRANSFER), 276 .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW | 277 SNDRV_PCM_FMTBIT_A_LAW), 278 .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 | 279 SNDRV_PCM_RATE_KNOT), 280 .rate_min = 5512, 281 .rate_max = 48000, 282 .channels_min = 1, 283 .channels_max = 2, 284 .buffer_bytes_max = MAX_BUF_SIZE, 285 .period_bytes_min = BUF_SIZE, 286 .period_bytes_max = BUF_SIZE, 287 .periods_min = 1, 288 .periods_max = MAX_BUFS, 289 .fifo_size = 0, 290 }; 291 292 static int 293 snd_harmony_playback_trigger(struct snd_pcm_substream *ss, int cmd) 294 { 295 struct snd_harmony *h = snd_pcm_substream_chip(ss); 296 297 if (h->st.capturing) 298 return -EBUSY; 299 300 spin_lock(&h->lock); 301 switch (cmd) { 302 case SNDRV_PCM_TRIGGER_START: 303 h->st.playing = 1; 304 harmony_write(h, HARMONY_PNXTADD, h->pbuf.addr); 305 harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); 306 harmony_unmute(h); 307 harmony_enable_interrupts(h); 308 break; 309 case SNDRV_PCM_TRIGGER_STOP: 310 h->st.playing = 0; 311 harmony_mute(h); 312 harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); 313 harmony_disable_interrupts(h); 314 break; 315 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 316 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 317 case SNDRV_PCM_TRIGGER_SUSPEND: 318 default: 319 spin_unlock(&h->lock); 320 snd_BUG(); 321 return -EINVAL; 322 } 323 spin_unlock(&h->lock); 324 325 return 0; 326 } 327 328 static int 329 snd_harmony_capture_trigger(struct snd_pcm_substream *ss, int cmd) 330 { 331 struct snd_harmony *h = snd_pcm_substream_chip(ss); 332 333 if (h->st.playing) 334 return -EBUSY; 335 336 spin_lock(&h->lock); 337 switch (cmd) { 338 case SNDRV_PCM_TRIGGER_START: 339 h->st.capturing = 1; 340 harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); 341 harmony_write(h, HARMONY_RNXTADD, h->cbuf.addr); 342 harmony_unmute(h); 343 harmony_enable_interrupts(h); 344 break; 345 case SNDRV_PCM_TRIGGER_STOP: 346 h->st.capturing = 0; 347 harmony_mute(h); 348 harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); 349 harmony_disable_interrupts(h); 350 break; 351 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 352 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 353 case SNDRV_PCM_TRIGGER_SUSPEND: 354 default: 355 spin_unlock(&h->lock); 356 snd_BUG(); 357 return -EINVAL; 358 } 359 spin_unlock(&h->lock); 360 361 return 0; 362 } 363 364 static int 365 snd_harmony_set_data_format(struct snd_harmony *h, int fmt, int force) 366 { 367 int o = h->st.format; 368 int n; 369 370 switch(fmt) { 371 case SNDRV_PCM_FORMAT_S16_BE: 372 n = HARMONY_DF_16BIT_LINEAR; 373 break; 374 case SNDRV_PCM_FORMAT_A_LAW: 375 n = HARMONY_DF_8BIT_ALAW; 376 break; 377 case SNDRV_PCM_FORMAT_MU_LAW: 378 n = HARMONY_DF_8BIT_ULAW; 379 break; 380 default: 381 n = HARMONY_DF_16BIT_LINEAR; 382 break; 383 } 384 385 if (force || o != n) { 386 snd_pcm_format_set_silence(fmt, h->sdma.area, SILENCE_BUFSZ / 387 (snd_pcm_format_physical_width(fmt) 388 / 8)); 389 } 390 391 return n; 392 } 393 394 static int 395 snd_harmony_playback_prepare(struct snd_pcm_substream *ss) 396 { 397 struct snd_harmony *h = snd_pcm_substream_chip(ss); 398 struct snd_pcm_runtime *rt = ss->runtime; 399 400 if (h->st.capturing) 401 return -EBUSY; 402 403 h->pbuf.size = snd_pcm_lib_buffer_bytes(ss); 404 h->pbuf.count = snd_pcm_lib_period_bytes(ss); 405 if (h->pbuf.buf >= h->pbuf.size) 406 h->pbuf.buf = 0; 407 h->st.playing = 0; 408 409 h->st.rate = snd_harmony_rate_bits(rt->rate); 410 h->st.format = snd_harmony_set_data_format(h, rt->format, 0); 411 412 if (rt->channels == 2) 413 h->st.stereo = HARMONY_SS_STEREO; 414 else 415 h->st.stereo = HARMONY_SS_MONO; 416 417 harmony_set_control(h); 418 419 h->pbuf.addr = rt->dma_addr; 420 421 return 0; 422 } 423 424 static int 425 snd_harmony_capture_prepare(struct snd_pcm_substream *ss) 426 { 427 struct snd_harmony *h = snd_pcm_substream_chip(ss); 428 struct snd_pcm_runtime *rt = ss->runtime; 429 430 if (h->st.playing) 431 return -EBUSY; 432 433 h->cbuf.size = snd_pcm_lib_buffer_bytes(ss); 434 h->cbuf.count = snd_pcm_lib_period_bytes(ss); 435 if (h->cbuf.buf >= h->cbuf.size) 436 h->cbuf.buf = 0; 437 h->st.capturing = 0; 438 439 h->st.rate = snd_harmony_rate_bits(rt->rate); 440 h->st.format = snd_harmony_set_data_format(h, rt->format, 0); 441 442 if (rt->channels == 2) 443 h->st.stereo = HARMONY_SS_STEREO; 444 else 445 h->st.stereo = HARMONY_SS_MONO; 446 447 harmony_set_control(h); 448 449 h->cbuf.addr = rt->dma_addr; 450 451 return 0; 452 } 453 454 static snd_pcm_uframes_t 455 snd_harmony_playback_pointer(struct snd_pcm_substream *ss) 456 { 457 struct snd_pcm_runtime *rt = ss->runtime; 458 struct snd_harmony *h = snd_pcm_substream_chip(ss); 459 unsigned long pcuradd; 460 unsigned long played; 461 462 if (!(h->st.playing) || (h->psubs == NULL)) 463 return 0; 464 465 if ((h->pbuf.addr == 0) || (h->pbuf.size == 0)) 466 return 0; 467 468 pcuradd = harmony_read(h, HARMONY_PCURADD); 469 played = pcuradd - h->pbuf.addr; 470 471 #ifdef HARMONY_DEBUG 472 printk(KERN_DEBUG PFX "playback_pointer is 0x%lx-0x%lx = %d bytes\n", 473 pcuradd, h->pbuf.addr, played); 474 #endif 475 476 if (pcuradd > h->pbuf.addr + h->pbuf.size) { 477 return 0; 478 } 479 480 return bytes_to_frames(rt, played); 481 } 482 483 static snd_pcm_uframes_t 484 snd_harmony_capture_pointer(struct snd_pcm_substream *ss) 485 { 486 struct snd_pcm_runtime *rt = ss->runtime; 487 struct snd_harmony *h = snd_pcm_substream_chip(ss); 488 unsigned long rcuradd; 489 unsigned long caught; 490 491 if (!(h->st.capturing) || (h->csubs == NULL)) 492 return 0; 493 494 if ((h->cbuf.addr == 0) || (h->cbuf.size == 0)) 495 return 0; 496 497 rcuradd = harmony_read(h, HARMONY_RCURADD); 498 caught = rcuradd - h->cbuf.addr; 499 500 #ifdef HARMONY_DEBUG 501 printk(KERN_DEBUG PFX "capture_pointer is 0x%lx-0x%lx = %d bytes\n", 502 rcuradd, h->cbuf.addr, caught); 503 #endif 504 505 if (rcuradd > h->cbuf.addr + h->cbuf.size) { 506 return 0; 507 } 508 509 return bytes_to_frames(rt, caught); 510 } 511 512 static int 513 snd_harmony_playback_open(struct snd_pcm_substream *ss) 514 { 515 struct snd_harmony *h = snd_pcm_substream_chip(ss); 516 struct snd_pcm_runtime *rt = ss->runtime; 517 int err; 518 519 h->psubs = ss; 520 rt->hw = snd_harmony_playback; 521 snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE, 522 &hw_constraint_rates); 523 524 err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS); 525 if (err < 0) 526 return err; 527 528 return 0; 529 } 530 531 static int 532 snd_harmony_capture_open(struct snd_pcm_substream *ss) 533 { 534 struct snd_harmony *h = snd_pcm_substream_chip(ss); 535 struct snd_pcm_runtime *rt = ss->runtime; 536 int err; 537 538 h->csubs = ss; 539 rt->hw = snd_harmony_capture; 540 snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE, 541 &hw_constraint_rates); 542 543 err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS); 544 if (err < 0) 545 return err; 546 547 return 0; 548 } 549 550 static int 551 snd_harmony_playback_close(struct snd_pcm_substream *ss) 552 { 553 struct snd_harmony *h = snd_pcm_substream_chip(ss); 554 h->psubs = NULL; 555 return 0; 556 } 557 558 static int 559 snd_harmony_capture_close(struct snd_pcm_substream *ss) 560 { 561 struct snd_harmony *h = snd_pcm_substream_chip(ss); 562 h->csubs = NULL; 563 return 0; 564 } 565 566 static int 567 snd_harmony_hw_params(struct snd_pcm_substream *ss, 568 struct snd_pcm_hw_params *hw) 569 { 570 int err; 571 struct snd_harmony *h = snd_pcm_substream_chip(ss); 572 573 err = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw)); 574 if (err > 0 && h->dma.type == SNDRV_DMA_TYPE_CONTINUOUS) 575 ss->runtime->dma_addr = __pa(ss->runtime->dma_area); 576 577 return err; 578 } 579 580 static int 581 snd_harmony_hw_free(struct snd_pcm_substream *ss) 582 { 583 return snd_pcm_lib_free_pages(ss); 584 } 585 586 static const struct snd_pcm_ops snd_harmony_playback_ops = { 587 .open = snd_harmony_playback_open, 588 .close = snd_harmony_playback_close, 589 .ioctl = snd_pcm_lib_ioctl, 590 .hw_params = snd_harmony_hw_params, 591 .hw_free = snd_harmony_hw_free, 592 .prepare = snd_harmony_playback_prepare, 593 .trigger = snd_harmony_playback_trigger, 594 .pointer = snd_harmony_playback_pointer, 595 }; 596 597 static const struct snd_pcm_ops snd_harmony_capture_ops = { 598 .open = snd_harmony_capture_open, 599 .close = snd_harmony_capture_close, 600 .ioctl = snd_pcm_lib_ioctl, 601 .hw_params = snd_harmony_hw_params, 602 .hw_free = snd_harmony_hw_free, 603 .prepare = snd_harmony_capture_prepare, 604 .trigger = snd_harmony_capture_trigger, 605 .pointer = snd_harmony_capture_pointer, 606 }; 607 608 static int 609 snd_harmony_pcm_init(struct snd_harmony *h) 610 { 611 struct snd_pcm *pcm; 612 int err; 613 614 if (snd_BUG_ON(!h)) 615 return -EINVAL; 616 617 harmony_disable_interrupts(h); 618 619 err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm); 620 if (err < 0) 621 return err; 622 623 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 624 &snd_harmony_playback_ops); 625 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 626 &snd_harmony_capture_ops); 627 628 pcm->private_data = h; 629 pcm->info_flags = 0; 630 strcpy(pcm->name, "harmony"); 631 h->pcm = pcm; 632 633 h->psubs = NULL; 634 h->csubs = NULL; 635 636 /* initialize graveyard buffer */ 637 h->dma.type = SNDRV_DMA_TYPE_DEV; 638 h->dma.dev = &h->dev->dev; 639 err = snd_dma_alloc_pages(h->dma.type, 640 h->dma.dev, 641 BUF_SIZE*GRAVEYARD_BUFS, 642 &h->gdma); 643 if (err < 0) { 644 printk(KERN_ERR PFX "cannot allocate graveyard buffer!\n"); 645 return err; 646 } 647 648 /* initialize silence buffers */ 649 err = snd_dma_alloc_pages(h->dma.type, 650 h->dma.dev, 651 BUF_SIZE*SILENCE_BUFS, 652 &h->sdma); 653 if (err < 0) { 654 printk(KERN_ERR PFX "cannot allocate silence buffer!\n"); 655 return err; 656 } 657 658 /* pre-allocate space for DMA */ 659 snd_pcm_lib_preallocate_pages_for_all(pcm, h->dma.type, h->dma.dev, 660 MAX_BUF_SIZE, MAX_BUF_SIZE); 661 662 h->st.format = snd_harmony_set_data_format(h, 663 SNDRV_PCM_FORMAT_S16_BE, 1); 664 665 return 0; 666 } 667 668 static void 669 snd_harmony_set_new_gain(struct snd_harmony *h) 670 { 671 harmony_wait_for_control(h); 672 harmony_write(h, HARMONY_GAINCTL, h->st.gain); 673 } 674 675 static int 676 snd_harmony_mixercontrol_info(struct snd_kcontrol *kc, 677 struct snd_ctl_elem_info *uinfo) 678 { 679 int mask = (kc->private_value >> 16) & 0xff; 680 int left_shift = (kc->private_value) & 0xff; 681 int right_shift = (kc->private_value >> 8) & 0xff; 682 683 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : 684 SNDRV_CTL_ELEM_TYPE_INTEGER; 685 uinfo->count = left_shift == right_shift ? 1 : 2; 686 uinfo->value.integer.min = 0; 687 uinfo->value.integer.max = mask; 688 689 return 0; 690 } 691 692 static int 693 snd_harmony_volume_get(struct snd_kcontrol *kc, 694 struct snd_ctl_elem_value *ucontrol) 695 { 696 struct snd_harmony *h = snd_kcontrol_chip(kc); 697 int shift_left = (kc->private_value) & 0xff; 698 int shift_right = (kc->private_value >> 8) & 0xff; 699 int mask = (kc->private_value >> 16) & 0xff; 700 int invert = (kc->private_value >> 24) & 0xff; 701 int left, right; 702 703 spin_lock_irq(&h->mixer_lock); 704 705 left = (h->st.gain >> shift_left) & mask; 706 right = (h->st.gain >> shift_right) & mask; 707 if (invert) { 708 left = mask - left; 709 right = mask - right; 710 } 711 712 ucontrol->value.integer.value[0] = left; 713 if (shift_left != shift_right) 714 ucontrol->value.integer.value[1] = right; 715 716 spin_unlock_irq(&h->mixer_lock); 717 718 return 0; 719 } 720 721 static int 722 snd_harmony_volume_put(struct snd_kcontrol *kc, 723 struct snd_ctl_elem_value *ucontrol) 724 { 725 struct snd_harmony *h = snd_kcontrol_chip(kc); 726 int shift_left = (kc->private_value) & 0xff; 727 int shift_right = (kc->private_value >> 8) & 0xff; 728 int mask = (kc->private_value >> 16) & 0xff; 729 int invert = (kc->private_value >> 24) & 0xff; 730 int left, right; 731 int old_gain = h->st.gain; 732 733 spin_lock_irq(&h->mixer_lock); 734 735 left = ucontrol->value.integer.value[0] & mask; 736 if (invert) 737 left = mask - left; 738 h->st.gain &= ~( (mask << shift_left ) ); 739 h->st.gain |= (left << shift_left); 740 741 if (shift_left != shift_right) { 742 right = ucontrol->value.integer.value[1] & mask; 743 if (invert) 744 right = mask - right; 745 h->st.gain &= ~( (mask << shift_right) ); 746 h->st.gain |= (right << shift_right); 747 } 748 749 snd_harmony_set_new_gain(h); 750 751 spin_unlock_irq(&h->mixer_lock); 752 753 return h->st.gain != old_gain; 754 } 755 756 static int 757 snd_harmony_captureroute_info(struct snd_kcontrol *kc, 758 struct snd_ctl_elem_info *uinfo) 759 { 760 static const char * const texts[2] = { "Line", "Mic" }; 761 762 return snd_ctl_enum_info(uinfo, 1, 2, texts); 763 } 764 765 static int 766 snd_harmony_captureroute_get(struct snd_kcontrol *kc, 767 struct snd_ctl_elem_value *ucontrol) 768 { 769 struct snd_harmony *h = snd_kcontrol_chip(kc); 770 int value; 771 772 spin_lock_irq(&h->mixer_lock); 773 774 value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1; 775 ucontrol->value.enumerated.item[0] = value; 776 777 spin_unlock_irq(&h->mixer_lock); 778 779 return 0; 780 } 781 782 static int 783 snd_harmony_captureroute_put(struct snd_kcontrol *kc, 784 struct snd_ctl_elem_value *ucontrol) 785 { 786 struct snd_harmony *h = snd_kcontrol_chip(kc); 787 int value; 788 int old_gain = h->st.gain; 789 790 spin_lock_irq(&h->mixer_lock); 791 792 value = ucontrol->value.enumerated.item[0] & 1; 793 h->st.gain &= ~HARMONY_GAIN_IS_MASK; 794 h->st.gain |= value << HARMONY_GAIN_IS_SHIFT; 795 796 snd_harmony_set_new_gain(h); 797 798 spin_unlock_irq(&h->mixer_lock); 799 800 return h->st.gain != old_gain; 801 } 802 803 #define HARMONY_CONTROLS ARRAY_SIZE(snd_harmony_controls) 804 805 #define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \ 806 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 807 .info = snd_harmony_mixercontrol_info, \ 808 .get = snd_harmony_volume_get, .put = snd_harmony_volume_put, \ 809 .private_value = ((left_shift) | ((right_shift) << 8) | \ 810 ((mask) << 16) | ((invert) << 24)) } 811 812 static struct snd_kcontrol_new snd_harmony_controls[] = { 813 HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT, 814 HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1), 815 HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT, 816 HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0), 817 HARMONY_VOLUME("Monitor Volume", HARMONY_GAIN_MA_SHIFT, 818 HARMONY_GAIN_MA_SHIFT, HARMONY_GAIN_MA, 1), 819 { 820 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 821 .name = "Input Route", 822 .info = snd_harmony_captureroute_info, 823 .get = snd_harmony_captureroute_get, 824 .put = snd_harmony_captureroute_put 825 }, 826 HARMONY_VOLUME("Internal Speaker Switch", HARMONY_GAIN_SE_SHIFT, 827 HARMONY_GAIN_SE_SHIFT, 1, 0), 828 HARMONY_VOLUME("Line-Out Switch", HARMONY_GAIN_LE_SHIFT, 829 HARMONY_GAIN_LE_SHIFT, 1, 0), 830 HARMONY_VOLUME("Headphones Switch", HARMONY_GAIN_HE_SHIFT, 831 HARMONY_GAIN_HE_SHIFT, 1, 0), 832 }; 833 834 static void 835 snd_harmony_mixer_reset(struct snd_harmony *h) 836 { 837 harmony_mute(h); 838 harmony_reset(h); 839 h->st.gain = HARMONY_GAIN_DEFAULT; 840 harmony_unmute(h); 841 } 842 843 static int 844 snd_harmony_mixer_init(struct snd_harmony *h) 845 { 846 struct snd_card *card; 847 int idx, err; 848 849 if (snd_BUG_ON(!h)) 850 return -EINVAL; 851 card = h->card; 852 strcpy(card->mixername, "Harmony Gain control interface"); 853 854 for (idx = 0; idx < HARMONY_CONTROLS; idx++) { 855 err = snd_ctl_add(card, 856 snd_ctl_new1(&snd_harmony_controls[idx], h)); 857 if (err < 0) 858 return err; 859 } 860 861 snd_harmony_mixer_reset(h); 862 863 return 0; 864 } 865 866 static int 867 snd_harmony_free(struct snd_harmony *h) 868 { 869 if (h->gdma.addr) 870 snd_dma_free_pages(&h->gdma); 871 if (h->sdma.addr) 872 snd_dma_free_pages(&h->sdma); 873 874 if (h->irq >= 0) 875 free_irq(h->irq, h); 876 877 iounmap(h->iobase); 878 kfree(h); 879 return 0; 880 } 881 882 static int 883 snd_harmony_dev_free(struct snd_device *dev) 884 { 885 struct snd_harmony *h = dev->device_data; 886 return snd_harmony_free(h); 887 } 888 889 static int 890 snd_harmony_create(struct snd_card *card, 891 struct parisc_device *padev, 892 struct snd_harmony **rchip) 893 { 894 int err; 895 struct snd_harmony *h; 896 static struct snd_device_ops ops = { 897 .dev_free = snd_harmony_dev_free, 898 }; 899 900 *rchip = NULL; 901 902 h = kzalloc(sizeof(*h), GFP_KERNEL); 903 if (h == NULL) 904 return -ENOMEM; 905 906 h->hpa = padev->hpa.start; 907 h->card = card; 908 h->dev = padev; 909 h->irq = -1; 910 h->iobase = ioremap_nocache(padev->hpa.start, HARMONY_SIZE); 911 if (h->iobase == NULL) { 912 printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n", 913 (unsigned long)padev->hpa.start); 914 err = -EBUSY; 915 goto free_and_ret; 916 } 917 918 err = request_irq(padev->irq, snd_harmony_interrupt, 0, 919 "harmony", h); 920 if (err) { 921 printk(KERN_ERR PFX "could not obtain interrupt %d", 922 padev->irq); 923 goto free_and_ret; 924 } 925 h->irq = padev->irq; 926 927 spin_lock_init(&h->mixer_lock); 928 spin_lock_init(&h->lock); 929 930 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, 931 h, &ops)) < 0) { 932 goto free_and_ret; 933 } 934 935 *rchip = h; 936 937 return 0; 938 939 free_and_ret: 940 snd_harmony_free(h); 941 return err; 942 } 943 944 static int __init 945 snd_harmony_probe(struct parisc_device *padev) 946 { 947 int err; 948 struct snd_card *card; 949 struct snd_harmony *h; 950 951 err = snd_card_new(&padev->dev, index, id, THIS_MODULE, 0, &card); 952 if (err < 0) 953 return err; 954 955 err = snd_harmony_create(card, padev, &h); 956 if (err < 0) 957 goto free_and_ret; 958 959 err = snd_harmony_pcm_init(h); 960 if (err < 0) 961 goto free_and_ret; 962 963 err = snd_harmony_mixer_init(h); 964 if (err < 0) 965 goto free_and_ret; 966 967 strcpy(card->driver, "harmony"); 968 strcpy(card->shortname, "Harmony"); 969 sprintf(card->longname, "%s at 0x%lx, irq %i", 970 card->shortname, h->hpa, h->irq); 971 972 err = snd_card_register(card); 973 if (err < 0) 974 goto free_and_ret; 975 976 parisc_set_drvdata(padev, card); 977 return 0; 978 979 free_and_ret: 980 snd_card_free(card); 981 return err; 982 } 983 984 static int __exit 985 snd_harmony_remove(struct parisc_device *padev) 986 { 987 snd_card_free(parisc_get_drvdata(padev)); 988 return 0; 989 } 990 991 static struct parisc_driver snd_harmony_driver __refdata = { 992 .name = "harmony", 993 .id_table = snd_harmony_devtable, 994 .probe = snd_harmony_probe, 995 .remove = __exit_p(snd_harmony_remove), 996 }; 997 998 static int __init 999 alsa_harmony_init(void) 1000 { 1001 return register_parisc_driver(&snd_harmony_driver); 1002 } 1003 1004 static void __exit 1005 alsa_harmony_fini(void) 1006 { 1007 unregister_parisc_driver(&snd_harmony_driver); 1008 } 1009 1010 MODULE_LICENSE("GPL"); 1011 MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>"); 1012 MODULE_DESCRIPTION("Harmony sound driver"); 1013 1014 module_init(alsa_harmony_init); 1015 module_exit(alsa_harmony_fini); 1016