]>
Commit | Line | Data |
---|---|---|
d0fa1179 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 LT |
2 | /* |
3 | * Universal Interface for Intel High Definition Audio Codec | |
4 | * | |
5 | * HD audio interface patch for C-Media CMI9880 | |
6 | * | |
7 | * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> | |
1da177e4 LT |
8 | */ |
9 | ||
1da177e4 | 10 | #include <linux/init.h> |
1da177e4 | 11 | #include <linux/slab.h> |
da155d5b | 12 | #include <linux/module.h> |
1da177e4 | 13 | #include <sound/core.h> |
be57bfff | 14 | #include <sound/hda_codec.h> |
1da177e4 | 15 | #include "hda_local.h" |
128bc4ba | 16 | #include "hda_auto_parser.h" |
b060fb0e TI |
17 | #include "hda_jack.h" |
18 | #include "hda_generic.h" | |
19 | ||
1da177e4 | 20 | struct cmi_spec { |
b060fb0e | 21 | struct hda_gen_spec gen; |
1da177e4 LT |
22 | }; |
23 | ||
b060fb0e TI |
24 | /* |
25 | * stuff for auto-parser | |
26 | */ | |
27 | static const struct hda_codec_ops cmi_auto_patch_ops = { | |
28 | .build_controls = snd_hda_gen_build_controls, | |
29 | .build_pcms = snd_hda_gen_build_pcms, | |
30 | .init = snd_hda_gen_init, | |
31 | .free = snd_hda_gen_free, | |
8a6c21ae | 32 | .unsol_event = snd_hda_jack_unsol_event, |
b060fb0e TI |
33 | }; |
34 | ||
db8e8a9d | 35 | static int patch_cmi9880(struct hda_codec *codec) |
b060fb0e | 36 | { |
db8e8a9d TI |
37 | struct cmi_spec *spec; |
38 | struct auto_pin_cfg *cfg; | |
b060fb0e TI |
39 | int err; |
40 | ||
db8e8a9d TI |
41 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
42 | if (spec == NULL) | |
43 | return -ENOMEM; | |
44 | ||
45 | codec->spec = spec; | |
225068ab | 46 | codec->patch_ops = cmi_auto_patch_ops; |
db8e8a9d | 47 | cfg = &spec->gen.autocfg; |
b060fb0e TI |
48 | snd_hda_gen_spec_init(&spec->gen); |
49 | ||
50 | err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); | |
51 | if (err < 0) | |
998caa4d | 52 | goto error; |
b060fb0e TI |
53 | err = snd_hda_gen_parse_auto_config(codec, cfg); |
54 | if (err < 0) | |
998caa4d | 55 | goto error; |
b060fb0e | 56 | |
b060fb0e | 57 | return 0; |
998caa4d TI |
58 | |
59 | error: | |
60 | snd_hda_gen_free(codec); | |
61 | return err; | |
b060fb0e TI |
62 | } |
63 | ||
875f0dd7 TI |
64 | static int patch_cmi8888(struct hda_codec *codec) |
65 | { | |
66 | struct cmi_spec *spec; | |
67 | struct auto_pin_cfg *cfg; | |
68 | int err; | |
69 | ||
70 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | |
71 | if (!spec) | |
72 | return -ENOMEM; | |
73 | ||
74 | codec->spec = spec; | |
225068ab | 75 | codec->patch_ops = cmi_auto_patch_ops; |
875f0dd7 TI |
76 | cfg = &spec->gen.autocfg; |
77 | snd_hda_gen_spec_init(&spec->gen); | |
78 | ||
79 | /* mask NID 0x10 from the playback volume selection; | |
80 | * it's a headphone boost volume handled manually below | |
81 | */ | |
82 | spec->gen.out_vol_mask = (1ULL << 0x10); | |
83 | ||
84 | err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); | |
85 | if (err < 0) | |
86 | goto error; | |
87 | err = snd_hda_gen_parse_auto_config(codec, cfg); | |
88 | if (err < 0) | |
89 | goto error; | |
90 | ||
91 | if (get_defcfg_device(snd_hda_codec_get_pincfg(codec, 0x10)) == | |
92 | AC_JACK_HP_OUT) { | |
93 | static const struct snd_kcontrol_new amp_kctl = | |
94 | HDA_CODEC_VOLUME("Headphone Amp Playback Volume", | |
95 | 0x10, 0, HDA_OUTPUT); | |
96 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &_kctl)) { | |
97 | err = -ENOMEM; | |
98 | goto error; | |
99 | } | |
100 | } | |
101 | ||
875f0dd7 TI |
102 | return 0; |
103 | ||
104 | error: | |
105 | snd_hda_gen_free(codec); | |
106 | return err; | |
107 | } | |
108 | ||
1da177e4 LT |
109 | /* |
110 | * patch entries | |
111 | */ | |
b9a94a9c TI |
112 | static const struct hda_device_id snd_hda_id_cmedia[] = { |
113 | HDA_CODEC_ENTRY(0x13f68888, "CMI8888", patch_cmi8888), | |
114 | HDA_CODEC_ENTRY(0x13f69880, "CMI9880", patch_cmi9880), | |
115 | HDA_CODEC_ENTRY(0x434d4980, "CMI9880", patch_cmi9880), | |
1da177e4 LT |
116 | {} /* terminator */ |
117 | }; | |
b9a94a9c | 118 | MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cmedia); |
1289e9e8 TI |
119 | |
120 | MODULE_LICENSE("GPL"); | |
121 | MODULE_DESCRIPTION("C-Media HD-audio codec"); | |
122 | ||
d8a766a1 | 123 | static struct hda_codec_driver cmedia_driver = { |
b9a94a9c | 124 | .id = snd_hda_id_cmedia, |
1289e9e8 TI |
125 | }; |
126 | ||
d8a766a1 | 127 | module_hda_codec_driver(cmedia_driver); |