alc680_quirks.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * ALC680 quirk models
  3. * included by patch_realtek.c
  4. */
  5. /* ALC680 models */
  6. enum {
  7. ALC680_AUTO,
  8. ALC680_BASE,
  9. ALC680_MODEL_LAST,
  10. };
  11. #define ALC680_DIGIN_NID ALC880_DIGIN_NID
  12. #define ALC680_DIGOUT_NID ALC880_DIGOUT_NID
  13. #define alc680_modes alc260_modes
  14. static const hda_nid_t alc680_dac_nids[3] = {
  15. /* Lout1, Lout2, hp */
  16. 0x02, 0x03, 0x04
  17. };
  18. static const hda_nid_t alc680_adc_nids[3] = {
  19. /* ADC0-2 */
  20. /* DMIC, MIC, Line-in*/
  21. 0x07, 0x08, 0x09
  22. };
  23. /*
  24. * Analog capture ADC cgange
  25. */
  26. static hda_nid_t alc680_get_cur_adc(struct hda_codec *codec)
  27. {
  28. static hda_nid_t pins[] = {0x18, 0x19};
  29. static hda_nid_t adcs[] = {0x08, 0x09};
  30. int i;
  31. for (i = 0; i < ARRAY_SIZE(pins); i++) {
  32. if (!is_jack_detectable(codec, pins[i]))
  33. continue;
  34. if (snd_hda_jack_detect(codec, pins[i]))
  35. return adcs[i];
  36. }
  37. return 0x07;
  38. }
  39. static void alc680_rec_autoswitch(struct hda_codec *codec)
  40. {
  41. struct alc_spec *spec = codec->spec;
  42. hda_nid_t nid = alc680_get_cur_adc(codec);
  43. if (spec->cur_adc && nid != spec->cur_adc) {
  44. __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
  45. spec->cur_adc = nid;
  46. snd_hda_codec_setup_stream(codec, nid,
  47. spec->cur_adc_stream_tag, 0,
  48. spec->cur_adc_format);
  49. }
  50. }
  51. static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
  52. struct hda_codec *codec,
  53. unsigned int stream_tag,
  54. unsigned int format,
  55. struct snd_pcm_substream *substream)
  56. {
  57. struct alc_spec *spec = codec->spec;
  58. hda_nid_t nid = alc680_get_cur_adc(codec);
  59. spec->cur_adc = nid;
  60. spec->cur_adc_stream_tag = stream_tag;
  61. spec->cur_adc_format = format;
  62. snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
  63. return 0;
  64. }
  65. static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
  66. struct hda_codec *codec,
  67. struct snd_pcm_substream *substream)
  68. {
  69. struct alc_spec *spec = codec->spec;
  70. snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
  71. spec->cur_adc = 0;
  72. return 0;
  73. }
  74. static const struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
  75. .substreams = 1, /* can be overridden */
  76. .channels_min = 2,
  77. .channels_max = 2,
  78. /* NID is set in alc_build_pcms */
  79. .ops = {
  80. .prepare = alc680_capture_pcm_prepare,
  81. .cleanup = alc680_capture_pcm_cleanup
  82. },
  83. };
  84. static const struct snd_kcontrol_new alc680_base_mixer[] = {
  85. /* output mixer control */
  86. HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
  87. HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
  88. HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT),
  89. HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT),
  90. HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x12, 0, HDA_INPUT),
  91. HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
  92. HDA_CODEC_VOLUME("Line In Boost Volume", 0x19, 0, HDA_INPUT),
  93. { }
  94. };
  95. static const struct hda_bind_ctls alc680_bind_cap_vol = {
  96. .ops = &snd_hda_bind_vol,
  97. .values = {
  98. HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
  99. HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
  100. HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
  101. 0
  102. },
  103. };
  104. static const struct hda_bind_ctls alc680_bind_cap_switch = {
  105. .ops = &snd_hda_bind_sw,
  106. .values = {
  107. HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
  108. HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
  109. HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
  110. 0
  111. },
  112. };
  113. static const struct snd_kcontrol_new alc680_master_capture_mixer[] = {
  114. HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol),
  115. HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch),
  116. { } /* end */
  117. };
  118. /*
  119. * generic initialization of ADC, input mixers and output mixers
  120. */
  121. static const struct hda_verb alc680_init_verbs[] = {
  122. {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
  123. {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
  124. {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
  125. {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
  126. {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
  127. {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
  128. {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
  129. {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
  130. {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
  131. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
  132. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
  133. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
  134. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
  135. {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
  136. {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
  137. {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
  138. {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
  139. { }
  140. };
  141. /* toggle speaker-output according to the hp-jack state */
  142. static void alc680_base_setup(struct hda_codec *codec)
  143. {
  144. struct alc_spec *spec = codec->spec;
  145. spec->autocfg.hp_pins[0] = 0x16;
  146. spec->autocfg.speaker_pins[0] = 0x14;
  147. spec->autocfg.speaker_pins[1] = 0x15;
  148. spec->autocfg.num_inputs = 2;
  149. spec->autocfg.inputs[0].pin = 0x18;
  150. spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
  151. spec->autocfg.inputs[1].pin = 0x19;
  152. spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
  153. spec->automute = 1;
  154. spec->automute_mode = ALC_AUTOMUTE_AMP;
  155. }
  156. static void alc680_unsol_event(struct hda_codec *codec,
  157. unsigned int res)
  158. {
  159. if ((res >> 26) == ALC_HP_EVENT)
  160. alc_hp_automute(codec);
  161. if ((res >> 26) == ALC_MIC_EVENT)
  162. alc680_rec_autoswitch(codec);
  163. }
  164. static void alc680_inithook(struct hda_codec *codec)
  165. {
  166. alc_hp_automute(codec);
  167. alc680_rec_autoswitch(codec);
  168. }
  169. /*
  170. * configuration and preset
  171. */
  172. static const char * const alc680_models[ALC680_MODEL_LAST] = {
  173. [ALC680_BASE] = "base",
  174. [ALC680_AUTO] = "auto",
  175. };
  176. static const struct snd_pci_quirk alc680_cfg_tbl[] = {
  177. SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
  178. {}
  179. };
  180. static const struct alc_config_preset alc680_presets[] = {
  181. [ALC680_BASE] = {
  182. .mixers = { alc680_base_mixer },
  183. .cap_mixer = alc680_master_capture_mixer,
  184. .init_verbs = { alc680_init_verbs },
  185. .num_dacs = ARRAY_SIZE(alc680_dac_nids),
  186. .dac_nids = alc680_dac_nids,
  187. .dig_out_nid = ALC680_DIGOUT_NID,
  188. .num_channel_mode = ARRAY_SIZE(alc680_modes),
  189. .channel_mode = alc680_modes,
  190. .unsol_event = alc680_unsol_event,
  191. .setup = alc680_base_setup,
  192. .init_hook = alc680_inithook,
  193. },
  194. };