alc262_quirks.c 26 KB

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