Commit 80bf8e05 authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Linus Torvalds

[PATCH] ALSA update [10/10] - 2002/08/05

  - CS46xx
    - fixed capture with new DSP firmware
    - multiple pcm playback streams
    - pcm playback instance is allocated dynamically
    - fixed detection of secondary codec
  - changed ctl/rawmidi/timer read() code to follow POSIX standard - when some data are ready, return immediately
  - RME96 - added 32 bit sample formats for ADAT
parent 7ba59717
......@@ -195,6 +195,81 @@
#define BA1_FRSC 0x00030038
#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.
......@@ -1629,10 +1704,11 @@
#define POWER_DOWN_ALL 0x7f0f
/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
#define MAX_NR_AC97 4
#define CS46XX_PRIMARY_CODEC_INDEX 0
#define MAX_NR_AC97 4
#define CS46XX_PRIMARY_CODEC_INDEX 0
#define CS46XX_SECONDARY_CODEC_INDEX 1
#define CS46XX_SECONDARY_CODEC_OFFSET 0x80
#define CS46XX_DSP_CAPTURE_CHANNEL 1
/*
*
......
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc2"
#define CONFIG_SND_DATE " (Thu Aug 01 15:59:56 2002 UTC)"
#define CONFIG_SND_DATE " (Mon Aug 05 14:24:05 2002 UTC)"
......@@ -660,7 +660,7 @@ static ssize_t snd_ctl_read(struct file *file, char *buffer, size_t count, loff_
snd_kctl_event_t *kev;
while (list_empty(&ctl->events)) {
wait_queue_t wait;
if (file->f_flags & O_NONBLOCK) {
if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
err = -EAGAIN;
goto __end;
}
......
......@@ -943,7 +943,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char *buf, size_t count, loff
spin_lock_irq(&runtime->lock);
while (!snd_rawmidi_ready(substream)) {
wait_queue_t wait;
if (file->f_flags & O_NONBLOCK) {
if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
spin_unlock_irq(&runtime->lock);
return result > 0 ? result : -EAGAIN;
}
......
......@@ -1270,7 +1270,7 @@ static ssize_t snd_timer_user_read(struct file *file, char *buffer, size_t count
while (!tu->qused) {
wait_queue_t wait;
if (file->f_flags & O_NONBLOCK) {
if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
spin_unlock_irq(&tu->qlock);
err = -EAGAIN;
break;
......@@ -1285,6 +1285,7 @@ static ssize_t snd_timer_user_read(struct file *file, char *buffer, size_t count
spin_lock_irq(&tu->qlock);
remove_wait_queue(&tu->qchange_sleep, &wait);
set_current_state(TASK_RUNNING);
if (signal_pending(current)) {
err = -ERESTARTSYS;
......@@ -1307,7 +1308,7 @@ static ssize_t snd_timer_user_read(struct file *file, char *buffer, size_t count
result += sizeof(snd_timer_read_t);
buffer += sizeof(snd_timer_read_t);
}
return err? err: result;
return result > 0 ? result : err;
}
static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
......
......@@ -8,11 +8,12 @@
* --
*
* TODO:
* We need a DSP code to support multichannel outputs and S/PDIF.
* Unfortunately, it seems that Cirrus Logic, Inc. is not willing
* to provide us sufficient information about the DSP processor,
* so we can't update the driver.
* SPDIF input.
* Secondary CODEC on some soundcards
*
* NOTE: with CONFIG_SND_CS46XX_NEW_DSP unset uses old DSP image (which
* is default configuration), no SPDIF, no secondary codec, no
* multi channel PCM. But known to work.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -334,7 +335,6 @@ int snd_cs46xx_download(cs46xx_t *chip,
#ifdef CONFIG_SND_CS46XX_NEW_DSP
// #include "imgs/cwcemb80.h"
#include "imgs/cwc4630.h"
#include "imgs/cwcasync.h"
#include "imgs/cwcsnoop.h"
......@@ -880,12 +880,14 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
if (substream->runtime->periods != CS46XX_FRAGS)
snd_cs46xx_playback_transfer(substream, 0);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
if (cpcm->pcm_channel->unlinked)
cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel);
if (substream->runtime->periods != CS46XX_FRAGS)
snd_cs46xx_playback_transfer(substream, 0);
#else
if (substream->runtime->periods != CS46XX_FRAGS)
snd_cs46xx_playback_transfer(substream, 0);
{ unsigned int tmp;
tmp = snd_cs46xx_peek(chip, BA1_PCTL);
tmp &= 0x0000ffff;
......@@ -1165,7 +1167,7 @@ static void snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) {
if (i <= 15) {
if ( status1 & (1 << i) ) {
if (i == 1) {
if (i == CS46XX_DSP_CAPTURE_CHANNEL) {
if (chip->capt.substream)
snd_pcm_period_elapsed(chip->capt.substream);
} else {
......@@ -2447,6 +2449,106 @@ static void amp_none(cs46xx_t *chip, int change)
{
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
static int voyetra_setup_eapd_slot(cs46xx_t *chip)
{
int i;
u32 idx;
u16 modem_power,pin_config,logic_type,valid_slots,status;
snd_printd ("cs46xx: cs46xx_setup_eapd_slot()+\n");
/*
* Clear PRA. The Bonzo chip will be used for GPIO not for modem
* stuff.
*/
if(chip->nr_ac97_codecs != 2)
{
snd_printk (KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() - no secondary codec configured\n");
return -EINVAL;
}
modem_power = snd_cs46xx_codec_read (chip,
BA0_AC97_EXT_MODEM_POWER,
CS46XX_SECONDARY_CODEC_INDEX);
modem_power &=0xFEFF;
snd_cs46xx_codec_write(chip,
BA0_AC97_EXT_MODEM_POWER, modem_power,
CS46XX_SECONDARY_CODEC_INDEX);
/*
* Set GPIO pin's 7 and 8 so that they are configured for output.
*/
pin_config = snd_cs46xx_codec_read (chip,
BA0_AC97_GPIO_PIN_CONFIG,
CS46XX_SECONDARY_CODEC_INDEX);
pin_config &=0x27F;
snd_cs46xx_codec_write(chip,
BA0_AC97_GPIO_PIN_CONFIG, pin_config,
CS46XX_SECONDARY_CODEC_INDEX);
/*
* Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic.
*/
logic_type = snd_cs46xx_codec_read(chip, BA0_AC97_GPIO_PIN_TYPE,
CS46XX_SECONDARY_CODEC_INDEX);
logic_type &=0x27F;
snd_cs46xx_codec_write (chip, BA0_AC97_GPIO_PIN_TYPE, logic_type,
CS46XX_SECONDARY_CODEC_INDEX);
valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV);
valid_slots |= 0x200;
snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);
/*
* Fill slots 12 with the correct value for the GPIO pins.
*/
for(idx = 0x90; idx <= 0x9F; idx++) {
/*
* Initialize the fifo so that bits 7 and 8 are on.
*
* Remember that the GPIO pins in bonzo are shifted by 4 bits to
* the left. 0x1800 corresponds to bits 7 and 8.
*/
snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800);
/*
* Make sure the previous FIFO write operation has completed.
*/
for(i = 0; i < 5; i++){
status = snd_cs46xx_peekBA0(chip, BA0_SERBST);
if( !(status & SERBST_WBSY) ) {
break;
}
mdelay(100);
}
if(status & SERBST_WBSY) {
snd_printk( KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() " \
"Failure to write the GPIO pins for slot 12.\n");
return -EINVAL;
}
/*
* Write the serial port FIFO index.
*/
snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
/*
* Tell the serial port to load the new value into the FIFO location.
*/
snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
}
return 0;
}
#endif
/*
* Crystal EAPD mode
*/
......@@ -2477,6 +2579,12 @@ static void amp_voyetra(cs46xx_t *chip, int change)
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->eapd_switch->id);
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
if (chip->amplifier && !old) {
voyetra_setup_eapd_slot(chip);
}
#endif
}
......
......@@ -735,7 +735,7 @@ static void cs46xx_dsp_proc_sample_dump_read (snd_info_entry_t *entry, snd_info_
snd_iprintf(buffer,"\nOUTPUT_SNOOP:\n");
col = 0;
for (i = 0x1200;i < 0x1240; i += sizeof(u32),col ++) {
for (i = OUTPUT_SNOOP_BUFFER;i < OUTPUT_SNOOP_BUFFER + 0x40; i += sizeof(u32),col ++) {
if (col == 4) {
snd_iprintf(buffer,"\n");
col = 0;
......@@ -748,9 +748,9 @@ static void cs46xx_dsp_proc_sample_dump_read (snd_info_entry_t *entry, snd_info_
snd_iprintf(buffer,"%08X ",readl(dst + i));
}
snd_iprintf(buffer,"\n...\n");
snd_iprintf(buffer,"\nCODEC_INPUT_BUF1: \n");
col = 0;
for (i = 0x12D0;i < 0x1310; i += sizeof(u32),col ++) {
for (i = CODEC_INPUT_BUF1;i < CODEC_INPUT_BUF1 + 0x40; i += sizeof(u32),col ++) {
if (col == 4) {
snd_iprintf(buffer,"\n");
col = 0;
......@@ -763,20 +763,23 @@ static void cs46xx_dsp_proc_sample_dump_read (snd_info_entry_t *entry, snd_info_
snd_iprintf(buffer,"%08X ",readl(dst + i));
}
snd_iprintf(buffer,"\n");
}
snd_iprintf(buffer,"\nWRITE_BACK_BUF1: \n");
col = 0;
for (i = WRITE_BACK_BUF1;i < WRITE_BACK_BUF1 + 0x40; i += sizeof(u32),col ++) {
if (col == 4) {
snd_iprintf(buffer,"\n");
col = 0;
}
#if 0
static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int subidx)
{
int reg, val;
if (col == 0) {
snd_iprintf(buffer, "%04X ",i);
}
for (reg = 0; reg < 0x80; reg += 2) {
val = snd_ac97_read(ac97, reg);
snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val);
snd_iprintf(buffer,"%08X ",readl(dst + i));
}
snd_iprintf(buffer,"\n");
}
#endif
int cs46xx_dsp_proc_init (snd_card_t * card, cs46xx_t *chip)
{
......@@ -1349,9 +1352,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,
MIX_SAMPLE_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;
/* create write back scb */
......
......@@ -697,7 +697,7 @@ cs46xx_dsp_create_mix_to_ostream_scb(cs46xx_t * chip,char * scb_name,
DMA_RQ_C2_AC_NONE +
DMA_RQ_C2_SIGNAL_DEST_PINGPONG +
1,
CS46XX_DSP_CAPTURE_CHANNEL,
DMA_RQ_SD_SP_SAMPLE_ADDR +
mix_buffer_addr,
0x0
......@@ -1108,7 +1108,7 @@ pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sa
/* virtual channel reserved
for capture */
if (i == 1) continue;
if (i == CS46XX_DSP_CAPTURE_CHANNEL) continue;
if (ins->pcm_channels[i].active) {
if (!src_scb && ins->pcm_channels[i].sample_rate == sample_rate) {
......
......@@ -437,7 +437,8 @@ static snd_pcm_hardware_t snd_rme96_playback_adat_info =
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE),
formats: SNDRV_PCM_FMTBIT_S16_LE,
formats: (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE),
rates: (SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
rate_min: 44100,
......@@ -461,7 +462,8 @@ static snd_pcm_hardware_t snd_rme96_capture_adat_info =
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE),
formats: SNDRV_PCM_FMTBIT_S16_LE,
formats: (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE),
rates: (SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
rate_min: 44100,
......
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