1 /* Hewlett-Packard Harmony audio driver
3 * This is a driver for the Harmony audio chipset found
4 * on the LASI ASIC of various early HP PA-RISC workstations.
6 * Copyright (C) 2004, Kyle McMartin <kyle@{debian.org,parisc-linux.org}>
8 * Based on the previous Harmony incarnations by,
9 * Copyright 2000 (c) Linuxcare Canada, Alex deVries
10 * Copyright 2000-2003 (c) Helge Deller
11 * Copyright 2001 (c) Matthieu Delahaye
12 * Copyright 2001 (c) Jean-Christophe Vaugeois
13 * Copyright 2003 (c) Laurent Canet
14 * Copyright 2004 (c) Stuart Brady
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License, version 2, as
18 * published by the Free Software Foundation.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 * - graveyard and silence buffers last for lifetime of
31 * the driver. playback and capture buffers are allocated
32 * per _open()/_close().
38 #include <linux/init.h>
39 #include <linux/slab.h>
40 #include <linux/time.h>
41 #include <linux/wait.h>
42 #include <linux/delay.h>
43 #include <linux/module.h>
44 #include <linux/interrupt.h>
45 #include <linux/spinlock.h>
46 #include <linux/dma-mapping.h>
48 #include <sound/core.h>
49 #include <sound/pcm.h>
50 #include <sound/control.h>
51 #include <sound/rawmidi.h>
52 #include <sound/initval.h>
53 #include <sound/info.h>
56 #include <asm/hardware.h>
57 #include <asm/parisc-device.h>
61 static int index
= SNDRV_DEFAULT_IDX1
; /* Index 0-MAX */
62 static char *id
= SNDRV_DEFAULT_STR1
; /* ID for this card */
63 module_param(index
, int, 0444);
64 MODULE_PARM_DESC(index
, "Index value for Harmony driver.");
65 module_param(id
, charp
, 0444);
66 MODULE_PARM_DESC(id
, "ID string for Harmony driver.");
69 static struct parisc_device_id snd_harmony_devtable
[] = {
70 /* bushmaster / flounder */
71 { HPHW_FIO
, HVERSION_REV_ANY_ID
, HVERSION_ANY_ID
, 0x0007A },
73 { HPHW_FIO
, HVERSION_REV_ANY_ID
, HVERSION_ANY_ID
, 0x0007B },
75 { HPHW_FIO
, HVERSION_REV_ANY_ID
, HVERSION_ANY_ID
, 0x0007E },
76 /* outfield / coral II */
77 { HPHW_FIO
, HVERSION_REV_ANY_ID
, HVERSION_ANY_ID
, 0x0007F },
81 MODULE_DEVICE_TABLE(parisc
, snd_harmony_devtable
);
83 #define NAME "harmony"
86 static unsigned int snd_harmony_rates
[] = {
87 5512, 6615, 8000, 9600,
88 11025, 16000, 18900, 22050,
89 27428, 32000, 33075, 37800,
93 static unsigned int rate_bits
[14] = {
94 HARMONY_SR_5KHZ
, HARMONY_SR_6KHZ
, HARMONY_SR_8KHZ
,
95 HARMONY_SR_9KHZ
, HARMONY_SR_11KHZ
, HARMONY_SR_16KHZ
,
96 HARMONY_SR_18KHZ
, HARMONY_SR_22KHZ
, HARMONY_SR_27KHZ
,
97 HARMONY_SR_32KHZ
, HARMONY_SR_33KHZ
, HARMONY_SR_37KHZ
,
98 HARMONY_SR_44KHZ
, HARMONY_SR_48KHZ
101 static struct snd_pcm_hw_constraint_list hw_constraint_rates
= {
102 .count
= ARRAY_SIZE(snd_harmony_rates
),
103 .list
= snd_harmony_rates
,
107 static inline unsigned long
108 harmony_read(struct snd_harmony
*h
, unsigned r
)
110 return __raw_readl(h
->iobase
+ r
);
114 harmony_write(struct snd_harmony
*h
, unsigned r
, unsigned long v
)
116 __raw_writel(v
, h
->iobase
+ r
);
120 harmony_wait_for_control(struct snd_harmony
*h
)
122 while (harmony_read(h
, HARMONY_CNTL
) & HARMONY_CNTL_C
) ;
126 harmony_reset(struct snd_harmony
*h
)
128 harmony_write(h
, HARMONY_RESET
, 1);
130 harmony_write(h
, HARMONY_RESET
, 0);
134 harmony_disable_interrupts(struct snd_harmony
*h
)
137 harmony_wait_for_control(h
);
138 dstatus
= harmony_read(h
, HARMONY_DSTATUS
);
139 dstatus
&= ~HARMONY_DSTATUS_IE
;
140 harmony_write(h
, HARMONY_DSTATUS
, dstatus
);
144 harmony_enable_interrupts(struct snd_harmony
*h
)
147 harmony_wait_for_control(h
);
148 dstatus
= harmony_read(h
, HARMONY_DSTATUS
);
149 dstatus
|= HARMONY_DSTATUS_IE
;
150 harmony_write(h
, HARMONY_DSTATUS
, dstatus
);
154 harmony_mute(struct snd_harmony
*h
)
158 spin_lock_irqsave(&h
->mixer_lock
, flags
);
159 harmony_wait_for_control(h
);
160 harmony_write(h
, HARMONY_GAINCTL
, HARMONY_GAIN_SILENCE
);
161 spin_unlock_irqrestore(&h
->mixer_lock
, flags
);
165 harmony_unmute(struct snd_harmony
*h
)
169 spin_lock_irqsave(&h
->mixer_lock
, flags
);
170 harmony_wait_for_control(h
);
171 harmony_write(h
, HARMONY_GAINCTL
, h
->st
.gain
);
172 spin_unlock_irqrestore(&h
->mixer_lock
, flags
);
176 harmony_set_control(struct snd_harmony
*h
)
181 spin_lock_irqsave(&h
->lock
, flags
);
183 ctrl
= (HARMONY_CNTL_C
|
184 (h
->st
.format
<< 6) |
185 (h
->st
.stereo
<< 5) |
188 harmony_wait_for_control(h
);
189 harmony_write(h
, HARMONY_CNTL
, ctrl
);
191 spin_unlock_irqrestore(&h
->lock
, flags
);
195 snd_harmony_interrupt(int irq
, void *dev
)
198 struct snd_harmony
*h
= dev
;
201 harmony_disable_interrupts(h
);
202 harmony_wait_for_control(h
);
203 dstatus
= harmony_read(h
, HARMONY_DSTATUS
);
204 spin_unlock(&h
->lock
);
206 if (dstatus
& HARMONY_DSTATUS_PN
) {
207 if (h
->psubs
&& h
->st
.playing
) {
209 h
->pbuf
.buf
+= h
->pbuf
.count
; /* PAGE_SIZE */
210 h
->pbuf
.buf
%= h
->pbuf
.size
; /* MAX_BUFS*PAGE_SIZE */
212 harmony_write(h
, HARMONY_PNXTADD
,
213 h
->pbuf
.addr
+ h
->pbuf
.buf
);
214 h
->stats
.play_intr
++;
215 spin_unlock(&h
->lock
);
216 snd_pcm_period_elapsed(h
->psubs
);
219 harmony_write(h
, HARMONY_PNXTADD
, h
->sdma
.addr
);
220 h
->stats
.silence_intr
++;
221 spin_unlock(&h
->lock
);
225 if (dstatus
& HARMONY_DSTATUS_RN
) {
226 if (h
->csubs
&& h
->st
.capturing
) {
228 h
->cbuf
.buf
+= h
->cbuf
.count
;
229 h
->cbuf
.buf
%= h
->cbuf
.size
;
231 harmony_write(h
, HARMONY_RNXTADD
,
232 h
->cbuf
.addr
+ h
->cbuf
.buf
);
234 spin_unlock(&h
->lock
);
235 snd_pcm_period_elapsed(h
->csubs
);
238 harmony_write(h
, HARMONY_RNXTADD
, h
->gdma
.addr
);
239 h
->stats
.graveyard_intr
++;
240 spin_unlock(&h
->lock
);
245 harmony_enable_interrupts(h
);
246 spin_unlock(&h
->lock
);
252 snd_harmony_rate_bits(int rate
)
256 for (i
= 0; i
< ARRAY_SIZE(snd_harmony_rates
); i
++)
257 if (snd_harmony_rates
[i
] == rate
)
260 return HARMONY_SR_44KHZ
;
263 static struct snd_pcm_hardware snd_harmony_playback
=
265 .info
= (SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_INTERLEAVED
|
266 SNDRV_PCM_INFO_JOINT_DUPLEX
| SNDRV_PCM_INFO_MMAP_VALID
|
267 SNDRV_PCM_INFO_BLOCK_TRANSFER
),
268 .formats
= (SNDRV_PCM_FMTBIT_S16_BE
| SNDRV_PCM_FMTBIT_MU_LAW
|
269 SNDRV_PCM_FMTBIT_A_LAW
),
270 .rates
= (SNDRV_PCM_RATE_5512
| SNDRV_PCM_RATE_8000_48000
|
271 SNDRV_PCM_RATE_KNOT
),
276 .buffer_bytes_max
= MAX_BUF_SIZE
,
277 .period_bytes_min
= BUF_SIZE
,
278 .period_bytes_max
= BUF_SIZE
,
280 .periods_max
= MAX_BUFS
,
284 static struct snd_pcm_hardware snd_harmony_capture
=
286 .info
= (SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_INTERLEAVED
|
287 SNDRV_PCM_INFO_JOINT_DUPLEX
| SNDRV_PCM_INFO_MMAP_VALID
|
288 SNDRV_PCM_INFO_BLOCK_TRANSFER
),
289 .formats
= (SNDRV_PCM_FMTBIT_S16_BE
| SNDRV_PCM_FMTBIT_MU_LAW
|
290 SNDRV_PCM_FMTBIT_A_LAW
),
291 .rates
= (SNDRV_PCM_RATE_5512
| SNDRV_PCM_RATE_8000_48000
|
292 SNDRV_PCM_RATE_KNOT
),
297 .buffer_bytes_max
= MAX_BUF_SIZE
,
298 .period_bytes_min
= BUF_SIZE
,
299 .period_bytes_max
= BUF_SIZE
,
301 .periods_max
= MAX_BUFS
,
306 snd_harmony_playback_trigger(struct snd_pcm_substream
*ss
, int cmd
)
308 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
315 case SNDRV_PCM_TRIGGER_START
:
317 harmony_write(h
, HARMONY_PNXTADD
, h
->pbuf
.addr
);
318 harmony_write(h
, HARMONY_RNXTADD
, h
->gdma
.addr
);
320 harmony_enable_interrupts(h
);
322 case SNDRV_PCM_TRIGGER_STOP
:
325 harmony_write(h
, HARMONY_PNXTADD
, h
->sdma
.addr
);
326 harmony_disable_interrupts(h
);
328 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
329 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
330 case SNDRV_PCM_TRIGGER_SUSPEND
:
332 spin_unlock(&h
->lock
);
336 spin_unlock(&h
->lock
);
342 snd_harmony_capture_trigger(struct snd_pcm_substream
*ss
, int cmd
)
344 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
351 case SNDRV_PCM_TRIGGER_START
:
353 harmony_write(h
, HARMONY_PNXTADD
, h
->sdma
.addr
);
354 harmony_write(h
, HARMONY_RNXTADD
, h
->cbuf
.addr
);
356 harmony_enable_interrupts(h
);
358 case SNDRV_PCM_TRIGGER_STOP
:
361 harmony_write(h
, HARMONY_RNXTADD
, h
->gdma
.addr
);
362 harmony_disable_interrupts(h
);
364 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
365 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
366 case SNDRV_PCM_TRIGGER_SUSPEND
:
368 spin_unlock(&h
->lock
);
372 spin_unlock(&h
->lock
);
378 snd_harmony_set_data_format(struct snd_harmony
*h
, int fmt
, int force
)
380 int o
= h
->st
.format
;
384 case SNDRV_PCM_FORMAT_S16_BE
:
385 n
= HARMONY_DF_16BIT_LINEAR
;
387 case SNDRV_PCM_FORMAT_A_LAW
:
388 n
= HARMONY_DF_8BIT_ALAW
;
390 case SNDRV_PCM_FORMAT_MU_LAW
:
391 n
= HARMONY_DF_8BIT_ULAW
;
394 n
= HARMONY_DF_16BIT_LINEAR
;
398 if (force
|| o
!= n
) {
399 snd_pcm_format_set_silence(fmt
, h
->sdma
.area
, SILENCE_BUFSZ
/
400 (snd_pcm_format_physical_width(fmt
)
408 snd_harmony_playback_prepare(struct snd_pcm_substream
*ss
)
410 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
411 struct snd_pcm_runtime
*rt
= ss
->runtime
;
416 h
->pbuf
.size
= snd_pcm_lib_buffer_bytes(ss
);
417 h
->pbuf
.count
= snd_pcm_lib_period_bytes(ss
);
418 if (h
->pbuf
.buf
>= h
->pbuf
.size
)
422 h
->st
.rate
= snd_harmony_rate_bits(rt
->rate
);
423 h
->st
.format
= snd_harmony_set_data_format(h
, rt
->format
, 0);
425 if (rt
->channels
== 2)
426 h
->st
.stereo
= HARMONY_SS_STEREO
;
428 h
->st
.stereo
= HARMONY_SS_MONO
;
430 harmony_set_control(h
);
432 h
->pbuf
.addr
= rt
->dma_addr
;
438 snd_harmony_capture_prepare(struct snd_pcm_substream
*ss
)
440 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
441 struct snd_pcm_runtime
*rt
= ss
->runtime
;
446 h
->cbuf
.size
= snd_pcm_lib_buffer_bytes(ss
);
447 h
->cbuf
.count
= snd_pcm_lib_period_bytes(ss
);
448 if (h
->cbuf
.buf
>= h
->cbuf
.size
)
452 h
->st
.rate
= snd_harmony_rate_bits(rt
->rate
);
453 h
->st
.format
= snd_harmony_set_data_format(h
, rt
->format
, 0);
455 if (rt
->channels
== 2)
456 h
->st
.stereo
= HARMONY_SS_STEREO
;
458 h
->st
.stereo
= HARMONY_SS_MONO
;
460 harmony_set_control(h
);
462 h
->cbuf
.addr
= rt
->dma_addr
;
467 static snd_pcm_uframes_t
468 snd_harmony_playback_pointer(struct snd_pcm_substream
*ss
)
470 struct snd_pcm_runtime
*rt
= ss
->runtime
;
471 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
472 unsigned long pcuradd
;
473 unsigned long played
;
475 if (!(h
->st
.playing
) || (h
->psubs
== NULL
))
478 if ((h
->pbuf
.addr
== 0) || (h
->pbuf
.size
== 0))
481 pcuradd
= harmony_read(h
, HARMONY_PCURADD
);
482 played
= pcuradd
- h
->pbuf
.addr
;
485 printk(KERN_DEBUG PFX
"playback_pointer is 0x%lx-0x%lx = %d bytes\n",
486 pcuradd
, h
->pbuf
.addr
, played
);
489 if (pcuradd
> h
->pbuf
.addr
+ h
->pbuf
.size
) {
493 return bytes_to_frames(rt
, played
);
496 static snd_pcm_uframes_t
497 snd_harmony_capture_pointer(struct snd_pcm_substream
*ss
)
499 struct snd_pcm_runtime
*rt
= ss
->runtime
;
500 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
501 unsigned long rcuradd
;
502 unsigned long caught
;
504 if (!(h
->st
.capturing
) || (h
->csubs
== NULL
))
507 if ((h
->cbuf
.addr
== 0) || (h
->cbuf
.size
== 0))
510 rcuradd
= harmony_read(h
, HARMONY_RCURADD
);
511 caught
= rcuradd
- h
->cbuf
.addr
;
514 printk(KERN_DEBUG PFX
"capture_pointer is 0x%lx-0x%lx = %d bytes\n",
515 rcuradd
, h
->cbuf
.addr
, caught
);
518 if (rcuradd
> h
->cbuf
.addr
+ h
->cbuf
.size
) {
522 return bytes_to_frames(rt
, caught
);
526 snd_harmony_playback_open(struct snd_pcm_substream
*ss
)
528 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
529 struct snd_pcm_runtime
*rt
= ss
->runtime
;
533 rt
->hw
= snd_harmony_playback
;
534 snd_pcm_hw_constraint_list(rt
, 0, SNDRV_PCM_HW_PARAM_RATE
,
535 &hw_constraint_rates
);
537 err
= snd_pcm_hw_constraint_integer(rt
, SNDRV_PCM_HW_PARAM_PERIODS
);
545 snd_harmony_capture_open(struct snd_pcm_substream
*ss
)
547 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
548 struct snd_pcm_runtime
*rt
= ss
->runtime
;
552 rt
->hw
= snd_harmony_capture
;
553 snd_pcm_hw_constraint_list(rt
, 0, SNDRV_PCM_HW_PARAM_RATE
,
554 &hw_constraint_rates
);
556 err
= snd_pcm_hw_constraint_integer(rt
, SNDRV_PCM_HW_PARAM_PERIODS
);
564 snd_harmony_playback_close(struct snd_pcm_substream
*ss
)
566 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
572 snd_harmony_capture_close(struct snd_pcm_substream
*ss
)
574 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
580 snd_harmony_hw_params(struct snd_pcm_substream
*ss
,
581 struct snd_pcm_hw_params
*hw
)
584 struct snd_harmony
*h
= snd_pcm_substream_chip(ss
);
586 err
= snd_pcm_lib_malloc_pages(ss
, params_buffer_bytes(hw
));
587 if (err
> 0 && h
->dma
.type
== SNDRV_DMA_TYPE_CONTINUOUS
)
588 ss
->runtime
->dma_addr
= __pa(ss
->runtime
->dma_area
);
594 snd_harmony_hw_free(struct snd_pcm_substream
*ss
)
596 return snd_pcm_lib_free_pages(ss
);
599 static struct snd_pcm_ops snd_harmony_playback_ops
= {
600 .open
= snd_harmony_playback_open
,
601 .close
= snd_harmony_playback_close
,
602 .ioctl
= snd_pcm_lib_ioctl
,
603 .hw_params
= snd_harmony_hw_params
,
604 .hw_free
= snd_harmony_hw_free
,
605 .prepare
= snd_harmony_playback_prepare
,
606 .trigger
= snd_harmony_playback_trigger
,
607 .pointer
= snd_harmony_playback_pointer
,
610 static struct snd_pcm_ops snd_harmony_capture_ops
= {
611 .open
= snd_harmony_capture_open
,
612 .close
= snd_harmony_capture_close
,
613 .ioctl
= snd_pcm_lib_ioctl
,
614 .hw_params
= snd_harmony_hw_params
,
615 .hw_free
= snd_harmony_hw_free
,
616 .prepare
= snd_harmony_capture_prepare
,
617 .trigger
= snd_harmony_capture_trigger
,
618 .pointer
= snd_harmony_capture_pointer
,
622 snd_harmony_pcm_init(struct snd_harmony
*h
)
630 harmony_disable_interrupts(h
);
632 err
= snd_pcm_new(h
->card
, "harmony", 0, 1, 1, &pcm
);
636 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
,
637 &snd_harmony_playback_ops
);
638 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
,
639 &snd_harmony_capture_ops
);
641 pcm
->private_data
= h
;
643 strcpy(pcm
->name
, "harmony");
649 /* initialize graveyard buffer */
650 h
->dma
.type
= SNDRV_DMA_TYPE_DEV
;
651 h
->dma
.dev
= &h
->dev
->dev
;
652 err
= snd_dma_alloc_pages(h
->dma
.type
,
654 BUF_SIZE
*GRAVEYARD_BUFS
,
657 printk(KERN_ERR PFX
"cannot allocate graveyard buffer!\n");
661 /* initialize silence buffers */
662 err
= snd_dma_alloc_pages(h
->dma
.type
,
664 BUF_SIZE
*SILENCE_BUFS
,
667 printk(KERN_ERR PFX
"cannot allocate silence buffer!\n");
671 /* pre-allocate space for DMA */
672 err
= snd_pcm_lib_preallocate_pages_for_all(pcm
, h
->dma
.type
,
677 printk(KERN_ERR PFX
"buffer allocation error: %d\n", err
);
681 h
->st
.format
= snd_harmony_set_data_format(h
,
682 SNDRV_PCM_FORMAT_S16_BE
, 1);
688 snd_harmony_set_new_gain(struct snd_harmony
*h
)
690 harmony_wait_for_control(h
);
691 harmony_write(h
, HARMONY_GAINCTL
, h
->st
.gain
);
695 snd_harmony_mixercontrol_info(struct snd_kcontrol
*kc
,
696 struct snd_ctl_elem_info
*uinfo
)
698 int mask
= (kc
->private_value
>> 16) & 0xff;
699 int left_shift
= (kc
->private_value
) & 0xff;
700 int right_shift
= (kc
->private_value
>> 8) & 0xff;
702 uinfo
->type
= mask
== 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN
:
703 SNDRV_CTL_ELEM_TYPE_INTEGER
;
704 uinfo
->count
= left_shift
== right_shift
? 1 : 2;
705 uinfo
->value
.integer
.min
= 0;
706 uinfo
->value
.integer
.max
= mask
;
712 snd_harmony_volume_get(struct snd_kcontrol
*kc
,
713 struct snd_ctl_elem_value
*ucontrol
)
715 struct snd_harmony
*h
= snd_kcontrol_chip(kc
);
716 int shift_left
= (kc
->private_value
) & 0xff;
717 int shift_right
= (kc
->private_value
>> 8) & 0xff;
718 int mask
= (kc
->private_value
>> 16) & 0xff;
719 int invert
= (kc
->private_value
>> 24) & 0xff;
722 spin_lock_irq(&h
->mixer_lock
);
724 left
= (h
->st
.gain
>> shift_left
) & mask
;
725 right
= (h
->st
.gain
>> shift_right
) & mask
;
728 right
= mask
- right
;
731 ucontrol
->value
.integer
.value
[0] = left
;
732 if (shift_left
!= shift_right
)
733 ucontrol
->value
.integer
.value
[1] = right
;
735 spin_unlock_irq(&h
->mixer_lock
);
741 snd_harmony_volume_put(struct snd_kcontrol
*kc
,
742 struct snd_ctl_elem_value
*ucontrol
)
744 struct snd_harmony
*h
= snd_kcontrol_chip(kc
);
745 int shift_left
= (kc
->private_value
) & 0xff;
746 int shift_right
= (kc
->private_value
>> 8) & 0xff;
747 int mask
= (kc
->private_value
>> 16) & 0xff;
748 int invert
= (kc
->private_value
>> 24) & 0xff;
750 int old_gain
= h
->st
.gain
;
752 spin_lock_irq(&h
->mixer_lock
);
754 left
= ucontrol
->value
.integer
.value
[0] & mask
;
757 h
->st
.gain
&= ~( (mask
<< shift_left
) );
758 h
->st
.gain
|= (left
<< shift_left
);
760 if (shift_left
!= shift_right
) {
761 right
= ucontrol
->value
.integer
.value
[1] & mask
;
763 right
= mask
- right
;
764 h
->st
.gain
&= ~( (mask
<< shift_right
) );
765 h
->st
.gain
|= (right
<< shift_right
);
768 snd_harmony_set_new_gain(h
);
770 spin_unlock_irq(&h
->mixer_lock
);
772 return h
->st
.gain
!= old_gain
;
776 snd_harmony_captureroute_info(struct snd_kcontrol
*kc
,
777 struct snd_ctl_elem_info
*uinfo
)
779 static char *texts
[2] = { "Line", "Mic" };
780 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
782 uinfo
->value
.enumerated
.items
= 2;
783 if (uinfo
->value
.enumerated
.item
> 1)
784 uinfo
->value
.enumerated
.item
= 1;
785 strcpy(uinfo
->value
.enumerated
.name
,
786 texts
[uinfo
->value
.enumerated
.item
]);
791 snd_harmony_captureroute_get(struct snd_kcontrol
*kc
,
792 struct snd_ctl_elem_value
*ucontrol
)
794 struct snd_harmony
*h
= snd_kcontrol_chip(kc
);
797 spin_lock_irq(&h
->mixer_lock
);
799 value
= (h
->st
.gain
>> HARMONY_GAIN_IS_SHIFT
) & 1;
800 ucontrol
->value
.enumerated
.item
[0] = value
;
802 spin_unlock_irq(&h
->mixer_lock
);
808 snd_harmony_captureroute_put(struct snd_kcontrol
*kc
,
809 struct snd_ctl_elem_value
*ucontrol
)
811 struct snd_harmony
*h
= snd_kcontrol_chip(kc
);
813 int old_gain
= h
->st
.gain
;
815 spin_lock_irq(&h
->mixer_lock
);
817 value
= ucontrol
->value
.enumerated
.item
[0] & 1;
818 h
->st
.gain
&= ~HARMONY_GAIN_IS_MASK
;
819 h
->st
.gain
|= value
<< HARMONY_GAIN_IS_SHIFT
;
821 snd_harmony_set_new_gain(h
);
823 spin_unlock_irq(&h
->mixer_lock
);
825 return h
->st
.gain
!= old_gain
;
828 #define HARMONY_CONTROLS ARRAY_SIZE(snd_harmony_controls)
830 #define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \
831 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
832 .info = snd_harmony_mixercontrol_info, \
833 .get = snd_harmony_volume_get, .put = snd_harmony_volume_put, \
834 .private_value = ((left_shift) | ((right_shift) << 8) | \
835 ((mask) << 16) | ((invert) << 24)) }
837 static struct snd_kcontrol_new snd_harmony_controls
[] = {
838 HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT
,
839 HARMONY_GAIN_RO_SHIFT
, HARMONY_GAIN_OUT
, 1),
840 HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT
,
841 HARMONY_GAIN_RI_SHIFT
, HARMONY_GAIN_IN
, 0),
842 HARMONY_VOLUME("Monitor Volume", HARMONY_GAIN_MA_SHIFT
,
843 HARMONY_GAIN_MA_SHIFT
, HARMONY_GAIN_MA
, 1),
845 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
846 .name
= "Input Route",
847 .info
= snd_harmony_captureroute_info
,
848 .get
= snd_harmony_captureroute_get
,
849 .put
= snd_harmony_captureroute_put
851 HARMONY_VOLUME("Internal Speaker Switch", HARMONY_GAIN_SE_SHIFT
,
852 HARMONY_GAIN_SE_SHIFT
, 1, 0),
853 HARMONY_VOLUME("Line-Out Switch", HARMONY_GAIN_LE_SHIFT
,
854 HARMONY_GAIN_LE_SHIFT
, 1, 0),
855 HARMONY_VOLUME("Headphones Switch", HARMONY_GAIN_HE_SHIFT
,
856 HARMONY_GAIN_HE_SHIFT
, 1, 0),
859 static void __devinit
860 snd_harmony_mixer_reset(struct snd_harmony
*h
)
864 h
->st
.gain
= HARMONY_GAIN_DEFAULT
;
869 snd_harmony_mixer_init(struct snd_harmony
*h
)
871 struct snd_card
*card
;
877 strcpy(card
->mixername
, "Harmony Gain control interface");
879 for (idx
= 0; idx
< HARMONY_CONTROLS
; idx
++) {
880 err
= snd_ctl_add(card
,
881 snd_ctl_new1(&snd_harmony_controls
[idx
], h
));
886 snd_harmony_mixer_reset(h
);
892 snd_harmony_free(struct snd_harmony
*h
)
895 snd_dma_free_pages(&h
->gdma
);
897 snd_dma_free_pages(&h
->sdma
);
905 parisc_set_drvdata(h
->dev
, NULL
);
912 snd_harmony_dev_free(struct snd_device
*dev
)
914 struct snd_harmony
*h
= dev
->device_data
;
915 return snd_harmony_free(h
);
919 snd_harmony_create(struct snd_card
*card
,
920 struct parisc_device
*padev
,
921 struct snd_harmony
**rchip
)
924 struct snd_harmony
*h
;
925 static struct snd_device_ops ops
= {
926 .dev_free
= snd_harmony_dev_free
,
931 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
935 h
->hpa
= padev
->hpa
.start
;
939 h
->iobase
= ioremap_nocache(padev
->hpa
.start
, HARMONY_SIZE
);
940 if (h
->iobase
== NULL
) {
941 printk(KERN_ERR PFX
"unable to remap hpa 0x%lx\n",
942 (unsigned long)padev
->hpa
.start
);
947 err
= request_irq(padev
->irq
, snd_harmony_interrupt
, 0,
950 printk(KERN_ERR PFX
"could not obtain interrupt %d",
956 spin_lock_init(&h
->mixer_lock
);
957 spin_lock_init(&h
->lock
);
959 if ((err
= snd_device_new(card
, SNDRV_DEV_LOWLEVEL
,
964 snd_card_set_dev(card
, &padev
->dev
);
976 snd_harmony_probe(struct parisc_device
*padev
)
979 struct snd_card
*card
;
980 struct snd_harmony
*h
;
982 err
= snd_card_create(index
, id
, THIS_MODULE
, 0, &card
);
986 err
= snd_harmony_create(card
, padev
, &h
);
990 err
= snd_harmony_pcm_init(h
);
994 err
= snd_harmony_mixer_init(h
);
998 strcpy(card
->driver
, "harmony");
999 strcpy(card
->shortname
, "Harmony");
1000 sprintf(card
->longname
, "%s at 0x%lx, irq %i",
1001 card
->shortname
, h
->hpa
, h
->irq
);
1003 err
= snd_card_register(card
);
1007 parisc_set_drvdata(padev
, card
);
1011 snd_card_free(card
);
1015 static int __devexit
1016 snd_harmony_remove(struct parisc_device
*padev
)
1018 snd_card_free(parisc_get_drvdata(padev
));
1019 parisc_set_drvdata(padev
, NULL
);
1023 static struct parisc_driver snd_harmony_driver
= {
1025 .id_table
= snd_harmony_devtable
,
1026 .probe
= snd_harmony_probe
,
1027 .remove
= __devexit_p(snd_harmony_remove
),
1031 alsa_harmony_init(void)
1033 return register_parisc_driver(&snd_harmony_driver
);
1037 alsa_harmony_fini(void)
1039 unregister_parisc_driver(&snd_harmony_driver
);
1042 MODULE_LICENSE("GPL");
1043 MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>");
1044 MODULE_DESCRIPTION("Harmony sound driver");
1046 module_init(alsa_harmony_init
);
1047 module_exit(alsa_harmony_fini
);