diff options
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 151 |
1 files changed, 83 insertions, 68 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index dbffb5b5c69..8c416bb18a5 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -568,6 +568,11 @@ static hda_nid_t stac92hd83xxx_pin_nids[10] = { 0x0f, 0x10, 0x11, 0x1f, 0x20, }; +static hda_nid_t stac92hd88xxx_pin_nids[10] = { + 0x0a, 0x0b, 0x0c, 0x0d, + 0x0f, 0x11, 0x1f, 0x20, +}; + #define STAC92HD71BXX_NUM_PINS 13 static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { 0x0a, 0x0b, 0x0c, 0x0d, 0x00, @@ -2873,6 +2878,13 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) conn_len = snd_hda_get_connections(codec, nid, conn, HDA_MAX_CONNECTIONS); + /* 92HD88: trace back up the link of nids to find the DAC */ + while (conn_len == 1 && (get_wcaps_type(get_wcaps(codec, conn[0])) + != AC_WID_AUD_OUT)) { + nid = conn[0]; + conn_len = snd_hda_get_connections(codec, nid, conn, + HDA_MAX_CONNECTIONS); + } for (j = 0; j < conn_len; j++) { wcaps = get_wcaps(codec, conn[j]); wtype = get_wcaps_type(wcaps); @@ -4351,6 +4363,12 @@ static int stac92xx_init(struct hda_codec *codec) if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) stac_issue_unsol_event(codec, nid); } + +#ifdef CONFIG_SND_HDA_POWER_SAVE + /* sync mute LED */ + if (spec->gpio_led && codec->patch_ops.check_power_status) + codec->patch_ops.check_power_status(codec, 0x01); +#endif if (spec->dac_list) stac92xx_power_down(codec); return 0; @@ -4742,19 +4760,14 @@ static int hp_blike_system(u32 subsystem_id); static void set_hp_led_gpio(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; - switch (codec->vendor_id) { - case 0x111d7608: - /* GPIO 0 */ - spec->gpio_led = 0x01; - break; - case 0x111d7600: - case 0x111d7601: - case 0x111d7602: - case 0x111d7603: - /* GPIO 3 */ - spec->gpio_led = 0x08; - break; - } + unsigned int gpio; + + gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); + gpio &= AC_GPIO_IO_COUNT; + if (gpio > 3) + spec->gpio_led = 0x08; /* GPIO 3 */ + else + spec->gpio_led = 0x01; /* GPIO 0 */ } /* @@ -4777,7 +4790,7 @@ static void set_hp_led_gpio(struct hda_codec *codec) * Need more information on whether it is true across the entire series. * -- kunal */ -static int find_mute_led_gpio(struct hda_codec *codec) +static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) { struct sigmatel_spec *spec = codec->spec; const struct dmi_device *dev = NULL; @@ -4804,7 +4817,7 @@ static int find_mute_led_gpio(struct hda_codec *codec) */ if (!hp_blike_system(codec->subsystem_id)) { set_hp_led_gpio(codec); - spec->gpio_led_polarity = 1; + spec->gpio_led_polarity = default_polarity; return 1; } } @@ -4902,6 +4915,11 @@ static int stac92xx_resume(struct hda_codec *codec) stac_issue_unsol_event(codec, spec->autocfg.line_out_pins[0]); } +#ifdef CONFIG_SND_HDA_POWER_SAVE + /* sync mute LED */ + if (spec->gpio_led && codec->patch_ops.check_power_status) + codec->patch_ops.check_power_status(codec, 0x01); +#endif return 0; } @@ -4921,43 +4939,29 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, hda_nid_t nid) { struct sigmatel_spec *spec = codec->spec; + int i, muted = 1; - if (nid == 0x10) { - if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & - HDA_AMP_MUTE) - spec->gpio_data &= ~spec->gpio_led; /* orange */ - else - spec->gpio_data |= spec->gpio_led; /* white */ - - if (!spec->gpio_led_polarity) { - /* LED state is inverted on these systems */ - spec->gpio_data ^= spec->gpio_led; + for (i = 0; i < spec->multiout.num_dacs; i++) { + nid = spec->multiout.dac_nids[i]; + if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & + HDA_AMP_MUTE)) { + muted = 0; /* something heard */ + break; } - - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, - spec->gpio_data); } + if (muted) + spec->gpio_data &= ~spec->gpio_led; /* orange */ + else + spec->gpio_data |= spec->gpio_led; /* white */ - return 0; -} - -static int idt92hd83xxx_hp_check_power_status(struct hda_codec *codec, - hda_nid_t nid) -{ - struct sigmatel_spec *spec = codec->spec; + if (!spec->gpio_led_polarity) { + /* LED state is inverted on these systems */ + spec->gpio_data ^= spec->gpio_led; + } - if (nid != 0x13) - return 0; - if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & HDA_AMP_MUTE) - spec->gpio_data |= spec->gpio_led; /* mute LED on */ - else - spec->gpio_data &= ~spec->gpio_led; /* mute LED off */ stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); - return 0; } - #endif static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) @@ -5279,7 +5283,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) hda_nid_t conn[STAC92HD83_DAC_COUNT + 1]; int err; int num_dacs; - hda_nid_t nid; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -5318,7 +5321,18 @@ again: stac92hd83xxx_brd_tbl[spec->board_config]); switch (codec->vendor_id) { + case 0x111d7666: + case 0x111d7667: + case 0x111d7668: + case 0x111d7669: + spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); + spec->pin_nids = stac92hd88xxx_pin_nids; + spec->mono_nid = 0; + spec->digbeep_nid = 0; + spec->num_pwrs = 0; + break; case 0x111d7604: + case 0x111d76d4: case 0x111d7605: case 0x111d76d5: if (spec->board_config == STAC_92HD83XXX_PWR_REF) @@ -5329,8 +5343,10 @@ again: codec->patch_ops = stac92xx_patch_ops; - if (spec->board_config == STAC_92HD83XXX_HP) - spec->gpio_led = 0x01; + if (find_mute_led_gpio(codec, 0)) + snd_printd("mute LED gpio %d polarity %d\n", + spec->gpio_led, + spec->gpio_led_polarity); #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { @@ -5339,7 +5355,7 @@ again: spec->gpio_data |= spec->gpio_led; /* register check_power_status callback. */ codec->patch_ops.check_power_status = - idt92hd83xxx_hp_check_power_status; + stac92xx_hp_check_power_status; } #endif @@ -5359,24 +5375,21 @@ again: return err; } - switch (spec->board_config) { - case STAC_DELL_S14: - nid = 0xf; - break; - default: - nid = 0xe; - break; - } - - num_dacs = snd_hda_get_connections(codec, nid, + /* docking output support */ + num_dacs = snd_hda_get_connections(codec, 0xF, conn, STAC92HD83_DAC_COUNT + 1) - 1; - if (num_dacs < 0) - num_dacs = STAC92HD83_DAC_COUNT; - - /* set port X to select the last DAC - */ - snd_hda_codec_write_cache(codec, nid, 0, + /* skip non-DAC connections */ + while (num_dacs >= 0 && + (get_wcaps_type(get_wcaps(codec, conn[num_dacs])) + != AC_WID_AUD_OUT)) + num_dacs--; + /* set port E and F to select the last DAC */ + if (num_dacs >= 0) { + snd_hda_codec_write_cache(codec, 0xE, 0, + AC_VERB_SET_CONNECT_SEL, num_dacs); + snd_hda_codec_write_cache(codec, 0xF, 0, AC_VERB_SET_CONNECT_SEL, num_dacs); + } codec->proc_widget_hook = stac92hd_proc_hook; @@ -5657,7 +5670,6 @@ again: */ spec->num_smuxes = 1; spec->num_dmuxes = 1; - spec->gpio_led = 0x01; /* fallthrough */ case STAC_HP_DV5: snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); @@ -5672,8 +5684,6 @@ again: spec->num_dmics = 1; spec->num_dmuxes = 1; spec->num_smuxes = 1; - /* orange/white mute led on GPIO3, orange=0, white=1 */ - spec->gpio_led = 0x08; break; } @@ -5695,7 +5705,7 @@ again: } } - if (find_mute_led_gpio(codec)) + if (find_mute_led_gpio(codec, 1)) snd_printd("mute LED gpio %d polarity %d\n", spec->gpio_led, spec->gpio_led_polarity); @@ -6236,8 +6246,13 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = { { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx}, { .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx}, + { .id = 0x111d76d4, .name = "92HD83C1C5", .patch = patch_stac92hd83xxx}, { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, + { .id = 0x111d7666, .name = "92HD88B3", .patch = patch_stac92hd83xxx}, + { .id = 0x111d7667, .name = "92HD88B1", .patch = patch_stac92hd83xxx}, + { .id = 0x111d7668, .name = "92HD88B2", .patch = patch_stac92hd83xxx}, + { .id = 0x111d7669, .name = "92HD88B4", .patch = patch_stac92hd83xxx}, { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx}, { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, |