alc262_quirks.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. /*
  2. * ALC262 quirk models
  3. * included by patch_realtek.c
  4. */
  5. /* ALC262 models */
  6. enum {
  7. ALC262_AUTO,
  8. ALC262_BASIC,
  9. ALC262_HIPPO,
  10. ALC262_HIPPO_1,
  11. ALC262_FUJITSU,
  12. ALC262_ULTRA,
  13. ALC262_MODEL_LAST /* last tag */
  14. };
  15. #define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
  16. #define ALC262_DIGIN_NID ALC880_DIGIN_NID
  17. #define alc262_dac_nids alc260_dac_nids
  18. #define alc262_adc_nids alc882_adc_nids
  19. #define alc262_adc_nids_alt alc882_adc_nids_alt
  20. #define alc262_capsrc_nids alc882_capsrc_nids
  21. #define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
  22. #define alc262_modes alc260_modes
  23. #define alc262_capture_source alc882_capture_source
  24. static const hda_nid_t alc262_dmic_adc_nids[1] = {
  25. /* ADC0 */
  26. 0x09
  27. };
  28. static const hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
  29. static const struct snd_kcontrol_new alc262_base_mixer[] = {
  30. HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
  31. HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
  32. HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
  33. HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
  34. HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
  35. HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
  36. HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
  37. HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
  38. HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
  39. HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
  40. HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
  41. HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
  42. HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
  43. HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
  44. HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
  45. HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
  46. { } /* end */
  47. };
  48. /* bind hp and internal speaker mute (with plug check) as master switch */
  49. static int alc262_hippo_master_sw_get(struct snd_kcontrol *kcontrol,
  50. struct snd_ctl_elem_value *ucontrol)
  51. {
  52. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  53. struct alc_spec *spec = codec->spec;
  54. *ucontrol->value.integer.value = !spec->master_mute;
  55. return 0;
  56. }
  57. static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol,
  58. struct snd_ctl_elem_value *ucontrol)
  59. {
  60. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  61. struct alc_spec *spec = codec->spec;
  62. int val = !*ucontrol->value.integer.value;
  63. if (val == spec->master_mute)
  64. return 0;
  65. spec->master_mute = val;
  66. update_outputs(codec);
  67. return 1;
  68. }
  69. #define ALC262_HIPPO_MASTER_SWITCH \
  70. { \
  71. .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  72. .name = "Master Playback Switch", \
  73. .info = snd_ctl_boolean_mono_info, \
  74. .get = alc262_hippo_master_sw_get, \
  75. .put = alc262_hippo_master_sw_put, \
  76. }, \
  77. { \
  78. .iface = NID_MAPPING, \
  79. .name = "Master Playback Switch", \
  80. .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
  81. (SUBDEV_SPEAKER(0) << 16), \
  82. }
  83. #define alc262_hp_master_sw_get alc262_hippo_master_sw_get
  84. #define alc262_hp_master_sw_put alc262_hippo_master_sw_put
  85. static const struct snd_kcontrol_new alc262_hippo_mixer[] = {
  86. ALC262_HIPPO_MASTER_SWITCH,
  87. HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
  88. HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
  89. HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
  90. HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
  91. HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
  92. HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
  93. HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
  94. HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
  95. HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
  96. HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
  97. HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
  98. HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
  99. { } /* end */
  100. };
  101. static const struct snd_kcontrol_new alc262_hippo1_mixer[] = {
  102. HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
  103. ALC262_HIPPO_MASTER_SWITCH,
  104. HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
  105. HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
  106. HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
  107. HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
  108. HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
  109. HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
  110. HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
  111. HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
  112. HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
  113. HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
  114. { } /* end */
  115. };
  116. /* mute/unmute internal speaker according to the hp jack and mute state */
  117. static void alc262_hippo_setup(struct hda_codec *codec)
  118. {
  119. struct alc_spec *spec = codec->spec;
  120. spec->autocfg.hp_pins[0] = 0x15;
  121. spec->autocfg.speaker_pins[0] = 0x14;
  122. alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
  123. }
  124. static void alc262_hippo1_setup(struct hda_codec *codec)
  125. {
  126. struct alc_spec *spec = codec->spec;
  127. spec->autocfg.hp_pins[0] = 0x1b;
  128. spec->autocfg.speaker_pins[0] = 0x14;
  129. alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
  130. }
  131. static const struct snd_kcontrol_new alc262_sony_mixer[] = {
  132. HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
  133. ALC262_HIPPO_MASTER_SWITCH,
  134. HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
  135. HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
  136. HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
  137. HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
  138. { } /* end */
  139. };
  140. #define alc262_capture_mixer alc882_capture_mixer
  141. #define alc262_capture_alt_mixer alc882_capture_alt_mixer
  142. /*
  143. * generic initialization of ADC, input mixers and output mixers
  144. */
  145. static const struct hda_verb alc262_init_verbs[] = {
  146. /*
  147. * Unmute ADC0-2 and set the default input to mic-in
  148. */
  149. {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
  150. {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  151. {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
  152. {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  153. {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
  154. {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  155. /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
  156. * mixer widget
  157. * Note: PASD motherboards uses the Line In 2 as the input for
  158. * front panel mic (mic 2)
  159. */
  160. /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
  161. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
  162. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
  163. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
  164. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
  165. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
  166. /*
  167. * Set up output mixers (0x0c - 0x0e)
  168. */
  169. /* set vol=0 to output mixers */
  170. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  171. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  172. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  173. /* set up input amps for analog loopback */
  174. /* Amp Indices: DAC = 0, mixer = 1 */
  175. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  176. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  177. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  178. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  179. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  180. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  181. {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  182. {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
  183. {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  184. {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
  185. {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  186. {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  187. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  188. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  189. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  190. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  191. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  192. {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
  193. {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
  194. /* FIXME: use matrix-type input source selection */
  195. /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
  196. /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
  197. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  198. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
  199. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
  200. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
  201. /* Input mixer2 */
  202. {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  203. {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
  204. {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
  205. {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
  206. /* Input mixer3 */
  207. {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  208. {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
  209. {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
  210. {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
  211. { }
  212. };
  213. static const struct hda_verb alc262_eapd_verbs[] = {
  214. {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
  215. {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
  216. { }
  217. };
  218. static const struct hda_verb alc262_hippo1_unsol_verbs[] = {
  219. {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
  220. {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
  221. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  222. {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
  223. {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
  224. {}
  225. };
  226. static const struct hda_verb alc262_sony_unsol_verbs[] = {
  227. {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
  228. {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
  229. {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic
  230. {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
  231. {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
  232. {}
  233. };
  234. /*
  235. * fujitsu model
  236. * 0x14 = headphone/spdif-out, 0x15 = internal speaker,
  237. * 0x1b = port replicator headphone out
  238. */
  239. static const struct hda_verb alc262_fujitsu_unsol_verbs[] = {
  240. {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
  241. {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
  242. {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
  243. {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
  244. {}
  245. };
  246. static const struct hda_input_mux alc262_fujitsu_capture_source = {
  247. .num_items = 3,
  248. .items = {
  249. { "Mic", 0x0 },
  250. { "Internal Mic", 0x1 },
  251. { "CD", 0x4 },
  252. },
  253. };
  254. static void alc262_fujitsu_setup(struct hda_codec *codec)
  255. {
  256. struct alc_spec *spec = codec->spec;
  257. spec->autocfg.hp_pins[0] = 0x14;
  258. spec->autocfg.hp_pins[1] = 0x1b;
  259. spec->autocfg.speaker_pins[0] = 0x15;
  260. alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
  261. }
  262. /* bind volumes of both NID 0x0c and 0x0d */
  263. static const struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
  264. .ops = &snd_hda_bind_vol,
  265. .values = {
  266. HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
  267. HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
  268. 0
  269. },
  270. };
  271. static const struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
  272. HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
  273. {
  274. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  275. .name = "Master Playback Switch",
  276. .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
  277. .info = snd_ctl_boolean_mono_info,
  278. .get = alc262_hp_master_sw_get,
  279. .put = alc262_hp_master_sw_put,
  280. },
  281. {
  282. .iface = NID_MAPPING,
  283. .name = "Master Playback Switch",
  284. .private_value = 0x1b,
  285. },
  286. HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
  287. HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
  288. HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
  289. HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
  290. HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
  291. HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
  292. HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
  293. HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
  294. { } /* end */
  295. };
  296. /* additional init verbs for Benq laptops */
  297. static const struct hda_verb alc262_EAPD_verbs[] = {
  298. {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
  299. {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
  300. {}
  301. };
  302. /* Samsung Q1 Ultra Vista model setup */
  303. static const struct snd_kcontrol_new alc262_ultra_mixer[] = {
  304. HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
  305. HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
  306. HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
  307. HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
  308. HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
  309. HDA_CODEC_VOLUME("Headphone Mic Boost Volume", 0x15, 0, HDA_INPUT),
  310. { } /* end */
  311. };
  312. static const struct hda_verb alc262_ultra_verbs[] = {
  313. /* output mixer */
  314. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
  315. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
  316. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  317. /* speaker */
  318. {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
  319. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
  320. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  321. {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
  322. /* HP */
  323. {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
  324. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
  325. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  326. {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
  327. {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
  328. /* internal mic */
  329. {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
  330. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
  331. /* ADC, choose mic */
  332. {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
  333. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
  334. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  335. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
  336. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
  337. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
  338. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
  339. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
  340. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
  341. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
  342. {}
  343. };
  344. /* mute/unmute internal speaker according to the hp jack and mute state */
  345. static void alc262_ultra_automute(struct hda_codec *codec)
  346. {
  347. struct alc_spec *spec = codec->spec;
  348. unsigned int mute;
  349. mute = 0;
  350. /* auto-mute only when HP is used as HP */
  351. if (!spec->cur_mux[0]) {
  352. spec->hp_jack_present = snd_hda_jack_detect(codec, 0x15);
  353. if (spec->hp_jack_present)
  354. mute = HDA_AMP_MUTE;
  355. }
  356. /* mute/unmute internal speaker */
  357. snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
  358. HDA_AMP_MUTE, mute);
  359. /* mute/unmute HP */
  360. snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
  361. HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
  362. }
  363. /* unsolicited event for HP jack sensing */
  364. static void alc262_ultra_unsol_event(struct hda_codec *codec,
  365. unsigned int res)
  366. {
  367. if ((res >> 26) != ALC_HP_EVENT)
  368. return;
  369. alc262_ultra_automute(codec);
  370. }
  371. static const struct hda_input_mux alc262_ultra_capture_source = {
  372. .num_items = 2,
  373. .items = {
  374. { "Mic", 0x1 },
  375. { "Headphone", 0x7 },
  376. },
  377. };
  378. static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
  379. struct snd_ctl_elem_value *ucontrol)
  380. {
  381. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  382. struct alc_spec *spec = codec->spec;
  383. int ret;
  384. ret = alc_mux_enum_put(kcontrol, ucontrol);
  385. if (!ret)
  386. return 0;
  387. /* reprogram the HP pin as mic or HP according to the input source */
  388. snd_hda_codec_write_cache(codec, 0x15, 0,
  389. AC_VERB_SET_PIN_WIDGET_CONTROL,
  390. spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
  391. alc262_ultra_automute(codec); /* mute/unmute HP */
  392. return ret;
  393. }
  394. static const struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
  395. HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
  396. HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
  397. {
  398. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  399. .name = "Capture Source",
  400. .info = alc_mux_enum_info,
  401. .get = alc_mux_enum_get,
  402. .put = alc262_ultra_mux_enum_put,
  403. },
  404. {
  405. .iface = NID_MAPPING,
  406. .name = "Capture Source",
  407. .private_value = 0x15,
  408. },
  409. { } /* end */
  410. };
  411. /*
  412. * configuration and preset
  413. */
  414. static const char * const alc262_models[ALC262_MODEL_LAST] = {
  415. [ALC262_BASIC] = "basic",
  416. [ALC262_HIPPO] = "hippo",
  417. [ALC262_HIPPO_1] = "hippo_1",
  418. [ALC262_FUJITSU] = "fujitsu",
  419. [ALC262_ULTRA] = "ultra",
  420. [ALC262_AUTO] = "auto",
  421. };
  422. static const struct snd_pci_quirk alc262_cfg_tbl[] = {
  423. SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
  424. SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
  425. SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
  426. SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
  427. ALC262_ULTRA),
  428. SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
  429. SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
  430. {}
  431. };
  432. static const struct alc_config_preset alc262_presets[] = {
  433. [ALC262_BASIC] = {
  434. .mixers = { alc262_base_mixer },
  435. .init_verbs = { alc262_init_verbs },
  436. .num_dacs = ARRAY_SIZE(alc262_dac_nids),
  437. .dac_nids = alc262_dac_nids,
  438. .hp_nid = 0x03,
  439. .num_channel_mode = ARRAY_SIZE(alc262_modes),
  440. .channel_mode = alc262_modes,
  441. .input_mux = &alc262_capture_source,
  442. },
  443. [ALC262_HIPPO] = {
  444. .mixers = { alc262_hippo_mixer },
  445. .init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
  446. .num_dacs = ARRAY_SIZE(alc262_dac_nids),
  447. .dac_nids = alc262_dac_nids,
  448. .hp_nid = 0x03,
  449. .dig_out_nid = ALC262_DIGOUT_NID,
  450. .num_channel_mode = ARRAY_SIZE(alc262_modes),
  451. .channel_mode = alc262_modes,
  452. .input_mux = &alc262_capture_source,
  453. .unsol_event = alc_sku_unsol_event,
  454. .setup = alc262_hippo_setup,
  455. .init_hook = alc_inithook,
  456. },
  457. [ALC262_HIPPO_1] = {
  458. .mixers = { alc262_hippo1_mixer },
  459. .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
  460. .num_dacs = ARRAY_SIZE(alc262_dac_nids),
  461. .dac_nids = alc262_dac_nids,
  462. .hp_nid = 0x02,
  463. .dig_out_nid = ALC262_DIGOUT_NID,
  464. .num_channel_mode = ARRAY_SIZE(alc262_modes),
  465. .channel_mode = alc262_modes,
  466. .input_mux = &alc262_capture_source,
  467. .unsol_event = alc_sku_unsol_event,
  468. .setup = alc262_hippo1_setup,
  469. .init_hook = alc_inithook,
  470. },
  471. [ALC262_FUJITSU] = {
  472. .mixers = { alc262_fujitsu_mixer },
  473. .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
  474. alc262_fujitsu_unsol_verbs },
  475. .num_dacs = ARRAY_SIZE(alc262_dac_nids),
  476. .dac_nids = alc262_dac_nids,
  477. .hp_nid = 0x03,
  478. .dig_out_nid = ALC262_DIGOUT_NID,
  479. .num_channel_mode = ARRAY_SIZE(alc262_modes),
  480. .channel_mode = alc262_modes,
  481. .input_mux = &alc262_fujitsu_capture_source,
  482. .unsol_event = alc_sku_unsol_event,
  483. .setup = alc262_fujitsu_setup,
  484. .init_hook = alc_inithook,
  485. },
  486. [ALC262_ULTRA] = {
  487. .mixers = { alc262_ultra_mixer },
  488. .cap_mixer = alc262_ultra_capture_mixer,
  489. .init_verbs = { alc262_ultra_verbs },
  490. .num_dacs = ARRAY_SIZE(alc262_dac_nids),
  491. .dac_nids = alc262_dac_nids,
  492. .num_channel_mode = ARRAY_SIZE(alc262_modes),
  493. .channel_mode = alc262_modes,
  494. .input_mux = &alc262_ultra_capture_source,
  495. .adc_nids = alc262_adc_nids, /* ADC0 */
  496. .capsrc_nids = alc262_capsrc_nids,
  497. .num_adc_nids = 1, /* single ADC */
  498. .unsol_event = alc262_ultra_unsol_event,
  499. .init_hook = alc262_ultra_automute,
  500. },
  501. };