summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_codec.c162
-rw-r--r--sound/pci/hda/hda_codec.h15
-rw-r--r--sound/pci/hda/hda_generic.c2
-rw-r--r--sound/pci/hda/hda_hwdep.c66
-rw-r--r--sound/pci/hda/patch_analog.c3
-rw-r--r--sound/pci/hda/patch_cmedia.c12
-rw-r--r--sound/pci/hda/patch_realtek.c78
-rw-r--r--sound/pci/hda/patch_sigmatel.c255
-rw-r--r--sound/pci/hda/patch_via.c7
9 files changed, 310 insertions, 290 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 98884bc8f35f..a13480fa8e74 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -682,11 +682,140 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
return 0;
}
+/* read all pin default configurations and save codec->init_pins */
+static int read_pin_defaults(struct hda_codec *codec)
+{
+ int i;
+ hda_nid_t nid = codec->start_nid;
+
+ for (i = 0; i < codec->num_nodes; i++, nid++) {
+ struct hda_pincfg *pin;
+ unsigned int wcaps = get_wcaps(codec, nid);
+ unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
+ AC_WCAP_TYPE_SHIFT;
+ if (wid_type != AC_WID_PIN)
+ continue;
+ pin = snd_array_new(&codec->init_pins);
+ if (!pin)
+ return -ENOMEM;
+ pin->nid = nid;
+ pin->cfg = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CONFIG_DEFAULT, 0);
+ }
+ return 0;
+}
+
+/* look up the given pin config list and return the item matching with NID */
+static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
+ struct snd_array *array,
+ hda_nid_t nid)
+{
+ int i;
+ for (i = 0; i < array->used; i++) {
+ struct hda_pincfg *pin = snd_array_elem(array, i);
+ if (pin->nid == nid)
+ return pin;
+ }
+ return NULL;
+}
+
+/* write a config value for the given NID */
+static void set_pincfg(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int cfg)
+{
+ int i;
+ for (i = 0; i < 4; i++) {
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
+ cfg & 0xff);
+ cfg >>= 8;
+ }
+}
+
+/* set the current pin config value for the given NID.
+ * the value is cached, and read via snd_hda_codec_get_pincfg()
+ */
+int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
+ hda_nid_t nid, unsigned int cfg)
+{
+ struct hda_pincfg *pin;
+ unsigned int oldcfg;
+
+ oldcfg = snd_hda_codec_get_pincfg(codec, nid);
+ pin = look_up_pincfg(codec, list, nid);
+ if (!pin) {
+ pin = snd_array_new(list);
+ if (!pin)
+ return -ENOMEM;
+ pin->nid = nid;
+ }
+ pin->cfg = cfg;
+
+ /* change only when needed; e.g. if the pincfg is already present
+ * in user_pins[], don't write it
+ */
+ cfg = snd_hda_codec_get_pincfg(codec, nid);
+ if (oldcfg != cfg)
+ set_pincfg(codec, nid, cfg);
+ return 0;
+}
+
+int snd_hda_codec_set_pincfg(struct hda_codec *codec,
+ hda_nid_t nid, unsigned int cfg)
+{
+ return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
+}
+EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
+
+/* get the current pin config value of the given pin NID */
+unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct hda_pincfg *pin;
+
+#ifdef CONFIG_SND_HDA_HWDEP
+ pin = look_up_pincfg(codec, &codec->user_pins, nid);
+ if (pin)
+ return pin->cfg;
+#endif
+ pin = look_up_pincfg(codec, &codec->driver_pins, nid);
+ if (pin)
+ return pin->cfg;
+ pin = look_up_pincfg(codec, &codec->init_pins, nid);
+ if (pin)
+ return pin->cfg;
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
+
+/* restore all current pin configs */
+static void restore_pincfgs(struct hda_codec *codec)
+{
+ int i;
+ for (i = 0; i < codec->init_pins.used; i++) {
+ struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+ set_pincfg(codec, pin->nid,
+ snd_hda_codec_get_pincfg(codec, pin->nid));
+ }
+}
static void init_hda_cache(struct hda_cache_rec *cache,
unsigned int record_size);
static void free_hda_cache(struct hda_cache_rec *cache);
+/* restore the initial pin cfgs and release all pincfg lists */
+static void restore_init_pincfgs(struct hda_codec *codec)
+{
+ /* first free driver_pins and user_pins, then call restore_pincfg
+ * so that only the values in init_pins are restored
+ */
+ snd_array_free(&codec->driver_pins);
+#ifdef CONFIG_SND_HDA_HWDEP
+ snd_array_free(&codec->user_pins);
+#endif
+ restore_pincfgs(codec);
+ snd_array_free(&codec->init_pins);
+}
+
/*
* codec destructor
*/
@@ -694,6 +823,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
{
if (!codec)
return;
+ restore_init_pincfgs(codec);
#ifdef CONFIG_SND_HDA_POWER_SAVE
cancel_delayed_work(&codec->power_work);
flush_workqueue(codec->bus->workq);
@@ -751,6 +881,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
+ snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
+ snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
if (codec->bus->modelname) {
codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
if (!codec->modelname) {
@@ -787,15 +919,18 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
setup_fg_nodes(codec);
if (!codec->afg && !codec->mfg) {
snd_printdd("hda_codec: no AFG or MFG node found\n");
- snd_hda_codec_free(codec);
- return -ENODEV;
+ err = -ENODEV;
+ goto error;
}
- if (read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg) < 0) {
+ err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg);
+ if (err < 0) {
snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
- snd_hda_codec_free(codec);
- return -ENOMEM;
+ goto error;
}
+ err = read_pin_defaults(codec);
+ if (err < 0)
+ goto error;
if (!codec->subsystem_id) {
hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
@@ -808,10 +943,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
if (do_init) {
err = snd_hda_codec_configure(codec);
- if (err < 0) {
- snd_hda_codec_free(codec);
- return err;
- }
+ if (err < 0)
+ goto error;
}
snd_hda_codec_proc_new(codec);
@@ -824,6 +957,10 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
if (codecp)
*codecp = codec;
return 0;
+
+ error:
+ snd_hda_codec_free(codec);
+ return err;
}
EXPORT_SYMBOL_HDA(snd_hda_codec_new);
@@ -1334,6 +1471,9 @@ void snd_hda_codec_reset(struct hda_codec *codec)
free_hda_cache(&codec->cmd_cache);
init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
+ /* free only driver_pins so that init_pins + user_pins are restored */
+ snd_array_free(&codec->driver_pins);
+ restore_pincfgs(codec);
codec->num_pcms = 0;
codec->pcm_info = NULL;
codec->preset = NULL;
@@ -2175,6 +2315,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
hda_set_power_state(codec,
codec->afg ? codec->afg : codec->mfg,
AC_PWRST_D0);
+ restore_pincfgs(codec); /* restore all current pin configs */
hda_exec_init_verbs(codec);
if (codec->patch_ops.resume)
codec->patch_ops.resume(codec);
@@ -3355,8 +3496,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
if (ignore_nids && is_in_nid_list(nid, ignore_nids))
continue;
- def_conf = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
continue;
loc = get_defcfg_location(def_conf);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 09a332ada0c6..2ea628478a91 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -778,11 +778,14 @@ struct hda_codec {
unsigned short spdif_ctls; /* SPDIF control bits */
unsigned int spdif_in_enable; /* SPDIF input enable? */
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
struct snd_hwdep *hwdep; /* assigned hwdep device */
struct snd_array init_verbs; /* additional init verbs */
struct snd_array hints; /* additional hints */
+ struct snd_array user_pins; /* default pin configs to override */
#endif
/* misc flags */
@@ -855,6 +858,18 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec);
#define snd_hda_sequence_write_cache snd_hda_sequence_write
#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
*/
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 65745e96dc70..2c81a683e8f8 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -146,7 +146,7 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid
if (node->type == AC_WID_PIN) {
node->pin_caps = snd_hda_param_read(codec, node->nid, AC_PAR_PIN_CAP);
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) {
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index 4ae51dcb81af..c660383ef381 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -109,6 +109,7 @@ static void clear_hwdep_elements(struct hda_codec *codec)
for (i = 0; i < codec->hints.used; i++, head++)
kfree(*head);
snd_array_free(&codec->hints);
+ snd_array_free(&codec->user_pins);
}
static void hwdep_free(struct snd_hwdep *hwdep)
@@ -141,6 +142,7 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
snd_array_init(&codec->hints, sizeof(char *), 32);
+ snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16);
return 0;
}
@@ -316,6 +318,67 @@ static ssize_t hints_store(struct device *dev,
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;
+}
+
#define CODEC_ATTR_RW(type) \
__ATTR(type, 0644, type##_show, type##_store)
#define CODEC_ATTR_RO(type) \
@@ -333,6 +396,9 @@ static struct device_attribute codec_attrs[] = {
CODEC_ATTR_RW(modelname),
CODEC_ATTR_WO(init_verbs),
CODEC_ATTR_WO(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(clear),
};
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index b16802841468..0253cb93aa7f 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -1047,8 +1047,7 @@ static struct hda_amp_list ad1986a_loopbacks[] = {
static int is_jack_available(struct hda_codec *codec, hda_nid_t nid)
{
- unsigned int conf = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
+ unsigned int conf = snd_hda_codec_get_pincfg(codec, nid);
return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
}
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index f3ebe837f2d5..c921264bbd71 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -680,13 +680,13 @@ static int patch_cmi9880(struct hda_codec *codec)
struct auto_pin_cfg cfg;
/* collect pin default configuration */
- port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ port_e = snd_hda_codec_get_pincfg(codec, 0x0f);
+ port_f = snd_hda_codec_get_pincfg(codec, 0x10);
spec->front_panel = 1;
if (get_defcfg_connect(port_e) == 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_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ port_g = snd_hda_codec_get_pincfg(codec, 0x1f);
+ port_h = snd_hda_codec_get_pincfg(codec, 0x20);
spec->channel_modes = cmi9880_channel_modes;
/* no front panel */
if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE ||
@@ -703,8 +703,8 @@ static int patch_cmi9880(struct hda_codec *codec)
spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
} else {
spec->input_mux = &cmi9880_basic_mux;
- port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ port_spdifi = snd_hda_codec_get_pincfg(codec, 0x13);
+ port_spdifo = snd_hda_codec_get_pincfg(codec, 0x12);
if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE)
spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 5c9bb066a764..50ae8f33af5f 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -330,13 +330,6 @@ struct alc_spec {
/* for PLL fix */
hda_nid_t pll_nid;
unsigned int pll_coef_idx, pll_coef_bit;
-
-#ifdef SND_HDA_NEEDS_RESUME
-#define ALC_MAX_PINS 16
- unsigned int num_pins;
- hda_nid_t pin_nids[ALC_MAX_PINS];
- unsigned int pin_cfgs[ALC_MAX_PINS];
-#endif
};
/*
@@ -1010,8 +1003,7 @@ static void alc_subsystem_id(struct hda_codec *codec,
nid = 0x1d;
if (codec->vendor_id == 0x10ec0260)
nid = 0x17;
- ass = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
+ ass = snd_hda_codec_get_pincfg(codec, nid);
if (!(ass & 1) && !(ass & 0x100000))
return;
if ((ass >> 30) != 1) /* no physical connection */
@@ -1185,16 +1177,8 @@ static void alc_fix_pincfg(struct hda_codec *codec,
return;
cfg = pinfix[quirk->value];
- for (; cfg->nid; cfg++) {
- int i;
- u32 val = cfg->val;
- for (i = 0; i < 4; i++) {
- snd_hda_codec_write(codec, cfg->nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i,
- val & 0xff);
- val >>= 8;
- }
- }
+ for (; cfg->nid; cfg++)
+ snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
}
/*
@@ -3216,61 +3200,13 @@ static void alc_free(struct hda_codec *codec)
}
#ifdef SND_HDA_NEEDS_RESUME
-static void store_pin_configs(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t nid, end_nid;
-
- end_nid = codec->start_nid + codec->num_nodes;
- for (nid = codec->start_nid; nid < end_nid; nid++) {
- unsigned int wid_caps = get_wcaps(codec, nid);
- unsigned int wid_type =
- (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
- if (wid_type != AC_WID_PIN)
- continue;
- if (spec->num_pins >= ARRAY_SIZE(spec->pin_nids))
- break;
- spec->pin_nids[spec->num_pins] = nid;
- spec->pin_cfgs[spec->num_pins] =
- snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
- spec->num_pins++;
- }
-}
-
-static void resume_pin_configs(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < spec->num_pins; i++) {
- hda_nid_t pin_nid = spec->pin_nids[i];
- unsigned int pin_config = spec->pin_cfgs[i];
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
- pin_config & 0x000000ff);
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
- (pin_config & 0x0000ff00) >> 8);
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
- (pin_config & 0x00ff0000) >> 16);
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
- pin_config >> 24);
- }
-}
-
static int alc_resume(struct hda_codec *codec)
{
- resume_pin_configs(codec);
codec->patch_ops.init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
return 0;
}
-#else
-#define store_pin_configs(codec)
#endif
/*
@@ -4330,7 +4266,6 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0];
- store_pin_configs(codec);
return 1;
}
@@ -5809,7 +5744,6 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0];
- store_pin_configs(codec);
return 1;
}
@@ -10821,7 +10755,6 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
- store_pin_configs(codec);
return 1;
}
@@ -11994,7 +11927,6 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
- store_pin_configs(codec);
return 1;
}
@@ -12907,7 +12839,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (!spec->cap_mixer && !spec->no_analog)
set_capture_mixer(spec);
- store_pin_configs(codec);
return 1;
}
@@ -13958,7 +13889,6 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
set_capture_mixer(spec);
- store_pin_configs(codec);
return 1;
}
@@ -15060,7 +14990,6 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
- store_pin_configs(codec);
return 1;
}
@@ -16870,7 +16799,6 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
- store_pin_configs(codec);
return 1;
}
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index d00a211a813b..da48d8c0b295 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -229,7 +229,6 @@ struct sigmatel_spec {
/* pin widgets */
hda_nid_t *pin_nids;
unsigned int num_pins;
- unsigned int *pin_configs;
/* codec specific stuff */
struct hda_verb *init;
@@ -2272,101 +2271,19 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
{} /* terminator */
};
-static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
+static void stac92xx_set_config_regs(struct hda_codec *codec,
+ unsigned int *pincfgs)
{
int i;
struct sigmatel_spec *spec = codec->spec;
-
- kfree(spec->pin_configs);
- spec->pin_configs = kcalloc(spec->num_pins, sizeof(*spec->pin_configs),
- GFP_KERNEL);
- if (!spec->pin_configs)
- return -ENOMEM;
-
- for (i = 0; i < spec->num_pins; i++) {
- hda_nid_t nid = spec->pin_nids[i];
- unsigned int pin_cfg;
-
- if (!nid)
- continue;
- pin_cfg = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0x00);
- snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n",
- nid, pin_cfg);
- spec->pin_configs[i] = pin_cfg;
- }
-
- return 0;
-}
-static void stac92xx_set_config_reg(struct hda_codec *codec,
- hda_nid_t pin_nid, unsigned int pin_config)
-{
- int i;
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
- pin_config & 0x000000ff);
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
- (pin_config & 0x0000ff00) >> 8);
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
- (pin_config & 0x00ff0000) >> 16);
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
- pin_config >> 24);
- i = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT,
- 0x00);
- snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n",
- pin_nid, i);
-}
-
-static void stac92xx_set_config_regs(struct hda_codec *codec)
-{
- int i;
- struct sigmatel_spec *spec = codec->spec;
-
- if (!spec->pin_configs)
- return;
+ if (!pincfgs)
+ return;
for (i = 0; i < spec->num_pins; i++)
- if (spec->pin_nids[i] && spec->pin_configs[i])
- stac92xx_set_config_reg(codec, spec->pin_nids[i],
- spec->pin_configs[i]);
-}
-
-static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (!pins)
- return stac92xx_save_bios_config_regs(codec);
-
- kfree(spec->pin_configs);
- spec->pin_configs = kmemdup(pins,
- spec->num_pins * sizeof(*pins),
- GFP_KERNEL);
- if (!spec->pin_configs)
- return -ENOMEM;
-
- stac92xx_set_config_regs(codec);
- return 0;
-}
-
-static void stac_change_pin_config(struct hda_codec *codec, hda_nid_t nid,
- unsigned int cfg)
-{
- struct sigmatel_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < spec->num_pins; i++) {
- if (spec->pin_nids[i] == nid) {
- spec->pin_configs[i] = cfg;
- stac92xx_set_config_reg(codec, nid, cfg);
- break;
- }
- }
+ if (spec->pin_nids[i] && pincfgs[i])
+ snd_hda_codec_set_pincfg(codec, spec->pin_nids[i],
+ pincfgs[i]);
}
/*
@@ -2853,8 +2770,7 @@ static hda_nid_t check_mic_out_switch(struct hda_codec *codec)
mic_pin = AUTO_PIN_MIC;
for (;;) {
hda_nid_t nid = cfg->input_pins[mic_pin];
- def_conf = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
/* some laptops have an internal analog microphone
* which can't be used as a output */
if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
@@ -3426,11 +3342,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
unsigned int wcaps;
unsigned int def_conf;
- def_conf = snd_hda_codec_read(codec,
- spec->dmic_nids[i],
- 0,
- AC_VERB_GET_CONFIG_DEFAULT,
- 0);
+ def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]);
if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
continue;
@@ -3779,9 +3691,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) {
hda_nid_t pin = spec->autocfg.line_out_pins[i];
unsigned int defcfg;
- defcfg = snd_hda_codec_read(codec, pin, 0,
- AC_VERB_GET_CONFIG_DEFAULT,
- 0x00);
+ defcfg = snd_hda_codec_get_pincfg(codec, pin);
if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) {
unsigned int wcaps = get_wcaps(codec, pin);
wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
@@ -3885,8 +3795,7 @@ static int stac92xx_add_jack(struct hda_codec *codec,
#ifdef CONFIG_SND_JACK
struct sigmatel_spec *spec = codec->spec;
struct sigmatel_jack *jack;
- int def_conf = snd_hda_codec_read(codec, nid,
- 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ int def_conf = snd_hda_codec_get_pincfg(codec, nid);
int connectivity = get_defcfg_connect(def_conf);
char name[32];
@@ -4066,8 +3975,7 @@ static int stac92xx_init(struct hda_codec *codec)
pinctl);
}
}
- conf = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
+ conf = snd_hda_codec_get_pincfg(codec, nid);
if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
enable_pin_detect(codec, nid,
STAC_INSERT_EVENT);
@@ -4108,8 +4016,7 @@ static int stac92xx_init(struct hda_codec *codec)
stac_toggle_power_map(codec, nid, 1);
continue;
}
- def_conf = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
def_conf = get_defcfg_connect(def_conf);
/* skip any ports that don't have jacks since presence
* detection is useless */
@@ -4163,7 +4070,6 @@ static void stac92xx_free(struct hda_codec *codec)
if (! spec)
return;
- kfree(spec->pin_configs);
stac92xx_free_jacks(codec);
snd_array_free(&spec->events);
@@ -4474,7 +4380,6 @@ static int stac92xx_resume(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
- stac92xx_set_config_regs(codec);
stac92xx_init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
@@ -4523,16 +4428,11 @@ static int patch_stac9200(struct hda_codec *codec)
spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
stac9200_models,
stac9200_cfg_tbl);
- if (spec->board_config < 0) {
+ if (spec->board_config < 0)
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
- err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
+ else
+ stac92xx_set_config_regs(codec,
stac9200_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
spec->multiout.max_channels = 2;
spec->multiout.num_dacs = 1;
@@ -4600,17 +4500,12 @@ static int patch_stac925x(struct hda_codec *codec)
stac925x_models,
stac925x_cfg_tbl);
again:
- if (spec->board_config < 0) {
+ if (spec->board_config < 0)
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x,"
"using BIOS defaults\n");
- err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
+ else
+ stac92xx_set_config_regs(codec,
stac925x_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
spec->multiout.max_channels = 2;
spec->multiout.num_dacs = 1;
@@ -4688,17 +4583,12 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
stac92hd73xx_models,
stac92hd73xx_cfg_tbl);
again:
- if (spec->board_config < 0) {
+ if (spec->board_config < 0)
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD73XX, using BIOS defaults\n");
- err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
+ else
+ stac92xx_set_config_regs(codec,
stac92hd73xx_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
num_dacs = snd_hda_get_connections(codec, 0x0a,
conn, STAC92HD73_DAC_COUNT + 2) - 1;
@@ -4758,18 +4648,18 @@ again:
spec->init = dell_m6_core_init;
switch (spec->board_config) {
case STAC_DELL_M6_AMIC: /* Analog Mics */
- stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
+ snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170);
spec->num_dmics = 0;
spec->private_dimux.num_items = 1;
break;
case STAC_DELL_M6_DMIC: /* Digital Mics */
- stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
+ snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160);
spec->num_dmics = 1;
spec->private_dimux.num_items = 2;
break;
case STAC_DELL_M6_BOTH: /* Both */
- stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
- stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
+ snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170);
+ snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160);
spec->num_dmics = 1;
spec->private_dimux.num_items = 2;
break;
@@ -4865,17 +4755,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
stac92hd83xxx_models,
stac92hd83xxx_cfg_tbl);
again:
- if (spec->board_config < 0) {
+ if (spec->board_config < 0)
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD83XXX, using BIOS defaults\n");
- err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
+ else
+ stac92xx_set_config_regs(codec,
stac92hd83xxx_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
switch (codec->vendor_id) {
case 0x111d7604:
@@ -4945,6 +4830,16 @@ static struct hda_input_mux stac92hd71bxx_dmux_amixer = {
}
};
+/* get the pin connection (fixed, none, etc) */
+static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ unsigned int cfg;
+
+ cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]);
+ return get_defcfg_connect(cfg);
+}
+
static int stac92hd71bxx_connected_ports(struct hda_codec *codec,
hda_nid_t *nids, int num_nids)
{
@@ -4958,7 +4853,7 @@ static int stac92hd71bxx_connected_ports(struct hda_codec *codec,
break;
if (idx >= spec->num_pins)
break;
- def_conf = get_defcfg_connect(spec->pin_configs[idx]);
+ def_conf = stac_get_defcfg_connect(codec, idx);
if (def_conf == AC_JACK_PORT_NONE)
break;
}
@@ -4978,13 +4873,13 @@ static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec,
return 0;
/* dig1pin case */
- if (get_defcfg_connect(spec->pin_configs[idx+1]) != AC_JACK_PORT_NONE)
+ if (stac_get_defcfg_connect(codec, idx + 1) != AC_JACK_PORT_NONE)
return 2;
/* dig0pin + dig2pin case */
- if (get_defcfg_connect(spec->pin_configs[idx+2]) != AC_JACK_PORT_NONE)
+ if (stac_get_defcfg_connect(codec, idx + 2) != AC_JACK_PORT_NONE)
return 2;
- if (get_defcfg_connect(spec->pin_configs[idx]) != AC_JACK_PORT_NONE)
+ if (stac_get_defcfg_connect(codec, idx) != AC_JACK_PORT_NONE)
return 1;
else
return 0;
@@ -5023,17 +4918,12 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
stac92hd71bxx_models,
stac92hd71bxx_cfg_tbl);
again:
- if (spec->board_config < 0) {
+ if (spec->board_config < 0)
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD71BXX, using BIOS defaults\n");
- err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
+ else
+ stac92xx_set_config_regs(codec,
stac92hd71bxx_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
if (spec->board_config > STAC_92HD71BXX_REF) {
/* GPIO0 = EAPD */
@@ -5097,8 +4987,8 @@ again:
/* disable VSW */
spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
unmute_init++;
- stac_change_pin_config(codec, 0x0f, 0x40f000f0);
- stac_change_pin_config(codec, 0x19, 0x40f000f3);
+ snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);
+ snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0;
spec->num_dmics = stac92hd71bxx_connected_ports(codec,
stac92hd71bxx_dmic_nids,
@@ -5147,7 +5037,7 @@ again:
switch (spec->board_config) {
case STAC_HP_M4:
/* enable internal microphone */
- stac_change_pin_config(codec, 0x0e, 0x01813040);
+ snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040);
stac92xx_auto_set_pinctl(codec, 0x0e,
AC_PINCTL_IN_EN | AC_PINCTL_VREF_80);
/* fallthru */
@@ -5163,7 +5053,7 @@ again:
spec->num_dmuxes = 0;
break;
case STAC_HP_DV5:
- stac_change_pin_config(codec, 0x0d, 0x90170010);
+ snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010);
stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN);
break;
};
@@ -5247,17 +5137,12 @@ static int patch_stac922x(struct hda_codec *codec)
}
again:
- if (spec->board_config < 0) {
+ if (spec->board_config < 0)
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
"using BIOS defaults\n");
- err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
+ else
+ stac92xx_set_config_regs(codec,
stac922x_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
spec->adc_nids = stac922x_adc_nids;
spec->mux_nids = stac922x_mux_nids;
@@ -5315,17 +5200,12 @@ static int patch_stac927x(struct hda_codec *codec)
stac927x_models,
stac927x_cfg_tbl);
again:
- if (spec->board_config < 0) {
+ if (spec->board_config < 0)
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
"STAC927x, using BIOS defaults\n");
- err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
+ else
+ stac92xx_set_config_regs(codec,
stac927x_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
spec->digbeep_nid = 0x23;
spec->adc_nids = stac927x_adc_nids;
@@ -5354,15 +5234,15 @@ static int patch_stac927x(struct hda_codec *codec)
case 0x10280209:
case 0x1028022e:
/* correct the device field to SPDIF out */
- stac_change_pin_config(codec, 0x21, 0x01442070);
+ snd_hda_codec_set_pincfg(codec, 0x21, 0x01442070);
break;
};
/* configure the analog microphone on some laptops */
- stac_change_pin_config(codec, 0x0c, 0x90a79130);
+ snd_hda_codec_set_pincfg(codec, 0x0c, 0x90a79130);
/* correct the front output jack as a hp out */
- stac_change_pin_config(codec, 0x0f, 0x0227011f);
+ snd_hda_codec_set_pincfg(codec, 0x0f, 0x0227011f);
/* correct the front input jack as a mic */
- stac_change_pin_config(codec, 0x0e, 0x02a79130);
+ snd_hda_codec_set_pincfg(codec, 0x0e, 0x02a79130);
/* fallthru */
case STAC_DELL_3ST:
/* GPIO2 High = Enable EAPD */
@@ -5447,16 +5327,11 @@ static int patch_stac9205(struct hda_codec *codec)
stac9205_models,
stac9205_cfg_tbl);
again:
- if (spec->board_config < 0) {
+ if (spec->board_config < 0)
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
- err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
+ else
+ stac92xx_set_config_regs(codec,
stac9205_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
- }
spec->digbeep_nid = 0x23;
spec->adc_nids = stac9205_adc_nids;
@@ -5484,8 +5359,8 @@ static int patch_stac9205(struct hda_codec *codec)
switch (spec->board_config){
case STAC_9205_DELL_M43:
/* Enable SPDIF in/out */
- stac_change_pin_config(codec, 0x1f, 0x01441030);
- stac_change_pin_config(codec, 0x20, 0x1c410030);
+ snd_hda_codec_set_pincfg(codec, 0x1f, 0x01441030);
+ snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030);
/* Enable unsol response for GPIO4/Dock HP connection */
err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 639b2ff510a6..b25a5cc637d6 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -1308,16 +1308,13 @@ static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
unsigned int def_conf;
unsigned char seqassoc;
- def_conf = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
seqassoc = (unsigned char) get_defcfg_association(def_conf);
seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) {
if (seqassoc == 0xff) {
def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
- def_conf >> 24);
+ snd_hda_codec_set_pincfg(codec, nid, def_conf);
}
}