Commit b35a6301 authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Jaroslav Kysela

[PATCH] ALSA update [1/12] - 2002/08/09

  - Corrections for PCM sample silence (24-bits)
  - OPL3 code fixes (delays)
  - CS4281
    - added the power management code
    - added mixer controls for internal FM and PCM volumes
  - EMU10K1
    - fixed the dma mask
  - ICE1712
    - replaced EREMOTE with EIO
    - check the return value from ews88mt_chip_select()
  - Maestro3
    - corrected the wrong pci id for inspiron 8000
    - use the quirk list for gpio workarounds
parent 1d819b9d
/* include/version.h. Generated automatically by configure. */ /* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc2" #define CONFIG_SND_VERSION "0.9.0rc2"
#define CONFIG_SND_DATE " (Mon Aug 05 14:24:05 2002 UTC)" #define CONFIG_SND_DATE " (Fri Aug 09 11:49:03 2002 UTC)"
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* 2002-04-04 Tomas Kasparek better rates handling (allow non-standard rates) * 2002-04-04 Tomas Kasparek better rates handling (allow non-standard rates)
*/ */
/* $Id: sa11xx-uda1341.c,v 1.3 2002/05/25 10:26:06 perex Exp $ */ /* $Id: sa11xx-uda1341.c,v 1.4 2002/08/06 18:03:25 perex Exp $ */
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/module.h> #include <linux/module.h>
......
...@@ -460,7 +460,6 @@ static int __init snd_ioctl32_init(void) ...@@ -460,7 +460,6 @@ static int __init snd_ioctl32_init(void)
return err; return err;
} }
#endif #endif
return 0; return 0;
} }
......
...@@ -329,6 +329,18 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) ...@@ -329,6 +329,18 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
return 0x0000800000008000ULL; return 0x0000800000008000ULL;
case SNDRV_PCM_FORMAT_U32_BE: case SNDRV_PCM_FORMAT_U32_BE:
return 0x0000008000000080ULL; return 0x0000008000000080ULL;
case SNDRV_PCM_FORMAT_U24_3LE:
return 0x0000800000800000ULL;
case SNDRV_PCM_FORMAT_U24_3BE:
return 0x0080000080000080ULL;
case SNDRV_PCM_FORMAT_U20_3LE:
return 0x0000080000080000ULL;
case SNDRV_PCM_FORMAT_U20_3BE:
return 0x0008000008000008ULL;
case SNDRV_PCM_FORMAT_U18_3LE:
return 0x0000020000020000ULL;
case SNDRV_PCM_FORMAT_U18_3BE:
return 0x0002000002000002ULL;
#else #else
case SNDRV_PCM_FORMAT_U16_LE: case SNDRV_PCM_FORMAT_U16_LE:
return 0x0080008000800080ULL; return 0x0080008000800080ULL;
...@@ -342,16 +354,19 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) ...@@ -342,16 +354,19 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
return 0x0080000000800000ULL; return 0x0080000000800000ULL;
case SNDRV_PCM_FORMAT_U32_BE: case SNDRV_PCM_FORMAT_U32_BE:
return 0x8000000080000000ULL; return 0x8000000080000000ULL;
#endif
case SNDRV_PCM_FORMAT_U24_3LE: case SNDRV_PCM_FORMAT_U24_3LE:
return 0x0080000080000080ULL;
case SNDRV_PCM_FORMAT_U24_3BE: case SNDRV_PCM_FORMAT_U24_3BE:
return 0x0000800000800000ULL; return 0x0000800000800000ULL;
case SNDRV_PCM_FORMAT_U20_3LE: case SNDRV_PCM_FORMAT_U20_3LE:
return 0x0008000008000008ULL;
case SNDRV_PCM_FORMAT_U20_3BE: case SNDRV_PCM_FORMAT_U20_3BE:
return 0x0000080000080000ULL; return 0x0000080000080000ULL;
case SNDRV_PCM_FORMAT_U18_3LE: case SNDRV_PCM_FORMAT_U18_3LE:
return 0x0002000002000002ULL;
case SNDRV_PCM_FORMAT_U18_3BE: case SNDRV_PCM_FORMAT_U18_3BE:
return 0x0000020000020000ULL; return 0x0000020000020000ULL;
#endif
case SNDRV_PCM_FORMAT_FLOAT_LE: case SNDRV_PCM_FORMAT_FLOAT_LE:
{ {
union { union {
...@@ -471,11 +486,16 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int ...@@ -471,11 +486,16 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
if (! silence) if (! silence)
memset(data, 0, samples * 3); memset(data, 0, samples * 3);
else { else {
/* FIXME: rewrite in the more better way.. */
int i;
while (samples-- > 0) { while (samples-- > 0) {
for (i = 0; i < 3; i++) #ifdef SNDRV_LITTLE_ENDIAN
*((u_int8_t *)data)++ = silence >> (i * 8); *((u_int8_t *)data)++ = silence >> 0;
*((u_int8_t *)data)++ = silence >> 8;
*((u_int8_t *)data)++ = silence >> 16;
#else
*((u_int8_t *)data)++ = silence >> 16;
*((u_int8_t *)data)++ = silence >> 8;
*((u_int8_t *)data)++ = silence >> 0;
#endif
} }
} }
} }
......
...@@ -1616,7 +1616,6 @@ int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream) ...@@ -1616,7 +1616,6 @@ int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream)
snd_assert(err >= 0, return -EINVAL); snd_assert(err >= 0, return -EINVAL);
err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats); err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
//err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
snd_assert(err >= 0, return -EINVAL); snd_assert(err >= 0, return -EINVAL);
err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD); err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD);
......
...@@ -101,8 +101,10 @@ void snd_opl3_cs4281_command(opl3_t * opl3, unsigned short cmd, unsigned char va ...@@ -101,8 +101,10 @@ void snd_opl3_cs4281_command(opl3_t * opl3, unsigned short cmd, unsigned char va
spin_lock_irqsave(&opl3->reg_lock, flags); spin_lock_irqsave(&opl3->reg_lock, flags);
writel((unsigned int)cmd, port << 2); writel((unsigned int)cmd, port << 2);
udelay(10);
writel((unsigned int)val, (port + 1) << 2); writel((unsigned int)val, (port + 1) << 2);
udelay(30);
spin_unlock_irqrestore(&opl3->reg_lock, flags); spin_unlock_irqrestore(&opl3->reg_lock, flags);
} }
......
...@@ -6,7 +6,7 @@ comment 'PCI devices' ...@@ -6,7 +6,7 @@ comment 'PCI devices'
dep_tristate 'ALi PCI Audio M5451' CONFIG_SND_ALI5451 $CONFIG_SND dep_tristate 'ALi PCI Audio M5451' CONFIG_SND_ALI5451 $CONFIG_SND
dep_tristate 'Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x' CONFIG_SND_CS46XX $CONFIG_SND dep_tristate 'Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x' CONFIG_SND_CS46XX $CONFIG_SND
dep_mbool ' Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)' CONFIG_SND_CS46XX_NEW_DSP $CONFIG_SND_CS46XX $CONFIG_EXPERIMENTAL dep_mbool ' Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)' CONFIG_SND_CS46XX_NEW_DSP $CONFIG_SND_CS46XX $CONFIG_EXPERIMENTAL
dep_tristate 'Cirrus Logic CS4281' CONFIG_SND_CS4281 $CONFIG_SND dep_tristate 'Cirrus Logic (Sound Fusion) CS4281' CONFIG_SND_CS4281 $CONFIG_SND
dep_tristate 'EMU10K1 (SB Live!, E-mu APS)' CONFIG_SND_EMU10K1 $CONFIG_SND dep_tristate 'EMU10K1 (SB Live!, E-mu APS)' CONFIG_SND_EMU10K1 $CONFIG_SND
dep_tristate 'Korg 1212 IO' CONFIG_SND_KORG1212 $CONFIG_SND dep_tristate 'Korg 1212 IO' CONFIG_SND_KORG1212 $CONFIG_SND
dep_tristate 'NeoMagic NM256AV/ZX' CONFIG_SND_NM256 $CONFIG_SND dep_tristate 'NeoMagic NM256AV/ZX' CONFIG_SND_NM256 $CONFIG_SND
......
...@@ -362,6 +362,8 @@ MODULE_PARM_SYNTAX(snd_dual_codec, SNDRV_ENABLED ",allows:{{0,3}}"); ...@@ -362,6 +362,8 @@ MODULE_PARM_SYNTAX(snd_dual_codec, SNDRV_ENABLED ",allows:{{0,3}}");
#define BA0_SRCSA 0x075c /* SRC Slot Assignments */ #define BA0_SRCSA 0x075c /* SRC Slot Assignments */
#define BA0_PPLVC 0x0760 /* PCM Playback Left Volume Control */ #define BA0_PPLVC 0x0760 /* PCM Playback Left Volume Control */
#define BA0_PPRVC 0x0764 /* PCM Playback Right Volume Control */ #define BA0_PPRVC 0x0764 /* PCM Playback Right Volume Control */
#define BA0_PASR 0x0768 /* playback sample rate */
#define BA0_CASR 0x076C /* capture sample rate */
/* Source Slot Numbers - Playback */ /* Source Slot Numbers - Playback */
#define SRCSLOT_LEFT_PCM_PLAYBACK 0 #define SRCSLOT_LEFT_PCM_PLAYBACK 0
...@@ -465,6 +467,8 @@ struct snd_cs4281_dma { ...@@ -465,6 +467,8 @@ struct snd_cs4281_dma {
int frag; /* period number */ int frag; /* period number */
}; };
#define SUSPEND_REGISTERS 20
struct snd_cs4281 { struct snd_cs4281 {
int irq; int irq;
...@@ -506,6 +510,11 @@ struct snd_cs4281 { ...@@ -506,6 +510,11 @@ struct snd_cs4281 {
snd_info_entry_t *proc_entry; snd_info_entry_t *proc_entry;
struct snd_cs4281_gameport *gameport; struct snd_cs4281_gameport *gameport;
#ifdef CONFIG_PM
u32 suspend_regs[SUSPEND_REGISTERS];
#endif
}; };
static void snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs);
...@@ -527,9 +536,10 @@ MODULE_DEVICE_TABLE(pci, snd_cs4281_ids); ...@@ -527,9 +536,10 @@ MODULE_DEVICE_TABLE(pci, snd_cs4281_ids);
* common I/O routines * common I/O routines
*/ */
static void snd_cs4281_delay(unsigned int delay) static void snd_cs4281_delay(unsigned int delay, int can_schedule)
{ {
if (delay > 999) { if (delay > 999) {
if (can_schedule) {
signed long end_time; signed long end_time;
delay = (delay * HZ) / 1000000; delay = (delay * HZ) / 1000000;
if (delay < 1) if (delay < 1)
...@@ -539,11 +549,22 @@ static void snd_cs4281_delay(unsigned int delay) ...@@ -539,11 +549,22 @@ static void snd_cs4281_delay(unsigned int delay)
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1); schedule_timeout(1);
} while (end_time - (signed long)jiffies >= 0); } while (end_time - (signed long)jiffies >= 0);
} else
mdelay(delay);
} else { } else {
udelay(delay); udelay(delay);
} }
} }
inline static void snd_cs4281_delay_long(int can_schedule)
{
if (can_schedule) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
} else
mdelay(1999 / HZ);
}
static inline void snd_cs4281_pokeBA0(cs4281_t *chip, unsigned long offset, unsigned int val) static inline void snd_cs4281_pokeBA0(cs4281_t *chip, unsigned long offset, unsigned int val)
{ {
writel(val, chip->ba0 + offset); writel(val, chip->ba0 + offset);
...@@ -717,6 +738,9 @@ static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd) ...@@ -717,6 +738,9 @@ static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
dma->valDMR &= ~(BA0_DMR_DMA|BA0_DMR_POLL); dma->valDMR &= ~(BA0_DMR_DMA|BA0_DMR_POLL);
dma->valDCR |= BA0_DCR_MSK; dma->valDCR |= BA0_DCR_MSK;
dma->valFCR &= ~BA0_FCR_FEN; dma->valFCR &= ~BA0_FCR_FEN;
/* Leave wave playback FIFO enabled for FM */
if (dma->regFCR != BA0_FCR0)
dma->valFCR &= ~BA0_FCR_FEN;
break; break;
default: default:
spin_unlock_irqrestore(&chip->reg_lock, flags); spin_unlock_irqrestore(&chip->reg_lock, flags);
...@@ -800,12 +824,18 @@ static void snd_cs4281_mode(cs4281_t *chip, cs4281_dma_t *dma, snd_pcm_runtime_t ...@@ -800,12 +824,18 @@ static void snd_cs4281_mode(cs4281_t *chip, cs4281_dma_t *dma, snd_pcm_runtime_t
} }
} }
__skip_src: __skip_src:
/* Deactivate wave playback FIFO before changing slot assignments */
if (dma->regFCR == BA0_FCR0)
snd_cs4281_pokeBA0(chip, dma->regFCR, snd_cs4281_peekBA0(chip, dma->regFCR) & ~BA0_FCR_FEN);
/* Initialize FIFO */ /* Initialize FIFO */
dma->valFCR = BA0_FCR_LS(dma->left_slot) | dma->valFCR = BA0_FCR_LS(dma->left_slot) |
BA0_FCR_RS(capture && (dma->valDMR & BA0_DMR_MONO) ? 31 : dma->right_slot) | BA0_FCR_RS(capture && (dma->valDMR & BA0_DMR_MONO) ? 31 : dma->right_slot) |
BA0_FCR_SZ(CS4281_FIFO_SIZE) | BA0_FCR_SZ(CS4281_FIFO_SIZE) |
BA0_FCR_OF(dma->fifo_offset); BA0_FCR_OF(dma->fifo_offset);
snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR | (capture ? BA0_FCR_PSH : 0)); snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR | (capture ? BA0_FCR_PSH : 0));
/* Activate FIFO again for FM playback */
if (dma->regFCR == BA0_FCR0)
snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR | BA0_FCR_FEN);
/* Clear FIFO Status and Interrupt Control Register */ /* Clear FIFO Status and Interrupt Control Register */
snd_cs4281_pokeBA0(chip, dma->regFSIC, 0); snd_cs4281_pokeBA0(chip, dma->regFSIC, 0);
} }
...@@ -855,7 +885,7 @@ static snd_pcm_uframes_t snd_cs4281_pointer(snd_pcm_substream_t * substream) ...@@ -855,7 +885,7 @@ static snd_pcm_uframes_t snd_cs4281_pointer(snd_pcm_substream_t * substream)
// printk("DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, jiffies); // printk("DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, jiffies);
return runtime->buffer_size - return runtime->buffer_size -
snd_cs4281_peekBA0(chip, dma->regDCC); snd_cs4281_peekBA0(chip, dma->regDCC) - 1;
} }
static snd_pcm_hardware_t snd_cs4281_playback = static snd_pcm_hardware_t snd_cs4281_playback =
...@@ -1024,6 +1054,76 @@ static int __devinit snd_cs4281_pcm(cs4281_t * chip, int device, snd_pcm_t ** rp ...@@ -1024,6 +1054,76 @@ static int __devinit snd_cs4281_pcm(cs4281_t * chip, int device, snd_pcm_t ** rp
* Mixer section * Mixer section
*/ */
#define CS_VOL_MASK 0x1f
static int snd_cs4281_info_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = CS_VOL_MASK;
return 0;
}
static int snd_cs4281_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
cs4281_t *chip = snd_kcontrol_chip(kcontrol);
int regL = (kcontrol->private_value >> 16) & 0xffff;
int regR = kcontrol->private_value & 0xffff;
int volL, volR;
volL = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regL) & CS_VOL_MASK);
volR = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regR) & CS_VOL_MASK);
ucontrol->value.integer.value[0] = volL;
ucontrol->value.integer.value[1] = volR;
return 0;
}
static int snd_cs4281_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
cs4281_t *chip = snd_kcontrol_chip(kcontrol);
int change = 0;
int regL = (kcontrol->private_value >> 16) & 0xffff;
int regR = kcontrol->private_value & 0xffff;
int volL, volR;
volL = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regL) & CS_VOL_MASK);
volR = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regR) & CS_VOL_MASK);
if (ucontrol->value.integer.value[0] != volL) {
volL = CS_VOL_MASK - (ucontrol->value.integer.value[0] & CS_VOL_MASK);
snd_cs4281_pokeBA0(chip, regL, volL);
change = 1;
}
if (ucontrol->value.integer.value[0] != volL) {
volR = CS_VOL_MASK - (ucontrol->value.integer.value[1] & CS_VOL_MASK);
snd_cs4281_pokeBA0(chip, regR, volR);
change = 1;
}
return change;
}
static snd_kcontrol_new_t snd_cs4281_fm_vol =
{
iface: SNDRV_CTL_ELEM_IFACE_MIXER,
name: "Synth Playback Volume",
info: snd_cs4281_info_volume,
get: snd_cs4281_get_volume,
put: snd_cs4281_put_volume,
private_value: ((BA0_FMLVC << 16) | BA0_FMRVC),
};
static snd_kcontrol_new_t snd_cs4281_pcm_vol =
{
iface: SNDRV_CTL_ELEM_IFACE_MIXER,
name: "PCM Stream Playback Volume",
info: snd_cs4281_info_volume,
get: snd_cs4281_get_volume,
put: snd_cs4281_put_volume,
private_value: ((BA0_PPLVC << 16) | BA0_PPRVC),
};
static void snd_cs4281_mixer_free_ac97(ac97_t *ac97) static void snd_cs4281_mixer_free_ac97(ac97_t *ac97)
{ {
cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return); cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return);
...@@ -1051,11 +1151,16 @@ static int __devinit snd_cs4281_mixer(cs4281_t * chip) ...@@ -1051,11 +1151,16 @@ static int __devinit snd_cs4281_mixer(cs4281_t * chip)
if ((err = snd_ac97_mixer(card, &ac97, &chip->ac97_secondary)) < 0) if ((err = snd_ac97_mixer(card, &ac97, &chip->ac97_secondary)) < 0)
return err; return err;
} }
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_fm_vol, chip))) < 0)
return err;
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_pcm_vol, chip))) < 0)
return err;
return 0; return 0;
} }
/*
/*
* proc interface
*/ */
static void snd_cs4281_proc_read(snd_info_entry_t *entry, static void snd_cs4281_proc_read(snd_info_entry_t *entry,
...@@ -1337,6 +1442,11 @@ static int snd_cs4281_dev_free(snd_device_t *device) ...@@ -1337,6 +1442,11 @@ static int snd_cs4281_dev_free(snd_device_t *device)
return snd_cs4281_free(chip); return snd_cs4281_free(chip);
} }
static int snd_cs4281_chip_init(cs4281_t *chip, int can_schedule); /* defined below */
#ifdef CONFIG_PM
static int snd_cs4281_set_power_state(snd_card_t *card, unsigned int power_state);
#endif
static int __devinit snd_cs4281_create(snd_card_t * card, static int __devinit snd_cs4281_create(snd_card_t * card,
struct pci_dev *pci, struct pci_dev *pci,
cs4281_t ** rchip, cs4281_t ** rchip,
...@@ -1344,7 +1454,6 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1344,7 +1454,6 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
{ {
cs4281_t *chip; cs4281_t *chip;
unsigned int tmp; unsigned int tmp;
signed long end_time;
int err; int err;
static snd_device_ops_t ops = { static snd_device_ops_t ops = {
dev_free: snd_cs4281_dev_free, dev_free: snd_cs4281_dev_free,
...@@ -1393,13 +1502,39 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1393,13 +1502,39 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
return -ENOMEM; return -ENOMEM;
} }
tmp = snd_cs4281_chip_init(chip, 0);
if (tmp) {
snd_cs4281_free(chip);
return tmp;
}
snd_cs4281_proc_init(chip);
#ifdef CONFIG_PM
card->set_power_state = snd_cs4281_set_power_state;
card->power_state_private_data = chip;
#endif
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_cs4281_free(chip);
return err;
}
*rchip = chip;
return 0;
}
static int snd_cs4281_chip_init(cs4281_t *chip, int can_schedule)
{
unsigned int tmp;
int timeout;
tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); tmp = snd_cs4281_peekBA0(chip, BA0_CFLR);
if (tmp != BA0_CFLR_DEFAULT) { if (tmp != BA0_CFLR_DEFAULT) {
snd_cs4281_pokeBA0(chip, BA0_CFLR, BA0_CFLR_DEFAULT); snd_cs4281_pokeBA0(chip, BA0_CFLR, BA0_CFLR_DEFAULT);
tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); tmp = snd_cs4281_peekBA0(chip, BA0_CFLR);
if (tmp != BA0_CFLR_DEFAULT) { if (tmp != BA0_CFLR_DEFAULT) {
snd_printk(KERN_ERR "CFLR setup failed (0x%x)\n", tmp); snd_printk(KERN_ERR "CFLR setup failed (0x%x)\n", tmp);
snd_cs4281_free(chip);
return -EIO; return -EIO;
} }
} }
...@@ -1411,12 +1546,10 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1411,12 +1546,10 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC1)) != (BA0_SERC1_SO1EN | BA0_SERC1_AC97)) { if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC1)) != (BA0_SERC1_SO1EN | BA0_SERC1_AC97)) {
snd_printk(KERN_ERR "SERC1 AC'97 check failed (0x%x)\n", tmp); snd_printk(KERN_ERR "SERC1 AC'97 check failed (0x%x)\n", tmp);
snd_cs4281_free(chip);
return -EIO; return -EIO;
} }
if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC2)) != (BA0_SERC2_SI1EN | BA0_SERC2_AC97)) { if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC2)) != (BA0_SERC2_SI1EN | BA0_SERC2_AC97)) {
snd_printk(KERN_ERR "SERC2 AC'97 check failed (0x%x)\n", tmp); snd_printk(KERN_ERR "SERC2 AC'97 check failed (0x%x)\n", tmp);
snd_cs4281_free(chip);
return -EIO; return -EIO;
} }
...@@ -1445,7 +1578,7 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1445,7 +1578,7 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
snd_cs4281_pokeBA0(chip, BA0_SPMC, 0); snd_cs4281_pokeBA0(chip, BA0_SPMC, 0);
udelay(50); udelay(50);
snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN); snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN);
snd_cs4281_delay(50000); snd_cs4281_delay(50000, can_schedule);
if (chip->dual_codec) if (chip->dual_codec)
snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN | BA0_SPMC_ASDI2E); snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN | BA0_SPMC_ASDI2E);
...@@ -1461,13 +1594,13 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1461,13 +1594,13 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
* Start the DLL Clock logic. * Start the DLL Clock logic.
*/ */
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_DLLP); snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_DLLP);
snd_cs4281_delay(50000); snd_cs4281_delay(50000, can_schedule);
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_SWCE | BA0_CLKCR1_DLLP); snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_SWCE | BA0_CLKCR1_DLLP);
/* /*
* Wait for the DLL ready signal from the clock logic. * Wait for the DLL ready signal from the clock logic.
*/ */
end_time = (jiffies + HZ / 4) + 1; timeout = HZ;
do { do {
/* /*
* Read the AC97 status register to see if we've seen a CODEC * Read the AC97 status register to see if we've seen a CODEC
...@@ -1475,12 +1608,10 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1475,12 +1608,10 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
*/ */
if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY) if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY)
goto __ok0; goto __ok0;
set_current_state(TASK_UNINTERRUPTIBLE); snd_cs4281_delay_long(can_schedule);
schedule_timeout(1); } while (timeout-- > 0);
} while (end_time - (signed long)jiffies >= 0);
snd_printk(KERN_ERR "DLLRDY not seen\n"); snd_printk(KERN_ERR "DLLRDY not seen\n");
snd_cs4281_free(chip);
return -EIO; return -EIO;
__ok0: __ok0:
...@@ -1495,7 +1626,7 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1495,7 +1626,7 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
/* /*
* Wait for the codec ready signal from the AC97 codec. * Wait for the codec ready signal from the AC97 codec.
*/ */
end_time = (jiffies + (3 * HZ) / 4) + 1; timeout = HZ;
do { do {
/* /*
* Read the AC97 status register to see if we've seen a CODEC * Read the AC97 status register to see if we've seen a CODEC
...@@ -1503,23 +1634,20 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1503,23 +1634,20 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
*/ */
if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY) if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY)
goto __ok1; goto __ok1;
set_current_state(TASK_UNINTERRUPTIBLE); snd_cs4281_delay_long(can_schedule);
schedule_timeout(1); } while (timeout-- > 0);
} while (end_time - (signed long)jiffies >= 0);
snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS)); snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS));
snd_cs4281_free(chip);
return -EIO; return -EIO;
__ok1: __ok1:
if (chip->dual_codec) { if (chip->dual_codec) {
end_time = (jiffies + (3 * HZ) / 4) + 1; timeout = HZ;
do { do {
if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY) if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY)
goto __codec2_ok; goto __codec2_ok;
set_current_state(TASK_UNINTERRUPTIBLE); snd_cs4281_delay_long(can_schedule);
schedule_timeout(1); } while (timeout-- > 0);
} while (end_time - (signed long)jiffies >= 0);
snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n"); snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n");
chip->dual_codec = 0; chip->dual_codec = 0;
__codec2_ok: ; __codec2_ok: ;
...@@ -1537,7 +1665,7 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1537,7 +1665,7 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
* the codec is pumping ADC data across the AC-link. * the codec is pumping ADC data across the AC-link.
*/ */
end_time = (jiffies + (5 * HZ) / 4) + 1; timeout = HZ;
do { do {
/* /*
* Read the input slot valid register and see if input slots 3 * Read the input slot valid register and see if input slots 3
...@@ -1545,12 +1673,10 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1545,12 +1673,10 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
*/ */
if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4)))
goto __ok2; goto __ok2;
set_current_state(TASK_UNINTERRUPTIBLE); snd_cs4281_delay_long(can_schedule);
schedule_timeout(1); } while (timeout-- > 0);
} while (end_time - (signed long)jiffies >= 0);
snd_printk(KERN_ERR "never read ISV3 and ISV4 from AC'97\n"); snd_printk(KERN_ERR "never read ISV3 and ISV4 from AC'97\n");
snd_cs4281_free(chip);
return -EIO; return -EIO;
__ok2: __ok2:
...@@ -1588,12 +1714,21 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1588,12 +1714,21 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
chip->src_left_rec_slot = 10; /* AC'97 left PCM record (3) */ chip->src_left_rec_slot = 10; /* AC'97 left PCM record (3) */
chip->src_right_rec_slot = 11; /* AC'97 right PCM record (4) */ chip->src_right_rec_slot = 11; /* AC'97 right PCM record (4) */
/* Activate wave playback FIFO for FM playback */
chip->dma[0].valFCR = BA0_FCR_FEN | BA0_FCR_LS(0) |
BA0_FCR_RS(1) |
BA0_FCR_SZ(CS4281_FIFO_SIZE) |
BA0_FCR_OF(chip->dma[0].fifo_offset);
snd_cs4281_pokeBA0(chip, chip->dma[0].regFCR, chip->dma[0].valFCR);
snd_cs4281_pokeBA0(chip, BA0_SRCSA, (chip->src_left_play_slot << 0) |
(chip->src_right_play_slot << 8) |
(chip->src_left_rec_slot << 16) |
(chip->src_right_rec_slot << 24));
/* Initialize digital volume */ /* Initialize digital volume */
snd_cs4281_pokeBA0(chip, BA0_PPLVC, 0); snd_cs4281_pokeBA0(chip, BA0_PPLVC, 0);
snd_cs4281_pokeBA0(chip, BA0_PPRVC, 0); snd_cs4281_pokeBA0(chip, BA0_PPRVC, 0);
snd_cs4281_proc_init(chip);
/* Enable IRQs */ /* Enable IRQs */
snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_EOI); snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_EOI);
/* Unmask interrupts */ /* Unmask interrupts */
...@@ -1606,12 +1741,6 @@ static int __devinit snd_cs4281_create(snd_card_t * card, ...@@ -1606,12 +1741,6 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
BA0_HISR_DMA(3))); BA0_HISR_DMA(3)));
synchronize_irq(chip->irq); synchronize_irq(chip->irq);
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_cs4281_free(chip);
return err;
}
*rchip = chip;
return 0; return 0;
} }
...@@ -1917,22 +2046,180 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci, ...@@ -1917,22 +2046,180 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci,
return err; return err;
} }
pci_set_drvdata(pci, card); pci_set_drvdata(pci, chip);
dev++; dev++;
return 0; return 0;
} }
static void __devexit snd_cs4281_remove(struct pci_dev *pci) static void __devexit snd_cs4281_remove(struct pci_dev *pci)
{ {
snd_card_free(pci_get_drvdata(pci)); cs4281_t *chip = pci_get_drvdata(pci);
snd_card_free(chip->card);
pci_set_drvdata(pci, NULL); pci_set_drvdata(pci, NULL);
} }
/*
* Power Management
*/
#ifdef CONFIG_PM
static int saved_regs[SUSPEND_REGISTERS] = {
BA0_JSCTL,
BA0_GPIOR,
BA0_SSCR,
BA0_MIDCR,
BA0_SRCSA,
BA0_PASR,
BA0_CASR,
BA0_DACSR,
BA0_ADCSR,
BA0_FMLVC,
BA0_FMRVC,
BA0_PPLVC,
BA0_PPRVC,
};
#define number_of(array) (sizeof(array) / sizeof(array[0]))
#define CLKCR1_CKRA 0x00010000L
static void cs4281_suspend(cs4281_t *chip)
{
snd_card_t *card = chip->card;
u32 ulCLK;
int i;
snd_power_lock(card);
if (card->power_state == SNDRV_CTL_POWER_D3hot)
goto __skip;
snd_pcm_suspend_all(chip->pcm);
ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
ulCLK |= CLKCR1_CKRA;
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
/* Disable interrupts. */
snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_CHGM);
/* remember the status registers */
for (i = 0; number_of(saved_regs); i++)
chip->suspend_regs[i] = snd_cs4281_peekBA0(chip, saved_regs[i]);
/* Turn off the serial ports. */
snd_cs4281_pokeBA0(chip, BA0_SERMC, 0);
/* Power off FM, Joystick, AC link, */
snd_cs4281_pokeBA0(chip, BA0_SSPM, 0);
/* DLL off. */
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, 0);
/* AC link off. */
snd_cs4281_pokeBA0(chip, BA0_SPMC, 0);
ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
ulCLK &= ~CLKCR1_CKRA;
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
__skip:
snd_power_unlock(card);
}
static void cs4281_resume(cs4281_t *chip)
{
snd_card_t *card = chip->card;
int i;
u32 ulCLK;
snd_power_lock(card);
if (card->power_state == SNDRV_CTL_POWER_D0)
goto __skip;
pci_enable_device(chip->pci);
ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
ulCLK |= CLKCR1_CKRA;
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
snd_cs4281_chip_init(chip, 0);
/* restore the status registers */
for (i = 0; number_of(saved_regs); i++)
snd_cs4281_pokeBA0(chip, saved_regs[i], chip->suspend_regs[i]);
if (chip->ac97)
snd_ac97_resume(chip->ac97);
if (chip->ac97_secondary)
snd_ac97_resume(chip->ac97_secondary);
ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
ulCLK &= ~CLKCR1_CKRA;
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
__skip:
snd_power_unlock(card);
}
#ifndef PCI_OLD_SUSPEND
static int snd_cs4281_suspend(struct pci_dev *dev, u32 state)
{
cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return -ENXIO);
cs4281_suspend(chip);
return 0;
}
static int snd_cs4281_resume(struct pci_dev *dev)
{
cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return -ENXIO);
cs4281_resume(chip);
return 0;
}
#else
static void snd_cs4281_suspend(struct pci_dev *dev)
{
cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return);
cs4281_suspend(chip);
}
static void snd_cs4281_resume(struct pci_dev *dev)
{
cs4281_t *chip = snd_magic_cast(cs4281_t, pci_get_drvdata(dev), return);
cs4281_resume(chip);
}
#endif
/* callback */
static int snd_cs4281_set_power_state(snd_card_t *card, unsigned int power_state)
{
cs4281_t *chip = snd_magic_cast(cs4281_t, card->power_state_private_data, return -ENXIO);
switch (power_state) {
case SNDRV_CTL_POWER_D0:
case SNDRV_CTL_POWER_D1:
case SNDRV_CTL_POWER_D2:
cs4281_resume(chip);
break;
case SNDRV_CTL_POWER_D3hot:
case SNDRV_CTL_POWER_D3cold:
cs4281_suspend(chip);
break;
default:
return -EINVAL;
}
return 0;
}
#endif /* CONFIG_PM */
static struct pci_driver driver = { static struct pci_driver driver = {
name: "CS4281", name: "CS4281",
id_table: snd_cs4281_ids, id_table: snd_cs4281_ids,
probe: snd_cs4281_probe, probe: snd_cs4281_probe,
remove: __devexit_p(snd_cs4281_remove), remove: __devexit_p(snd_cs4281_remove),
#ifdef CONFIG_PM
suspend: snd_cs4281_suspend,
resume: snd_cs4281_resume,
#endif
}; };
static int __init alsa_card_cs4281_init(void) static int __init alsa_card_cs4281_init(void)
......
...@@ -534,24 +534,31 @@ int __devinit snd_emu10k1_create(snd_card_t * card, ...@@ -534,24 +534,31 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
{ {
emu10k1_t *emu; emu10k1_t *emu;
int err; int err;
int is_audigy;
static snd_device_ops_t ops = { static snd_device_ops_t ops = {
dev_free: snd_emu10k1_dev_free, dev_free: snd_emu10k1_dev_free,
}; };
*remu = NULL; *remu = NULL;
// is_audigy = (int)pci->driver_data;
is_audigy = (pci->device == 0x0004);
/* enable PCI device */ /* enable PCI device */
if ((err = pci_enable_device(pci)) < 0) if ((err = pci_enable_device(pci)) < 0)
return err; return err;
/* check, if we can restrict PCI DMA transfers to 31 bits */ /* set the DMA transfer mask */
if (!pci_dma_supported(pci, 0x7fffffff)) { if (is_audigy) {
snd_printk("architecture does not support 31bit PCI busmaster DMA\n"); if (pci_set_dma_mask(pci, 0xffffffff) < 0) {
snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");
return -ENXIO; return -ENXIO;
} }
if (pci_get_drvdata(pci)) } else {
pci_set_dma_mask(pci, 0xffffffff); /* audigy */ if (pci_set_dma_mask(pci, 0x1fffffff) < 0) {
else snd_printk(KERN_ERR "architecture does not support 29bit PCI busmaster DMA\n");
pci_set_dma_mask(pci, 0x7fffffff); return -ENXIO;
}
}
emu = snd_magic_kcalloc(emu10k1_t, 0, GFP_KERNEL); emu = snd_magic_kcalloc(emu10k1_t, 0, GFP_KERNEL);
if (emu == NULL) if (emu == NULL)
...@@ -572,11 +579,8 @@ int __devinit snd_emu10k1_create(snd_card_t * card, ...@@ -572,11 +579,8 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu->get_synth_voice = NULL; emu->get_synth_voice = NULL;
emu->port = pci_resource_start(pci, 0); emu->port = pci_resource_start(pci, 0);
// emu->audigy = (int)pci->driver_data; emu->audigy = is_audigy;
if (pci->device == 0x0004) if (is_audigy)
emu->audigy = 1;
if (emu->audigy)
emu->gpr_base = A_FXGPREGBASE; emu->gpr_base = A_FXGPREGBASE;
else else
emu->gpr_base = FXGPREGBASE; emu->gpr_base = FXGPREGBASE;
......
...@@ -960,17 +960,25 @@ static snd_i2c_bit_ops_t snd_ice1712_ewx_cs8427_bit_ops = { ...@@ -960,17 +960,25 @@ static snd_i2c_bit_ops_t snd_ice1712_ewx_cs8427_bit_ops = {
}; };
/* AK4524 chip select; address 0x48 bit 0-3 */ /* AK4524 chip select; address 0x48 bit 0-3 */
static void snd_ice1712_ews88mt_chip_select(ice1712_t *ice, int chip_mask) static int snd_ice1712_ews88mt_chip_select(ice1712_t *ice, int chip_mask)
{ {
unsigned char data, ndata; unsigned char data, ndata;
snd_assert(chip_mask >= 0 && chip_mask <= 0x0f, return); snd_assert(chip_mask >= 0 && chip_mask <= 0x0f, return -EINVAL);
snd_i2c_lock(ice->i2c); snd_i2c_lock(ice->i2c);
snd_runtime_check(snd_i2c_readbytes(ice->pcf8574[1], &data, 1) == 1, snd_i2c_unlock(ice->i2c); return); if (snd_i2c_readbytes(ice->pcf8574[1], &data, 1) != 1)
goto __error;
ndata = (data & 0xf0) | chip_mask; ndata = (data & 0xf0) | chip_mask;
if (ndata != data) if (ndata != data)
snd_runtime_check(snd_i2c_sendbytes(ice->pcf8574[1], &ndata, 1) == 1, snd_i2c_unlock(ice->i2c); return); if (snd_i2c_sendbytes(ice->pcf8574[1], &ndata, 1) != 1)
goto __error;
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return 0;
__error:
snd_i2c_unlock(ice->i2c);
snd_printk(KERN_ERR "AK4524 chip select failed, check cable to the front module\n");
return -EIO;
} }
/* /*
...@@ -988,7 +996,8 @@ static void snd_ice1712_ak4524_write(ice1712_t *ice, int chip, ...@@ -988,7 +996,8 @@ static void snd_ice1712_ak4524_write(ice1712_t *ice, int chip,
if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_EWS88MT) { if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_EWS88MT) {
/* assert AK4524 CS */ /* assert AK4524 CS */
snd_ice1712_ews88mt_chip_select(ice, ~(1 << chip) & 0x0f); if (snd_ice1712_ews88mt_chip_select(ice, ~(1 << chip) & 0x0f) < 0)
return;
//snd_ice1712_ews88mt_chip_select(ice, 0x0f); //snd_ice1712_ews88mt_chip_select(ice, 0x0f);
} }
...@@ -1147,11 +1156,11 @@ static int snd_ice1712_cs8427_set_input_clock(ice1712_t *ice, int spdif_clock) ...@@ -1147,11 +1156,11 @@ static int snd_ice1712_cs8427_set_input_clock(ice1712_t *ice, int spdif_clock)
snd_i2c_lock(ice->i2c); snd_i2c_lock(ice->i2c);
if (snd_i2c_sendbytes(ice->cs8427, reg, 1) != 1) { if (snd_i2c_sendbytes(ice->cs8427, reg, 1) != 1) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
if (snd_i2c_readbytes(ice->cs8427, &val, 1) != 1) { if (snd_i2c_readbytes(ice->cs8427, &val, 1) != 1) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
nval = val & 0xf0; nval = val & 0xf0;
if (spdif_clock) if (spdif_clock)
...@@ -1161,7 +1170,7 @@ static int snd_ice1712_cs8427_set_input_clock(ice1712_t *ice, int spdif_clock) ...@@ -1161,7 +1170,7 @@ static int snd_ice1712_cs8427_set_input_clock(ice1712_t *ice, int spdif_clock)
if (val != nval) { if (val != nval) {
reg[1] = nval; reg[1] = nval;
if (snd_i2c_sendbytes(ice->cs8427, reg, 2) != 2) { if (snd_i2c_sendbytes(ice->cs8427, reg, 2) != 2) {
res = -EREMOTE; res = -EIO;
} else { } else {
res++; res++;
} }
...@@ -3187,7 +3196,7 @@ static int snd_ice1712_ews88mt_output_sense_get(snd_kcontrol_t *kcontrol, snd_ct ...@@ -3187,7 +3196,7 @@ static int snd_ice1712_ews88mt_output_sense_get(snd_kcontrol_t *kcontrol, snd_ct
snd_i2c_lock(ice->i2c); snd_i2c_lock(ice->i2c);
if (snd_i2c_readbytes(ice->pcf8574[1], &data, 1) != 1) { if (snd_i2c_readbytes(ice->pcf8574[1], &data, 1) != 1) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
ucontrol->value.enumerated.item[0] = data & ICE1712_EWS88MT_OUTPUT_SENSE ? 1 : 0; /* high = -10dBV, low = +4dBu */ ucontrol->value.enumerated.item[0] = data & ICE1712_EWS88MT_OUTPUT_SENSE ? 1 : 0; /* high = -10dBV, low = +4dBu */
...@@ -3203,12 +3212,12 @@ static int snd_ice1712_ews88mt_output_sense_put(snd_kcontrol_t *kcontrol, snd_ct ...@@ -3203,12 +3212,12 @@ static int snd_ice1712_ews88mt_output_sense_put(snd_kcontrol_t *kcontrol, snd_ct
snd_i2c_lock(ice->i2c); snd_i2c_lock(ice->i2c);
if (snd_i2c_readbytes(ice->pcf8574[1], &data, 1) != 1) { if (snd_i2c_readbytes(ice->pcf8574[1], &data, 1) != 1) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
ndata = (data & ~ICE1712_EWS88MT_OUTPUT_SENSE) | (ucontrol->value.enumerated.item[0] ? ICE1712_EWS88MT_OUTPUT_SENSE : 0); ndata = (data & ~ICE1712_EWS88MT_OUTPUT_SENSE) | (ucontrol->value.enumerated.item[0] ? ICE1712_EWS88MT_OUTPUT_SENSE : 0);
if (ndata != data && snd_i2c_sendbytes(ice->pcf8574[1], &ndata, 1) != 1) { if (ndata != data && snd_i2c_sendbytes(ice->pcf8574[1], &ndata, 1) != 1) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return ndata != data; return ndata != data;
...@@ -3225,7 +3234,7 @@ static int snd_ice1712_ews88mt_input_sense_get(snd_kcontrol_t *kcontrol, snd_ctl ...@@ -3225,7 +3234,7 @@ static int snd_ice1712_ews88mt_input_sense_get(snd_kcontrol_t *kcontrol, snd_ctl
snd_i2c_lock(ice->i2c); snd_i2c_lock(ice->i2c);
if (snd_i2c_readbytes(ice->pcf8574[0], &data, 1) != 1) { if (snd_i2c_readbytes(ice->pcf8574[0], &data, 1) != 1) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
/* reversed; high = +4dBu, low = -10dBV */ /* reversed; high = +4dBu, low = -10dBV */
ucontrol->value.enumerated.item[0] = data & (1 << channel) ? 0 : 1; ucontrol->value.enumerated.item[0] = data & (1 << channel) ? 0 : 1;
...@@ -3243,12 +3252,12 @@ static int snd_ice1712_ews88mt_input_sense_put(snd_kcontrol_t *kcontrol, snd_ctl ...@@ -3243,12 +3252,12 @@ static int snd_ice1712_ews88mt_input_sense_put(snd_kcontrol_t *kcontrol, snd_ctl
snd_i2c_lock(ice->i2c); snd_i2c_lock(ice->i2c);
if (snd_i2c_readbytes(ice->pcf8574[0], &data, 1) != 1) { if (snd_i2c_readbytes(ice->pcf8574[0], &data, 1) != 1) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
ndata = (data & ~(1 << channel)) | (ucontrol->value.enumerated.item[0] ? 0 : (1 << channel)); ndata = (data & ~(1 << channel)) | (ucontrol->value.enumerated.item[0] ? 0 : (1 << channel));
if (ndata != data && snd_i2c_sendbytes(ice->pcf8574[0], &ndata, 1) != 1) { if (ndata != data && snd_i2c_sendbytes(ice->pcf8574[0], &ndata, 1) != 1) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return ndata != data; return ndata != data;
...@@ -3294,7 +3303,7 @@ static int snd_ice1712_ews88d_control_get(snd_kcontrol_t *kcontrol, snd_ctl_elem ...@@ -3294,7 +3303,7 @@ static int snd_ice1712_ews88d_control_get(snd_kcontrol_t *kcontrol, snd_ctl_elem
snd_i2c_lock(ice->i2c); snd_i2c_lock(ice->i2c);
if (snd_i2c_readbytes(ice->pcf8575, data, 2) != 2) { if (snd_i2c_readbytes(ice->pcf8575, data, 2) != 2) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
data[0] = (data[shift >> 3] >> (shift & 7)) & 0x01; data[0] = (data[shift >> 3] >> (shift & 7)) & 0x01;
...@@ -3315,7 +3324,7 @@ static int snd_ice1712_ews88d_control_put(snd_kcontrol_t * kcontrol, snd_ctl_ele ...@@ -3315,7 +3324,7 @@ static int snd_ice1712_ews88d_control_put(snd_kcontrol_t * kcontrol, snd_ctl_ele
snd_i2c_lock(ice->i2c); snd_i2c_lock(ice->i2c);
if (snd_i2c_readbytes(ice->pcf8575, data, 2) != 2) { if (snd_i2c_readbytes(ice->pcf8575, data, 2) != 2) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
ndata[shift >> 3] = data[shift >> 3] & ~(1 << (shift & 7)); ndata[shift >> 3] = data[shift >> 3] & ~(1 << (shift & 7));
if (invert) { if (invert) {
...@@ -3328,7 +3337,7 @@ static int snd_ice1712_ews88d_control_put(snd_kcontrol_t * kcontrol, snd_ctl_ele ...@@ -3328,7 +3337,7 @@ static int snd_ice1712_ews88d_control_put(snd_kcontrol_t * kcontrol, snd_ctl_ele
change = (data[shift >> 3] != ndata[shift >> 3]); change = (data[shift >> 3] != ndata[shift >> 3]);
if (change && snd_i2c_sendbytes(ice->pcf8575, data, 2) != 2) { if (change && snd_i2c_sendbytes(ice->pcf8575, data, 2) != 2) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return change; return change;
...@@ -3366,7 +3375,7 @@ static int snd_ice1712_6fire_read_pca(ice1712_t *ice) ...@@ -3366,7 +3375,7 @@ static int snd_ice1712_6fire_read_pca(ice1712_t *ice)
snd_i2c_sendbytes(ice->pcf8575, &byte, 1); snd_i2c_sendbytes(ice->pcf8575, &byte, 1);
if (snd_i2c_readbytes(ice->pcf8575, &byte, 1) != 1) { if (snd_i2c_readbytes(ice->pcf8575, &byte, 1) != 1) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return byte; return byte;
...@@ -3380,7 +3389,7 @@ static int snd_ice1712_6fire_write_pca(ice1712_t *ice, unsigned char data) ...@@ -3380,7 +3389,7 @@ static int snd_ice1712_6fire_write_pca(ice1712_t *ice, unsigned char data)
bytes[1] = data; bytes[1] = data;
if (snd_i2c_sendbytes(ice->pcf8575, bytes, 2) != 2) { if (snd_i2c_sendbytes(ice->pcf8575, bytes, 2) != 2) {
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return -EREMOTE; return -EIO;
} }
snd_i2c_unlock(ice->i2c); snd_i2c_unlock(ice->i2c);
return 0; return 0;
...@@ -3836,11 +3845,15 @@ static int __devinit snd_ice1712_chip_init(ice1712_t *ice) ...@@ -3836,11 +3845,15 @@ static int __devinit snd_ice1712_chip_init(ice1712_t *ice)
} }
/* second stage of initialization, analog parts and others */ /* second stage of initialization, analog parts and others */
switch (ice->eeprom.subvendor) { switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_EWS88MT:
/* Check if the front module is connected */
if ((err = snd_ice1712_ews88mt_chip_select(ice, 0x0f)) < 0)
return err;
/* Fall through */
case ICE1712_SUBDEVICE_DELTA66: case ICE1712_SUBDEVICE_DELTA66:
case ICE1712_SUBDEVICE_DELTA44: case ICE1712_SUBDEVICE_DELTA44:
case ICE1712_SUBDEVICE_AUDIOPHILE: case ICE1712_SUBDEVICE_AUDIOPHILE:
case ICE1712_SUBDEVICE_EWX2496: case ICE1712_SUBDEVICE_EWX2496:
case ICE1712_SUBDEVICE_EWS88MT:
case ICE1712_SUBDEVICE_DMX6FIRE: case ICE1712_SUBDEVICE_DMX6FIRE:
snd_ice1712_ak4524_init(ice); snd_ice1712_ak4524_init(ice);
break; break;
......
...@@ -776,6 +776,14 @@ typedef struct snd_m3 m3_t; ...@@ -776,6 +776,14 @@ typedef struct snd_m3 m3_t;
#define chip_t m3_t #define chip_t m3_t
/* quirk lists */
struct m3_quirk {
u16 vendor, device; /* subsystem ids */
int amp_gpio; /* gpio pin # for external amp, -1 = default */
int irda_workaround; /* non-zero if avoid to touch 0x10 on GPIO_DIRECTION
(e.g. for IrDA on Dell Inspirons) */
};
struct m3_list { struct m3_list {
int curlen; int curlen;
int mem_addr; int mem_addr;
...@@ -825,9 +833,7 @@ struct snd_m3 { ...@@ -825,9 +833,7 @@ struct snd_m3 {
snd_pcm_t *pcm; snd_pcm_t *pcm;
struct pci_dev *pci; struct pci_dev *pci;
/* pci_dev in 2.2 kernel doesn't have them, so we keep them private */ struct m3_quirk *quirk;
u16 subsystem_vendor;
u16 subsystem_device;
int dacs_active; int dacs_active;
int timer_users; int timer_users;
...@@ -908,6 +914,33 @@ static struct pci_device_id snd_m3_ids[] __devinitdata = { ...@@ -908,6 +914,33 @@ static struct pci_device_id snd_m3_ids[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, snd_m3_ids); MODULE_DEVICE_TABLE(pci, snd_m3_ids);
static struct m3_quirk m3_quirk_list[] = {
/* panasonic CF-28 "toughbook" */
{
vendor: 0x10f7,
device: 0x833e,
amp_gpio: 0x0d,
},
/* Dell Inspiron 4000 */
{
vendor: 0x1028,
device: 0x00b0,
amp_gpio: -1,
irda_workaround: 1,
},
/* Dell Inspiron 8000 */
{
vendor: 0x1028,
device: 0x00a4,
amp_gpio: -1,
irda_workaround: 1,
},
/* FIXME: Inspiron 8100 and 8200 ids should be here, too */
/* END */
{ 0 }
};
/* /*
* lowlevel functions * lowlevel functions
*/ */
...@@ -1859,10 +1892,7 @@ static void snd_m3_ac97_reset(m3_t *chip, int busywait) ...@@ -1859,10 +1892,7 @@ static void snd_m3_ac97_reset(m3_t *chip, int busywait)
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
dir = inw(io + GPIO_DIRECTION); dir = inw(io + GPIO_DIRECTION);
if (chip->subsystem_vendor == 0x1028 && if (! chip->quirk || ! chip->quirk->irda_workaround)
chip->subsystem_device == 0x00b0) /* Dell Inspiron 4000 */
; /* seems conflicting with IrDA */
else
dir |= 0x10; /* assuming pci bus master? */ dir |= 0x10; /* assuming pci bus master? */
snd_m3_remote_codec_config(io, 0); snd_m3_remote_codec_config(io, 0);
...@@ -2470,6 +2500,8 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, ...@@ -2470,6 +2500,8 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
{ {
m3_t *chip; m3_t *chip;
int i, err; int i, err;
struct m3_quirk *quirk;
u16 subsystem_vendor, subsystem_device;
static snd_device_ops_t ops = { static snd_device_ops_t ops = {
dev_free: snd_m3_dev_free, dev_free: snd_m3_dev_free,
}; };
...@@ -2500,29 +2532,35 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, ...@@ -2500,29 +2532,35 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
break; break;
} }
chip->card = card;
chip->pci = pci;
chip->irq = -1;
#ifndef LINUX_2_2 #ifndef LINUX_2_2
chip->subsystem_vendor = pci->subsystem_vendor; subsystem_vendor = pci->subsystem_vendor;
chip->subsystem_device = pci->subsystem_device; subsystem_device = pci->subsystem_device;
#else #else
pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->subsystem_vendor); pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->subsystem_device); pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
#endif #endif
for (quirk = m3_quirk_list; quirk->vendor; quirk++) {
if (subsystem_vendor == quirk->vendor &&
subsystem_device == quirk->device) {
chip->quirk = quirk;
break;
}
}
chip->card = card;
chip->pci = pci;
chip->irq = -1;
chip->external_amp = enable_amp; chip->external_amp = enable_amp;
if (amp_gpio >= 0 && amp_gpio <= 0x0f) if (amp_gpio >= 0 && amp_gpio <= 0x0f)
chip->amp_gpio = amp_gpio; chip->amp_gpio = amp_gpio;
else if (chip->allegro_flag) { else if (chip->quirk && chip->quirk->amp_gpio >= 0)
/* panasonic CF-28 "toughbook" has different GPIO connection.. */ chip->amp_gpio = chip->quirk->amp_gpio;
if (chip->subsystem_vendor == 0x10f7 && else if (chip->allegro_flag)
chip->subsystem_device == 0x833e)
chip->amp_gpio = 0x0d;
else
chip->amp_gpio = GPO_EXT_AMP_ALLEGRO; chip->amp_gpio = GPO_EXT_AMP_ALLEGRO;
} else else /* presumably this is for all 'maestro3's.. */
chip->amp_gpio = GPO_EXT_AMP_M3; /* presumably this is for all 'maestro3's.. */ chip->amp_gpio = GPO_EXT_AMP_M3;
chip->num_substreams = NR_DSPS; chip->num_substreams = NR_DSPS;
chip->substreams = kmalloc(sizeof(m3_dma_t) * chip->num_substreams, GFP_KERNEL); chip->substreams = kmalloc(sizeof(m3_dma_t) * chip->num_substreams, GFP_KERNEL);
if (chip->substreams == NULL) { if (chip->substreams == NULL) {
......
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