Commit e7bfbb02 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/hda' into for-linus

parents fe506d6b 9b6682ff
...@@ -741,6 +741,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -741,6 +741,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
model - force the model name model - force the model name
position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF) position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
probe_mask - Bitmask to probe codecs (default = -1, meaning all slots) probe_mask - Bitmask to probe codecs (default = -1, meaning all slots)
When the bit 8 (0x100) is set, the lower 8 bits are used
as the "fixed" codec slots; i.e. the driver probes the
slots regardless what hardware reports back
probe_only - Only probing and no codec initialization (default=off); probe_only - Only probing and no codec initialization (default=off);
Useful to check the initial codec status for debugging Useful to check the initial codec status for debugging
bdl_pos_adj - Specifies the DMA IRQ timing delay in samples. bdl_pos_adj - Specifies the DMA IRQ timing delay in samples.
......
...@@ -56,6 +56,7 @@ ALC262 ...@@ -56,6 +56,7 @@ ALC262
sony-assamd Sony ASSAMD sony-assamd Sony ASSAMD
toshiba-s06 Toshiba S06 toshiba-s06 Toshiba S06
toshiba-rx1 Toshiba RX1 toshiba-rx1 Toshiba RX1
tyan Tyan Thunder n6650W (S2915-E)
ultra Samsung Q1 Ultra Vista model ultra Samsung Q1 Ultra Vista model
lenovo-3000 Lenovo 3000 y410 lenovo-3000 Lenovo 3000 y410
nec NEC Versa S9100 nec NEC Versa S9100
...@@ -261,6 +262,8 @@ Conexant 5051 ...@@ -261,6 +262,8 @@ Conexant 5051
============= =============
laptop Basic Laptop config (default) laptop Basic Laptop config (default)
hp HP Spartan laptop hp HP Spartan laptop
hp-dv6736 HP dv6736
lenovo-x200 Lenovo X200 laptop
STAC9200 STAC9200
======== ========
...@@ -278,6 +281,7 @@ STAC9200 ...@@ -278,6 +281,7 @@ STAC9200
gateway-m4 Gateway laptops with EAPD control gateway-m4 Gateway laptops with EAPD control
gateway-m4-2 Gateway laptops with EAPD control gateway-m4-2 Gateway laptops with EAPD control
panasonic Panasonic CF-74 panasonic Panasonic CF-74
auto BIOS setup (default)
STAC9205/9254 STAC9205/9254
============= =============
...@@ -285,6 +289,8 @@ STAC9205/9254 ...@@ -285,6 +289,8 @@ STAC9205/9254
dell-m42 Dell (unknown) dell-m42 Dell (unknown)
dell-m43 Dell Precision dell-m43 Dell Precision
dell-m44 Dell Inspiron dell-m44 Dell Inspiron
eapd Keep EAPD on (e.g. Gateway T1616)
auto BIOS setup (default)
STAC9220/9221 STAC9220/9221
============= =============
...@@ -308,6 +314,7 @@ STAC9220/9221 ...@@ -308,6 +314,7 @@ STAC9220/9221
dell-d82 Dell (unknown) dell-d82 Dell (unknown)
dell-m81 Dell (unknown) dell-m81 Dell (unknown)
dell-m82 Dell XPS M1210 dell-m82 Dell XPS M1210
auto BIOS setup (default)
STAC9202/9250/9251 STAC9202/9250/9251
================== ==================
...@@ -319,6 +326,7 @@ STAC9202/9250/9251 ...@@ -319,6 +326,7 @@ STAC9202/9250/9251
m3 Some Gateway MX series laptops m3 Some Gateway MX series laptops
m5 Some Gateway MX series laptops (MP6954) m5 Some Gateway MX series laptops (MP6954)
m6 Some Gateway NX series laptops m6 Some Gateway NX series laptops
auto BIOS setup (default)
STAC9227/9228/9229/927x STAC9227/9228/9229/927x
======================= =======================
...@@ -328,6 +336,7 @@ STAC9227/9228/9229/927x ...@@ -328,6 +336,7 @@ STAC9227/9228/9229/927x
5stack D965 5stack + SPDIF 5stack D965 5stack + SPDIF
dell-3stack Dell Dimension E520 dell-3stack Dell Dimension E520
dell-bios Fixes with Dell BIOS setup dell-bios Fixes with Dell BIOS setup
auto BIOS setup (default)
STAC92HD71B* STAC92HD71B*
============ ============
...@@ -335,7 +344,10 @@ STAC92HD71B* ...@@ -335,7 +344,10 @@ STAC92HD71B*
dell-m4-1 Dell desktops dell-m4-1 Dell desktops
dell-m4-2 Dell desktops dell-m4-2 Dell desktops
dell-m4-3 Dell desktops dell-m4-3 Dell desktops
hp-m4 HP dv laptops hp-m4 HP mini 1000
hp-dv5 HP dv series
hp-hdx HP HDX series
auto BIOS setup (default)
STAC92HD73* STAC92HD73*
=========== ===========
...@@ -345,13 +357,16 @@ STAC92HD73* ...@@ -345,13 +357,16 @@ STAC92HD73*
dell-m6-dmic Dell desktops/laptops with digital mics dell-m6-dmic Dell desktops/laptops with digital mics
dell-m6 Dell desktops/laptops with both type of mics dell-m6 Dell desktops/laptops with both type of mics
dell-eq Dell desktops/laptops dell-eq Dell desktops/laptops
auto BIOS setup (default)
STAC92HD83* STAC92HD83*
=========== ===========
ref Reference board ref Reference board
mic-ref Reference board with power managment for ports mic-ref Reference board with power managment for ports
dell-s14 Dell laptop
auto BIOS setup (default)
STAC9872 STAC9872
======== ========
vaio Setup for VAIO FE550G/SZ110 vaio VAIO laptop without SPDIF
vaio-ar Setup for VAIO AR auto BIOS setup (default)
...@@ -109,6 +109,13 @@ slot, pass `probe_mask=1`. For the first and the third slots, pass ...@@ -109,6 +109,13 @@ slot, pass `probe_mask=1`. For the first and the third slots, pass
Since 2.6.29 kernel, the driver has a more robust probing method, so Since 2.6.29 kernel, the driver has a more robust probing method, so
this error might happen rarely, though. this error might happen rarely, though.
On a machine with a broken BIOS, sometimes you need to force the
driver to probe the codec slots the hardware doesn't report for use.
In such a case, turn the bit 8 (0x100) of `probe_mask` option on.
Then the rest 8 bits are passed as the codec slots to probe
unconditionally. For example, `probe_mask=0x103` will force to probe
the codec slots 0 and 1 no matter what the hardware reports.
Interrupt Handling Interrupt Handling
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
...@@ -358,10 +365,26 @@ modelname:: ...@@ -358,10 +365,26 @@ modelname::
to this file. to this file.
init_verbs:: init_verbs::
The extra verbs to execute at initialization. You can add a verb by The extra verbs to execute at initialization. You can add a verb by
writing to this file. Pass tree numbers, nid, verb and parameter. writing to this file. Pass three numbers: nid, verb and parameter
(separated with a space).
hints:: hints::
Shows hint strings for codec parsers for any use. Right now it's Shows / stores hint strings for codec parsers for any use.
not used. Its format is `key = value`. For example, passing `hp_detect = yes`
to IDT/STAC codec parser will result in the disablement of the
headphone detection.
init_pin_configs::
Shows the initial pin default config values set by BIOS.
driver_pin_configs::
Shows the pin default values set by the codec parser explicitly.
This doesn't show all pin values but only the changed values by
the parser. That is, if the parser doesn't change the pin default
config values by itself, this will contain nothing.
user_pin_configs::
Shows the pin default config values to override the BIOS setup.
Writing this (with two numbers, NID and value) appends the new
value. The given will be used instead of the initial BIOS value at
the next reconfiguration time. Note that this config will override
even the driver pin configs, too.
reconfig:: reconfig::
Triggers the codec re-configuration. When any value is written to Triggers the codec re-configuration. When any value is written to
this file, the driver re-initialize and parses the codec tree this file, the driver re-initialize and parses the codec tree
...@@ -371,6 +394,14 @@ clear:: ...@@ -371,6 +394,14 @@ clear::
Resets the codec, removes the mixer elements and PCM stuff of the Resets the codec, removes the mixer elements and PCM stuff of the
specified codec, and clear all init verbs and hints. specified codec, and clear all init verbs and hints.
For example, when you want to change the pin default configuration
value of the pin widget 0x14 to 0x9993013f, and let the driver
re-configure based on that state, run like below:
------------------------------------------------------------------------
# echo 0x14 0x9993013f > /sys/class/sound/hwC0D0/user_pin_configs
# echo 1 > /sys/class/sound/hwC0D0/reconfig
------------------------------------------------------------------------
Power-Saving Power-Saving
~~~~~~~~~~~~ ~~~~~~~~~~~~
...@@ -461,6 +492,16 @@ run with `--no-upload` option, and attach the generated file. ...@@ -461,6 +492,16 @@ run with `--no-upload` option, and attach the generated file.
There are some other useful options. See `--help` option output for There are some other useful options. See `--help` option output for
details. details.
When a probe error occurs or when the driver obviously assigns a
mismatched model, it'd be helpful to load the driver with
`probe_only=1` option (at best after the cold reboot) and run
alsa-info at this state. With this option, the driver won't configure
the mixer and PCM but just tries to probe the codec slot. After
probing, the proc file is available, so you can get the raw codec
information before modified by the driver. Of course, the driver
isn't usable with `probe_only=1`. But you can continue the
configuration via hwdep sysfs file if hda-reconfig option is enabled.
hda-verb hda-verb
~~~~~~~~ ~~~~~~~~
......
...@@ -2112,6 +2112,8 @@ ...@@ -2112,6 +2112,8 @@
#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
#define PCI_DEVICE_ID_MELLANOX_SINAI 0x6274 #define PCI_DEVICE_ID_MELLANOX_SINAI 0x6274
#define PCI_VENDOR_ID_DFI 0x15bd
#define PCI_VENDOR_ID_QUICKNET 0x15e2 #define PCI_VENDOR_ID_QUICKNET 0x15e2
#define PCI_DEVICE_ID_QUICKNET_XJ 0x0500 #define PCI_DEVICE_ID_QUICKNET_XJ 0x0500
......
...@@ -138,6 +138,7 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) ...@@ -138,6 +138,7 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
input_unregister_device(beep->dev); input_unregister_device(beep->dev);
kfree(beep); kfree(beep);
codec->beep = NULL;
} }
} }
EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device);
...@@ -39,7 +39,7 @@ struct hda_beep { ...@@ -39,7 +39,7 @@ struct hda_beep {
int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); int snd_hda_attach_beep_device(struct hda_codec *codec, int nid);
void snd_hda_detach_beep_device(struct hda_codec *codec); void snd_hda_detach_beep_device(struct hda_codec *codec);
#else #else
#define snd_hda_attach_beep_device(...) #define snd_hda_attach_beep_device(...) 0
#define snd_hda_detach_beep_device(...) #define snd_hda_detach_beep_device(...)
#endif #endif
#endif #endif
This diff is collapsed.
...@@ -739,6 +739,7 @@ struct hda_codec { ...@@ -739,6 +739,7 @@ struct hda_codec {
hda_nid_t mfg; /* MFG node id */ hda_nid_t mfg; /* MFG node id */
/* ids */ /* ids */
u32 function_id;
u32 vendor_id; u32 vendor_id;
u32 subsystem_id; u32 subsystem_id;
u32 revision_id; u32 revision_id;
...@@ -778,11 +779,14 @@ struct hda_codec { ...@@ -778,11 +779,14 @@ struct hda_codec {
unsigned short spdif_ctls; /* SPDIF control bits */ unsigned short spdif_ctls; /* SPDIF control bits */
unsigned int spdif_in_enable; /* SPDIF input enable? */ unsigned int spdif_in_enable; /* SPDIF input enable? */
hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
struct snd_array init_pins; /* initial (BIOS) pin configurations */
struct snd_array driver_pins; /* pin configs set by codec parser */
#ifdef CONFIG_SND_HDA_HWDEP #ifdef CONFIG_SND_HDA_HWDEP
struct snd_hwdep *hwdep; /* assigned hwdep device */ struct snd_hwdep *hwdep; /* assigned hwdep device */
struct snd_array init_verbs; /* additional init verbs */ struct snd_array init_verbs; /* additional init verbs */
struct snd_array hints; /* additional hints */ struct snd_array hints; /* additional hints */
struct snd_array user_pins; /* default pin configs to override */
#endif #endif
/* misc flags */ /* misc flags */
...@@ -790,6 +794,9 @@ struct hda_codec { ...@@ -790,6 +794,9 @@ struct hda_codec {
* status change * status change
* (e.g. Realtek codecs) * (e.g. Realtek codecs)
*/ */
unsigned int pin_amp_workaround:1; /* pin out-amp takes index
* (e.g. Conexant codecs)
*/
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
unsigned int power_on :1; /* current (global) power-state */ unsigned int power_on :1; /* current (global) power-state */
unsigned int power_transition :1; /* power-state in transition */ unsigned int power_transition :1; /* power-state in transition */
...@@ -855,6 +862,18 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec); ...@@ -855,6 +862,18 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec);
#define snd_hda_sequence_write_cache snd_hda_sequence_write #define snd_hda_sequence_write_cache snd_hda_sequence_write
#endif #endif
/* the struct for codec->pin_configs */
struct hda_pincfg {
hda_nid_t nid;
unsigned int cfg;
};
unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_codec_set_pincfg(struct hda_codec *codec, hda_nid_t nid,
unsigned int cfg);
int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
hda_nid_t nid, unsigned int cfg); /* for hwdep */
/* /*
* Mixer * Mixer
*/ */
......
...@@ -144,9 +144,9 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid ...@@ -144,9 +144,9 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid
node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
if (node->type == AC_WID_PIN) { if (node->type == AC_WID_PIN) {
node->pin_caps = snd_hda_param_read(codec, node->nid, AC_PAR_PIN_CAP); node->pin_caps = snd_hda_query_pin_caps(codec, node->nid);
node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
node->def_cfg = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); node->def_cfg = snd_hda_codec_get_pincfg(codec, node->nid);
} }
if (node->wid_caps & AC_WCAP_OUT_AMP) { if (node->wid_caps & AC_WCAP_OUT_AMP) {
......
...@@ -30,6 +30,12 @@ ...@@ -30,6 +30,12 @@
#include <sound/hda_hwdep.h> #include <sound/hda_hwdep.h>
#include <sound/minors.h> #include <sound/minors.h>
/* hint string pair */
struct hda_hint {
const char *key;
const char *val; /* contained in the same alloc as key */
};
/* /*
* write/read an out-of-bound verb * write/read an out-of-bound verb
*/ */
...@@ -99,16 +105,17 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) ...@@ -99,16 +105,17 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
static void clear_hwdep_elements(struct hda_codec *codec) static void clear_hwdep_elements(struct hda_codec *codec)
{ {
char **head;
int i; int i;
/* clear init verbs */ /* clear init verbs */
snd_array_free(&codec->init_verbs); snd_array_free(&codec->init_verbs);
/* clear hints */ /* clear hints */
head = codec->hints.list; for (i = 0; i < codec->hints.used; i++) {
for (i = 0; i < codec->hints.used; i++, head++) struct hda_hint *hint = snd_array_elem(&codec->hints, i);
kfree(*head); kfree(hint->key); /* we don't need to free hint->val */
}
snd_array_free(&codec->hints); snd_array_free(&codec->hints);
snd_array_free(&codec->user_pins);
} }
static void hwdep_free(struct snd_hwdep *hwdep) static void hwdep_free(struct snd_hwdep *hwdep)
...@@ -140,7 +147,8 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) ...@@ -140,7 +147,8 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
#endif #endif
snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
snd_array_init(&codec->hints, sizeof(char *), 32); snd_array_init(&codec->hints, sizeof(struct hda_hint), 32);
snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16);
return 0; return 0;
} }
...@@ -153,7 +161,13 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) ...@@ -153,7 +161,13 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
static int clear_codec(struct hda_codec *codec) static int clear_codec(struct hda_codec *codec)
{ {
snd_hda_codec_reset(codec); int err;
err = snd_hda_codec_reset(codec);
if (err < 0) {
snd_printk(KERN_ERR "The codec is being used, can't free.\n");
return err;
}
clear_hwdep_elements(codec); clear_hwdep_elements(codec);
return 0; return 0;
} }
...@@ -162,20 +176,29 @@ static int reconfig_codec(struct hda_codec *codec) ...@@ -162,20 +176,29 @@ static int reconfig_codec(struct hda_codec *codec)
{ {
int err; int err;
snd_hda_power_up(codec);
snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); snd_printk(KERN_INFO "hda-codec: reconfiguring\n");
snd_hda_codec_reset(codec); err = snd_hda_codec_reset(codec);
if (err < 0) {
snd_printk(KERN_ERR
"The codec is being used, can't reconfigure.\n");
goto error;
}
err = snd_hda_codec_configure(codec); err = snd_hda_codec_configure(codec);
if (err < 0) if (err < 0)
return err; goto error;
/* rebuild PCMs */ /* rebuild PCMs */
err = snd_hda_codec_build_pcms(codec); err = snd_hda_codec_build_pcms(codec);
if (err < 0) if (err < 0)
return err; goto error;
/* rebuild mixers */ /* rebuild mixers */
err = snd_hda_codec_build_controls(codec); err = snd_hda_codec_build_controls(codec);
if (err < 0) if (err < 0)
goto error;
err = snd_card_register(codec->bus->card);
error:
snd_hda_power_down(codec);
return err; return err;
return snd_card_register(codec->bus->card);
} }
/* /*
...@@ -271,6 +294,22 @@ static ssize_t type##_store(struct device *dev, \ ...@@ -271,6 +294,22 @@ static ssize_t type##_store(struct device *dev, \
CODEC_ACTION_STORE(reconfig); CODEC_ACTION_STORE(reconfig);
CODEC_ACTION_STORE(clear); CODEC_ACTION_STORE(clear);
static ssize_t init_verbs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data;
int i, len = 0;
for (i = 0; i < codec->init_verbs.used; i++) {
struct hda_verb *v = snd_array_elem(&codec->init_verbs, i);
len += snprintf(buf + len, PAGE_SIZE - len,
"0x%02x 0x%03x 0x%04x\n",
v->nid, v->verb, v->param);
}
return len;
}
static ssize_t init_verbs_store(struct device *dev, static ssize_t init_verbs_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -293,26 +332,157 @@ static ssize_t init_verbs_store(struct device *dev, ...@@ -293,26 +332,157 @@ static ssize_t init_verbs_store(struct device *dev,
return count; return count;
} }
static ssize_t hints_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data;
int i, len = 0;
for (i = 0; i < codec->hints.used; i++) {
struct hda_hint *hint = snd_array_elem(&codec->hints, i);
len += snprintf(buf + len, PAGE_SIZE - len,
"%s = %s\n", hint->key, hint->val);
}
return len;
}
static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
{
int i;
for (i = 0; i < codec->hints.used; i++) {
struct hda_hint *hint = snd_array_elem(&codec->hints, i);
if (!strcmp(hint->key, key))
return hint;
}
return NULL;
}
static void remove_trail_spaces(char *str)
{
char *p;
if (!*str)
return;
p = str + strlen(str) - 1;
for (; isspace(*p); p--) {
*p = 0;
if (p == str)
return;
}
}
#define MAX_HINTS 1024
static ssize_t hints_store(struct device *dev, static ssize_t hints_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct snd_hwdep *hwdep = dev_get_drvdata(dev); struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data; struct hda_codec *codec = hwdep->private_data;
char *p; char *key, *val;
char **hint; struct hda_hint *hint;
if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n') while (isspace(*buf))
buf++;
if (!*buf || *buf == '#' || *buf == '\n')
return count; return count;
p = kstrndup_noeol(buf, 1024); if (*buf == '=')
if (!p) return -EINVAL;
key = kstrndup_noeol(buf, 1024);
if (!key)
return -ENOMEM; return -ENOMEM;
/* extract key and val */
val = strchr(key, '=');
if (!val) {
kfree(key);
return -EINVAL;
}
*val++ = 0;
while (isspace(*val))
val++;
remove_trail_spaces(key);
remove_trail_spaces(val);
hint = get_hint(codec, key);
if (hint) {
/* replace */
kfree(hint->key);
hint->key = key;
hint->val = val;
return count;
}
/* allocate a new hint entry */
if (codec->hints.used >= MAX_HINTS)
hint = NULL;
else
hint = snd_array_new(&codec->hints); hint = snd_array_new(&codec->hints);
if (!hint) { if (!hint) {
kfree(p); kfree(key);
return -ENOMEM; return -ENOMEM;
} }
*hint = p; hint->key = key;
hint->val = val;
return count;
}
static ssize_t pin_configs_show(struct hda_codec *codec,
struct snd_array *list,
char *buf)
{
int i, len = 0;
for (i = 0; i < list->used; i++) {
struct hda_pincfg *pin = snd_array_elem(list, i);
len += sprintf(buf + len, "0x%02x 0x%08x\n",
pin->nid, pin->cfg);
}
return len;
}
static ssize_t init_pin_configs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data;
return pin_configs_show(codec, &codec->init_pins, buf);
}
static ssize_t user_pin_configs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data;
return pin_configs_show(codec, &codec->user_pins, buf);
}
static ssize_t driver_pin_configs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data;
return pin_configs_show(codec, &codec->driver_pins, buf);
}
#define MAX_PIN_CONFIGS 32
static ssize_t user_pin_configs_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data;
int nid, cfg;
int err;
if (sscanf(buf, "%i %i", &nid, &cfg) != 2)
return -EINVAL;
if (!nid)
return -EINVAL;
err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg);
if (err < 0)
return err;
return count; return count;
} }
...@@ -331,8 +501,11 @@ static struct device_attribute codec_attrs[] = { ...@@ -331,8 +501,11 @@ static struct device_attribute codec_attrs[] = {
CODEC_ATTR_RO(mfg), CODEC_ATTR_RO(mfg),
CODEC_ATTR_RW(name), CODEC_ATTR_RW(name),
CODEC_ATTR_RW(modelname), CODEC_ATTR_RW(modelname),
CODEC_ATTR_WO(init_verbs), CODEC_ATTR_RW(init_verbs),
CODEC_ATTR_WO(hints), CODEC_ATTR_RW(hints),
CODEC_ATTR_RO(init_pin_configs),
CODEC_ATTR_RW(user_pin_configs),
CODEC_ATTR_RO(driver_pin_configs),
CODEC_ATTR_WO(reconfig), CODEC_ATTR_WO(reconfig),
CODEC_ATTR_WO(clear), CODEC_ATTR_WO(clear),
}; };
...@@ -351,4 +524,29 @@ int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) ...@@ -351,4 +524,29 @@ int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
return 0; return 0;
} }
/*
* Look for hint string
*/
const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
{
struct hda_hint *hint = get_hint(codec, key);
return hint ? hint->val : NULL;
}
EXPORT_SYMBOL_HDA(snd_hda_get_hint);
int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
{
const char *p = snd_hda_get_hint(codec, key);
if (!p || !*p)
return -ENOENT;
switch (toupper(*p)) {
case 'T': /* true */
case 'Y': /* yes */
case '1':
return 1;
}
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint);
#endif /* CONFIG_SND_HDA_RECONFIG */ #endif /* CONFIG_SND_HDA_RECONFIG */
...@@ -381,6 +381,7 @@ struct azx { ...@@ -381,6 +381,7 @@ struct azx {
/* HD codec */ /* HD codec */
unsigned short codec_mask; unsigned short codec_mask;
int codec_probe_mask; /* copied from probe_mask option */
struct hda_bus *bus; struct hda_bus *bus;
/* CORB/RIRB */ /* CORB/RIRB */
...@@ -858,13 +859,18 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) ...@@ -858,13 +859,18 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev)
SD_CTL_DMA_START | SD_INT_MASK); SD_CTL_DMA_START | SD_INT_MASK);
} }
/* stop a stream */ /* stop DMA */
static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev)
{ {
/* stop DMA */
azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
~(SD_CTL_DMA_START | SD_INT_MASK)); ~(SD_CTL_DMA_START | SD_INT_MASK));
azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
}
/* stop a stream */
static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
{
azx_stream_clear(chip, azx_dev);
/* disable SIE */ /* disable SIE */
azx_writeb(chip, INTCTL, azx_writeb(chip, INTCTL,
azx_readb(chip, INTCTL) & ~(1 << azx_dev->index)); azx_readb(chip, INTCTL) & ~(1 << azx_dev->index));
...@@ -1075,8 +1081,7 @@ static int azx_setup_periods(struct azx *chip, ...@@ -1075,8 +1081,7 @@ static int azx_setup_periods(struct azx *chip,
azx_sd_writel(azx_dev, SD_BDLPL, 0); azx_sd_writel(azx_dev, SD_BDLPL, 0);
azx_sd_writel(azx_dev, SD_BDLPU, 0); azx_sd_writel(azx_dev, SD_BDLPU, 0);
period_bytes = snd_pcm_lib_period_bytes(substream); period_bytes = azx_dev->period_bytes;
azx_dev->period_bytes = period_bytes;
periods = azx_dev->bufsize / period_bytes; periods = azx_dev->bufsize / period_bytes;
/* program the initial BDL entries */ /* program the initial BDL entries */
...@@ -1123,24 +1128,17 @@ static int azx_setup_periods(struct azx *chip, ...@@ -1123,24 +1128,17 @@ static int azx_setup_periods(struct azx *chip,
error: error:
snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n", snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n",
azx_dev->bufsize, period_bytes); azx_dev->bufsize, period_bytes);
/* reset */
azx_sd_writel(azx_dev, SD_BDLPL, 0);
azx_sd_writel(azx_dev, SD_BDLPU, 0);
return -EINVAL; return -EINVAL;
} }
/* /* reset stream */
* set up the SD for streaming static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
*/
static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
{ {
unsigned char val; unsigned char val;
int timeout; int timeout;
/* make sure the run bit is zero for SD */ azx_stream_clear(chip, azx_dev);
azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
~SD_CTL_DMA_START);
/* reset stream */
azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) |
SD_CTL_STREAM_RESET); SD_CTL_STREAM_RESET);
udelay(3); udelay(3);
...@@ -1157,7 +1155,15 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) ...@@ -1157,7 +1155,15 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
--timeout) --timeout)
; ;
}
/*
* set up the SD for streaming
*/
static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
{
/* make sure the run bit is zero for SD */
azx_stream_clear(chip, azx_dev);
/* program the stream_tag */ /* program the stream_tag */
azx_sd_writel(azx_dev, SD_CTL, azx_sd_writel(azx_dev, SD_CTL,
(azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)| (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)|
...@@ -1228,7 +1234,6 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { ...@@ -1228,7 +1234,6 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
}; };
static int __devinit azx_codec_create(struct azx *chip, const char *model, static int __devinit azx_codec_create(struct azx *chip, const char *model,
unsigned int codec_probe_mask,
int no_init) int no_init)
{ {
struct hda_bus_template bus_temp; struct hda_bus_template bus_temp;
...@@ -1261,7 +1266,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, ...@@ -1261,7 +1266,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
/* First try to probe all given codec slots */ /* First try to probe all given codec slots */
for (c = 0; c < max_slots; c++) { for (c = 0; c < max_slots; c++) {
if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
if (probe_codec(chip, c) < 0) { if (probe_codec(chip, c) < 0) {
/* Some BIOSen give you wrong codec addresses /* Some BIOSen give you wrong codec addresses
* that don't exist * that don't exist
...@@ -1285,7 +1290,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, ...@@ -1285,7 +1290,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
/* Then create codec instances */ /* Then create codec instances */
for (c = 0; c < max_slots; c++) { for (c = 0; c < max_slots; c++) {
if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
struct hda_codec *codec; struct hda_codec *codec;
err = snd_hda_codec_new(chip->bus, c, !no_init, &codec); err = snd_hda_codec_new(chip->bus, c, !no_init, &codec);
if (err < 0) if (err < 0)
...@@ -1403,6 +1408,8 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) ...@@ -1403,6 +1408,8 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
runtime->private_data = azx_dev; runtime->private_data = azx_dev;
snd_pcm_set_sync(substream); snd_pcm_set_sync(substream);
mutex_unlock(&chip->open_mutex); mutex_unlock(&chip->open_mutex);
azx_stream_reset(chip, azx_dev);
return 0; return 0;
} }
...@@ -1429,6 +1436,11 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) ...@@ -1429,6 +1436,11 @@ static int azx_pcm_close(struct snd_pcm_substream *substream)
static int azx_pcm_hw_params(struct snd_pcm_substream *substream, static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params) struct snd_pcm_hw_params *hw_params)
{ {
struct azx_dev *azx_dev = get_azx_dev(substream);
azx_dev->bufsize = 0;
azx_dev->period_bytes = 0;
azx_dev->format_val = 0;
return snd_pcm_lib_malloc_pages(substream, return snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params)); params_buffer_bytes(hw_params));
} }
...@@ -1443,6 +1455,9 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) ...@@ -1443,6 +1455,9 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
azx_sd_writel(azx_dev, SD_BDLPL, 0); azx_sd_writel(azx_dev, SD_BDLPL, 0);
azx_sd_writel(azx_dev, SD_BDLPU, 0); azx_sd_writel(azx_dev, SD_BDLPU, 0);
azx_sd_writel(azx_dev, SD_CTL, 0); azx_sd_writel(azx_dev, SD_CTL, 0);
azx_dev->bufsize = 0;
azx_dev->period_bytes = 0;
azx_dev->format_val = 0;
hinfo->ops.cleanup(hinfo, apcm->codec, substream); hinfo->ops.cleanup(hinfo, apcm->codec, substream);
...@@ -1456,23 +1471,37 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -1456,23 +1471,37 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
struct azx_dev *azx_dev = get_azx_dev(substream); struct azx_dev *azx_dev = get_azx_dev(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int bufsize, period_bytes, format_val;
int err;
azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream); format_val = snd_hda_calc_stream_format(runtime->rate,
azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
runtime->channels, runtime->channels,
runtime->format, runtime->format,
hinfo->maxbps); hinfo->maxbps);
if (!azx_dev->format_val) { if (!format_val) {
snd_printk(KERN_ERR SFX snd_printk(KERN_ERR SFX
"invalid format_val, rate=%d, ch=%d, format=%d\n", "invalid format_val, rate=%d, ch=%d, format=%d\n",
runtime->rate, runtime->channels, runtime->format); runtime->rate, runtime->channels, runtime->format);
return -EINVAL; return -EINVAL;
} }
bufsize = snd_pcm_lib_buffer_bytes(substream);
period_bytes = snd_pcm_lib_period_bytes(substream);
snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
azx_dev->bufsize, azx_dev->format_val); bufsize, format_val);
if (azx_setup_periods(chip, substream, azx_dev) < 0)
return -EINVAL; if (bufsize != azx_dev->bufsize ||
period_bytes != azx_dev->period_bytes ||
format_val != azx_dev->format_val) {
azx_dev->bufsize = bufsize;
azx_dev->period_bytes = period_bytes;
azx_dev->format_val = format_val;
err = azx_setup_periods(chip, substream, azx_dev);
if (err < 0)
return err;
}
azx_setup_controller(chip, azx_dev); azx_setup_controller(chip, azx_dev);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
...@@ -2100,25 +2129,36 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = { ...@@ -2100,25 +2129,36 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01), SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01),
/* including bogus ALC268 in slot#2 that conflicts with ALC888 */ /* including bogus ALC268 in slot#2 that conflicts with ALC888 */
SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01), SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
/* conflict of ALC268 in slot#3 (digital I/O); a temporary fix */ /* forced codec slots */
SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba laptop", 0x03), SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
{} {}
}; };
#define AZX_FORCE_CODEC_MASK 0x100
static void __devinit check_probe_mask(struct azx *chip, int dev) static void __devinit check_probe_mask(struct azx *chip, int dev)
{ {
const struct snd_pci_quirk *q; const struct snd_pci_quirk *q;
if (probe_mask[dev] == -1) { chip->codec_probe_mask = probe_mask[dev];
if (chip->codec_probe_mask == -1) {
q = snd_pci_quirk_lookup(chip->pci, probe_mask_list); q = snd_pci_quirk_lookup(chip->pci, probe_mask_list);
if (q) { if (q) {
printk(KERN_INFO printk(KERN_INFO
"hda_intel: probe_mask set to 0x%x " "hda_intel: probe_mask set to 0x%x "
"for device %04x:%04x\n", "for device %04x:%04x\n",
q->value, q->subvendor, q->subdevice); q->value, q->subvendor, q->subdevice);
probe_mask[dev] = q->value; chip->codec_probe_mask = q->value;
} }
} }
/* check forced option */
if (chip->codec_probe_mask != -1 &&
(chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) {
chip->codec_mask = chip->codec_probe_mask & 0xff;
printk(KERN_INFO "hda_intel: codec_mask forced to 0x%x\n",
chip->codec_mask);
}
} }
...@@ -2359,8 +2399,7 @@ static int __devinit azx_probe(struct pci_dev *pci, ...@@ -2359,8 +2399,7 @@ static int __devinit azx_probe(struct pci_dev *pci,
card->private_data = chip; card->private_data = chip;
/* create codec instances */ /* create codec instances */
err = azx_codec_create(chip, model[dev], probe_mask[dev], err = azx_codec_create(chip, model[dev], probe_only[dev]);
probe_only[dev]);
if (err < 0) if (err < 0)
goto out_free; goto out_free;
...@@ -2457,10 +2496,10 @@ static struct pci_device_id azx_ids[] = { ...@@ -2457,10 +2496,10 @@ static struct pci_device_id azx_ids[] = {
{ PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0bd4), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA },
/* Teradici */ /* Teradici */
{ PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
/* AMD Generic, PCI class code and Vendor ID for HD Audio */ /* AMD Generic, PCI class code and Vendor ID for HD Audio */
......
...@@ -26,8 +26,10 @@ ...@@ -26,8 +26,10 @@
/* /*
* for mixer controls * for mixer controls
*/ */
#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \
((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23))
#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0)
/* mono volume with index (index=0,1,...) (channel=1,2) */ /* mono volume with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
...@@ -96,7 +98,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, ...@@ -96,7 +98,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
const char *name); const char *name);
int snd_hda_add_vmaster(struct hda_codec *codec, char *name, int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
unsigned int *tlv, const char **slaves); unsigned int *tlv, const char **slaves);
void snd_hda_codec_reset(struct hda_codec *codec); int snd_hda_codec_reset(struct hda_codec *codec);
int snd_hda_codec_configure(struct hda_codec *codec); int snd_hda_codec_configure(struct hda_codec *codec);
/* amp value bits */ /* amp value bits */
...@@ -134,7 +136,7 @@ extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */ ...@@ -134,7 +136,7 @@ extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */
struct hda_bind_ctls { struct hda_bind_ctls {
struct hda_ctl_ops *ops; struct hda_ctl_ops *ops;
long values[]; unsigned long values[];
}; };
int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
...@@ -227,6 +229,7 @@ struct hda_multi_out { ...@@ -227,6 +229,7 @@ struct hda_multi_out {
hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */
hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */ hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */
hda_nid_t dig_out_nid; /* digital out audio widget */ hda_nid_t dig_out_nid; /* digital out audio widget */
hda_nid_t *slave_dig_outs;
int max_channels; /* currently supported analog channels */ int max_channels; /* currently supported analog channels */
int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */
int no_share_stream; /* don't share a stream with multiple pins */ int no_share_stream; /* don't share a stream with multiple pins */
...@@ -354,9 +357,12 @@ struct auto_pin_cfg { ...@@ -354,9 +357,12 @@ struct auto_pin_cfg {
int line_out_type; /* AUTO_PIN_XXX_OUT */ int line_out_type; /* AUTO_PIN_XXX_OUT */
hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
hda_nid_t input_pins[AUTO_PIN_LAST]; hda_nid_t input_pins[AUTO_PIN_LAST];
hda_nid_t dig_out_pin; int dig_outs;
hda_nid_t dig_out_pins[2];
hda_nid_t dig_in_pin; hda_nid_t dig_in_pin;
hda_nid_t mono_out_pin; hda_nid_t mono_out_pin;
int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */
int dig_in_type; /* HDA_PCM_TYPE_XXX */
}; };
#define get_defcfg_connect(cfg) \ #define get_defcfg_connect(cfg) \
...@@ -405,6 +411,7 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid) ...@@ -405,6 +411,7 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps); unsigned int caps);
u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl);
void snd_hda_ctls_clear(struct hda_codec *codec); void snd_hda_ctls_clear(struct hda_codec *codec);
...@@ -427,6 +434,23 @@ static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) ...@@ -427,6 +434,23 @@ static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
} }
#endif #endif
#ifdef CONFIG_SND_HDA_RECONFIG
const char *snd_hda_get_hint(struct hda_codec *codec, const char *key);
int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key);
#else
static inline
const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
{
return NULL;
}
static inline
int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
{
return -ENOENT;
}
#endif
/* /*
* power-management * power-management
*/ */
...@@ -458,6 +482,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, ...@@ -458,6 +482,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f)
/* /*
* CEA Short Audio Descriptor data * CEA Short Audio Descriptor data
......
...@@ -399,8 +399,10 @@ static void print_conn_list(struct snd_info_buffer *buffer, ...@@ -399,8 +399,10 @@ static void print_conn_list(struct snd_info_buffer *buffer,
{ {
int c, curr = -1; int c, curr = -1;
if (conn_len > 1 && wid_type != AC_WID_AUD_MIX && if (conn_len > 1 &&
wid_type != AC_WID_VOL_KNB) wid_type != AC_WID_AUD_MIX &&
wid_type != AC_WID_VOL_KNB &&
wid_type != AC_WID_POWER)
curr = snd_hda_codec_read(codec, nid, 0, curr = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_CONNECT_SEL, 0); AC_VERB_GET_CONNECT_SEL, 0);
snd_iprintf(buffer, " Connection: %d\n", conn_len); snd_iprintf(buffer, " Connection: %d\n", conn_len);
...@@ -467,8 +469,9 @@ static void print_codec_info(struct snd_info_entry *entry, ...@@ -467,8 +469,9 @@ static void print_codec_info(struct snd_info_entry *entry,
snd_iprintf(buffer, "Codec: %s\n", snd_iprintf(buffer, "Codec: %s\n",
codec->name ? codec->name : "Not Set"); codec->name ? codec->name : "Not Set");
snd_iprintf(buffer, "Address: %d\n", codec->addr); snd_iprintf(buffer, "Address: %d\n", codec->addr);
snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id);
snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
if (codec->mfg) if (codec->mfg)
...@@ -554,6 +557,12 @@ static void print_codec_info(struct snd_info_entry *entry, ...@@ -554,6 +557,12 @@ static void print_codec_info(struct snd_info_entry *entry,
snd_iprintf(buffer, " Amp-Out caps: "); snd_iprintf(buffer, " Amp-Out caps: ");
print_amp_caps(buffer, codec, nid, HDA_OUTPUT); print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
snd_iprintf(buffer, " Amp-Out vals: "); snd_iprintf(buffer, " Amp-Out vals: ");
if (wid_type == AC_WID_PIN &&
codec->pin_amp_workaround)
print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
wid_caps & AC_WCAP_STEREO,
conn_len);
else
print_amp_vals(buffer, codec, nid, HDA_OUTPUT, print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
wid_caps & AC_WCAP_STEREO, 1); wid_caps & AC_WCAP_STEREO, 1);
} }
......
This diff is collapsed.
...@@ -680,13 +680,13 @@ static int patch_cmi9880(struct hda_codec *codec) ...@@ -680,13 +680,13 @@ static int patch_cmi9880(struct hda_codec *codec)
struct auto_pin_cfg cfg; struct auto_pin_cfg cfg;
/* collect pin default configuration */ /* collect pin default configuration */
port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); port_e = snd_hda_codec_get_pincfg(codec, 0x0f);
port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); port_f = snd_hda_codec_get_pincfg(codec, 0x10);
spec->front_panel = 1; spec->front_panel = 1;
if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE ||
get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) {
port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); port_g = snd_hda_codec_get_pincfg(codec, 0x1f);
port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); port_h = snd_hda_codec_get_pincfg(codec, 0x20);
spec->channel_modes = cmi9880_channel_modes; spec->channel_modes = cmi9880_channel_modes;
/* no front panel */ /* no front panel */
if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE ||
...@@ -703,8 +703,8 @@ static int patch_cmi9880(struct hda_codec *codec) ...@@ -703,8 +703,8 @@ static int patch_cmi9880(struct hda_codec *codec)
spec->multiout.max_channels = cmi9880_channel_modes[0].channels; spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
} else { } else {
spec->input_mux = &cmi9880_basic_mux; spec->input_mux = &cmi9880_basic_mux;
port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); port_spdifi = snd_hda_codec_get_pincfg(codec, 0x13);
port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); port_spdifo = snd_hda_codec_get_pincfg(codec, 0x12);
if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE)
spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -1308,16 +1308,13 @@ static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid) ...@@ -1308,16 +1308,13 @@ static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
unsigned int def_conf; unsigned int def_conf;
unsigned char seqassoc; unsigned char seqassoc;
def_conf = snd_hda_codec_read(codec, nid, 0, def_conf = snd_hda_codec_get_pincfg(codec, nid);
AC_VERB_GET_CONFIG_DEFAULT, 0);
seqassoc = (unsigned char) get_defcfg_association(def_conf); seqassoc = (unsigned char) get_defcfg_association(def_conf);
seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf); seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) { if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) {
if (seqassoc == 0xff) { if (seqassoc == 0xff) {
def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30)); def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
snd_hda_codec_write(codec, nid, 0, snd_hda_codec_set_pincfg(codec, nid, def_conf);
AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
def_conf >> 24);
} }
} }
...@@ -1354,7 +1351,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) ...@@ -1354,7 +1351,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2; spec->multiout.max_channels = spec->multiout.num_dacs * 2;
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_outs)
spec->multiout.dig_out_nid = VT1708_DIGOUT_NID; spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708_DIGIN_NID; spec->dig_in_nid = VT1708_DIGIN_NID;
...@@ -1827,7 +1824,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) ...@@ -1827,7 +1824,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2; spec->multiout.max_channels = spec->multiout.num_dacs * 2;
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_outs)
spec->multiout.dig_out_nid = VT1709_DIGOUT_NID; spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1709_DIGIN_NID; spec->dig_in_nid = VT1709_DIGIN_NID;
...@@ -2371,7 +2368,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) ...@@ -2371,7 +2368,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2; spec->multiout.max_channels = spec->multiout.num_dacs * 2;
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_outs)
spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID; spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708B_DIGIN_NID; spec->dig_in_nid = VT1708B_DIGIN_NID;
...@@ -2836,7 +2833,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) ...@@ -2836,7 +2833,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2; spec->multiout.max_channels = spec->multiout.num_dacs * 2;
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_outs)
spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID; spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID;
spec->extra_dig_out_nid = 0x15; spec->extra_dig_out_nid = 0x15;
...@@ -3155,7 +3152,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) ...@@ -3155,7 +3152,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2; spec->multiout.max_channels = spec->multiout.num_dacs * 2;
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_outs)
spec->multiout.dig_out_nid = VT1702_DIGOUT_NID; spec->multiout.dig_out_nid = VT1702_DIGOUT_NID;
spec->extra_dig_out_nid = 0x1B; spec->extra_dig_out_nid = 0x1B;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment