Update of /cvsroot/alsa/alsa-kernel/pci/ac97
In directory sc8-pr-cvs1:/tmp/cvs-serv24118
Modified Files:
Makefile ac97_codec.c ac97_patch.c ac97_patch.h
Added Files:
ac97_local.h ac97_proc.c
Log Message:
Moved codec-specific code to ac97_patch.c
--- NEW FILE: ac97_local.h ---
/*
* Copyright (c) by Jaroslav Kysela <[EMAIL PROTECTED]>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
* by Intel Corporation (http://developer.intel.com).
*
*
* 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 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 = reg | (shift << 8) | (mask << 16) | (invert << 24) }
/* ac97_codec.c */
extern const char *snd_ac97_stereo_enhancements[];
extern const snd_kcontrol_new_t snd_ac97_controls_3d[];
extern const snd_kcontrol_new_t snd_ac97_controls_spdif[];
snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97);
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_try_bit(ac97_t * ac97, int reg, int bit);
/* ac97_proc.c */
void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97, const char *prefix);
--- NEW FILE: ac97_proc.c ---
/*
* Copyright (c) by Jaroslav Kysela <[EMAIL PROTECTED]>
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
* by Intel Corporation (http://developer.intel.com).
*
*
* 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 <sound/driver.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/ac97_codec.h>
#include <sound/asoundef.h>
#include "ac97_local.h"
#include "ac97_id.h"
/*
* proc interface
*/
static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int
subidx)
{
char name[64];
unsigned int id;
unsigned short val, tmp, ext, mext;
static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", "
SPDIF=6/9", " SPDIF=res" };
static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", "
Rate=48kHz", " Rate=32kHz" };
static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", "
Rate=res", " Rate=res" };
id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
snd_ac97_get_name(NULL, id, name, 0);
snd_iprintf(buffer, "%d-%d/%d: %s\n\n", ac97->addr, ac97->num, subidx, name);
if ((ac97->scaps & AC97_SCAP_AUDIO) == 0)
goto __modem;
// val = snd_ac97_read(ac97, AC97_RESET);
val = ac97->caps;
snd_iprintf(buffer, "Capabilities :%s%s%s%s%s%s\n",
val & AC97_BC_DEDICATED_MIC ? " -dedicated MIC PCM IN channel-" :
"",
val & AC97_BC_RESERVED1 ? " -reserved1-" : "",
val & AC97_BC_BASS_TREBLE ? " -bass & treble-" : "",
val & AC97_BC_SIM_STEREO ? " -simulated stereo-" : "",
val & AC97_BC_HEADPHONE ? " -headphone out-" : "",
val & AC97_BC_LOUDNESS ? " -loudness-" : "");
tmp = ac97->caps & AC97_BC_DAC_MASK;
snd_iprintf(buffer, "DAC resolution : %s%s%s%s\n",
tmp == AC97_BC_16BIT_DAC ? "16-bit" : "",
tmp == AC97_BC_18BIT_DAC ? "18-bit" : "",
tmp == AC97_BC_20BIT_DAC ? "20-bit" : "",
tmp == AC97_BC_DAC_MASK ? "???" : "");
tmp = ac97->caps & AC97_BC_ADC_MASK;
snd_iprintf(buffer, "ADC resolution : %s%s%s%s\n",
tmp == AC97_BC_16BIT_ADC ? "16-bit" : "",
tmp == AC97_BC_18BIT_ADC ? "18-bit" : "",
tmp == AC97_BC_20BIT_ADC ? "20-bit" : "",
tmp == AC97_BC_ADC_MASK ? "???" : "");
snd_iprintf(buffer, "3D enhancement : %s\n",
snd_ac97_stereo_enhancements[(val >> 10) & 0x1f]);
snd_iprintf(buffer, "\nCurrent setup\n");
val = snd_ac97_read(ac97, AC97_MIC);
snd_iprintf(buffer, "Mic gain : %s [%s]\n", val & 0x0040 ? "+20dB" :
"+0dB", ac97->regs[AC97_MIC] & 0x0040 ? "+20dB" : "+0dB");
val = snd_ac97_read(ac97, AC97_GENERAL_PURPOSE);
snd_iprintf(buffer, "POP path : %s 3D\n"
"Sim. stereo : %s\n"
"3D enhancement : %s\n"
"Loudness : %s\n"
"Mono output : %s\n"
"Mic select : %s\n"
"ADC/DAC loopback : %s\n",
val & 0x8000 ? "post" : "pre",
val & 0x4000 ? "on" : "off",
val & 0x2000 ? "on" : "off",
val & 0x1000 ? "on" : "off",
val & 0x0200 ? "Mic" : "MIX",
val & 0x0100 ? "Mic2" : "Mic1",
val & 0x0080 ? "on" : "off");
ext = snd_ac97_read(ac97, AC97_EXTENDED_ID);
if (ext == 0)
goto __modem;
snd_iprintf(buffer, "Extended ID : codec=%i rev=%i%s%s%s%s
DSA=%i%s%s%s%s\n",
(ext & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT,
(ext & AC97_EI_REV_MASK) >> AC97_EI_REV_SHIFT,
ext & AC97_EI_AMAP ? " AMAP" : "",
ext & AC97_EI_LDAC ? " LDAC" : "",
ext & AC97_EI_SDAC ? " SDAC" : "",
ext & AC97_EI_CDAC ? " CDAC" : "",
(ext & AC97_EI_DACS_SLOT_MASK) >> AC97_EI_DACS_SLOT_SHIFT,
ext & AC97_EI_VRM ? " VRM" : "",
ext & AC97_EI_SPDIF ? " SPDIF" : "",
ext & AC97_EI_DRA ? " DRA" : "",
ext & AC97_EI_VRA ? " VRA" : "");
val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
snd_iprintf(buffer, "Extended status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
val & AC97_EA_PRL ? " PRL" : "",
val & AC97_EA_PRK ? " PRK" : "",
val & AC97_EA_PRJ ? " PRJ" : "",
val & AC97_EA_PRI ? " PRI" : "",
val & AC97_EA_SPCV ? " SPCV" : "",
val & AC97_EA_MDAC ? " MADC" : "",
val & AC97_EA_LDAC ? " LDAC" : "",
val & AC97_EA_SDAC ? " SDAC" : "",
val & AC97_EA_CDAC ? " CDAC" : "",
ext & AC97_EI_SPDIF ? spdif_slots[(val &
AC97_EA_SPSA_SLOT_MASK) >> AC97_EA_SPSA_SLOT_SHIFT] : "",
val & AC97_EA_VRM ? " VRM" : "",
val & AC97_EA_SPDIF ? " SPDIF" : "",
val & AC97_EA_DRA ? " DRA" : "",
val & AC97_EA_VRA ? " VRA" : "");
if (ext & AC97_EI_VRA) { /* VRA */
val = snd_ac97_read(ac97, AC97_PCM_FRONT_DAC_RATE);
snd_iprintf(buffer, "PCM front DAC : %iHz\n", val);
if (ext & AC97_EI_SDAC) {
val = snd_ac97_read(ac97, AC97_PCM_SURR_DAC_RATE);
snd_iprintf(buffer, "PCM Surr DAC : %iHz\n", val);
}
if (ext & AC97_EI_LDAC) {
val = snd_ac97_read(ac97, AC97_PCM_LFE_DAC_RATE);
snd_iprintf(buffer, "PCM LFE DAC : %iHz\n", val);
}
val = snd_ac97_read(ac97, AC97_PCM_LR_ADC_RATE);
snd_iprintf(buffer, "PCM ADC : %iHz\n", val);
}
if (ext & AC97_EI_VRM) {
val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE);
snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val);
}
if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF)) {
if (ac97->flags & AC97_CS_SPDIF)
val = snd_ac97_read(ac97, AC97_CSR_SPDIF);
else
val = snd_ac97_read(ac97, AC97_SPDIF);
snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x
Generation=%i%s%s%s\n",
val & AC97_SC_PRO ? " PRO" : " Consumer",
val & AC97_SC_NAUDIO ? " Non-audio" : " PCM",
val & AC97_SC_COPY ? " Copyright" : "",
val & AC97_SC_PRE ? " Preemph50/15" : "",
(val & AC97_SC_CC_MASK) >> AC97_SC_CC_SHIFT,
(val & AC97_SC_L) >> 11,
(ac97->flags & AC97_CS_SPDIF) ?
spdif_rates_cs4205[(val & AC97_SC_SPSR_MASK) >>
AC97_SC_SPSR_SHIFT] :
spdif_rates[(val & AC97_SC_SPSR_MASK) >>
AC97_SC_SPSR_SHIFT],
(ac97->flags & AC97_CS_SPDIF) ?
(val & AC97_SC_DRS ? " Validity" : "") :
(val & AC97_SC_DRS ? " DRS" : ""),
(ac97->flags & AC97_CS_SPDIF) ?
(val & AC97_SC_V ? " Enabled" : "") :
(val & AC97_SC_V ? " Validity" : ""));
}
__modem:
mext = snd_ac97_read(ac97, AC97_EXTENDED_MID);
if (mext == 0)
return;
snd_iprintf(buffer, "Extended modem ID: codec=%i%s%s%s%s%s\n",
(mext & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT,
mext & AC97_MEI_CID2 ? " CID2" : "",
mext & AC97_MEI_CID1 ? " CID1" : "",
mext & AC97_MEI_HANDSET ? " HSET" : "",
mext & AC97_MEI_LINE2 ? " LIN2" : "",
mext & AC97_MEI_LINE1 ? " LIN1" : "");
val = snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS);
snd_iprintf(buffer, "Modem status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
val & AC97_MEA_GPIO ? " GPIO" : "",
val & AC97_MEA_MREF ? " MREF" : "",
val & AC97_MEA_ADC1 ? " ADC1" : "",
val & AC97_MEA_DAC1 ? " DAC1" : "",
val & AC97_MEA_ADC2 ? " ADC2" : "",
val & AC97_MEA_DAC2 ? " DAC2" : "",
val & AC97_MEA_HADC ? " HADC" : "",
val & AC97_MEA_HDAC ? " HDAC" : "",
val & AC97_MEA_PRA ? " PRA(GPIO)" : "",
val & AC97_MEA_PRB ? " PRB(res)" : "",
val & AC97_MEA_PRC ? " PRC(ADC1)" : "",
val & AC97_MEA_PRD ? " PRD(DAC1)" : "",
val & AC97_MEA_PRE ? " PRE(ADC2)" : "",
val & AC97_MEA_PRF ? " PRF(DAC2)" : "",
val & AC97_MEA_PRG ? " PRG(HADC)" : "",
val & AC97_MEA_PRH ? " PRH(HDAC)" : "");
if (mext & AC97_MEI_LINE1) {
val = snd_ac97_read(ac97, AC97_LINE1_RATE);
snd_iprintf(buffer, "Line1 rate : %iHz\n", val);
}
if (mext & AC97_MEI_LINE2) {
val = snd_ac97_read(ac97, AC97_LINE2_RATE);
snd_iprintf(buffer, "Line2 rate : %iHz\n", val);
}
if (mext & AC97_MEI_HANDSET) {
val = snd_ac97_read(ac97, AC97_HANDSET_RATE);
snd_iprintf(buffer, "Headset rate : %iHz\n", val);
}
}
static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
{
ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
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 */
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG,
ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
snd_ac97_proc_read_main(ac97, buffer, idx);
snd_iprintf(buffer, "\n\n");
}
/* select all codecs */
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000);
up(&ac97->spec.ad18xx.mutex);
snd_iprintf(buffer, "\nAD18XX configuration\n");
snd_iprintf(buffer, "Unchained : 0x%04x,0x%04x,0x%04x\n",
ac97->spec.ad18xx.unchained[0],
ac97->spec.ad18xx.unchained[1],
ac97->spec.ad18xx.unchained[2]);
snd_iprintf(buffer, "Chained : 0x%04x,0x%04x,0x%04x\n",
ac97->spec.ad18xx.chained[0],
ac97->spec.ad18xx.chained[1],
ac97->spec.ad18xx.chained[2]);
} else {
snd_ac97_proc_read_main(ac97, buffer, 0);
}
}
static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int
subidx)
{
int reg, val;
for (reg = 0; reg < 0x80; reg += 2) {
val = snd_ac97_read(ac97, reg);
snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val);
}
}
static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,
snd_info_buffer_t * buffer)
{
ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
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 */
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG,
ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
snd_ac97_proc_regs_read_main(ac97, buffer, idx);
}
/* select all codecs */
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000);
up(&ac97->spec.ad18xx.mutex);
} else {
snd_ac97_proc_regs_read_main(ac97, buffer, 0);
}
}
void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97, const char *prefix)
{
snd_info_entry_t *entry;
char name[32];
if (ac97->num)
sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num);
else
sprintf(name, "%s#%d", prefix, ac97->addr);
if (! snd_card_proc_new(card, name, &entry))
snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read);
if (ac97->num)
sprintf(name, "%s#%d-%dregs", prefix, ac97->addr, ac97->num);
else
sprintf(name, "%s#%dregs", prefix, ac97->addr);
if (! snd_card_proc_new(card, name, &entry))
snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);
}
Index: Makefile
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/Makefile,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- Makefile 17 Apr 2003 12:02:27 -0000 1.11
+++ Makefile 17 Jun 2003 18:43:31 -0000 1.12
@@ -3,7 +3,7 @@
# Copyright (c) 2001 by Jaroslav Kysela <[EMAIL PROTECTED]>
#
-snd-ac97-codec-objs := ac97_codec.o ac97_patch.o
+snd-ac97-codec-objs := ac97_codec.o ac97_proc.o ac97_patch.o
snd-ak4531-codec-objs := ak4531_codec.o
# Toplevel Module Dependency
Index: ac97_codec.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_codec.c,v
retrieving revision 1.97
retrieving revision 1.98
diff -u -r1.97 -r1.98
--- ac97_codec.c 17 Jun 2003 15:11:00 -0000 1.97
+++ ac97_codec.c 17 Jun 2003 18:43:32 -0000 1.98
@@ -32,6 +32,7 @@
#include <sound/ac97_codec.h>
#include <sound/asoundef.h>
#include <sound/initval.h>
+#include "ac97_local.h"
#include "ac97_id.h"
#include "ac97_patch.h"
@@ -51,8 +52,6 @@
*/
-static void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97, const char *prefix);
-
typedef struct {
unsigned int id;
unsigned int mask;
@@ -114,7 +113,7 @@
{ 0x414c4740, 0xfffffff0, "ALC202", NULL, NULL },
{ 0x414c4750, 0xfffffff0, "ALC250", NULL, NULL },
{ 0x414c4770, 0xfffffff0, "ALC203", NULL, NULL },
-{ 0x434d4941, 0xffffffff, "CMI9738", NULL, NULL },
+{ 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL },
{ 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL },
{ 0x43525900, 0xfffffff8, "CS4297", NULL, NULL },
{ 0x43525910, 0xfffffff8, "CS4297A", patch_cirrus_spdif, NULL },
@@ -134,8 +133,8 @@
{ 0x49434501, 0xffffffff, "ICE1230", NULL, NULL },
{ 0x49434511, 0xffffffff, "ICE1232", NULL, NULL }, // alias VIA
VT1611A?
{ 0x49434514, 0xffffffff, "ICE1232A", NULL, NULL },
-{ 0x49434551, 0xffffffff, "VT1616", NULL, NULL },
-{ 0x49434552, 0xffffffff, "VT1616i", NULL, NULL }, // VT1616
compatible (chipset integrated)
+{ 0x49434551, 0xffffffff, "VT1616", patch_vt1616, NULL },
+{ 0x49434552, 0xffffffff, "VT1616i", patch_vt1616, NULL }, // VT1616
compatible (chipset integrated)
{ 0x49544520, 0xffffffff, "IT2226E", NULL, NULL },
{ 0x4e534300, 0xffffffff, "LM4540/43/45/46/48", NULL, NULL }, //
only guess --jk
{ 0x4e534331, 0xffffffff, "LM4549", NULL, NULL },
@@ -158,7 +157,7 @@
{ 0x594d4800, 0xffffffff, "YMF743", NULL, NULL },
{ 0x594d4802, 0xffffffff, "YMF752", NULL, NULL },
{ 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL },
-{ 0x83847600, 0xffffffff, "STAC9700/83/84", NULL, NULL },
+{ 0x83847600, 0xffffffff, "STAC9700/83/84", patch_sigmatel_stac9700, NULL },
{ 0x83847604, 0xffffffff, "STAC9701/3/4/5", NULL, NULL },
{ 0x83847605, 0xffffffff, "STAC9704", NULL, NULL },
{ 0x83847608, 0xffffffff, "STAC9708/11", patch_sigmatel_stac9708, NULL },
@@ -171,7 +170,7 @@
{ 0, 0, NULL, NULL, NULL }
};
-static const char *snd_ac97_stereo_enhancements[] =
+const char *snd_ac97_stereo_enhancements[] =
{
/* 0 */ "No 3D Stereo Enhancement",
/* 1 */ "Analog Devices Phat Stereo",
@@ -310,21 +309,6 @@
set_bit(reg, ac97->reg_accessed);
}
-static void snd_ac97_write_cache_test(ac97_t *ac97, unsigned short reg, unsigned
short value)
-{
-#if 0
- if (!snd_ac97_valid_reg(ac97, reg))
- return;
- //spin_lock(&ac97->reg_lock);
- ac97->write(ac97, reg, value);
- ac97->regs[reg] = ac97->read(ac97, reg);
- if (value != ac97->regs[reg])
- snd_printk("AC97 reg=%02x val=%04x real=%04x\n", reg, value,
ac97->regs[reg]);
- //spin_unlock(&ac97->reg_lock);
-#endif
- snd_ac97_write_cache(ac97, reg, value);
-}
-
/**
* snd_ac97_update - update the value on the given register
* @ac97: the ac97 instance
@@ -518,12 +502,7 @@
return snd_ac97_update_bits(ac97, reg, 1 << shift, val << shift);
}
-#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 = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-
-static int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -534,7 +513,7 @@
return 0;
}
-static int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
ucontrol)
+int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
@@ -548,7 +527,7 @@
return 0;
}
-static int snd_ac97_put_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)
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
@@ -718,7 +697,7 @@
AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
};
-static const snd_kcontrol_new_t snd_ac97_controls_3d[2] = {
+const snd_kcontrol_new_t snd_ac97_controls_3d[2] = {
AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0),
AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0)
};
@@ -743,27 +722,9 @@
AC97_DOUBLE("Sigmatel Surround Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1)
};
-static const snd_kcontrol_new_t snd_ac97_sigmatel_4speaker =
-AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch", AC97_SIGMATEL_DAC2INVERT, 2,
1, 0);
-
-static const snd_kcontrol_new_t snd_ac97_sigmatel_phaseinvert =
-AC97_SINGLE("Sigmatel Surround Phase Inversion Playback Switch",
AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
-
-static const snd_kcontrol_new_t snd_ac97_sigmatel_controls[] = {
-AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
-AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
-};
-
static const snd_kcontrol_new_t snd_ac97_control_eapd =
AC97_SINGLE("External Amplifier Power Down", AC97_POWERDOWN, 15, 1, 0);
-static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {
-AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
-AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
-AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
-AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
-};
-
static int snd_ac97_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -898,7 +859,7 @@
return 0;
}
-static const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {
+const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -933,15 +894,6 @@
},
};
-static const snd_kcontrol_new_t snd_ac97_cirrus_controls_spdif[2] = {
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE,
0, 3, 0)
-};
-
-static const snd_kcontrol_new_t snd_ac97_conexant_controls_spdif[2] = {
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1,
0),
-};
-
#define AD18XX_PCM_BITS(xname, codec, shift, mask) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info =
snd_ac97_ad18xx_pcm_info_bits, \
.get = snd_ac97_ad18xx_pcm_get_bits, .put = snd_ac97_ad18xx_pcm_put_bits, \
@@ -1037,325 +989,6 @@
AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 31)
};
-static int snd_ac97_ad1980_spdif_source_info(snd_kcontrol_t *kcontrol,
snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[2] = { "AC-Link", "A/D Converter" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item > 1)
- uinfo->value.enumerated.item = 1;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_ac97_ad1980_spdif_source_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- val = ac97->regs[AC97_AD_SERIAL_CFG];
- ucontrol->value.enumerated.item[0] = (val >> 2) & 1;
- return 0;
-}
-
-static int snd_ac97_ad1980_spdif_source_put(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- if (ucontrol->value.enumerated.item[0] > 1)
- return -EINVAL;
- val = ucontrol->value.enumerated.item[0] << 2;
- return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);
-}
-
-static const snd_kcontrol_new_t snd_ac97_ad1980_spdif_source = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
- .info = snd_ac97_ad1980_spdif_source_info,
- .get = snd_ac97_ad1980_spdif_source_get,
- .put = snd_ac97_ad1980_spdif_source_put,
-};
-
-/*
- * ALC650
- */
-static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
- AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
- AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
- AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
- AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
- /* 4: Analog Input To Surround */
- /* 5: Analog Input To Center/LFE */
- /* 6: Independent Master Volume Right */
- /* 7: Independent Master Volume Left */
- /* 8: reserved */
- AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
- AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
-#if 0 /* always set in patch_alc650 */
- AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
- AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
- AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
- AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
- AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
- AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
-#endif
-};
-
-static const snd_kcontrol_new_t snd_ac97_control_alc650_mic =
-AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0);
-
-
-static int snd_ac97_alc650_mic_gpio_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_ALC650_MULTICH] >> 10) & 1;
- return 0;
-}
-
-static int snd_ac97_alc650_mic_gpio_put(snd_kcontrol_t *kcontrol,
snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- int change;
- change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
- ucontrol->value.integer.value[0] ? (1 << 10) :
0);
- if (change) {
- /* GPIO0 write for mic */
- snd_ac97_update_bits(ac97, 0x76, 0x01,
- ucontrol->value.integer.value[0] ? 0 : 0x01);
- /* GPIO0 high for mic */
- snd_ac97_update_bits(ac97, 0x78, 0x100,
- ucontrol->value.integer.value[0] ? 0 : 0x100);
- }
- return change;
-}
-
-static const snd_kcontrol_new_t snd_ac97_control_alc650_mic_gpio = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Mic As Center/LFE",
- .info = snd_ac97_info_single,
- .get = snd_ac97_alc650_mic_gpio_get,
- .put = snd_ac97_alc650_mic_gpio_put,
- .private_value = (1 << 16), /* for info */
-};
-
-static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
- AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
- AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
- AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0),
-};
-
-/* The following snd_ac97_ymf753_... items added by David Shust ([EMAIL PROTECTED]) */
-
-/* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
-static int snd_ac97_ymf753_info_speaker(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
* uinfo)
-{
- static char *texts[3] = {
- "Standard", "Small", "Smaller"
- };
-
- 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 snd_ac97_ymf753_get_speaker(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- val = ac97->regs[AC97_YMF753_3D_MODE_SEL];
- val = (val >> 10) & 3;
- if (val > 0) /* 0 = invalid */
- val--;
- ucontrol->value.enumerated.item[0] = val;
- return 0;
-}
-
-static int snd_ac97_ymf753_put_speaker(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- if (ucontrol->value.enumerated.item[0] > 2)
- return -EINVAL;
- val = (ucontrol->value.enumerated.item[0] + 1) << 10;
- return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val);
-}
-
-static const snd_kcontrol_new_t snd_ac97_ymf753_controls_speaker =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "3D Control - Speaker",
- .info = snd_ac97_ymf753_info_speaker,
- .get = snd_ac97_ymf753_get_speaker,
- .put = snd_ac97_ymf753_put_speaker,
-};
-
-/* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF
output. */
-static int snd_ac97_ymf753_spdif_source_info(snd_kcontrol_t *kcontrol,
snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[2] = { "AC-Link", "A/D Converter" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item > 1)
- uinfo->value.enumerated.item = 1;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_ac97_ymf753_spdif_source_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- val = ac97->regs[AC97_YMF753_DIT_CTRL2];
- ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
- return 0;
-}
-
-static int snd_ac97_ymf753_spdif_source_put(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- if (ucontrol->value.enumerated.item[0] > 1)
- return -EINVAL;
- val = ucontrol->value.enumerated.item[0] << 1;
- return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0002, val);
-}
-
-/* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
- The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48.
- By default, no output pin is selected, and the S/PDIF signal is not output.
- There is also a bit to mute S/PDIF output in a vendor-specific register. */
-static int snd_ac97_ymf753_spdif_output_pin_info(snd_kcontrol_t *kcontrol,
snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" };
-
- 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 snd_ac97_ymf753_spdif_output_pin_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- val = ac97->regs[AC97_YMF753_DIT_CTRL2];
- ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 :
0;
- return 0;
-}
-
-static int snd_ac97_ymf753_spdif_output_pin_put(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- if (ucontrol->value.enumerated.item[0] > 2)
- return -EINVAL;
- val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
- (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
- return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0028, val);
- /* The following can be used to direct S/PDIF output to pin 47 (EAPD).
- snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
-}
-
-static const snd_kcontrol_new_t snd_ac97_ymf753_controls_spdif[3] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
- .info = snd_ac97_ymf753_spdif_source_info,
- .get = snd_ac97_ymf753_spdif_source_get,
- .put = snd_ac97_ymf753_spdif_source_put,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
- .info = snd_ac97_ymf753_spdif_output_pin_info,
- .get = snd_ac97_ymf753_spdif_output_pin_get,
- .put = snd_ac97_ymf753_spdif_output_pin_put,
- },
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2,
2, 1, 1)
-};
-
-
-/*
- * C-Media codecs
- */
-
-static int snd_ac97_cmedia_spdif_playback_source_info(snd_kcontrol_t *kcontrol,
snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[] = { "Analog", "Digital" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item > 1)
- uinfo->value.enumerated.item = 1;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_ac97_cmedia_spdif_playback_source_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
- ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
- return 0;
-}
-
-static int snd_ac97_cmedia_spdif_playback_source_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_CM9739_SPDIF_CTRL,
- 0x01 << 1,
- (ucontrol->value.enumerated.item[0] & 0x01) << 1);
-}
-
-static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
- /* BIT 0: SPDI_EN - always true */
- { /* BIT 1: SPDIFS */
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
- .info = snd_ac97_cmedia_spdif_playback_source_info,
- .get = snd_ac97_cmedia_spdif_playback_source_get,
- .put = snd_ac97_cmedia_spdif_playback_source_put,
- },
- /* BIT 2: IG_SPIV */
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch",
AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
- /* BIT 3: SPI2F */
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor",
AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
- /* BIT 4: SPI2SDI */
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL,
4, 1, 0),
- /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
-};
-
-static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
- AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),
-};
-
-static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
- AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
- AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
-};
-
/*
*
*/
@@ -1420,7 +1053,7 @@
if (!(val & mask)) {
/* nothing seems to be here - mute flag is not set */
/* try another test */
- snd_ac97_write_cache_test(ac97, reg, val | mask);
+ snd_ac97_write_cache(ac97, reg, val | mask);
val = snd_ac97_read(ac97, reg);
if (!(val & mask))
return 0; /* nothing here */
@@ -1428,7 +1061,7 @@
return 1; /* success, useable */
}
-static int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit)
+int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit)
{
unsigned short mask, val, orig, res;
@@ -1497,7 +1130,7 @@
return x;
}
-static snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t *
ac97)
+snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97)
{
snd_kcontrol_new_t template;
memcpy(&template, _template, sizeof(template));
@@ -1506,8 +1139,9 @@
return snd_ctl_new1(&template, ac97);
}
-static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
+static int snd_ac97_mixer_build(ac97_t * ac97)
{
+ snd_card_t *card = ac97->card;
snd_kcontrol_t *kctl;
const snd_kcontrol_new_t *knew;
int err;
@@ -1757,39 +1391,9 @@
snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0x0000);
/* build 3D controls */
- switch (ac97->id) {
- case AC97_ID_STAC9708:
- if ((err = snd_ctl_add(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);
- if ((err = snd_ctl_add(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);
- snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
- break;
- case AC97_ID_STAC9700:
- case AC97_ID_STAC9721:
- case AC97_ID_STAC9744:
- case AC97_ID_STAC9756:
- if ((err = snd_ctl_add(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);
- snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
- break;
- case AC97_ID_YMF753:
- if ((err = snd_ctl_add(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);
- snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
- return err;
- snd_ac97_write_cache(ac97, AC97_YMF753_3D_MODE_SEL, 0x0c00);
- break;
- default:
+ if (ac97->build_ops && ac97->build_ops->build_3d) {
+ ac97->build_ops->build_3d(ac97);
+ } else {
if (snd_ac97_try_volume_mix(ac97, AC97_3D_CONTROL)) {
unsigned short val;
val = 0x0707;
@@ -1807,121 +1411,31 @@
snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
}
}
-
+
/* build S/PDIF controls */
if (ac97->ext_id & AC97_EI_SPDIF) {
- if (ac97->flags & AC97_CS_SPDIF) {
- for (idx = 0; idx < 3; idx++)
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
- return err;
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_cirrus_controls_spdif[0], ac97))) < 0)
+ if (ac97->build_ops && ac97->build_ops->build_spdif) {
+ if ((err = ac97->build_ops->build_spdif(ac97)) < 0)
return err;
- switch (ac97->id & AC97_ID_CS_MASK) {
- case AC97_ID_CS4205:
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_cirrus_controls_spdif[1], ac97))) < 0)
- return err;
- break;
- }
- /* set default PCM S/PDIF params */
- /* consumer,PCM audio,no copyright,no preemphasis,PCM
coder,original,48000Hz */
- snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
- } else if (ac97->flags & AC97_CX_SPDIF) {
- for (idx = 0; idx < 3; idx++)
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
- return err;
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_conexant_controls_spdif[0], ac97))) < 0)
- return err;
- /* set default PCM S/PDIF params */
- /* consumer,PCM audio,no copyright,no preemphasis,PCM
coder,original,48000Hz */
- snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
- snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC)
& ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
-
} else {
for (idx = 0; idx < 5; idx++)
if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
return err;
- switch (ac97->id) {
- case AC97_ID_YMF753:
- for (idx = 0; idx < 3; idx++)
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_ymf753_controls_spdif[idx], ac97))) < 0)
- return err;
- break;
- case AC97_ID_AD1980:
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_ad1980_spdif_source, ac97))) < 0)
+ if (ac97->build_ops && ac97->build_ops->build_post_spdif) {
+ if ((err = ac97->build_ops->build_post_spdif(ac97)) <
0)
return err;
- break;
- case AC97_ID_CM9739:
- for (idx = 0; idx <
ARRAY_SIZE(snd_ac97_cm9739_controls_spdif); idx++)
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_cm9739_controls_spdif[idx], ac97))) < 0)
- return err;
- break;
}
/* 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->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
}
/* build chip specific controls */
- switch (ac97->id) {
- case AC97_ID_STAC9700:
- case AC97_ID_STAC9708:
- case AC97_ID_STAC9721:
- case AC97_ID_STAC9744:
- case AC97_ID_STAC9756:
- snd_ac97_write_cache_test(ac97, AC97_SIGMATEL_ANALOG,
snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);
- if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1))
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_sigmatel_controls[0], ac97))) < 0)
- return err;
- if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_sigmatel_controls[1], ac97))) < 0)
- return err;
- if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2))
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_sigmatel_4speaker, ac97))) < 0)
- return err;
- if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3))
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_sigmatel_phaseinvert, ac97))) < 0)
- return err;
- break;
- case AC97_ID_ALC650:
- /* detect ALC650 rev.E of later */
- for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_alc650); idx++)
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_controls_alc650[idx], ac97))) < 0)
- return err;
- if ((err = snd_ctl_add(card, snd_ac97_cnew(ac97->spec.dev_flags ?
-
&snd_ac97_control_alc650_mic :
-
&snd_ac97_control_alc650_mic_gpio, ac97))) < 0)
- return err;
- if (ac97->ext_id & AC97_EI_SPDIF) {
- for (idx = 0; idx <
ARRAY_SIZE(snd_ac97_spdif_controls_alc650); idx++)
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_spdif_controls_alc650[idx], ac97))) < 0)
- return err;
- }
- break;
- case AC97_ID_VT1616:
- if (snd_ac97_try_bit(ac97, 0x5a, 9))
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_controls_vt1616[0], ac97))) < 0)
- return err;
- for (idx = 1; idx < ARRAY_SIZE(snd_ac97_controls_vt1616); idx++)
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_controls_vt1616[idx], ac97))) < 0)
- return err;
- break;
- case AC97_ID_CM9739:
- for (idx = 1; idx < ARRAY_SIZE(snd_ac97_cm9739_controls); idx++)
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_cm9739_controls[idx], ac97))) < 0)
- return err;
- break;
- case AC97_ID_CM9738:
- for (idx = 1; idx < ARRAY_SIZE(snd_ac97_cm9738_controls); idx++)
- if ((err = snd_ctl_add(card,
snd_ac97_cnew(&snd_ac97_cm9738_controls[idx], ac97))) < 0)
- return err;
- break;
- default:
- /* nothing */
- break;
- }
+ if (ac97->build_ops && ac97->build_ops->build_specific)
+ if ((err = ac97->build_ops->build_specific(ac97)) < 0)
+ return err;
if (snd_ac97_try_bit(ac97, AC97_POWERDOWN, 15)) {
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_eapd,
ac97))) < 0)
@@ -1943,7 +1457,7 @@
unsigned int tmp;
tmp = ((unsigned int)rate * ac97->clock) / 48000;
- snd_ac97_write_cache_test(ac97, reg, tmp & 0xffff);
+ snd_ac97_write_cache(ac97, reg, tmp & 0xffff);
val = snd_ac97_read(ac97, reg);
return val == (tmp & 0xffff);
}
@@ -1973,7 +1487,7 @@
*r_result = result;
}
-static void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
+void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
{
const ac97_codec_id_t *pid;
@@ -2150,12 +1664,12 @@
/* FIXME: add powerdown control */
if (ac97_is_audio(ac97)) {
/* nothing should be in powerdown mode */
- snd_ac97_write_cache_test(ac97, AC97_POWERDOWN, 0);
- snd_ac97_write_cache_test(ac97, AC97_RESET, 0); /* reset to
defaults */
+ snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
+ snd_ac97_write_cache(ac97, AC97_RESET, 0); /* reset to
defaults */
udelay(100);
/* nothing should be in powerdown mode */
- snd_ac97_write_cache_test(ac97, AC97_POWERDOWN, 0);
- snd_ac97_write_cache_test(ac97, AC97_GENERAL_PURPOSE, 0);
+ snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
+ snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0);
end_time = jiffies + (HZ / 10);
do {
if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
@@ -2224,10 +1738,10 @@
snd_ac97_free(ac97);
return err;
}
- }
- if (ac97_is_audio(ac97) && snd_ac97_mixer_build(card, ac97) < 0) {
- snd_ac97_free(ac97);
- return -ENOMEM;
+ if (snd_ac97_mixer_build(ac97) < 0) {
+ snd_ac97_free(ac97);
+ return -ENOMEM;
+ }
}
snd_ac97_proc_init(card, ac97, "ac97");
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ac97, &ops)) < 0) {
@@ -2369,21 +1883,21 @@
/* note: it's important to set the rate at first */
tmp = AC97_MEA_GPIO;
if (ac97->ext_mid & AC97_MEI_LINE1) {
- snd_ac97_write_cache_test(ac97, AC97_LINE1_RATE, 12000);
+ snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 12000);
tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1;
}
if (ac97->ext_mid & AC97_MEI_LINE2) {
- snd_ac97_write_cache_test(ac97, AC97_LINE2_RATE, 12000);
+ snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 12000);
tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2;
}
if (ac97->ext_mid & AC97_MEI_HANDSET) {
- snd_ac97_write_cache_test(ac97, AC97_HANDSET_RATE, 12000);
+ snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 12000);
tmp |= AC97_MEA_HADC | AC97_MEA_HDAC;
}
- snd_ac97_write_cache_test(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp
<< 8));
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp <<
8));
udelay(100);
/* nothing should be in powerdown mode */
- snd_ac97_write_cache_test(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp
<< 8));
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp <<
8));
end_time = jiffies + (HZ / 10);
do {
if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
@@ -2431,270 +1945,6 @@
}
*rac97 = ac97;
return 0;
-}
-
-/*
- * proc interface
- */
-
-static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int
subidx)
-{
- char name[64];
- unsigned int id;
- unsigned short val, tmp, ext, mext;
- static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", "
SPDIF=6/9", " SPDIF=res" };
- static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", "
Rate=48kHz", " Rate=32kHz" };
- static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", "
Rate=res", " Rate=res" };
-
- id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
- id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
- snd_ac97_get_name(NULL, id, name, 0);
- snd_iprintf(buffer, "%d-%d/%d: %s\n\n", ac97->addr, ac97->num, subidx, name);
- if ((ac97->scaps & AC97_SCAP_AUDIO) == 0)
- goto __modem;
-
- // val = snd_ac97_read(ac97, AC97_RESET);
- val = ac97->caps;
- snd_iprintf(buffer, "Capabilities :%s%s%s%s%s%s\n",
- val & AC97_BC_DEDICATED_MIC ? " -dedicated MIC PCM IN channel-" :
"",
- val & AC97_BC_RESERVED1 ? " -reserved1-" : "",
- val & AC97_BC_BASS_TREBLE ? " -bass & treble-" : "",
- val & AC97_BC_SIM_STEREO ? " -simulated stereo-" : "",
- val & AC97_BC_HEADPHONE ? " -headphone out-" : "",
- val & AC97_BC_LOUDNESS ? " -loudness-" : "");
- tmp = ac97->caps & AC97_BC_DAC_MASK;
- snd_iprintf(buffer, "DAC resolution : %s%s%s%s\n",
- tmp == AC97_BC_16BIT_DAC ? "16-bit" : "",
- tmp == AC97_BC_18BIT_DAC ? "18-bit" : "",
- tmp == AC97_BC_20BIT_DAC ? "20-bit" : "",
- tmp == AC97_BC_DAC_MASK ? "???" : "");
- tmp = ac97->caps & AC97_BC_ADC_MASK;
- snd_iprintf(buffer, "ADC resolution : %s%s%s%s\n",
- tmp == AC97_BC_16BIT_ADC ? "16-bit" : "",
- tmp == AC97_BC_18BIT_ADC ? "18-bit" : "",
- tmp == AC97_BC_20BIT_ADC ? "20-bit" : "",
- tmp == AC97_BC_ADC_MASK ? "???" : "");
- snd_iprintf(buffer, "3D enhancement : %s\n",
- snd_ac97_stereo_enhancements[(val >> 10) & 0x1f]);
- snd_iprintf(buffer, "\nCurrent setup\n");
- val = snd_ac97_read(ac97, AC97_MIC);
- snd_iprintf(buffer, "Mic gain : %s [%s]\n", val & 0x0040 ? "+20dB" :
"+0dB", ac97->regs[AC97_MIC] & 0x0040 ? "+20dB" : "+0dB");
- val = snd_ac97_read(ac97, AC97_GENERAL_PURPOSE);
- snd_iprintf(buffer, "POP path : %s 3D\n"
- "Sim. stereo : %s\n"
- "3D enhancement : %s\n"
- "Loudness : %s\n"
- "Mono output : %s\n"
- "Mic select : %s\n"
- "ADC/DAC loopback : %s\n",
- val & 0x8000 ? "post" : "pre",
- val & 0x4000 ? "on" : "off",
- val & 0x2000 ? "on" : "off",
- val & 0x1000 ? "on" : "off",
- val & 0x0200 ? "Mic" : "MIX",
- val & 0x0100 ? "Mic2" : "Mic1",
- val & 0x0080 ? "on" : "off");
-
- ext = snd_ac97_read(ac97, AC97_EXTENDED_ID);
- if (ext == 0)
- goto __modem;
-
- snd_iprintf(buffer, "Extended ID : codec=%i rev=%i%s%s%s%s
DSA=%i%s%s%s%s\n",
- (ext & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT,
- (ext & AC97_EI_REV_MASK) >> AC97_EI_REV_SHIFT,
- ext & AC97_EI_AMAP ? " AMAP" : "",
- ext & AC97_EI_LDAC ? " LDAC" : "",
- ext & AC97_EI_SDAC ? " SDAC" : "",
- ext & AC97_EI_CDAC ? " CDAC" : "",
- (ext & AC97_EI_DACS_SLOT_MASK) >> AC97_EI_DACS_SLOT_SHIFT,
- ext & AC97_EI_VRM ? " VRM" : "",
- ext & AC97_EI_SPDIF ? " SPDIF" : "",
- ext & AC97_EI_DRA ? " DRA" : "",
- ext & AC97_EI_VRA ? " VRA" : "");
- val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
- snd_iprintf(buffer, "Extended status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
- val & AC97_EA_PRL ? " PRL" : "",
- val & AC97_EA_PRK ? " PRK" : "",
- val & AC97_EA_PRJ ? " PRJ" : "",
- val & AC97_EA_PRI ? " PRI" : "",
- val & AC97_EA_SPCV ? " SPCV" : "",
- val & AC97_EA_MDAC ? " MADC" : "",
- val & AC97_EA_LDAC ? " LDAC" : "",
- val & AC97_EA_SDAC ? " SDAC" : "",
- val & AC97_EA_CDAC ? " CDAC" : "",
- ext & AC97_EI_SPDIF ? spdif_slots[(val &
AC97_EA_SPSA_SLOT_MASK) >> AC97_EA_SPSA_SLOT_SHIFT] : "",
- val & AC97_EA_VRM ? " VRM" : "",
- val & AC97_EA_SPDIF ? " SPDIF" : "",
- val & AC97_EA_DRA ? " DRA" : "",
- val & AC97_EA_VRA ? " VRA" : "");
- if (ext & AC97_EI_VRA) { /* VRA */
- val = snd_ac97_read(ac97, AC97_PCM_FRONT_DAC_RATE);
- snd_iprintf(buffer, "PCM front DAC : %iHz\n", val);
- if (ext & AC97_EI_SDAC) {
- val = snd_ac97_read(ac97, AC97_PCM_SURR_DAC_RATE);
- snd_iprintf(buffer, "PCM Surr DAC : %iHz\n", val);
- }
- if (ext & AC97_EI_LDAC) {
- val = snd_ac97_read(ac97, AC97_PCM_LFE_DAC_RATE);
- snd_iprintf(buffer, "PCM LFE DAC : %iHz\n", val);
- }
- val = snd_ac97_read(ac97, AC97_PCM_LR_ADC_RATE);
- snd_iprintf(buffer, "PCM ADC : %iHz\n", val);
- }
- if (ext & AC97_EI_VRM) {
- val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE);
- snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val);
- }
- if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF)) {
- if (ac97->flags & AC97_CS_SPDIF)
- val = snd_ac97_read(ac97, AC97_CSR_SPDIF);
- else
- val = snd_ac97_read(ac97, AC97_SPDIF);
-
- snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x
Generation=%i%s%s%s\n",
- val & AC97_SC_PRO ? " PRO" : " Consumer",
- val & AC97_SC_NAUDIO ? " Non-audio" : " PCM",
- val & AC97_SC_COPY ? " Copyright" : "",
- val & AC97_SC_PRE ? " Preemph50/15" : "",
- (val & AC97_SC_CC_MASK) >> AC97_SC_CC_SHIFT,
- (val & AC97_SC_L) >> 11,
- (ac97->flags & AC97_CS_SPDIF) ?
- spdif_rates_cs4205[(val & AC97_SC_SPSR_MASK) >>
AC97_SC_SPSR_SHIFT] :
- spdif_rates[(val & AC97_SC_SPSR_MASK) >>
AC97_SC_SPSR_SHIFT],
- (ac97->flags & AC97_CS_SPDIF) ?
- (val & AC97_SC_DRS ? " Validity" : "") :
- (val & AC97_SC_DRS ? " DRS" : ""),
- (ac97->flags & AC97_CS_SPDIF) ?
- (val & AC97_SC_V ? " Enabled" : "") :
- (val & AC97_SC_V ? " Validity" : ""));
- }
-
- __modem:
- mext = snd_ac97_read(ac97, AC97_EXTENDED_MID);
- if (mext == 0)
- return;
-
- snd_iprintf(buffer, "Extended modem ID: codec=%i%s%s%s%s%s\n",
- (mext & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT,
- mext & AC97_MEI_CID2 ? " CID2" : "",
- mext & AC97_MEI_CID1 ? " CID1" : "",
- mext & AC97_MEI_HANDSET ? " HSET" : "",
- mext & AC97_MEI_LINE2 ? " LIN2" : "",
- mext & AC97_MEI_LINE1 ? " LIN1" : "");
- val = snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS);
- snd_iprintf(buffer, "Modem status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
- val & AC97_MEA_GPIO ? " GPIO" : "",
- val & AC97_MEA_MREF ? " MREF" : "",
- val & AC97_MEA_ADC1 ? " ADC1" : "",
- val & AC97_MEA_DAC1 ? " DAC1" : "",
- val & AC97_MEA_ADC2 ? " ADC2" : "",
- val & AC97_MEA_DAC2 ? " DAC2" : "",
- val & AC97_MEA_HADC ? " HADC" : "",
- val & AC97_MEA_HDAC ? " HDAC" : "",
- val & AC97_MEA_PRA ? " PRA(GPIO)" : "",
- val & AC97_MEA_PRB ? " PRB(res)" : "",
- val & AC97_MEA_PRC ? " PRC(ADC1)" : "",
- val & AC97_MEA_PRD ? " PRD(DAC1)" : "",
- val & AC97_MEA_PRE ? " PRE(ADC2)" : "",
- val & AC97_MEA_PRF ? " PRF(DAC2)" : "",
- val & AC97_MEA_PRG ? " PRG(HADC)" : "",
- val & AC97_MEA_PRH ? " PRH(HDAC)" : "");
- if (mext & AC97_MEI_LINE1) {
- val = snd_ac97_read(ac97, AC97_LINE1_RATE);
- snd_iprintf(buffer, "Line1 rate : %iHz\n", val);
- }
- if (mext & AC97_MEI_LINE2) {
- val = snd_ac97_read(ac97, AC97_LINE2_RATE);
- snd_iprintf(buffer, "Line2 rate : %iHz\n", val);
- }
- if (mext & AC97_MEI_HANDSET) {
- val = snd_ac97_read(ac97, AC97_HANDSET_RATE);
- snd_iprintf(buffer, "Headset rate : %iHz\n", val);
- }
-}
-
-static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
-{
- ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
-
- 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 */
- snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG,
ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
- snd_ac97_proc_read_main(ac97, buffer, idx);
- snd_iprintf(buffer, "\n\n");
- }
- /* select all codecs */
- snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000);
- up(&ac97->spec.ad18xx.mutex);
-
- snd_iprintf(buffer, "\nAD18XX configuration\n");
- snd_iprintf(buffer, "Unchained : 0x%04x,0x%04x,0x%04x\n",
- ac97->spec.ad18xx.unchained[0],
- ac97->spec.ad18xx.unchained[1],
- ac97->spec.ad18xx.unchained[2]);
- snd_iprintf(buffer, "Chained : 0x%04x,0x%04x,0x%04x\n",
- ac97->spec.ad18xx.chained[0],
- ac97->spec.ad18xx.chained[1],
- ac97->spec.ad18xx.chained[2]);
- } else {
- snd_ac97_proc_read_main(ac97, buffer, 0);
- }
-}
-
-static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffer,
int subidx)
-{
- int reg, val;
-
- for (reg = 0; reg < 0x80; reg += 2) {
- val = snd_ac97_read(ac97, reg);
- snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val);
- }
-}
-
-static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
-{
- ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
-
- 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 */
- snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG,
ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
- snd_ac97_proc_regs_read_main(ac97, buffer, idx);
- }
- /* select all codecs */
- snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000);
- up(&ac97->spec.ad18xx.mutex);
- } else {
- snd_ac97_proc_regs_read_main(ac97, buffer, 0);
- }
-}
-
-static void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97, const char *prefix)
-{
- snd_info_entry_t *entry;
- char name[32];
-
- if (ac97->num)
- sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num);
- else
- sprintf(name, "%s#%d", prefix, ac97->addr);
- if (! snd_card_proc_new(card, name, &entry))
- snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read);
- if (ac97->num)
- sprintf(name, "%s#%d-%dregs", prefix, ac97->addr, ac97->num);
- else
- sprintf(name, "%s#%dregs", prefix, ac97->addr);
- if (! snd_card_proc_new(card, name, &entry))
- snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);
}
/*
Index: ac97_patch.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_patch.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- ac97_patch.c 6 Jun 2003 09:29:17 -0000 1.15
+++ ac97_patch.c 17 Jun 2003 18:43:32 -0000 1.16
@@ -3,7 +3,8 @@
* Universal interface for Audio Codec '97
*
* For more details look to AC '97 component specification revision 2.2
- * by Intel Corporation (http://developer.intel.com).
+ * by Intel Corporation (http://developer.intel.com) and to datasheets
+ * for specific codecs.
*
*
* This program is free software; you can redistribute it and/or modify
@@ -28,15 +29,203 @@
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
+#include <sound/control.h>
#include <sound/ac97_codec.h>
-#include <sound/asoundef.h>
-#include <sound/initval.h>
#include "ac97_patch.h"
+#include "ac97_id.h"
+#include "ac97_local.h"
+
+#define chip_t ac97_t
/*
* Chip specific initialization
*/
+static int patch_build_controls(ac97_t * ac97, const snd_kcontrol_new_t *controls,
int count)
+{
+ int idx, err;
+
+ for (idx = 0; idx < count; idx++)
+ if ((err = snd_ctl_add(ac97->card, snd_ac97_cnew(&controls[idx],
ac97))) < 0)
+ return err;
+ return 0;
+}
+
+/* The following snd_ac97_ymf753_... items added by David Shust ([EMAIL PROTECTED]) */
+
+/* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
+static int snd_ac97_ymf753_info_speaker(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
* uinfo)
+{
+ static char *texts[3] = {
+ "Standard", "Small", "Smaller"
+ };
+
+ 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 snd_ac97_ymf753_get_speaker(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ val = ac97->regs[AC97_YMF753_3D_MODE_SEL];
+ val = (val >> 10) & 3;
+ if (val > 0) /* 0 = invalid */
+ val--;
+ ucontrol->value.enumerated.item[0] = val;
+ return 0;
+}
+
+static int snd_ac97_ymf753_put_speaker(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ if (ucontrol->value.enumerated.item[0] > 2)
+ return -EINVAL;
+ val = (ucontrol->value.enumerated.item[0] + 1) << 10;
+ return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val);
+}
+
+static const snd_kcontrol_new_t snd_ac97_ymf753_controls_speaker =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "3D Control - Speaker",
+ .info = snd_ac97_ymf753_info_speaker,
+ .get = snd_ac97_ymf753_get_speaker,
+ .put = snd_ac97_ymf753_put_speaker,
+};
+
+/* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF
output. */
+static int snd_ac97_ymf753_spdif_source_info(snd_kcontrol_t *kcontrol,
snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[2] = { "AC-Link", "A/D Converter" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item > 1)
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_ac97_ymf753_spdif_source_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ val = ac97->regs[AC97_YMF753_DIT_CTRL2];
+ ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
+ return 0;
+}
+
+static int snd_ac97_ymf753_spdif_source_put(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ if (ucontrol->value.enumerated.item[0] > 1)
+ return -EINVAL;
+ val = ucontrol->value.enumerated.item[0] << 1;
+ return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0002, val);
+}
+
+/* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
+ The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48.
+ By default, no output pin is selected, and the S/PDIF signal is not output.
+ There is also a bit to mute S/PDIF output in a vendor-specific register. */
+static int snd_ac97_ymf753_spdif_output_pin_info(snd_kcontrol_t *kcontrol,
snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" };
+
+ 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 snd_ac97_ymf753_spdif_output_pin_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ val = ac97->regs[AC97_YMF753_DIT_CTRL2];
+ ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 :
0;
+ return 0;
+}
+
+static int snd_ac97_ymf753_spdif_output_pin_put(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ if (ucontrol->value.enumerated.item[0] > 2)
+ return -EINVAL;
+ val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
+ (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
+ return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0028, val);
+ /* The following can be used to direct S/PDIF output to pin 47 (EAPD).
+ snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
+}
+
+static const snd_kcontrol_new_t snd_ac97_ymf753_controls_spdif[3] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+ .info = snd_ac97_ymf753_spdif_source_info,
+ .get = snd_ac97_ymf753_spdif_source_get,
+ .put = snd_ac97_ymf753_spdif_source_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
+ .info = snd_ac97_ymf753_spdif_output_pin_info,
+ .get = snd_ac97_ymf753_spdif_output_pin_get,
+ .put = snd_ac97_ymf753_spdif_output_pin_put,
+ },
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2,
2, 1, 1)
+};
+
+static int patch_yamaha_ymf753_3d(ac97_t * ac97)
+{
+ snd_kcontrol_t *kctl;
+ int err;
+
+ if ((err = snd_ctl_add(ac97->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);
+ snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
+ if ((err = snd_ctl_add(ac97->card,
snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
+ return err;
+ snd_ac97_write_cache(ac97, AC97_YMF753_3D_MODE_SEL, 0x0c00);
+ return 0;
+}
+
+static int patch_yamaha_ymf753_post_spdif(ac97_t * ac97)
+{
+ int err;
+
+ if ((err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif,
ARRAY_SIZE(snd_ac97_ymf753_controls_spdif))) < 0)
+ return err;
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
+ .build_3d = patch_yamaha_ymf753_3d,
+ .build_post_spdif = patch_yamaha_ymf753_post_spdif
+};
+
int patch_yamaha_ymf753(ac97_t * ac97)
{
/* Patch for Yamaha YMF753, Copyright (c) by David Shust, [EMAIL PROTECTED]
@@ -46,6 +235,7 @@
By default, no output pin is selected, and the S/PDIF signal is not output.
There is also a bit to mute S/PDIF output in a vendor-specific register.
*/
+ ac97->build_ops = &patch_yamaha_ymf753_ops;
ac97->caps |= AC97_BC_BASS_TREBLE;
ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
return 0;
@@ -57,12 +247,6 @@
* added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
*/
-#define AC97_WM97XX_FMIXER_VOL 0x72
-#define AC97_WM9704_RMIXER_VOL 0x74
-#define AC97_WM9704_TEST 0x5a
-#define AC97_WM9704_RPCM_VOL 0x70
-#define AC97_WM9711_OUT3VOL 0x16
-
int patch_wolfson03(ac97_t * ac97)
{
/* This is known to work for the ViewSonic ViewPad 1000
@@ -117,10 +301,89 @@
return 0;
}
+static int patch_sigmatel_stac9700_3d(ac97_t * ac97)
+{
+ snd_kcontrol_t *kctl;
+ int err;
+
+ if ((err = snd_ctl_add(ac97->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);
+ snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
+ return 0;
+}
+
+static int patch_sigmatel_stac9708_3d(ac97_t * ac97)
+{
+ snd_kcontrol_t *kctl;
+ int err;
+
+ if ((err = snd_ctl_add(ac97->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);
+ if ((err = snd_ctl_add(ac97->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);
+ snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
+ return 0;
+}
+
+static const snd_kcontrol_new_t snd_ac97_sigmatel_4speaker =
+AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch", AC97_SIGMATEL_DAC2INVERT, 2,
1, 0);
+
+static const snd_kcontrol_new_t snd_ac97_sigmatel_phaseinvert =
+AC97_SINGLE("Sigmatel Surround Phase Inversion Playback Switch",
AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
+
+static const snd_kcontrol_new_t snd_ac97_sigmatel_controls[] = {
+AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
+AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
+};
+
+static int patch_sigmatel_stac97xx_specific(ac97_t * ac97)
+{
+ int err;
+
+ snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97,
AC97_SIGMATEL_ANALOG) & ~0x0003);
+ if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1))
+ if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0],
1)) < 0)
+ return err;
+ if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))
+ if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1],
1)) < 0)
+ return err;
+ if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2))
+ if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1))
< 0)
+ return err;
+ if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3))
+ if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert,
1)) < 0)
+ return err;
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
+ .build_3d = patch_sigmatel_stac9700_3d,
+ .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;
+}
+
int patch_sigmatel_stac9708(ac97_t * ac97)
{
unsigned int codec72, codec6c;
+ ac97->build_ops = &patch_sigmatel_stac9708_ops;
+
codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
@@ -142,6 +405,7 @@
int patch_sigmatel_stac9721(ac97_t * ac97)
{
+ ac97->build_ops = &patch_sigmatel_stac9700_ops;
if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
// patch for SigmaTel
snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
@@ -156,6 +420,7 @@
int patch_sigmatel_stac9744(ac97_t * ac97)
{
// patch for SigmaTel
+ ac97->build_ops = &patch_sigmatel_stac9700_ops;
snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct?
--jk */
snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
@@ -167,6 +432,7 @@
int patch_sigmatel_stac9756(ac97_t * ac97)
{
// patch for SigmaTel
+ ac97->build_ops = &patch_sigmatel_stac9700_ops;
snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct?
--jk */
snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
@@ -175,6 +441,35 @@
return 0;
}
+static const snd_kcontrol_new_t snd_ac97_cirrus_controls_spdif[2] = {
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1,
0),
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA",
AC97_CSR_ACMODE, 0, 3, 0)
+};
+
+static int patch_cirrus_build_spdif(ac97_t * ac97)
+{
+ int err;
+
+ if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
+ return err;
+ if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1))
< 0)
+ return err;
+ switch (ac97->id & AC97_ID_CS_MASK) {
+ case AC97_ID_CS4205:
+ if ((err = patch_build_controls(ac97,
&snd_ac97_cirrus_controls_spdif[1], 1)) < 0)
+ return err;
+ break;
+ }
+ /* set default PCM S/PDIF params */
+ /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
+ snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_cirrus_ops = {
+ .build_spdif = patch_cirrus_build_spdif
+};
+
int patch_cirrus_spdif(ac97_t * ac97)
{
/* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.
@@ -188,6 +483,7 @@
- sp/dif ssource select is in 0x5e bits 0,1.
*/
+ ac97->build_ops = &patch_cirrus_ops;
ac97->flags |= AC97_CS_SPDIF;
ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
@@ -203,8 +499,32 @@
return patch_cirrus_spdif(ac97);
}
+static const snd_kcontrol_new_t snd_ac97_conexant_controls_spdif[1] = {
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3,
1, 0),
+};
+
+static int patch_conexant_build_spdif(ac97_t * ac97)
+{
+ int err;
+
+ if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
+ return err;
+ if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0],
1)) < 0)
+ return err;
+ /* set default PCM S/PDIF params */
+ /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
+ snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
+ snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) &
~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_conexant_ops = {
+ .build_spdif = patch_conexant_build_spdif
+};
+
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 */
return 0;
@@ -353,11 +673,63 @@
return 0;
}
+static int snd_ac97_ad1980_spdif_source_info(snd_kcontrol_t *kcontrol,
snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[2] = { "AC-Link", "A/D Converter" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item > 1)
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_ac97_ad1980_spdif_source_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ val = ac97->regs[AC97_AD_SERIAL_CFG];
+ ucontrol->value.enumerated.item[0] = (val >> 2) & 1;
+ return 0;
+}
+
+static int snd_ac97_ad1980_spdif_source_put(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ if (ucontrol->value.enumerated.item[0] > 1)
+ return -EINVAL;
+ val = ucontrol->value.enumerated.item[0] << 2;
+ return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);
+}
+
+static const snd_kcontrol_new_t snd_ac97_ad1980_spdif_source = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+ .info = snd_ac97_ad1980_spdif_source_info,
+ .get = snd_ac97_ad1980_spdif_source_get,
+ .put = snd_ac97_ad1980_spdif_source_put,
+};
+
+static int patch_ad1980_post_spdif(ac97_t * ac97)
+{
+ return patch_build_controls(ac97, &snd_ac97_ad1980_spdif_source, 1);
+}
+
+static struct snd_ac97_build_ops patch_ad1980_build_ops = {
+ .build_post_spdif = &patch_ad1980_post_spdif
+};
+
int patch_ad1980(ac97_t * ac97)
{
unsigned short misc;
patch_ad1881(ac97);
+ ac97->build_ops = &patch_ad1980_build_ops;
/* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
/* it seems that most vendors connect line-out connector to headphone out of
AC'97 */
misc = snd_ac97_read(ac97, AC97_AD_MISC);
@@ -365,6 +737,92 @@
return 0;
}
+static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
+ AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
+ AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
+ AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
+ AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
+ /* 4: Analog Input To Surround */
+ /* 5: Analog Input To Center/LFE */
+ /* 6: Independent Master Volume Right */
+ /* 7: Independent Master Volume Left */
+ /* 8: reserved */
+ AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
+ AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
+#if 0 /* always set in patch_alc650 */
+ AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
+ AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
+ AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
+ AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
+ AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
+ AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
+#endif
+};
+
+static const snd_kcontrol_new_t snd_ac97_control_alc650_mic =
+AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0);
+
+static int snd_ac97_alc650_mic_gpio_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_ALC650_MULTICH] >> 10) &
1;
+ return 0;
+}
+
+static int snd_ac97_alc650_mic_gpio_put(snd_kcontrol_t *kcontrol,
snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ int change;
+ change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
+ ucontrol->value.integer.value[0] ? (1 << 10) :
0);
+ if (change) {
+ /* GPIO0 write for mic */
+ snd_ac97_update_bits(ac97, 0x76, 0x01,
+ ucontrol->value.integer.value[0] ? 0 : 0x01);
+ /* GPIO0 high for mic */
+ snd_ac97_update_bits(ac97, 0x78, 0x100,
+ ucontrol->value.integer.value[0] ? 0 : 0x100);
+ }
+ return change;
+}
+
+static const snd_kcontrol_new_t snd_ac97_control_alc650_mic_gpio = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic As Center/LFE",
+ .info = snd_ac97_info_single,
+ .get = snd_ac97_alc650_mic_gpio_get,
+ .put = snd_ac97_alc650_mic_gpio_put,
+ .private_value = (1 << 16), /* for info */
+};
+
+static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
+ AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
+ AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
+ AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0),
+};
+
+static int patch_alc650_specific(ac97_t * ac97)
+{
+ int err;
+
+ if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650,
ARRAY_SIZE(snd_ac97_controls_alc650))) < 0)
+ return err;
+ if ((err = patch_build_controls(ac97,
+ ac97->spec.dev_flags ?
+ &snd_ac97_control_alc650_mic :
+ &snd_ac97_control_alc650_mic_gpio, 1))
< 0)
+ return err;
+ if (ac97->ext_id & AC97_EI_SPDIF) {
+ if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650,
ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
+ return err;
+ }
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_alc650_ops = {
+ .build_specific = patch_alc650_specific
+};
+
int patch_alc650(ac97_t * ac97)
{
unsigned short val;
@@ -374,6 +832,7 @@
* this is used for switching mic and center/lfe, which needs
* resetting GPIO0 level on the older revision.
*/
+ ac97->build_ops = &patch_alc650_ops;
ac97->spec.dev_flags = 0;
/* check spdif (should be only on rev.E) */
@@ -417,10 +876,101 @@
return 0;
}
+static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
+ AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
+ AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
+};
+
+static int patch_cm9738_specific(ac97_t * ac97)
+{
+ return patch_build_controls(ac97, snd_ac97_cm9738_controls,
ARRAY_SIZE(snd_ac97_cm9738_controls));
+}
+
+static struct snd_ac97_build_ops patch_cm9738_ops = {
+ .build_specific = patch_cm9738_specific
+};
+
+int patch_cm9738(ac97_t * ac97)
+{
+ ac97->build_ops = &patch_cm9738_ops;
+ return 0;
+}
+
+static int snd_ac97_cmedia_spdif_playback_source_info(snd_kcontrol_t *kcontrol,
snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[] = { "Analog", "Digital" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item > 1)
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_ac97_cmedia_spdif_playback_source_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
+ ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
+ return 0;
+}
+
+static int snd_ac97_cmedia_spdif_playback_source_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_CM9739_SPDIF_CTRL,
+ 0x01 << 1,
+ (ucontrol->value.enumerated.item[0] & 0x01) << 1);
+}
+
+static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
+ /* BIT 0: SPDI_EN - always true */
+ { /* BIT 1: SPDIFS */
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+ .info = snd_ac97_cmedia_spdif_playback_source_info,
+ .get = snd_ac97_cmedia_spdif_playback_source_get,
+ .put = snd_ac97_cmedia_spdif_playback_source_put,
+ },
+ /* BIT 2: IG_SPIV */
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch",
AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
+ /* BIT 3: SPI2F */
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor",
AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
+ /* BIT 4: SPI2SDI */
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL,
4, 1, 0),
+ /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
+};
+
+static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
+ AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),
+};
+
+static int patch_cm9739_specific(ac97_t * ac97)
+{
+ return patch_build_controls(ac97, snd_ac97_cm9739_controls,
ARRAY_SIZE(snd_ac97_cm9739_controls));
+}
+
+static int patch_cm9739_post_spdif(ac97_t * ac97)
+{
+ return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif,
ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
+}
+
+static struct snd_ac97_build_ops patch_cm9739_ops = {
+ .build_specific = patch_cm9739_specific,
+ .build_post_spdif = patch_cm9739_post_spdif
+};
+
int patch_cm9739(ac97_t * ac97)
{
unsigned short val;
+ ac97->build_ops = &patch_cm9739_ops;
+
/* check spdif */
val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
if (val & AC97_EA_SPCV) {
@@ -444,3 +994,31 @@
return 0;
}
+static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {
+AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
+AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
+AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
+AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
+};
+
+static int patch_vt1616_specific(ac97_t * ac97)
+{
+ int err;
+
+ if (snd_ac97_try_bit(ac97, 0x5a, 9))
+ if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0],
1)) < 0)
+ return err;
+ if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1],
ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0)
+ return err;
+ return 0;
+}
+
+static struct snd_ac97_build_ops patch_vt1616_ops = {
+ .build_specific = patch_vt1616_specific
+};
+
+int patch_vt1616(ac97_t * ac97)
+{
+ ac97->build_ops = &patch_vt1616_ops;
+ return 0;
+}
Index: ac97_patch.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_patch.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- ac97_patch.h 5 May 2003 14:28:23 -0000 1.7
+++ ac97_patch.h 17 Jun 2003 18:43:32 -0000 1.8
@@ -29,6 +29,7 @@
int patch_wolfson05(ac97_t * ac97);
int patch_wolfson11(ac97_t * ac97);
int patch_tritech_tr28028(ac97_t * ac97);
+int patch_sigmatel_stac9700(ac97_t * ac97);
int patch_sigmatel_stac9708(ac97_t * ac97);
int patch_sigmatel_stac9721(ac97_t * ac97);
int patch_sigmatel_stac9744(ac97_t * ac97);
@@ -42,4 +43,6 @@
int patch_ad1886(ac97_t * ac97);
int patch_ad1980(ac97_t * ac97);
int patch_alc650(ac97_t * ac97);
+int patch_cm9738(ac97_t * ac97);
int patch_cm9739(ac97_t * ac97);
+int patch_vt1616(ac97_t * ac97);
-------------------------------------------------------
This SF.Net email is sponsored by: INetU
Attention Web Developers & Consultants: Become An INetU Hosting Partner.
Refer Dedicated Servers. We Manage Them. You Get 10% Monthly Commission!
INetU Dedicated Managed Hosting http://www.inetu.net/partner/index.php
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog