enum {
STAC_9205_REF,
+ STAC_M43xx,
STAC_9205_MODELS
};
0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x14, 0x16, 0x17, 0x18,
0x21, 0x22,
-
};
static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol,
};
static struct snd_kcontrol_new stac925x_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Source",
};
static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
- ref9205_pin_configs,
+ [STAC_REF] = ref9205_pin_configs,
+ [STAC_M43xx] = NULL,
};
static const char *stac9205_models[STAC_9205_MODELS] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_9205_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01f8,
+ "Dell Precision", STAC_M43xx),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01ff,
+ "Dell Precision", STAC_M43xx),
{} /* terminator */
};
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;
- unsigned int pin_cfg;
- if (! spec->pin_nids || ! spec->pin_configs)
- return;
+ if (!spec->pin_configs)
+ return;
- for (i = 0; i < spec->num_pins; i++) {
- snd_hda_codec_write(codec, spec->pin_nids[i], 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
- spec->pin_configs[i] & 0x000000ff);
- snd_hda_codec_write(codec, spec->pin_nids[i], 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
- (spec->pin_configs[i] & 0x0000ff00) >> 8);
- snd_hda_codec_write(codec, spec->pin_nids[i], 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
- (spec->pin_configs[i] & 0x00ff0000) >> 16);
- snd_hda_codec_write(codec, spec->pin_nids[i], 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
- spec->pin_configs[i] >> 24);
- pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
- AC_VERB_GET_CONFIG_DEFAULT,
- 0x00);
- snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);
- }
+ for (i = 0; i < spec->num_pins; i++)
+ stac92xx_set_config_reg(codec, spec->pin_nids[i],
+ spec->pin_configs[i]);
}
-static void stac92xx_enable_eapd(struct hda_codec *codec)
+static void stac92xx_enable_gpio_mask(struct hda_codec *codec,
+ int gpio_mask, int gpio_data)
{
- /* Configure GPIO0 as output */
+ /* Configure GPIOx as output */
snd_hda_codec_write(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_DIRECTION, 0x00000001);
- /* Configure GPIO0 as CMOS */
+ AC_VERB_SET_GPIO_DIRECTION, gpio_mask);
+ /* Configure GPIOx as CMOS */
snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000);
- /* Assert GPIO0 high */
+ /* Assert GPIOx */
snd_hda_codec_write(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_DATA, 0x00000001);
- /* Enable GPIO0 */
+ AC_VERB_SET_GPIO_DATA, gpio_data);
+ /* Enable GPIOx */
snd_hda_codec_write(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_MASK, 0x00000001);
+ AC_VERB_SET_GPIO_MASK, gpio_mask);
}
/*
* and 9202/925x. For those, dac_nids[] must be hard-coded.
*/
static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
- const struct auto_pin_cfg *cfg)
+ struct auto_pin_cfg *cfg)
{
struct sigmatel_spec *spec = codec->spec;
int i, j, conn_len = 0;
}
if (j == conn_len) {
+ if (spec->multiout.num_dacs > 0) {
+ /* we have already working output pins,
+ * so let's drop the broken ones again
+ */
+ cfg->line_outs = spec->multiout.num_dacs;
+ break;
+ }
/* error out, no available DAC found */
snd_printk(KERN_ERR
"%s: No available DAC for pin 0x%x\n",
continue;
add_spec_dacs(spec, nid);
}
-
+ for (i = 0; i < cfg->line_outs; i++) {
+ nid = snd_hda_codec_read(codec, cfg->line_out_pins[i], 0,
+ AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
+ if (check_in_dac_nids(spec, nid))
+ nid = 0;
+ if (! nid)
+ continue;
+ add_spec_dacs(spec, nid);
+ }
for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) {
static const char *pfxs[] = {
"Speaker", "External Speaker", "Speaker2",
return -ENOMEM;
codec->spec = spec;
- spec->num_pins = 8;
+ spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
spec->pin_nids = stac9200_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
stac9200_models,
return -ENOMEM;
codec->spec = spec;
- spec->num_pins = 8;
+ spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
spec->pin_nids = stac925x_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS,
stac925x_models,
return -ENOMEM;
codec->spec = spec;
- spec->num_pins = 10;
+ spec->num_pins = ARRAY_SIZE(stac922x_pin_nids);
spec->pin_nids = stac922x_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
stac922x_models,
return -ENOMEM;
codec->spec = spec;
- spec->num_pins = 14;
+ spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
spec->pin_nids = stac927x_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
stac927x_models,
}
spec->multiout.dac_nids = spec->dac_nids;
- stac92xx_enable_eapd(codec);
+ /* GPIO0 High = Enable EAPD */
+ stac92xx_enable_gpio_mask(codec, 0x00000001, 0x00000001);
err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
if (!err) {
codec->patch_ops = stac92xx_patch_ops;
- /* Fix Mux capture level; max to 2 */
- snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT,
- (0 << AC_AMPCAP_OFFSET_SHIFT) |
- (2 << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (0 << AC_AMPCAP_MUTE_SHIFT));
-
return 0;
}
static int patch_stac9205(struct hda_codec *codec)
{
struct sigmatel_spec *spec;
- int err;
+ int err, gpio_mask, gpio_data;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
codec->spec = spec;
- spec->num_pins = 14;
+ spec->num_pins = ARRAY_SIZE(stac9205_pin_nids);
spec->pin_nids = stac9205_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
stac9205_models,
spec->mixer = stac9205_mixer;
spec->multiout.dac_nids = spec->dac_nids;
- stac92xx_enable_eapd(codec);
+
+ if (spec->board_config == STAC_M43xx) {
+ /* Enable SPDIF in/out */
+ stac92xx_set_config_reg(codec, 0x1f, 0x01441030);
+ stac92xx_set_config_reg(codec, 0x20, 0x1c410030);
+
+ gpio_mask = 0x00000007; /* GPIO0-2 */
+ /* GPIO0 High = EAPD, GPIO1 Low = DRM,
+ * GPIO2 High = Headphone Mute
+ */
+ gpio_data = 0x00000005;
+ } else
+ gpio_mask = gpio_data = 0x00000001; /* GPIO0 High = EAPD */
+ stac92xx_enable_gpio_mask(codec, gpio_mask, gpio_data);
err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);
if (!err) {
if (spec->board_config < 0) {
.num_items = 2,
.items = {
/* { "HP", 0x0 }, */
- { "Line", 0x1 },
- { "Mic", 0x2 },
+ { "Mic Jack", 0x1 },
+ { "Internal Mic", 0x2 },
{ "PCM", 0x3 },
}
};
{0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
{0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
{0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
/* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
/* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */