patch_sigmatel.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. /*
  2. * Universal Interface for Intel High Definition Audio Codec
  3. *
  4. * HD audio interface patch for SigmaTel STAC92xx
  5. *
  6. * Copyright (c) 2005 Embedded Alley Solutions, Inc.
  7. * <matt@embeddedalley.com>
  8. *
  9. * Based on patch_cmedia.c and patch_realtek.c
  10. * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
  11. *
  12. * This driver is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This driver is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  25. */
  26. #include <sound/driver.h>
  27. #include <linux/init.h>
  28. #include <linux/delay.h>
  29. #include <linux/slab.h>
  30. #include <linux/pci.h>
  31. #include <sound/core.h>
  32. #include "hda_codec.h"
  33. #include "hda_local.h"
  34. #undef STAC_TEST
  35. struct sigmatel_spec {
  36. /* playback */
  37. struct hda_multi_out multiout;
  38. hda_nid_t playback_nid;
  39. /* capture */
  40. hda_nid_t *adc_nids;
  41. hda_nid_t *mux_nids;
  42. unsigned int num_adcs;
  43. hda_nid_t capture_nid;
  44. /* power management*/
  45. hda_nid_t *pstate_nids;
  46. unsigned int num_pstates;
  47. /* pin widgets */
  48. hda_nid_t *pin_nids;
  49. unsigned int num_pins;
  50. #ifdef STAC_TEST
  51. unsigned int *pin_configs;
  52. #endif
  53. /* codec specific stuff */
  54. struct hda_verb *init;
  55. snd_kcontrol_new_t *mixer;
  56. /* capture source */
  57. const struct hda_input_mux *input_mux;
  58. unsigned int cur_mux[2];
  59. /* channel mode */
  60. unsigned int num_ch_modes;
  61. unsigned int cur_ch_mode;
  62. const struct sigmatel_channel_mode *channel_modes;
  63. struct hda_pcm pcm_rec[1]; /* PCM information */
  64. };
  65. static hda_nid_t stac9200_adc_nids[1] = {
  66. 0x03,
  67. };
  68. static hda_nid_t stac9200_mux_nids[1] = {
  69. 0x0c,
  70. };
  71. static hda_nid_t stac9200_dac_nids[1] = {
  72. 0x02,
  73. };
  74. static hda_nid_t stac9200_pstate_nids[3] = {
  75. 0x01, 0x02, 0x03,
  76. };
  77. static hda_nid_t stac9200_pin_nids[8] = {
  78. 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
  79. };
  80. static hda_nid_t stac922x_adc_nids[2] = {
  81. 0x06, 0x07,
  82. };
  83. static hda_nid_t stac922x_mux_nids[2] = {
  84. 0x12, 0x13,
  85. };
  86. static hda_nid_t stac922x_dac_nids[4] = {
  87. 0x02, 0x03, 0x04, 0x05,
  88. };
  89. static hda_nid_t stac922x_pstate_nids[7] = {
  90. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  91. };
  92. static hda_nid_t stac922x_pin_nids[10] = {
  93. 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
  94. 0x0f, 0x10, 0x11, 0x15, 0x1b,
  95. };
  96. static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  97. {
  98. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  99. struct sigmatel_spec *spec = codec->spec;
  100. return snd_hda_input_mux_info(spec->input_mux, uinfo);
  101. }
  102. static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  103. {
  104. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  105. struct sigmatel_spec *spec = codec->spec;
  106. unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  107. ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
  108. return 0;
  109. }
  110. static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  111. {
  112. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  113. struct sigmatel_spec *spec = codec->spec;
  114. unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  115. return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
  116. spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
  117. }
  118. static struct hda_verb stac9200_ch2_init[] = {
  119. /* set dac0mux for dac converter */
  120. { 0x07, 0x701, 0x00},
  121. {}
  122. };
  123. static struct hda_verb stac922x_ch2_init[] = {
  124. /* set master volume and direct control */
  125. { 0x16, 0x70f, 0xff},
  126. {}
  127. };
  128. struct sigmatel_channel_mode {
  129. unsigned int channels;
  130. const struct hda_verb *sequence;
  131. };
  132. static snd_kcontrol_new_t stac9200_mixer[] = {
  133. HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
  134. HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
  135. {
  136. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  137. .name = "Input Source",
  138. .count = 1,
  139. .info = stac92xx_mux_enum_info,
  140. .get = stac92xx_mux_enum_get,
  141. .put = stac92xx_mux_enum_put,
  142. },
  143. HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
  144. HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
  145. HDA_CODEC_VOLUME("Input Mux Volume", 0x0c, 0, HDA_OUTPUT),
  146. { } /* end */
  147. };
  148. static snd_kcontrol_new_t stac922x_mixer[] = {
  149. HDA_CODEC_VOLUME("PCM Playback Volume", 0x2, 0x0, HDA_OUTPUT),
  150. HDA_CODEC_MUTE("PCM Playback Switch", 0x2, 0x0, HDA_OUTPUT),
  151. {
  152. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  153. .name = "Input Source",
  154. .count = 1,
  155. .info = stac92xx_mux_enum_info,
  156. .get = stac92xx_mux_enum_get,
  157. .put = stac92xx_mux_enum_put,
  158. },
  159. HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT),
  160. HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT),
  161. HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT),
  162. { } /* end */
  163. };
  164. static struct hda_input_mux stac9200_input_mux = {
  165. .num_items = 5,
  166. .items = {
  167. { "Port B", 0x0 },
  168. { "Port C", 0x1 },
  169. { "Port D", 0x2 },
  170. { "Port A", 0x3 },
  171. { "CD", 0x4 },
  172. }
  173. };
  174. static struct hda_input_mux stac922x_input_mux = {
  175. .num_items = 7,
  176. .items = {
  177. { "Port E", 0x0 },
  178. { "CD", 0x1 },
  179. { "Port F", 0x2 },
  180. { "Port B", 0x3 },
  181. { "Port C", 0x4 },
  182. { "Port D", 0x5 },
  183. { "Port A", 0x6 },
  184. }
  185. };
  186. static int stac92xx_build_controls(struct hda_codec *codec)
  187. {
  188. struct sigmatel_spec *spec = codec->spec;
  189. int err;
  190. err = snd_hda_add_new_ctls(codec, spec->mixer);
  191. if (err < 0)
  192. return err;
  193. return 0;
  194. }
  195. #ifdef STAC_TEST
  196. static unsigned int stac9200_pin_configs[8] = {
  197. 0x40000100, 0x40000100, 0x0221401f, 0x01114010,
  198. 0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
  199. };
  200. static unsigned int stac922x_pin_configs[14] = {
  201. 0x40000100, 0x40000100, 0x40000100, 0x01114010,
  202. 0x01813122, 0x40000100, 0x40000100, 0x40000100,
  203. 0x40000100, 0x40000100,
  204. };
  205. static void stac92xx_set_config_regs(struct hda_codec *codec)
  206. {
  207. int i;
  208. struct sigmatel_spec *spec = codec->spec;
  209. unsigned int pin_cfg;
  210. for (i=0; i < spec->num_pins; i++) {
  211. snd_hda_codec_write(codec, spec->pin_nids[i], 0,
  212. AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
  213. spec->pin_configs[i] & 0x000000ff);
  214. snd_hda_codec_write(codec, spec->pin_nids[i], 0,
  215. AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
  216. (spec->pin_configs[i] & 0x0000ff00) >> 8);
  217. snd_hda_codec_write(codec, spec->pin_nids[i], 0,
  218. AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
  219. (spec->pin_configs[i] & 0x00ff0000) >> 16);
  220. snd_hda_codec_write(codec, spec->pin_nids[i], 0,
  221. AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
  222. spec->pin_configs[i] >> 24);
  223. pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
  224. AC_VERB_GET_CONFIG_DEFAULT,
  225. 0x00);
  226. printk("pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);
  227. }
  228. }
  229. #endif
  230. static int stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int value)
  231. {
  232. unsigned int pin_ctl;
  233. pin_ctl = snd_hda_codec_read(codec, nid, 0,
  234. AC_VERB_GET_PIN_WIDGET_CONTROL,
  235. 0x00);
  236. snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
  237. pin_ctl | value);
  238. return 0;
  239. }
  240. static int stac92xx_set_vref(struct hda_codec *codec, hda_nid_t nid)
  241. {
  242. unsigned int vref_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) >> AC_PINCAP_VREF_SHIFT;
  243. unsigned int vref_ctl = AC_PINCTL_VREF_HIZ;
  244. if (vref_caps & AC_PINCAP_VREF_100)
  245. vref_ctl = AC_PINCTL_VREF_100;
  246. else if (vref_caps & AC_PINCAP_VREF_80)
  247. vref_ctl = AC_PINCTL_VREF_80;
  248. else if (vref_caps & AC_PINCAP_VREF_50)
  249. vref_ctl = AC_PINCTL_VREF_50;
  250. else if (vref_caps & AC_PINCAP_VREF_GRD)
  251. vref_ctl = AC_PINCTL_VREF_GRD;
  252. stac92xx_set_pinctl(codec, nid, vref_ctl);
  253. return 0;
  254. }
  255. static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg)
  256. {
  257. switch((pin_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) {
  258. case AC_JACK_HP_OUT:
  259. /* Enable HP amp */
  260. stac92xx_set_pinctl(codec, nid, AC_PINCTL_HP_EN);
  261. /* Fall through */
  262. case AC_JACK_LINE_OUT:
  263. case AC_JACK_SPEAKER:
  264. /* Enable output */
  265. stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
  266. break;
  267. case AC_JACK_MIC_IN:
  268. /* Set vref */
  269. stac92xx_set_vref(codec, nid);
  270. case AC_JACK_CD:
  271. case AC_JACK_LINE_IN:
  272. case AC_JACK_AUX:
  273. /* Enable input */
  274. stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
  275. break;
  276. }
  277. return 0;
  278. }
  279. static int stac92xx_config_pins(struct hda_codec *codec)
  280. {
  281. struct sigmatel_spec *spec = codec->spec;
  282. int i;
  283. unsigned int pin_cfg;
  284. for (i=0; i < spec->num_pins; i++) {
  285. /* Default to disabled */
  286. snd_hda_codec_write(codec, spec->pin_nids[i], 0,
  287. AC_VERB_SET_PIN_WIDGET_CONTROL,
  288. 0x00);
  289. pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
  290. AC_VERB_GET_CONFIG_DEFAULT,
  291. 0x00);
  292. if (((pin_cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) == AC_JACK_PORT_NONE)
  293. continue; /* Move on */
  294. stac92xx_config_pin(codec, spec->pin_nids[i], pin_cfg);
  295. }
  296. return 0;
  297. }
  298. static int stac92xx_init(struct hda_codec *codec)
  299. {
  300. struct sigmatel_spec *spec = codec->spec;
  301. int i;
  302. for (i=0; i < spec->num_pstates; i++)
  303. snd_hda_codec_write(codec, spec->pstate_nids[i], 0,
  304. AC_VERB_SET_POWER_STATE, 0x00);
  305. mdelay(100);
  306. snd_hda_sequence_write(codec, spec->init);
  307. #ifdef STAC_TEST
  308. stac92xx_set_config_regs(codec);
  309. #endif
  310. stac92xx_config_pins(codec);
  311. return 0;
  312. }
  313. /*
  314. * Analog playback callbacks
  315. */
  316. static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
  317. struct hda_codec *codec,
  318. snd_pcm_substream_t *substream)
  319. {
  320. struct sigmatel_spec *spec = codec->spec;
  321. return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
  322. }
  323. static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
  324. struct hda_codec *codec,
  325. unsigned int stream_tag,
  326. unsigned int format,
  327. snd_pcm_substream_t *substream)
  328. {
  329. struct sigmatel_spec *spec = codec->spec;
  330. return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
  331. format, substream);
  332. }
  333. static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
  334. struct hda_codec *codec,
  335. snd_pcm_substream_t *substream)
  336. {
  337. struct sigmatel_spec *spec = codec->spec;
  338. return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
  339. }
  340. /*
  341. * Analog capture callbacks
  342. */
  343. static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
  344. struct hda_codec *codec,
  345. unsigned int stream_tag,
  346. unsigned int format,
  347. snd_pcm_substream_t *substream)
  348. {
  349. struct sigmatel_spec *spec = codec->spec;
  350. snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
  351. stream_tag, 0, format);
  352. return 0;
  353. }
  354. static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
  355. struct hda_codec *codec,
  356. snd_pcm_substream_t *substream)
  357. {
  358. struct sigmatel_spec *spec = codec->spec;
  359. snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
  360. return 0;
  361. }
  362. static struct hda_pcm_stream stac92xx_pcm_analog_playback = {
  363. .substreams = 1,
  364. .channels_min = 2,
  365. .channels_max = 2,
  366. .nid = 0x02, /* NID to query formats and rates */
  367. .ops = {
  368. .open = stac92xx_playback_pcm_open,
  369. .prepare = stac92xx_playback_pcm_prepare,
  370. .cleanup = stac92xx_playback_pcm_cleanup
  371. },
  372. };
  373. static struct hda_pcm_stream stac92xx_pcm_analog_capture = {
  374. .substreams = 2,
  375. .channels_min = 2,
  376. .channels_max = 2,
  377. .nid = 0x06, /* NID to query formats and rates */
  378. .ops = {
  379. .prepare = stac92xx_capture_pcm_prepare,
  380. .cleanup = stac92xx_capture_pcm_cleanup
  381. },
  382. };
  383. static int stac92xx_build_pcms(struct hda_codec *codec)
  384. {
  385. struct sigmatel_spec *spec = codec->spec;
  386. struct hda_pcm *info = spec->pcm_rec;
  387. codec->num_pcms = 1;
  388. codec->pcm_info = info;
  389. info->name = "STAC92xx";
  390. info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;
  391. info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->playback_nid;
  392. info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
  393. info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid;
  394. return 0;
  395. }
  396. static void stac92xx_free(struct hda_codec *codec)
  397. {
  398. kfree(codec->spec);
  399. }
  400. static struct hda_codec_ops stac92xx_patch_ops = {
  401. .build_controls = stac92xx_build_controls,
  402. .build_pcms = stac92xx_build_pcms,
  403. .init = stac92xx_init,
  404. .free = stac92xx_free,
  405. };
  406. static int patch_stac9200(struct hda_codec *codec)
  407. {
  408. struct sigmatel_spec *spec;
  409. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  410. if (spec == NULL)
  411. return -ENOMEM;
  412. codec->spec = spec;
  413. spec->multiout.max_channels = 2;
  414. spec->multiout.num_dacs = 1;
  415. spec->multiout.dac_nids = stac9200_dac_nids;
  416. spec->adc_nids = stac9200_adc_nids;
  417. spec->mux_nids = stac9200_mux_nids;
  418. spec->input_mux = &stac9200_input_mux;
  419. spec->pstate_nids = stac9200_pstate_nids;
  420. spec->num_pstates = 3;
  421. spec->pin_nids = stac9200_pin_nids;
  422. #ifdef STAC_TEST
  423. spec->pin_configs = stac9200_pin_configs;
  424. #endif
  425. spec->num_pins = 8;
  426. spec->init = stac9200_ch2_init;
  427. spec->mixer = stac9200_mixer;
  428. spec->playback_nid = 0x02;
  429. spec->capture_nid = 0x03;
  430. codec->patch_ops = stac92xx_patch_ops;
  431. return 0;
  432. }
  433. static int patch_stac922x(struct hda_codec *codec)
  434. {
  435. struct sigmatel_spec *spec;
  436. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  437. if (spec == NULL)
  438. return -ENOMEM;
  439. codec->spec = spec;
  440. spec->multiout.max_channels = 2;
  441. spec->multiout.num_dacs = 4;
  442. spec->multiout.dac_nids = stac922x_dac_nids;
  443. spec->adc_nids = stac922x_adc_nids;
  444. spec->mux_nids = stac922x_mux_nids;
  445. spec->input_mux = &stac922x_input_mux;
  446. spec->pstate_nids = stac922x_pstate_nids;
  447. spec->num_pstates = 7;
  448. spec->pin_nids = stac922x_pin_nids;
  449. #ifdef STAC_TEST
  450. spec->pin_configs = stac922x_pin_configs;
  451. #endif
  452. spec->num_pins = 10;
  453. spec->init = stac922x_ch2_init;
  454. spec->mixer = stac922x_mixer;
  455. spec->playback_nid = 0x02;
  456. spec->capture_nid = 0x06;
  457. codec->patch_ops = stac92xx_patch_ops;
  458. return 0;
  459. }
  460. /*
  461. * patch entries
  462. */
  463. struct hda_codec_preset snd_hda_preset_sigmatel[] = {
  464. { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
  465. { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
  466. { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
  467. { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x },
  468. { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x },
  469. { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x },
  470. { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x },
  471. {} /* terminator */
  472. };