From 9f6af713341d5147a0211fe85b920aafdf0f7c02 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 18:12:17 +0200 Subject: ALSA CVS update - Clemens Ladisch ALSA sequencer,ALSA<-OSS sequencer export snd_seq_set_queue_tempo() for OSS to prevent calling snd_seq_kernel_client_ctl() (using copy_from_user()) in interrupt context --- include/sound/seq_kernel.h | 3 +++ sound/core/seq/oss/seq_oss_timer.c | 2 +- sound/core/seq/seq.c | 1 + sound/core/seq/seq_clientmgr.c | 18 +++++++++--------- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h index 22dd3a4eccbd..973952b47b4f 100644 --- a/include/sound/seq_kernel.h +++ b/include/sound/seq_kernel.h @@ -168,6 +168,9 @@ typedef int (*snd_seq_dump_func_t)(void *ptr, void *buf, int count); int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf, int in_kernel, int size_aligned); int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t func, void *private_data); +/* interface for OSS emulation */ +int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo); + /* port callback routines */ void snd_port_init_callback(snd_seq_port_callback_t *p); snd_seq_port_callback_t *snd_port_alloc_callback(void); diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c index b0d72a883eeb..d3976147a0fd 100644 --- a/sound/core/seq/oss/seq_oss_timer.c +++ b/sound/core/seq/oss/seq_oss_timer.c @@ -168,7 +168,7 @@ snd_seq_oss_timer_start(seq_oss_timer_t *timer) tmprec.queue = dp->queue; tmprec.ppq = timer->ppq; tmprec.tempo = timer->tempo; - snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, &tmprec); + snd_seq_set_queue_tempo(dp->cseq, &tmprec); send_timer_event(dp, SNDRV_SEQ_EVENT_START, 0); timer->running = 1; diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index 5f8beb4a2037..0559bc89060f 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c @@ -133,6 +133,7 @@ EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); EXPORT_SYMBOL(snd_seq_kernel_client_ctl); EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); +EXPORT_SYMBOL(snd_seq_set_queue_tempo); /* seq_memory.c */ EXPORT_SYMBOL(snd_seq_expand_var_event); EXPORT_SYMBOL(snd_seq_dump_var_event); diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 40fef22f5bc8..df9ff003f929 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1694,6 +1694,13 @@ static int snd_seq_ioctl_get_queue_tempo(client_t * client, void __user *arg) /* SET_QUEUE_TEMPO ioctl() */ +int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo) +{ + if (!snd_seq_queue_check_access(tempo->queue, client)) + return -EPERM; + return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); +} + static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg) { int result; @@ -1702,15 +1709,8 @@ static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg) if (copy_from_user(&tempo, arg, sizeof(tempo))) return -EFAULT; - if (snd_seq_queue_check_access(tempo.queue, client->number)) { - result = snd_seq_queue_timer_set_tempo(tempo.queue, client->number, &tempo); - if (result < 0) - return result; - } else { - return -EPERM; - } - - return 0; + result = snd_seq_set_queue_tempo(client->number, &tempo); + return result < 0 ? result : 0; } -- cgit v1.2.3 From 42265c1d71c23cf4482d772df55f27f75d55269f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 18:13:07 +0200 Subject: ALSA CVS update - Takashi Iwai ATIIXP driver - continue to probe other codecs even if a codec returns error (instead of breaking the probing). this will fix some cases with both AC97 and MC97 codecs. --- sound/pci/atiixp.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 8869e7a68a27..a561b6625f1d 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1,5 +1,5 @@ /* - * ALSA driver for ATI IXP 150/200/250 AC97 controllers + * ALSA driver for ATI IXP 150/200/250/300 AC97 controllers * * Copyright (c) 2004 Takashi Iwai * @@ -1387,17 +1387,9 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock) ac97.num = i; ac97.scaps = AC97_SCAP_SKIP_MODEM; if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { - if (chip->codec_not_ready_bits) - /* codec(s) was detected but not available. - * return the error - */ - return err; - else { - /* codec(s) was NOT detected, so just ignore here */ - chip->ac97[i] = NULL; /* to be sure */ - snd_printd("atiixp: codec %d not found\n", i); - continue; - } + chip->ac97[i] = NULL; /* to be sure */ + snd_printdd("atiixp: codec %d not available for audio\n", i); + continue; } codec_count++; } -- cgit v1.2.3 From a43e48357ad72eac6a44d6116bc971c7a63c2ab9 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 18:13:31 +0200 Subject: ALSA CVS update - Takashi Iwai Documentation,ICE1712 driver,ICE1724 driver - fixed the description of model module parameters for ice1712 and ice1724 drivers. - added the support of VT1720-based mobo. (still experimental and supporting AC97 only) --- Documentation/sound/alsa/ALSA-Configuration.txt | 5 +- sound/pci/ice1712/Makefile | 2 +- sound/pci/ice1712/ice1724.c | 12 +-- sound/pci/ice1712/vt1720_mobo.c | 97 +++++++++++++++++++++++++ sound/pci/ice1712/vt1720_mobo.h | 35 +++++++++ 5 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 sound/pci/ice1712/vt1720_mobo.c create mode 100644 sound/pci/ice1712/vt1720_mobo.h diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 10c5bed26b1c..1edf8cb98d7c 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -613,7 +613,7 @@ Module parameters model - Use the given board model, one of the following: delta1010, dio2496, delta66, delta44, audiophile, delta410, delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d, - dmx6fire, dsp24, dsp24_71, ez8 + dmx6fire, dsp24, dsp24_value, dsp24_71, ez8 omni - Omni I/O support for MidiMan M-Audio Delta44/66 cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever) in msec resolution, default value is 500 (0.5 sec) @@ -631,7 +631,8 @@ Module parameters * TerraTec Aureon Sky-5.1, Space-7.1 model - Use the given board model, one of the following: - revo71, amp2000, prodigy71, aureon51, aureon71 + revo71, amp2000, prodigy71, aureon51, aureon71, + k8x800 Module supports up to 8 cards and autoprobe. diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile index f1e417ca036d..1ac1659237b6 100644 --- a/sound/pci/ice1712/Makefile +++ b/sound/pci/ice1712/Makefile @@ -5,7 +5,7 @@ snd-ice17xx-ak4xxx-objs := ak4xxx.o snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o -snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o +snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o # Toplevel Module Dependency obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index a7a55a98bac1..8d97a38e0ec6 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -44,6 +44,7 @@ #include "amp.h" #include "revo.h" #include "aureon.h" +#include "vt1720_mobo.h" MODULE_AUTHOR("Jaroslav Kysela "); @@ -54,6 +55,7 @@ MODULE_DEVICES("{" REVO_DEVICE_DESC AMP_AUDIO2000_DEVICE_DESC AUREON_DEVICE_DESC + VT1720_MOBO_DEVICE_DESC "{VIA,VT1720}," "{VIA,VT1724}," "{ICEnsemble,Generic ICE1724}," @@ -419,7 +421,7 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force ice->cur_rate = rate; /* check MT02 */ - if (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) { + if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) { val = old = inb(ICEMT1724(ice, I2S_FORMAT)); if (rate > 96000) val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */ @@ -448,7 +450,7 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force } /* set up AC97 registers if needed */ - if (! (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) && ice->ac97) { + if (! (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) && ice->ac97) { snd_ac97_set_rate(ice->ac97, AC97_PCM_FRONT_DAC_RATE, rate); snd_ac97_set_rate(ice->ac97, AC97_PCM_SURR_DAC_RATE, rate); snd_ac97_set_rate(ice->ac97, AC97_PCM_LFE_DAC_RATE, rate); @@ -698,7 +700,7 @@ static snd_pcm_hardware_t snd_vt1724_2ch_stereo = static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream) { snd_pcm_runtime_t *runtime = substream->runtime; - if (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) { + if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) { /* I2S */ if (ice->eeprom.data[ICE_EEP2_I2S] & 0x08) return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_192); @@ -1815,6 +1817,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = { snd_vt1724_revo_cards, snd_vt1724_amp_cards, snd_vt1724_aureon_cards, + snd_vt1720_mobo_cards, 0, }; @@ -1930,9 +1933,6 @@ static int __devinit snd_vt1724_chip_init(ice1712_t *ice) outb(0, ICEREG1724(ice, POWERDOWN)); - /* read back to check the availability of SPDIF out */ - ice->eeprom.data[ICE_EEP2_SPDIF] = inb(ICEREG1724(ice, SPDIF_CFG)); - return 0; } diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c new file mode 100644 index 000000000000..5986f3561521 --- /dev/null +++ b/sound/pci/ice1712/vt1720_mobo.c @@ -0,0 +1,97 @@ +/* + * ALSA driver for VT1720/VT1724 (Envy24PT/Envy24HT) + * + * Lowlevel functions for VT1720-based motherboards + * + * Copyright (c) 2004 Takashi Iwai + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ice1712.h" +#include "vt1720_mobo.h" + + +static int __devinit k8x800_init(ice1712_t *ice) +{ + ice->vt1720 = 1; + + /* VT1616 codec */ + ice->num_total_dacs = 6; + ice->num_total_adcs = 2; + + /* WM8728 codec */ + /* FIXME: TODO */ + + return 0; +} + +static int __devinit k8x800_add_controls(ice1712_t *ice) +{ + /* FIXME: needs some quirks for VT1616? */ + return 0; +} + +/* EEPROM image */ + +static unsigned char k8x800_eeprom[] __devinitdata = { + 0x01, /* SYSCONF: clock 256, 1ADC, 2DACs */ + 0x02, /* ACLINK: ACLINK, packed */ + 0x00, /* I2S: - */ + 0x00, /* SPDIF: - */ + 0xff, /* GPIO_DIR */ + 0xff, /* GPIO_DIR1 */ + 0x00, /* - */ + 0xff, /* GPIO_MASK */ + 0xff, /* GPIO_MASK1 */ + 0x00, /* - */ + 0x00, /* GPIO_STATE */ + 0x00, /* GPIO_STATE1 */ + 0x00, /* - */ +}; + + +/* entry point */ +struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = { + { + .subvendor = VT1720_SUBDEVICE_K8X800, + .name = "Albatron K8X800 Pro II", + .model = "k8x800", + .chip_init = k8x800_init, + .build_controls = k8x800_add_controls, + .eeprom_size = sizeof(k8x800_eeprom), + .eeprom_data = k8x800_eeprom, + }, + { + .subvendor = VT1720_SUBDEVICE_ZNF3_150, + .name = "Chaintech ZNF3-150", + /* identical with k8x800 */ + .chip_init = k8x800_init, + .build_controls = k8x800_add_controls, + .eeprom_size = sizeof(k8x800_eeprom), + .eeprom_data = k8x800_eeprom, + }, + { } /* terminator */ +}; + diff --git a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h new file mode 100644 index 000000000000..aba19bb780de --- /dev/null +++ b/sound/pci/ice1712/vt1720_mobo.h @@ -0,0 +1,35 @@ +#ifndef __SOUND_VT1720_MOBO_H +#define __SOUND_VT1720_MOBO_H + +/* + * ALSA driver for VT1720/VT1724 (Envy24PT/Envy24HT) + * + * Lowlevel functions for VT1720-based motherboards + * + * Copyright (c) 2004 Takashi Iwai + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define VT1720_MOBO_DEVICE_DESC "{Albatron,K8X800 Pro II},"\ + "{Chaintech,ZNF3-150}," + +#define VT1720_SUBDEVICE_K8X800 0xf217052c +#define VT1720_SUBDEVICE_ZNF3_150 0x0f2741f6 + +extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[]; + +#endif /* __SOUND_VT1720_MOBO_H */ -- cgit v1.2.3 From b29b3ca8069bd02d6cff6b4afbf3cfe1feee1f20 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 18:13:55 +0200 Subject: ALSA CVS update - Takashi Iwai Memalloc module - added ifdef CONFIG_PCI around the enable module option to avoid the compile warnings without PCI support. --- sound/core/memalloc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 3cf0917741d6..e562950c9824 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -45,10 +45,14 @@ MODULE_LICENSE("GPL"); #ifndef SNDRV_CARDS #define SNDRV_CARDS 8 #endif + +/* FIXME: so far only some PCI devices have the preallocation table */ +#ifdef CONFIG_PCI static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; static int boot_devs; module_param_array(enable, bool, boot_devs, 0444); MODULE_PARM_DESC(enable, "Enable cards to allocate buffers."); +#endif /* */ -- cgit v1.2.3 From 9d5a2fe0c99dd37fe5b3c3631f0cd0f3c094405e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 18:14:19 +0200 Subject: ALSA CVS update - Takashi Iwai AC97 Codec Core - added the global mutex for ac97_t (ad18xx mutex is removed). used to protect paging and AD18xx multi-codecs. - set PAGE_INT register explicitly before accessing (for STAC9758). - moved ALC650 revision check to patch_alc650(). - support stereo Mic playback. - moved STAC9708 quirk to patch_stac9708(). - don't clear PC_BEEP high bits (ac97 2.3 sets frequency there). - avoid the unnecessary RESET-waiting for audio/modem codec. - fixed the evaluation of modem codec to call mpatch callback properly. - determine the SPDIF rate in the build path. - added suffix argument to snd_ac97_rename|remove|swap_ctl(). - added snd_ac97_rename_vol_ctl(). --- include/sound/ac97_codec.h | 2 +- sound/pci/ac97/ac97_codec.c | 163 +++++++++++++++++++++++++------------------- sound/pci/ac97/ac97_local.h | 7 +- sound/pci/ac97/ac97_patch.c | 105 ++++++++++++++++++++-------- sound/pci/ac97/ac97_proc.c | 10 +-- 5 files changed, 179 insertions(+), 108 deletions(-) diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index 3629059ad262..49bf543d366b 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -441,6 +441,7 @@ struct _snd_ac97 { unsigned short subsystem_vendor; unsigned short subsystem_device; spinlock_t reg_lock; + struct semaphore mutex; /* mutex for AD18xx multi-codecs and paging (2.3) */ unsigned short num; /* number of codec: 0 = primary, 1 = secondary */ unsigned short addr; /* physical address of codec [0-3] */ unsigned int id; /* identification of codec */ @@ -461,7 +462,6 @@ struct _snd_ac97 { unsigned short id[3]; // codec IDs (lower 16-bit word) unsigned short pcmreg[3]; // PCM registers unsigned short codec_cfg[3]; // CODEC_CFG bits - struct semaphore mutex; } ad18xx; unsigned int dev_flags; /* device specific */ } spec; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 8f43dd60dd1b..1aa6f7028df1 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -108,10 +108,10 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { { 0x41445375, 0xffffffff, "AD1985", patch_ad1985, NULL }, { 0x414c4300, 0xffffff00, "ALC100/100P", NULL, NULL }, { 0x414c4710, 0xfffffff0, "ALC200/200P", NULL, NULL }, +{ 0x414c4721, 0xffffffff, "ALC650D", NULL, NULL }, /* already patched */ +{ 0x414c4722, 0xffffffff, "ALC650E", NULL, NULL }, /* already patched */ +{ 0x414c4723, 0xffffffff, "ALC650F", NULL, NULL }, /* already patched */ { 0x414c4720, 0xfffffff0, "ALC650", patch_alc650, NULL }, -{ 0x414c4721, 0xfffffff0, "ALC650D", patch_alc650, NULL }, -{ 0x414c4722, 0xfffffff0, "ALC650E", patch_alc650, NULL }, -{ 0x414c4723, 0xfffffff0, "ALC650F", patch_alc650, NULL }, { 0x414c4760, 0xfffffff0, "ALC655", patch_alc655, NULL }, { 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL }, { 0x414c4730, 0xffffffff, "ALC101", NULL, NULL }, @@ -398,7 +398,7 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho int change; unsigned short old, new, cfg; - down(&ac97->spec.ad18xx.mutex); + down(&ac97->mutex); spin_lock(&ac97->reg_lock); old = ac97->spec.ad18xx.pcmreg[codec]; new = (old & ~mask) | value; @@ -418,7 +418,7 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho cfg | 0x7000); } else spin_unlock(&ac97->reg_lock); - up(&ac97->spec.ad18xx.mutex); + up(&ac97->mutex); return change; } @@ -1120,6 +1120,7 @@ static void snd_ac97_change_volume_params1(ac97_t * ac97, int reg, unsigned char snd_ac97_write_cache(ac97, reg, 0x8000); } +/* check the volume resolution of center/lfe */ static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, unsigned char *max) { unsigned short val, val1; @@ -1135,6 +1136,7 @@ static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, un snd_ac97_write_cache(ac97, reg, 0x8080); } +/* check whether the volume resolution is 4 or 5 bits */ static void snd_ac97_change_volume_params3(ac97_t * ac97, int reg, unsigned char *max) { unsigned short val, val1; @@ -1150,6 +1152,18 @@ static void snd_ac97_change_volume_params3(ac97_t * ac97, int reg, unsigned char snd_ac97_write_cache(ac97, reg, 0x8000); } +/* check whether the volume is mono or stereo */ +static int snd_ac97_is_stereo_vol(ac97_t *ac97, int reg) +{ + unsigned short val, val1, val2; + val = snd_ac97_read(ac97, reg); + val1 = val | 0x8000 | (0x01 << 8); + snd_ac97_write(ac97, reg, val1); + val2 = snd_ac97_read(ac97, reg); + snd_ac97_write(ac97, reg, val); /* restore */ + return val1 == val2; +} + static inline int printable(unsigned int x) { x &= 0xff; @@ -1239,6 +1253,8 @@ static int snd_ac97_cmix_new(snd_card_t *card, const char *pfx, int reg, int che } +static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97); + static int snd_ac97_mixer_build(ac97_t * ac97) { snd_card_t *card = ac97->bus->card; @@ -1293,11 +1309,8 @@ static int snd_ac97_mixer_build(ac97_t * ac97) } /* build headphone controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE) || ac97->id == AC97_ID_STAC9708) { - const char *name = ac97->id == AC97_ID_STAC9708 ? - "Sigmatel Surround Playback" : - "Headphone Playback"; - if ((err = snd_ac97_cmix_new(card, name, AC97_HEADPHONE, 1, ac97)) < 0) + if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) { + if ((err = snd_ac97_cmix_new(card, "Headphone Playback", AC97_HEADPHONE, 1, ac97)) < 0) return err; } @@ -1332,7 +1345,8 @@ static int snd_ac97_mixer_build(ac97_t * ac97) for (idx = 0; idx < 2; idx++) if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0) return err; - snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e); + snd_ac97_write_cache(ac97, AC97_PC_BEEP, + snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e); } /* build Phone controls */ @@ -1349,15 +1363,26 @@ static int snd_ac97_mixer_build(ac97_t * ac97) /* build MIC controls */ snd_ac97_change_volume_params3(ac97, AC97_MIC, &max); - for (idx = 0; idx < 3; idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0) + if (snd_ac97_is_stereo_vol(ac97, AC97_MIC)) { + /* build stereo mic */ + if ((err = snd_ac97_cmute_new(card, "Mic Playback Switch", AC97_MIC, ac97)) < 0) + return err; + if ((err = snd_ac97_cvol_new(card, "Mic Playback Volume", AC97_MIC, max, ac97)) < 0) + return err; + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic[2], ac97))) < 0) return err; - if (idx == 1) { // volume - kctl->private_value &= ~(0xff << 16); - kctl->private_value |= (int)max << 16; + } else { + /* build mono mic */ + for (idx = 0; idx < 3; idx++) { + if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0) + return err; + if (idx == 1) { // volume + kctl->private_value &= ~(0xff << 16); + kctl->private_value |= (int)max << 16; + } } + snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max); } - snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max); /* build Line controls */ if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, 0, ac97)) < 0) @@ -1520,6 +1545,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97) /* set default PCM S/PDIF params */ /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */ snd_ac97_write_cache(ac97, AC97_SPDIF, 0x2a20); + ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97); } ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF; } @@ -1675,7 +1701,7 @@ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem) if (snd_ac97_read(ac97, AC97_REC_GAIN) == 0x8a05) return 0; set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/100); + schedule_timeout(1); } while (time_after_eq(end_time, jiffies)); return -ENODEV; } @@ -1774,6 +1800,7 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97) ac97->bus = bus; bus->codec[ac97->num] = ac97; spin_lock_init(&ac97->reg_lock); + init_MUTEX(&ac97->mutex); if (ac97->pci) { pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor); @@ -1789,8 +1816,12 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97) bus->wait(ac97); else { udelay(50); - if (ac97_reset_wait(ac97, HZ/2, 0) < 0 && - ac97_reset_wait(ac97, HZ/2, 1) < 0) { + err = -ENXIO; + if (! (ac97->scaps & AC97_SCAP_SKIP_AUDIO)) + err = ac97_reset_wait(ac97, HZ/2, 0); + if (err < 0 && ! (ac97->scaps & AC97_SCAP_SKIP_MODEM)) + err = ac97_reset_wait(ac97, HZ/2, 1); + if (err < 0) { snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num); /* proceed anyway - it's often non-critical */ } @@ -1803,20 +1834,6 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97) snd_ac97_free(ac97); return -EIO; } - /* AC97 audio codec chip revision detection. */ - /* Currently only Realtek ALC650 detection implemented. */ - switch(ac97->id & 0xfffffff0) { - case 0x414c4720: /* ALC650 */ - reg = snd_ac97_read(ac97, AC97_ALC650_REVISION); - if (((reg & 0x3f) >= 0) && ((reg & 0x3f) < 3)) - ac97->id = 0x414c4720; /* Old version */ - else if (((reg & 0x3f) >= 3) && ((reg & 0x3f) < 0x10)) - ac97->id = 0x414c4721; /* D version */ - else if ((reg&0x30) == 0x10) - ac97->id = 0x414c4722; /* E version */ - else if ((reg&0x30) == 0x20) - ac97->id = 0x414c4723; /* F version */ - } /* test for AC'97 */ if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) { @@ -1865,9 +1882,9 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97) if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f) goto __ready_ok; set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + schedule_timeout(1); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 %d analog subsections not ready\n", ac97->num); + snd_printk(KERN_WARNING "AC'97 %d analog subsections not ready\n", ac97->num); } /* FIXME: add powerdown control */ @@ -1898,9 +1915,9 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97) if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) goto __ready_ok; set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + schedule_timeout(1); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS)); + snd_printk(KERN_WARNING "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS)); } __ready_ok: @@ -1919,12 +1936,7 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97) } if (ac97->ext_id & AC97_EI_SPDIF) { /* codec specific code (patch) should override these values */ - if (ac97->flags & AC97_CS_SPDIF) - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100; - else if (ac97->id == AC97_ID_CM9739) - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; - else - ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97); + ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_32000; } if (ac97->ext_id & AC97_EI_VRM) { /* MIC VRA support */ snd_ac97_determine_rates(ac97, AC97_PCM_MIC_ADC_RATE, 0, &ac97->rates[AC97_RATES_MIC_ADC]); @@ -1942,8 +1954,8 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97) /* additional initializations */ if (bus->init) bus->init(ac97); - snd_ac97_get_name(ac97, ac97->id, name, 0); - snd_ac97_get_name(NULL, ac97->id, name, 0); // ac97->id might be changed in the special setup code + snd_ac97_get_name(ac97, ac97->id, name, !ac97_is_audio(ac97)); + snd_ac97_get_name(NULL, ac97->id, name, !ac97_is_audio(ac97)); // ac97->id might be changed in the special setup code if (ac97_is_audio(ac97)) { if (card->mixername[0] == '\0') { strcpy(card->mixername, name); @@ -2151,42 +2163,57 @@ __reset_ready: /* */ -int snd_ac97_remove_ctl(ac97_t *ac97, const char *name) +static void set_ctl_name(char *dst, const char *src, const char *suffix) +{ + if (suffix) + sprintf(dst, "%s %s", src, suffix); + else + strcpy(dst, src); +} + +int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix) { snd_ctl_elem_id_t id; memset(&id, 0, sizeof(id)); - strcpy(id.name, name); + set_ctl_name(id.name, name, suffix); id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; return snd_ctl_remove_id(ac97->bus->card, &id); } -static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name) +static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name, const char *suffix) { snd_ctl_elem_id_t sid; memset(&sid, 0, sizeof(sid)); - strcpy(sid.name, name); + set_ctl_name(sid.name, name, suffix); sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; return snd_ctl_find_id(ac97->bus->card, &sid); } -int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst) +int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix) { - snd_kcontrol_t *kctl = ctl_find(ac97, src); + snd_kcontrol_t *kctl = ctl_find(ac97, src, suffix); if (kctl) { - strcpy(kctl->id.name, dst); + set_ctl_name(kctl->id.name, dst, suffix); return 0; } return -ENOENT; } -int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2) +/* rename both Volume and Switch controls - don't check the return value */ +void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst) +{ + snd_ac97_rename_ctl(ac97, src, dst, "Switch"); + snd_ac97_rename_ctl(ac97, src, dst, "Volume"); +} + +int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix) { snd_kcontrol_t *kctl1, *kctl2; - kctl1 = ctl_find(ac97, s1); - kctl2 = ctl_find(ac97, s2); + kctl1 = ctl_find(ac97, s1, suffix); + kctl2 = ctl_find(ac97, s2, suffix); if (kctl1 && kctl2) { - strcpy(kctl1->id.name, s2); - strcpy(kctl2->id.name, s1); + set_ctl_name(kctl1->id.name, s2, suffix); + set_ctl_name(kctl2->id.name, s1, suffix); return 0; } return -ENOENT; @@ -2194,26 +2221,22 @@ int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2) static int swap_headphone(ac97_t *ac97, int remove_master) { - /* FIXME: error checks.. */ if (remove_master) { - if (ctl_find(ac97, "Headphone Playback Switch") == NULL) + if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL) return 0; - snd_ac97_remove_ctl(ac97, "Master Playback Switch"); - snd_ac97_remove_ctl(ac97, "Master Playback Volume"); - } else { - snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Line-Out Playback Switch"); - snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Line-Out Playback Volume"); - } - snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch"); - snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume"); + snd_ac97_remove_ctl(ac97, "Master Playback", "Switch"); + snd_ac97_remove_ctl(ac97, "Master Playback", "Volume"); + } else + snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Line-Out Playback"); + snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback"); return 0; } static int swap_surround(ac97_t *ac97) { /* FIXME: error checks.. */ - snd_ac97_swap_ctl(ac97, "Master Playback Switch", "Surround Playback Switch"); - snd_ac97_swap_ctl(ac97, "Master Playback Volume", "Surround Playback Volume"); + snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch"); + snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume"); return 0; } diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h index 838656f76177..3abdeda27dfe 100644 --- a/sound/pci/ac97/ac97_local.h +++ b/sound/pci/ac97/ac97_local.h @@ -38,9 +38,10 @@ int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo); int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit); -int snd_ac97_remove_ctl(ac97_t *ac97, const char *name); -int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst); -int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2); +int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix); +int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix); +int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix); +void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst); /* ac97_proc.c */ void snd_ac97_bus_proc_init(ac97_bus_t * ac97); diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 85124051ef70..d228c4dff358 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -204,7 +204,7 @@ static int patch_yamaha_ymf753_3d(ac97_t * ac97) if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) return err; strcpy(kctl->id.name, "3D Control - Wide"); - kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16); + kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0); snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0) return err; @@ -315,7 +315,7 @@ static int patch_sigmatel_stac9700_3d(ac97_t * ac97) if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) return err; strcpy(kctl->id.name, "3D Control Sigmatel - Depth"); - kctl->private_value = AC97_3D_CONTROL | (3 << 16); + kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0); snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); return 0; } @@ -328,11 +328,11 @@ static int patch_sigmatel_stac9708_3d(ac97_t * ac97) if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) return err; strcpy(kctl->id.name, "3D Control Sigmatel - Depth"); - kctl->private_value = AC97_3D_CONTROL | (3 << 16); + kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0); if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) return err; strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth"); - kctl->private_value = AC97_3D_CONTROL | (2 << 8) | (3 << 16); + kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0); snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); return 0; } @@ -373,17 +373,23 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = { .build_specific = patch_sigmatel_stac97xx_specific }; -static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = { - .build_3d = patch_sigmatel_stac9708_3d, - .build_specific = patch_sigmatel_stac97xx_specific -}; - int patch_sigmatel_stac9700(ac97_t * ac97) { ac97->build_ops = &patch_sigmatel_stac9700_ops; return 0; } +static int patch_sigmatel_stac9708_specific(ac97_t *ac97) +{ + snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback"); + return patch_sigmatel_stac97xx_specific(ac97); +} + +static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = { + .build_3d = patch_sigmatel_stac9708_3d, + .build_specific = patch_sigmatel_stac9708_specific +}; + int patch_sigmatel_stac9708(ac97_t * ac97) { unsigned int codec72, codec6c; @@ -467,11 +473,11 @@ static int snd_ac97_stac9758_output_jack_get(snd_kcontrol_t *kcontrol, snd_ctl_e int shift = kcontrol->private_value; unsigned short val; - val = ac97->regs[AC97_SIGMATEL_OUTSEL]; - if (!((val >> shift) & 4)) + val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift; + if (!(val & 4)) ucontrol->value.enumerated.item[0] = 0; else - ucontrol->value.enumerated.item[0] = 1 + ((val >> shift) & 3); + ucontrol->value.enumerated.item[0] = 1 + (val & 3); return 0; } @@ -480,6 +486,7 @@ static int snd_ac97_stac9758_output_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_e ac97_t *ac97 = snd_kcontrol_chip(kcontrol); int shift = kcontrol->private_value; unsigned short val; + int ret; if (ucontrol->value.enumerated.item[0] > 4) return -EINVAL; @@ -487,8 +494,12 @@ static int snd_ac97_stac9758_output_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_e val = 0; else val = 4 | (ucontrol->value.enumerated.item[0] - 1); - return snd_ac97_update_bits(ac97, AC97_SIGMATEL_OUTSEL, - 7 << shift, val << shift); + down(&ac97->mutex); + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); + ret = snd_ac97_update_bits(ac97, AC97_SIGMATEL_OUTSEL, + 7 << shift, val << shift); + up(&ac97->mutex); + return ret; } static int snd_ac97_stac9758_input_jack_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) @@ -520,9 +531,14 @@ static int snd_ac97_stac9758_input_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_el { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); int shift = kcontrol->private_value; + int ret; - return snd_ac97_update_bits(ac97, AC97_SIGMATEL_INSEL, 7 << shift, - ucontrol->value.enumerated.item[0] << shift); + down(&ac97->mutex); + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); + ret = snd_ac97_update_bits(ac97, AC97_SIGMATEL_INSEL, 7 << shift, + ucontrol->value.enumerated.item[0] << shift); + up(&ac97->mutex); + return ret; } static int snd_ac97_stac9758_phonesel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) @@ -549,9 +565,14 @@ static int snd_ac97_stac9758_phonesel_get(snd_kcontrol_t *kcontrol, snd_ctl_elem static int snd_ac97_stac9758_phonesel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + int ret; - return snd_ac97_update_bits(ac97, AC97_SIGMATEL_IOMISC, 3, - ucontrol->value.enumerated.item[0]); + down(&ac97->mutex); + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); + ret = snd_ac97_update_bits(ac97, AC97_SIGMATEL_IOMISC, 3, + ucontrol->value.enumerated.item[0]); + up(&ac97->mutex); + return ret; } #define STAC9758_OUTPUT_JACK(xname, shift) \ @@ -596,6 +617,14 @@ static int patch_sigmatel_stac9758_specific(ac97_t *ac97) ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls)); if (err < 0) return err; + /* DAC-A direct */ + snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback"); + /* DAC-A to Mix = PCM */ + /* DAC-B direct = Surround */ + /* DAC-B to Mix */ + snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback"); + /* DAC-C direct = Center/LFE */ + return 0; } @@ -613,16 +642,16 @@ int patch_sigmatel_stac9758(ac97_t * ac97) AC97_SIGMATEL_VARIOUS }; static unsigned short def_regs[4] = { - /* OUTSEL */ 0xd794, + /* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */ /* IOMISC */ 0x2001, - /* INSEL */ 0x0201, + /* INSEL */ 0x0201, /* LI:LI, MI:M1 */ /* VARIOUS */ 0x0040 }; static unsigned short m675_regs[4] = { - /* OUTSEL */ 0x9040, - /* IOMISC */ 0x2102, - /* INSEL */ 0x0203, - /* VARIOUS */ 0x0041 + /* OUTSEL */ 0x9040, /* CL:FR, SR:FR, LO:DS, LI:FR, MI:DS */ + /* IOMISC */ 0x2102, /* HP amp on */ + /* INSEL */ 0x0203, /* LI:LI, MI:FR */ + /* VARIOUS */ 0x0041 /* stereo mic */ }; unsigned short *pregs = def_regs; int i; @@ -635,6 +664,8 @@ int patch_sigmatel_stac9758(ac97_t * ac97) // patch for SigmaTel ac97->build_ops = &patch_sigmatel_stac9758_ops; + /* FIXME: assume only page 0 for writing cache */ + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); for (i = 0; i < 4; i++) snd_ac97_write_cache(ac97, regs[i], pregs[i]); @@ -654,8 +685,10 @@ static int patch_cirrus_build_spdif(ac97_t * ac97) { int err; + /* con mask, pro mask, default */ if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0) return err; + /* switch, spsa */ if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0) return err; switch (ac97->id & AC97_ID_CS_MASK) { @@ -714,8 +747,10 @@ static int patch_conexant_build_spdif(ac97_t * ac97) { int err; + /* con mask, pro mask, default */ if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0) return err; + /* switch */ if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0) return err; /* set default PCM S/PDIF params */ @@ -734,6 +769,7 @@ int patch_conexant(ac97_t * ac97) ac97->build_ops = &patch_conexant_ops; ac97->flags |= AC97_CX_SPDIF; ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ + ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ return 0; } @@ -821,8 +857,6 @@ int patch_ad1881(ac97_t * ac97) unsigned short val; int idx, num; - init_MUTEX(&ac97->spec.ad18xx.mutex); - val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG); snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val); codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12)); @@ -1114,10 +1148,8 @@ static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = { static int patch_ad1888_specific(ac97_t *ac97) { /* rename 0x04 as "Master" and 0x02 as "Master Surround" */ - snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Master Surround Playback Switch"); - snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Master Surround Playback Volume"); - snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch"); - snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume"); + snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Master Surround Playback"); + snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback"); return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls)); } @@ -1303,6 +1335,17 @@ int patch_alc650(ac97_t * ac97) ac97->build_ops = &patch_alc650_ops; + /* determine the revision */ + val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f; + if (val < 3) + ac97->id = 0x414c4720; /* Old version */ + else if (val < 0x10) + ac97->id = 0x414c4721; /* D version */ + else if (val < 0x20) + ac97->id = 0x414c4722; /* E version */ + else if (val < 0x30) + ac97->id = 0x414c4723; /* F version */ + /* revision E or F */ /* FIXME: what about revision D ? */ ac97->spec.dev_flags = (ac97->id == 0x414c4722 || @@ -1599,8 +1642,10 @@ int patch_cm9739(ac97_t * ac97) /* enable spdif in */ snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL, snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01); + ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ } else { ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */ + ac97->rates[AC97_RATES_SPDIF] = 0; } /* set-up multi channel */ diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 40b3e9fd8f5b..0a5865066018 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c @@ -292,9 +292,9 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff { ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return); + down(&ac97->mutex); if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 int idx; - down(&ac97->spec.ad18xx.mutex); for (idx = 0; idx < 3; idx++) if (ac97->spec.ad18xx.id[idx]) { /* select single codec */ @@ -305,7 +305,6 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff } /* select all codecs */ snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); - up(&ac97->spec.ad18xx.mutex); snd_iprintf(buffer, "\nAD18XX configuration\n"); snd_iprintf(buffer, "Unchained : 0x%04x,0x%04x,0x%04x\n", @@ -319,6 +318,7 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff } else { snd_ac97_proc_read_main(ac97, buffer, 0); } + up(&ac97->mutex); } #ifdef CONFIG_SND_DEBUG @@ -328,6 +328,7 @@ static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return); char line[64]; unsigned int reg, val; + down(&ac97->mutex); while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; @@ -335,6 +336,7 @@ static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff) snd_ac97_write_cache(ac97, reg, val); } + up(&ac97->mutex); } #endif @@ -353,10 +355,10 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry, { ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return); + down(&ac97->mutex); if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 int idx; - down(&ac97->spec.ad18xx.mutex); for (idx = 0; idx < 3; idx++) if (ac97->spec.ad18xx.id[idx]) { /* select single codec */ @@ -366,10 +368,10 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry, } /* select all codecs */ snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); - up(&ac97->spec.ad18xx.mutex); } else { snd_ac97_proc_regs_read_main(ac97, buffer, 0); } + up(&ac97->mutex); } void snd_ac97_proc_init(ac97_t * ac97) -- cgit v1.2.3 From 974d45016a5e9a04a188d756b4de0af833aa8944 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 18:19:07 +0200 Subject: ALSA CVS update - Takashi Iwai Digigram VX core fixed sleep while atomic in the trigger callback. --- sound/drivers/vx/vx_pcm.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index 9ee1c80efb6a..38a1f08f1889 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -394,17 +394,14 @@ static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state) * enough sound buffer for this pipe) */ if (state) { - int delay = CAN_START_DELAY; for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) { - snd_vx_delay(chip, delay); err = vx_pipe_can_start(chip, pipe); if (err > 0) break; /* Wait for a few, before asking again * to avoid flooding the DSP with our requests */ - if ((i % 4 ) == 0) - delay <<= 1; + mdelay(1); } } @@ -418,15 +415,12 @@ static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state) * reaching the expected state before returning * Check one pipe only (since they are synchronous) */ - delay = WAIT_STATE_DELAY; for (i = 0; i < MAX_WAIT_FOR_DSP; i++) { - snd_vx_delay(chip, delay); err = vx_get_pipe_state(chip, pipe, &cur_state); if (err < 0 || cur_state == state) break; err = -EIO; - if ((i % 4 ) == 0) - delay <<= 1; + mdelay(1); } return err < 0 ? -EIO : 0; } -- cgit v1.2.3 From 1792dfe63cce2a5ca536588a8ebe433dea6b377e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 18:19:28 +0200 Subject: ALSA CVS update - Takashi Iwai PARISC Harmony driver - fixed the buffer handling without dma_alloc_coherent support. --- sound/parisc/harmony.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 423ab05c0480..fe86169d56b6 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -751,6 +751,8 @@ static int snd_card_harmony_hw_params(snd_pcm_substream_t *substream, int err; err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); + if (err > 0 && substream->dma_device.type == SNDRV_DMA_TYPE_CONTINUOUS) + substream->runtime->dma_addr = __pa(substream->runtime->dma_area); DPRINTK(KERN_INFO PFX "HW Params returned %d, dma_addr %lx\n", err, (unsigned long)substream->runtime->dma_addr); return err; @@ -784,7 +786,7 @@ static snd_pcm_ops_t snd_card_harmony_capture_ops = { .pointer = snd_card_harmony_capture_pointer, }; -static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device) +static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony) { snd_pcm_t *pcm; int err; @@ -797,7 +799,7 @@ static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device) snd_harmony_disable_interrupts(harmony); - if ((err = snd_pcm_new(harmony->card, "Harmony", device, 1, 1, &pcm)) < 0) + if ((err = snd_pcm_new(harmony->card, "Harmony", 0, 1, 1, &pcm)) < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_harmony_playback_ops); @@ -813,26 +815,46 @@ static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device) harmony->dma_dev.dev = &harmony->pa_dev->dev; err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*GRAVEYARD_BUFS, &harmony->graveyard_dma); - if (err < 0) + if (err == -ENOMEM) { + /* use continuous buffers */ + harmony->dma_dev.type = SNDRV_DMA_TYPE_CONTINUOUS; + harmony->dma_dev.dev = snd_dma_continuous_data(GFP_KERNEL); + err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*GRAVEYARD_BUFS, + &harmony->graveyard_dma); + } + if (err < 0) { + printk(KERN_ERR PFX "can't allocate graveyard buffer\n"); return err; + } harmony->graveyard_count = 0; /* initialize silence buffers */ err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*SILENCE_BUFS, &harmony->silence_dma); - if (err < 0) + if (err < 0) { + printk(KERN_ERR PFX "can't allocate silence buffer\n"); return err; + } harmony->silence_count = 0; + if (harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS) { + harmony->graveyard_dma.addr = __pa(harmony->graveyard_dma.area); + harmony->silence_dma.addr = __pa(harmony->silence_dma.area); + } + harmony->ply_stopped = harmony->cap_stopped = 1; harmony->playback_substream = NULL; harmony->capture_substream = NULL; harmony->graveyard_count = 0; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - &harmony->pa_dev->dev, - MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); + + err = snd_pcm_lib_preallocate_pages_for_all(pcm, harmony->dma_dev.type, + harmony->dma_dev.dev, + MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); + if (err < 0) { + printk(KERN_ERR PFX "buffer allocation error %d\n", err); + // return err; + } return 0; } @@ -1037,7 +1059,7 @@ static int __init snd_card_harmony_probe(struct parisc_device *pa_dev) snd_card_free(card); return err; } - if ((err = snd_card_harmony_pcm_init(chip, dev)) < 0) { + if ((err = snd_card_harmony_pcm_init(chip)) < 0) { printk(KERN_ERR PFX "PCM Init failed\n"); snd_card_free(card); return err; -- cgit v1.2.3 From 2b622aa61d2a3e889cb817de971fbe7fba095bba Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 18:19:53 +0200 Subject: ALSA CVS update - Takashi Iwai Digigram VX core fixed the compile warnings due to the last change. --- sound/drivers/vx/vx_pcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index 38a1f08f1889..9ae96b949d65 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -381,7 +382,7 @@ static int vx_send_irqa(vx_core_t *chip) */ static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state) { - int err, i, cur_state, delay; + int err, i, cur_state; /* Check the pipe is not already in the requested state */ if (vx_get_pipe_state(chip, pipe, &cur_state) < 0) -- cgit v1.2.3 From 51c11179920da536dc7255a997eb5ffa1de38bcf Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 18:20:17 +0200 Subject: ALSA CVS update - Takashi Iwai Digigram VX core added 'Clock Mode' control to choose the clock source. --- include/sound/vx_core.h | 8 +++++++ sound/drivers/vx/vx_core.c | 3 +++ sound/drivers/vx/vx_mixer.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ sound/drivers/vx/vx_uer.c | 15 ++++++------- 4 files changed, 70 insertions(+), 7 deletions(-) diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h index bcc633a55885..09e1f84892e7 100644 --- a/include/sound/vx_core.h +++ b/include/sound/vx_core.h @@ -182,6 +182,7 @@ struct snd_vx_core { /* clock and audio sources */ unsigned int audio_source; /* current audio input source */ unsigned int audio_source_target; + unsigned int clock_mode; /* clock mode (VX_CLOCK_MODE_XXX) */ unsigned int clock_source; /* current clock source (INTERNAL_QUARTZ or UER_SYNC) */ unsigned int freq; /* current frequency */ unsigned int freq_detected; /* detected frequency from digital in */ @@ -364,6 +365,13 @@ enum { UER_SYNC }; +/* clock mode */ +enum { + VX_CLOCK_MODE_AUTO, /* depending on the current audio source */ + VX_CLOCK_MODE_INTERNAL, /* fixed to internal quartz */ + VX_CLOCK_MODE_EXTERNAL /* fixed to UER sync */ +}; + /* SPDIF/UER type */ enum { VX_UER_MODE_CONSUMER, diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index 31a94efd6534..2ba233df3286 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -572,6 +572,7 @@ static void vx_reset_board(vx_core_t *chip, int cold_reset) if (cold_reset) { chip->audio_source_target = chip->audio_source; chip->clock_source = INTERNAL_QUARTZ; + chip->clock_mode = VX_CLOCK_MODE_AUTO; chip->freq = 48000; chip->uer_detected = VX_UER_MODE_NOT_PRESENT; chip->uer_bits = SNDRV_PCM_DEFAULT_CON_SPDIF; @@ -606,6 +607,7 @@ static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) vx_core_t *chip = snd_magic_cast(vx_core_t, entry->private_data, return); static char *audio_src_vxp[] = { "Line", "Mic", "Digital" }; static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" }; + static char *clock_mode[] = { "Auto", "Internal", "External" }; static char *clock_src[] = { "Internal", "External" }; static char *uer_type[] = { "Consumer", "Professional", "Not Present" }; @@ -629,6 +631,7 @@ static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) snd_iprintf(buffer, "Input Source: %s\n", vx_is_pcmcia(chip) ? audio_src_vxp[chip->audio_source] : audio_src_vx2[chip->audio_source]); + snd_iprintf(buffer, "Clock Mode: %s\n", clock_mode[chip->clock_mode]); snd_iprintf(buffer, "Clock Source: %s\n", clock_src[chip->clock_source]); snd_iprintf(buffer, "Frequency: %d\n", chip->freq); snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected); diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c index 52cfb80b5b3c..cbffed79278c 100644 --- a/sound/drivers/vx/vx_mixer.c +++ b/sound/drivers/vx/vx_mixer.c @@ -523,6 +523,54 @@ static snd_kcontrol_new_t vx_control_audio_src = { .put = vx_audio_src_put, }; +/* + * clock mode selection + */ +static int vx_clock_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + static char *texts[3] = { + "Auto", "Internal", "External" + }; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 3; + if (uinfo->value.enumerated.item > 2) + uinfo->value.enumerated.item = 2; + strcpy(uinfo->value.enumerated.name, + texts[uinfo->value.enumerated.item]); + return 0; +} + +static int vx_clock_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + vx_core_t *chip = snd_kcontrol_chip(kcontrol); + ucontrol->value.enumerated.item[0] = chip->clock_mode; + return 0; +} + +static int vx_clock_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + vx_core_t *chip = snd_kcontrol_chip(kcontrol); + down(&chip->mixer_mutex); + if (chip->clock_mode != ucontrol->value.enumerated.item[0]) { + chip->clock_mode = ucontrol->value.enumerated.item[0]; + vx_set_clock(chip, chip->freq); + up(&chip->mixer_mutex); + return 1; + } + up(&chip->mixer_mutex); + return 0; +} + +static snd_kcontrol_new_t vx_control_clock_mode = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Clock Mode", + .info = vx_clock_mode_info, + .get = vx_clock_mode_get, + .put = vx_clock_mode_put, +}; + /* * Audio Gain */ @@ -913,6 +961,9 @@ int snd_vx_mixer_new(vx_core_t *chip) /* Audio source */ if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0) return err; + /* clock mode */ + if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0) + return err; /* IEC958 controls */ if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0) return err; diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c index 54609aac8a14..5db41f136d64 100644 --- a/sound/drivers/vx/vx_uer.c +++ b/sound/drivers/vx/vx_uer.c @@ -263,17 +263,17 @@ int vx_set_clock(vx_core_t *chip, unsigned int freq) /* change the audio source if possible */ vx_sync_audio_source(chip); - switch (chip->audio_source) { - case VX_AUDIO_SRC_DIGITAL: + if (chip->clock_mode == VX_CLOCK_MODE_EXTERNAL || + (chip->clock_mode == VX_CLOCK_MODE_AUTO && + chip->audio_source == VX_AUDIO_SRC_DIGITAL)) { if (chip->clock_source != UER_SYNC) { vx_change_clock_source(chip, UER_SYNC); mdelay(6); src_changed = 1; } - if (chip->freq == freq) - return 0; - break; - default: + } else if (chip->clock_mode == VX_CLOCK_MODE_INTERNAL || + (chip->clock_mode == VX_CLOCK_MODE_AUTO && + chip->audio_source != VX_AUDIO_SRC_DIGITAL)) { if (chip->clock_source != INTERNAL_QUARTZ) { vx_change_clock_source(chip, INTERNAL_QUARTZ); src_changed = 1; @@ -283,8 +283,9 @@ int vx_set_clock(vx_core_t *chip, unsigned int freq) vx_set_internal_clock(chip, freq); if (src_changed) vx_modify_board_inputs(chip); - break; } + if (chip->freq == freq) + return 0; chip->freq = freq; vx_modify_board_clock(chip, 1); return 0; -- cgit v1.2.3 From 23349d0d958ea2f1e473ca0aed69e1a3b0fabd92 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 18:20:37 +0200 Subject: ALSA CVS update - Takashi Iwai ICE1724 driver avoid to change the AC97 rate registers. this seems conflicting with the rate conversion on VT172x. --- sound/pci/ice1712/ice1724.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 8d97a38e0ec6..26719f6ed5a7 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -448,15 +448,6 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force if (ice->akm[i].ops.set_rate_val) ice->akm[i].ops.set_rate_val(&ice->akm[i], rate); } - - /* set up AC97 registers if needed */ - if (! (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) && ice->ac97) { - snd_ac97_set_rate(ice->ac97, AC97_PCM_FRONT_DAC_RATE, rate); - snd_ac97_set_rate(ice->ac97, AC97_PCM_SURR_DAC_RATE, rate); - snd_ac97_set_rate(ice->ac97, AC97_PCM_LFE_DAC_RATE, rate); - snd_ac97_set_rate(ice->ac97, AC97_SPDIF, rate); - snd_ac97_set_rate(ice->ac97, AC97_PCM_LR_ADC_RATE, rate); - } } static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream, @@ -716,15 +707,9 @@ static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream) ratec = AC97_RATES_FRONT_DAC; else ratec = AC97_RATES_ADC; - runtime->hw.rates = ice->ac97->rates[ratec]; runtime->hw.rate_max = 48000; - if (runtime->hw.rates == SNDRV_PCM_RATE_48000) { - runtime->hw.rate_min = 48000; - return 0; - } else { - runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000; - return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_48); - } + runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000; + return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_48); } return 0; } -- cgit v1.2.3 From 1bd7d13247e128511c4128a35c211d4492a190e1 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 19:01:53 +0200 Subject: ALSA CVS update - Clemens Ladisch Wavefront drivers fix possible buffer overflow in wavefront_download_firmware() --- sound/isa/wavefront/wavefront_synth.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index af561df2a413..cbba4bc00daa 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -1966,6 +1966,12 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path) break; } + if (section_length < 0 || section_length > WF_SECTION_MAX) { + snd_printk ("invalid firmware section length %d\n", + section_length); + goto failure; + } + if (sys_read (fd, section, section_length) != section_length) { snd_printk ("firmware section " "read error.\n"); -- cgit v1.2.3 From d85823dcca278295fe3aa5cde11962b74fa8d682 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 19:02:13 +0200 Subject: ALSA CVS update - Takashi Iwai VIA82xx driver added the DXS entry for Mitac/Vobis/Yakumo laptop. --- sound/pci/via82xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 67e5edd5b5c2..b8e96af2eea7 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2114,6 +2114,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) { .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/ { .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */ { .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ + { .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ { .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */ { .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */ { .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */ -- cgit v1.2.3 From dc979556bd06dad106537e09c94a71e1e3388eee Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 19:02:35 +0200 Subject: ALSA CVS update - Takashi Iwai AC97 Codec Core added ac97_can_spdif() for checking the SPDIF support. --- include/sound/ac97_codec.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index 49bf543d366b..ee64dd0bf169 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -484,6 +484,10 @@ static inline int ac97_can_amap(ac97_t * ac97) { return (ac97->ext_id & AC97_EI_AMAP) != 0; } +static inline int ac97_can_spdif(ac97_t * ac97) +{ + return (ac97->ext_id & AC97_EI_SPDIF) != 0; +} /* functions */ int snd_ac97_bus(snd_card_t * card, ac97_bus_t * _bus, ac97_bus_t ** rbus); /* create new AC97 bus */ -- cgit v1.2.3 From 36e65502739d1072e18d4aaa0230d7c89fba1106 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 19:02:56 +0200 Subject: ALSA CVS update - Takashi Iwai VIA82xx driver - use snd_pcm_limit_hw_rates() and removed redundant codes. - fixed the rate constraints when 'IEC958 Output Switch' is on. - check the SPDIF support on AC97 and don't build IEC958 stuffs if not available. --- sound/pci/via82xx.c | 53 +++++++++++++++-------------------------------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index b8e96af2eea7..f69510f54c48 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1060,19 +1060,6 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst int err; unsigned long flags; struct via_rate_lock *ratep; - struct ratetbl { - int rate; - unsigned int bit; - } ratebits[] = { - {8000, SNDRV_PCM_RATE_8000}, - {11025, SNDRV_PCM_RATE_11025}, - {16000, SNDRV_PCM_RATE_16000}, - {22050, SNDRV_PCM_RATE_22050}, - {32000, SNDRV_PCM_RATE_32000}, - {44100, SNDRV_PCM_RATE_44100}, - {48000, SNDRV_PCM_RATE_48000}, - }; - int i; runtime->hw = snd_via82xx_hw; @@ -1080,10 +1067,10 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst ratep = &chip->rates[viadev->direction]; spin_lock_irqsave(&ratep->lock, flags); ratep->used++; - if (chip->spdif_on) { - runtime->hw.rates = SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000; - runtime->hw.rate_min = 32000; - runtime->hw.rate_max = 48000; + if (chip->spdif_on && viadev->reg_offset == 0x30) { + /* DXS#3 and spdif is on */ + runtime->hw.rates = chip->ac97->rates[AC97_RATES_SPDIF]; + snd_pcm_limit_hw_rates(runtime); } else if (chip->dxs_fixed && viadev->reg_offset < 0x40) { /* fixed DXS playback rate */ runtime->hw.rates = SNDRV_PCM_RATE_48000; @@ -1091,27 +1078,10 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst } else if (! ratep->rate) { int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; runtime->hw.rates = chip->ac97->rates[idx]; - for (i = 0; i < (int)ARRAY_SIZE(ratebits); i++) { - if (runtime->hw.rates & ratebits[i].bit) { - runtime->hw.rate_min = ratebits[i].rate; - break; - } - } - for (i = ARRAY_SIZE(ratebits) - 1; i >= 0; i--) { - if (runtime->hw.rates & ratebits[i].bit) { - runtime->hw.rate_max = ratebits[i].rate; - break; - } - } + snd_pcm_limit_hw_rates(runtime); } else { /* a fixed rate */ runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - for (i = 0; i < (int)ARRAY_SIZE(ratebits); i++) { - if (ratep->rate == ratebits[i].rate) { - runtime->hw.rates = ratebits[i].bit; - break; - } - } runtime->hw.rate_max = runtime->hw.rate_min = ratep->rate; } spin_unlock_irqrestore(&ratep->lock, flags); @@ -1363,6 +1333,10 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip) snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) return err; + /* SPDIF supported? */ + if (! ac97_can_spdif(chip->ac97)) + return 0; + /* PCM #1: DXS3 playback (for spdif) */ err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 0, &pcm); if (err < 0) @@ -1660,9 +1634,11 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev) if (err < 0) return err; } - err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs3_spdif_control, chip)); - if (err < 0) - return err; + if (ac97_can_spdif(chip->ac97)) { + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs3_spdif_control, chip)); + if (err < 0) + return err; + } if (chip->chip_type != TYPE_VIA8233A) { err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip)); if (err < 0) @@ -1672,6 +1648,7 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev) /* select spdif data slot 10/11 */ pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val); val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011; + val &= ~VIA8233_SPDIF_DX3; /* SPDIF off as default */ pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, val); return 0; -- cgit v1.2.3 From 41aa0545969c1abd643177adeda59baba8089824 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 19:03:20 +0200 Subject: ALSA CVS update - Jaroslav Kysela AC97 Codec Core Signed-off-by: Kevin Mack For Gateway M675 notebook - this will direct mixer output to speaker, headphone and line-out instead of just the front(DAC-A) signal. --- sound/pci/ac97/ac97_patch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index d228c4dff358..6587832e916d 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -648,7 +648,7 @@ int patch_sigmatel_stac9758(ac97_t * ac97) /* VARIOUS */ 0x0040 }; static unsigned short m675_regs[4] = { - /* OUTSEL */ 0x9040, /* CL:FR, SR:FR, LO:DS, LI:FR, MI:DS */ + /* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */ /* IOMISC */ 0x2102, /* HP amp on */ /* INSEL */ 0x0203, /* LI:LI, MI:FR */ /* VARIOUS */ 0x0041 /* stereo mic */ -- cgit v1.2.3 From 39e34f02a8e545dc2180ed414e6daf11e9583057 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 19:03:42 +0200 Subject: ALSA CVS update - Takashi Iwai PARISC Harmony driver fixed typos. --- sound/parisc/harmony.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index fe86169d56b6..90bd82a6e842 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -556,7 +556,7 @@ static int snd_card_harmony_playback_prepare(snd_pcm_substream_t * substream) harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate); /* data format */ - harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format); + harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format); /* number of channels */ if (runtime->channels == 2) @@ -587,7 +587,7 @@ static int snd_card_harmony_capture_prepare(snd_pcm_substream_t * substream) harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate); /* data format */ - harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format); + harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format); /* number of channels */ if (runtime->channels == 1) -- cgit v1.2.3 From a19652ee6b8ddffeeee9c88addb29c2ed548175e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 19:04:07 +0200 Subject: ALSA CVS update - Takashi Iwai AC97 Codec Core Avoid warning message during codec probing in case SKIP_AUDIO flag is not set. --- sound/pci/ac97/ac97_codec.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 1aa6f7028df1..3fa99a03a90e 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1816,11 +1816,13 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97) bus->wait(ac97); else { udelay(50); - err = -ENXIO; - if (! (ac97->scaps & AC97_SCAP_SKIP_AUDIO)) - err = ac97_reset_wait(ac97, HZ/2, 0); - if (err < 0 && ! (ac97->scaps & AC97_SCAP_SKIP_MODEM)) + if (ac97->scaps & AC97_SCAP_SKIP_AUDIO) err = ac97_reset_wait(ac97, HZ/2, 1); + else { + err = ac97_reset_wait(ac97, HZ/2, 0); + if (err < 0) + err = ac97_reset_wait(ac97, 0, 1); + } if (err < 0) { snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num); /* proceed anyway - it's often non-critical */ -- cgit v1.2.3 From 883f8f57de2cc240a876c3e8cc5328d8ddb84399 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 May 2004 19:04:32 +0200 Subject: ALSA CVS update - Takashi Iwai AC97 Codec Core - Added the single mixer control with AC97 2.3 paging. - Handle the paging for some ALC655/658 registers. - Added the experimental support for ALC850. --- sound/pci/ac97/ac97_codec.c | 79 +++++++++++++++----- sound/pci/ac97/ac97_id.h | 7 ++ sound/pci/ac97/ac97_local.h | 7 ++ sound/pci/ac97/ac97_patch.c | 176 +++++++++++++++++++++++++++++++++++++------- sound/pci/ac97/ac97_patch.h | 1 + 5 files changed, 224 insertions(+), 46 deletions(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 3fa99a03a90e..518a94287fa5 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -114,6 +114,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { { 0x414c4720, 0xfffffff0, "ALC650", patch_alc650, NULL }, { 0x414c4760, 0xfffffff0, "ALC655", patch_alc655, NULL }, { 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL }, +{ 0x414c4790, 0xfffffff0, "ALC850", patch_alc850, NULL }, { 0x414c4730, 0xffffffff, "ALC101", NULL, NULL }, { 0x414c4740, 0xfffffff0, "ALC202", NULL, NULL }, { 0x414c4750, 0xfffffff0, "ALC250", NULL, NULL }, @@ -274,7 +275,7 @@ void snd_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short value) { if (!snd_ac97_valid_reg(ac97, reg)) return; - if ((ac97->id & 0xffffff00) == 0x414c4300) { + if ((ac97->id & 0xffffff00) == AC97_ID_ALC100) { /* Fix H/W bug of ALC100/100P */ if (reg == AC97_MASTER || reg == AC97_HEADPHONE) ac97->bus->write(ac97, AC97_RESET, 0); /* reset audio codec */ @@ -545,7 +546,7 @@ int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontr int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; + int invert = (kcontrol->private_value >> 24) & 0x01; ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask; if (invert) @@ -559,7 +560,7 @@ int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontr int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; + int invert = (kcontrol->private_value >> 24) & 0x01; unsigned short val; val = (ucontrol->value.integer.value[0] & mask); @@ -625,6 +626,40 @@ static int snd_ac97_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * (val1 << shift_left) | (val2 << shift_right)); } +int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, + int (*func)(snd_kcontrol_t *, snd_ctl_elem_value_t *)) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + int reg = kcontrol->private_value & 0xff; + int err; + + if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 && + (reg >= 0x60 && reg < 0x70)) { + unsigned short page_save; + unsigned short page = (kcontrol->private_value >> 25) & 0x0f; + down(&ac97->mutex); /* lock paging */ + page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); + err = func(kcontrol, ucontrol); + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); + down(&ac97->mutex); /* unlock paging */ + } else + err = func(kcontrol, ucontrol); + return err; +} + +/* for rev2.3 paging */ +int snd_ac97_page_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_get_single); +} + +/* for rev2.3 paging */ +int snd_ac97_page_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_put_single); +} + static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = { AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1) @@ -1435,9 +1470,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97) if ((err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97)) < 0) return err; /* FIXME: C-Media chips have no PCM volume!! */ - if (/*ac97->id == 0x434d4941 ||*/ - ac97->id == 0x434d4942 || - ac97->id == 0x434d4961) + if (ac97->id == AC97_ID_CM9739) snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f); else { if ((err = snd_ac97_cvol_new(card, "PCM Playback Volume", AC97_PCM, 31, ac97)) < 0) @@ -2080,18 +2113,28 @@ void snd_ac97_resume(ac97_t *ac97) snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0); snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]); - ac97->bus->write(ac97, AC97_MASTER, 0x8101); - for (i = 0; i < 10; i++) { - if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - } - /* FIXME: extra delay */ - ac97->bus->write(ac97, AC97_MASTER, 0x8000); - if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/4); + if (ac97_is_audio(ac97)) { + ac97->bus->write(ac97, AC97_MASTER, 0x8101); + for (i = HZ/10; i >= 0; i--) { + if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + /* FIXME: extra delay */ + ac97->bus->write(ac97, AC97_MASTER, 0x8000); + if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/4); + } + } else { + for (i = HZ/10; i >= 0; i--) { + unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID); + if (val != 0xffff && (val & 1) != 0) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } } __reset_ready: diff --git a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h index fa75c06fde9a..24a9f6cc3ea4 100644 --- a/sound/pci/ac97/ac97_id.h +++ b/sound/pci/ac97/ac97_id.h @@ -45,7 +45,14 @@ #define AC97_ID_CS4201 0x43525948 #define AC97_ID_CS4205 0x43525958 #define AC97_ID_CS_MASK 0xfffffff8 /* bit 0-2: rev */ +#define AC97_ID_ALC100 0x414c4300 #define AC97_ID_ALC650 0x414c4720 +#define AC97_ID_ALC650D 0x414c4721 +#define AC97_ID_ALC650E 0x414c4722 +#define AC97_ID_ALC650F 0x414c4723 +#define AC97_ID_ALC655 0x414c4760 +#define AC97_ID_ALC658 0x414c4780 +#define AC97_ID_ALC850 0x414c4790 #define AC97_ID_YMF753 0x594d4803 #define AC97_ID_VT1616 0x49434551 #define AC97_ID_CM9738 0x434d4941 diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h index 3abdeda27dfe..27d3236eed63 100644 --- a/sound/pci/ac97/ac97_local.h +++ b/sound/pci/ac97/ac97_local.h @@ -23,10 +23,15 @@ */ #define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24)) +#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) | ((page) << 25)) #define AC97_SINGLE(xname, reg, shift, mask, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \ .get = snd_ac97_get_single, .put = snd_ac97_put_single, \ .private_value = AC97_SINGLE_VALUE(reg, shift, mask, invert) } +#define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \ + .get = snd_ac97_page_get_single, .put = snd_ac97_page_put_single, \ + .private_value = AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) } /* ac97_codec.c */ extern const char *snd_ac97_stereo_enhancements[]; @@ -37,6 +42,8 @@ void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem); int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo); int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); +int snd_ac97_page_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); +int snd_ac97_page_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit); int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix); int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix); diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 6587832e916d..b1057f7ab75a 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -51,6 +51,21 @@ static int patch_build_controls(ac97_t * ac97, const snd_kcontrol_new_t *control return 0; } +/* set to the page, update bits and restore the page */ +static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page) +{ + unsigned short page_save; + int ret; + + down(&ac97->mutex); + page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); + ret = snd_ac97_update_bits(ac97, reg, mask, value); + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); + down(&ac97->mutex); /* unlock paging */ + return ret; +} + /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */ @@ -494,8 +509,6 @@ static int snd_ac97_stac9758_output_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_e val = 0; else val = 4 | (ucontrol->value.enumerated.item[0] - 1); - down(&ac97->mutex); - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); ret = snd_ac97_update_bits(ac97, AC97_SIGMATEL_OUTSEL, 7 << shift, val << shift); up(&ac97->mutex); @@ -531,14 +544,9 @@ static int snd_ac97_stac9758_input_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_el { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); int shift = kcontrol->private_value; - int ret; - down(&ac97->mutex); - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); - ret = snd_ac97_update_bits(ac97, AC97_SIGMATEL_INSEL, 7 << shift, - ucontrol->value.enumerated.item[0] << shift); - up(&ac97->mutex); - return ret; + return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift, + ucontrol->value.enumerated.item[0] << shift, 0); } static int snd_ac97_stac9758_phonesel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) @@ -565,14 +573,9 @@ static int snd_ac97_stac9758_phonesel_get(snd_kcontrol_t *kcontrol, snd_ctl_elem static int snd_ac97_stac9758_phonesel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - int ret; - down(&ac97->mutex); - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); - ret = snd_ac97_update_bits(ac97, AC97_SIGMATEL_IOMISC, 3, - ucontrol->value.enumerated.item[0]); - up(&ac97->mutex); - return ret; + return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3, + ucontrol->value.enumerated.item[0], 0); } #define STAC9758_OUTPUT_JACK(xname, shift) \ @@ -1245,7 +1248,7 @@ int patch_ad1985(ac97_t * ac97) } /* - * realtek ALC65x codecs + * realtek ALC65x/850 codecs */ static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) { @@ -1394,20 +1397,19 @@ static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - int change; /* misc control; vrefout disable */ snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, ucontrol->value.integer.value[0] ? (1 << 12) : 0); - change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10, - ucontrol->value.integer.value[0] ? (1 << 10) : 0); - return change; + return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10, + ucontrol->value.integer.value[0] ? (1 << 10) : 0, + 0); } static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = { - AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0), - AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0), + AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), + AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", @@ -1434,7 +1436,6 @@ static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_ texts_658[uinfo->value.enumerated.item] : texts_655[uinfo->value.enumerated.item]); return 0; - } static int alc655_iec958_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) @@ -1453,13 +1454,15 @@ static int alc655_iec958_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ static int alc655_iec958_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - return snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 3 << 12, - (unsigned short)ucontrol->value.enumerated.item[0]); + + return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12, + (unsigned short)ucontrol->value.enumerated.item[0], + 0); } static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc655[] = { - AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0), - AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0), + AC97_PAGE_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0, 0), + AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "IEC958 Playback Route", @@ -1494,6 +1497,9 @@ int patch_alc655(ac97_t * ac97) ac97->build_ops = &patch_alc655_ops; + /* assume only page 0 for writing cache */ + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); + /* adjust default values */ val = snd_ac97_read(ac97, 0x7a); /* misc control */ val |= (1 << 1); /* spdif input pin */ @@ -1512,6 +1518,120 @@ int patch_alc655(ac97_t * ac97) return 0; } + +#define AC97_ALC850_JACK_SELECT 0x76 +#define AC97_ALC850_MISC1 0x7a + +static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2; + return 0; +} + +static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + + /* SURR 1kOhm (bit4), Amp (bit5) */ + snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5), + ucontrol->value.integer.value[0] ? (1<<5) : (1<<4)); + /* LINE-IN = 0, SURROUND = 2 */ + return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12, + ucontrol->value.integer.value[0] ? (2<<12) : (0<<12)); +} + +static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2; + return 0; +} + +static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + + /* Vref disable (bit12), 1kOhm (bit13) */ + snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13), + ucontrol->value.integer.value[0] ? (1<<12) : (1<<13)); + /* MIC-IN = 1, CENTER-LFE = 2 */ + return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, + ucontrol->value.integer.value[0] ? (2<<4) : (1<<4)); +} + +static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = { + AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line-In As Surround", + .info = snd_ac97_info_single, + .get = ac97_alc850_surround_get, + .put = ac97_alc850_surround_put, + .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic As Center/LFE", + .info = snd_ac97_info_single, + .get = ac97_alc850_mic_get, + .put = ac97_alc850_mic_put, + .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ + }, + +}; + +static int patch_alc850_specific(ac97_t *ac97) +{ + int err; + + if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0) + return err; + if (ac97->ext_id & AC97_EI_SPDIF) { + if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0) + return err; + } + return 0; +} + +static struct snd_ac97_build_ops patch_alc850_ops = { + .build_specific = patch_alc850_specific +}; + +int patch_alc850(ac97_t *ac97) +{ + ac97->build_ops = &patch_alc850_ops; + + ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */ + + /* assume only page 0 for writing cache */ + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); + + /* adjust default values */ + /* set default: spdif-in enabled, + spdif-in monitor off, spdif-in PCM off + center on mic off, surround on line-in off + duplicate front off + */ + snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15); + /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off + * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on + */ + snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)| + (1<<7)|(0<<12)|(1<<13)|(0<<14)); + /* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable, + * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute + */ + snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)| + (1<<11)|(0<<12)|(1<<15)); + + /* full DAC volume */ + snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808); + snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808); + return 0; +} + + /* * C-Media CM97xx codecs */ diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h index 3e78799c593a..a619d7276057 100644 --- a/sound/pci/ac97/ac97_patch.h +++ b/sound/pci/ac97/ac97_patch.h @@ -49,6 +49,7 @@ int patch_ad1981b(ac97_t * ac97); int patch_ad1985(ac97_t * ac97); int patch_alc650(ac97_t * ac97); int patch_alc655(ac97_t * ac97); +int patch_alc850(ac97_t * ac97); int patch_cm9738(ac97_t * ac97); int patch_cm9739(ac97_t * ac97); int patch_vt1616(ac97_t * ac97); -- cgit v1.2.3 From 6b4d30ebd4d7ae0312134afa7caae0696516de74 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sun, 30 May 2004 17:57:33 +0200 Subject: ALSA CVS update - Jaroslav Kysela ALSA Core Fixed warnings for pci PM callbacks when not CONFIG_PCI --- include/sound/core.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/sound/core.h b/include/sound/core.h index 5d609309aaec..081e3dbce72c 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -211,12 +211,14 @@ int snd_card_set_dev_pm_callback(snd_card_t *card, int type, void *private_data); #define snd_card_set_isa_pm_callback(card,suspend,resume,data) \ snd_card_set_dev_pm_callback(card, PM_ISA_DEV, suspend, resume, data) +#ifdef CONFIG_PCI #ifndef SND_PCI_PM_CALLBACKS int snd_card_pci_suspend(struct pci_dev *dev, u32 state); int snd_card_pci_resume(struct pci_dev *dev); #define SND_PCI_PM_CALLBACKS \ .suspend = snd_card_pci_suspend, .resume = snd_card_pci_resume #endif +#endif #else #define snd_power_lock(card) do { (void)(card); } while (0) #define snd_power_unlock(card) do { (void)(card); } while (0) @@ -226,8 +228,10 @@ static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct fi #define snd_card_set_pm_callback(card,suspend,resume,data) -EINVAL #define snd_card_set_dev_pm_callback(card,suspend,resume,data) -EINVAL #define snd_card_set_isa_pm_callback(card,suspend,resume,data) -EINVAL +#ifdef CONFIG_PCI #define SND_PCI_PM_CALLBACKS #endif +#endif /* device.c */ -- cgit v1.2.3 From aba8394b5441744b2306566ce2854a6d1c3b1c8d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sun, 30 May 2004 18:01:08 +0200 Subject: ALSA 1.0.5 --- include/sound/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sound/version.h b/include/sound/version.h index 9f7d0e930064..90a79d6148c4 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by configure. */ -#define CONFIG_SND_VERSION "1.0.4" -#define CONFIG_SND_DATE " (Mon May 17 14:31:44 2004 UTC)" +#define CONFIG_SND_VERSION "1.0.5" +#define CONFIG_SND_DATE " (Sun May 30 10:49:40 2004 UTC)" -- cgit v1.2.3 From a6c7717d44417a1622f0233be531309a868d3520 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 31 May 2004 12:49:28 +0200 Subject: ALSA CVS update - Takashi Iwai AC97 Codec Core Fixed mutex deadlocks. --- sound/pci/ac97/ac97_codec.c | 2 +- sound/pci/ac97/ac97_patch.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 518a94287fa5..54a4fda87e37 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -642,7 +642,7 @@ int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontro snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); err = func(kcontrol, ucontrol); snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); - down(&ac97->mutex); /* unlock paging */ + up(&ac97->mutex); /* unlock paging */ } else err = func(kcontrol, ucontrol); return err; diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index b1057f7ab75a..0db027495571 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -62,7 +62,7 @@ static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned shor snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); ret = snd_ac97_update_bits(ac97, reg, mask, value); snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); - down(&ac97->mutex); /* unlock paging */ + up(&ac97->mutex); /* unlock paging */ return ret; } -- cgit v1.2.3