2019-05-27 08:55:05 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-16 15:20:36 -07:00
/*
* Copyright ( c ) by James Courtier - Dutton < James @ superbug . demon . co . uk >
* Driver p16v chips
2005-05-07 16:13:40 +02:00
* Version : 0.25
2005-04-16 15:20:36 -07:00
*
* FEATURES currently supported :
* Output fixed at S32_LE , 2 channel to hw : 0 , 0
* Rates : 44.1 , 48 , 96 , 192.
*
* Changelog :
* 0.8
* Use separate card based buffer for periods table .
* 0.9
* Use 2 channel output streams instead of 8 channel .
* ( 8 channel output streams might be good for ASIO type output )
* Corrected speaker output , so Front - > Front etc .
* 0.10
* Fixed missed interrupts .
* 0.11
* Add Sound card model number and names .
* Add Analog volume controls .
* 0.12
* Corrected playback interrupts . Now interrupt per period , instead of half period .
* 0.13
* Use single trigger for multichannel .
* 0.14
* Mic capture now works at fixed : S32_LE , 96000 Hz , Stereo .
* 0.15
* Force buffer_size / period_size = = INTEGER .
* 0.16
* Update p16v . c to work with changed alsa api .
* 0.17
* Update p16v . c to work with changed alsa api . Removed boot_devs .
* 0.18
* Merging with snd - emu10k1 driver .
* 0.19
* One stereo channel at 24 bit now works .
* 0.20
* Added better register defines .
* 0.21
* Integrated with snd - emu10k1 driver .
* 0.22
* Removed # if 0 . . . # endif
2005-05-07 15:34:13 +02:00
* 0.23
* Implement different capture rates .
* 0.24
* Implement different capture source channels .
* e . g . When HD Capture source is set to SPDIF ,
* setting HD Capture channel to 0 captures from CDROM digital input .
* setting HD Capture channel to 1 captures from SPDIF in .
2005-05-07 16:13:40 +02:00
* 0.25
* Include capture buffer sizes .
2005-04-16 15:20:36 -07:00
*
* BUGS :
* Some stability problems when unloading the snd - p16v kernel module .
* - -
*
* TODO :
* SPDIF out .
* Find out how to change capture sample rates . E . g . To record SPDIF at 48000 Hz .
* Currently capture fixed at 48000 Hz .
*
* - -
* GENERAL INFO :
* Model : SB0240
* P16V Chip : CA0151 - DBS
* Audigy 2 Chip : CA0102 - IAT
* AC97 Codec : STAC 9721
* ADC : Philips 1361 T ( Stereo 24 bit )
* DAC : CS4382 - K ( 8 - channel , 24 bit , 192 Khz )
*
2011-03-30 22:57:33 -03:00
* This code was initially based on code from ALSA ' s emu10k1x . c which is :
2005-04-16 15:20:36 -07:00
* Copyright ( c ) by Francisco Moraes < fmoraes @ nc . rr . com >
*/
# include <linux/delay.h>
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/pci.h>
# include <linux/slab.h>
2005-12-05 15:12:20 +01:00
# include <linux/vmalloc.h>
2005-04-16 15:20:36 -07:00
# include <linux/moduleparam.h>
# include <sound/core.h>
# include <sound/initval.h>
# include <sound/pcm.h>
# include <sound/ac97_codec.h>
# include <sound/info.h>
2006-07-22 17:02:10 +01:00
# include <sound/tlv.h>
2005-04-16 15:20:36 -07:00
# include <sound/emu10k1.h>
# include "p16v.h"
# define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
# define PCM_FRONT_CHANNEL 0
# define PCM_REAR_CHANNEL 1
# define PCM_CENTER_LFE_CHANNEL 2
2005-12-22 17:01:20 +01:00
# define PCM_SIDE_CHANNEL 3
2005-04-16 15:20:36 -07:00
# define CONTROL_FRONT_CHANNEL 0
# define CONTROL_REAR_CHANNEL 3
# define CONTROL_CENTER_LFE_CHANNEL 1
2005-12-22 17:01:20 +01:00
# define CONTROL_SIDE_CHANNEL 2
2005-04-16 15:20:36 -07:00
/* Card IDs:
* Class 0401 : 1102 : 0004 ( rev 04 ) Subsystem : 1102 : 2002 - > Audigy2 ZS 7.1 Model : SB0350
* Class 0401 : 1102 : 0004 ( rev 04 ) Subsystem : 1102 : 1007 - > Audigy2 6.1 Model : SB0240
* Class 0401 : 1102 : 0004 ( rev 04 ) Subsystem : 1102 : 1002 - > Audigy2 Platinum Model : SB msb0240230009266
* Class 0401 : 1102 : 0004 ( rev 04 ) Subsystem : 1102 : 2007 - > Audigy4 Pro Model : SB0380 M1SB0380472001901E
*
*/
/* hardware definition */
2017-08-12 21:01:18 +05:30
static const struct snd_pcm_hardware snd_p16v_playback_hw = {
2007-08-13 17:37:55 +02:00
. info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_SYNC_START ,
2005-04-16 15:20:36 -07:00
. formats = SNDRV_PCM_FMTBIT_S32_LE , /* Only supports 24-bit samples padded to 32 bits. */
2005-04-09 23:38:25 +02:00
. rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 ,
. rate_min = 44100 ,
2005-04-16 15:20:36 -07:00
. rate_max = 192000 ,
. channels_min = 8 ,
. channels_max = 8 ,
2005-04-10 00:00:24 +02:00
. buffer_bytes_max = ( ( 65536 - 64 ) * 8 ) ,
2005-04-16 15:20:36 -07:00
. period_bytes_min = 64 ,
2005-04-10 00:00:24 +02:00
. period_bytes_max = ( 65536 - 64 ) ,
2005-04-16 15:20:36 -07:00
. periods_min = 2 ,
. periods_max = 8 ,
. fifo_size = 0 ,
} ;
2017-08-12 21:01:18 +05:30
static const struct snd_pcm_hardware snd_p16v_capture_hw = {
2005-05-04 17:26:28 +02:00
. info = ( SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
2005-11-17 16:14:10 +01:00
SNDRV_PCM_INFO_RESUME |
2005-05-04 17:26:28 +02:00
SNDRV_PCM_INFO_MMAP_VALID ) ,
. formats = SNDRV_PCM_FMTBIT_S32_LE ,
. rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 ,
. rate_min = 44100 ,
. rate_max = 192000 ,
. channels_min = 2 ,
. channels_max = 2 ,
2005-05-07 16:13:40 +02:00
. buffer_bytes_max = ( 65536 - 64 ) ,
2005-05-04 17:26:28 +02:00
. period_bytes_min = 64 ,
2005-05-07 16:13:40 +02:00
. period_bytes_max = ( 65536 - 128 ) > > 1 , /* size has to be N*64 bytes */
2005-05-04 17:26:28 +02:00
. periods_min = 2 ,
. periods_max = 2 ,
. fifo_size = 0 ,
2005-03-26 19:35:29 +01:00
} ;
2005-11-17 14:50:13 +01:00
static void snd_p16v_pcm_free_substream ( struct snd_pcm_runtime * runtime )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1_pcm * epcm = runtime - > private_data ;
2015-01-03 17:06:04 +01:00
kfree ( epcm ) ;
2005-04-16 15:20:36 -07:00
}
/* open_playback callback */
2005-11-17 14:50:13 +01:00
static int snd_p16v_pcm_open_playback_channel ( struct snd_pcm_substream * substream , int channel_id )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_pcm_substream_chip ( substream ) ;
struct snd_emu10k1_voice * channel = & ( emu - > p16v_voices [ channel_id ] ) ;
struct snd_emu10k1_pcm * epcm ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
2005-04-16 15:20:36 -07:00
int err ;
[ALSA] Replace with kzalloc() - pci stuff
AD1889 driver,ATIIXP driver,ATIIXP-modem driver,AZT3328 driver
BT87x driver,CMIPCI driver,CS4281 driver,ENS1370/1+ driver
ES1938 driver,ES1968 driver,FM801 driver,Intel8x0 driver
Intel8x0-modem driver,Maestro3 driver,SonicVibes driver,VIA82xx driver
VIA82xx-modem driver,AC97 Codec,AK4531 codec,au88x0 driver
CA0106 driver,CS46xx driver,EMU10K1/EMU10K2 driver,HDA Codec driver
HDA generic driver,HDA Intel driver,ICE1712 driver,ICE1724 driver
KORG1212 driver,MIXART driver,NM256 driver,Trident driver,YMFPCI driver
Replace kcalloc(1,..) with kzalloc().
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2005-09-09 14:21:46 +02:00
epcm = kzalloc ( sizeof ( * epcm ) , GFP_KERNEL ) ;
2014-02-25 17:02:09 +01:00
/* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */
2005-04-16 15:20:36 -07:00
if ( epcm = = NULL )
return - ENOMEM ;
epcm - > emu = emu ;
epcm - > substream = substream ;
2009-02-05 16:08:14 +01:00
/*
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev , " epcm device=%d, channel_id=%d \n " ,
2009-02-05 16:08:14 +01:00
substream - > pcm - > device , channel_id ) ;
*/
2005-04-16 15:20:36 -07:00
runtime - > private_data = epcm ;
runtime - > private_free = snd_p16v_pcm_free_substream ;
runtime - > hw = snd_p16v_playback_hw ;
channel - > emu = emu ;
channel - > number = channel_id ;
channel - > use = 1 ;
2009-02-05 16:08:14 +01:00
#if 0 /* debug */
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev ,
2009-02-05 16:08:14 +01:00
" p16v: open channel_id=%d, channel=%p, use=0x%x \n " ,
channel_id , channel , channel - > use ) ;
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev , " open:channel_id=%d, chip=%p, channel=%p \n " ,
2009-02-05 16:08:14 +01:00
channel_id , chip , channel ) ;
# endif /* debug */
/* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
channel - > epcm = epcm ;
2021-06-08 16:05:14 +02:00
err = snd_pcm_hw_constraint_integer ( runtime , SNDRV_PCM_HW_PARAM_PERIODS ) ;
if ( err < 0 )
2005-04-16 15:20:36 -07:00
return err ;
2007-08-13 17:37:55 +02:00
runtime - > sync . id32 [ 0 ] = substream - > pcm - > card - > number ;
runtime - > sync . id32 [ 1 ] = ' P ' ;
runtime - > sync . id32 [ 2 ] = 16 ;
runtime - > sync . id32 [ 3 ] = ' V ' ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-03-26 19:35:29 +01:00
/* open_capture callback */
2005-11-17 14:50:13 +01:00
static int snd_p16v_pcm_open_capture_channel ( struct snd_pcm_substream * substream , int channel_id )
2005-03-26 19:35:29 +01:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_pcm_substream_chip ( substream ) ;
struct snd_emu10k1_voice * channel = & ( emu - > p16v_capture_voice ) ;
struct snd_emu10k1_pcm * epcm ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
2005-03-26 19:35:29 +01:00
int err ;
[ALSA] Replace with kzalloc() - pci stuff
AD1889 driver,ATIIXP driver,ATIIXP-modem driver,AZT3328 driver
BT87x driver,CMIPCI driver,CS4281 driver,ENS1370/1+ driver
ES1938 driver,ES1968 driver,FM801 driver,Intel8x0 driver
Intel8x0-modem driver,Maestro3 driver,SonicVibes driver,VIA82xx driver
VIA82xx-modem driver,AC97 Codec,AK4531 codec,au88x0 driver
CA0106 driver,CS46xx driver,EMU10K1/EMU10K2 driver,HDA Codec driver
HDA generic driver,HDA Intel driver,ICE1712 driver,ICE1724 driver
KORG1212 driver,MIXART driver,NM256 driver,Trident driver,YMFPCI driver
Replace kcalloc(1,..) with kzalloc().
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2005-09-09 14:21:46 +02:00
epcm = kzalloc ( sizeof ( * epcm ) , GFP_KERNEL ) ;
2014-02-25 17:02:09 +01:00
/* dev_dbg(emu->card->dev, "epcm kcalloc: %p\n", epcm); */
2005-03-26 19:35:29 +01:00
if ( epcm = = NULL )
return - ENOMEM ;
epcm - > emu = emu ;
epcm - > substream = substream ;
2009-02-05 16:08:14 +01:00
/*
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev , " epcm device=%d, channel_id=%d \n " ,
2009-02-05 16:08:14 +01:00
substream - > pcm - > device , channel_id ) ;
*/
2005-03-26 19:35:29 +01:00
runtime - > private_data = epcm ;
runtime - > private_free = snd_p16v_pcm_free_substream ;
runtime - > hw = snd_p16v_capture_hw ;
channel - > emu = emu ;
channel - > number = channel_id ;
channel - > use = 1 ;
2009-02-05 16:08:14 +01:00
#if 0 /* debug */
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev ,
2009-02-05 16:08:14 +01:00
" p16v: open channel_id=%d, channel=%p, use=0x%x \n " ,
channel_id , channel , channel - > use ) ;
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev , " open:channel_id=%d, chip=%p, channel=%p \n " ,
2009-02-05 16:08:14 +01:00
channel_id , chip , channel ) ;
# endif /* debug */
/* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
channel - > epcm = epcm ;
2021-06-08 16:05:14 +02:00
err = snd_pcm_hw_constraint_integer ( runtime , SNDRV_PCM_HW_PARAM_PERIODS ) ;
if ( err < 0 )
2005-03-26 19:35:29 +01:00
return err ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
/* close callback */
2005-11-17 14:50:13 +01:00
static int snd_p16v_pcm_close_playback ( struct snd_pcm_substream * substream )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_pcm_substream_chip ( substream ) ;
//struct snd_pcm_runtime *runtime = substream->runtime;
//struct snd_emu10k1_pcm *epcm = runtime->private_data;
2006-10-01 10:48:04 +01:00
emu - > p16v_voices [ substream - > pcm - > device - emu - > p16v_device_offset ] . use = 0 ;
2005-03-26 19:35:29 +01:00
/* FIXME: maybe zero others */
return 0 ;
}
/* close callback */
2005-11-17 14:50:13 +01:00
static int snd_p16v_pcm_close_capture ( struct snd_pcm_substream * substream )
2005-03-26 19:35:29 +01:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_pcm_substream_chip ( substream ) ;
//struct snd_pcm_runtime *runtime = substream->runtime;
//struct snd_emu10k1_pcm *epcm = runtime->private_data;
2006-10-01 10:48:04 +01:00
emu - > p16v_capture_voice . use = 0 ;
2005-03-26 19:35:29 +01:00
/* FIXME: maybe zero others */
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-11-17 14:50:13 +01:00
static int snd_p16v_pcm_open_playback_front ( struct snd_pcm_substream * substream )
2005-04-16 15:20:36 -07:00
{
return snd_p16v_pcm_open_playback_channel ( substream , PCM_FRONT_CHANNEL ) ;
}
2005-11-17 14:50:13 +01:00
static int snd_p16v_pcm_open_capture ( struct snd_pcm_substream * substream )
2005-03-26 19:35:29 +01:00
{
// Only using channel 0 for now, but the card has 2 channels.
return snd_p16v_pcm_open_capture_channel ( substream , 0 ) ;
}
2005-04-16 15:20:36 -07:00
/* prepare playback callback */
2005-11-17 14:50:13 +01:00
static int snd_p16v_pcm_prepare_playback ( struct snd_pcm_substream * substream )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_pcm_substream_chip ( substream ) ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
2005-04-16 15:20:36 -07:00
int channel = substream - > pcm - > device - emu - > p16v_device_offset ;
2021-07-15 09:58:55 +02:00
u32 * table_base = ( u32 * ) ( emu - > p16v_buffer - > area + ( 8 * 16 * channel ) ) ;
2005-04-16 15:20:36 -07:00
u32 period_size_bytes = frames_to_bytes ( runtime , runtime - > period_size ) ;
int i ;
u32 tmp ;
2009-02-05 16:08:14 +01:00
#if 0 /* debug */
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev ,
" prepare:channel_number=%d, rate=%d, "
2009-02-05 16:08:14 +01:00
" format=0x%x, channels=%d, buffer_size=%ld, "
" period_size=%ld, periods=%u, frames_to_bytes=%d \n " ,
channel , runtime - > rate , runtime - > format , runtime - > channels ,
runtime - > buffer_size , runtime - > period_size ,
runtime - > periods , frames_to_bytes ( runtime , 1 ) ) ;
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev ,
" dma_addr=%x, dma_area=%p, table_base=%p \n " ,
2009-02-05 16:08:14 +01:00
runtime - > dma_addr , runtime - > dma_area , table_base ) ;
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev ,
" dma_addr=%x, dma_area=%p, dma_bytes(size)=%x \n " ,
2021-07-15 09:58:55 +02:00
emu - > p16v_buffer - > addr , emu - > p16v_buffer - > area ,
emu - > p16v_buffer - > bytes ) ;
2009-02-05 16:08:14 +01:00
# endif /* debug */
2005-04-16 15:20:36 -07:00
tmp = snd_emu10k1_ptr_read ( emu , A_SPDIF_SAMPLERATE , channel ) ;
switch ( runtime - > rate ) {
case 44100 :
2005-04-09 23:38:25 +02:00
snd_emu10k1_ptr_write ( emu , A_SPDIF_SAMPLERATE , channel , ( tmp & ~ 0xe0e0 ) | 0x8080 ) ;
2005-04-16 15:20:36 -07:00
break ;
case 96000 :
2005-04-09 23:38:25 +02:00
snd_emu10k1_ptr_write ( emu , A_SPDIF_SAMPLERATE , channel , ( tmp & ~ 0xe0e0 ) | 0x4040 ) ;
2005-04-16 15:20:36 -07:00
break ;
case 192000 :
2005-04-09 23:38:25 +02:00
snd_emu10k1_ptr_write ( emu , A_SPDIF_SAMPLERATE , channel , ( tmp & ~ 0xe0e0 ) | 0x2020 ) ;
2005-04-16 15:20:36 -07:00
break ;
2005-04-09 23:38:25 +02:00
case 48000 :
2005-04-16 15:20:36 -07:00
default :
2005-04-09 23:38:25 +02:00
snd_emu10k1_ptr_write ( emu , A_SPDIF_SAMPLERATE , channel , ( tmp & ~ 0xe0e0 ) | 0x0000 ) ;
2005-04-16 15:20:36 -07:00
break ;
}
/* FIXME: Check emu->buffer.size before actually writing to it. */
2006-10-01 10:48:04 +01:00
for ( i = 0 ; i < runtime - > periods ; i + + ) {
2005-04-16 15:20:36 -07:00
table_base [ i * 2 ] = runtime - > dma_addr + ( i * period_size_bytes ) ;
table_base [ ( i * 2 ) + 1 ] = period_size_bytes < < 16 ;
}
2021-07-15 09:58:55 +02:00
snd_emu10k1_ptr20_write ( emu , PLAYBACK_LIST_ADDR , channel , emu - > p16v_buffer - > addr + ( 8 * 16 * channel ) ) ;
2005-04-16 15:20:36 -07:00
snd_emu10k1_ptr20_write ( emu , PLAYBACK_LIST_SIZE , channel , ( runtime - > periods - 1 ) < < 19 ) ;
snd_emu10k1_ptr20_write ( emu , PLAYBACK_LIST_PTR , channel , 0 ) ;
snd_emu10k1_ptr20_write ( emu , PLAYBACK_DMA_ADDR , channel , runtime - > dma_addr ) ;
2005-04-10 00:00:24 +02:00
//snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
snd_emu10k1_ptr20_write ( emu , PLAYBACK_PERIOD_SIZE , channel , 0 ) ; // buffer size in bytes
2005-04-16 15:20:36 -07:00
snd_emu10k1_ptr20_write ( emu , PLAYBACK_POINTER , channel , 0 ) ;
snd_emu10k1_ptr20_write ( emu , 0x07 , channel , 0x0 ) ;
snd_emu10k1_ptr20_write ( emu , 0x08 , channel , 0 ) ;
return 0 ;
}
2005-03-26 19:35:29 +01:00
/* prepare capture callback */
2005-11-17 14:50:13 +01:00
static int snd_p16v_pcm_prepare_capture ( struct snd_pcm_substream * substream )
2005-03-26 19:35:29 +01:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_pcm_substream_chip ( substream ) ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
2005-03-26 19:35:29 +01:00
int channel = substream - > pcm - > device - emu - > p16v_device_offset ;
2005-05-04 17:26:28 +02:00
u32 tmp ;
2009-02-05 16:08:14 +01:00
/*
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev , " prepare capture:channel_number=%d, rate=%d, "
2009-02-05 16:08:14 +01:00
" format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, "
" frames_to_bytes=%d \n " ,
channel , runtime - > rate , runtime - > format , runtime - > channels ,
runtime - > buffer_size , runtime - > period_size ,
frames_to_bytes ( runtime , 1 ) ) ;
*/
2005-05-04 17:26:28 +02:00
tmp = snd_emu10k1_ptr_read ( emu , A_SPDIF_SAMPLERATE , channel ) ;
switch ( runtime - > rate ) {
case 44100 :
snd_emu10k1_ptr_write ( emu , A_SPDIF_SAMPLERATE , channel , ( tmp & ~ 0x0e00 ) | 0x0800 ) ;
break ;
case 96000 :
snd_emu10k1_ptr_write ( emu , A_SPDIF_SAMPLERATE , channel , ( tmp & ~ 0x0e00 ) | 0x0400 ) ;
break ;
case 192000 :
snd_emu10k1_ptr_write ( emu , A_SPDIF_SAMPLERATE , channel , ( tmp & ~ 0x0e00 ) | 0x0200 ) ;
break ;
case 48000 :
default :
snd_emu10k1_ptr_write ( emu , A_SPDIF_SAMPLERATE , channel , ( tmp & ~ 0x0e00 ) | 0x0000 ) ;
break ;
}
/* FIXME: Check emu->buffer.size before actually writing to it. */
2005-03-26 19:35:29 +01:00
snd_emu10k1_ptr20_write ( emu , 0x13 , channel , 0 ) ;
snd_emu10k1_ptr20_write ( emu , CAPTURE_DMA_ADDR , channel , runtime - > dma_addr ) ;
2006-10-01 10:48:04 +01:00
snd_emu10k1_ptr20_write ( emu , CAPTURE_BUFFER_SIZE , channel , frames_to_bytes ( runtime , runtime - > buffer_size ) < < 16 ) ; // buffer size in bytes
2005-03-26 19:35:29 +01:00
snd_emu10k1_ptr20_write ( emu , CAPTURE_POINTER , channel , 0 ) ;
//snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
//snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
return 0 ;
}
2005-11-17 14:50:13 +01:00
static void snd_p16v_intr_enable ( struct snd_emu10k1 * emu , unsigned int intrenb )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
unsigned int enable ;
spin_lock_irqsave ( & emu - > emu_lock , flags ) ;
enable = inl ( emu - > port + INTE2 ) | intrenb ;
outl ( enable , emu - > port + INTE2 ) ;
spin_unlock_irqrestore ( & emu - > emu_lock , flags ) ;
}
2005-11-17 14:50:13 +01:00
static void snd_p16v_intr_disable ( struct snd_emu10k1 * emu , unsigned int intrenb )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
unsigned int disable ;
spin_lock_irqsave ( & emu - > emu_lock , flags ) ;
disable = inl ( emu - > port + INTE2 ) & ( ~ intrenb ) ;
outl ( disable , emu - > port + INTE2 ) ;
spin_unlock_irqrestore ( & emu - > emu_lock , flags ) ;
}
/* trigger_playback callback */
2005-11-17 14:50:13 +01:00
static int snd_p16v_pcm_trigger_playback ( struct snd_pcm_substream * substream ,
2005-04-16 15:20:36 -07:00
int cmd )
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_pcm_substream_chip ( substream ) ;
struct snd_pcm_runtime * runtime ;
struct snd_emu10k1_pcm * epcm ;
2005-04-16 15:20:36 -07:00
int channel ;
int result = 0 ;
2005-11-17 14:50:13 +01:00
struct snd_pcm_substream * s ;
2005-04-16 15:20:36 -07:00
u32 basic = 0 ;
u32 inte = 0 ;
2006-10-01 10:48:04 +01:00
int running = 0 ;
2005-04-16 15:20:36 -07:00
switch ( cmd ) {
case SNDRV_PCM_TRIGGER_START :
running = 1 ;
break ;
case SNDRV_PCM_TRIGGER_STOP :
default :
2006-10-01 10:48:04 +01:00
running = 0 ;
2005-04-16 15:20:36 -07:00
break ;
}
2007-02-22 12:52:53 +01:00
snd_pcm_group_for_each_entry ( s , substream ) {
2007-07-30 08:14:31 +02:00
if ( snd_pcm_substream_chip ( s ) ! = emu | |
s - > stream ! = SNDRV_PCM_STREAM_PLAYBACK )
continue ;
2005-04-16 15:20:36 -07:00
runtime = s - > runtime ;
epcm = runtime - > private_data ;
channel = substream - > pcm - > device - emu - > p16v_device_offset ;
2014-02-25 17:02:09 +01:00
/* dev_dbg(emu->card->dev, "p16v channel=%d\n", channel); */
2005-04-16 15:20:36 -07:00
epcm - > running = running ;
basic | = ( 0x1 < < channel ) ;
inte | = ( INTE2_PLAYBACK_CH_0_LOOP < < channel ) ;
snd_pcm_trigger_done ( s , substream ) ;
}
2014-02-25 17:02:09 +01:00
/* dev_dbg(emu->card->dev, "basic=0x%x, inte=0x%x\n", basic, inte); */
2005-04-16 15:20:36 -07:00
switch ( cmd ) {
case SNDRV_PCM_TRIGGER_START :
snd_p16v_intr_enable ( emu , inte ) ;
snd_emu10k1_ptr20_write ( emu , BASIC_INTERRUPT , 0 , snd_emu10k1_ptr20_read ( emu , BASIC_INTERRUPT , 0 ) | ( basic ) ) ;
break ;
case SNDRV_PCM_TRIGGER_STOP :
snd_emu10k1_ptr20_write ( emu , BASIC_INTERRUPT , 0 , snd_emu10k1_ptr20_read ( emu , BASIC_INTERRUPT , 0 ) & ~ ( basic ) ) ;
snd_p16v_intr_disable ( emu , inte ) ;
break ;
default :
result = - EINVAL ;
break ;
}
return result ;
}
2005-03-26 19:35:29 +01:00
/* trigger_capture callback */
2005-11-17 14:50:13 +01:00
static int snd_p16v_pcm_trigger_capture ( struct snd_pcm_substream * substream ,
2005-03-26 19:35:29 +01:00
int cmd )
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_pcm_substream_chip ( substream ) ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
struct snd_emu10k1_pcm * epcm = runtime - > private_data ;
2005-03-26 19:35:29 +01:00
int channel = 0 ;
int result = 0 ;
u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP ;
switch ( cmd ) {
case SNDRV_PCM_TRIGGER_START :
snd_p16v_intr_enable ( emu , inte ) ;
snd_emu10k1_ptr20_write ( emu , BASIC_INTERRUPT , 0 , snd_emu10k1_ptr20_read ( emu , BASIC_INTERRUPT , 0 ) | ( 0x100 < < channel ) ) ;
epcm - > running = 1 ;
break ;
case SNDRV_PCM_TRIGGER_STOP :
snd_emu10k1_ptr20_write ( emu , BASIC_INTERRUPT , 0 , snd_emu10k1_ptr20_read ( emu , BASIC_INTERRUPT , 0 ) & ~ ( 0x100 < < channel ) ) ;
snd_p16v_intr_disable ( emu , inte ) ;
//snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
epcm - > running = 0 ;
break ;
default :
result = - EINVAL ;
break ;
}
return result ;
}
2005-04-16 15:20:36 -07:00
/* pointer_playback callback */
static snd_pcm_uframes_t
2005-11-17 14:50:13 +01:00
snd_p16v_pcm_pointer_playback ( struct snd_pcm_substream * substream )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_pcm_substream_chip ( substream ) ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
struct snd_emu10k1_pcm * epcm = runtime - > private_data ;
2005-04-16 15:20:36 -07:00
snd_pcm_uframes_t ptr , ptr1 , ptr2 , ptr3 , ptr4 = 0 ;
int channel = substream - > pcm - > device - emu - > p16v_device_offset ;
if ( ! epcm - > running )
return 0 ;
ptr3 = snd_emu10k1_ptr20_read ( emu , PLAYBACK_LIST_PTR , channel ) ;
ptr1 = snd_emu10k1_ptr20_read ( emu , PLAYBACK_POINTER , channel ) ;
ptr4 = snd_emu10k1_ptr20_read ( emu , PLAYBACK_LIST_PTR , channel ) ;
if ( ptr3 ! = ptr4 ) ptr1 = snd_emu10k1_ptr20_read ( emu , PLAYBACK_POINTER , channel ) ;
ptr2 = bytes_to_frames ( runtime , ptr1 ) ;
ptr2 + = ( ptr4 > > 3 ) * runtime - > period_size ;
ptr = ptr2 ;
if ( ptr > = runtime - > buffer_size )
ptr - = runtime - > buffer_size ;
return ptr ;
}
2005-03-26 19:35:29 +01:00
/* pointer_capture callback */
static snd_pcm_uframes_t
2005-11-17 14:50:13 +01:00
snd_p16v_pcm_pointer_capture ( struct snd_pcm_substream * substream )
2005-03-26 19:35:29 +01:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_pcm_substream_chip ( substream ) ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
struct snd_emu10k1_pcm * epcm = runtime - > private_data ;
2005-03-26 19:35:29 +01:00
snd_pcm_uframes_t ptr , ptr1 , ptr2 = 0 ;
int channel = 0 ;
if ( ! epcm - > running )
return 0 ;
ptr1 = snd_emu10k1_ptr20_read ( emu , CAPTURE_POINTER , channel ) ;
ptr2 = bytes_to_frames ( runtime , ptr1 ) ;
ptr = ptr2 ;
if ( ptr > = runtime - > buffer_size ) {
ptr - = runtime - > buffer_size ;
2014-02-25 17:02:09 +01:00
dev_warn ( emu - > card - > dev , " buffer capture limited! \n " ) ;
2005-03-26 19:35:29 +01:00
}
2009-02-05 16:08:14 +01:00
/*
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev , " ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, "
2009-02-05 16:08:14 +01:00
" buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d \n " ,
ptr1 , ptr2 , ptr , ( int ) runtime - > buffer_size ,
( int ) runtime - > period_size , ( int ) runtime - > frame_bits ,
( int ) runtime - > rate ) ;
*/
2005-03-26 19:35:29 +01:00
return ptr ;
}
2005-04-16 15:20:36 -07:00
/* operators */
2016-09-02 00:13:10 +02:00
static const struct snd_pcm_ops snd_p16v_playback_front_ops = {
2005-04-16 15:20:36 -07:00
. open = snd_p16v_pcm_open_playback_front ,
. close = snd_p16v_pcm_close_playback ,
. prepare = snd_p16v_pcm_prepare_playback ,
. trigger = snd_p16v_pcm_trigger_playback ,
. pointer = snd_p16v_pcm_pointer_playback ,
} ;
2016-09-02 00:13:10 +02:00
static const struct snd_pcm_ops snd_p16v_capture_ops = {
2005-03-26 19:35:29 +01:00
. open = snd_p16v_pcm_open_capture ,
. close = snd_p16v_pcm_close_capture ,
. prepare = snd_p16v_pcm_prepare_capture ,
. trigger = snd_p16v_pcm_trigger_capture ,
. pointer = snd_p16v_pcm_pointer_capture ,
} ;
2015-01-02 12:24:49 +01:00
int snd_p16v_pcm ( struct snd_emu10k1 * emu , int device )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:50:13 +01:00
struct snd_pcm * pcm ;
struct snd_pcm_substream * substream ;
2005-04-16 15:20:36 -07:00
int err ;
2005-03-26 19:35:29 +01:00
int capture = 1 ;
2005-04-16 15:20:36 -07:00
2014-02-25 17:02:09 +01:00
/* dev_dbg(emu->card->dev, "snd_p16v_pcm called. device=%d\n", device); */
2005-04-16 15:20:36 -07:00
emu - > p16v_device_offset = device ;
2005-03-26 19:35:29 +01:00
2021-06-08 16:05:14 +02:00
err = snd_pcm_new ( emu - > card , " p16v " , device , 1 , capture , & pcm ) ;
if ( err < 0 )
2005-04-16 15:20:36 -07:00
return err ;
pcm - > private_data = emu ;
2005-03-26 19:35:29 +01:00
// Single playback 8 channel device.
// Single capture 2 channel device.
2005-04-16 15:20:36 -07:00
snd_pcm_set_ops ( pcm , SNDRV_PCM_STREAM_PLAYBACK , & snd_p16v_playback_front_ops ) ;
2005-03-26 19:35:29 +01:00
snd_pcm_set_ops ( pcm , SNDRV_PCM_STREAM_CAPTURE , & snd_p16v_capture_ops ) ;
2005-04-16 15:20:36 -07:00
pcm - > info_flags = 0 ;
pcm - > dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX ;
strcpy ( pcm - > name , " p16v " ) ;
2005-11-17 16:14:10 +01:00
emu - > pcm_p16v = pcm ;
2005-04-16 15:20:36 -07:00
for ( substream = pcm - > streams [ SNDRV_PCM_STREAM_PLAYBACK ] . substream ;
substream ;
substream = substream - > next ) {
2019-12-09 10:49:08 +01:00
snd_pcm_set_managed_buffer ( substream , SNDRV_DMA_TYPE_DEV ,
& emu - > pci - > dev ,
( 65536 - 64 ) * 8 ,
( 65536 - 64 ) * 8 ) ;
2009-02-05 16:08:14 +01:00
/*
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev ,
2009-02-05 16:08:14 +01:00
" preallocate playback substream: err=%d \n " , err ) ;
*/
2005-04-16 15:20:36 -07:00
}
for ( substream = pcm - > streams [ SNDRV_PCM_STREAM_CAPTURE ] . substream ;
substream ;
substream = substream - > next ) {
2019-12-09 10:49:08 +01:00
snd_pcm_set_managed_buffer ( substream , SNDRV_DMA_TYPE_DEV ,
& emu - > pci - > dev ,
65536 - 64 , 65536 - 64 ) ;
2009-02-05 16:08:14 +01:00
/*
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev ,
2009-02-05 16:08:14 +01:00
" preallocate capture substream: err=%d \n " , err ) ;
*/
2005-04-16 15:20:36 -07:00
}
return 0 ;
}
2005-12-22 17:01:20 +01:00
static int snd_p16v_volume_info ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo )
2005-04-16 15:20:36 -07:00
{
uinfo - > type = SNDRV_CTL_ELEM_TYPE_INTEGER ;
uinfo - > count = 2 ;
uinfo - > value . integer . min = 0 ;
uinfo - > value . integer . max = 255 ;
return 0 ;
}
2005-11-17 14:50:13 +01:00
static int snd_p16v_volume_get ( struct snd_kcontrol * kcontrol ,
2005-12-22 17:01:20 +01:00
struct snd_ctl_elem_value * ucontrol )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_kcontrol_chip ( kcontrol ) ;
2005-12-22 17:01:20 +01:00
int high_low = ( kcontrol - > private_value > > 8 ) & 0xff ;
int reg = kcontrol - > private_value & 0xff ;
u32 value ;
value = snd_emu10k1_ptr20_read ( emu , reg , high_low ) ;
if ( high_low ) {
ucontrol - > value . integer . value [ 0 ] = 0xff - ( ( value > > 24 ) & 0xff ) ; /* Left */
ucontrol - > value . integer . value [ 1 ] = 0xff - ( ( value > > 16 ) & 0xff ) ; /* Right */
2005-04-16 15:20:36 -07:00
} else {
2005-12-22 17:01:20 +01:00
ucontrol - > value . integer . value [ 0 ] = 0xff - ( ( value > > 8 ) & 0xff ) ; /* Left */
ucontrol - > value . integer . value [ 1 ] = 0xff - ( ( value > > 0 ) & 0xff ) ; /* Right */
2005-04-16 15:20:36 -07:00
}
2005-12-22 17:01:20 +01:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2005-11-17 14:50:13 +01:00
static int snd_p16v_volume_put ( struct snd_kcontrol * kcontrol ,
2005-12-22 17:01:20 +01:00
struct snd_ctl_elem_value * ucontrol )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_kcontrol_chip ( kcontrol ) ;
2005-12-22 17:01:20 +01:00
int high_low = ( kcontrol - > private_value > > 8 ) & 0xff ;
int reg = kcontrol - > private_value & 0xff ;
u32 value , oval ;
oval = value = snd_emu10k1_ptr20_read ( emu , reg , 0 ) ;
2005-04-16 15:20:36 -07:00
if ( high_low = = 1 ) {
value & = 0xffff ;
2005-12-22 17:01:20 +01:00
value | = ( ( 0xff - ucontrol - > value . integer . value [ 0 ] ) < < 24 ) |
( ( 0xff - ucontrol - > value . integer . value [ 1 ] ) < < 16 ) ;
2005-04-16 15:20:36 -07:00
} else {
value & = 0xffff0000 ;
2005-12-22 17:01:20 +01:00
value | = ( ( 0xff - ucontrol - > value . integer . value [ 0 ] ) < < 8 ) |
( ( 0xff - ucontrol - > value . integer . value [ 1 ] ) ) ;
2005-04-16 15:20:36 -07:00
}
2005-12-22 17:01:20 +01:00
if ( value ! = oval ) {
snd_emu10k1_ptr20_write ( emu , reg , 0 , value ) ;
return 1 ;
}
return 0 ;
2005-04-16 15:20:36 -07:00
}
2005-12-22 17:01:20 +01:00
static int snd_p16v_capture_source_info ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo )
2005-04-16 15:20:36 -07:00
{
2014-10-20 18:16:48 +02:00
static const char * const texts [ 8 ] = {
2005-12-22 17:01:20 +01:00
" SPDIF " , " I2S " , " SRC48 " , " SRCMulti_SPDIF " , " SRCMulti_I2S " ,
" CDIF " , " FX " , " AC97 "
} ;
2005-03-26 19:35:29 +01:00
2014-10-20 18:16:48 +02:00
return snd_ctl_enum_info ( uinfo , 1 , 8 , texts ) ;
2005-03-26 19:35:29 +01:00
}
2005-11-17 14:50:13 +01:00
static int snd_p16v_capture_source_get ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
2005-03-26 19:35:29 +01:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_kcontrol_chip ( kcontrol ) ;
2005-03-26 19:35:29 +01:00
ucontrol - > value . enumerated . item [ 0 ] = emu - > p16v_capture_source ;
return 0 ;
}
2005-11-17 14:50:13 +01:00
static int snd_p16v_capture_source_put ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
2005-03-26 19:35:29 +01:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_kcontrol_chip ( kcontrol ) ;
2005-03-26 19:35:29 +01:00
unsigned int val ;
int change = 0 ;
u32 mask ;
u32 source ;
val = ucontrol - > value . enumerated . item [ 0 ] ;
2007-11-15 13:16:02 +01:00
if ( val > 7 )
return - EINVAL ;
2005-03-26 19:35:29 +01:00
change = ( emu - > p16v_capture_source ! = val ) ;
if ( change ) {
emu - > p16v_capture_source = val ;
source = ( val < < 28 ) | ( val < < 24 ) | ( val < < 20 ) | ( val < < 16 ) ;
mask = snd_emu10k1_ptr20_read ( emu , BASIC_INTERRUPT , 0 ) & 0xffff ;
snd_emu10k1_ptr20_write ( emu , BASIC_INTERRUPT , 0 , source | mask ) ;
}
return change ;
}
2005-12-22 17:01:20 +01:00
static int snd_p16v_capture_channel_info ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo )
2005-05-07 15:34:13 +02:00
{
2014-10-20 18:16:48 +02:00
static const char * const texts [ 4 ] = { " 0 " , " 1 " , " 2 " , " 3 " , } ;
return snd_ctl_enum_info ( uinfo , 1 , 4 , texts ) ;
2005-05-07 15:34:13 +02:00
}
2005-11-17 14:50:13 +01:00
static int snd_p16v_capture_channel_get ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
2005-05-07 15:34:13 +02:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_kcontrol_chip ( kcontrol ) ;
2005-05-07 15:34:13 +02:00
ucontrol - > value . enumerated . item [ 0 ] = emu - > p16v_capture_channel ;
return 0 ;
}
2005-11-17 14:50:13 +01:00
static int snd_p16v_capture_channel_put ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
2005-05-07 15:34:13 +02:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = snd_kcontrol_chip ( kcontrol ) ;
2005-05-07 15:34:13 +02:00
unsigned int val ;
int change = 0 ;
u32 tmp ;
val = ucontrol - > value . enumerated . item [ 0 ] ;
2007-11-15 13:16:02 +01:00
if ( val > 3 )
return - EINVAL ;
2005-05-07 15:34:13 +02:00
change = ( emu - > p16v_capture_channel ! = val ) ;
if ( change ) {
emu - > p16v_capture_channel = val ;
tmp = snd_emu10k1_ptr20_read ( emu , CAPTURE_P16V_SOURCE , 0 ) & 0xfffc ;
snd_emu10k1_ptr20_write ( emu , CAPTURE_P16V_SOURCE , 0 , tmp | val ) ;
}
return change ;
}
2007-01-29 15:33:49 +01:00
static const DECLARE_TLV_DB_SCALE ( snd_p16v_db_scale1 , - 5175 , 25 , 1 ) ;
2005-05-07 15:34:13 +02:00
2005-12-22 17:01:20 +01:00
# define P16V_VOL(xname,xreg,xhl) { \
. iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , \
2006-07-22 17:02:10 +01:00
. access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_TLV_READ , \
2005-12-22 17:01:20 +01:00
. info = snd_p16v_volume_info , \
. get = snd_p16v_volume_get , \
. put = snd_p16v_volume_put , \
2006-08-17 16:23:07 +02:00
. tlv = { . p = snd_p16v_db_scale1 } , \
2005-12-22 17:01:20 +01:00
. private_value = ( ( xreg ) | ( ( xhl ) < < 8 ) ) \
}
2020-01-03 09:16:53 +01:00
static const struct snd_kcontrol_new p16v_mixer_controls [ ] = {
2005-12-22 17:01:20 +01:00
P16V_VOL ( " HD Analog Front Playback Volume " , PLAYBACK_VOLUME_MIXER9 , 0 ) ,
P16V_VOL ( " HD Analog Rear Playback Volume " , PLAYBACK_VOLUME_MIXER10 , 1 ) ,
P16V_VOL ( " HD Analog Center/LFE Playback Volume " , PLAYBACK_VOLUME_MIXER9 , 1 ) ,
P16V_VOL ( " HD Analog Side Playback Volume " , PLAYBACK_VOLUME_MIXER10 , 0 ) ,
P16V_VOL ( " HD SPDIF Front Playback Volume " , PLAYBACK_VOLUME_MIXER7 , 0 ) ,
P16V_VOL ( " HD SPDIF Rear Playback Volume " , PLAYBACK_VOLUME_MIXER8 , 1 ) ,
P16V_VOL ( " HD SPDIF Center/LFE Playback Volume " , PLAYBACK_VOLUME_MIXER7 , 1 ) ,
P16V_VOL ( " HD SPDIF Side Playback Volume " , PLAYBACK_VOLUME_MIXER8 , 0 ) ,
{
. iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
. name = " HD source Capture " ,
. info = snd_p16v_capture_source_info ,
. get = snd_p16v_capture_source_get ,
. put = snd_p16v_capture_source_put
} ,
{
. iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
. name = " HD channel Capture " ,
. info = snd_p16v_capture_channel_info ,
. get = snd_p16v_capture_channel_get ,
. put = snd_p16v_capture_channel_put
} ,
2005-05-07 15:34:13 +02:00
} ;
2005-12-22 17:01:20 +01:00
2012-12-06 12:35:10 -05:00
int snd_p16v_mixer ( struct snd_emu10k1 * emu )
2005-04-16 15:20:36 -07:00
{
2005-12-22 17:01:20 +01:00
int i , err ;
2005-11-17 14:50:13 +01:00
struct snd_card * card = emu - > card ;
2005-12-22 17:01:20 +01:00
for ( i = 0 ; i < ARRAY_SIZE ( p16v_mixer_controls ) ; i + + ) {
2021-06-08 16:05:14 +02:00
err = snd_ctl_add ( card , snd_ctl_new1 ( & p16v_mixer_controls [ i ] , emu ) ) ;
if ( err < 0 )
2005-12-22 17:01:20 +01:00
return err ;
}
2005-04-16 15:20:36 -07:00
return 0 ;
}
2012-08-14 18:12:04 +02:00
# ifdef CONFIG_PM_SLEEP
2005-11-17 16:14:10 +01:00
# define NUM_CHS 1 /* up to 4, but only first channel is used */
2012-12-06 12:35:10 -05:00
int snd_p16v_alloc_pm_buffer ( struct snd_emu10k1 * emu )
2005-11-17 16:14:10 +01:00
{
treewide: Use array_size() in vmalloc()
The vmalloc() function has no 2-factor argument form, so multiplication
factors need to be wrapped in array_size(). This patch replaces cases of:
vmalloc(a * b)
with:
vmalloc(array_size(a, b))
as well as handling cases of:
vmalloc(a * b * c)
with:
vmalloc(array3_size(a, b, c))
This does, however, attempt to ignore constant size factors like:
vmalloc(4 * 1024)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
vmalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
vmalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
vmalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
vmalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
vmalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
vmalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
vmalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
vmalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
vmalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
vmalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
vmalloc(
- sizeof(TYPE) * (COUNT_ID)
+ array_size(COUNT_ID, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * COUNT_ID
+ array_size(COUNT_ID, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * (COUNT_CONST)
+ array_size(COUNT_CONST, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * COUNT_CONST
+ array_size(COUNT_CONST, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(THING) * (COUNT_ID)
+ array_size(COUNT_ID, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * COUNT_ID
+ array_size(COUNT_ID, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * (COUNT_CONST)
+ array_size(COUNT_CONST, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * COUNT_CONST
+ array_size(COUNT_CONST, sizeof(THING))
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
vmalloc(
- SIZE * COUNT
+ array_size(COUNT, SIZE)
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
vmalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
vmalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
vmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
vmalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
vmalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
vmalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
vmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
vmalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
vmalloc(C1 * C2 * C3, ...)
|
vmalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants.
@@
expression E1, E2;
constant C1, C2;
@@
(
vmalloc(C1 * C2, ...)
|
vmalloc(
- E1 * E2
+ array_size(E1, E2)
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:27:11 -07:00
emu - > p16v_saved = vmalloc ( array_size ( NUM_CHS * 4 , 0x80 ) ) ;
2005-11-17 16:14:10 +01:00
if ( ! emu - > p16v_saved )
return - ENOMEM ;
return 0 ;
}
void snd_p16v_free_pm_buffer ( struct snd_emu10k1 * emu )
{
vfree ( emu - > p16v_saved ) ;
}
void snd_p16v_suspend ( struct snd_emu10k1 * emu )
{
int i , ch ;
unsigned int * val ;
val = emu - > p16v_saved ;
for ( ch = 0 ; ch < NUM_CHS ; ch + + )
for ( i = 0 ; i < 0x80 ; i + + , val + + )
* val = snd_emu10k1_ptr20_read ( emu , i , ch ) ;
}
void snd_p16v_resume ( struct snd_emu10k1 * emu )
{
int i , ch ;
unsigned int * val ;
val = emu - > p16v_saved ;
for ( ch = 0 ; ch < NUM_CHS ; ch + + )
for ( i = 0 ; i < 0x80 ; i + + , val + + )
snd_emu10k1_ptr20_write ( emu , i , ch , * val ) ;
}
# endif