📄 patch_sigmatel.c
字号:
int err; if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) return err; if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) return err; if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) return err; if (spec->autocfg.dig_out_pin) spec->multiout.dig_out_nid = 0x05; if (spec->autocfg.dig_in_pin) spec->dig_in_nid = 0x04; if (spec->kctl_alloc) spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->input_mux = &spec->private_imux; return 1;}static int stac92xx_init(struct hda_codec *codec){ struct sigmatel_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; int i; snd_hda_sequence_write(codec, spec->init); /* set up pins */ if (spec->hp_detect) { /* Enable unsolicited responses on the HP widget */ snd_hda_codec_write(codec, cfg->hp_pin, 0, AC_VERB_SET_UNSOLICITED_ENABLE, STAC_UNSOL_ENABLE); /* fake event to set up pins */ codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); } else { stac92xx_auto_init_multi_out(codec); stac92xx_auto_init_hp_out(codec); } for (i = 0; i < AUTO_PIN_LAST; i++) { hda_nid_t nid = cfg->input_pins[i]; if (nid) { unsigned int pinctl = AC_PINCTL_IN_EN; if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) pinctl |= stac92xx_get_vref(codec, nid); stac92xx_auto_set_pinctl(codec, nid, pinctl); } } if (cfg->dig_out_pin) stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, AC_PINCTL_OUT_EN); if (cfg->dig_in_pin) stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, AC_PINCTL_IN_EN); return 0;}static void stac92xx_free(struct hda_codec *codec){ struct sigmatel_spec *spec = codec->spec; int i; if (! spec) return; if (spec->kctl_alloc) { for (i = 0; i < spec->num_kctl_used; i++) kfree(spec->kctl_alloc[i].name); kfree(spec->kctl_alloc); } kfree(spec);}static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int flag){ unsigned int pin_ctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_ctl | flag);}static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int flag){ unsigned int pin_ctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_ctl & ~flag);}static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res){ struct sigmatel_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; int i, presence; if ((res >> 26) != STAC_HP_EVENT) return; presence = snd_hda_codec_read(codec, cfg->hp_pin, 0, AC_VERB_GET_PIN_SENSE, 0x00) >> 31; if (presence) { /* disable lineouts, enable hp */ for (i = 0; i < cfg->line_outs; i++) stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], AC_PINCTL_OUT_EN); stac92xx_set_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); } else { /* enable lineouts, disable hp */ for (i = 0; i < cfg->line_outs; i++) stac92xx_set_pinctl(codec, cfg->line_out_pins[i], AC_PINCTL_OUT_EN); stac92xx_reset_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); }} #ifdef CONFIG_PMstatic int stac92xx_resume(struct hda_codec *codec){ struct sigmatel_spec *spec = codec->spec; int i; stac92xx_init(codec); for (i = 0; i < spec->num_mixers; i++) snd_hda_resume_ctls(codec, spec->mixers[i]); if (spec->multiout.dig_out_nid) snd_hda_resume_spdif_out(codec); if (spec->dig_in_nid) snd_hda_resume_spdif_in(codec); return 0;}#endifstatic struct hda_codec_ops stac92xx_patch_ops = { .build_controls = stac92xx_build_controls, .build_pcms = stac92xx_build_pcms, .init = stac92xx_init, .free = stac92xx_free, .unsol_event = stac92xx_unsol_event,#ifdef CONFIG_PM .resume = stac92xx_resume,#endif};static int patch_stac9200(struct hda_codec *codec){ struct sigmatel_spec *spec; int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; codec->spec = spec; spec->board_config = snd_hda_check_board_config(codec, stac9200_cfg_tbl); if (spec->board_config < 0) snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); else { spec->num_pins = 8; spec->pin_nids = stac9200_pin_nids; spec->pin_configs = stac9200_brd_tbl[spec->board_config]; stac92xx_set_config_regs(codec); } spec->multiout.max_channels = 2; spec->multiout.num_dacs = 1; spec->multiout.dac_nids = stac9200_dac_nids; spec->adc_nids = stac9200_adc_nids; spec->mux_nids = stac9200_mux_nids; spec->num_muxes = 1; spec->init = stac9200_core_init; spec->mixer = stac9200_mixer; err = stac9200_parse_auto_config(codec); if (err < 0) { stac92xx_free(codec); return err; } codec->patch_ops = stac92xx_patch_ops; return 0;}static int patch_stac922x(struct hda_codec *codec){ struct sigmatel_spec *spec; int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; codec->spec = spec; spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); if (spec->board_config < 0) snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n"); else { spec->num_pins = 10; spec->pin_nids = stac922x_pin_nids; spec->pin_configs = stac922x_brd_tbl[spec->board_config]; stac92xx_set_config_regs(codec); } spec->adc_nids = stac922x_adc_nids; spec->mux_nids = stac922x_mux_nids; spec->num_muxes = 2; spec->init = stac922x_core_init; spec->mixer = stac922x_mixer; spec->multiout.dac_nids = spec->dac_nids; err = stac92xx_parse_auto_config(codec, 0x08, 0x09); if (err < 0) { stac92xx_free(codec); return err; } codec->patch_ops = stac92xx_patch_ops; return 0;}static int patch_stac927x(struct hda_codec *codec){ struct sigmatel_spec *spec; int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; codec->spec = spec; spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl); if (spec->board_config < 0) snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n"); else { spec->num_pins = 14; spec->pin_nids = stac927x_pin_nids; spec->pin_configs = stac927x_brd_tbl[spec->board_config]; stac92xx_set_config_regs(codec); } spec->adc_nids = stac927x_adc_nids; spec->mux_nids = stac927x_mux_nids; spec->num_muxes = 3; spec->init = stac927x_core_init; spec->mixer = stac927x_mixer; spec->multiout.dac_nids = spec->dac_nids; err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); if (err < 0) { stac92xx_free(codec); return err; } codec->patch_ops = stac92xx_patch_ops; return 0;}/* * STAC 7661(?) hack *//* static config for Sony VAIO FE550G */static hda_nid_t vaio_dacs[] = { 0x2 };#define VAIO_HP_DAC 0x5static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ };static hda_nid_t vaio_mux_nids[] = { 0x15 };static struct hda_input_mux vaio_mux = { .num_items = 2, .items = { /* { "HP", 0x0 }, */ { "Line", 0x1 }, { "Mic", 0x2 }, { "PCM", 0x3 }, }};static struct hda_verb vaio_init[] = { {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ {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 */ {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 */ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ {}};/* bind volumes of both NID 0x02 and 0x05 */static int vaio_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); long *valp = ucontrol->value.integer.value; int change; change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, 0x7f, valp[0] & 0x7f); change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, 0x7f, valp[1] & 0x7f); snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, 0x7f, valp[0] & 0x7f); snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, 0x7f, valp[1] & 0x7f); return change;}/* bind volumes of both NID 0x02 and 0x05 */static int vaio_master_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); long *valp = ucontrol->value.integer.value; int change; change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, 0x80, (valp[0] ? 0 : 0x80)); change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, 0x80, (valp[1] ? 0 : 0x80)); snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, 0x80, (valp[0] ? 0 : 0x80)); snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, 0x80, (valp[1] ? 0 : 0x80)); return change;}static struct snd_kcontrol_new vaio_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Volume", .info = snd_hda_mixer_amp_volume_info, .get = snd_hda_mixer_amp_volume_get, .put = vaio_master_vol_put, .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", .info = snd_hda_mixer_amp_switch_info, .get = snd_hda_mixer_amp_switch_get, .put = vaio_master_sw_put, .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), }, /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .count = 1, .info = stac92xx_mux_enum_info, .get = stac92xx_mux_enum_get, .put = stac92xx_mux_enum_put, }, {}};static struct hda_codec_ops stac7661_patch_ops = { .build_controls = stac92xx_build_controls, .build_pcms = stac92xx_build_pcms, .init = stac92xx_init, .free = stac92xx_free,#ifdef CONFIG_PM .resume = stac92xx_resume,#endif};enum { STAC7661_VAIO };static struct hda_board_config stac7661_cfg_tbl[] = { { .modelname = "vaio", .config = STAC7661_VAIO }, { .pci_subvendor = 0x104d, .pci_subdevice = 0x81e6, .config = STAC7661_VAIO }, { .pci_subvendor = 0x104d, .pci_subdevice = 0x81ef, .config = STAC7661_VAIO }, {}};static int patch_stac7661(struct hda_codec *codec){ struct sigmatel_spec *spec; int board_config; board_config = snd_hda_check_board_config(codec, stac7661_cfg_tbl); if (board_config < 0) /* unknown config, let generic-parser do its job... */ return snd_hda_parse_generic_codec(codec); spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; codec->spec = spec; switch (board_config) { case STAC7661_VAIO: spec->mixer = vaio_mixer; spec->init = vaio_init; spec->multiout.max_channels = 2; spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); spec->multiout.dac_nids = vaio_dacs; spec->multiout.hp_nid = VAIO_HP_DAC; spec->num_adcs = ARRAY_SIZE(vaio_adcs); spec->adc_nids = vaio_adcs; spec->input_mux = &vaio_mux; spec->mux_nids = vaio_mux_nids; break; } codec->patch_ops = stac7661_patch_ops; return 0;}/* * patch entries */struct hda_codec_preset snd_hda_preset_sigmatel[] = { { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 }, { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x }, { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x }, { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x }, { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, { .id = 0x83847623, .name = "STAC9273D", .patch = patch_stac927x }, { .id = 0x83847624, .name = "STAC9272X", .patch = patch_stac927x }, { .id = 0x83847625, .name = "STAC9272D", .patch = patch_stac927x }, { .id = 0x83847626, .name = "STAC9271X", .patch = patch_stac927x }, { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, { .id = 0x83847661, .name = "STAC7661", .patch = patch_stac7661 }, {} /* terminator */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -