Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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