Commit a1a1c402 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA update

   - CS46xx driver
     - DSP is started after initializing AC97 codecs
     - rewrite SPDIF output stuff
     - variable period size support on playback and capture
     - DAC volume mechanism  rewrite
     - IEC958 input volume mechanism rewrite
     - added "AC3 Mode Switch" in mixer
     - code cleanups
   - ENS1371 driver
     - added definitions for the ES1373 chip
     - added code to control IEC958 (S/PDIF) channel status register
parent a673e746
......@@ -196,80 +196,6 @@
#define BA1_OMNI_MEM 0x000E0000
/*
* The following define the offsets of the AC97 shadow registers, which appear
* as a virtual extension to the base address register zero memory range.
*/
#define AC97_REG_OFFSET_MASK 0x0000007EL
#define AC97_CODEC_NUMBER_MASK 0x00003000L
#define BA0_AC97_RESET 0x00001000L
#define BA0_AC97_MASTER_VOLUME 0x00001002L
#define BA0_AC97_HEADPHONE_VOLUME 0x00001004L
#define BA0_AC97_MASTER_VOLUME_MONO 0x00001006L
#define BA0_AC97_MASTER_TONE 0x00001008L
#define BA0_AC97_PC_BEEP_VOLUME 0x0000100AL
#define BA0_AC97_PHONE_VOLUME 0x0000100CL
#define BA0_AC97_MIC_VOLUME 0x0000100EL
#define BA0_AC97_LINE_IN_VOLUME 0x00001010L
#define BA0_AC97_CD_VOLUME 0x00001012L
#define BA0_AC97_VIDEO_VOLUME 0x00001014L
#define BA0_AC97_AUX_VOLUME 0x00001016L
#define BA0_AC97_PCM_OUT_VOLUME 0x00001018L
#define BA0_AC97_RECORD_SELECT 0x0000101AL
#define BA0_AC97_RECORD_GAIN 0x0000101CL
#define BA0_AC97_RECORD_GAIN_MIC 0x0000101EL
#define BA0_AC97_GENERAL_PURPOSE 0x00001020L
#define BA0_AC97_3D_CONTROL 0x00001022L
#define BA0_AC97_MODEM_RATE 0x00001024L
#define BA0_AC97_POWERDOWN 0x00001026L
#define BA0_AC97_EXT_AUDIO_ID 0x00001028L
#define BA0_AC97_EXT_AUDIO_POWER 0x0000102AL
#define BA0_AC97_PCM_FRONT_DAC_RATE 0x0000102CL
#define BA0_AC97_PCM_SURR_DAC_RATE 0x0000102EL
#define BA0_AC97_PCM_LFE_DAC_RATE 0x00001030L
#define BA0_AC97_PCM_LR_ADC_RATE 0x00001032L
#define BA0_AC97_MIC_ADC_RATE 0x00001034L
#define BA0_AC97_6CH_VOL_C_LFE 0x00001036L
#define BA0_AC97_6CH_VOL_SURROUND 0x00001038L
#define BA0_AC97_RESERVED_3A 0x0000103AL
#define BA0_AC97_EXT_MODEM_ID 0x0000103CL
#define BA0_AC97_EXT_MODEM_POWER 0x0000103EL
#define BA0_AC97_LINE1_CODEC_RATE 0x00001040L
#define BA0_AC97_LINE2_CODEC_RATE 0x00001042L
#define BA0_AC97_HANDSET_CODEC_RATE 0x00001044L
#define BA0_AC97_LINE1_CODEC_LEVEL 0x00001046L
#define BA0_AC97_LINE2_CODEC_LEVEL 0x00001048L
#define BA0_AC97_HANDSET_CODEC_LEVEL 0x0000104AL
#define BA0_AC97_GPIO_PIN_CONFIG 0x0000104CL
#define BA0_AC97_GPIO_PIN_TYPE 0x0000104EL
#define BA0_AC97_GPIO_PIN_STICKY 0x00001050L
#define BA0_AC97_GPIO_PIN_WAKEUP 0x00001052L
#define BA0_AC97_GPIO_PIN_STATUS 0x00001054L
#define BA0_AC97_MISC_MODEM_AFE_STAT 0x00001056L
#define BA0_AC97_RESERVED_58 0x00001058L
#define BA0_AC97_CRYSTAL_REV_N_FAB_ID 0x0000105AL
#define BA0_AC97_TEST_AND_MISC_CTRL 0x0000105CL
#define BA0_AC97_AC_MODE 0x0000105EL
#define BA0_AC97_MISC_CRYSTAL_CONTROL 0x00001060L
#define BA0_AC97_LINE1_HYPRID_CTRL 0x00001062L
#define BA0_AC97_VENDOR_RESERVED_64 0x00001064L
#define BA0_AC97_VENDOR_RESERVED_66 0x00001066L
#define BA0_AC97_SPDIF_CONTROL 0x00001068L
#define BA0_AC97_VENDOR_RESERVED_6A 0x0000106AL
#define BA0_AC97_VENDOR_RESERVED_6C 0x0000106CL
#define BA0_AC97_VENDOR_RESERVED_6E 0x0000106EL
#define BA0_AC97_VENDOR_RESERVED_70 0x00001070L
#define BA0_AC97_VENDOR_RESERVED_72 0x00001072L
#define BA0_AC97_VENDOR_RESERVED_74 0x00001074L
#define BA0_AC97_CAL_ADDRESS 0x00001076L
#define BA0_AC97_CAL_DATA 0x00001078L
#define BA0_AC97_VENDOR_RESERVED_7A 0x0000107AL
#define BA0_AC97_VENDOR_ID1 0x0000107CL
#define BA0_AC97_VENDOR_ID2 0x0000107EL
/*
* The following defines are for the flags in the host interrupt status
* register.
......@@ -1790,6 +1716,7 @@ struct _snd_cs46xx {
struct pci_dev *pci;
snd_card_t *card;
snd_pcm_t *pcm;
snd_rawmidi_t *rmidi;
snd_rawmidi_substream_t *midi_input;
snd_rawmidi_substream_t *midi_output;
......@@ -1814,12 +1741,15 @@ struct _snd_cs46xx {
struct pm_dev *pm_dev;
#endif
#ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
int current_gpio;
int current_gpio;
#endif
#ifdef CONFIG_SND_CS46XX_NEW_DSP
struct semaphore spos_mutex;
dsp_spos_instance_t * dsp_spos_instance;
snd_pcm_t *pcm_rear;
snd_pcm_t *pcm_iec958;
#else /* for compatibility */
cs46xx_pcm_t *playback_pcm;
unsigned int play_ctl;
......@@ -1832,8 +1762,11 @@ int snd_cs46xx_create(snd_card_t *card,
cs46xx_t **rcodec);
int snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
int snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
int snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
int snd_cs46xx_mixer(cs46xx_t *chip);
int snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rmidi);
int snd_cs46xx_start_dsp(cs46xx_t *chip);
void snd_cs46xx_gameport(cs46xx_t *chip);
#ifdef CONFIG_PM
......
......@@ -36,24 +36,35 @@
#define SEGTYPE_SP_COEFFICIENT 0x00000004
#define DSP_SPOS_UU 0x0deadul /* unused */
#define DSP_SPOS_DC 0x0badul /* dont care */
#define DSP_SPOS_DC_DC 0x0bad0badul /* dont care */
#define DSP_SPOS_DC 0x0badul /* dont care */
#define DSP_SPOS_DC_DC 0x0bad0badul /* dont care */
#define DSP_SPOS_UUUU 0xdeadc0edul /* unused */
#define DSP_SPOS_UUHI 0xdeadul
#define DSP_SPOS_UULO 0xc0edul
#define DSP_SPOS_DCDC 0x0badf1d0ul /* dont care */
#define DSP_SPOS_DCDC 0x0badf1d0ul /* dont care */
#define DSP_SPOS_DCDCHI 0x0badul
#define DSP_SPOS_DCDCLO 0xf1d0ul
#define DSP_MAX_TASK_NAME 60
#define DSP_MAX_TASK_NAME 60
#define DSP_MAX_SYMBOL_NAME 100
#define DSP_MAX_SCB_NAME 60
#define DSP_MAX_SCB_DESC 200
#define DSP_MAX_TASK_DESC 50
#define DSP_MAX_SCB_NAME 60
#define DSP_MAX_SCB_DESC 200
#define DSP_MAX_TASK_DESC 50
#define DSP_MAX_PCM_CHANNELS 32
#define DSP_MAX_SRC_NR 6
#define DSP_PCM_MAIN_CHANNEL 1
#define DSP_PCM_REAR_CHANNEL 2
#define DSP_PCM_CENTER_CHANNEL 3
#define DSP_PCM_LFE_CHANNEL 4
#define DSP_IEC958_CHANNEL 5
#define DSP_SPDIF_STATUS_OUTPUT_ENABLED 1
#define DSP_SPDIF_STATUS_PLAYBACK_OPEN 2
#define DSP_SPDIF_STATUS_HW_ENABLED 4
#define DSP_SPDIF_STATUS_AC3_MODE 8
struct _dsp_module_desc_t;
typedef struct _symbol_entry_t {
......@@ -129,6 +140,8 @@ typedef struct _pcm_channel_descriptor_t {
u32 unlinked;
dsp_scb_descriptor_t * pcm_reader_scb;
dsp_scb_descriptor_t * src_scb;
dsp_scb_descriptor_t * mixer_scb;
int pcm_channel_id;
void * private_data;
} pcm_channel_descriptor_t;
......@@ -141,8 +154,14 @@ typedef struct _dsp_spos_instance_t {
segment_desc_t code;
/* PCM playback */
/* Main PCM playback mixer */
dsp_scb_descriptor_t * master_mix_scb;
u16 dac_volume_right;
u16 dac_volume_left;
/* Rear PCM playback mixer */
dsp_scb_descriptor_t * rear_mix_scb;
int npcm_channels;
int nsrc_scb;
pcm_channel_descriptor_t pcm_channels[DSP_MAX_PCM_CHANNELS];
......@@ -175,7 +194,8 @@ typedef struct _dsp_spos_instance_t {
/* SPDIF status */
int spdif_status_out;
int spdif_status_in;
u32 spdif_input_volume;
u16 spdif_input_volume_right;
u16 spdif_input_volume_left;
/* SPDIF input sample rate converter */
dsp_scb_descriptor_t * spdif_in_src;
......@@ -191,6 +211,12 @@ typedef struct _dsp_spos_instance_t {
/* reference snooper */
dsp_scb_descriptor_t * ref_snoop_scb;
/* SPDIF output PCM reference */
dsp_scb_descriptor_t * spdif_pcm_input_scb;
/* asynch TX task */
dsp_scb_descriptor_t * asynch_tx_scb;
/* record sources */
dsp_scb_descriptor_t * pcm_input;
dsp_scb_descriptor_t * adc_input;
......@@ -199,4 +225,3 @@ typedef struct _dsp_spos_instance_t {
} dsp_spos_instance_t;
#endif /* __DSP_SPOS_H__ */
......@@ -110,6 +110,16 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
if ((err = snd_cs46xx_pcm_rear(chip,1, NULL)) < 0) {
snd_card_free(card);
return err;
}
if ((err = snd_cs46xx_pcm_iec958(chip,2,NULL)) < 0) {
snd_card_free(card);
return err;
}
#endif
if ((err = snd_cs46xx_mixer(chip)) < 0) {
snd_card_free(card);
return err;
......@@ -118,6 +128,12 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
if ((err = snd_cs46xx_start_dsp(chip)) < 0) {
snd_card_free(card);
return err;
}
snd_cs46xx_gameport(chip);
strcpy(card->driver, "CS46xx");
......@@ -132,6 +148,7 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
pci_set_drvdata(pci, chip);
dev++;
return 0;
......
This diff is collapsed.
......@@ -35,9 +35,17 @@
#define CS46XX_BA1_REG_SIZE 0x0100
#define CS46XX_PERIOD_SIZE 2048
#ifdef CONFIG_SND_CS46XX_NEW_DSP
#define CS46XX_MIN_PERIOD_SIZE 1
#define CS46XX_MAX_PERIOD_SIZE 1024*1024
#else
#define CS46XX_MIN_PERIOD_SIZE 2048
#define CS46XX_MAX_PERIOD_SIZE 2048
#endif
#define CS46XX_FRAGS 2
#define CS46XX_BUFFER_SIZE CS46XX_PERIOD_SIZE * CS46XX_FRAGS
/* #define CS46XX_BUFFER_SIZE CS46XX_MAX_PERIOD_SIZE * CS46XX_FRAGS */
#define SCB_NO_PARENT 0
#define SCB_ON_PARENT_NEXT_SCB 1
......@@ -51,6 +59,10 @@ extern snd_pcm_ops_t snd_cs46xx_playback_ops;
extern snd_pcm_ops_t snd_cs46xx_playback_indirect_ops;
extern snd_pcm_ops_t snd_cs46xx_capture_ops;
extern snd_pcm_ops_t snd_cs46xx_capture_indirect_ops;
extern snd_pcm_ops_t snd_cs46xx_playback_rear_ops;
extern snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops;
extern snd_pcm_ops_t snd_cs46xx_playback_iec958_ops;
extern snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops;
/*
......@@ -96,6 +108,7 @@ int snd_cs46xx_download (cs46xx_t *chip,u32 *src,unsigned lon
unsigned long len);
int snd_cs46xx_clear_BA1(cs46xx_t *chip,unsigned long offset,unsigned long len);
int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip);
int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip);
int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip);
int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip);
int cs46xx_dsp_disable_spdif_in (cs46xx_t *chip);
......@@ -185,7 +198,8 @@ dsp_scb_descriptor_t * cs46xx_dsp_create_magic_snoop_scb(cs46xx_t * chip,char *
dsp_scb_descriptor_t * snoop_scb,
dsp_scb_descriptor_t * parent_scb,
int scb_child_type);
pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr);
pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr,
int pcm_channel_id);
void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,
pcm_channel_descriptor_t * pcm_channel);
void cs46xx_dsp_set_src_sample_rate(cs46xx_t * chip,dsp_scb_descriptor_t * src,
......@@ -194,6 +208,15 @@ int cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_de
int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel);
dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source,
u16 addr,char * scb_name);
int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src);
int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src);
int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src);
int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src);
int cs46xx_iec958_pre_open (cs46xx_t *chip);
int cs46xx_iec958_post_close (cs46xx_t *chip);
int cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip,
pcm_channel_descriptor_t * pcm_channel,
int period_size);
int cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip,
int period_size);
int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 right,u16 left);
int cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 right,u16 left);
#endif /* __CS46XX_LIB_H__ */
......@@ -257,7 +257,10 @@ dsp_spos_instance_t * cs46xx_dsp_spos_create (cs46xx_t * chip)
ins->spdif_in_sample_rate = 48000;
/* maximize volume */
ins->spdif_input_volume = 0x80008000;
ins->dac_volume_right = 0x8000;
ins->dac_volume_left = 0x8000;
ins->spdif_input_volume_right = 0x8000;
ins->spdif_input_volume_left = 0x8000;
return ins;
}
......@@ -1017,11 +1020,10 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
dsp_scb_descriptor_t * codec_in_scb;
dsp_scb_descriptor_t * src_task_scb;
dsp_scb_descriptor_t * master_mix_scb;
dsp_scb_descriptor_t * rear_mix_scb;
dsp_scb_descriptor_t * record_mix_scb;
dsp_scb_descriptor_t * write_back_scb;
dsp_scb_descriptor_t * vari_decimate_scb;
dsp_scb_descriptor_t * pcm_serial_input_task;
dsp_scb_descriptor_t * asynch_tx_scb;
dsp_scb_descriptor_t * sec_codec_out_scb;
dsp_scb_descriptor_t * magic_snoop_scb;
......@@ -1095,6 +1097,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
ins->the_null_scb->sub_list_ptr = ins->the_null_scb;
ins->the_null_scb->next_scb_ptr = ins->the_null_scb;
ins->the_null_scb->parent_scb_ptr = NULL;
cs46xx_dsp_proc_register_scb_desc (chip,ins->the_null_scb);
}
{
......@@ -1264,9 +1267,9 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
/* create codec in */
codec_in_scb = cs46xx_dsp_create_codec_in_scb(chip,"CodecInSCB",0x0010,0x00A0,
CODEC_INPUT_BUF1,
CODECIN_SCB_ADDR,codec_out_scb,
SCB_ON_PARENT_NEXT_SCB);
CODEC_INPUT_BUF1,
CODECIN_SCB_ADDR,codec_out_scb,
SCB_ON_PARENT_NEXT_SCB);
if (!codec_in_scb) goto _fail_end;
ins->codec_in_scb = codec_in_scb;
......@@ -1309,46 +1312,38 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
/* create secondary CODEC output */
sec_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_II",0x0010,0x0040,
OUTPUTSNOOP_SCB_ADDR,
REAR_MIXER_SCB_ADDR,
SEC_CODECOUT_SCB_ADDR,codec_in_scb,
SCB_ON_PARENT_NEXT_SCB);
if (!sec_codec_out_scb) goto _fail_end;
/* create the rear PCM channel mixer SCB */
rear_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RearMixerSCB",
MIX_SAMPLE_BUF3,
REAR_MIXER_SCB_ADDR,
sec_codec_out_scb,
SCB_ON_PARENT_SUBLIST_SCB);
ins->rear_mix_scb = rear_mix_scb;
if (!rear_mix_scb) goto _fail_end;
/* the magic snooper */
magic_snoop_scb = cs46xx_dsp_create_magic_snoop_scb (chip,"MagicSnoopSCB_I",OUTPUTSNOOP_SCB_ADDR,
OUTPUT_SNOOP_BUFFER,
codec_out_scb,
sec_codec_out_scb,
SCB_ON_PARENT_SUBLIST_SCB);
SCB_ON_PARENT_NEXT_SCB);
if (!magic_snoop_scb) goto _fail_end;
ins->ref_snoop_scb = magic_snoop_scb;
/* The asynch. transfer task */
asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
SPDIFO_SCB_INST,
SPDIFO_IP_OUTPUT_BUFFER1,
magic_snoop_scb,
SCB_ON_PARENT_NEXT_SCB);
if (!asynch_tx_scb) goto _fail_end;
/* pcm input */
pcm_serial_input_task = cs46xx_dsp_create_pcm_serial_input_scb(chip,"PCMSerialInput_II",
PCMSERIALINII_SCB_ADDR,
magic_snoop_scb,asynch_tx_scb,
SCB_ON_PARENT_SUBLIST_SCB);
if (!pcm_serial_input_task) goto _fail_end;
/* SP IO access */
if (!cs46xx_dsp_create_spio_write_scb(chip,"SPIOWriteSCB",SPIOWRITE_SCB_ADDR,
asynch_tx_scb,
magic_snoop_scb,
SCB_ON_PARENT_NEXT_SCB))
goto _fail_end;
/* SPDIF input sampel rate converter */
src_task_scb = cs46xx_dsp_create_src_task_scb(chip,"SrcTaskSCB_SPDIFI",
SRC_OUTPUT_BUF1,
......@@ -1505,6 +1500,7 @@ int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry)
};
spdifo_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFOSCB",(u32 *)&spdifo_scb,SPDIFO_SCB_INST);
snd_assert(spdifo_scb_desc, return -EIO);
spdifi_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFISCB",(u32 *)&spdifi_scb,SPDIFI_SCB_INST);
snd_assert(spdifi_scb_desc, return -EIO);
......@@ -1530,6 +1526,11 @@ int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry)
is the FG task tree */
fg_entry->parent_scb_ptr = spdifo_scb_desc;
/* for proc fs */
cs46xx_dsp_proc_register_scb_desc (chip,spdifo_scb_desc);
cs46xx_dsp_proc_register_scb_desc (chip,spdifi_scb_desc);
cs46xx_dsp_proc_register_scb_desc (chip,async_codec_scb_desc);
/* Async MASTER ENABLE, affects both SPDIF input and output */
snd_cs46xx_pokeBA0(chip, BA0_ASER_MASTER, 0x1 );
}
......@@ -1537,7 +1538,7 @@ int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry)
return 0;
}
int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip)
int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip)
{
dsp_spos_instance_t * ins = chip->dsp_spos_instance;
......@@ -1547,29 +1548,11 @@ int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip)
/* SPDIF output MASTER ENABLE */
cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x80000000);
/* right and left validate bit
NOTE: 0x80000000 and enables the SCMC protection on stream
*/
/* right and left validate bit */
cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x00000000 | (1 << 13) | (1 << 12));
/* monitor state */
ins->spdif_status_out = 1;
return 0;
}
int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip)
{
dsp_spos_instance_t * ins = chip->dsp_spos_instance;
/* disable SPDIF output FIFO slot */
snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, 0);
/* SPDIF output MASTER DISABLE */
cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x0);
/* monitor state */
ins->spdif_status_out = 0;
ins->spdif_status_out |= DSP_SPDIF_STATUS_HW_ENABLED;
return 0;
}
......@@ -1605,8 +1588,10 @@ int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip)
cs46xx_src_link(chip,ins->spdif_in_src);
/* restore SPDIF input volume */
snd_cs46xx_poke(chip, (ASYNCRX_SCB_ADDR + 0xE) << 2, ins->spdif_input_volume);
snd_cs46xx_poke(chip, (ASYNCRX_SCB_ADDR + 0xF) << 2, ins->spdif_input_volume);
cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,
ins->spdif_input_volume_right,
ins->spdif_input_volume_left);
spin_unlock_irq(&chip->reg_lock);
/* set SPDIF input sample rate and unmute
......@@ -1739,3 +1724,41 @@ int cs46xx_poke_via_dsp (cs46xx_t *chip,u32 address,u32 data)
return 0;
}
int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 right,u16 left)
{
int i;
dsp_spos_instance_t * ins = chip->dsp_spos_instance;
down(&chip->spos_mutex);
ins->dac_volume_right = right;
ins->dac_volume_left = left;
for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) {
if (ins->pcm_channels[i].active &&
!ins->pcm_channels[i].unlinked) {
cs46xx_dsp_scb_set_volume (chip,ins->pcm_channels[i].pcm_reader_scb,
right,left);
}
}
up(&chip->spos_mutex);
return 0;
}
int cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 right,u16 left) {
dsp_spos_instance_t * ins = chip->dsp_spos_instance;
down(&chip->spos_mutex);
cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,
right,left);
ins->spdif_input_volume_right = right;
ins->spdif_input_volume_left = left;
up(&chip->spos_mutex);
return 0;
}
......@@ -73,7 +73,10 @@ typedef enum {
#define SPDIFI_IP_OUTPUT_BUFFER1 0x0E00
#define SPDIFO_IP_OUTPUT_BUFFER1 0x1000
#define MIX_SAMPLE_BUF1 0x1400
#define MIX_SAMPLE_BUF2 0x3000
#define MIX_SAMPLE_BUF2 0x2D00
#define MIX_SAMPLE_BUF3 0x2E00
#define MIX_SAMPLE_BUF4 0x2F00
#define MIX_SAMPLE_BUF5 0x3000
/* Task stack address */
#define HFG_STACK 0x066A
......@@ -104,6 +107,8 @@ typedef enum {
#define OUTPUTSNOOPII_SCB_ADDR 0x150
#define PCMSERIALIN_PCM_SCB_ADDR 0x160
#define RECORD_MIXER_SCB_ADDR 0x170
#define REAR_MIXER_SCB_ADDR 0x180
#define SPDIF_MIXER_SCB_ADDR 0x190
/* hyperforground SCB's*/
#define HFG_TREE_SCB 0xBA0
......@@ -123,6 +128,7 @@ typedef enum {
#define SCBfuncEntryPtr 0xA
#define SRCCorPerGof 0x2
#define SRCPhiIncr6Int26Frac 0xd
#define SCBVolumeCtrl 0xe
/* conf */
#define UseASER1Input 1
......@@ -179,5 +185,22 @@ typedef enum {
#define SP_SPDOUT_CONTROL 0x804D
#define SP_SPDOUT_CSUV 0x808E
static inline void cs46xx_dsp_spos_update_scb (cs46xx_t * chip,dsp_scb_descriptor_t * scb)
{
/* update nextSCB and subListPtr in SCB */
snd_cs46xx_poke(chip,
(scb->address + SCBsubListPtr) << 2,
(scb->sub_list_ptr->address << 0x10) |
(scb->next_scb_ptr->address));
}
static inline void cs46xx_dsp_scb_set_volume (cs46xx_t * chip,dsp_scb_descriptor_t * scb,
u16 right,u16 left) {
unsigned int val = ((0xffff - right) << 16 | (0xffff - left));
snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl) << 2, val);
snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl + 1) << 2, val);
}
#endif /* __DSP_SPOS_H__ */
#endif /* CONFIG_SND_CS46XX_NEW_DSP */
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment