harmony.c (24159B)
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 48static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ 49static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ 50module_param(index, int, 0444); 51MODULE_PARM_DESC(index, "Index value for Harmony driver."); 52module_param(id, charp, 0444); 53MODULE_PARM_DESC(id, "ID string for Harmony driver."); 54 55 56static 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 68MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable); 69 70#define NAME "harmony" 71#define PFX NAME ": " 72 73static 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 80static 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 88static 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 94static inline unsigned long 95harmony_read(struct snd_harmony *h, unsigned r) 96{ 97 return __raw_readl(h->iobase + r); 98} 99 100static inline void 101harmony_write(struct snd_harmony *h, unsigned r, unsigned long v) 102{ 103 __raw_writel(v, h->iobase + r); 104} 105 106static inline void 107harmony_wait_for_control(struct snd_harmony *h) 108{ 109 while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ; 110} 111 112static inline void 113harmony_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 120static void 121harmony_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 130static void 131harmony_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 140static void 141harmony_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 151static void 152harmony_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 162static void 163harmony_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 181static irqreturn_t 182snd_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 238static unsigned int 239snd_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 250static 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 271static 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 292static int 293snd_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 328static int 329snd_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 364static int 365snd_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 394static int 395snd_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 424static int 425snd_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 454static snd_pcm_uframes_t 455snd_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 483static snd_pcm_uframes_t 484snd_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 512static int 513snd_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 531static int 532snd_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 550static int 551snd_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 558static int 559snd_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 566static const struct snd_pcm_ops snd_harmony_playback_ops = { 567 .open = snd_harmony_playback_open, 568 .close = snd_harmony_playback_close, 569 .prepare = snd_harmony_playback_prepare, 570 .trigger = snd_harmony_playback_trigger, 571 .pointer = snd_harmony_playback_pointer, 572}; 573 574static const struct snd_pcm_ops snd_harmony_capture_ops = { 575 .open = snd_harmony_capture_open, 576 .close = snd_harmony_capture_close, 577 .prepare = snd_harmony_capture_prepare, 578 .trigger = snd_harmony_capture_trigger, 579 .pointer = snd_harmony_capture_pointer, 580}; 581 582static int 583snd_harmony_pcm_init(struct snd_harmony *h) 584{ 585 struct snd_pcm *pcm; 586 int err; 587 588 if (snd_BUG_ON(!h)) 589 return -EINVAL; 590 591 harmony_disable_interrupts(h); 592 593 err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm); 594 if (err < 0) 595 return err; 596 597 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 598 &snd_harmony_playback_ops); 599 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 600 &snd_harmony_capture_ops); 601 602 pcm->private_data = h; 603 pcm->info_flags = 0; 604 strcpy(pcm->name, "harmony"); 605 h->pcm = pcm; 606 607 h->psubs = NULL; 608 h->csubs = NULL; 609 610 /* initialize graveyard buffer */ 611 h->dma.type = SNDRV_DMA_TYPE_DEV; 612 h->dma.dev = &h->dev->dev; 613 err = snd_dma_alloc_pages(h->dma.type, 614 h->dma.dev, 615 BUF_SIZE*GRAVEYARD_BUFS, 616 &h->gdma); 617 if (err < 0) { 618 printk(KERN_ERR PFX "cannot allocate graveyard buffer!\n"); 619 return err; 620 } 621 622 /* initialize silence buffers */ 623 err = snd_dma_alloc_pages(h->dma.type, 624 h->dma.dev, 625 BUF_SIZE*SILENCE_BUFS, 626 &h->sdma); 627 if (err < 0) { 628 printk(KERN_ERR PFX "cannot allocate silence buffer!\n"); 629 return err; 630 } 631 632 /* pre-allocate space for DMA */ 633 snd_pcm_set_managed_buffer_all(pcm, h->dma.type, h->dma.dev, 634 MAX_BUF_SIZE, MAX_BUF_SIZE); 635 636 h->st.format = snd_harmony_set_data_format(h, 637 SNDRV_PCM_FORMAT_S16_BE, 1); 638 639 return 0; 640} 641 642static void 643snd_harmony_set_new_gain(struct snd_harmony *h) 644{ 645 harmony_wait_for_control(h); 646 harmony_write(h, HARMONY_GAINCTL, h->st.gain); 647} 648 649static int 650snd_harmony_mixercontrol_info(struct snd_kcontrol *kc, 651 struct snd_ctl_elem_info *uinfo) 652{ 653 int mask = (kc->private_value >> 16) & 0xff; 654 int left_shift = (kc->private_value) & 0xff; 655 int right_shift = (kc->private_value >> 8) & 0xff; 656 657 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : 658 SNDRV_CTL_ELEM_TYPE_INTEGER; 659 uinfo->count = left_shift == right_shift ? 1 : 2; 660 uinfo->value.integer.min = 0; 661 uinfo->value.integer.max = mask; 662 663 return 0; 664} 665 666static int 667snd_harmony_volume_get(struct snd_kcontrol *kc, 668 struct snd_ctl_elem_value *ucontrol) 669{ 670 struct snd_harmony *h = snd_kcontrol_chip(kc); 671 int shift_left = (kc->private_value) & 0xff; 672 int shift_right = (kc->private_value >> 8) & 0xff; 673 int mask = (kc->private_value >> 16) & 0xff; 674 int invert = (kc->private_value >> 24) & 0xff; 675 int left, right; 676 677 spin_lock_irq(&h->mixer_lock); 678 679 left = (h->st.gain >> shift_left) & mask; 680 right = (h->st.gain >> shift_right) & mask; 681 if (invert) { 682 left = mask - left; 683 right = mask - right; 684 } 685 686 ucontrol->value.integer.value[0] = left; 687 if (shift_left != shift_right) 688 ucontrol->value.integer.value[1] = right; 689 690 spin_unlock_irq(&h->mixer_lock); 691 692 return 0; 693} 694 695static int 696snd_harmony_volume_put(struct snd_kcontrol *kc, 697 struct snd_ctl_elem_value *ucontrol) 698{ 699 struct snd_harmony *h = snd_kcontrol_chip(kc); 700 int shift_left = (kc->private_value) & 0xff; 701 int shift_right = (kc->private_value >> 8) & 0xff; 702 int mask = (kc->private_value >> 16) & 0xff; 703 int invert = (kc->private_value >> 24) & 0xff; 704 int left, right; 705 int old_gain = h->st.gain; 706 707 spin_lock_irq(&h->mixer_lock); 708 709 left = ucontrol->value.integer.value[0] & mask; 710 if (invert) 711 left = mask - left; 712 h->st.gain &= ~( (mask << shift_left ) ); 713 h->st.gain |= (left << shift_left); 714 715 if (shift_left != shift_right) { 716 right = ucontrol->value.integer.value[1] & mask; 717 if (invert) 718 right = mask - right; 719 h->st.gain &= ~( (mask << shift_right) ); 720 h->st.gain |= (right << shift_right); 721 } 722 723 snd_harmony_set_new_gain(h); 724 725 spin_unlock_irq(&h->mixer_lock); 726 727 return h->st.gain != old_gain; 728} 729 730static int 731snd_harmony_captureroute_info(struct snd_kcontrol *kc, 732 struct snd_ctl_elem_info *uinfo) 733{ 734 static const char * const texts[2] = { "Line", "Mic" }; 735 736 return snd_ctl_enum_info(uinfo, 1, 2, texts); 737} 738 739static int 740snd_harmony_captureroute_get(struct snd_kcontrol *kc, 741 struct snd_ctl_elem_value *ucontrol) 742{ 743 struct snd_harmony *h = snd_kcontrol_chip(kc); 744 int value; 745 746 spin_lock_irq(&h->mixer_lock); 747 748 value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1; 749 ucontrol->value.enumerated.item[0] = value; 750 751 spin_unlock_irq(&h->mixer_lock); 752 753 return 0; 754} 755 756static int 757snd_harmony_captureroute_put(struct snd_kcontrol *kc, 758 struct snd_ctl_elem_value *ucontrol) 759{ 760 struct snd_harmony *h = snd_kcontrol_chip(kc); 761 int value; 762 int old_gain = h->st.gain; 763 764 spin_lock_irq(&h->mixer_lock); 765 766 value = ucontrol->value.enumerated.item[0] & 1; 767 h->st.gain &= ~HARMONY_GAIN_IS_MASK; 768 h->st.gain |= value << HARMONY_GAIN_IS_SHIFT; 769 770 snd_harmony_set_new_gain(h); 771 772 spin_unlock_irq(&h->mixer_lock); 773 774 return h->st.gain != old_gain; 775} 776 777#define HARMONY_CONTROLS ARRAY_SIZE(snd_harmony_controls) 778 779#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \ 780{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 781 .info = snd_harmony_mixercontrol_info, \ 782 .get = snd_harmony_volume_get, .put = snd_harmony_volume_put, \ 783 .private_value = ((left_shift) | ((right_shift) << 8) | \ 784 ((mask) << 16) | ((invert) << 24)) } 785 786static const struct snd_kcontrol_new snd_harmony_controls[] = { 787 HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT, 788 HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1), 789 HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT, 790 HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0), 791 HARMONY_VOLUME("Monitor Volume", HARMONY_GAIN_MA_SHIFT, 792 HARMONY_GAIN_MA_SHIFT, HARMONY_GAIN_MA, 1), 793 { 794 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 795 .name = "Input Route", 796 .info = snd_harmony_captureroute_info, 797 .get = snd_harmony_captureroute_get, 798 .put = snd_harmony_captureroute_put 799 }, 800 HARMONY_VOLUME("Internal Speaker Switch", HARMONY_GAIN_SE_SHIFT, 801 HARMONY_GAIN_SE_SHIFT, 1, 0), 802 HARMONY_VOLUME("Line-Out Switch", HARMONY_GAIN_LE_SHIFT, 803 HARMONY_GAIN_LE_SHIFT, 1, 0), 804 HARMONY_VOLUME("Headphones Switch", HARMONY_GAIN_HE_SHIFT, 805 HARMONY_GAIN_HE_SHIFT, 1, 0), 806}; 807 808static void 809snd_harmony_mixer_reset(struct snd_harmony *h) 810{ 811 harmony_mute(h); 812 harmony_reset(h); 813 h->st.gain = HARMONY_GAIN_DEFAULT; 814 harmony_unmute(h); 815} 816 817static int 818snd_harmony_mixer_init(struct snd_harmony *h) 819{ 820 struct snd_card *card; 821 int idx, err; 822 823 if (snd_BUG_ON(!h)) 824 return -EINVAL; 825 card = h->card; 826 strcpy(card->mixername, "Harmony Gain control interface"); 827 828 for (idx = 0; idx < HARMONY_CONTROLS; idx++) { 829 err = snd_ctl_add(card, 830 snd_ctl_new1(&snd_harmony_controls[idx], h)); 831 if (err < 0) 832 return err; 833 } 834 835 snd_harmony_mixer_reset(h); 836 837 return 0; 838} 839 840static int 841snd_harmony_free(struct snd_harmony *h) 842{ 843 if (h->gdma.addr) 844 snd_dma_free_pages(&h->gdma); 845 if (h->sdma.addr) 846 snd_dma_free_pages(&h->sdma); 847 848 if (h->irq >= 0) 849 free_irq(h->irq, h); 850 851 iounmap(h->iobase); 852 kfree(h); 853 return 0; 854} 855 856static int 857snd_harmony_dev_free(struct snd_device *dev) 858{ 859 struct snd_harmony *h = dev->device_data; 860 return snd_harmony_free(h); 861} 862 863static int 864snd_harmony_create(struct snd_card *card, 865 struct parisc_device *padev, 866 struct snd_harmony **rchip) 867{ 868 int err; 869 struct snd_harmony *h; 870 static const struct snd_device_ops ops = { 871 .dev_free = snd_harmony_dev_free, 872 }; 873 874 *rchip = NULL; 875 876 h = kzalloc(sizeof(*h), GFP_KERNEL); 877 if (h == NULL) 878 return -ENOMEM; 879 880 h->hpa = padev->hpa.start; 881 h->card = card; 882 h->dev = padev; 883 h->irq = -1; 884 h->iobase = ioremap(padev->hpa.start, HARMONY_SIZE); 885 if (h->iobase == NULL) { 886 printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n", 887 (unsigned long)padev->hpa.start); 888 err = -EBUSY; 889 goto free_and_ret; 890 } 891 892 err = request_irq(padev->irq, snd_harmony_interrupt, 0, 893 "harmony", h); 894 if (err) { 895 printk(KERN_ERR PFX "could not obtain interrupt %d", 896 padev->irq); 897 goto free_and_ret; 898 } 899 h->irq = padev->irq; 900 901 spin_lock_init(&h->mixer_lock); 902 spin_lock_init(&h->lock); 903 904 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, h, &ops); 905 if (err < 0) 906 goto free_and_ret; 907 908 *rchip = h; 909 910 return 0; 911 912free_and_ret: 913 snd_harmony_free(h); 914 return err; 915} 916 917static int __init 918snd_harmony_probe(struct parisc_device *padev) 919{ 920 int err; 921 struct snd_card *card; 922 struct snd_harmony *h; 923 924 err = snd_card_new(&padev->dev, index, id, THIS_MODULE, 0, &card); 925 if (err < 0) 926 return err; 927 928 err = snd_harmony_create(card, padev, &h); 929 if (err < 0) 930 goto free_and_ret; 931 932 err = snd_harmony_pcm_init(h); 933 if (err < 0) 934 goto free_and_ret; 935 936 err = snd_harmony_mixer_init(h); 937 if (err < 0) 938 goto free_and_ret; 939 940 strcpy(card->driver, "harmony"); 941 strcpy(card->shortname, "Harmony"); 942 sprintf(card->longname, "%s at 0x%lx, irq %i", 943 card->shortname, h->hpa, h->irq); 944 945 err = snd_card_register(card); 946 if (err < 0) 947 goto free_and_ret; 948 949 parisc_set_drvdata(padev, card); 950 return 0; 951 952free_and_ret: 953 snd_card_free(card); 954 return err; 955} 956 957static void __exit 958snd_harmony_remove(struct parisc_device *padev) 959{ 960 snd_card_free(parisc_get_drvdata(padev)); 961} 962 963static struct parisc_driver snd_harmony_driver __refdata = { 964 .name = "harmony", 965 .id_table = snd_harmony_devtable, 966 .probe = snd_harmony_probe, 967 .remove = __exit_p(snd_harmony_remove), 968}; 969 970static int __init 971alsa_harmony_init(void) 972{ 973 return register_parisc_driver(&snd_harmony_driver); 974} 975 976static void __exit 977alsa_harmony_fini(void) 978{ 979 unregister_parisc_driver(&snd_harmony_driver); 980} 981 982MODULE_LICENSE("GPL"); 983MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>"); 984MODULE_DESCRIPTION("Harmony sound driver"); 985 986module_init(alsa_harmony_init); 987module_exit(alsa_harmony_fini);