alc262_quirks.c 23 KB

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