cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

p16v.c (26950B)


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