From 3be141494a080a9189b51fa78154c975ad8d9806 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 20 Feb 2009 14:11:16 +0100 Subject: [PATCH 1/9] ALSA: hda - Add generic pincfg initialization Added the generic pincfg cache and save/restore functions. Also introduced the pin-overriding via hwdep sysfs. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 151 +++++++++++++++++++++++++++++++++++--- sound/pci/hda/hda_codec.h | 15 ++++ sound/pci/hda/hda_hwdep.c | 66 +++++++++++++++++ 3 files changed, 223 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 98884bc8f35f..6fa871f66a72 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -682,11 +682,132 @@ 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; + + pin = look_up_pincfg(codec, list, nid); + if (!pin) { + pin = snd_array_new(list); + if (!pin) + return -ENOMEM; + pin->nid = nid; + } + pin->cfg = 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->cur_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; + + pin = look_up_pincfg(codec, &codec->cur_pins, nid); + if (pin) + return pin->cfg; +#ifdef CONFIG_SND_HDA_HWDEP + pin = look_up_pincfg(codec, &codec->override_pins, nid); + if (pin) + return pin->cfg; +#endif + 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 cur_pins and override_pins, then call restore_pincfg + * so that only the values in init_pins are restored + */ + snd_array_free(&codec->cur_pins); +#ifdef CONFIG_SND_HDA_HWDEP + snd_array_free(&codec->override_pins); +#endif + restore_pincfgs(codec); + snd_array_free(&codec->init_pins); +} + /* * codec destructor */ @@ -694,6 +815,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 +873,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->cur_pins, sizeof(struct hda_pincfg), 16); if (codec->bus->modelname) { codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); if (!codec->modelname) { @@ -787,15 +911,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 +935,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 +949,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 +1463,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 cur_pins so that init_pins + override_pins are restored */ + snd_array_free(&codec->cur_pins); + restore_pincfgs(codec); codec->num_pcms = 0; codec->pcm_info = NULL; codec->preset = NULL; @@ -2175,6 +2307,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); diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 09a332ada0c6..6d01a8058f0a 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 cur_pins; /* current pin configurations */ #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 override_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_hwdep.c b/sound/pci/hda/hda_hwdep.c index 4ae51dcb81af..71039a6dec28 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->override_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->override_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 override_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->override_pins, buf); +} + +static ssize_t cur_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->cur_pins, buf); +} + +#define MAX_PIN_CONFIGS 32 + +static ssize_t override_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->override_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(override_pin_configs), + CODEC_ATTR_RO(cur_pin_configs), CODEC_ATTR_WO(reconfig), CODEC_ATTR_WO(clear), }; From 0e8a21b59d48a63f45b3e6d2aca7fb91c5aec882 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 20 Feb 2009 14:13:06 +0100 Subject: [PATCH 2/9] ALSA: hda - Remove realtek codec-specific pin save/restore functions Now it's done in the common code. Also use the common access functions for pin defaults. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 78 ++--------------------------------- 1 file changed, 3 insertions(+), 75 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 169b3837af52..d7f255e3b916 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -329,13 +329,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 }; /* @@ -1009,8 +1002,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 */ @@ -1184,16 +1176,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); } /* @@ -3215,61 +3199,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 /* @@ -4329,7 +4265,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; } @@ -5693,7 +5628,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; } @@ -10688,7 +10622,6 @@ static int alc262_parse_auto_config(struct hda_codec *codec) if (err < 0) return err; - store_pin_configs(codec); return 1; } @@ -11861,7 +11794,6 @@ static int alc268_parse_auto_config(struct hda_codec *codec) if (err < 0) return err; - store_pin_configs(codec); return 1; } @@ -12774,7 +12706,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; } @@ -13825,7 +13756,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; } @@ -14927,7 +14857,6 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) if (err < 0) return err; - store_pin_configs(codec); return 1; } @@ -16737,7 +16666,6 @@ static int alc662_parse_auto_config(struct hda_codec *codec) if (err < 0) return err; - store_pin_configs(codec); return 1; } From 330ee9957910826a072c2ad5d4045182335f9963 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 20 Feb 2009 14:33:36 +0100 Subject: [PATCH 3/9] ALSA: hda - Remove IDT codec-specific pin save/restore functions Removed its own save/restore functions and replaced with the common code. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 255 +++++++++------------------------ 1 file changed, 65 insertions(+), 190 deletions(-) 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) -{ - 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) +static void stac92xx_set_config_regs(struct hda_codec *codec, + unsigned int *pincfgs) { 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 @@ static int patch_stac92hd73xx(struct hda_codec *codec) 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 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) /* 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 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) 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 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) 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); From 2f334f92cfb44d17b9f24a43f8998cca03f9a3dd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 20 Feb 2009 14:37:42 +0100 Subject: [PATCH 4/9] ALSA: hda - Remove codec-specific pin save/restore functions Replace the accessor to pin defaults with the common code for caching. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 3 +-- sound/pci/hda/patch_cmedia.c | 12 ++++++------ sound/pci/hda/patch_via.c | 7 ++----- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2c58d7b05aba..53d0edaf04c7 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_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); } } From f1085c4f319f1e43c95718045a235f276cc4b615 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 20 Feb 2009 14:50:35 +0100 Subject: [PATCH 5/9] ALSA: hda - Update documentation for pincfg sysfs entries Added the brief descriptions of new sysfs entries for pint default config values. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio.txt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index 99f7fbbe3e67..9c51e104546f 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -365,10 +365,22 @@ modelname:: to this file. init_verbs:: 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. hints:: Shows hint strings for codec parsers for any use. Right now it's not used. +init_pin_configs:: + Shows the initial pin default config values set by BIOS. +override_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. +cur_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. reconfig:: Triggers the codec re-configuration. When any value is written to this file, the driver re-initialize and parses the codec tree From c17a1abae2f29047a0f57324240b01609489261b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Feb 2009 09:28:12 +0100 Subject: [PATCH 6/9] ALSA: hda - Use snd_hda_codec_get_pincfg() in the rest places Replace with snd_hda_codec_get_pincfg() in the places where available. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 3 +-- sound/pci/hda/hda_generic.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 6fa871f66a72..8ec2dfca9a6c 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3488,8 +3488,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_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) { From 346ff70fdbe9093947b9494fe714c89cafcceade Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Feb 2009 09:42:57 +0100 Subject: [PATCH 7/9] ALSA: hda - Rename {override,cur}_pin with {user,driver}_pin Rename from override_pin and cur_pin with user_pin and driver_pin, respectively, to be a bit more intuitive. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio.txt | 12 +++++----- sound/pci/hda/hda_codec.c | 18 +++++++-------- sound/pci/hda/hda_codec.h | 4 ++-- sound/pci/hda/hda_hwdep.c | 32 +++++++++++++-------------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index 9c51e104546f..f590850c149f 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -371,16 +371,16 @@ hints:: not used. init_pin_configs:: Shows the initial pin default config values set by BIOS. -override_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. -cur_pin_configs:: +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. reconfig:: Triggers the codec re-configuration. When any value is written to this file, the driver re-initialize and parses the codec tree diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 8ec2dfca9a6c..df9453d0122e 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -755,7 +755,7 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, int snd_hda_codec_set_pincfg(struct hda_codec *codec, hda_nid_t nid, unsigned int cfg) { - return snd_hda_add_pincfg(codec, &codec->cur_pins, nid, cfg); + return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg); } EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg); @@ -764,11 +764,11 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid) { struct hda_pincfg *pin; - pin = look_up_pincfg(codec, &codec->cur_pins, nid); + pin = look_up_pincfg(codec, &codec->driver_pins, nid); if (pin) return pin->cfg; #ifdef CONFIG_SND_HDA_HWDEP - pin = look_up_pincfg(codec, &codec->override_pins, nid); + pin = look_up_pincfg(codec, &codec->user_pins, nid); if (pin) return pin->cfg; #endif @@ -797,12 +797,12 @@ 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 cur_pins and override_pins, then call restore_pincfg + /* 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->cur_pins); + snd_array_free(&codec->driver_pins); #ifdef CONFIG_SND_HDA_HWDEP - snd_array_free(&codec->override_pins); + snd_array_free(&codec->user_pins); #endif restore_pincfgs(codec); snd_array_free(&codec->init_pins); @@ -874,7 +874,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr 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->cur_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) { @@ -1463,8 +1463,8 @@ 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 cur_pins so that init_pins + override_pins are restored */ - snd_array_free(&codec->cur_pins); + /* 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; diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 6d01a8058f0a..2ea628478a91 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -779,13 +779,13 @@ struct hda_codec { 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 cur_pins; /* current 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 override_pins; /* default pin configs to override */ + struct snd_array user_pins; /* default pin configs to override */ #endif /* misc flags */ diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 71039a6dec28..c660383ef381 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c @@ -109,7 +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->override_pins); + snd_array_free(&codec->user_pins); } static void hwdep_free(struct snd_hwdep *hwdep) @@ -142,7 +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->override_pins, sizeof(struct hda_pincfg), 16); + snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); return 0; } @@ -340,29 +340,29 @@ static ssize_t init_pin_configs_show(struct device *dev, return pin_configs_show(codec, &codec->init_pins, buf); } -static ssize_t override_pin_configs_show(struct device *dev, - struct device_attribute *attr, - char *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->override_pins, buf); + return pin_configs_show(codec, &codec->user_pins, buf); } -static ssize_t cur_pin_configs_show(struct device *dev, - struct device_attribute *attr, - char *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->cur_pins, buf); + return pin_configs_show(codec, &codec->driver_pins, buf); } #define MAX_PIN_CONFIGS 32 -static ssize_t override_pin_configs_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +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; @@ -373,7 +373,7 @@ static ssize_t override_pin_configs_store(struct device *dev, return -EINVAL; if (!nid) return -EINVAL; - err = snd_hda_add_pincfg(codec, &codec->override_pins, nid, cfg); + err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); if (err < 0) return err; return count; @@ -397,8 +397,8 @@ static struct device_attribute codec_attrs[] = { CODEC_ATTR_WO(init_verbs), CODEC_ATTR_WO(hints), CODEC_ATTR_RO(init_pin_configs), - CODEC_ATTR_RW(override_pin_configs), - CODEC_ATTR_RO(cur_pin_configs), + CODEC_ATTR_RW(user_pin_configs), + CODEC_ATTR_RO(driver_pin_configs), CODEC_ATTR_WO(reconfig), CODEC_ATTR_WO(clear), }; From 5e7b8e0d87091ae21b291588817b5359a5e00795 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Feb 2009 09:45:59 +0100 Subject: [PATCH 8/9] ALSA: hda - Make user_pin overriding the driver setup Make user_pin overriding even the driver pincfg, e.g. the static / fixed pin config table in patch_sigmatel.c. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio.txt | 3 ++- sound/pci/hda/hda_codec.c | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index f590850c149f..a4e5ef87af6b 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -380,7 +380,8 @@ 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. + the next reconfiguration time. Note that this config will override + even the driver pin configs, too. reconfig:: Triggers the codec re-configuration. When any value is written to this file, the driver re-initialize and parses the codec tree diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index df9453d0122e..a13480fa8e74 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -739,7 +739,9 @@ 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); @@ -748,7 +750,13 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, pin->nid = nid; } pin->cfg = cfg; - set_pincfg(codec, nid, 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; } @@ -764,14 +772,14 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid) { struct hda_pincfg *pin; - pin = look_up_pincfg(codec, &codec->driver_pins, nid); - if (pin) - return pin->cfg; #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; From 39c2871eeaeeddcbecee29ec905ec528a057ca52 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Feb 2009 14:14:51 +0100 Subject: [PATCH 9/9] ALSA: hda - Add an example about pin reconfiguration Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index a4e5ef87af6b..99958be7b454 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -391,6 +391,14 @@ clear:: Resets the codec, removes the mixer elements and PCM stuff of the 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 ~~~~~~~~~~~~