^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Driver p16v chips
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Version: 0.25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * FEATURES currently supported:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Output fixed at S32_LE, 2 channel to hw:0,0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Rates: 44.1, 48, 96, 192.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Changelog:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * 0.8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Use separate card based buffer for periods table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * 0.9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Use 2 channel output streams instead of 8 channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * (8 channel output streams might be good for ASIO type output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Corrected speaker output, so Front -> Front etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * 0.10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Fixed missed interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * 0.11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Add Sound card model number and names.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Add Analog volume controls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * 0.12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Corrected playback interrupts. Now interrupt per period, instead of half period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 0.13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Use single trigger for multichannel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 0.14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * 0.15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Force buffer_size / period_size == INTEGER.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * 0.16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * Update p16v.c to work with changed alsa api.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * 0.17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * Update p16v.c to work with changed alsa api. Removed boot_devs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * 0.18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * Merging with snd-emu10k1 driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * 0.19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * One stereo channel at 24bit now works.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * 0.20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Added better register defines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * 0.21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Integrated with snd-emu10k1 driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * 0.22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * Removed #if 0 ... #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * 0.23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Implement different capture rates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * 0.24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * Implement different capture source channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * e.g. When HD Capture source is set to SPDIF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * setting HD Capture channel to 0 captures from CDROM digital input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * setting HD Capture channel to 1 captures from SPDIF in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * 0.25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * Include capture buffer sizes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * BUGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Some stability problems when unloading the snd-p16v kernel module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * SPDIF out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * Currently capture fixed at 48000Hz.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * GENERAL INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Model: SB0240
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * P16V Chip: CA0151-DBS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * Audigy 2 Chip: CA0102-IAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * AC97 Codec: STAC 9721
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * ADC: Philips 1361T (Stereo 24bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * DAC: CS4382-K (8-channel, 24bit, 192Khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * This code was initially based on code from ALSA's emu10k1x.c which is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #include <sound/ac97_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #include <sound/info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #include <sound/emu10k1.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #include "p16v.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define PCM_FRONT_CHANNEL 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define PCM_REAR_CHANNEL 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define PCM_CENTER_LFE_CHANNEL 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define PCM_SIDE_CHANNEL 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define CONTROL_FRONT_CHANNEL 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define CONTROL_REAR_CHANNEL 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define CONTROL_CENTER_LFE_CHANNEL 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define CONTROL_SIDE_CHANNEL 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* Card IDs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2002 -> Audigy2 ZS 7.1 Model:SB0350
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1007 -> Audigy2 6.1 Model:SB0240
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1002 -> Audigy2 Platinum Model:SB msb0240230009266
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2007 -> Audigy4 Pro Model:SB0380 M1SB0380472001901E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* hardware definition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static const struct snd_pcm_hardware snd_p16v_playback_hw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .info = SNDRV_PCM_INFO_MMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) SNDRV_PCM_INFO_RESUME |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) SNDRV_PCM_INFO_SYNC_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .rate_min = 44100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .rate_max = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .channels_min = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .channels_max = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .buffer_bytes_max = ((65536 - 64) * 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .period_bytes_min = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .period_bytes_max = (65536 - 64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .periods_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .periods_max = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .fifo_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static const struct snd_pcm_hardware snd_p16v_capture_hw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .info = (SNDRV_PCM_INFO_MMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) SNDRV_PCM_INFO_RESUME |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) SNDRV_PCM_INFO_MMAP_VALID),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .formats = SNDRV_PCM_FMTBIT_S32_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .rate_min = 44100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .rate_max = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .channels_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .buffer_bytes_max = (65536 - 64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .period_bytes_min = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .period_bytes_max = (65536 - 128) >> 1, /* size has to be N*64 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .periods_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .periods_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .fifo_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct snd_emu10k1_pcm *epcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) kfree(epcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* open_playback callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct snd_emu10k1_voice *channel = &(emu->p16v_voices[channel_id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct snd_emu10k1_pcm *epcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (epcm == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) epcm->emu = emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) epcm->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) substream->pcm->device, channel_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) runtime->private_data = epcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) runtime->private_free = snd_p16v_pcm_free_substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) runtime->hw = snd_p16v_playback_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) channel->emu = emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) channel->number = channel_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) channel->use=1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #if 0 /* debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dev_dbg(emu->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) "p16v: open channel_id=%d, channel=%p, use=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) channel_id, channel, channel->use);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) dev_dbg(emu->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) channel_id, chip, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #endif /* debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) channel->epcm = epcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) runtime->sync.id32[0] = substream->pcm->card->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) runtime->sync.id32[1] = 'P';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) runtime->sync.id32[2] = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) runtime->sync.id32[3] = 'V';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* open_capture callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream, int channel_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct snd_emu10k1_voice *channel = &(emu->p16v_capture_voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct snd_emu10k1_pcm *epcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (epcm == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) epcm->emu = emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) epcm->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) substream->pcm->device, channel_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) runtime->private_data = epcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) runtime->private_free = snd_p16v_pcm_free_substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) runtime->hw = snd_p16v_capture_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) channel->emu = emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) channel->number = channel_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) channel->use=1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #if 0 /* debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) dev_dbg(emu->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) "p16v: open channel_id=%d, channel=%p, use=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) channel_id, channel, channel->use);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) dev_dbg(emu->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) channel_id, chip, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #endif /* debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) channel->epcm = epcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* close callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) //struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) //struct snd_emu10k1_pcm *epcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* FIXME: maybe zero others */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* close callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) //struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) //struct snd_emu10k1_pcm *epcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) emu->p16v_capture_voice.use = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* FIXME: maybe zero others */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static int snd_p16v_pcm_open_playback_front(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static int snd_p16v_pcm_open_capture(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) // Only using channel 0 for now, but the card has 2 channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return snd_p16v_pcm_open_capture_channel(substream, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* prepare playback callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) int channel = substream->pcm->device - emu->p16v_device_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) #if 0 /* debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) dev_dbg(emu->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) "prepare:channel_number=%d, rate=%d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) "format=0x%x, channels=%d, buffer_size=%ld, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) "period_size=%ld, periods=%u, frames_to_bytes=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) channel, runtime->rate, runtime->format, runtime->channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) runtime->buffer_size, runtime->period_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) runtime->periods, frames_to_bytes(runtime, 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) dev_dbg(emu->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) "dma_addr=%x, dma_area=%p, table_base=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) runtime->dma_addr, runtime->dma_area, table_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) dev_dbg(emu->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) emu->p16v_buffer.addr, emu->p16v_buffer.area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) emu->p16v_buffer.bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) #endif /* debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) switch (runtime->rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) case 44100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) case 96000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) case 192000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) case 48000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* FIXME: Check emu->buffer.size before actually writing to it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) for(i = 0; i < runtime->periods; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) table_base[(i*2)+1]=period_size_bytes<<16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* prepare capture callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) int channel = substream->pcm->device - emu->p16v_device_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dev_dbg(emu->card->dev, "prepare capture:channel_number=%d, rate=%d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) "format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) "frames_to_bytes=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) channel, runtime->rate, runtime->format, runtime->channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) runtime->buffer_size, runtime->period_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) frames_to_bytes(runtime, 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) switch (runtime->rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) case 44100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) case 96000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) case 192000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) case 48000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* FIXME: Check emu->buffer.size before actually writing to it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size) << 16); // buffer size in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static void snd_p16v_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) unsigned int enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) enable = inl(emu->port + INTE2) | intrenb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) outl(enable, emu->port + INTE2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static void snd_p16v_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) unsigned int disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) disable = inl(emu->port + INTE2) & (~intrenb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) outl(disable, emu->port + INTE2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* trigger_playback callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct snd_pcm_runtime *runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct snd_emu10k1_pcm *epcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) struct snd_pcm_substream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) u32 basic = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) u32 inte = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) int running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) running=1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) snd_pcm_group_for_each_entry(s, substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (snd_pcm_substream_chip(s) != emu ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) s->stream != SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) runtime = s->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) epcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) channel = substream->pcm->device-emu->p16v_device_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) /* dev_dbg(emu->card->dev, "p16v channel=%d\n", channel); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) epcm->running = running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) basic |= (0x1<<channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) snd_pcm_trigger_done(s, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* dev_dbg(emu->card->dev, "basic=0x%x, inte=0x%x\n", basic, inte); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) snd_p16v_intr_enable(emu, inte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)| (basic));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) snd_p16v_intr_disable(emu, inte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* trigger_capture callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static int snd_p16v_pcm_trigger_capture(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct snd_emu10k1_pcm *epcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) int channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) snd_p16v_intr_enable(emu, inte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) epcm->running = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) snd_p16v_intr_disable(emu, inte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) epcm->running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /* pointer_playback callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static snd_pcm_uframes_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) snd_p16v_pcm_pointer_playback(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct snd_emu10k1_pcm *epcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int channel = substream->pcm->device - emu->p16v_device_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (!epcm->running)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ptr4 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (ptr3 != ptr4) ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) ptr2 = bytes_to_frames(runtime, ptr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) ptr2+= (ptr4 >> 3) * runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) ptr=ptr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (ptr >= runtime->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ptr -= runtime->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /* pointer_capture callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) static snd_pcm_uframes_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct snd_emu10k1_pcm *epcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (!epcm->running)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ptr2 = bytes_to_frames(runtime, ptr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ptr=ptr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (ptr >= runtime->buffer_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) ptr -= runtime->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) dev_warn(emu->card->dev, "buffer capture limited!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) dev_dbg(emu->card->dev, "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ptr1, ptr2, ptr, (int)runtime->buffer_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) (int)runtime->period_size, (int)runtime->frame_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) (int)runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /* operators */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static const struct snd_pcm_ops snd_p16v_playback_front_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) .open = snd_p16v_pcm_open_playback_front,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) .close = snd_p16v_pcm_close_playback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) .prepare = snd_p16v_pcm_prepare_playback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) .trigger = snd_p16v_pcm_trigger_playback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) .pointer = snd_p16v_pcm_pointer_playback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static const struct snd_pcm_ops snd_p16v_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) .open = snd_p16v_pcm_open_capture,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) .close = snd_p16v_pcm_close_capture,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) .prepare = snd_p16v_pcm_prepare_capture,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) .trigger = snd_p16v_pcm_trigger_capture,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) .pointer = snd_p16v_pcm_pointer_capture,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int snd_p16v_free(struct snd_emu10k1 *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) // release the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (chip->p16v_buffer.area) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) snd_dma_free_pages(&chip->p16v_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) dev_dbg(chip->card->dev, "period lables free: %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) &chip->p16v_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) int capture=1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* dev_dbg(emu->card->dev, "snd_p16v_pcm called. device=%d\n", device); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) emu->p16v_device_offset = device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) pcm->private_data = emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) // Single playback 8 channel device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) // Single capture 2 channel device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) strcpy(pcm->name, "p16v");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) emu->pcm_p16v = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) substream = substream->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) &emu->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) (65536 - 64) * 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) (65536 - 64) * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) dev_dbg(emu->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) "preallocate playback substream: err=%d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) substream = substream->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) &emu->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 65536 - 64, 65536 - 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) dev_dbg(emu->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) "preallocate capture substream: err=%d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static int snd_p16v_volume_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) uinfo->value.integer.max = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) static int snd_p16v_volume_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) int high_low = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) int reg = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) value = snd_emu10k1_ptr20_read(emu, reg, high_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (high_low) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ucontrol->value.integer.value[0] = 0xff - ((value >> 8) & 0xff); /* Left */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ucontrol->value.integer.value[1] = 0xff - ((value >> 0) & 0xff); /* Right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static int snd_p16v_volume_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) int high_low = (kcontrol->private_value >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) int reg = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) u32 value, oval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) oval = value = snd_emu10k1_ptr20_read(emu, reg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (high_low == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) value &= 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) value |= ((0xff - ucontrol->value.integer.value[0]) << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) ((0xff - ucontrol->value.integer.value[1]) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) value &= 0xffff0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) value |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) ((0xff - ucontrol->value.integer.value[1]) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (value != oval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) snd_emu10k1_ptr20_write(emu, reg, 0, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) static int snd_p16v_capture_source_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static const char * const texts[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) "CDIF", "FX", "AC97"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return snd_ctl_enum_info(uinfo, 1, 8, texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static int snd_p16v_capture_source_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) ucontrol->value.enumerated.item[0] = emu->p16v_capture_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) static int snd_p16v_capture_source_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) u32 source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) val = ucontrol->value.enumerated.item[0] ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (val > 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) change = (emu->p16v_capture_source != val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) emu->p16v_capture_source = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) static int snd_p16v_capture_channel_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static const char * const texts[4] = { "0", "1", "2", "3", };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return snd_ctl_enum_info(uinfo, 1, 4, texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) static int snd_p16v_capture_channel_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) val = ucontrol->value.enumerated.item[0] ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (val > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) change = (emu->p16v_capture_channel != val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) emu->p16v_capture_channel = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) #define P16V_VOL(xname,xreg,xhl) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .info = snd_p16v_volume_info, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) .get = snd_p16v_volume_get, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .put = snd_p16v_volume_put, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .tlv = { .p = snd_p16v_db_scale1 }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) .private_value = ((xreg) | ((xhl) << 8)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) static const struct snd_kcontrol_new p16v_mixer_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) P16V_VOL("HD Analog Side Playback Volume", PLAYBACK_VOLUME_MIXER10, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) P16V_VOL("HD SPDIF Front Playback Volume", PLAYBACK_VOLUME_MIXER7, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) P16V_VOL("HD SPDIF Rear Playback Volume", PLAYBACK_VOLUME_MIXER8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) P16V_VOL("HD SPDIF Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER7, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) P16V_VOL("HD SPDIF Side Playback Volume", PLAYBACK_VOLUME_MIXER8, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .name = "HD source Capture",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .info = snd_p16v_capture_source_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .get = snd_p16v_capture_source_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .put = snd_p16v_capture_source_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) .name = "HD channel Capture",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .info = snd_p16v_capture_channel_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .get = snd_p16v_capture_channel_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .put = snd_p16v_capture_channel_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) int snd_p16v_mixer(struct snd_emu10k1 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) struct snd_card *card = emu->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) for (i = 0; i < ARRAY_SIZE(p16v_mixer_controls); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if ((err = snd_ctl_add(card, snd_ctl_new1(&p16v_mixer_controls[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) emu))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) #define NUM_CHS 1 /* up to 4, but only first channel is used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) int snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) emu->p16v_saved = vmalloc(array_size(NUM_CHS * 4, 0x80));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (! emu->p16v_saved)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) void snd_p16v_free_pm_buffer(struct snd_emu10k1 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) vfree(emu->p16v_saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) void snd_p16v_suspend(struct snd_emu10k1 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) int i, ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) unsigned int *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) val = emu->p16v_saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) for (ch = 0; ch < NUM_CHS; ch++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) for (i = 0; i < 0x80; i++, val++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) *val = snd_emu10k1_ptr20_read(emu, i, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) void snd_p16v_resume(struct snd_emu10k1 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) int i, ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) unsigned int *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) val = emu->p16v_saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) for (ch = 0; ch < NUM_CHS; ch++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) for (i = 0; i < 0x80; i++, val++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) snd_emu10k1_ptr20_write(emu, i, ch, *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) #endif