Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
0004  *  Driver p16v chips
0005  *  Version: 0.25
0006  *
0007  *  FEATURES currently supported:
0008  *    Output fixed at S32_LE, 2 channel to hw:0,0
0009  *    Rates: 44.1, 48, 96, 192.
0010  *
0011  *  Changelog:
0012  *  0.8
0013  *    Use separate card based buffer for periods table.
0014  *  0.9
0015  *    Use 2 channel output streams instead of 8 channel.
0016  *       (8 channel output streams might be good for ASIO type output)
0017  *    Corrected speaker output, so Front -> Front etc.
0018  *  0.10
0019  *    Fixed missed interrupts.
0020  *  0.11
0021  *    Add Sound card model number and names.
0022  *    Add Analog volume controls.
0023  *  0.12
0024  *    Corrected playback interrupts. Now interrupt per period, instead of half period.
0025  *  0.13
0026  *    Use single trigger for multichannel.
0027  *  0.14
0028  *    Mic capture now works at fixed: S32_LE, 96000Hz, Stereo.
0029  *  0.15
0030  *    Force buffer_size / period_size == INTEGER.
0031  *  0.16
0032  *    Update p16v.c to work with changed alsa api.
0033  *  0.17
0034  *    Update p16v.c to work with changed alsa api. Removed boot_devs.
0035  *  0.18
0036  *    Merging with snd-emu10k1 driver.
0037  *  0.19
0038  *    One stereo channel at 24bit now works.
0039  *  0.20
0040  *    Added better register defines.
0041  *  0.21
0042  *    Integrated with snd-emu10k1 driver.
0043  *  0.22
0044  *    Removed #if 0 ... #endif
0045  *  0.23
0046  *    Implement different capture rates.
0047  *  0.24
0048  *    Implement different capture source channels.
0049  *    e.g. When HD Capture source is set to SPDIF,
0050  *    setting HD Capture channel to 0 captures from CDROM digital input.
0051  *    setting HD Capture channel to 1 captures from SPDIF in.
0052  *  0.25
0053  *    Include capture buffer sizes.
0054  *
0055  *  BUGS:
0056  *    Some stability problems when unloading the snd-p16v kernel module.
0057  *    --
0058  *
0059  *  TODO:
0060  *    SPDIF out.
0061  *    Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz.
0062  *    Currently capture fixed at 48000Hz.
0063  *
0064  *    --
0065  *  GENERAL INFO:
0066  *    Model: SB0240
0067  *    P16V Chip: CA0151-DBS
0068  *    Audigy 2 Chip: CA0102-IAT
0069  *    AC97 Codec: STAC 9721
0070  *    ADC: Philips 1361T (Stereo 24bit)
0071  *    DAC: CS4382-K (8-channel, 24bit, 192Khz)
0072  *
0073  *  This code was initially based on code from ALSA's emu10k1x.c which is:
0074  *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
0075  */
0076 #include <linux/delay.h>
0077 #include <linux/init.h>
0078 #include <linux/interrupt.h>
0079 #include <linux/pci.h>
0080 #include <linux/slab.h>
0081 #include <linux/vmalloc.h>
0082 #include <linux/moduleparam.h>
0083 #include <sound/core.h>
0084 #include <sound/initval.h>
0085 #include <sound/pcm.h>
0086 #include <sound/ac97_codec.h>
0087 #include <sound/info.h>
0088 #include <sound/tlv.h>
0089 #include <sound/emu10k1.h>
0090 #include "p16v.h"
0091 
0092 #define SET_CHANNEL 0  /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
0093 #define PCM_FRONT_CHANNEL 0
0094 #define PCM_REAR_CHANNEL 1
0095 #define PCM_CENTER_LFE_CHANNEL 2
0096 #define PCM_SIDE_CHANNEL 3
0097 #define CONTROL_FRONT_CHANNEL 0
0098 #define CONTROL_REAR_CHANNEL 3
0099 #define CONTROL_CENTER_LFE_CHANNEL 1
0100 #define CONTROL_SIDE_CHANNEL 2
0101 
0102 /* Card IDs:
0103  * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2002 -> Audigy2 ZS 7.1 Model:SB0350
0104  * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1007 -> Audigy2 6.1    Model:SB0240
0105  * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1002 -> Audigy2 Platinum  Model:SB msb0240230009266
0106  * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2007 -> Audigy4 Pro Model:SB0380 M1SB0380472001901E
0107  *
0108  */
0109 
0110  /* hardware definition */
0111 static const struct snd_pcm_hardware snd_p16v_playback_hw = {
0112     .info =         SNDRV_PCM_INFO_MMAP | 
0113                 SNDRV_PCM_INFO_INTERLEAVED |
0114                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
0115                 SNDRV_PCM_INFO_RESUME |
0116                 SNDRV_PCM_INFO_MMAP_VALID |
0117                 SNDRV_PCM_INFO_SYNC_START,
0118     .formats =      SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
0119     .rates =        SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, 
0120     .rate_min =     44100,
0121     .rate_max =     192000,
0122     .channels_min =     8, 
0123     .channels_max =     8,
0124     .buffer_bytes_max = ((65536 - 64) * 8),
0125     .period_bytes_min = 64,
0126     .period_bytes_max = (65536 - 64),
0127     .periods_min =      2,
0128     .periods_max =      8,
0129     .fifo_size =        0,
0130 };
0131 
0132 static const struct snd_pcm_hardware snd_p16v_capture_hw = {
0133     .info =         (SNDRV_PCM_INFO_MMAP |
0134                  SNDRV_PCM_INFO_INTERLEAVED |
0135                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
0136                  SNDRV_PCM_INFO_RESUME |
0137                  SNDRV_PCM_INFO_MMAP_VALID),
0138     .formats =      SNDRV_PCM_FMTBIT_S32_LE,
0139     .rates =        SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, 
0140     .rate_min =     44100,
0141     .rate_max =     192000,
0142     .channels_min =     2,
0143     .channels_max =     2,
0144     .buffer_bytes_max = (65536 - 64),
0145     .period_bytes_min = 64,
0146     .period_bytes_max = (65536 - 128) >> 1,  /* size has to be N*64 bytes */
0147     .periods_min =      2,
0148     .periods_max =      2,
0149     .fifo_size =        0,
0150 };
0151 
0152 static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime)
0153 {
0154     struct snd_emu10k1_pcm *epcm = runtime->private_data;
0155 
0156     kfree(epcm);
0157 }
0158 
0159 /* open_playback callback */
0160 static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id)
0161 {
0162     struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
0163         struct snd_emu10k1_voice *channel = &(emu->p16v_voices[channel_id]);
0164     struct snd_emu10k1_pcm *epcm;
0165     struct snd_pcm_runtime *runtime = substream->runtime;
0166     int err;
0167 
0168     epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
0169     /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */
0170 
0171     if (epcm == NULL)
0172         return -ENOMEM;
0173     epcm->emu = emu;
0174     epcm->substream = substream;
0175     /*
0176     dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n",
0177            substream->pcm->device, channel_id);
0178     */
0179     runtime->private_data = epcm;
0180     runtime->private_free = snd_p16v_pcm_free_substream;
0181   
0182     runtime->hw = snd_p16v_playback_hw;
0183 
0184         channel->emu = emu;
0185         channel->number = channel_id;
0186 
0187         channel->use=1;
0188 #if 0 /* debug */
0189     dev_dbg(emu->card->dev,
0190            "p16v: open channel_id=%d, channel=%p, use=0x%x\n",
0191            channel_id, channel, channel->use);
0192     dev_dbg(emu->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n",
0193            channel_id, chip, channel);
0194 #endif /* debug */
0195     /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
0196     channel->epcm = epcm;
0197     err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
0198     if (err < 0)
0199                 return err;
0200 
0201     runtime->sync.id32[0] = substream->pcm->card->number;
0202     runtime->sync.id32[1] = 'P';
0203     runtime->sync.id32[2] = 16;
0204     runtime->sync.id32[3] = 'V';
0205 
0206     return 0;
0207 }
0208 /* open_capture callback */
0209 static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream, int channel_id)
0210 {
0211     struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
0212     struct snd_emu10k1_voice *channel = &(emu->p16v_capture_voice);
0213     struct snd_emu10k1_pcm *epcm;
0214     struct snd_pcm_runtime *runtime = substream->runtime;
0215     int err;
0216 
0217     epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
0218     /* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */
0219 
0220     if (epcm == NULL)
0221         return -ENOMEM;
0222     epcm->emu = emu;
0223     epcm->substream = substream;
0224     /*
0225     dev_dbg(emu->card->dev, "epcm device=%d, channel_id=%d\n",
0226            substream->pcm->device, channel_id);
0227     */
0228     runtime->private_data = epcm;
0229     runtime->private_free = snd_p16v_pcm_free_substream;
0230   
0231     runtime->hw = snd_p16v_capture_hw;
0232 
0233     channel->emu = emu;
0234     channel->number = channel_id;
0235 
0236     channel->use=1;
0237 #if 0 /* debug */
0238     dev_dbg(emu->card->dev,
0239            "p16v: open channel_id=%d, channel=%p, use=0x%x\n",
0240            channel_id, channel, channel->use);
0241     dev_dbg(emu->card->dev, "open:channel_id=%d, chip=%p, channel=%p\n",
0242            channel_id, chip, channel);
0243 #endif /* debug */
0244     /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
0245     channel->epcm = epcm;
0246     err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
0247     if (err < 0)
0248         return err;
0249 
0250     return 0;
0251 }
0252 
0253 
0254 /* close callback */
0255 static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream)
0256 {
0257     struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
0258     //struct snd_pcm_runtime *runtime = substream->runtime;
0259     //struct snd_emu10k1_pcm *epcm = runtime->private_data;
0260     emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0;
0261     /* FIXME: maybe zero others */
0262     return 0;
0263 }
0264 
0265 /* close callback */
0266 static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream)
0267 {
0268     struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
0269     //struct snd_pcm_runtime *runtime = substream->runtime;
0270     //struct snd_emu10k1_pcm *epcm = runtime->private_data;
0271     emu->p16v_capture_voice.use = 0;
0272     /* FIXME: maybe zero others */
0273     return 0;
0274 }
0275 
0276 static int snd_p16v_pcm_open_playback_front(struct snd_pcm_substream *substream)
0277 {
0278     return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
0279 }
0280 
0281 static int snd_p16v_pcm_open_capture(struct snd_pcm_substream *substream)
0282 {
0283     // Only using channel 0 for now, but the card has 2 channels.
0284     return snd_p16v_pcm_open_capture_channel(substream, 0);
0285 }
0286 
0287 /* prepare playback callback */
0288 static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
0289 {
0290     struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
0291     struct snd_pcm_runtime *runtime = substream->runtime;
0292     int channel = substream->pcm->device - emu->p16v_device_offset;
0293     u32 *table_base = (u32 *)(emu->p16v_buffer->area+(8*16*channel));
0294     u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
0295     int i;
0296     u32 tmp;
0297     
0298 #if 0 /* debug */
0299     dev_dbg(emu->card->dev,
0300         "prepare:channel_number=%d, rate=%d, "
0301            "format=0x%x, channels=%d, buffer_size=%ld, "
0302            "period_size=%ld, periods=%u, frames_to_bytes=%d\n",
0303            channel, runtime->rate, runtime->format, runtime->channels,
0304            runtime->buffer_size, runtime->period_size,
0305            runtime->periods, frames_to_bytes(runtime, 1));
0306     dev_dbg(emu->card->dev,
0307         "dma_addr=%x, dma_area=%p, table_base=%p\n",
0308            runtime->dma_addr, runtime->dma_area, table_base);
0309     dev_dbg(emu->card->dev,
0310         "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
0311            emu->p16v_buffer->addr, emu->p16v_buffer->area,
0312            emu->p16v_buffer->bytes);
0313 #endif /* debug */
0314     tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
0315         switch (runtime->rate) {
0316     case 44100:
0317       snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080);
0318       break;
0319     case 96000:
0320       snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040);
0321       break;
0322     case 192000:
0323       snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020);
0324       break;
0325     case 48000:
0326     default:
0327       snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000);
0328       break;
0329     }
0330     /* FIXME: Check emu->buffer.size before actually writing to it. */
0331     for(i = 0; i < runtime->periods; i++) {
0332         table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
0333         table_base[(i*2)+1]=period_size_bytes<<16;
0334     }
0335  
0336     snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer->addr+(8*16*channel));
0337     snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
0338     snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
0339     snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
0340     //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
0341     snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
0342     snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
0343     snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
0344     snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);
0345 
0346     return 0;
0347 }
0348 
0349 /* prepare capture callback */
0350 static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream)
0351 {
0352     struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
0353     struct snd_pcm_runtime *runtime = substream->runtime;
0354     int channel = substream->pcm->device - emu->p16v_device_offset;
0355     u32 tmp;
0356 
0357     /*
0358     dev_dbg(emu->card->dev, "prepare capture:channel_number=%d, rate=%d, "
0359            "format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, "
0360            "frames_to_bytes=%d\n",
0361            channel, runtime->rate, runtime->format, runtime->channels,
0362            runtime->buffer_size, runtime->period_size,
0363            frames_to_bytes(runtime, 1));
0364     */
0365     tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
0366         switch (runtime->rate) {
0367     case 44100:
0368       snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800);
0369       break;
0370     case 96000:
0371       snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400);
0372       break;
0373     case 192000:
0374       snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200);
0375       break;
0376     case 48000:
0377     default:
0378       snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000);
0379       break;
0380     }
0381     /* FIXME: Check emu->buffer.size before actually writing to it. */
0382     snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
0383     snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
0384     snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size) << 16); // buffer size in bytes
0385     snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
0386     //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
0387     //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
0388 
0389     return 0;
0390 }
0391 
0392 static void snd_p16v_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
0393 {
0394     unsigned long flags;
0395     unsigned int enable;
0396 
0397     spin_lock_irqsave(&emu->emu_lock, flags);
0398     enable = inl(emu->port + INTE2) | intrenb;
0399     outl(enable, emu->port + INTE2);
0400     spin_unlock_irqrestore(&emu->emu_lock, flags);
0401 }
0402 
0403 static void snd_p16v_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
0404 {
0405     unsigned long flags;
0406     unsigned int disable;
0407 
0408     spin_lock_irqsave(&emu->emu_lock, flags);
0409     disable = inl(emu->port + INTE2) & (~intrenb);
0410     outl(disable, emu->port + INTE2);
0411     spin_unlock_irqrestore(&emu->emu_lock, flags);
0412 }
0413 
0414 /* trigger_playback callback */
0415 static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
0416                     int cmd)
0417 {
0418     struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
0419     struct snd_pcm_runtime *runtime;
0420     struct snd_emu10k1_pcm *epcm;
0421     int channel;
0422     int result = 0;
0423         struct snd_pcm_substream *s;
0424     u32 basic = 0;
0425     u32 inte = 0;
0426     int running = 0;
0427 
0428     switch (cmd) {
0429     case SNDRV_PCM_TRIGGER_START:
0430         running=1;
0431         break;
0432     case SNDRV_PCM_TRIGGER_STOP:
0433     default:
0434         running = 0;
0435         break;
0436     }
0437         snd_pcm_group_for_each_entry(s, substream) {
0438         if (snd_pcm_substream_chip(s) != emu ||
0439             s->stream != SNDRV_PCM_STREAM_PLAYBACK)
0440             continue;
0441         runtime = s->runtime;
0442         epcm = runtime->private_data;
0443         channel = substream->pcm->device-emu->p16v_device_offset;
0444         /* dev_dbg(emu->card->dev, "p16v channel=%d\n", channel); */
0445         epcm->running = running;
0446         basic |= (0x1<<channel);
0447         inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel);
0448                 snd_pcm_trigger_done(s, substream);
0449         }
0450     /* dev_dbg(emu->card->dev, "basic=0x%x, inte=0x%x\n", basic, inte); */
0451 
0452     switch (cmd) {
0453     case SNDRV_PCM_TRIGGER_START:
0454         snd_p16v_intr_enable(emu, inte);
0455         snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)| (basic));
0456         break;
0457     case SNDRV_PCM_TRIGGER_STOP:
0458         snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
0459         snd_p16v_intr_disable(emu, inte);
0460         break;
0461     default:
0462         result = -EINVAL;
0463         break;
0464     }
0465     return result;
0466 }
0467 
0468 /* trigger_capture callback */
0469 static int snd_p16v_pcm_trigger_capture(struct snd_pcm_substream *substream,
0470                                    int cmd)
0471 {
0472     struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
0473     struct snd_pcm_runtime *runtime = substream->runtime;
0474     struct snd_emu10k1_pcm *epcm = runtime->private_data;
0475     int channel = 0;
0476     int result = 0;
0477     u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP;
0478 
0479     switch (cmd) {
0480     case SNDRV_PCM_TRIGGER_START:
0481         snd_p16v_intr_enable(emu, inte);
0482         snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
0483         epcm->running = 1;
0484         break;
0485     case SNDRV_PCM_TRIGGER_STOP:
0486         snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
0487         snd_p16v_intr_disable(emu, inte);
0488         //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
0489         epcm->running = 0;
0490         break;
0491     default:
0492         result = -EINVAL;
0493         break;
0494     }
0495     return result;
0496 }
0497 
0498 /* pointer_playback callback */
0499 static snd_pcm_uframes_t
0500 snd_p16v_pcm_pointer_playback(struct snd_pcm_substream *substream)
0501 {
0502     struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
0503     struct snd_pcm_runtime *runtime = substream->runtime;
0504     struct snd_emu10k1_pcm *epcm = runtime->private_data;
0505     snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
0506     int channel = substream->pcm->device - emu->p16v_device_offset;
0507     if (!epcm->running)
0508         return 0;
0509 
0510     ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
0511     ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
0512     ptr4 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
0513     if (ptr3 != ptr4) ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
0514     ptr2 = bytes_to_frames(runtime, ptr1);
0515     ptr2+= (ptr4 >> 3) * runtime->period_size;
0516     ptr=ptr2;
0517         if (ptr >= runtime->buffer_size)
0518         ptr -= runtime->buffer_size;
0519 
0520     return ptr;
0521 }
0522 
0523 /* pointer_capture callback */
0524 static snd_pcm_uframes_t
0525 snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream)
0526 {
0527     struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
0528     struct snd_pcm_runtime *runtime = substream->runtime;
0529     struct snd_emu10k1_pcm *epcm = runtime->private_data;
0530     snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
0531     int channel = 0;
0532 
0533     if (!epcm->running)
0534         return 0;
0535 
0536     ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel);
0537     ptr2 = bytes_to_frames(runtime, ptr1);
0538     ptr=ptr2;
0539     if (ptr >= runtime->buffer_size) {
0540         ptr -= runtime->buffer_size;
0541         dev_warn(emu->card->dev, "buffer capture limited!\n");
0542     }
0543     /*
0544     dev_dbg(emu->card->dev, "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, "
0545            "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n",
0546            ptr1, ptr2, ptr, (int)runtime->buffer_size,
0547            (int)runtime->period_size, (int)runtime->frame_bits,
0548            (int)runtime->rate);
0549     */
0550     return ptr;
0551 }
0552 
0553 /* operators */
0554 static const struct snd_pcm_ops snd_p16v_playback_front_ops = {
0555     .open =        snd_p16v_pcm_open_playback_front,
0556     .close =       snd_p16v_pcm_close_playback,
0557     .prepare =     snd_p16v_pcm_prepare_playback,
0558     .trigger =     snd_p16v_pcm_trigger_playback,
0559     .pointer =     snd_p16v_pcm_pointer_playback,
0560 };
0561 
0562 static const struct snd_pcm_ops snd_p16v_capture_ops = {
0563     .open =        snd_p16v_pcm_open_capture,
0564     .close =       snd_p16v_pcm_close_capture,
0565     .prepare =     snd_p16v_pcm_prepare_capture,
0566     .trigger =     snd_p16v_pcm_trigger_capture,
0567     .pointer =     snd_p16v_pcm_pointer_capture,
0568 };
0569 
0570 int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
0571 {
0572     struct snd_pcm *pcm;
0573     struct snd_pcm_substream *substream;
0574     int err;
0575         int capture=1;
0576   
0577     /* dev_dbg(emu->card->dev, "snd_p16v_pcm called. device=%d\n", device); */
0578     emu->p16v_device_offset = device;
0579 
0580     err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm);
0581     if (err < 0)
0582         return err;
0583   
0584     pcm->private_data = emu;
0585     // Single playback 8 channel device.
0586     // Single capture 2 channel device.
0587     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
0588     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops);
0589 
0590     pcm->info_flags = 0;
0591     pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
0592     strcpy(pcm->name, "p16v");
0593     emu->pcm_p16v = pcm;
0594 
0595     for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 
0596         substream; 
0597         substream = substream->next) {
0598         snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
0599                        &emu->pci->dev,
0600                        (65536 - 64) * 8,
0601                        (65536 - 64) * 8);
0602         /*
0603         dev_dbg(emu->card->dev,
0604                "preallocate playback substream: err=%d\n", err);
0605         */
0606     }
0607 
0608     for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 
0609           substream; 
0610           substream = substream->next) {
0611         snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
0612                        &emu->pci->dev,
0613                        65536 - 64, 65536 - 64);
0614         /*
0615         dev_dbg(emu->card->dev,
0616                "preallocate capture substream: err=%d\n", err);
0617         */
0618     }
0619   
0620     return 0;
0621 }
0622 
0623 static int snd_p16v_volume_info(struct snd_kcontrol *kcontrol,
0624                 struct snd_ctl_elem_info *uinfo)
0625 {
0626         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0627         uinfo->count = 2;
0628         uinfo->value.integer.min = 0;
0629         uinfo->value.integer.max = 255;
0630         return 0;
0631 }
0632 
0633 static int snd_p16v_volume_get(struct snd_kcontrol *kcontrol,
0634                    struct snd_ctl_elem_value *ucontrol)
0635 {
0636         struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
0637     int high_low = (kcontrol->private_value >> 8) & 0xff;
0638     int reg = kcontrol->private_value & 0xff;
0639     u32 value;
0640 
0641     value = snd_emu10k1_ptr20_read(emu, reg, high_low);
0642     if (high_low) {
0643         ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
0644         ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
0645     } else {
0646         ucontrol->value.integer.value[0] = 0xff - ((value >> 8) & 0xff); /* Left */
0647         ucontrol->value.integer.value[1] = 0xff - ((value >> 0) & 0xff); /* Right */
0648     }
0649     return 0;
0650 }
0651 
0652 static int snd_p16v_volume_put(struct snd_kcontrol *kcontrol,
0653                    struct snd_ctl_elem_value *ucontrol)
0654 {
0655         struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
0656     int high_low = (kcontrol->private_value >> 8) & 0xff;
0657     int reg = kcontrol->private_value & 0xff;
0658         u32 value, oval;
0659 
0660     oval = value = snd_emu10k1_ptr20_read(emu, reg, 0);
0661     if (high_low == 1) {
0662         value &= 0xffff;
0663         value |= ((0xff - ucontrol->value.integer.value[0]) << 24) |
0664             ((0xff - ucontrol->value.integer.value[1]) << 16);
0665     } else {
0666         value &= 0xffff0000;
0667         value |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
0668             ((0xff - ucontrol->value.integer.value[1]) );
0669     }
0670     if (value != oval) {
0671         snd_emu10k1_ptr20_write(emu, reg, 0, value);
0672         return 1;
0673     }
0674     return 0;
0675 }
0676 
0677 static int snd_p16v_capture_source_info(struct snd_kcontrol *kcontrol,
0678                     struct snd_ctl_elem_info *uinfo)
0679 {
0680     static const char * const texts[8] = {
0681         "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S",
0682         "CDIF", "FX", "AC97"
0683     };
0684 
0685     return snd_ctl_enum_info(uinfo, 1, 8, texts);
0686 }
0687 
0688 static int snd_p16v_capture_source_get(struct snd_kcontrol *kcontrol,
0689                     struct snd_ctl_elem_value *ucontrol)
0690 {
0691     struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
0692 
0693     ucontrol->value.enumerated.item[0] = emu->p16v_capture_source;
0694     return 0;
0695 }
0696 
0697 static int snd_p16v_capture_source_put(struct snd_kcontrol *kcontrol,
0698                     struct snd_ctl_elem_value *ucontrol)
0699 {
0700     struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
0701     unsigned int val;
0702     int change = 0;
0703     u32 mask;
0704     u32 source;
0705 
0706     val = ucontrol->value.enumerated.item[0] ;
0707     if (val > 7)
0708         return -EINVAL;
0709     change = (emu->p16v_capture_source != val);
0710     if (change) {
0711         emu->p16v_capture_source = val;
0712         source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
0713         mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff;
0714         snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask);
0715     }
0716         return change;
0717 }
0718 
0719 static int snd_p16v_capture_channel_info(struct snd_kcontrol *kcontrol,
0720                      struct snd_ctl_elem_info *uinfo)
0721 {
0722     static const char * const texts[4] = { "0", "1", "2", "3", };
0723 
0724     return snd_ctl_enum_info(uinfo, 1, 4, texts);
0725 }
0726 
0727 static int snd_p16v_capture_channel_get(struct snd_kcontrol *kcontrol,
0728                     struct snd_ctl_elem_value *ucontrol)
0729 {
0730     struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
0731 
0732     ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel;
0733     return 0;
0734 }
0735 
0736 static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol,
0737                     struct snd_ctl_elem_value *ucontrol)
0738 {
0739     struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
0740     unsigned int val;
0741     int change = 0;
0742     u32 tmp;
0743 
0744     val = ucontrol->value.enumerated.item[0] ;
0745     if (val > 3)
0746         return -EINVAL;
0747     change = (emu->p16v_capture_channel != val);
0748     if (change) {
0749         emu->p16v_capture_channel = val;
0750         tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc;
0751         snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val);
0752     }
0753         return change;
0754 }
0755 static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
0756 
0757 #define P16V_VOL(xname,xreg,xhl) { \
0758     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
0759         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |             \
0760                   SNDRV_CTL_ELEM_ACCESS_TLV_READ,               \
0761     .info = snd_p16v_volume_info, \
0762     .get = snd_p16v_volume_get, \
0763     .put = snd_p16v_volume_put, \
0764     .tlv = { .p = snd_p16v_db_scale1 }, \
0765     .private_value = ((xreg) | ((xhl) << 8)) \
0766 }
0767 
0768 static const struct snd_kcontrol_new p16v_mixer_controls[] = {
0769     P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0),
0770     P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1),
0771     P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1),
0772     P16V_VOL("HD Analog Side Playback Volume", PLAYBACK_VOLUME_MIXER10, 0),
0773     P16V_VOL("HD SPDIF Front Playback Volume", PLAYBACK_VOLUME_MIXER7, 0),
0774     P16V_VOL("HD SPDIF Rear Playback Volume", PLAYBACK_VOLUME_MIXER8, 1),
0775     P16V_VOL("HD SPDIF Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER7, 1),
0776     P16V_VOL("HD SPDIF Side Playback Volume", PLAYBACK_VOLUME_MIXER8, 0),
0777     {
0778         .iface =    SNDRV_CTL_ELEM_IFACE_MIXER,
0779         .name =     "HD source Capture",
0780         .info =     snd_p16v_capture_source_info,
0781         .get =      snd_p16v_capture_source_get,
0782         .put =      snd_p16v_capture_source_put
0783     },
0784     {
0785         .iface =    SNDRV_CTL_ELEM_IFACE_MIXER,
0786         .name =     "HD channel Capture",
0787         .info =     snd_p16v_capture_channel_info,
0788         .get =      snd_p16v_capture_channel_get,
0789         .put =      snd_p16v_capture_channel_put
0790     },
0791 };
0792 
0793 
0794 int snd_p16v_mixer(struct snd_emu10k1 *emu)
0795 {
0796     int i, err;
0797         struct snd_card *card = emu->card;
0798 
0799     for (i = 0; i < ARRAY_SIZE(p16v_mixer_controls); i++) {
0800         err = snd_ctl_add(card, snd_ctl_new1(&p16v_mixer_controls[i], emu));
0801         if (err < 0)
0802             return err;
0803     }
0804         return 0;
0805 }
0806 
0807 #ifdef CONFIG_PM_SLEEP
0808 
0809 #define NUM_CHS 1   /* up to 4, but only first channel is used */
0810 
0811 int snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
0812 {
0813     emu->p16v_saved = vmalloc(array_size(NUM_CHS * 4, 0x80));
0814     if (! emu->p16v_saved)
0815         return -ENOMEM;
0816     return 0;
0817 }
0818 
0819 void snd_p16v_free_pm_buffer(struct snd_emu10k1 *emu)
0820 {
0821     vfree(emu->p16v_saved);
0822 }
0823 
0824 void snd_p16v_suspend(struct snd_emu10k1 *emu)
0825 {
0826     int i, ch;
0827     unsigned int *val;
0828 
0829     val = emu->p16v_saved;
0830     for (ch = 0; ch < NUM_CHS; ch++)
0831         for (i = 0; i < 0x80; i++, val++)
0832             *val = snd_emu10k1_ptr20_read(emu, i, ch);
0833 }
0834 
0835 void snd_p16v_resume(struct snd_emu10k1 *emu)
0836 {
0837     int i, ch;
0838     unsigned int *val;
0839 
0840     val = emu->p16v_saved;
0841     for (ch = 0; ch < NUM_CHS; ch++)
0842         for (i = 0; i < 0x80; i++, val++)
0843             snd_emu10k1_ptr20_write(emu, i, ch, *val);
0844 }
0845 #endif