Update of /cvsroot/alsa/alsa-kernel/pci/ac97
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13026/pci/ac97
Modified Files:
ac97_codec.c ac97_local.h ac97_patch.c ac97_proc.c
Log Message:
- 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().
Index: ac97_codec.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_codec.c,v
retrieving revision 1.132
retrieving revision 1.133
diff -u -r1.132 -r1.133
--- ac97_codec.c 3 May 2004 17:32:57 -0000 1.132
+++ ac97_codec.c 24 May 2004 13:24:42 -0000 1.133
@@ -108,10 +108,10 @@
{ 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 @@
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 @@
cfg | 0x7000);
} else
spin_unlock(&ac97->reg_lock);
- up(&ac97->spec.ad18xx.mutex);
+ up(&ac97->mutex);
return change;
}
@@ -1120,6 +1120,7 @@
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 @@
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 @@
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 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 @@
}
/* 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 @@
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 @@
/* 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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
/* 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 @@
/*
*/
-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 @@
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;
}
Index: ac97_local.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_local.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ac97_local.h 16 Apr 2004 15:01:08 -0000 1.5
+++ ac97_local.h 24 May 2004 13:24:42 -0000 1.6
@@ -38,9 +38,10 @@
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);
Index: ac97_patch.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_patch.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- ac97_patch.c 11 May 2004 08:32:58 -0000 1.49
+++ ac97_patch.c 24 May 2004 13:24:42 -0000 1.50
@@ -204,7 +204,7 @@
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 @@
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 @@
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 @@
.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 @@
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 @@
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 @@
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 @@
{
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_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 @@
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 @@
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 @@
// 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 @@
{
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 @@
{
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 @@
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 @@
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 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 @@
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 @@
/* 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 */
Index: ac97_proc.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_proc.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- ac97_proc.c 16 Apr 2004 18:29:12 -0000 1.7
+++ ac97_proc.c 24 May 2004 13:24:42 -0000 1.8
@@ -292,9 +292,9 @@
{
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 @@
}
/* 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 @@
} else {
snd_ac97_proc_read_main(ac97, buffer, 0);
}
+ up(&ac97->mutex);
}
#ifdef CONFIG_SND_DEBUG
@@ -328,6 +328,7 @@
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 @@
if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff)
snd_ac97_write_cache(ac97, reg, val);
}
+ up(&ac97->mutex);
}
#endif
@@ -353,10 +355,10 @@
{
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 @@
}
/* 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)
-------------------------------------------------------
This SF.Net email is sponsored by: Oracle 10g
Get certified on the hottest thing ever to hit the market... Oracle 10g.
Take an Oracle 10g class now, and we'll give you the exam FREE.
http://ads.osdn.com/?ad_id=3149&alloc_id=8166&op=click
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog