Lines Matching full:h

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>
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>
43 #include <asm/hardware.h>
44 #include <asm/parisc-device.h>
46 #include "harmony.h"
95 harmony_read(struct snd_harmony *h, unsigned r) in harmony_read() argument
97 return __raw_readl(h->iobase + r); in harmony_read()
101 harmony_write(struct snd_harmony *h, unsigned r, unsigned long v) in harmony_write() argument
103 __raw_writel(v, h->iobase + r); in harmony_write()
107 harmony_wait_for_control(struct snd_harmony *h) in harmony_wait_for_control() argument
109 while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ; in harmony_wait_for_control()
113 harmony_reset(struct snd_harmony *h) in harmony_reset() argument
115 harmony_write(h, HARMONY_RESET, 1); in harmony_reset()
117 harmony_write(h, HARMONY_RESET, 0); in harmony_reset()
121 harmony_disable_interrupts(struct snd_harmony *h) in harmony_disable_interrupts() argument
124 harmony_wait_for_control(h); in harmony_disable_interrupts()
125 dstatus = harmony_read(h, HARMONY_DSTATUS); in harmony_disable_interrupts()
127 harmony_write(h, HARMONY_DSTATUS, dstatus); in harmony_disable_interrupts()
131 harmony_enable_interrupts(struct snd_harmony *h) in harmony_enable_interrupts() argument
134 harmony_wait_for_control(h); in harmony_enable_interrupts()
135 dstatus = harmony_read(h, HARMONY_DSTATUS); in harmony_enable_interrupts()
137 harmony_write(h, HARMONY_DSTATUS, dstatus); in harmony_enable_interrupts()
141 harmony_mute(struct snd_harmony *h) in harmony_mute() argument
145 spin_lock_irqsave(&h->mixer_lock, flags); in harmony_mute()
146 harmony_wait_for_control(h); in harmony_mute()
147 harmony_write(h, HARMONY_GAINCTL, HARMONY_GAIN_SILENCE); in harmony_mute()
148 spin_unlock_irqrestore(&h->mixer_lock, flags); in harmony_mute()
152 harmony_unmute(struct snd_harmony *h) in harmony_unmute() argument
156 spin_lock_irqsave(&h->mixer_lock, flags); in harmony_unmute()
157 harmony_wait_for_control(h); in harmony_unmute()
158 harmony_write(h, HARMONY_GAINCTL, h->st.gain); in harmony_unmute()
159 spin_unlock_irqrestore(&h->mixer_lock, flags); in harmony_unmute()
163 harmony_set_control(struct snd_harmony *h) in harmony_set_control() argument
168 spin_lock_irqsave(&h->lock, flags); in harmony_set_control()
171 (h->st.format << 6) | in harmony_set_control()
172 (h->st.stereo << 5) | in harmony_set_control()
173 (h->st.rate)); in harmony_set_control()
175 harmony_wait_for_control(h); in harmony_set_control()
176 harmony_write(h, HARMONY_CNTL, ctrl); in harmony_set_control()
178 spin_unlock_irqrestore(&h->lock, flags); in harmony_set_control()
185 struct snd_harmony *h = dev; in snd_harmony_interrupt() local
187 spin_lock(&h->lock); in snd_harmony_interrupt()
188 harmony_disable_interrupts(h); in snd_harmony_interrupt()
189 harmony_wait_for_control(h); in snd_harmony_interrupt()
190 dstatus = harmony_read(h, HARMONY_DSTATUS); in snd_harmony_interrupt()
191 spin_unlock(&h->lock); in snd_harmony_interrupt()
194 if (h->psubs && h->st.playing) { in snd_harmony_interrupt()
195 spin_lock(&h->lock); in snd_harmony_interrupt()
196 h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */ in snd_harmony_interrupt()
197 h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */ in snd_harmony_interrupt()
199 harmony_write(h, HARMONY_PNXTADD, in snd_harmony_interrupt()
200 h->pbuf.addr + h->pbuf.buf); in snd_harmony_interrupt()
201 h->stats.play_intr++; in snd_harmony_interrupt()
202 spin_unlock(&h->lock); in snd_harmony_interrupt()
203 snd_pcm_period_elapsed(h->psubs); in snd_harmony_interrupt()
205 spin_lock(&h->lock); in snd_harmony_interrupt()
206 harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); in snd_harmony_interrupt()
207 h->stats.silence_intr++; in snd_harmony_interrupt()
208 spin_unlock(&h->lock); in snd_harmony_interrupt()
213 if (h->csubs && h->st.capturing) { in snd_harmony_interrupt()
214 spin_lock(&h->lock); in snd_harmony_interrupt()
215 h->cbuf.buf += h->cbuf.count; in snd_harmony_interrupt()
216 h->cbuf.buf %= h->cbuf.size; in snd_harmony_interrupt()
218 harmony_write(h, HARMONY_RNXTADD, in snd_harmony_interrupt()
219 h->cbuf.addr + h->cbuf.buf); in snd_harmony_interrupt()
220 h->stats.rec_intr++; in snd_harmony_interrupt()
221 spin_unlock(&h->lock); in snd_harmony_interrupt()
222 snd_pcm_period_elapsed(h->csubs); in snd_harmony_interrupt()
224 spin_lock(&h->lock); in snd_harmony_interrupt()
225 harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); in snd_harmony_interrupt()
226 h->stats.graveyard_intr++; in snd_harmony_interrupt()
227 spin_unlock(&h->lock); in snd_harmony_interrupt()
231 spin_lock(&h->lock); in snd_harmony_interrupt()
232 harmony_enable_interrupts(h); in snd_harmony_interrupt()
233 spin_unlock(&h->lock); in snd_harmony_interrupt()
295 struct snd_harmony *h = snd_pcm_substream_chip(ss); in snd_harmony_playback_trigger() local
297 if (h->st.capturing) in snd_harmony_playback_trigger()
300 spin_lock(&h->lock); in snd_harmony_playback_trigger()
303 h->st.playing = 1; in snd_harmony_playback_trigger()
304 harmony_write(h, HARMONY_PNXTADD, h->pbuf.addr); in snd_harmony_playback_trigger()
305 harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); in snd_harmony_playback_trigger()
306 harmony_unmute(h); in snd_harmony_playback_trigger()
307 harmony_enable_interrupts(h); in snd_harmony_playback_trigger()
310 h->st.playing = 0; in snd_harmony_playback_trigger()
311 harmony_mute(h); in snd_harmony_playback_trigger()
312 harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); in snd_harmony_playback_trigger()
313 harmony_disable_interrupts(h); in snd_harmony_playback_trigger()
319 spin_unlock(&h->lock); in snd_harmony_playback_trigger()
323 spin_unlock(&h->lock); in snd_harmony_playback_trigger()
331 struct snd_harmony *h = snd_pcm_substream_chip(ss); in snd_harmony_capture_trigger() local
333 if (h->st.playing) in snd_harmony_capture_trigger()
336 spin_lock(&h->lock); in snd_harmony_capture_trigger()
339 h->st.capturing = 1; in snd_harmony_capture_trigger()
340 harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); in snd_harmony_capture_trigger()
341 harmony_write(h, HARMONY_RNXTADD, h->cbuf.addr); in snd_harmony_capture_trigger()
342 harmony_unmute(h); in snd_harmony_capture_trigger()
343 harmony_enable_interrupts(h); in snd_harmony_capture_trigger()
346 h->st.capturing = 0; in snd_harmony_capture_trigger()
347 harmony_mute(h); in snd_harmony_capture_trigger()
348 harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); in snd_harmony_capture_trigger()
349 harmony_disable_interrupts(h); in snd_harmony_capture_trigger()
355 spin_unlock(&h->lock); in snd_harmony_capture_trigger()
359 spin_unlock(&h->lock); in snd_harmony_capture_trigger()
365 snd_harmony_set_data_format(struct snd_harmony *h, int fmt, int force) in snd_harmony_set_data_format() argument
367 int o = h->st.format; in snd_harmony_set_data_format()
386 snd_pcm_format_set_silence(fmt, h->sdma.area, SILENCE_BUFSZ / in snd_harmony_set_data_format()
397 struct snd_harmony *h = snd_pcm_substream_chip(ss); in snd_harmony_playback_prepare() local
400 if (h->st.capturing) in snd_harmony_playback_prepare()
403 h->pbuf.size = snd_pcm_lib_buffer_bytes(ss); in snd_harmony_playback_prepare()
404 h->pbuf.count = snd_pcm_lib_period_bytes(ss); in snd_harmony_playback_prepare()
405 if (h->pbuf.buf >= h->pbuf.size) in snd_harmony_playback_prepare()
406 h->pbuf.buf = 0; in snd_harmony_playback_prepare()
407 h->st.playing = 0; in snd_harmony_playback_prepare()
409 h->st.rate = snd_harmony_rate_bits(rt->rate); in snd_harmony_playback_prepare()
410 h->st.format = snd_harmony_set_data_format(h, rt->format, 0); in snd_harmony_playback_prepare()
413 h->st.stereo = HARMONY_SS_STEREO; in snd_harmony_playback_prepare()
415 h->st.stereo = HARMONY_SS_MONO; in snd_harmony_playback_prepare()
417 harmony_set_control(h); in snd_harmony_playback_prepare()
419 h->pbuf.addr = rt->dma_addr; in snd_harmony_playback_prepare()
427 struct snd_harmony *h = snd_pcm_substream_chip(ss); in snd_harmony_capture_prepare() local
430 if (h->st.playing) in snd_harmony_capture_prepare()
433 h->cbuf.size = snd_pcm_lib_buffer_bytes(ss); in snd_harmony_capture_prepare()
434 h->cbuf.count = snd_pcm_lib_period_bytes(ss); in snd_harmony_capture_prepare()
435 if (h->cbuf.buf >= h->cbuf.size) in snd_harmony_capture_prepare()
436 h->cbuf.buf = 0; in snd_harmony_capture_prepare()
437 h->st.capturing = 0; in snd_harmony_capture_prepare()
439 h->st.rate = snd_harmony_rate_bits(rt->rate); in snd_harmony_capture_prepare()
440 h->st.format = snd_harmony_set_data_format(h, rt->format, 0); in snd_harmony_capture_prepare()
443 h->st.stereo = HARMONY_SS_STEREO; in snd_harmony_capture_prepare()
445 h->st.stereo = HARMONY_SS_MONO; in snd_harmony_capture_prepare()
447 harmony_set_control(h); in snd_harmony_capture_prepare()
449 h->cbuf.addr = rt->dma_addr; in snd_harmony_capture_prepare()
458 struct snd_harmony *h = snd_pcm_substream_chip(ss); in snd_harmony_playback_pointer() local
462 if (!(h->st.playing) || (h->psubs == NULL)) in snd_harmony_playback_pointer()
465 if ((h->pbuf.addr == 0) || (h->pbuf.size == 0)) in snd_harmony_playback_pointer()
468 pcuradd = harmony_read(h, HARMONY_PCURADD); in snd_harmony_playback_pointer()
469 played = pcuradd - h->pbuf.addr; in snd_harmony_playback_pointer()
473 pcuradd, h->pbuf.addr, played); in snd_harmony_playback_pointer()
476 if (pcuradd > h->pbuf.addr + h->pbuf.size) { in snd_harmony_playback_pointer()
487 struct snd_harmony *h = snd_pcm_substream_chip(ss); in snd_harmony_capture_pointer() local
491 if (!(h->st.capturing) || (h->csubs == NULL)) in snd_harmony_capture_pointer()
494 if ((h->cbuf.addr == 0) || (h->cbuf.size == 0)) in snd_harmony_capture_pointer()
497 rcuradd = harmony_read(h, HARMONY_RCURADD); in snd_harmony_capture_pointer()
498 caught = rcuradd - h->cbuf.addr; in snd_harmony_capture_pointer()
502 rcuradd, h->cbuf.addr, caught); in snd_harmony_capture_pointer()
505 if (rcuradd > h->cbuf.addr + h->cbuf.size) { in snd_harmony_capture_pointer()
515 struct snd_harmony *h = snd_pcm_substream_chip(ss); in snd_harmony_playback_open() local
519 h->psubs = ss; in snd_harmony_playback_open()
534 struct snd_harmony *h = snd_pcm_substream_chip(ss); in snd_harmony_capture_open() local
538 h->csubs = ss; in snd_harmony_capture_open()
553 struct snd_harmony *h = snd_pcm_substream_chip(ss); in snd_harmony_playback_close() local
554 h->psubs = NULL; in snd_harmony_playback_close()
561 struct snd_harmony *h = snd_pcm_substream_chip(ss); in snd_harmony_capture_close() local
562 h->csubs = NULL; in snd_harmony_capture_close()
583 snd_harmony_pcm_init(struct snd_harmony *h) in snd_harmony_pcm_init() argument
588 if (snd_BUG_ON(!h)) in snd_harmony_pcm_init()
591 harmony_disable_interrupts(h); in snd_harmony_pcm_init()
593 err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm); in snd_harmony_pcm_init()
602 pcm->private_data = h; in snd_harmony_pcm_init()
605 h->pcm = pcm; in snd_harmony_pcm_init()
607 h->psubs = NULL; in snd_harmony_pcm_init()
608 h->csubs = NULL; in snd_harmony_pcm_init()
611 h->dma.type = SNDRV_DMA_TYPE_DEV; in snd_harmony_pcm_init()
612 h->dma.dev = &h->dev->dev; in snd_harmony_pcm_init()
613 err = snd_dma_alloc_pages(h->dma.type, in snd_harmony_pcm_init()
614 h->dma.dev, in snd_harmony_pcm_init()
616 &h->gdma); in snd_harmony_pcm_init()
623 err = snd_dma_alloc_pages(h->dma.type, in snd_harmony_pcm_init()
624 h->dma.dev, in snd_harmony_pcm_init()
626 &h->sdma); in snd_harmony_pcm_init()
633 snd_pcm_set_managed_buffer_all(pcm, h->dma.type, h->dma.dev, in snd_harmony_pcm_init()
636 h->st.format = snd_harmony_set_data_format(h, in snd_harmony_pcm_init()
643 snd_harmony_set_new_gain(struct snd_harmony *h) in snd_harmony_set_new_gain() argument
645 harmony_wait_for_control(h); in snd_harmony_set_new_gain()
646 harmony_write(h, HARMONY_GAINCTL, h->st.gain); in snd_harmony_set_new_gain()
670 struct snd_harmony *h = snd_kcontrol_chip(kc); in snd_harmony_volume_get() local
677 spin_lock_irq(&h->mixer_lock); in snd_harmony_volume_get()
679 left = (h->st.gain >> shift_left) & mask; in snd_harmony_volume_get()
680 right = (h->st.gain >> shift_right) & mask; in snd_harmony_volume_get()
690 spin_unlock_irq(&h->mixer_lock); in snd_harmony_volume_get()
699 struct snd_harmony *h = snd_kcontrol_chip(kc); in snd_harmony_volume_put() local
705 int old_gain = h->st.gain; in snd_harmony_volume_put()
707 spin_lock_irq(&h->mixer_lock); in snd_harmony_volume_put()
712 h->st.gain &= ~( (mask << shift_left ) ); in snd_harmony_volume_put()
713 h->st.gain |= (left << shift_left); in snd_harmony_volume_put()
719 h->st.gain &= ~( (mask << shift_right) ); in snd_harmony_volume_put()
720 h->st.gain |= (right << shift_right); in snd_harmony_volume_put()
723 snd_harmony_set_new_gain(h); in snd_harmony_volume_put()
725 spin_unlock_irq(&h->mixer_lock); in snd_harmony_volume_put()
727 return h->st.gain != old_gain; in snd_harmony_volume_put()
743 struct snd_harmony *h = snd_kcontrol_chip(kc); in snd_harmony_captureroute_get() local
746 spin_lock_irq(&h->mixer_lock); in snd_harmony_captureroute_get()
748 value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1; in snd_harmony_captureroute_get()
751 spin_unlock_irq(&h->mixer_lock); in snd_harmony_captureroute_get()
760 struct snd_harmony *h = snd_kcontrol_chip(kc); in snd_harmony_captureroute_put() local
762 int old_gain = h->st.gain; in snd_harmony_captureroute_put()
764 spin_lock_irq(&h->mixer_lock); in snd_harmony_captureroute_put()
767 h->st.gain &= ~HARMONY_GAIN_IS_MASK; in snd_harmony_captureroute_put()
768 h->st.gain |= value << HARMONY_GAIN_IS_SHIFT; in snd_harmony_captureroute_put()
770 snd_harmony_set_new_gain(h); in snd_harmony_captureroute_put()
772 spin_unlock_irq(&h->mixer_lock); in snd_harmony_captureroute_put()
774 return h->st.gain != old_gain; in snd_harmony_captureroute_put()
809 snd_harmony_mixer_reset(struct snd_harmony *h) in snd_harmony_mixer_reset() argument
811 harmony_mute(h); in snd_harmony_mixer_reset()
812 harmony_reset(h); in snd_harmony_mixer_reset()
813 h->st.gain = HARMONY_GAIN_DEFAULT; in snd_harmony_mixer_reset()
814 harmony_unmute(h); in snd_harmony_mixer_reset()
818 snd_harmony_mixer_init(struct snd_harmony *h) in snd_harmony_mixer_init() argument
823 if (snd_BUG_ON(!h)) in snd_harmony_mixer_init()
825 card = h->card; in snd_harmony_mixer_init()
830 snd_ctl_new1(&snd_harmony_controls[idx], h)); in snd_harmony_mixer_init()
835 snd_harmony_mixer_reset(h); in snd_harmony_mixer_init()
841 snd_harmony_free(struct snd_harmony *h) in snd_harmony_free() argument
843 if (h->gdma.addr) in snd_harmony_free()
844 snd_dma_free_pages(&h->gdma); in snd_harmony_free()
845 if (h->sdma.addr) in snd_harmony_free()
846 snd_dma_free_pages(&h->sdma); in snd_harmony_free()
848 if (h->irq >= 0) in snd_harmony_free()
849 free_irq(h->irq, h); in snd_harmony_free()
851 iounmap(h->iobase); in snd_harmony_free()
852 kfree(h); in snd_harmony_free()
859 struct snd_harmony *h = dev->device_data; in snd_harmony_dev_free() local
860 return snd_harmony_free(h); in snd_harmony_dev_free()
869 struct snd_harmony *h; in snd_harmony_create() local
876 h = kzalloc(sizeof(*h), GFP_KERNEL); in snd_harmony_create()
877 if (h == NULL) in snd_harmony_create()
880 h->hpa = padev->hpa.start; in snd_harmony_create()
881 h->card = card; in snd_harmony_create()
882 h->dev = padev; in snd_harmony_create()
883 h->irq = -1; in snd_harmony_create()
884 h->iobase = ioremap(padev->hpa.start, HARMONY_SIZE); in snd_harmony_create()
885 if (h->iobase == NULL) { in snd_harmony_create()
893 "harmony", h); in snd_harmony_create()
899 h->irq = padev->irq; in snd_harmony_create()
901 spin_lock_init(&h->mixer_lock); in snd_harmony_create()
902 spin_lock_init(&h->lock); in snd_harmony_create()
904 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, h, &ops); in snd_harmony_create()
908 *rchip = h; in snd_harmony_create()
913 snd_harmony_free(h); in snd_harmony_create()
922 struct snd_harmony *h; in snd_harmony_probe() local
928 err = snd_harmony_create(card, padev, &h); in snd_harmony_probe()
932 err = snd_harmony_pcm_init(h); in snd_harmony_probe()
936 err = snd_harmony_mixer_init(h); in snd_harmony_probe()
943 card->shortname, h->hpa, h->irq); in snd_harmony_probe()