diff options
Diffstat (limited to 'sound/pci/hda/patch_cirrus.c')
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 89 |
1 files changed, 82 insertions, 7 deletions
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index cccaf9c7a7bb..b524f89a1f13 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -169,7 +169,7 @@ static void cs_automute(struct hda_codec *codec) | |||
169 | 169 | ||
170 | snd_hda_gen_update_outputs(codec); | 170 | snd_hda_gen_update_outputs(codec); |
171 | 171 | ||
172 | if (spec->gpio_eapd_hp) { | 172 | if (spec->gpio_eapd_hp || spec->gpio_eapd_speaker) { |
173 | spec->gpio_data = spec->gen.hp_jack_present ? | 173 | spec->gpio_data = spec->gen.hp_jack_present ? |
174 | spec->gpio_eapd_hp : spec->gpio_eapd_speaker; | 174 | spec->gpio_eapd_hp : spec->gpio_eapd_speaker; |
175 | snd_hda_codec_write(codec, 0x01, 0, | 175 | snd_hda_codec_write(codec, 0x01, 0, |
@@ -291,10 +291,11 @@ static int cs_init(struct hda_codec *codec) | |||
291 | { | 291 | { |
292 | struct cs_spec *spec = codec->spec; | 292 | struct cs_spec *spec = codec->spec; |
293 | 293 | ||
294 | /* init_verb sequence for C0/C1/C2 errata*/ | 294 | if (spec->vendor_nid == CS420X_VENDOR_NID) { |
295 | snd_hda_sequence_write(codec, cs_errata_init_verbs); | 295 | /* init_verb sequence for C0/C1/C2 errata*/ |
296 | 296 | snd_hda_sequence_write(codec, cs_errata_init_verbs); | |
297 | snd_hda_sequence_write(codec, cs_coef_init_verbs); | 297 | snd_hda_sequence_write(codec, cs_coef_init_verbs); |
298 | } | ||
298 | 299 | ||
299 | snd_hda_gen_init(codec); | 300 | snd_hda_gen_init(codec); |
300 | 301 | ||
@@ -307,8 +308,10 @@ static int cs_init(struct hda_codec *codec) | |||
307 | spec->gpio_data); | 308 | spec->gpio_data); |
308 | } | 309 | } |
309 | 310 | ||
310 | init_input_coef(codec); | 311 | if (spec->vendor_nid == CS420X_VENDOR_NID) { |
311 | init_digital_coef(codec); | 312 | init_input_coef(codec); |
313 | init_digital_coef(codec); | ||
314 | } | ||
312 | 315 | ||
313 | return 0; | 316 | return 0; |
314 | } | 317 | } |
@@ -552,6 +555,76 @@ static int patch_cs420x(struct hda_codec *codec) | |||
552 | } | 555 | } |
553 | 556 | ||
554 | /* | 557 | /* |
558 | * CS4208 support: | ||
559 | * Its layout is no longer compatible with CS4206/CS4207, and the generic | ||
560 | * parser seems working fairly well, except for trivial fixups. | ||
561 | */ | ||
562 | enum { | ||
563 | CS4208_GPIO0, | ||
564 | }; | ||
565 | |||
566 | static const struct hda_model_fixup cs4208_models[] = { | ||
567 | { .id = CS4208_GPIO0, .name = "gpio0" }, | ||
568 | {} | ||
569 | }; | ||
570 | |||
571 | static const struct snd_pci_quirk cs4208_fixup_tbl[] = { | ||
572 | /* codec SSID */ | ||
573 | SND_PCI_QUIRK(0x106b, 0x7100, "MacBookPro 6,1", CS4208_GPIO0), | ||
574 | SND_PCI_QUIRK(0x106b, 0x7200, "MacBookPro 6,2", CS4208_GPIO0), | ||
575 | {} /* terminator */ | ||
576 | }; | ||
577 | |||
578 | static void cs4208_fixup_gpio0(struct hda_codec *codec, | ||
579 | const struct hda_fixup *fix, int action) | ||
580 | { | ||
581 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
582 | struct cs_spec *spec = codec->spec; | ||
583 | spec->gpio_eapd_hp = 0; | ||
584 | spec->gpio_eapd_speaker = 1; | ||
585 | spec->gpio_mask = spec->gpio_dir = | ||
586 | spec->gpio_eapd_hp | spec->gpio_eapd_speaker; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | static const struct hda_fixup cs4208_fixups[] = { | ||
591 | [CS4208_GPIO0] = { | ||
592 | .type = HDA_FIXUP_FUNC, | ||
593 | .v.func = cs4208_fixup_gpio0, | ||
594 | }, | ||
595 | }; | ||
596 | |||
597 | static int patch_cs4208(struct hda_codec *codec) | ||
598 | { | ||
599 | struct cs_spec *spec; | ||
600 | int err; | ||
601 | |||
602 | spec = cs_alloc_spec(codec, 0); /* no specific w/a */ | ||
603 | if (!spec) | ||
604 | return -ENOMEM; | ||
605 | |||
606 | spec->gen.automute_hook = cs_automute; | ||
607 | |||
608 | snd_hda_pick_fixup(codec, cs4208_models, cs4208_fixup_tbl, | ||
609 | cs4208_fixups); | ||
610 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | ||
611 | |||
612 | err = cs_parse_auto_config(codec); | ||
613 | if (err < 0) | ||
614 | goto error; | ||
615 | |||
616 | codec->patch_ops = cs_patch_ops; | ||
617 | |||
618 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | ||
619 | |||
620 | return 0; | ||
621 | |||
622 | error: | ||
623 | cs_free(codec); | ||
624 | return err; | ||
625 | } | ||
626 | |||
627 | /* | ||
555 | * Cirrus Logic CS4210 | 628 | * Cirrus Logic CS4210 |
556 | * | 629 | * |
557 | * 1 DAC => HP(sense) / Speakers, | 630 | * 1 DAC => HP(sense) / Speakers, |
@@ -991,6 +1064,7 @@ static int patch_cs4213(struct hda_codec *codec) | |||
991 | static const struct hda_codec_preset snd_hda_preset_cirrus[] = { | 1064 | static const struct hda_codec_preset snd_hda_preset_cirrus[] = { |
992 | { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x }, | 1065 | { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x }, |
993 | { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x }, | 1066 | { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x }, |
1067 | { .id = 0x10134208, .name = "CS4208", .patch = patch_cs4208 }, | ||
994 | { .id = 0x10134210, .name = "CS4210", .patch = patch_cs4210 }, | 1068 | { .id = 0x10134210, .name = "CS4210", .patch = patch_cs4210 }, |
995 | { .id = 0x10134213, .name = "CS4213", .patch = patch_cs4213 }, | 1069 | { .id = 0x10134213, .name = "CS4213", .patch = patch_cs4213 }, |
996 | {} /* terminator */ | 1070 | {} /* terminator */ |
@@ -998,6 +1072,7 @@ static const struct hda_codec_preset snd_hda_preset_cirrus[] = { | |||
998 | 1072 | ||
999 | MODULE_ALIAS("snd-hda-codec-id:10134206"); | 1073 | MODULE_ALIAS("snd-hda-codec-id:10134206"); |
1000 | MODULE_ALIAS("snd-hda-codec-id:10134207"); | 1074 | MODULE_ALIAS("snd-hda-codec-id:10134207"); |
1075 | MODULE_ALIAS("snd-hda-codec-id:10134208"); | ||
1001 | MODULE_ALIAS("snd-hda-codec-id:10134210"); | 1076 | MODULE_ALIAS("snd-hda-codec-id:10134210"); |
1002 | MODULE_ALIAS("snd-hda-codec-id:10134213"); | 1077 | MODULE_ALIAS("snd-hda-codec-id:10134213"); |
1003 | 1078 | ||