Lines Matching +full:8 +full:- +full:channel
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
8 * Output fixed at S32_LE, 2 channel to hw:0,0
15 * Use 2 channel output streams instead of 8 channel.
16 * (8 channel output streams might be good for ASIO type output)
17 * Corrected speaker output, so Front -> Front etc.
36 * Merging with snd-emu10k1 driver.
38 * One stereo channel at 24bit now works.
42 * Integrated with snd-emu10k1 driver.
50 * setting HD Capture channel to 0 captures from CDROM digital input.
51 * setting HD Capture channel to 1 captures from SPDIF in.
56 * Some stability problems when unloading the snd-p16v kernel module.
57 * --
64 * --
67 * P16V Chip: CA0151-DBS
68 * Audigy 2 Chip: CA0102-IAT
71 * DAC: CS4382-K (8-channel, 24bit, 192Khz)
92 #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
103 * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2002 -> Audigy2 ZS 7.1 Model:SB0350
104 * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1007 -> Audigy2 6.1 Model:SB0240
105 …* Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1002 -> Audigy2 Platinum Model:SB msb02402300092…
106 …* Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2007 -> Audigy4 Pro Model:SB0380 M1SB038047200190…
118 .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
122 .channels_min = 8,
123 .channels_max = 8,
124 .buffer_bytes_max = ((65536 - 64) * 8),
126 .period_bytes_max = (65536 - 64),
128 .periods_max = 8,
144 .buffer_bytes_max = (65536 - 64),
146 .period_bytes_max = (65536 - 128) >> 1, /* size has to be N*64 bytes */
155 struct snd_pcm_runtime *runtime = substream->runtime; in snd_p16v_pcm_open_playback_channel()
159 dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n", in snd_p16v_pcm_open_playback_channel()
160 substream->pcm->device, channel_id); in snd_p16v_pcm_open_playback_channel()
163 runtime->hw = snd_p16v_playback_hw; in snd_p16v_pcm_open_playback_channel()
166 dev_dbg(emu->card->dev, in snd_p16v_pcm_open_playback_channel()
167 "p16v: open channel_id=%d, channel=%p, use=0x%x\n", in snd_p16v_pcm_open_playback_channel()
168 channel_id, channel, channel->use); in snd_p16v_pcm_open_playback_channel()
169 dev_dbg(emu->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n", in snd_p16v_pcm_open_playback_channel()
170 channel_id, chip, channel); in snd_p16v_pcm_open_playback_channel()
172 /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ in snd_p16v_pcm_open_playback_channel()
183 struct snd_pcm_runtime *runtime = substream->runtime; in snd_p16v_pcm_open_capture_channel()
187 dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n", in snd_p16v_pcm_open_capture_channel()
188 substream->pcm->device, channel_id); in snd_p16v_pcm_open_capture_channel()
191 runtime->hw = snd_p16v_capture_hw; in snd_p16v_pcm_open_capture_channel()
220 // Only using channel 0 for now, but the card has 2 channels. in snd_p16v_pcm_open_capture()
239 struct snd_pcm_runtime *runtime = substream->runtime; in snd_p16v_pcm_prepare_playback()
240 int channel = substream->pcm->device - emu->p16v_device_offset; in snd_p16v_pcm_prepare_playback() local
241 u32 *table_base = (u32 *)(emu->p16v_buffer->area+(8*16*channel)); in snd_p16v_pcm_prepare_playback()
242 u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); in snd_p16v_pcm_prepare_playback()
247 dev_dbg(emu->card->dev, in snd_p16v_pcm_prepare_playback()
251 channel, runtime->rate, runtime->format, runtime->channels, in snd_p16v_pcm_prepare_playback()
252 runtime->buffer_size, runtime->period_size, in snd_p16v_pcm_prepare_playback()
253 runtime->periods, frames_to_bytes(runtime, 1)); in snd_p16v_pcm_prepare_playback()
254 dev_dbg(emu->card->dev, in snd_p16v_pcm_prepare_playback()
256 runtime->dma_addr, runtime->dma_area, table_base); in snd_p16v_pcm_prepare_playback()
257 dev_dbg(emu->card->dev, in snd_p16v_pcm_prepare_playback()
259 emu->p16v_buffer->addr, emu->p16v_buffer->area, in snd_p16v_pcm_prepare_playback()
260 emu->p16v_buffer->bytes); in snd_p16v_pcm_prepare_playback()
262 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); in snd_p16v_pcm_prepare_playback()
264 switch (runtime->rate) { in snd_p16v_pcm_prepare_playback()
266 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, in snd_p16v_pcm_prepare_playback()
270 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, in snd_p16v_pcm_prepare_playback()
274 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, in snd_p16v_pcm_prepare_playback()
279 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, in snd_p16v_pcm_prepare_playback()
283 /* FIXME: Check emu->buffer.size before actually writing to it. */ in snd_p16v_pcm_prepare_playback()
284 for(i = 0; i < runtime->periods; i++) { in snd_p16v_pcm_prepare_playback()
285 table_base[i*2]=runtime->dma_addr+(i*period_size_bytes); in snd_p16v_pcm_prepare_playback()
289 snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer->addr+(8*16*channel)); in snd_p16v_pcm_prepare_playback()
290 snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19); in snd_p16v_pcm_prepare_playback()
291 snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0); in snd_p16v_pcm_prepare_playback()
292 snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr); in snd_p16v_pcm_prepare_playback()
293 …//snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->pe… in snd_p16v_pcm_prepare_playback()
294 snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes in snd_p16v_pcm_prepare_playback()
295 snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0); in snd_p16v_pcm_prepare_playback()
296 snd_emu10k1_ptr20_write(emu, PLAYBACK_FIFO_END_ADDRESS, channel, 0); in snd_p16v_pcm_prepare_playback()
297 snd_emu10k1_ptr20_write(emu, PLAYBACK_FIFO_POINTER, channel, 0); in snd_p16v_pcm_prepare_playback()
306 struct snd_pcm_runtime *runtime = substream->runtime; in snd_p16v_pcm_prepare_capture()
307 int channel = substream->pcm->device - emu->p16v_device_offset; in snd_p16v_pcm_prepare_capture() local
310 dev_dbg(emu->card->dev, "prepare capture:channel_number=%d, rate=%d, " in snd_p16v_pcm_prepare_capture()
313 channel, runtime->rate, runtime->format, runtime->channels, in snd_p16v_pcm_prepare_capture()
314 runtime->buffer_size, runtime->period_size, in snd_p16v_pcm_prepare_capture()
317 switch (runtime->rate) { in snd_p16v_pcm_prepare_capture()
319 snd_emu10k1_ptr_write(emu, A_I2S_CAPTURE_RATE, channel, A_I2S_CAPTURE_44100); in snd_p16v_pcm_prepare_capture()
322 snd_emu10k1_ptr_write(emu, A_I2S_CAPTURE_RATE, channel, A_I2S_CAPTURE_96000); in snd_p16v_pcm_prepare_capture()
325 snd_emu10k1_ptr_write(emu, A_I2S_CAPTURE_RATE, channel, A_I2S_CAPTURE_192000); in snd_p16v_pcm_prepare_capture()
329 snd_emu10k1_ptr_write(emu, A_I2S_CAPTURE_RATE, channel, A_I2S_CAPTURE_48000); in snd_p16v_pcm_prepare_capture()
332 /* FIXME: Check emu->buffer.size before actually writing to it. */ in snd_p16v_pcm_prepare_capture()
333 snd_emu10k1_ptr20_write(emu, CAPTURE_FIFO_POINTER, channel, 0); in snd_p16v_pcm_prepare_capture()
334 snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); in snd_p16v_pcm_prepare_capture()
335 …snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffe… in snd_p16v_pcm_prepare_capture()
336 snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0); in snd_p16v_pcm_prepare_capture()
338 …mu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel)); in snd_p16v_pcm_prepare_capture()
348 spin_lock_irqsave(&emu->emu_lock, flags); in snd_p16v_intr_enable()
349 enable = inl(emu->port + INTE2) | intrenb; in snd_p16v_intr_enable()
350 outl(enable, emu->port + INTE2); in snd_p16v_intr_enable()
351 spin_unlock_irqrestore(&emu->emu_lock, flags); in snd_p16v_intr_enable()
359 spin_lock_irqsave(&emu->emu_lock, flags); in snd_p16v_intr_disable()
360 disable = inl(emu->port + INTE2) & (~intrenb); in snd_p16v_intr_disable()
361 outl(disable, emu->port + INTE2); in snd_p16v_intr_disable()
362 spin_unlock_irqrestore(&emu->emu_lock, flags); in snd_p16v_intr_disable()
369 while ((status = inl(emu->port + IPR2)) != 0) { in snd_p16v_interrupt()
372 /* dev_dbg(emu->card->dev, "p16v status=0x%x\n", status); */ in snd_p16v_interrupt()
375 emu->pcm_p16v->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; in snd_p16v_interrupt()
376 struct snd_pcm_runtime *runtime = substream->runtime; in snd_p16v_interrupt()
378 if (runtime && runtime->private_data) { in snd_p16v_interrupt()
381 dev_err(emu->card->dev, in snd_p16v_interrupt()
388 emu->pcm_p16v->streams[SNDRV_PCM_STREAM_CAPTURE].substream; in snd_p16v_interrupt()
389 struct snd_pcm_runtime *runtime = substream->runtime; in snd_p16v_interrupt()
391 /* dev_info(emu->card->dev, "capture int found\n"); */ in snd_p16v_interrupt()
392 if (runtime && runtime->private_data) { in snd_p16v_interrupt()
393 /* dev_info(emu->card->dev, "capture period_elapsed\n"); */ in snd_p16v_interrupt()
397 outl(status, emu->port + IPR2); /* ack all */ in snd_p16v_interrupt()
407 int channel; in snd_p16v_pcm_trigger_playback() local
425 s->stream != SNDRV_PCM_STREAM_PLAYBACK) in snd_p16v_pcm_trigger_playback()
427 runtime = s->runtime; in snd_p16v_pcm_trigger_playback()
428 channel = substream->pcm->device-emu->p16v_device_offset; in snd_p16v_pcm_trigger_playback()
429 /* dev_dbg(emu->card->dev, "p16v channel=%d\n", channel); */ in snd_p16v_pcm_trigger_playback()
430 runtime->private_data = (void *)(ptrdiff_t)running; in snd_p16v_pcm_trigger_playback()
431 basic |= (0x1<<channel); in snd_p16v_pcm_trigger_playback()
432 inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel); in snd_p16v_pcm_trigger_playback()
435 /* dev_dbg(emu->card->dev, "basic=0x%x, inte=0x%x\n", basic, inte); */ in snd_p16v_pcm_trigger_playback()
447 result = -EINVAL; in snd_p16v_pcm_trigger_playback()
458 struct snd_pcm_runtime *runtime = substream->runtime; in snd_p16v_pcm_trigger_capture()
459 int channel = 0; in snd_p16v_pcm_trigger_capture() local
466 …0_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel)); in snd_p16v_pcm_trigger_capture()
467 runtime->private_data = (void *)1; in snd_p16v_pcm_trigger_capture()
470 …rite(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel)); in snd_p16v_pcm_trigger_capture()
472 …u, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel)); in snd_p16v_pcm_trigger_capture()
473 runtime->private_data = NULL; in snd_p16v_pcm_trigger_capture()
476 result = -EINVAL; in snd_p16v_pcm_trigger_capture()
487 struct snd_pcm_runtime *runtime = substream->runtime; in snd_p16v_pcm_pointer_playback()
489 int channel = substream->pcm->device - emu->p16v_device_offset; in snd_p16v_pcm_pointer_playback() local
491 if (!runtime->private_data) in snd_p16v_pcm_pointer_playback()
494 ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel); in snd_p16v_pcm_pointer_playback()
495 ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel); in snd_p16v_pcm_pointer_playback()
496 ptr4 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel); in snd_p16v_pcm_pointer_playback()
497 if (ptr3 != ptr4) ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel); in snd_p16v_pcm_pointer_playback()
499 ptr2+= (ptr4 >> 3) * runtime->period_size; in snd_p16v_pcm_pointer_playback()
501 if (ptr >= runtime->buffer_size) in snd_p16v_pcm_pointer_playback()
502 ptr -= runtime->buffer_size; in snd_p16v_pcm_pointer_playback()
512 struct snd_pcm_runtime *runtime = substream->runtime; in snd_p16v_pcm_pointer_capture()
514 int channel = 0; in snd_p16v_pcm_pointer_capture() local
516 if (!runtime->private_data) in snd_p16v_pcm_pointer_capture()
519 ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel); in snd_p16v_pcm_pointer_capture()
522 if (ptr >= runtime->buffer_size) { in snd_p16v_pcm_pointer_capture()
523 ptr -= runtime->buffer_size; in snd_p16v_pcm_pointer_capture()
524 dev_warn(emu->card->dev, "buffer capture limited!\n"); in snd_p16v_pcm_pointer_capture()
527 dev_dbg(emu->card->dev, "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " in snd_p16v_pcm_pointer_capture()
529 ptr1, ptr2, ptr, (int)runtime->buffer_size, in snd_p16v_pcm_pointer_capture()
530 (int)runtime->period_size, (int)runtime->frame_bits, in snd_p16v_pcm_pointer_capture()
531 (int)runtime->rate); in snd_p16v_pcm_pointer_capture()
561 /* dev_dbg(emu->card->dev, "snd_p16v_pcm called. device=%d\n", device); */ in snd_p16v_pcm()
562 emu->p16v_device_offset = device; in snd_p16v_pcm()
564 err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm); in snd_p16v_pcm()
568 pcm->private_data = emu; in snd_p16v_pcm()
569 // Single playback 8 channel device. in snd_p16v_pcm()
570 // Single capture 2 channel device. in snd_p16v_pcm()
574 pcm->info_flags = 0; in snd_p16v_pcm()
575 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; in snd_p16v_pcm()
576 strcpy(pcm->name, "p16v"); in snd_p16v_pcm()
577 emu->pcm_p16v = pcm; in snd_p16v_pcm()
578 emu->p16v_interrupt = snd_p16v_interrupt; in snd_p16v_pcm()
580 for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; in snd_p16v_pcm()
582 substream = substream->next) { in snd_p16v_pcm()
584 &emu->pci->dev, in snd_p16v_pcm()
585 (65536 - 64) * 8, in snd_p16v_pcm()
586 (65536 - 64) * 8); in snd_p16v_pcm()
588 dev_dbg(emu->card->dev, in snd_p16v_pcm()
593 for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; in snd_p16v_pcm()
595 substream = substream->next) { in snd_p16v_pcm()
597 &emu->pci->dev, in snd_p16v_pcm()
598 65536 - 64, 65536 - 64); in snd_p16v_pcm()
600 dev_dbg(emu->card->dev, in snd_p16v_pcm()
611 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in snd_p16v_volume_info()
612 uinfo->count = 2; in snd_p16v_volume_info()
613 uinfo->value.integer.min = 0; in snd_p16v_volume_info()
614 uinfo->value.integer.max = 255; in snd_p16v_volume_info()
622 int high_low = (kcontrol->private_value >> 8) & 0xff; in snd_p16v_volume_get()
623 int reg = kcontrol->private_value & 0xff; in snd_p16v_volume_get()
628 ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */ in snd_p16v_volume_get()
629 ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */ in snd_p16v_volume_get()
631 ucontrol->value.integer.value[0] = 0xff - ((value >> 8) & 0xff); /* Left */ in snd_p16v_volume_get()
632 ucontrol->value.integer.value[1] = 0xff - ((value >> 0) & 0xff); /* Right */ in snd_p16v_volume_get()
641 int high_low = (kcontrol->private_value >> 8) & 0xff; in snd_p16v_volume_put()
642 int reg = kcontrol->private_value & 0xff; in snd_p16v_volume_put()
648 value |= ((0xff - ucontrol->value.integer.value[0]) << 24) | in snd_p16v_volume_put()
649 ((0xff - ucontrol->value.integer.value[1]) << 16); in snd_p16v_volume_put()
652 value |= ((0xff - ucontrol->value.integer.value[0]) << 8) | in snd_p16v_volume_put()
653 ((0xff - ucontrol->value.integer.value[1]) ); in snd_p16v_volume_put()
665 static const char * const texts[8] = { in snd_p16v_capture_source_info()
670 return snd_ctl_enum_info(uinfo, 1, 8, texts); in snd_p16v_capture_source_info()
678 ucontrol->value.enumerated.item[0] = emu->p16v_capture_source; in snd_p16v_capture_source_get()
691 val = ucontrol->value.enumerated.item[0] ; in snd_p16v_capture_source_put()
693 return -EINVAL; in snd_p16v_capture_source_put()
694 change = (emu->p16v_capture_source != val); in snd_p16v_capture_source_put()
696 emu->p16v_capture_source = val; in snd_p16v_capture_source_put()
717 ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel; in snd_p16v_capture_channel_get()
729 val = ucontrol->value.enumerated.item[0] ; in snd_p16v_capture_channel_put()
731 return -EINVAL; in snd_p16v_capture_channel_put()
732 change = (emu->p16v_capture_channel != val); in snd_p16v_capture_channel_put()
734 emu->p16v_capture_channel = val; in snd_p16v_capture_channel_put()
740 static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
750 .private_value = ((xreg) | ((xhl) << 8)) \
771 .name = "HD channel Capture",
782 struct snd_card *card = emu->card; in snd_p16v_mixer()
794 #define NUM_CHS 1 /* up to 4, but only first channel is used */
798 emu->p16v_saved = vmalloc(array_size(NUM_CHS * 4, 0x80)); in snd_p16v_alloc_pm_buffer()
799 if (! emu->p16v_saved) in snd_p16v_alloc_pm_buffer()
800 return -ENOMEM; in snd_p16v_alloc_pm_buffer()
806 vfree(emu->p16v_saved); in snd_p16v_free_pm_buffer()
814 val = emu->p16v_saved; in snd_p16v_suspend()
825 val = emu->p16v_saved; in snd_p16v_resume()