Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17 1330 lines 35 kB view raw
1/* 2 drivers/sound/harmony.c 3 4 This is a sound driver for ASP's and Lasi's Harmony sound chip 5 and is unlikely to be used for anything other than on a HP PA-RISC. 6 7 Harmony is found in HP 712s, 715/new and many other GSC based machines. 8 On older 715 machines you'll find the technically identical chip 9 called 'Vivace'. Both Harmony and Vicace are supported by this driver. 10 11 Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@onefishtwo.ca> 12 Copyright 2000-2003 (c) Helge Deller <deller@gmx.de> 13 Copyright 2001 (c) Matthieu Delahaye <delahaym@esiee.fr> 14 Copyright 2001 (c) Jean-Christophe Vaugeois <vaugeoij@esiee.fr> 15 Copyright 2004 (c) Stuart Brady <sdbrady@ntlworld.com> 16 17 18TODO: 19 - fix SNDCTL_DSP_GETOSPACE and SNDCTL_DSP_GETISPACE ioctls to 20 return the real values 21 - add private ioctl for selecting line- or microphone input 22 (only one of them is available at the same time) 23 - add module parameters 24 - implement mmap functionality 25 - implement gain meter ? 26 - ... 27*/ 28 29#include <linux/delay.h> 30#include <linux/errno.h> 31#include <linux/init.h> 32#include <linux/interrupt.h> 33#include <linux/ioport.h> 34#include <linux/types.h> 35#include <linux/mm.h> 36#include <linux/pci.h> 37 38#include <asm/parisc-device.h> 39#include <asm/io.h> 40 41#include "sound_config.h" 42 43 44#define PFX "harmony: " 45#define HARMONY_VERSION "V0.9a" 46 47#undef DEBUG 48#ifdef DEBUG 49# define DPRINTK printk 50#else 51# define DPRINTK(x,...) 52#endif 53 54 55#define MAX_BUFS 10 /* maximum number of rotating buffers */ 56#define HARMONY_BUF_SIZE 4096 /* needs to be a multiple of PAGE_SIZE (4096)! */ 57 58#define CNTL_C 0x80000000 59#define CNTL_ST 0x00000020 60#define CNTL_44100 0x00000015 /* HARMONY_SR_44KHZ */ 61#define CNTL_8000 0x00000008 /* HARMONY_SR_8KHZ */ 62 63#define GAINCTL_HE 0x08000000 64#define GAINCTL_LE 0x04000000 65#define GAINCTL_SE 0x02000000 66 67#define DSTATUS_PN 0x00000200 68#define DSTATUS_RN 0x00000002 69 70#define DSTATUS_IE 0x80000000 71 72#define HARMONY_DF_16BIT_LINEAR 0 73#define HARMONY_DF_8BIT_ULAW 1 74#define HARMONY_DF_8BIT_ALAW 2 75 76#define HARMONY_SS_MONO 0 77#define HARMONY_SS_STEREO 1 78 79#define HARMONY_SR_8KHZ 0x08 80#define HARMONY_SR_16KHZ 0x09 81#define HARMONY_SR_27KHZ 0x0A 82#define HARMONY_SR_32KHZ 0x0B 83#define HARMONY_SR_48KHZ 0x0E 84#define HARMONY_SR_9KHZ 0x0F 85#define HARMONY_SR_5KHZ 0x10 86#define HARMONY_SR_11KHZ 0x11 87#define HARMONY_SR_18KHZ 0x12 88#define HARMONY_SR_22KHZ 0x13 89#define HARMONY_SR_37KHZ 0x14 90#define HARMONY_SR_44KHZ 0x15 91#define HARMONY_SR_33KHZ 0x16 92#define HARMONY_SR_6KHZ 0x17 93 94/* 95 * Some magics numbers used to auto-detect file formats 96 */ 97 98#define HARMONY_MAGIC_8B_ULAW 1 99#define HARMONY_MAGIC_8B_ALAW 27 100#define HARMONY_MAGIC_16B_LINEAR 3 101#define HARMONY_MAGIC_MONO 1 102#define HARMONY_MAGIC_STEREO 2 103 104/* 105 * Channels Positions in mixer register 106 */ 107 108#define GAIN_HE_SHIFT 27 109#define GAIN_HE_MASK ( 1 << GAIN_HE_SHIFT) 110#define GAIN_LE_SHIFT 26 111#define GAIN_LE_MASK ( 1 << GAIN_LE_SHIFT) 112#define GAIN_SE_SHIFT 25 113#define GAIN_SE_MASK ( 1 << GAIN_SE_SHIFT) 114#define GAIN_IS_SHIFT 24 115#define GAIN_IS_MASK ( 1 << GAIN_IS_SHIFT) 116#define GAIN_MA_SHIFT 20 117#define GAIN_MA_MASK ( 0x0f << GAIN_MA_SHIFT) 118#define GAIN_LI_SHIFT 16 119#define GAIN_LI_MASK ( 0x0f << GAIN_LI_SHIFT) 120#define GAIN_RI_SHIFT 12 121#define GAIN_RI_MASK ( 0x0f << GAIN_RI_SHIFT) 122#define GAIN_LO_SHIFT 6 123#define GAIN_LO_MASK ( 0x3f << GAIN_LO_SHIFT) 124#define GAIN_RO_SHIFT 0 125#define GAIN_RO_MASK ( 0x3f << GAIN_RO_SHIFT) 126 127 128#define MAX_OUTPUT_LEVEL (GAIN_RO_MASK >> GAIN_RO_SHIFT) 129#define MAX_INPUT_LEVEL (GAIN_RI_MASK >> GAIN_RI_SHIFT) 130#define MAX_MONITOR_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT) 131 132#define MIXER_INTERNAL SOUND_MIXER_LINE1 133#define MIXER_LINEOUT SOUND_MIXER_LINE2 134#define MIXER_HEADPHONES SOUND_MIXER_LINE3 135 136#define MASK_INTERNAL SOUND_MASK_LINE1 137#define MASK_LINEOUT SOUND_MASK_LINE2 138#define MASK_HEADPHONES SOUND_MASK_LINE3 139 140/* 141 * Channels Mask in mixer register 142 */ 143 144#define GAIN_TOTAL_SILENCE 0x00F00FFF 145#define GAIN_DEFAULT 0x0FF00000 146 147 148struct harmony_hpa { 149 u8 unused000; 150 u8 id; 151 u8 teleshare_id; 152 u8 unused003; 153 u32 reset; 154 u32 cntl; 155 u32 gainctl; 156 u32 pnxtadd; 157 u32 pcuradd; 158 u32 rnxtadd; 159 u32 rcuradd; 160 u32 dstatus; 161 u32 ov; 162 u32 pio; 163 u32 unused02c; 164 u32 unused030[3]; 165 u32 diag; 166}; 167 168struct harmony_dev { 169 struct harmony_hpa *hpa; 170 struct parisc_device *dev; 171 u32 current_gain; 172 u32 dac_rate; /* 8000 ... 48000 (Hz) */ 173 u8 data_format; /* HARMONY_DF_xx_BIT_xxx */ 174 u8 sample_rate; /* HARMONY_SR_xx_KHZ */ 175 u8 stereo_select; /* HARMONY_SS_MONO or HARMONY_SS_STEREO */ 176 int format_initialized :1; 177 int suspended_playing :1; 178 int suspended_recording :1; 179 180 int blocked_playing :1; 181 int blocked_recording :1; 182 int audio_open :1; 183 int mixer_open :1; 184 185 wait_queue_head_t wq_play, wq_record; 186 int first_filled_play; /* first buffer containing data (next to play) */ 187 int nb_filled_play; 188 int play_offset; 189 int first_filled_record; 190 int nb_filled_record; 191 192 int dsp_unit, mixer_unit; 193}; 194 195 196static struct harmony_dev harmony; 197 198 199/* 200 * Dynamic sound buffer allocation and DMA memory 201 */ 202 203struct harmony_buffer { 204 unsigned char *addr; 205 dma_addr_t dma_handle; 206 int dma_coherent; /* Zero if dma_alloc_coherent() fails */ 207 unsigned int len; 208}; 209 210/* 211 * Harmony memory buffers 212 */ 213 214static struct harmony_buffer played_buf, recorded_buf, silent, graveyard; 215 216 217#define CHECK_WBACK_INV_OFFSET(b,offset,len) \ 218 do { if (!b.dma_coherent) \ 219 dma_cache_wback_inv((unsigned long)b.addr+offset,len); \ 220 } while (0) 221 222 223static int __init harmony_alloc_buffer(struct harmony_buffer *b, 224 unsigned int buffer_count) 225{ 226 b->len = buffer_count * HARMONY_BUF_SIZE; 227 b->addr = dma_alloc_coherent(&harmony.dev->dev, 228 b->len, &b->dma_handle, GFP_KERNEL|GFP_DMA); 229 if (b->addr && b->dma_handle) { 230 b->dma_coherent = 1; 231 DPRINTK(KERN_INFO PFX "coherent memory: 0x%lx, played_buf: 0x%lx\n", 232 (unsigned long)b->dma_handle, (unsigned long)b->addr); 233 } else { 234 b->dma_coherent = 0; 235 /* kmalloc()ed memory will HPMC on ccio machines ! */ 236 b->addr = kmalloc(b->len, GFP_KERNEL); 237 if (!b->addr) { 238 printk(KERN_ERR PFX "couldn't allocate memory\n"); 239 return -EBUSY; 240 } 241 b->dma_handle = __pa(b->addr); 242 } 243 return 0; 244} 245 246static void __exit harmony_free_buffer(struct harmony_buffer *b) 247{ 248 if (!b->addr) 249 return; 250 251 if (b->dma_coherent) 252 dma_free_coherent(&harmony.dev->dev, 253 b->len, b->addr, b->dma_handle); 254 else 255 kfree(b->addr); 256 257 memset(b, 0, sizeof(*b)); 258} 259 260 261 262/* 263 * Low-Level sound-chip programming 264 */ 265 266static void __inline__ harmony_wait_CNTL(void) 267{ 268 /* Wait until we're out of control mode */ 269 while (gsc_readl(&harmony.hpa->cntl) & CNTL_C) 270 /* wait */ ; 271} 272 273 274static void harmony_update_control(void) 275{ 276 u32 default_cntl; 277 278 /* Set CNTL */ 279 default_cntl = (CNTL_C | /* The C bit */ 280 (harmony.data_format << 6) | /* Set the data format */ 281 (harmony.stereo_select << 5) | /* Stereo select */ 282 (harmony.sample_rate)); /* Set sample rate */ 283 harmony.format_initialized = 1; 284 285 /* initialize CNTL */ 286 gsc_writel(default_cntl, &harmony.hpa->cntl); 287} 288 289static void harmony_set_control(u8 data_format, u8 sample_rate, u8 stereo_select) 290{ 291 harmony.sample_rate = sample_rate; 292 harmony.data_format = data_format; 293 harmony.stereo_select = stereo_select; 294 harmony_update_control(); 295} 296 297static void harmony_set_rate(u8 data_rate) 298{ 299 harmony.sample_rate = data_rate; 300 harmony_update_control(); 301} 302 303static int harmony_detect_rate(int *freq) 304{ 305 int newrate; 306 switch (*freq) { 307 case 8000: newrate = HARMONY_SR_8KHZ; break; 308 case 16000: newrate = HARMONY_SR_16KHZ; break; 309 case 27428: newrate = HARMONY_SR_27KHZ; break; 310 case 32000: newrate = HARMONY_SR_32KHZ; break; 311 case 48000: newrate = HARMONY_SR_48KHZ; break; 312 case 9600: newrate = HARMONY_SR_9KHZ; break; 313 case 5512: newrate = HARMONY_SR_5KHZ; break; 314 case 11025: newrate = HARMONY_SR_11KHZ; break; 315 case 18900: newrate = HARMONY_SR_18KHZ; break; 316 case 22050: newrate = HARMONY_SR_22KHZ; break; 317 case 37800: newrate = HARMONY_SR_37KHZ; break; 318 case 44100: newrate = HARMONY_SR_44KHZ; break; 319 case 33075: newrate = HARMONY_SR_33KHZ; break; 320 case 6615: newrate = HARMONY_SR_6KHZ; break; 321 default: newrate = HARMONY_SR_8KHZ; 322 *freq = 8000; break; 323 } 324 return newrate; 325} 326 327static void harmony_set_format(u8 data_format) 328{ 329 harmony.data_format = data_format; 330 harmony_update_control(); 331} 332 333static void harmony_set_stereo(u8 stereo_select) 334{ 335 harmony.stereo_select = stereo_select; 336 harmony_update_control(); 337} 338 339static void harmony_disable_interrupts(void) 340{ 341 harmony_wait_CNTL(); 342 gsc_writel(0, &harmony.hpa->dstatus); 343} 344 345static void harmony_enable_interrupts(void) 346{ 347 harmony_wait_CNTL(); 348 gsc_writel(DSTATUS_IE, &harmony.hpa->dstatus); 349} 350 351/* 352 * harmony_silence() 353 * 354 * This subroutine fills in a buffer starting at location start and 355 * silences for length bytes. This references the current 356 * configuration of the audio format. 357 * 358 */ 359 360static void harmony_silence(struct harmony_buffer *buffer, int start, int length) 361{ 362 u8 silence_char; 363 364 /* Despite what you hear, silence is different in 365 different audio formats. */ 366 switch (harmony.data_format) { 367 case HARMONY_DF_8BIT_ULAW: silence_char = 0x55; break; 368 case HARMONY_DF_8BIT_ALAW: silence_char = 0xff; break; 369 case HARMONY_DF_16BIT_LINEAR: /* fall through */ 370 default: silence_char = 0; 371 } 372 373 memset(buffer->addr+start, silence_char, length); 374} 375 376 377static int harmony_audio_open(struct inode *inode, struct file *file) 378{ 379 if (harmony.audio_open) 380 return -EBUSY; 381 382 harmony.audio_open = 1; 383 harmony.suspended_playing = harmony.suspended_recording = 1; 384 harmony.blocked_playing = harmony.blocked_recording = 0; 385 harmony.first_filled_play = harmony.first_filled_record = 0; 386 harmony.nb_filled_play = harmony.nb_filled_record = 0; 387 harmony.play_offset = 0; 388 init_waitqueue_head(&harmony.wq_play); 389 init_waitqueue_head(&harmony.wq_record); 390 391 /* Start off in a balanced mode. */ 392 harmony_set_control(HARMONY_DF_8BIT_ULAW, HARMONY_SR_8KHZ, HARMONY_SS_MONO); 393 harmony_update_control(); 394 harmony.format_initialized = 0; 395 396 /* Clear out all the buffers and flush to cache */ 397 harmony_silence(&played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS); 398 CHECK_WBACK_INV_OFFSET(played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS); 399 400 return 0; 401} 402 403/* 404 * Release (close) the audio device. 405 */ 406 407static int harmony_audio_release(struct inode *inode, struct file *file) 408{ 409 if (!harmony.audio_open) 410 return -EBUSY; 411 412 harmony.audio_open = 0; 413 414 return 0; 415} 416 417/* 418 * Read recorded data off the audio device. 419 */ 420 421static ssize_t harmony_audio_read(struct file *file, 422 char *buffer, 423 size_t size_count, 424 loff_t *ppos) 425{ 426 int total_count = (int) size_count; 427 int count = 0; 428 int buf_to_read; 429 430 while (count<total_count) { 431 /* Wait until we're out of control mode */ 432 harmony_wait_CNTL(); 433 434 /* Figure out which buffer to fill in */ 435 if (harmony.nb_filled_record <= 2) { 436 harmony.blocked_recording = 1; 437 if (harmony.suspended_recording) { 438 harmony.suspended_recording = 0; 439 harmony_enable_interrupts(); 440 } 441 442 interruptible_sleep_on(&harmony.wq_record); 443 harmony.blocked_recording = 0; 444 } 445 446 if (harmony.nb_filled_record < 2) 447 return -EBUSY; 448 449 buf_to_read = harmony.first_filled_record; 450 451 /* Copy the page to an aligned buffer */ 452 if (copy_to_user(buffer+count, recorded_buf.addr + 453 (HARMONY_BUF_SIZE*buf_to_read), 454 HARMONY_BUF_SIZE)) { 455 count = -EFAULT; 456 break; 457 } 458 459 harmony.nb_filled_record--; 460 harmony.first_filled_record++; 461 harmony.first_filled_record %= MAX_BUFS; 462 463 count += HARMONY_BUF_SIZE; 464 } 465 return count; 466} 467 468 469 470 471/* 472 * Here is the place where we try to recognize file format. 473 * Sun/NeXT .au files begin with the string .snd 474 * At offset 12 is specified the encoding. 475 * At offset 16 is specified speed rate 476 * At Offset 20 is specified the numbers of voices 477 */ 478 479#define four_bytes_to_u32(start) (file_header[start] << 24)|\ 480 (file_header[start+1] << 16)|\ 481 (file_header[start+2] << 8)|\ 482 (file_header[start+3]); 483 484#define test_rate(tested,real_value,harmony_value) if ((tested)<=(real_value))\ 485 486 487static int harmony_format_auto_detect(const char *buffer, int block_size) 488{ 489 u8 file_header[24]; 490 u32 start_string; 491 int ret = 0; 492 493 if (block_size>24) { 494 if (copy_from_user(file_header, buffer, sizeof(file_header))) 495 ret = -EFAULT; 496 497 start_string = four_bytes_to_u32(0); 498 499 if ((file_header[4]==0) && (start_string==0x2E736E64)) { 500 u32 format; 501 u32 nb_voices; 502 u32 speed; 503 504 format = four_bytes_to_u32(12); 505 nb_voices = four_bytes_to_u32(20); 506 speed = four_bytes_to_u32(16); 507 508 switch (format) { 509 case HARMONY_MAGIC_8B_ULAW: 510 harmony.data_format = HARMONY_DF_8BIT_ULAW; 511 break; 512 case HARMONY_MAGIC_8B_ALAW: 513 harmony.data_format = HARMONY_DF_8BIT_ALAW; 514 break; 515 case HARMONY_MAGIC_16B_LINEAR: 516 harmony.data_format = HARMONY_DF_16BIT_LINEAR; 517 break; 518 default: 519 harmony_set_control(HARMONY_DF_16BIT_LINEAR, 520 HARMONY_SR_44KHZ, HARMONY_SS_STEREO); 521 goto out; 522 } 523 switch (nb_voices) { 524 case HARMONY_MAGIC_MONO: 525 harmony.stereo_select = HARMONY_SS_MONO; 526 break; 527 case HARMONY_MAGIC_STEREO: 528 harmony.stereo_select = HARMONY_SS_STEREO; 529 break; 530 default: 531 harmony.stereo_select = HARMONY_SS_MONO; 532 break; 533 } 534 harmony_set_rate(harmony_detect_rate(&speed)); 535 harmony.dac_rate = speed; 536 goto out; 537 } 538 } 539 harmony_set_control(HARMONY_DF_8BIT_ULAW, HARMONY_SR_8KHZ, HARMONY_SS_MONO); 540out: 541 return ret; 542} 543#undef four_bytes_to_u32 544 545 546static ssize_t harmony_audio_write(struct file *file, 547 const char *buffer, 548 size_t size_count, 549 loff_t *ppos) 550{ 551 int total_count = (int) size_count; 552 int count = 0; 553 int frame_size; 554 int buf_to_fill; 555 int fresh_buffer; 556 557 if (!harmony.format_initialized) { 558 if (harmony_format_auto_detect(buffer, total_count)) 559 return -EFAULT; 560 } 561 562 while (count<total_count) { 563 /* Wait until we're out of control mode */ 564 harmony_wait_CNTL(); 565 566 /* Figure out which buffer to fill in */ 567 if (harmony.nb_filled_play+2 >= MAX_BUFS && !harmony.play_offset) { 568 harmony.blocked_playing = 1; 569 interruptible_sleep_on(&harmony.wq_play); 570 harmony.blocked_playing = 0; 571 } 572 if (harmony.nb_filled_play+2 >= MAX_BUFS && !harmony.play_offset) 573 return -EBUSY; 574 575 576 buf_to_fill = (harmony.first_filled_play+harmony.nb_filled_play); 577 if (harmony.play_offset) { 578 buf_to_fill--; 579 buf_to_fill += MAX_BUFS; 580 } 581 buf_to_fill %= MAX_BUFS; 582 583 fresh_buffer = (harmony.play_offset == 0); 584 585 /* Figure out the size of the frame */ 586 if ((total_count-count) >= HARMONY_BUF_SIZE - harmony.play_offset) { 587 frame_size = HARMONY_BUF_SIZE - harmony.play_offset; 588 } else { 589 frame_size = total_count - count; 590 /* Clear out the buffer, since there we'll only be 591 overlaying part of the old buffer with the new one */ 592 harmony_silence(&played_buf, 593 HARMONY_BUF_SIZE*buf_to_fill+frame_size+harmony.play_offset, 594 HARMONY_BUF_SIZE-frame_size-harmony.play_offset); 595 } 596 597 /* Copy the page to an aligned buffer */ 598 if (copy_from_user(played_buf.addr +(HARMONY_BUF_SIZE*buf_to_fill) + harmony.play_offset, 599 buffer+count, frame_size)) 600 return -EFAULT; 601 CHECK_WBACK_INV_OFFSET(played_buf, (HARMONY_BUF_SIZE*buf_to_fill + harmony.play_offset), 602 frame_size); 603 604 if (fresh_buffer) 605 harmony.nb_filled_play++; 606 607 count += frame_size; 608 harmony.play_offset += frame_size; 609 harmony.play_offset %= HARMONY_BUF_SIZE; 610 if (harmony.suspended_playing && (harmony.nb_filled_play>=4)) 611 harmony_enable_interrupts(); 612 } 613 614 return count; 615} 616 617static unsigned int harmony_audio_poll(struct file *file, 618 struct poll_table_struct *wait) 619{ 620 unsigned int mask = 0; 621 622 if (file->f_mode & FMODE_READ) { 623 if (!harmony.suspended_recording) 624 poll_wait(file, &harmony.wq_record, wait); 625 if (harmony.nb_filled_record) 626 mask |= POLLIN | POLLRDNORM; 627 } 628 629 if (file->f_mode & FMODE_WRITE) { 630 if (!harmony.suspended_playing) 631 poll_wait(file, &harmony.wq_play, wait); 632 if (harmony.nb_filled_play) 633 mask |= POLLOUT | POLLWRNORM; 634 } 635 636 return mask; 637} 638 639static int harmony_audio_ioctl(struct inode *inode, 640 struct file *file, 641 unsigned int cmd, 642 unsigned long arg) 643{ 644 int ival, new_format; 645 int frag_size, frag_buf; 646 struct audio_buf_info info; 647 648 switch (cmd) { 649 case OSS_GETVERSION: 650 return put_user(SOUND_VERSION, (int *) arg); 651 652 case SNDCTL_DSP_GETCAPS: 653 ival = DSP_CAP_DUPLEX; 654 return put_user(ival, (int *) arg); 655 656 case SNDCTL_DSP_GETFMTS: 657 ival = (AFMT_S16_BE | AFMT_MU_LAW | AFMT_A_LAW ); 658 return put_user(ival, (int *) arg); 659 660 case SNDCTL_DSP_SETFMT: 661 if (get_user(ival, (int *) arg)) 662 return -EFAULT; 663 if (ival != AFMT_QUERY) { 664 switch (ival) { 665 case AFMT_MU_LAW: new_format = HARMONY_DF_8BIT_ULAW; break; 666 case AFMT_A_LAW: new_format = HARMONY_DF_8BIT_ALAW; break; 667 case AFMT_S16_BE: new_format = HARMONY_DF_16BIT_LINEAR; break; 668 default: { 669 DPRINTK(KERN_WARNING PFX 670 "unsupported sound format 0x%04x requested.\n", 671 ival); 672 ival = AFMT_S16_BE; 673 return put_user(ival, (int *) arg); 674 } 675 } 676 harmony_set_format(new_format); 677 return 0; 678 } else { 679 switch (harmony.data_format) { 680 case HARMONY_DF_8BIT_ULAW: ival = AFMT_MU_LAW; break; 681 case HARMONY_DF_8BIT_ALAW: ival = AFMT_A_LAW; break; 682 case HARMONY_DF_16BIT_LINEAR: ival = AFMT_U16_BE; break; 683 default: ival = 0; 684 } 685 return put_user(ival, (int *) arg); 686 } 687 688 case SOUND_PCM_READ_RATE: 689 ival = harmony.dac_rate; 690 return put_user(ival, (int *) arg); 691 692 case SNDCTL_DSP_SPEED: 693 if (get_user(ival, (int *) arg)) 694 return -EFAULT; 695 harmony_set_rate(harmony_detect_rate(&ival)); 696 harmony.dac_rate = ival; 697 return put_user(ival, (int*) arg); 698 699 case SNDCTL_DSP_STEREO: 700 if (get_user(ival, (int *) arg)) 701 return -EFAULT; 702 if (ival != 0 && ival != 1) 703 return -EINVAL; 704 harmony_set_stereo(ival); 705 return 0; 706 707 case SNDCTL_DSP_CHANNELS: 708 if (get_user(ival, (int *) arg)) 709 return -EFAULT; 710 if (ival != 1 && ival != 2) { 711 ival = harmony.stereo_select == HARMONY_SS_MONO ? 1 : 2; 712 return put_user(ival, (int *) arg); 713 } 714 harmony_set_stereo(ival-1); 715 return 0; 716 717 case SNDCTL_DSP_GETBLKSIZE: 718 ival = HARMONY_BUF_SIZE; 719 return put_user(ival, (int *) arg); 720 721 case SNDCTL_DSP_NONBLOCK: 722 file->f_flags |= O_NONBLOCK; 723 return 0; 724 725 case SNDCTL_DSP_RESET: 726 if (!harmony.suspended_recording) { 727 /* TODO: stop_recording() */ 728 } 729 return 0; 730 731 case SNDCTL_DSP_SETFRAGMENT: 732 if (get_user(ival, (int *)arg)) 733 return -EFAULT; 734 frag_size = ival & 0xffff; 735 frag_buf = (ival>>16) & 0xffff; 736 /* TODO: We use hardcoded fragment sizes and numbers for now */ 737 frag_size = 12; /* 4096 == 2^12 */ 738 frag_buf = MAX_BUFS; 739 ival = (frag_buf << 16) + frag_size; 740 return put_user(ival, (int *) arg); 741 742 case SNDCTL_DSP_GETOSPACE: 743 if (!(file->f_mode & FMODE_WRITE)) 744 return -EINVAL; 745 info.fragstotal = MAX_BUFS; 746 info.fragments = MAX_BUFS - harmony.nb_filled_play; 747 info.fragsize = HARMONY_BUF_SIZE; 748 info.bytes = info.fragments * info.fragsize; 749 return copy_to_user((void *)arg, &info, sizeof(info)) ? -EFAULT : 0; 750 751 case SNDCTL_DSP_GETISPACE: 752 if (!(file->f_mode & FMODE_READ)) 753 return -EINVAL; 754 info.fragstotal = MAX_BUFS; 755 info.fragments = /*MAX_BUFS-*/ harmony.nb_filled_record; 756 info.fragsize = HARMONY_BUF_SIZE; 757 info.bytes = info.fragments * info.fragsize; 758 return copy_to_user((void *)arg, &info, sizeof(info)) ? -EFAULT : 0; 759 760 case SNDCTL_DSP_SYNC: 761 return 0; 762 } 763 764 return -EINVAL; 765} 766 767 768/* 769 * harmony_interrupt() 770 * 771 * harmony interruption service routine 772 * 773 */ 774 775static irqreturn_t harmony_interrupt(int irq, void *dev, struct pt_regs *regs) 776{ 777 u32 dstatus; 778 struct harmony_hpa *hpa; 779 780 /* Setup the hpa */ 781 hpa = ((struct harmony_dev *)dev)->hpa; 782 harmony_wait_CNTL(); 783 784 /* Read dstatus and pcuradd (the current address) */ 785 dstatus = gsc_readl(&hpa->dstatus); 786 787 /* Turn off interrupts */ 788 harmony_disable_interrupts(); 789 790 /* Check if this is a request to get the next play buffer */ 791 if (dstatus & DSTATUS_PN) { 792 if (!harmony.nb_filled_play) { 793 harmony.suspended_playing = 1; 794 gsc_writel((unsigned long)silent.dma_handle, &hpa->pnxtadd); 795 796 if (!harmony.suspended_recording) 797 harmony_enable_interrupts(); 798 } else { 799 harmony.suspended_playing = 0; 800 gsc_writel((unsigned long)played_buf.dma_handle + 801 (HARMONY_BUF_SIZE*harmony.first_filled_play), 802 &hpa->pnxtadd); 803 harmony.first_filled_play++; 804 harmony.first_filled_play %= MAX_BUFS; 805 harmony.nb_filled_play--; 806 807 harmony_enable_interrupts(); 808 } 809 810 if (harmony.blocked_playing) 811 wake_up_interruptible(&harmony.wq_play); 812 } 813 814 /* Check if we're being asked to fill in a recording buffer */ 815 if (dstatus & DSTATUS_RN) { 816 if((harmony.nb_filled_record+2>=MAX_BUFS) || harmony.suspended_recording) 817 { 818 harmony.nb_filled_record = 0; 819 harmony.first_filled_record = 0; 820 harmony.suspended_recording = 1; 821 gsc_writel((unsigned long)graveyard.dma_handle, &hpa->rnxtadd); 822 if (!harmony.suspended_playing) 823 harmony_enable_interrupts(); 824 } else { 825 int buf_to_fill; 826 buf_to_fill = (harmony.first_filled_record+harmony.nb_filled_record) % MAX_BUFS; 827 CHECK_WBACK_INV_OFFSET(recorded_buf, HARMONY_BUF_SIZE*buf_to_fill, HARMONY_BUF_SIZE); 828 gsc_writel((unsigned long)recorded_buf.dma_handle + 829 HARMONY_BUF_SIZE*buf_to_fill, 830 &hpa->rnxtadd); 831 harmony.nb_filled_record++; 832 harmony_enable_interrupts(); 833 } 834 835 if (harmony.blocked_recording && harmony.nb_filled_record>3) 836 wake_up_interruptible(&harmony.wq_record); 837 } 838 return IRQ_HANDLED; 839} 840 841/* 842 * Sound playing functions 843 */ 844 845static struct file_operations harmony_audio_fops = { 846 .owner = THIS_MODULE, 847 .llseek = no_llseek, 848 .read = harmony_audio_read, 849 .write = harmony_audio_write, 850 .poll = harmony_audio_poll, 851 .ioctl = harmony_audio_ioctl, 852 .open = harmony_audio_open, 853 .release = harmony_audio_release, 854}; 855 856static int harmony_audio_init(void) 857{ 858 /* Request that IRQ */ 859 if (request_irq(harmony.dev->irq, harmony_interrupt, 0 ,"harmony", &harmony)) { 860 printk(KERN_ERR PFX "Error requesting irq %d.\n", harmony.dev->irq); 861 return -EFAULT; 862 } 863 864 harmony.dsp_unit = register_sound_dsp(&harmony_audio_fops, -1); 865 if (harmony.dsp_unit < 0) { 866 printk(KERN_ERR PFX "Error registering dsp\n"); 867 free_irq(harmony.dev->irq, &harmony); 868 return -EFAULT; 869 } 870 871 /* Clear the buffers so you don't end up with crap in the buffers. */ 872 harmony_silence(&played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS); 873 874 /* Make sure this makes it to cache */ 875 CHECK_WBACK_INV_OFFSET(played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS); 876 877 /* Clear out the silent buffer and flush to cache */ 878 harmony_silence(&silent, 0, HARMONY_BUF_SIZE); 879 CHECK_WBACK_INV_OFFSET(silent, 0, HARMONY_BUF_SIZE); 880 881 harmony.audio_open = 0; 882 883 return 0; 884} 885 886 887/* 888 * mixer functions 889 */ 890 891static void harmony_mixer_set_gain(void) 892{ 893 harmony_wait_CNTL(); 894 gsc_writel(harmony.current_gain, &harmony.hpa->gainctl); 895} 896 897/* 898 * Read gain of selected channel. 899 * The OSS rate is from 0 (silent) to 100 -> need some conversions 900 * 901 * The harmony gain are attenuation for output and monitor gain. 902 * is amplifaction for input gain 903 */ 904#define to_harmony_level(level,max) ((level)*max/100) 905#define to_oss_level(level,max) ((level)*100/max) 906 907static int harmony_mixer_get_level(int channel) 908{ 909 int left_level; 910 int right_level; 911 912 switch (channel) { 913 case SOUND_MIXER_VOLUME: 914 left_level = (harmony.current_gain & GAIN_LO_MASK) >> GAIN_LO_SHIFT; 915 right_level = (harmony.current_gain & GAIN_RO_MASK) >> GAIN_RO_SHIFT; 916 left_level = to_oss_level(MAX_OUTPUT_LEVEL - left_level, MAX_OUTPUT_LEVEL); 917 right_level = to_oss_level(MAX_OUTPUT_LEVEL - right_level, MAX_OUTPUT_LEVEL); 918 return (right_level << 8)+left_level; 919 920 case SOUND_MIXER_IGAIN: 921 left_level = (harmony.current_gain & GAIN_LI_MASK) >> GAIN_LI_SHIFT; 922 right_level= (harmony.current_gain & GAIN_RI_MASK) >> GAIN_RI_SHIFT; 923 left_level = to_oss_level(left_level, MAX_INPUT_LEVEL); 924 right_level= to_oss_level(right_level, MAX_INPUT_LEVEL); 925 return (right_level << 8)+left_level; 926 927 case SOUND_MIXER_MONITOR: 928 left_level = (harmony.current_gain & GAIN_MA_MASK) >> GAIN_MA_SHIFT; 929 left_level = to_oss_level(MAX_MONITOR_LEVEL-left_level, MAX_MONITOR_LEVEL); 930 return (left_level << 8)+left_level; 931 } 932 return -EINVAL; 933} 934 935 936 937/* 938 * Some conversions for the same reasons. 939 * We give back the new real value(s) due to 940 * the rescale. 941 */ 942 943static int harmony_mixer_set_level(int channel, int value) 944{ 945 int left_level; 946 int right_level; 947 int new_left_level; 948 int new_right_level; 949 950 right_level = (value & 0x0000ff00) >> 8; 951 left_level = value & 0x000000ff; 952 if (right_level > 100) right_level = 100; 953 if (left_level > 100) left_level = 100; 954 955 switch (channel) { 956 case SOUND_MIXER_VOLUME: 957 right_level = to_harmony_level(100-right_level, MAX_OUTPUT_LEVEL); 958 left_level = to_harmony_level(100-left_level, MAX_OUTPUT_LEVEL); 959 new_right_level = to_oss_level(MAX_OUTPUT_LEVEL - right_level, MAX_OUTPUT_LEVEL); 960 new_left_level = to_oss_level(MAX_OUTPUT_LEVEL - left_level, MAX_OUTPUT_LEVEL); 961 harmony.current_gain = (harmony.current_gain & ~(GAIN_LO_MASK | GAIN_RO_MASK)) 962 | (left_level << GAIN_LO_SHIFT) | (right_level << GAIN_RO_SHIFT); 963 harmony_mixer_set_gain(); 964 return (new_right_level << 8) + new_left_level; 965 966 case SOUND_MIXER_IGAIN: 967 right_level = to_harmony_level(right_level, MAX_INPUT_LEVEL); 968 left_level = to_harmony_level(left_level, MAX_INPUT_LEVEL); 969 new_right_level = to_oss_level(right_level, MAX_INPUT_LEVEL); 970 new_left_level = to_oss_level(left_level, MAX_INPUT_LEVEL); 971 harmony.current_gain = (harmony.current_gain & ~(GAIN_LI_MASK | GAIN_RI_MASK)) 972 | (left_level << GAIN_LI_SHIFT) | (right_level << GAIN_RI_SHIFT); 973 harmony_mixer_set_gain(); 974 return (new_right_level << 8) + new_left_level; 975 976 case SOUND_MIXER_MONITOR: 977 left_level = to_harmony_level(100-left_level, MAX_MONITOR_LEVEL); 978 new_left_level = to_oss_level(MAX_MONITOR_LEVEL-left_level, MAX_MONITOR_LEVEL); 979 harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK) | (left_level << GAIN_MA_SHIFT); 980 harmony_mixer_set_gain(); 981 return (new_left_level << 8) + new_left_level; 982 } 983 984 return -EINVAL; 985} 986 987#undef to_harmony_level 988#undef to_oss_level 989 990/* 991 * Return the selected input device (mic or line) 992 */ 993 994static int harmony_mixer_get_recmask(void) 995{ 996 int current_input_line; 997 998 current_input_line = (harmony.current_gain & GAIN_IS_MASK) 999 >> GAIN_IS_SHIFT; 1000 if (current_input_line) 1001 return SOUND_MASK_MIC; 1002 1003 return SOUND_MASK_LINE; 1004} 1005 1006/* 1007 * Set the input (only one at time, arbitrary priority to line in) 1008 */ 1009 1010static int harmony_mixer_set_recmask(int recmask) 1011{ 1012 int new_input_line; 1013 int new_input_mask; 1014 int current_input_line; 1015 1016 current_input_line = (harmony.current_gain & GAIN_IS_MASK) 1017 >> GAIN_IS_SHIFT; 1018 if ((current_input_line && ((recmask & SOUND_MASK_LINE) || !(recmask & SOUND_MASK_MIC))) || 1019 (!current_input_line && ((recmask & SOUND_MASK_LINE) && !(recmask & SOUND_MASK_MIC)))) { 1020 new_input_line = 0; 1021 new_input_mask = SOUND_MASK_LINE; 1022 } else { 1023 new_input_line = 1; 1024 new_input_mask = SOUND_MASK_MIC; 1025 } 1026 harmony.current_gain = ((harmony.current_gain & ~GAIN_IS_MASK) | 1027 (new_input_line << GAIN_IS_SHIFT )); 1028 harmony_mixer_set_gain(); 1029 return new_input_mask; 1030} 1031 1032 1033/* 1034 * give the active outlines 1035 */ 1036 1037static int harmony_mixer_get_outmask(void) 1038{ 1039 int outmask = 0; 1040 1041 if (harmony.current_gain & GAIN_SE_MASK) outmask |= MASK_INTERNAL; 1042 if (harmony.current_gain & GAIN_LE_MASK) outmask |= MASK_LINEOUT; 1043 if (harmony.current_gain & GAIN_HE_MASK) outmask |= MASK_HEADPHONES; 1044 1045 return outmask; 1046} 1047 1048 1049static int harmony_mixer_set_outmask(int outmask) 1050{ 1051 if (outmask & MASK_INTERNAL) 1052 harmony.current_gain |= GAIN_SE_MASK; 1053 else 1054 harmony.current_gain &= ~GAIN_SE_MASK; 1055 1056 if (outmask & MASK_LINEOUT) 1057 harmony.current_gain |= GAIN_LE_MASK; 1058 else 1059 harmony.current_gain &= ~GAIN_LE_MASK; 1060 1061 if (outmask & MASK_HEADPHONES) 1062 harmony.current_gain |= GAIN_HE_MASK; 1063 else 1064 harmony.current_gain &= ~GAIN_HE_MASK; 1065 1066 harmony_mixer_set_gain(); 1067 1068 return (outmask & (MASK_INTERNAL | MASK_LINEOUT | MASK_HEADPHONES)); 1069} 1070 1071/* 1072 * This code is inspired from sb_mixer.c 1073 */ 1074 1075static int harmony_mixer_ioctl(struct inode * inode, struct file * file, 1076 unsigned int cmd, unsigned long arg) 1077{ 1078 int val; 1079 int ret; 1080 1081 if (cmd == SOUND_MIXER_INFO) { 1082 mixer_info info; 1083 memset(&info, 0, sizeof(info)); 1084 strncpy(info.id, "harmony", sizeof(info.id)-1); 1085 strncpy(info.name, "Harmony audio", sizeof(info.name)-1); 1086 info.modify_counter = 1; /* ? */ 1087 if (copy_to_user((void *)arg, &info, sizeof(info))) 1088 return -EFAULT; 1089 return 0; 1090 } 1091 1092 if (cmd == OSS_GETVERSION) 1093 return put_user(SOUND_VERSION, (int *)arg); 1094 1095 /* read */ 1096 val = 0; 1097 if (_SIOC_DIR(cmd) & _SIOC_WRITE) 1098 if (get_user(val, (int *)arg)) 1099 return -EFAULT; 1100 1101 switch (cmd) { 1102 case MIXER_READ(SOUND_MIXER_CAPS): 1103 ret = SOUND_CAP_EXCL_INPUT; 1104 break; 1105 case MIXER_READ(SOUND_MIXER_STEREODEVS): 1106 ret = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN; 1107 break; 1108 1109 case MIXER_READ(SOUND_MIXER_RECMASK): 1110 ret = SOUND_MASK_MIC | SOUND_MASK_LINE; 1111 break; 1112 case MIXER_READ(SOUND_MIXER_DEVMASK): 1113 ret = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN | 1114 SOUND_MASK_MONITOR; 1115 break; 1116 case MIXER_READ(SOUND_MIXER_OUTMASK): 1117 ret = MASK_INTERNAL | MASK_LINEOUT | 1118 MASK_HEADPHONES; 1119 break; 1120 1121 case MIXER_WRITE(SOUND_MIXER_RECSRC): 1122 ret = harmony_mixer_set_recmask(val); 1123 break; 1124 case MIXER_READ(SOUND_MIXER_RECSRC): 1125 ret = harmony_mixer_get_recmask(); 1126 break; 1127 1128 case MIXER_WRITE(SOUND_MIXER_OUTSRC): 1129 ret = harmony_mixer_set_outmask(val); 1130 break; 1131 case MIXER_READ(SOUND_MIXER_OUTSRC): 1132 ret = harmony_mixer_get_outmask(); 1133 break; 1134 1135 case MIXER_WRITE(SOUND_MIXER_VOLUME): 1136 case MIXER_WRITE(SOUND_MIXER_IGAIN): 1137 case MIXER_WRITE(SOUND_MIXER_MONITOR): 1138 ret = harmony_mixer_set_level(cmd & 0xff, val); 1139 break; 1140 1141 case MIXER_READ(SOUND_MIXER_VOLUME): 1142 case MIXER_READ(SOUND_MIXER_IGAIN): 1143 case MIXER_READ(SOUND_MIXER_MONITOR): 1144 ret = harmony_mixer_get_level(cmd & 0xff); 1145 break; 1146 1147 default: 1148 return -EINVAL; 1149 } 1150 1151 if (put_user(ret, (int *)arg)) 1152 return -EFAULT; 1153 return 0; 1154} 1155 1156 1157static int harmony_mixer_open(struct inode *inode, struct file *file) 1158{ 1159 if (harmony.mixer_open) 1160 return -EBUSY; 1161 harmony.mixer_open = 1; 1162 return 0; 1163} 1164 1165static int harmony_mixer_release(struct inode *inode, struct file *file) 1166{ 1167 if (!harmony.mixer_open) 1168 return -EBUSY; 1169 harmony.mixer_open = 0; 1170 return 0; 1171} 1172 1173static struct file_operations harmony_mixer_fops = { 1174 .owner = THIS_MODULE, 1175 .llseek = no_llseek, 1176 .open = harmony_mixer_open, 1177 .release = harmony_mixer_release, 1178 .ioctl = harmony_mixer_ioctl, 1179}; 1180 1181 1182/* 1183 * Mute all the output and reset Harmony. 1184 */ 1185 1186static void __init harmony_mixer_reset(void) 1187{ 1188 harmony.current_gain = GAIN_TOTAL_SILENCE; 1189 harmony_mixer_set_gain(); 1190 harmony_wait_CNTL(); 1191 gsc_writel(1, &harmony.hpa->reset); 1192 mdelay(50); /* wait 50 ms */ 1193 gsc_writel(0, &harmony.hpa->reset); 1194 harmony.current_gain = GAIN_DEFAULT; 1195 harmony_mixer_set_gain(); 1196} 1197 1198static int __init harmony_mixer_init(void) 1199{ 1200 /* Register the device file operations */ 1201 harmony.mixer_unit = register_sound_mixer(&harmony_mixer_fops, -1); 1202 if (harmony.mixer_unit < 0) { 1203 printk(KERN_WARNING PFX "Error Registering Mixer Driver\n"); 1204 return -EFAULT; 1205 } 1206 1207 harmony_mixer_reset(); 1208 harmony.mixer_open = 0; 1209 1210 return 0; 1211} 1212 1213 1214 1215/* 1216 * This is the callback that's called by the inventory hardware code 1217 * if it finds a match to the registered driver. 1218 */ 1219static int __devinit 1220harmony_driver_probe(struct parisc_device *dev) 1221{ 1222 u8 id; 1223 u8 rev; 1224 u32 cntl; 1225 int ret; 1226 1227 if (harmony.hpa) { 1228 /* We only support one Harmony at this time */ 1229 printk(KERN_ERR PFX "driver already registered\n"); 1230 return -EBUSY; 1231 } 1232 1233 if (!dev->irq) { 1234 printk(KERN_ERR PFX "no irq found\n"); 1235 return -ENODEV; 1236 } 1237 1238 /* Set the HPA of harmony */ 1239 harmony.hpa = (struct harmony_hpa *)dev->hpa.start; 1240 harmony.dev = dev; 1241 1242 /* Grab the ID and revision from the device */ 1243 id = gsc_readb(&harmony.hpa->id); 1244 if ((id | 1) != 0x15) { 1245 printk(KERN_WARNING PFX "wrong harmony id 0x%02x\n", id); 1246 return -EBUSY; 1247 } 1248 cntl = gsc_readl(&harmony.hpa->cntl); 1249 rev = (cntl>>20) & 0xff; 1250 1251 printk(KERN_INFO "Lasi Harmony Audio driver " HARMONY_VERSION ", " 1252 "h/w id %i, rev. %i at 0x%lx, IRQ %i\n", 1253 id, rev, dev->hpa.start, harmony.dev->irq); 1254 1255 /* Make sure the control bit isn't set, although I don't think it 1256 ever is. */ 1257 if (cntl & CNTL_C) { 1258 printk(KERN_WARNING PFX "CNTL busy\n"); 1259 harmony.hpa = 0; 1260 return -EBUSY; 1261 } 1262 1263 /* Initialize the memory buffers */ 1264 if (harmony_alloc_buffer(&played_buf, MAX_BUFS) || 1265 harmony_alloc_buffer(&recorded_buf, MAX_BUFS) || 1266 harmony_alloc_buffer(&graveyard, 1) || 1267 harmony_alloc_buffer(&silent, 1)) { 1268 ret = -EBUSY; 1269 goto out_err; 1270 } 1271 1272 /* Initialize /dev/mixer and /dev/audio */ 1273 if ((ret=harmony_mixer_init())) 1274 goto out_err; 1275 if ((ret=harmony_audio_init())) 1276 goto out_err; 1277 1278 return 0; 1279 1280out_err: 1281 harmony.hpa = 0; 1282 harmony_free_buffer(&played_buf); 1283 harmony_free_buffer(&recorded_buf); 1284 harmony_free_buffer(&graveyard); 1285 harmony_free_buffer(&silent); 1286 return ret; 1287} 1288 1289 1290static struct parisc_device_id harmony_tbl[] = { 1291 /* { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, Bushmaster/Flounder */ 1292 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, /* 712/715 Audio */ 1293 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, /* Pace Audio */ 1294 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F }, /* Outfield / Coral II */ 1295 { 0, } 1296}; 1297 1298MODULE_DEVICE_TABLE(parisc, harmony_tbl); 1299 1300static struct parisc_driver harmony_driver = { 1301 .name = "Lasi Harmony", 1302 .id_table = harmony_tbl, 1303 .probe = harmony_driver_probe, 1304}; 1305 1306static int __init init_harmony(void) 1307{ 1308 return register_parisc_driver(&harmony_driver); 1309} 1310 1311static void __exit cleanup_harmony(void) 1312{ 1313 free_irq(harmony.dev->irq, &harmony); 1314 unregister_sound_mixer(harmony.mixer_unit); 1315 unregister_sound_dsp(harmony.dsp_unit); 1316 harmony_free_buffer(&played_buf); 1317 harmony_free_buffer(&recorded_buf); 1318 harmony_free_buffer(&graveyard); 1319 harmony_free_buffer(&silent); 1320 unregister_parisc_driver(&harmony_driver); 1321} 1322 1323 1324MODULE_AUTHOR("Alex DeVries <alex@onefishtwo.ca>"); 1325MODULE_DESCRIPTION("Harmony sound driver"); 1326MODULE_LICENSE("GPL"); 1327 1328module_init(init_harmony); 1329module_exit(cleanup_harmony); 1330