Lines Matching +full:audio +full:- +full:channel
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Sound driver for Silicon Graphics O2 Workstations A/V board audio.
5 * Copyright 2003 Vivien Chappelier <vivien.chappelier@linux-mips.org>
15 #include <linux/dma-mapping.h>
32 MODULE_AUTHOR("Vivien Chappelier <vivien.chappelier@linux-mips.org>");
33 MODULE_DESCRIPTION("SGI O2 Audio");
36 static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
45 #define AUDIO_CONTROL_RESET BIT(0) /* 1: reset audio interface */
52 #define CHANNEL_CONTROL_RESET BIT(10) /* 1: reset channel */
65 #define CHANNEL_RING_MASK (CHANNEL_RING_SIZE - 1)
78 /* definition of the chip-specific record */
87 struct snd_sgio2audio_chan channel[3]; member
99 * Returns unsigned register value on success, -errno on failure.
107 spin_lock_irqsave(&chip->ad1843_lock, flags); in read_ad1843_reg()
110 CODEC_CONTROL_READ, &mace->perif.audio.codec_control); in read_ad1843_reg()
112 val = readq(&mace->perif.audio.codec_control); /* flush bus */ in read_ad1843_reg()
115 val = readq(&mace->perif.audio.codec_read); in read_ad1843_reg()
117 spin_unlock_irqrestore(&chip->ad1843_lock, flags); in read_ad1843_reg()
130 spin_lock_irqsave(&chip->ad1843_lock, flags); in write_ad1843_reg()
134 &mace->perif.audio.codec_control); in write_ad1843_reg()
136 val = readq(&mace->perif.audio.codec_control); /* flush bus */ in write_ad1843_reg()
139 spin_unlock_irqrestore(&chip->ad1843_lock, flags); in write_ad1843_reg()
148 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in sgio2audio_gain_info()
149 uinfo->count = 2; in sgio2audio_gain_info()
150 uinfo->value.integer.min = 0; in sgio2audio_gain_info()
151 uinfo->value.integer.max = ad1843_get_gain_max(&chip->ad1843, in sgio2audio_gain_info()
152 (int)kcontrol->private_value); in sgio2audio_gain_info()
162 vol = ad1843_get_gain(&chip->ad1843, (int)kcontrol->private_value); in sgio2audio_gain_get()
164 ucontrol->value.integer.value[0] = (vol >> 8) & 0xFF; in sgio2audio_gain_get()
165 ucontrol->value.integer.value[1] = vol & 0xFF; in sgio2audio_gain_get()
176 oldvol = ad1843_get_gain(&chip->ad1843, kcontrol->private_value); in sgio2audio_gain_put()
177 newvol = (ucontrol->value.integer.value[0] << 8) | in sgio2audio_gain_put()
178 ucontrol->value.integer.value[1]; in sgio2audio_gain_put()
180 newvol = ad1843_set_gain(&chip->ad1843, kcontrol->private_value, in sgio2audio_gain_put()
200 ucontrol->value.enumerated.item[0] = ad1843_get_recsrc(&chip->ad1843); in sgio2audio_source_get()
210 oldsrc = ad1843_get_recsrc(&chip->ad1843); in sgio2audio_source_put()
211 newsrc = ad1843_set_recsrc(&chip->ad1843, in sgio2audio_source_put()
212 ucontrol->value.enumerated.item[0]); in sgio2audio_source_put()
302 err = snd_ctl_add(chip->card, in snd_sgio2audio_new_mixer()
307 err = snd_ctl_add(chip->card, in snd_sgio2audio_new_mixer()
312 err = snd_ctl_add(chip->card, in snd_sgio2audio_new_mixer()
317 err = snd_ctl_add(chip->card, in snd_sgio2audio_new_mixer()
321 err = snd_ctl_add(chip->card, in snd_sgio2audio_new_mixer()
326 err = snd_ctl_add(chip->card, in snd_sgio2audio_new_mixer()
331 err = snd_ctl_add(chip->card, in snd_sgio2audio_new_mixer()
339 /* low-level audio interface DMA */
354 struct snd_pcm_runtime *runtime = chip->channel[ch].substream->runtime; in snd_sgio2audio_dma_pull_frag()
356 spin_lock_irqsave(&chip->channel[ch].lock, flags); in snd_sgio2audio_dma_pull_frag()
358 src_base = (unsigned long) chip->ring_base | (ch << CHANNEL_RING_SHIFT); in snd_sgio2audio_dma_pull_frag()
359 src_pos = readq(&mace->perif.audio.chan[ch].read_ptr); in snd_sgio2audio_dma_pull_frag()
360 dst_base = runtime->dma_area; in snd_sgio2audio_dma_pull_frag()
361 dst_pos = chip->channel[ch].pos; in snd_sgio2audio_dma_pull_frag()
362 dst_mask = frames_to_bytes(runtime, runtime->buffer_size) - 1; in snd_sgio2audio_dma_pull_frag()
365 chip->channel[ch].size += (count >> 3); /* in frames */ in snd_sgio2audio_dma_pull_frag()
366 ret = chip->channel[ch].size >= runtime->period_size; in snd_sgio2audio_dma_pull_frag()
367 chip->channel[ch].size %= runtime->period_size; in snd_sgio2audio_dma_pull_frag()
379 count -= sizeof(u64); in snd_sgio2audio_dma_pull_frag()
382 writeq(src_pos, &mace->perif.audio.chan[ch].read_ptr); /* in bytes */ in snd_sgio2audio_dma_pull_frag()
383 chip->channel[ch].pos = dst_pos; in snd_sgio2audio_dma_pull_frag()
385 spin_unlock_irqrestore(&chip->channel[ch].lock, flags); in snd_sgio2audio_dma_pull_frag()
402 struct snd_pcm_runtime *runtime = chip->channel[ch].substream->runtime; in snd_sgio2audio_dma_push_frag()
404 spin_lock_irqsave(&chip->channel[ch].lock, flags); in snd_sgio2audio_dma_push_frag()
406 dst_base = (unsigned long)chip->ring_base | (ch << CHANNEL_RING_SHIFT); in snd_sgio2audio_dma_push_frag()
407 dst_pos = readq(&mace->perif.audio.chan[ch].write_ptr); in snd_sgio2audio_dma_push_frag()
408 src_base = runtime->dma_area; in snd_sgio2audio_dma_push_frag()
409 src_pos = chip->channel[ch].pos; in snd_sgio2audio_dma_push_frag()
410 src_mask = frames_to_bytes(runtime, runtime->buffer_size) - 1; in snd_sgio2audio_dma_push_frag()
413 chip->channel[ch].size += (count >> 3); /* in frames */ in snd_sgio2audio_dma_push_frag()
414 ret = chip->channel[ch].size >= runtime->period_size; in snd_sgio2audio_dma_push_frag()
415 chip->channel[ch].size %= runtime->period_size; in snd_sgio2audio_dma_push_frag()
429 count -= sizeof(u64); in snd_sgio2audio_dma_push_frag()
432 writeq(dst_pos, &mace->perif.audio.chan[ch].write_ptr); /* in bytes */ in snd_sgio2audio_dma_push_frag()
433 chip->channel[ch].pos = src_pos; in snd_sgio2audio_dma_push_frag()
435 spin_unlock_irqrestore(&chip->channel[ch].lock, flags); in snd_sgio2audio_dma_push_frag()
442 struct snd_sgio2audio_chan *chan = substream->runtime->private_data; in snd_sgio2audio_dma_start()
443 int ch = chan->idx; in snd_sgio2audio_dma_start()
445 /* reset DMA channel */ in snd_sgio2audio_dma_start()
446 writeq(CHANNEL_CONTROL_RESET, &mace->perif.audio.chan[ch].control); in snd_sgio2audio_dma_start()
448 writeq(0, &mace->perif.audio.chan[ch].control); in snd_sgio2audio_dma_start()
450 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in snd_sgio2audio_dma_start()
452 snd_sgio2audio_dma_push_frag(chip, ch, CHANNEL_RING_SIZE - 32); in snd_sgio2audio_dma_start()
456 &mace->perif.audio.chan[ch].control); in snd_sgio2audio_dma_start()
462 struct snd_sgio2audio_chan *chan = substream->runtime->private_data; in snd_sgio2audio_dma_stop()
464 writeq(0, &mace->perif.audio.chan[chan->idx].control); in snd_sgio2audio_dma_stop()
475 substream = chan->substream; in snd_sgio2audio_dma_in_isr()
477 ch = chan->idx; in snd_sgio2audio_dma_in_isr()
480 count = CHANNEL_RING_SIZE - in snd_sgio2audio_dma_in_isr()
481 readq(&mace->perif.audio.chan[ch].depth) - 32; in snd_sgio2audio_dma_in_isr()
495 substream = chan->substream; in snd_sgio2audio_dma_out_isr()
497 ch = chan->idx; in snd_sgio2audio_dma_out_isr()
499 count = CHANNEL_RING_SIZE - in snd_sgio2audio_dma_out_isr()
500 readq(&mace->perif.audio.chan[ch].depth) - 32; in snd_sgio2audio_dma_out_isr()
512 substream = chan->substream; in snd_sgio2audio_error_isr()
542 struct snd_pcm_runtime *runtime = substream->runtime; in snd_sgio2audio_playback1_open()
544 runtime->hw = snd_sgio2audio_pcm_hw; in snd_sgio2audio_playback1_open()
545 runtime->private_data = &chip->channel[1]; in snd_sgio2audio_playback1_open()
552 struct snd_pcm_runtime *runtime = substream->runtime; in snd_sgio2audio_playback2_open()
554 runtime->hw = snd_sgio2audio_pcm_hw; in snd_sgio2audio_playback2_open()
555 runtime->private_data = &chip->channel[2]; in snd_sgio2audio_playback2_open()
563 struct snd_pcm_runtime *runtime = substream->runtime; in snd_sgio2audio_capture_open()
565 runtime->hw = snd_sgio2audio_pcm_hw; in snd_sgio2audio_capture_open()
566 runtime->private_data = &chip->channel[0]; in snd_sgio2audio_capture_open()
573 struct snd_pcm_runtime *runtime = substream->runtime; in snd_sgio2audio_pcm_close()
575 runtime->private_data = NULL; in snd_sgio2audio_pcm_close()
583 struct snd_pcm_runtime *runtime = substream->runtime; in snd_sgio2audio_pcm_prepare()
584 struct snd_sgio2audio_chan *chan = substream->runtime->private_data; in snd_sgio2audio_pcm_prepare()
585 int ch = chan->idx; in snd_sgio2audio_pcm_prepare()
588 spin_lock_irqsave(&chip->channel[ch].lock, flags); in snd_sgio2audio_pcm_prepare()
590 /* Setup the pseudo-dma transfer pointers. */ in snd_sgio2audio_pcm_prepare()
591 chip->channel[ch].pos = 0; in snd_sgio2audio_pcm_prepare()
592 chip->channel[ch].size = 0; in snd_sgio2audio_pcm_prepare()
593 chip->channel[ch].substream = substream; in snd_sgio2audio_pcm_prepare()
597 switch (substream->stream) { in snd_sgio2audio_pcm_prepare()
599 ad1843_setup_dac(&chip->ad1843, in snd_sgio2audio_pcm_prepare()
600 ch - 1, in snd_sgio2audio_pcm_prepare()
601 runtime->rate, in snd_sgio2audio_pcm_prepare()
603 runtime->channels); in snd_sgio2audio_pcm_prepare()
606 ad1843_setup_adc(&chip->ad1843, in snd_sgio2audio_pcm_prepare()
607 runtime->rate, in snd_sgio2audio_pcm_prepare()
609 runtime->channels); in snd_sgio2audio_pcm_prepare()
612 spin_unlock_irqrestore(&chip->channel[ch].lock, flags); in snd_sgio2audio_pcm_prepare()
630 return -EINVAL; in snd_sgio2audio_pcm_trigger()
640 struct snd_sgio2audio_chan *chan = substream->runtime->private_data; in snd_sgio2audio_pcm_pointer()
643 return bytes_to_frames(substream->runtime, in snd_sgio2audio_pcm_pointer()
644 chip->channel[chan->idx].pos); in snd_sgio2audio_pcm_pointer()
683 err = snd_pcm_new(chip->card, "SGI O2 Audio", 0, 1, 1, &pcm); in snd_sgio2audio_new_pcm()
687 pcm->private_data = chip; in snd_sgio2audio_new_pcm()
688 strcpy(pcm->name, "SGI O2 DAC1"); in snd_sgio2audio_new_pcm()
698 err = snd_pcm_new(chip->card, "SGI O2 Audio", 1, 1, 0, &pcm); in snd_sgio2audio_new_pcm()
702 pcm->private_data = chip; in snd_sgio2audio_new_pcm()
703 strcpy(pcm->name, "SGI O2 DAC2"); in snd_sgio2audio_new_pcm()
723 .desc = "Capture DMA Channel 0"
733 .desc = "Playback DMA Channel 1"
738 .desc = "Memory Error Channel 1"
743 .desc = "Playback DMA Channel 2"
748 .desc = "Memory Error Channel 2"
759 writeq(AUDIO_CONTROL_RESET, &mace->perif.audio.control); in snd_sgio2audio_free()
761 writeq(0, &mace->perif.audio.control); in snd_sgio2audio_free()
766 &chip->channel[snd_sgio2_isr_table[i].idx]); in snd_sgio2audio_free()
768 dma_free_coherent(chip->card->dev, MACEISA_RINGBUFFERS_SIZE, in snd_sgio2audio_free()
769 chip->ring_base, chip->ring_base_dma); in snd_sgio2audio_free()
778 struct snd_sgio2audio *chip = device->device_data; in snd_sgio2audio_dev_free()
796 /* (Audio or Audio/Video board present) */ in snd_sgio2audio_create()
797 if (!(readq(&mace->perif.audio.control) & AUDIO_CONTROL_CODEC_PRESENT)) in snd_sgio2audio_create()
798 return -ENOENT; in snd_sgio2audio_create()
802 return -ENOMEM; in snd_sgio2audio_create()
804 chip->card = card; in snd_sgio2audio_create()
806 chip->ring_base = dma_alloc_coherent(card->dev, in snd_sgio2audio_create()
808 &chip->ring_base_dma, GFP_KERNEL); in snd_sgio2audio_create()
809 if (chip->ring_base == NULL) { in snd_sgio2audio_create()
813 return -ENOMEM; in snd_sgio2audio_create()
816 spin_lock_init(&chip->ad1843_lock); in snd_sgio2audio_create()
820 spin_lock_init(&chip->channel[i].lock); in snd_sgio2audio_create()
821 chip->channel[i].idx = i; in snd_sgio2audio_create()
830 &chip->channel[snd_sgio2_isr_table[i].idx])) { in snd_sgio2audio_create()
834 return -EBUSY; in snd_sgio2audio_create()
839 writeq(AUDIO_CONTROL_RESET, &mace->perif.audio.control); in snd_sgio2audio_create()
841 writeq(0, &mace->perif.audio.control); in snd_sgio2audio_create()
845 writeq(chip->ring_base_dma, &mace->perif.ctrl.ringbase); in snd_sgio2audio_create()
848 chip->ad1843.read = read_ad1843_reg; in snd_sgio2audio_create()
849 chip->ad1843.write = write_ad1843_reg; in snd_sgio2audio_create()
850 chip->ad1843.chip = chip; in snd_sgio2audio_create()
853 err = ad1843_init(&chip->ad1843); in snd_sgio2audio_create()
874 err = snd_card_new(&pdev->dev, index, id, THIS_MODULE, 0, &card); in snd_sgio2audio_probe()
895 strcpy(card->driver, "SGI O2 Audio"); in snd_sgio2audio_probe()
896 strcpy(card->shortname, "SGI O2 Audio"); in snd_sgio2audio_probe()
897 sprintf(card->longname, "%s irq %i-%i", in snd_sgio2audio_probe()
898 card->shortname, in snd_sgio2audio_probe()