STAC_92HD73XX_AUTO,
STAC_92HD73XX_NO_JD, /* no jack-detection */
STAC_92HD73XX_REF,
+ STAC_92HD73XX_INTEL,
STAC_DELL_M6_AMIC,
STAC_DELL_M6_DMIC,
STAC_DELL_M6_BOTH,
static unsigned int stac92xx_vref_set(struct hda_codec *codec,
hda_nid_t nid, unsigned int new_vref)
{
- unsigned int error;
+ int error;
unsigned int pincfg;
pincfg = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
return vref;
}
-static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int new_vref;
- unsigned int error;
-
- if (ucontrol->value.enumerated.item[0] == 0)
- new_vref = AC_PINCTL_VREF_80;
- else if (ucontrol->value.enumerated.item[0] == 1)
- new_vref = AC_PINCTL_VREF_GRD;
- else
- new_vref = AC_PINCTL_VREF_HIZ;
-
- if (new_vref != stac92xx_vref_get(codec, kcontrol->private_value)) {
- error = stac92xx_vref_set(codec,
- kcontrol->private_value, new_vref);
- return error;
- }
-
- return 0;
-}
-
-static int stac92xx_dc_bias_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int vref = stac92xx_vref_get(codec, kcontrol->private_value);
- if (vref == AC_PINCTL_VREF_80)
- ucontrol->value.enumerated.item[0] = 0;
- else if (vref == AC_PINCTL_VREF_GRD)
- ucontrol->value.enumerated.item[0] = 1;
- else if (vref == AC_PINCTL_VREF_HIZ)
- ucontrol->value.enumerated.item[0] = 2;
-
- return 0;
-}
-
-static int stac92xx_dc_bias_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- static char *texts[] = {
- "Mic In", "Line In", "Line Out"
- };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->value.enumerated.items = 3;
- uinfo->count = 1;
- if (uinfo->value.enumerated.item >= 3)
- uinfo->value.enumerated.item = 2;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
-
- return 0;
-}
-
static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
[STAC_92HD73XX_AUTO] = "auto",
[STAC_92HD73XX_NO_JD] = "no-jd",
[STAC_92HD73XX_REF] = "ref",
+ [STAC_92HD73XX_INTEL] = "intel",
[STAC_DELL_M6_AMIC] = "dell-m6-amic",
[STAC_DELL_M6_DMIC] = "dell-m6-dmic",
[STAC_DELL_M6_BOTH] = "dell-m6",
"DFI LanParty", STAC_92HD73XX_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
"DFI LanParty", STAC_92HD73XX_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5002,
+ "Intel DG45ID", STAC_92HD73XX_INTEL),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5003,
+ "Intel DG45FC", STAC_92HD73XX_INTEL),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
"Dell Studio 1535", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
"Dell Studio 1537", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a0,
"Dell Studio 17", STAC_DELL_M6_DMIC),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02be,
+ "Dell Studio 1555", STAC_DELL_M6_DMIC),
{} /* terminator */
};
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0227, "Dell Vostro 1400 ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022e, "Dell ", STAC_DELL_BIOS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_3ST),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0242, "Dell ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0243, "Dell ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS),
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_9205_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30,
+ "SigmaTel", STAC_9205_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
"DFI LanParty", STAC_9205_REF),
/* Dell */
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
"Dell Vostro 1500", STAC_9205_DELL_M42),
/* Gateway */
+ SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD),
SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD),
{} /* terminator */
};
return 0;
}
-static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid)
+static unsigned int stac92xx_get_default_vref(struct hda_codec *codec,
+ hda_nid_t nid)
{
unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
return 1;
}
-#define stac92xx_io_switch_info snd_ctl_boolean_mono_info
+static int stac92xx_dc_bias_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ int i;
+ static char *texts[] = {
+ "Mic In", "Line In", "Line Out"
+ };
+
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+ hda_nid_t nid = kcontrol->private_value;
+
+ if (nid == spec->mic_switch || nid == spec->line_switch)
+ i = 3;
+ else
+ i = 2;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->value.enumerated.items = i;
+ uinfo->count = 1;
+ if (uinfo->value.enumerated.item >= i)
+ uinfo->value.enumerated.item = i-1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+
+ return 0;
+}
+
+static int stac92xx_dc_bias_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = kcontrol->private_value;
+ unsigned int vref = stac92xx_vref_get(codec, nid);
+
+ if (vref == stac92xx_get_default_vref(codec, nid))
+ ucontrol->value.enumerated.item[0] = 0;
+ else if (vref == AC_PINCTL_VREF_GRD)
+ ucontrol->value.enumerated.item[0] = 1;
+ else if (vref == AC_PINCTL_VREF_HIZ)
+ ucontrol->value.enumerated.item[0] = 2;
+
+ return 0;
+}
+
+static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int new_vref = 0;
+ int error;
+ hda_nid_t nid = kcontrol->private_value;
+
+ if (ucontrol->value.enumerated.item[0] == 0)
+ new_vref = stac92xx_get_default_vref(codec, nid);
+ else if (ucontrol->value.enumerated.item[0] == 1)
+ new_vref = AC_PINCTL_VREF_GRD;
+ else if (ucontrol->value.enumerated.item[0] == 2)
+ new_vref = AC_PINCTL_VREF_HIZ;
+ else
+ return 0;
+
+ if (new_vref != stac92xx_vref_get(codec, nid)) {
+ error = stac92xx_vref_set(codec, nid, new_vref);
+ return error;
+ }
+
+ return 0;
+}
+
+static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static char *texts[2];
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+
+ if (kcontrol->private_value == spec->line_switch)
+ texts[0] = "Line In";
+ else
+ texts[0] = "Mic In";
+ texts[1] = "Line Out";
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->value.enumerated.items = 2;
+ uinfo->count = 1;
+
+ if (uinfo->value.enumerated.item >= 2)
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+
+ return 0;
+}
static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
- int io_idx = kcontrol-> private_value & 0xff;
+ hda_nid_t nid = kcontrol->private_value;
+ int io_idx = (nid == spec->mic_switch) ? 1 : 0;
- ucontrol->value.integer.value[0] = spec->io_switch[io_idx];
+ ucontrol->value.enumerated.item[0] = spec->io_switch[io_idx];
return 0;
}
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
- hda_nid_t nid = kcontrol->private_value >> 8;
- int io_idx = kcontrol-> private_value & 0xff;
- unsigned short val = !!ucontrol->value.integer.value[0];
+ hda_nid_t nid = kcontrol->private_value;
+ int io_idx = (nid == spec->mic_switch) ? 1 : 0;
+ unsigned short val = !!ucontrol->value.enumerated.item[0];
spec->io_switch[io_idx] = val;
else {
unsigned int pinctl = AC_PINCTL_IN_EN;
if (io_idx) /* set VREF for mic */
- pinctl |= stac92xx_get_vref(codec, nid);
+ pinctl |= stac92xx_get_default_vref(codec, nid);
stac92xx_auto_set_pinctl(codec, nid, pinctl);
}
.put = stac92xx_mux_enum_put,
};
+static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
+ hda_nid_t nid, int idx)
+{
+ int def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ int control = 0;
+ struct sigmatel_spec *spec = codec->spec;
+ char name[22];
+
+ if (!((get_defcfg_connect(def_conf)) & AC_JACK_PORT_FIXED)) {
+ if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
+ && nid == spec->line_switch)
+ control = STAC_CTL_WIDGET_IO_SWITCH;
+ else if (snd_hda_query_pin_caps(codec, nid)
+ & (AC_PINCAP_VREF_GRD << AC_PINCAP_VREF_SHIFT))
+ control = STAC_CTL_WIDGET_DC_BIAS;
+ else if (nid == spec->mic_switch)
+ control = STAC_CTL_WIDGET_IO_SWITCH;
+ }
+
+ if (control) {
+ strcpy(name, auto_pin_cfg_labels[idx]);
+ return stac92xx_add_control(codec->spec, control,
+ strcat(name, " Jack Mode"), nid);
+ }
+
+ return 0;
+}
+
static int stac92xx_add_input_source(struct sigmatel_spec *spec)
{
struct snd_kcontrol_new *knew;
const struct auto_pin_cfg *cfg)
{
struct sigmatel_spec *spec = codec->spec;
+ hda_nid_t nid;
int err;
+ int idx;
err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins,
spec->multiout.dac_nids,
return err;
}
- if (spec->line_switch) {
- err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH,
- "Line In as Output Switch",
- spec->line_switch << 8);
- if (err < 0)
- return err;
- }
-
- if (spec->mic_switch) {
- err = stac92xx_add_control(spec, STAC_CTL_WIDGET_DC_BIAS,
- "Mic Jack Mode",
- spec->mic_switch);
- if (err < 0)
- return err;
+ for (idx = AUTO_PIN_MIC; idx <= AUTO_PIN_FRONT_LINE; idx++) {
+ nid = cfg->input_pins[idx];
+ if (nid) {
+ err = stac92xx_add_jack_mode_control(codec, nid, idx);
+ if (err < 0)
+ return err;
+ }
}
return 0;
AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
}
-#ifdef CONFIG_SND_JACK
+#ifdef CONFIG_SND_HDA_INPUT_JACK
static void stac92xx_free_jack_priv(struct snd_jack *jack)
{
struct sigmatel_jack *jacks = jack->private_data;
static int stac92xx_add_jack(struct hda_codec *codec,
hda_nid_t nid, int type)
{
-#ifdef CONFIG_SND_JACK
+#ifdef CONFIG_SND_HDA_INPUT_JACK
struct sigmatel_spec *spec = codec->spec;
struct sigmatel_jack *jack;
int def_conf = snd_hda_codec_get_pincfg(codec, nid);
jack->nid = nid;
jack->type = type;
- sprintf(name, "%s at %s %s Jack",
+ snprintf(name, sizeof(name), "%s at %s %s Jack",
snd_hda_get_jack_type(def_conf),
snd_hda_get_jack_connectivity(def_conf),
snd_hda_get_jack_location(def_conf));
unsigned int pinctl, conf;
if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
/* for mic pins, force to initialize */
- pinctl = stac92xx_get_vref(codec, nid);
+ pinctl = stac92xx_get_default_vref(codec, nid);
pinctl |= AC_PINCTL_IN_EN;
stac92xx_auto_set_pinctl(codec, nid, pinctl);
} else {
static void stac92xx_free_jacks(struct hda_codec *codec)
{
-#ifdef CONFIG_SND_JACK
+#ifdef CONFIG_SND_HDA_INPUT_JACK
/* free jack instances manually when clearing/reconfiguring */
struct sigmatel_spec *spec = codec->spec;
if (!codec->bus->shutdown && spec->jacks.list) {
if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP)
snd_hda_sequence_write_cache(codec, unmute_init);
+ /* Some HP machines seem to have unstable codec communications
+ * especially with ATI fglrx driver. For recovering from the
+ * CORB/RIRB stall, allow the BUS reset and keep always sync
+ */
+ if (spec->board_config == STAC_HP_DV5) {
+ codec->bus->sync_write = 1;
+ codec->bus->allow_bus_reset = 1;
+ }
+
spec->aloopback_ctl = stac92hd71bxx_loopback;
spec->aloopback_mask = 0x50;
spec->aloopback_shift = 0;
/* GPIO2 High = Enable EAPD */
spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04;
spec->gpio_data = 0x04;
+ switch (codec->subsystem_id) {
+ case 0x1028022f:
+ /* correct EAPD to be GPIO0 */
+ spec->eapd_mask = spec->gpio_mask = 0x01;
+ spec->gpio_dir = spec->gpio_data = 0x01;
+ break;
+ };
spec->dmic_nids = stac927x_dmic_nids;
spec->num_dmics = STAC927X_NUM_DMICS;
};
static struct snd_pci_quirk stac9872_cfg_tbl[] = {
+ SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0,
+ "Sony VAIO F/S", STAC_9872_VAIO),
{} /* terminator */
};
if (spec == NULL)
return -ENOMEM;
codec->spec = spec;
+ spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
+ spec->pin_nids = stac9872_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
stac9872_models,
stac92xx_set_config_regs(codec,
stac9872_brd_tbl[spec->board_config]);
- spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
- spec->pin_nids = stac9872_pin_nids;
spec->multiout.dac_nids = spec->dac_nids;
spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids);
spec->adc_nids = stac9872_adc_nids;
{ .id = 0x83847661, .name = "CXD9872RD/K", .patch = patch_stac9872 },
{ .id = 0x83847662, .name = "STAC9872AK", .patch = patch_stac9872 },
{ .id = 0x83847664, .name = "CXD9872AKD", .patch = patch_stac9872 },
+ { .id = 0x83847698, .name = "STAC9205", .patch = patch_stac9205 },
{ .id = 0x838476a0, .name = "STAC9205", .patch = patch_stac9205 },
{ .id = 0x838476a1, .name = "STAC9205D", .patch = patch_stac9205 },
{ .id = 0x838476a2, .name = "STAC9204", .patch = patch_stac9205 },