ac97_patch.c 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309
  1. /*
  2. * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
  3. * Universal interface for Audio Codec '97
  4. *
  5. * For more details look to AC '97 component specification revision 2.2
  6. * by Intel Corporation (http://developer.intel.com) and to datasheets
  7. * for specific codecs.
  8. *
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. *
  24. */
  25. #include <sound/driver.h>
  26. #include <linux/delay.h>
  27. #include <linux/init.h>
  28. #include <linux/slab.h>
  29. #include <sound/core.h>
  30. #include <sound/pcm.h>
  31. #include <sound/control.h>
  32. #include <sound/ac97_codec.h>
  33. #include "ac97_patch.h"
  34. #include "ac97_id.h"
  35. #include "ac97_local.h"
  36. /*
  37. * Chip specific initialization
  38. */
  39. static int patch_build_controls(ac97_t * ac97, const snd_kcontrol_new_t *controls, int count)
  40. {
  41. int idx, err;
  42. for (idx = 0; idx < count; idx++)
  43. if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&controls[idx], ac97))) < 0)
  44. return err;
  45. return 0;
  46. }
  47. /* set to the page, update bits and restore the page */
  48. static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
  49. {
  50. unsigned short page_save;
  51. int ret;
  52. down(&ac97->page_mutex);
  53. page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
  54. snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
  55. ret = snd_ac97_update_bits(ac97, reg, mask, value);
  56. snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
  57. up(&ac97->page_mutex); /* unlock paging */
  58. return ret;
  59. }
  60. /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
  61. /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
  62. static int snd_ac97_ymf753_info_speaker(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  63. {
  64. static char *texts[3] = {
  65. "Standard", "Small", "Smaller"
  66. };
  67. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  68. uinfo->count = 1;
  69. uinfo->value.enumerated.items = 3;
  70. if (uinfo->value.enumerated.item > 2)
  71. uinfo->value.enumerated.item = 2;
  72. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  73. return 0;
  74. }
  75. static int snd_ac97_ymf753_get_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  76. {
  77. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  78. unsigned short val;
  79. val = ac97->regs[AC97_YMF753_3D_MODE_SEL];
  80. val = (val >> 10) & 3;
  81. if (val > 0) /* 0 = invalid */
  82. val--;
  83. ucontrol->value.enumerated.item[0] = val;
  84. return 0;
  85. }
  86. static int snd_ac97_ymf753_put_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  87. {
  88. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  89. unsigned short val;
  90. if (ucontrol->value.enumerated.item[0] > 2)
  91. return -EINVAL;
  92. val = (ucontrol->value.enumerated.item[0] + 1) << 10;
  93. return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val);
  94. }
  95. static const snd_kcontrol_new_t snd_ac97_ymf753_controls_speaker =
  96. {
  97. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  98. .name = "3D Control - Speaker",
  99. .info = snd_ac97_ymf753_info_speaker,
  100. .get = snd_ac97_ymf753_get_speaker,
  101. .put = snd_ac97_ymf753_put_speaker,
  102. };
  103. /* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF output. */
  104. static int snd_ac97_ymf753_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  105. {
  106. static char *texts[2] = { "AC-Link", "A/D Converter" };
  107. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  108. uinfo->count = 1;
  109. uinfo->value.enumerated.items = 2;
  110. if (uinfo->value.enumerated.item > 1)
  111. uinfo->value.enumerated.item = 1;
  112. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  113. return 0;
  114. }
  115. static int snd_ac97_ymf753_spdif_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  116. {
  117. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  118. unsigned short val;
  119. val = ac97->regs[AC97_YMF753_DIT_CTRL2];
  120. ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
  121. return 0;
  122. }
  123. static int snd_ac97_ymf753_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  124. {
  125. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  126. unsigned short val;
  127. if (ucontrol->value.enumerated.item[0] > 1)
  128. return -EINVAL;
  129. val = ucontrol->value.enumerated.item[0] << 1;
  130. return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0002, val);
  131. }
  132. /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
  133. The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48.
  134. By default, no output pin is selected, and the S/PDIF signal is not output.
  135. There is also a bit to mute S/PDIF output in a vendor-specific register. */
  136. static int snd_ac97_ymf753_spdif_output_pin_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  137. {
  138. static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" };
  139. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  140. uinfo->count = 1;
  141. uinfo->value.enumerated.items = 3;
  142. if (uinfo->value.enumerated.item > 2)
  143. uinfo->value.enumerated.item = 2;
  144. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  145. return 0;
  146. }
  147. static int snd_ac97_ymf753_spdif_output_pin_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  148. {
  149. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  150. unsigned short val;
  151. val = ac97->regs[AC97_YMF753_DIT_CTRL2];
  152. ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;
  153. return 0;
  154. }
  155. static int snd_ac97_ymf753_spdif_output_pin_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  156. {
  157. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  158. unsigned short val;
  159. if (ucontrol->value.enumerated.item[0] > 2)
  160. return -EINVAL;
  161. val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
  162. (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
  163. return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0028, val);
  164. /* The following can be used to direct S/PDIF output to pin 47 (EAPD).
  165. snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
  166. }
  167. static const snd_kcontrol_new_t snd_ac97_ymf753_controls_spdif[3] = {
  168. {
  169. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  170. .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
  171. .info = snd_ac97_ymf753_spdif_source_info,
  172. .get = snd_ac97_ymf753_spdif_source_get,
  173. .put = snd_ac97_ymf753_spdif_source_put,
  174. },
  175. {
  176. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  177. .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
  178. .info = snd_ac97_ymf753_spdif_output_pin_info,
  179. .get = snd_ac97_ymf753_spdif_output_pin_get,
  180. .put = snd_ac97_ymf753_spdif_output_pin_put,
  181. },
  182. AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2, 2, 1, 1)
  183. };
  184. static int patch_yamaha_ymf753_3d(ac97_t * ac97)
  185. {
  186. snd_kcontrol_t *kctl;
  187. int err;
  188. if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
  189. return err;
  190. strcpy(kctl->id.name, "3D Control - Wide");
  191. kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
  192. snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
  193. if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
  194. return err;
  195. snd_ac97_write_cache(ac97, AC97_YMF753_3D_MODE_SEL, 0x0c00);
  196. return 0;
  197. }
  198. static int patch_yamaha_ymf753_post_spdif(ac97_t * ac97)
  199. {
  200. int err;
  201. if ((err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif))) < 0)
  202. return err;
  203. return 0;
  204. }
  205. static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
  206. .build_3d = patch_yamaha_ymf753_3d,
  207. .build_post_spdif = patch_yamaha_ymf753_post_spdif
  208. };
  209. int patch_yamaha_ymf753(ac97_t * ac97)
  210. {
  211. /* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com.
  212. This chip has nonstandard and extended behaviour with regard to its S/PDIF output.
  213. The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
  214. The YMF753 will ouput the S/PDIF signal to pin 43, 47 (EAPD), or 48.
  215. By default, no output pin is selected, and the S/PDIF signal is not output.
  216. There is also a bit to mute S/PDIF output in a vendor-specific register.
  217. */
  218. ac97->build_ops = &patch_yamaha_ymf753_ops;
  219. ac97->caps |= AC97_BC_BASS_TREBLE;
  220. ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
  221. return 0;
  222. }
  223. /*
  224. * May 2, 2003 Liam Girdwood <liam.girdwood@wolfsonmicro.com>
  225. * removed broken wolfson00 patch.
  226. * added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
  227. */
  228. int patch_wolfson03(ac97_t * ac97)
  229. {
  230. /* This is known to work for the ViewSonic ViewPad 1000
  231. Randolph Bentson <bentson@holmsjoen.com> */
  232. // WM9703/9707/9708/9717
  233. snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
  234. snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0x8000);
  235. return 0;
  236. }
  237. int patch_wolfson04(ac97_t * ac97)
  238. {
  239. // WM9704M/9704Q
  240. // set front and rear mixer volume
  241. snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
  242. snd_ac97_write_cache(ac97, AC97_WM9704_RMIXER_VOL, 0x0808);
  243. // patch for DVD noise
  244. snd_ac97_write_cache(ac97, AC97_WM9704_TEST, 0x0200);
  245. // init vol
  246. snd_ac97_write_cache(ac97, AC97_WM9704_RPCM_VOL, 0x0808);
  247. // set rear surround volume
  248. snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000);
  249. return 0;
  250. }
  251. int patch_wolfson05(ac97_t * ac97)
  252. {
  253. // WM9705, WM9710
  254. // set front mixer volume
  255. snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808);
  256. return 0;
  257. }
  258. int patch_wolfson11(ac97_t * ac97)
  259. {
  260. // WM9711, WM9712
  261. // set out3 volume
  262. snd_ac97_write_cache(ac97, AC97_WM9711_OUT3VOL, 0x0808);
  263. return 0;
  264. }
  265. static const char* wm9713_mic_mixer[] = {"Stereo", "Mic1", "Mic2", "Mute"};
  266. static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
  267. static const char* wm9713_rec_src_l[] = {"Mic1", "Mic2", "Line L", "Mono In", "HP Mix L", "Spk Mix", "Mono Mix", "Zh"};
  268. static const char* wm9713_rec_src_r[] = {"Mic1", "Mic2", "Line R", "Mono In", "HP Mix R", "Spk Mix", "Mono Mix", "Zh"};
  269. static const struct ac97_enum wm9713_enum[] = {
  270. AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer),
  271. AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux),
  272. AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),
  273. AC97_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src_l),
  274. AC97_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src_r),
  275. };
  276. static const snd_kcontrol_new_t wm13_snd_ac97_controls_line_in[] = {
  277. AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
  278. AC97_SINGLE("Line In to Headphone Mute", AC97_PC_BEEP, 15, 1, 1),
  279. AC97_SINGLE("Line In to Speaker Mute", AC97_PC_BEEP, 14, 1, 1),
  280. AC97_SINGLE("Line In to Mono Mute", AC97_PC_BEEP, 13, 1, 1),
  281. };
  282. static const snd_kcontrol_new_t wm13_snd_ac97_controls_dac[] = {
  283. AC97_DOUBLE("DAC Volume", AC97_PHONE, 8, 0, 31, 1),
  284. AC97_SINGLE("DAC to Headphone Mute", AC97_PHONE, 15, 1, 1),
  285. AC97_SINGLE("DAC to Speaker Mute", AC97_PHONE, 14, 1, 1),
  286. AC97_SINGLE("DAC to Mono Mute", AC97_PHONE, 13, 1, 1),
  287. };
  288. static const snd_kcontrol_new_t wm13_snd_ac97_controls_mic[] = {
  289. AC97_SINGLE("MICA Volume", AC97_MIC, 8, 31, 1),
  290. AC97_SINGLE("MICB Volume", AC97_MIC, 0, 31, 1),
  291. AC97_SINGLE("MICA to Mono Mute", AC97_LINE, 7, 1, 1),
  292. AC97_SINGLE("MICB to Mono Mute", AC97_LINE, 6, 1, 1),
  293. AC97_SINGLE("MIC Boost (+20dB)", AC97_LINE, 5, 1, 1),
  294. AC97_ENUM("MIC Headphone Routing", wm9713_enum[0]),
  295. AC97_SINGLE("MIC Headphone Mixer Volume", AC97_LINE, 0, 7, 1)
  296. };
  297. static const snd_kcontrol_new_t wm13_snd_ac97_controls_adc[] = {
  298. AC97_SINGLE("ADC Mute", AC97_CD, 15, 1, 1),
  299. AC97_DOUBLE("Gain Step Size (1.5dB/0.75dB)", AC97_CD, 14, 6, 1, 1),
  300. AC97_DOUBLE("ADC Volume",AC97_CD, 8, 0, 15, 0),
  301. AC97_SINGLE("ADC Zero Cross", AC97_CD, 7, 1, 1),
  302. };
  303. static const snd_kcontrol_new_t wm13_snd_ac97_controls_recsel[] = {
  304. AC97_ENUM("Record to Headphone Path", wm9713_enum[1]),
  305. AC97_SINGLE("Record to Headphone Volume", AC97_VIDEO, 11, 7, 0),
  306. AC97_ENUM("Record to Mono Path", wm9713_enum[2]),
  307. AC97_SINGLE("Record to Mono Boost (+20dB)", AC97_VIDEO, 8, 1, 0),
  308. AC97_SINGLE("Record ADC Boost (+20dB)", AC97_VIDEO, 6, 1, 0),
  309. AC97_ENUM("Record Select Left", wm9713_enum[3]),
  310. AC97_ENUM("Record Select Right", wm9713_enum[4]),
  311. };
  312. static int patch_wolfson_wm9713_specific(ac97_t * ac97)
  313. {
  314. int err, i;
  315. for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_line_in); i++) {
  316. if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_line_in[i], ac97))) < 0)
  317. return err;
  318. }
  319. snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
  320. for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_dac); i++) {
  321. if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_dac[i], ac97))) < 0)
  322. return err;
  323. }
  324. snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808);
  325. for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_mic); i++) {
  326. if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_mic[i], ac97))) < 0)
  327. return err;
  328. }
  329. snd_ac97_write_cache(ac97, AC97_MIC, 0x0808);
  330. snd_ac97_write_cache(ac97, AC97_LINE, 0x00da);
  331. for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_adc); i++) {
  332. if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_adc[i], ac97))) < 0)
  333. return err;
  334. }
  335. snd_ac97_write_cache(ac97, AC97_CD, 0x0808);
  336. for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_recsel); i++) {
  337. if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_recsel[i], ac97))) < 0)
  338. return err;
  339. }
  340. snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612);
  341. snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0);
  342. return 0;
  343. }
  344. #ifdef CONFIG_PM
  345. static void patch_wolfson_wm9713_suspend (ac97_t * ac97)
  346. {
  347. snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff);
  348. snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff);
  349. }
  350. static void patch_wolfson_wm9713_resume (ac97_t * ac97)
  351. {
  352. snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
  353. snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
  354. snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
  355. }
  356. #endif
  357. static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
  358. .build_specific = patch_wolfson_wm9713_specific,
  359. #ifdef CONFIG_PM
  360. .suspend = patch_wolfson_wm9713_suspend,
  361. .resume = patch_wolfson_wm9713_resume
  362. #endif
  363. };
  364. int patch_wolfson13(ac97_t * ac97)
  365. {
  366. ac97->build_ops = &patch_wolfson_wm9713_ops;
  367. ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE |
  368. AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD;
  369. snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
  370. snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
  371. snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
  372. return 0;
  373. }
  374. /*
  375. * Tritech codec
  376. */
  377. int patch_tritech_tr28028(ac97_t * ac97)
  378. {
  379. snd_ac97_write_cache(ac97, 0x26, 0x0300);
  380. snd_ac97_write_cache(ac97, 0x26, 0x0000);
  381. snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000);
  382. snd_ac97_write_cache(ac97, AC97_SPDIF, 0x0000);
  383. return 0;
  384. }
  385. /*
  386. * Sigmatel STAC97xx codecs
  387. */
  388. static int patch_sigmatel_stac9700_3d(ac97_t * ac97)
  389. {
  390. snd_kcontrol_t *kctl;
  391. int err;
  392. if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
  393. return err;
  394. strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
  395. kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
  396. snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
  397. return 0;
  398. }
  399. static int patch_sigmatel_stac9708_3d(ac97_t * ac97)
  400. {
  401. snd_kcontrol_t *kctl;
  402. int err;
  403. if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
  404. return err;
  405. strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
  406. kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
  407. if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
  408. return err;
  409. strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
  410. kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
  411. snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
  412. return 0;
  413. }
  414. static const snd_kcontrol_new_t snd_ac97_sigmatel_4speaker =
  415. AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch", AC97_SIGMATEL_DAC2INVERT, 2, 1, 0);
  416. static const snd_kcontrol_new_t snd_ac97_sigmatel_phaseinvert =
  417. AC97_SINGLE("Sigmatel Surround Phase Inversion Playback Switch", AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
  418. static const snd_kcontrol_new_t snd_ac97_sigmatel_controls[] = {
  419. AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
  420. AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
  421. };
  422. static int patch_sigmatel_stac97xx_specific(ac97_t * ac97)
  423. {
  424. int err;
  425. snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);
  426. if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1))
  427. if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1)) < 0)
  428. return err;
  429. if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))
  430. if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1)) < 0)
  431. return err;
  432. if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2))
  433. if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1)) < 0)
  434. return err;
  435. if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3))
  436. if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1)) < 0)
  437. return err;
  438. return 0;
  439. }
  440. static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
  441. .build_3d = patch_sigmatel_stac9700_3d,
  442. .build_specific = patch_sigmatel_stac97xx_specific
  443. };
  444. int patch_sigmatel_stac9700(ac97_t * ac97)
  445. {
  446. ac97->build_ops = &patch_sigmatel_stac9700_ops;
  447. return 0;
  448. }
  449. static int snd_ac97_stac9708_put_bias(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  450. {
  451. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  452. int err;
  453. down(&ac97->page_mutex);
  454. snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
  455. err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010,
  456. (ucontrol->value.integer.value[0] & 1) << 4);
  457. snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0);
  458. up(&ac97->page_mutex);
  459. return err;
  460. }
  461. static const snd_kcontrol_new_t snd_ac97_stac9708_bias_control = {
  462. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  463. .name = "Sigmatel Output Bias Switch",
  464. .info = snd_ac97_info_volsw,
  465. .get = snd_ac97_get_volsw,
  466. .put = snd_ac97_stac9708_put_bias,
  467. .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0),
  468. };
  469. static int patch_sigmatel_stac9708_specific(ac97_t *ac97)
  470. {
  471. int err;
  472. snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
  473. if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0)
  474. return err;
  475. return patch_sigmatel_stac97xx_specific(ac97);
  476. }
  477. static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
  478. .build_3d = patch_sigmatel_stac9708_3d,
  479. .build_specific = patch_sigmatel_stac9708_specific
  480. };
  481. int patch_sigmatel_stac9708(ac97_t * ac97)
  482. {
  483. unsigned int codec72, codec6c;
  484. ac97->build_ops = &patch_sigmatel_stac9708_ops;
  485. ac97->caps |= 0x10; /* HP (sigmatel surround) support */
  486. codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
  487. codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
  488. if ((codec72==0) && (codec6c==0)) {
  489. snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
  490. snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1000);
  491. snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
  492. snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0007);
  493. } else if ((codec72==0x8000) && (codec6c==0)) {
  494. snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
  495. snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1001);
  496. snd_ac97_write_cache(ac97, AC97_SIGMATEL_DAC2INVERT, 0x0008);
  497. } else if ((codec72==0x8000) && (codec6c==0x0080)) {
  498. /* nothing */
  499. }
  500. snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
  501. return 0;
  502. }
  503. int patch_sigmatel_stac9721(ac97_t * ac97)
  504. {
  505. ac97->build_ops = &patch_sigmatel_stac9700_ops;
  506. if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
  507. // patch for SigmaTel
  508. snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
  509. snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x4000);
  510. snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
  511. snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
  512. }
  513. snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
  514. return 0;
  515. }
  516. int patch_sigmatel_stac9744(ac97_t * ac97)
  517. {
  518. // patch for SigmaTel
  519. ac97->build_ops = &patch_sigmatel_stac9700_ops;
  520. snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
  521. snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
  522. snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
  523. snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
  524. snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
  525. return 0;
  526. }
  527. int patch_sigmatel_stac9756(ac97_t * ac97)
  528. {
  529. // patch for SigmaTel
  530. ac97->build_ops = &patch_sigmatel_stac9700_ops;
  531. snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
  532. snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
  533. snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
  534. snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
  535. snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
  536. return 0;
  537. }
  538. static int snd_ac97_stac9758_output_jack_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  539. {
  540. static char *texts[5] = { "Input/Disabled", "Front Output",
  541. "Rear Output", "Center/LFE Output", "Mixer Output" };
  542. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  543. uinfo->count = 1;
  544. uinfo->value.enumerated.items = 5;
  545. if (uinfo->value.enumerated.item > 4)
  546. uinfo->value.enumerated.item = 4;
  547. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  548. return 0;
  549. }
  550. static int snd_ac97_stac9758_output_jack_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
  551. {
  552. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  553. int shift = kcontrol->private_value;
  554. unsigned short val;
  555. val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift;
  556. if (!(val & 4))
  557. ucontrol->value.enumerated.item[0] = 0;
  558. else
  559. ucontrol->value.enumerated.item[0] = 1 + (val & 3);
  560. return 0;
  561. }
  562. static int snd_ac97_stac9758_output_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  563. {
  564. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  565. int shift = kcontrol->private_value;
  566. unsigned short val;
  567. if (ucontrol->value.enumerated.item[0] > 4)
  568. return -EINVAL;
  569. if (ucontrol->value.enumerated.item[0] == 0)
  570. val = 0;
  571. else
  572. val = 4 | (ucontrol->value.enumerated.item[0] - 1);
  573. return ac97_update_bits_page(ac97, AC97_SIGMATEL_OUTSEL,
  574. 7 << shift, val << shift, 0);
  575. }
  576. static int snd_ac97_stac9758_input_jack_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  577. {
  578. static char *texts[7] = { "Mic2 Jack", "Mic1 Jack", "Line In Jack",
  579. "Front Jack", "Rear Jack", "Center/LFE Jack", "Mute" };
  580. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  581. uinfo->count = 1;
  582. uinfo->value.enumerated.items = 7;
  583. if (uinfo->value.enumerated.item > 6)
  584. uinfo->value.enumerated.item = 6;
  585. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  586. return 0;
  587. }
  588. static int snd_ac97_stac9758_input_jack_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
  589. {
  590. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  591. int shift = kcontrol->private_value;
  592. unsigned short val;
  593. val = ac97->regs[AC97_SIGMATEL_INSEL];
  594. ucontrol->value.enumerated.item[0] = (val >> shift) & 7;
  595. return 0;
  596. }
  597. static int snd_ac97_stac9758_input_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  598. {
  599. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  600. int shift = kcontrol->private_value;
  601. return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
  602. ucontrol->value.enumerated.item[0] << shift, 0);
  603. }
  604. static int snd_ac97_stac9758_phonesel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  605. {
  606. static char *texts[3] = { "None", "Front Jack", "Rear Jack" };
  607. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  608. uinfo->count = 1;
  609. uinfo->value.enumerated.items = 3;
  610. if (uinfo->value.enumerated.item > 2)
  611. uinfo->value.enumerated.item = 2;
  612. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  613. return 0;
  614. }
  615. static int snd_ac97_stac9758_phonesel_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
  616. {
  617. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  618. ucontrol->value.enumerated.item[0] = ac97->regs[AC97_SIGMATEL_IOMISC] & 3;
  619. return 0;
  620. }
  621. static int snd_ac97_stac9758_phonesel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  622. {
  623. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  624. return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3,
  625. ucontrol->value.enumerated.item[0], 0);
  626. }
  627. #define STAC9758_OUTPUT_JACK(xname, shift) \
  628. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
  629. .info = snd_ac97_stac9758_output_jack_info, \
  630. .get = snd_ac97_stac9758_output_jack_get, \
  631. .put = snd_ac97_stac9758_output_jack_put, \
  632. .private_value = shift }
  633. #define STAC9758_INPUT_JACK(xname, shift) \
  634. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
  635. .info = snd_ac97_stac9758_input_jack_info, \
  636. .get = snd_ac97_stac9758_input_jack_get, \
  637. .put = snd_ac97_stac9758_input_jack_put, \
  638. .private_value = shift }
  639. static const snd_kcontrol_new_t snd_ac97_sigmatel_stac9758_controls[] = {
  640. STAC9758_OUTPUT_JACK("Mic1 Jack", 1),
  641. STAC9758_OUTPUT_JACK("LineIn Jack", 4),
  642. STAC9758_OUTPUT_JACK("Front Jack", 7),
  643. STAC9758_OUTPUT_JACK("Rear Jack", 10),
  644. STAC9758_OUTPUT_JACK("Center/LFE Jack", 13),
  645. STAC9758_INPUT_JACK("Mic Input Source", 0),
  646. STAC9758_INPUT_JACK("Line Input Source", 8),
  647. {
  648. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  649. .name = "Headphone Amp",
  650. .info = snd_ac97_stac9758_phonesel_info,
  651. .get = snd_ac97_stac9758_phonesel_get,
  652. .put = snd_ac97_stac9758_phonesel_put
  653. },
  654. AC97_SINGLE("Exchange Center/LFE", AC97_SIGMATEL_IOMISC, 4, 1, 0),
  655. AC97_SINGLE("Headphone +3dB Boost", AC97_SIGMATEL_IOMISC, 8, 1, 0)
  656. };
  657. static int patch_sigmatel_stac9758_specific(ac97_t *ac97)
  658. {
  659. int err;
  660. err = patch_sigmatel_stac97xx_specific(ac97);
  661. if (err < 0)
  662. return err;
  663. err = patch_build_controls(ac97, snd_ac97_sigmatel_stac9758_controls,
  664. ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls));
  665. if (err < 0)
  666. return err;
  667. /* DAC-A direct */
  668. snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback");
  669. /* DAC-A to Mix = PCM */
  670. /* DAC-B direct = Surround */
  671. /* DAC-B to Mix */
  672. snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback");
  673. /* DAC-C direct = Center/LFE */
  674. return 0;
  675. }
  676. static struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = {
  677. .build_3d = patch_sigmatel_stac9700_3d,
  678. .build_specific = patch_sigmatel_stac9758_specific
  679. };
  680. int patch_sigmatel_stac9758(ac97_t * ac97)
  681. {
  682. static unsigned short regs[4] = {
  683. AC97_SIGMATEL_OUTSEL,
  684. AC97_SIGMATEL_IOMISC,
  685. AC97_SIGMATEL_INSEL,
  686. AC97_SIGMATEL_VARIOUS
  687. };
  688. static unsigned short def_regs[4] = {
  689. /* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */
  690. /* IOMISC */ 0x2001,
  691. /* INSEL */ 0x0201, /* LI:LI, MI:M1 */
  692. /* VARIOUS */ 0x0040
  693. };
  694. static unsigned short m675_regs[4] = {
  695. /* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */
  696. /* IOMISC */ 0x2102, /* HP amp on */
  697. /* INSEL */ 0x0203, /* LI:LI, MI:FR */
  698. /* VARIOUS */ 0x0041 /* stereo mic */
  699. };
  700. unsigned short *pregs = def_regs;
  701. int i;
  702. /* Gateway M675 notebook */
  703. if (ac97->pci &&
  704. ac97->subsystem_vendor == 0x107b &&
  705. ac97->subsystem_device == 0x0601)
  706. pregs = m675_regs;
  707. // patch for SigmaTel
  708. ac97->build_ops = &patch_sigmatel_stac9758_ops;
  709. /* FIXME: assume only page 0 for writing cache */
  710. snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
  711. for (i = 0; i < 4; i++)
  712. snd_ac97_write_cache(ac97, regs[i], pregs[i]);
  713. ac97->flags |= AC97_STEREO_MUTES;
  714. return 0;
  715. }
  716. /*
  717. * Cirrus Logic CS42xx codecs
  718. */
  719. static const snd_kcontrol_new_t snd_ac97_cirrus_controls_spdif[2] = {
  720. AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
  721. AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
  722. };
  723. static int patch_cirrus_build_spdif(ac97_t * ac97)
  724. {
  725. int err;
  726. /* con mask, pro mask, default */
  727. if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
  728. return err;
  729. /* switch, spsa */
  730. if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0)
  731. return err;
  732. switch (ac97->id & AC97_ID_CS_MASK) {
  733. case AC97_ID_CS4205:
  734. if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1)) < 0)
  735. return err;
  736. break;
  737. }
  738. /* set default PCM S/PDIF params */
  739. /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
  740. snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
  741. return 0;
  742. }
  743. static struct snd_ac97_build_ops patch_cirrus_ops = {
  744. .build_spdif = patch_cirrus_build_spdif
  745. };
  746. int patch_cirrus_spdif(ac97_t * ac97)
  747. {
  748. /* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.
  749. WHY CAN'T ANYONE FOLLOW THE BLOODY SPEC? *sigh*
  750. - sp/dif EA ID is not set, but sp/dif is always present.
  751. - enable/disable is spdif register bit 15.
  752. - sp/dif control register is 0x68. differs from AC97:
  753. - valid is bit 14 (vs 15)
  754. - no DRS
  755. - only 44.1/48k [00 = 48, 01=44,1] (AC97 is 00=44.1, 10=48)
  756. - sp/dif ssource select is in 0x5e bits 0,1.
  757. */
  758. ac97->build_ops = &patch_cirrus_ops;
  759. ac97->flags |= AC97_CS_SPDIF;
  760. ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
  761. ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
  762. snd_ac97_write_cache(ac97, AC97_CSR_ACMODE, 0x0080);
  763. return 0;
  764. }
  765. int patch_cirrus_cs4299(ac97_t * ac97)
  766. {
  767. /* force the detection of PC Beep */
  768. ac97->flags |= AC97_HAS_PC_BEEP;
  769. return patch_cirrus_spdif(ac97);
  770. }
  771. /*
  772. * Conexant codecs
  773. */
  774. static const snd_kcontrol_new_t snd_ac97_conexant_controls_spdif[1] = {
  775. AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
  776. };
  777. static int patch_conexant_build_spdif(ac97_t * ac97)
  778. {
  779. int err;
  780. /* con mask, pro mask, default */
  781. if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
  782. return err;
  783. /* switch */
  784. if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0)
  785. return err;
  786. /* set default PCM S/PDIF params */
  787. /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
  788. snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
  789. snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
  790. return 0;
  791. }
  792. static struct snd_ac97_build_ops patch_conexant_ops = {
  793. .build_spdif = patch_conexant_build_spdif
  794. };
  795. int patch_conexant(ac97_t * ac97)
  796. {
  797. ac97->build_ops = &patch_conexant_ops;
  798. ac97->flags |= AC97_CX_SPDIF;
  799. ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
  800. ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
  801. return 0;
  802. }
  803. /*
  804. * Analog Device AD18xx, AD19xx codecs
  805. */
  806. #ifdef CONFIG_PM
  807. static void ad18xx_resume(ac97_t *ac97)
  808. {
  809. static unsigned short setup_regs[] = {
  810. AC97_AD_MISC, AC97_AD_SERIAL_CFG, AC97_AD_JACK_SPDIF,
  811. };
  812. int i, codec;
  813. for (i = 0; i < (int)ARRAY_SIZE(setup_regs); i++) {
  814. unsigned short reg = setup_regs[i];
  815. if (test_bit(reg, ac97->reg_accessed)) {
  816. snd_ac97_write(ac97, reg, ac97->regs[reg]);
  817. snd_ac97_read(ac97, reg);
  818. }
  819. }
  820. if (! (ac97->flags & AC97_AD_MULTI))
  821. /* normal restore */
  822. snd_ac97_restore_status(ac97);
  823. else {
  824. /* restore the AD18xx codec configurations */
  825. for (codec = 0; codec < 3; codec++) {
  826. if (! ac97->spec.ad18xx.id[codec])
  827. continue;
  828. /* select single codec */
  829. snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
  830. ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
  831. ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
  832. }
  833. /* select all codecs */
  834. snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
  835. /* restore status */
  836. for (i = 2; i < 0x7c ; i += 2) {
  837. if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID)
  838. continue;
  839. if (test_bit(i, ac97->reg_accessed)) {
  840. /* handle multi codecs for AD18xx */
  841. if (i == AC97_PCM) {
  842. for (codec = 0; codec < 3; codec++) {
  843. if (! ac97->spec.ad18xx.id[codec])
  844. continue;
  845. /* select single codec */
  846. snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
  847. ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
  848. /* update PCM bits */
  849. ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
  850. }
  851. /* select all codecs */
  852. snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
  853. continue;
  854. } else if (i == AC97_AD_TEST ||
  855. i == AC97_AD_CODEC_CFG ||
  856. i == AC97_AD_SERIAL_CFG)
  857. continue; /* ignore */
  858. }
  859. snd_ac97_write(ac97, i, ac97->regs[i]);
  860. snd_ac97_read(ac97, i);
  861. }
  862. }
  863. snd_ac97_restore_iec958(ac97);
  864. }
  865. #endif
  866. int patch_ad1819(ac97_t * ac97)
  867. {
  868. unsigned short scfg;
  869. // patch for Analog Devices
  870. scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
  871. snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000); /* select all codecs */
  872. return 0;
  873. }
  874. static unsigned short patch_ad1881_unchained(ac97_t * ac97, int idx, unsigned short mask)
  875. {
  876. unsigned short val;
  877. // test for unchained codec
  878. snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, mask);
  879. snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000); /* ID0C, ID1C, SDIE = off */
  880. val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
  881. if ((val & 0xff40) != 0x5340)
  882. return 0;
  883. ac97->spec.ad18xx.unchained[idx] = mask;
  884. ac97->spec.ad18xx.id[idx] = val;
  885. ac97->spec.ad18xx.codec_cfg[idx] = 0x0000;
  886. return mask;
  887. }
  888. static int patch_ad1881_chained1(ac97_t * ac97, int idx, unsigned short codec_bits)
  889. {
  890. static int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 };
  891. unsigned short val;
  892. snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, cfg_bits[idx]);
  893. snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0004); // SDIE
  894. val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
  895. if ((val & 0xff40) != 0x5340)
  896. return 0;
  897. if (codec_bits)
  898. snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, codec_bits);
  899. ac97->spec.ad18xx.chained[idx] = cfg_bits[idx];
  900. ac97->spec.ad18xx.id[idx] = val;
  901. ac97->spec.ad18xx.codec_cfg[idx] = codec_bits ? codec_bits : 0x0004;
  902. return 1;
  903. }
  904. static void patch_ad1881_chained(ac97_t * ac97, int unchained_idx, int cidx1, int cidx2)
  905. {
  906. // already detected?
  907. if (ac97->spec.ad18xx.unchained[cidx1] || ac97->spec.ad18xx.chained[cidx1])
  908. cidx1 = -1;
  909. if (ac97->spec.ad18xx.unchained[cidx2] || ac97->spec.ad18xx.chained[cidx2])
  910. cidx2 = -1;
  911. if (cidx1 < 0 && cidx2 < 0)
  912. return;
  913. // test for chained codecs
  914. snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
  915. ac97->spec.ad18xx.unchained[unchained_idx]);
  916. snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002); // ID1C
  917. ac97->spec.ad18xx.codec_cfg[unchained_idx] = 0x0002;
  918. if (cidx1 >= 0) {
  919. if (patch_ad1881_chained1(ac97, cidx1, 0x0006)) // SDIE | ID1C
  920. patch_ad1881_chained1(ac97, cidx2, 0);
  921. else if (patch_ad1881_chained1(ac97, cidx2, 0x0006)) // SDIE | ID1C
  922. patch_ad1881_chained1(ac97, cidx1, 0);
  923. } else if (cidx2 >= 0) {
  924. patch_ad1881_chained1(ac97, cidx2, 0);
  925. }
  926. }
  927. static struct snd_ac97_build_ops patch_ad1881_build_ops = {
  928. #ifdef CONFIG_PM
  929. .resume = ad18xx_resume
  930. #endif
  931. };
  932. int patch_ad1881(ac97_t * ac97)
  933. {
  934. static const char cfg_idxs[3][2] = {
  935. {2, 1},
  936. {0, 2},
  937. {0, 1}
  938. };
  939. // patch for Analog Devices
  940. unsigned short codecs[3];
  941. unsigned short val;
  942. int idx, num;
  943. val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
  944. snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val);
  945. codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12));
  946. codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14));
  947. codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13));
  948. snd_runtime_check(codecs[0] | codecs[1] | codecs[2], goto __end);
  949. for (idx = 0; idx < 3; idx++)
  950. if (ac97->spec.ad18xx.unchained[idx])
  951. patch_ad1881_chained(ac97, idx, cfg_idxs[idx][0], cfg_idxs[idx][1]);
  952. if (ac97->spec.ad18xx.id[1]) {
  953. ac97->flags |= AC97_AD_MULTI;
  954. ac97->scaps |= AC97_SCAP_SURROUND_DAC;
  955. }
  956. if (ac97->spec.ad18xx.id[2]) {
  957. ac97->flags |= AC97_AD_MULTI;
  958. ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC;
  959. }
  960. __end:
  961. /* select all codecs */
  962. snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
  963. /* check if only one codec is present */
  964. for (idx = num = 0; idx < 3; idx++)
  965. if (ac97->spec.ad18xx.id[idx])
  966. num++;
  967. if (num == 1) {
  968. /* ok, deselect all ID bits */
  969. snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000);
  970. ac97->spec.ad18xx.codec_cfg[0] =
  971. ac97->spec.ad18xx.codec_cfg[1] =
  972. ac97->spec.ad18xx.codec_cfg[2] = 0x0000;
  973. }
  974. /* required for AD1886/AD1885 combination */
  975. ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID);
  976. if (ac97->spec.ad18xx.id[0]) {
  977. ac97->id &= 0xffff0000;
  978. ac97->id |= ac97->spec.ad18xx.id[0];
  979. }
  980. ac97->build_ops = &patch_ad1881_build_ops;
  981. return 0;
  982. }
  983. static const snd_kcontrol_new_t snd_ac97_controls_ad1885[] = {
  984. AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
  985. /* AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0), */ /* seems problematic */
  986. AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
  987. AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
  988. AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 9, 1, 1), /* inverted */
  989. AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
  990. };
  991. static int patch_ad1885_specific(ac97_t * ac97)
  992. {
  993. int err;
  994. if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0)
  995. return err;
  996. return 0;
  997. }
  998. static struct snd_ac97_build_ops patch_ad1885_build_ops = {
  999. .build_specific = &patch_ad1885_specific,
  1000. #ifdef CONFIG_PM
  1001. .resume = ad18xx_resume
  1002. #endif
  1003. };
  1004. int patch_ad1885(ac97_t * ac97)
  1005. {
  1006. patch_ad1881(ac97);
  1007. /* This is required to deal with the Intel D815EEAL2 */
  1008. /* i.e. Line out is actually headphone out from codec */
  1009. /* set default */
  1010. snd_ac97_write_cache(ac97, AC97_AD_MISC, 0x0404);
  1011. ac97->build_ops = &patch_ad1885_build_ops;
  1012. return 0;
  1013. }
  1014. int patch_ad1886(ac97_t * ac97)
  1015. {
  1016. patch_ad1881(ac97);
  1017. /* Presario700 workaround */
  1018. /* for Jack Sense/SPDIF Register misetting causing */
  1019. snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010);
  1020. return 0;
  1021. }
  1022. /* MISC bits */
  1023. #define AC97_AD198X_MBC 0x0003 /* mic boost */
  1024. #define AC97_AD198X_MBC_20 0x0000 /* +20dB */
  1025. #define AC97_AD198X_MBC_10 0x0001 /* +10dB */
  1026. #define AC97_AD198X_MBC_30 0x0002 /* +30dB */
  1027. #define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */
  1028. #define AC97_AD198X_VREFH 0x0008 /* 2.25V, 3.7V */
  1029. #define AC97_AD198X_VREF_0 0x000c /* 0V */
  1030. #define AC97_AD198X_SRU 0x0010 /* sample rate unlock */
  1031. #define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */
  1032. #define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */
  1033. #define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */
  1034. #define AC97_AD198X_DMIX0 0x0100 /* downmix mode: 0 = 6-to-4, 1 = 6-to-2 downmix */
  1035. #define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */
  1036. #define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */
  1037. #define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */
  1038. #define AC97_AD198X_LODIS 0x1000 /* LINE_OUT disable */
  1039. #define AC97_AD198X_MSPLT 0x2000 /* mute split */
  1040. #define AC97_AD198X_AC97NC 0x4000 /* AC97 no compatible mode */
  1041. #define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */
  1042. static int snd_ac97_ad198x_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  1043. {
  1044. static char *texts[2] = { "AC-Link", "A/D Converter" };
  1045. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  1046. uinfo->count = 1;
  1047. uinfo->value.enumerated.items = 2;
  1048. if (uinfo->value.enumerated.item > 1)
  1049. uinfo->value.enumerated.item = 1;
  1050. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  1051. return 0;
  1052. }
  1053. static int snd_ac97_ad198x_spdif_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  1054. {
  1055. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1056. unsigned short val;
  1057. val = ac97->regs[AC97_AD_SERIAL_CFG];
  1058. ucontrol->value.enumerated.item[0] = (val >> 2) & 1;
  1059. return 0;
  1060. }
  1061. static int snd_ac97_ad198x_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  1062. {
  1063. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1064. unsigned short val;
  1065. if (ucontrol->value.enumerated.item[0] > 1)
  1066. return -EINVAL;
  1067. val = ucontrol->value.enumerated.item[0] << 2;
  1068. return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);
  1069. }
  1070. static const snd_kcontrol_new_t snd_ac97_ad198x_spdif_source = {
  1071. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1072. .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
  1073. .info = snd_ac97_ad198x_spdif_source_info,
  1074. .get = snd_ac97_ad198x_spdif_source_get,
  1075. .put = snd_ac97_ad198x_spdif_source_put,
  1076. };
  1077. static int patch_ad198x_post_spdif(ac97_t * ac97)
  1078. {
  1079. return patch_build_controls(ac97, &snd_ac97_ad198x_spdif_source, 1);
  1080. }
  1081. static const snd_kcontrol_new_t snd_ac97_ad1981x_jack_sense[] = {
  1082. AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 11, 1, 0),
  1083. AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
  1084. };
  1085. static int patch_ad1981a_specific(ac97_t * ac97)
  1086. {
  1087. return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
  1088. ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
  1089. }
  1090. static struct snd_ac97_build_ops patch_ad1981a_build_ops = {
  1091. .build_post_spdif = patch_ad198x_post_spdif,
  1092. .build_specific = patch_ad1981a_specific,
  1093. #ifdef CONFIG_PM
  1094. .resume = ad18xx_resume
  1095. #endif
  1096. };
  1097. static void check_ad1981_hp_jack_sense(ac97_t *ac97)
  1098. {
  1099. u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device;
  1100. switch (subid) {
  1101. case 0x103c0890: /* HP nc6000 */
  1102. case 0x103c006d: /* HP nx9105 */
  1103. case 0x17340088: /* FSC Scenic-W */
  1104. /* enable headphone jack sense */
  1105. snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11);
  1106. break;
  1107. }
  1108. }
  1109. int patch_ad1981a(ac97_t *ac97)
  1110. {
  1111. patch_ad1881(ac97);
  1112. ac97->build_ops = &patch_ad1981a_build_ops;
  1113. snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
  1114. ac97->flags |= AC97_STEREO_MUTES;
  1115. check_ad1981_hp_jack_sense(ac97);
  1116. return 0;
  1117. }
  1118. static const snd_kcontrol_new_t snd_ac97_ad198x_2cmic =
  1119. AC97_SINGLE("Stereo Mic", AC97_AD_MISC, 6, 1, 0);
  1120. static int patch_ad1981b_specific(ac97_t *ac97)
  1121. {
  1122. int err;
  1123. if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
  1124. return err;
  1125. return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
  1126. ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
  1127. }
  1128. static struct snd_ac97_build_ops patch_ad1981b_build_ops = {
  1129. .build_post_spdif = patch_ad198x_post_spdif,
  1130. .build_specific = patch_ad1981b_specific,
  1131. #ifdef CONFIG_PM
  1132. .resume = ad18xx_resume
  1133. #endif
  1134. };
  1135. int patch_ad1981b(ac97_t *ac97)
  1136. {
  1137. patch_ad1881(ac97);
  1138. ac97->build_ops = &patch_ad1981b_build_ops;
  1139. snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
  1140. ac97->flags |= AC97_STEREO_MUTES;
  1141. check_ad1981_hp_jack_sense(ac97);
  1142. return 0;
  1143. }
  1144. static int snd_ac97_ad1888_lohpsel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  1145. {
  1146. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  1147. uinfo->count = 1;
  1148. uinfo->value.integer.min = 0;
  1149. uinfo->value.integer.max = 1;
  1150. return 0;
  1151. }
  1152. static int snd_ac97_ad1888_lohpsel_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
  1153. {
  1154. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1155. unsigned short val;
  1156. val = ac97->regs[AC97_AD_MISC];
  1157. ucontrol->value.integer.value[0] = !(val & AC97_AD198X_LOSEL);
  1158. return 0;
  1159. }
  1160. static int snd_ac97_ad1888_lohpsel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  1161. {
  1162. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1163. unsigned short val;
  1164. val = !ucontrol->value.integer.value[0]
  1165. ? (AC97_AD198X_LOSEL | AC97_AD198X_HPSEL) : 0;
  1166. return snd_ac97_update_bits(ac97, AC97_AD_MISC,
  1167. AC97_AD198X_LOSEL | AC97_AD198X_HPSEL, val);
  1168. }
  1169. static int snd_ac97_ad1888_downmix_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  1170. {
  1171. static char *texts[3] = {"Off", "6 -> 4", "6 -> 2"};
  1172. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  1173. uinfo->count = 1;
  1174. uinfo->value.enumerated.items = 3;
  1175. if (uinfo->value.enumerated.item > 2)
  1176. uinfo->value.enumerated.item = 2;
  1177. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  1178. return 0;
  1179. }
  1180. static int snd_ac97_ad1888_downmix_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
  1181. {
  1182. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1183. unsigned short val;
  1184. val = ac97->regs[AC97_AD_MISC];
  1185. if (!(val & AC97_AD198X_DMIX1))
  1186. ucontrol->value.enumerated.item[0] = 0;
  1187. else
  1188. ucontrol->value.enumerated.item[0] = 1 + ((val >> 8) & 1);
  1189. return 0;
  1190. }
  1191. static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  1192. {
  1193. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1194. unsigned short val;
  1195. if (ucontrol->value.enumerated.item[0] > 2)
  1196. return -EINVAL;
  1197. if (ucontrol->value.enumerated.item[0] == 0)
  1198. val = 0;
  1199. else
  1200. val = AC97_AD198X_DMIX1 |
  1201. ((ucontrol->value.enumerated.item[0] - 1) << 8);
  1202. return snd_ac97_update_bits(ac97, AC97_AD_MISC,
  1203. AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
  1204. }
  1205. static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
  1206. {
  1207. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1208. .name = "Exchange Front/Surround",
  1209. .info = snd_ac97_ad1888_lohpsel_info,
  1210. .get = snd_ac97_ad1888_lohpsel_get,
  1211. .put = snd_ac97_ad1888_lohpsel_put
  1212. },
  1213. AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0),
  1214. {
  1215. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1216. .name = "Downmix",
  1217. .info = snd_ac97_ad1888_downmix_info,
  1218. .get = snd_ac97_ad1888_downmix_get,
  1219. .put = snd_ac97_ad1888_downmix_put
  1220. },
  1221. AC97_SINGLE("Surround Jack as Input", AC97_AD_MISC, 12, 1, 0),
  1222. AC97_SINGLE("Center/LFE Jack as Input", AC97_AD_MISC, 11, 1, 0),
  1223. };
  1224. static int patch_ad1888_specific(ac97_t *ac97)
  1225. {
  1226. /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
  1227. snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Master Surround Playback");
  1228. snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
  1229. return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
  1230. }
  1231. static struct snd_ac97_build_ops patch_ad1888_build_ops = {
  1232. .build_post_spdif = patch_ad198x_post_spdif,
  1233. .build_specific = patch_ad1888_specific,
  1234. #ifdef CONFIG_PM
  1235. .resume = ad18xx_resume
  1236. #endif
  1237. };
  1238. int patch_ad1888(ac97_t * ac97)
  1239. {
  1240. unsigned short misc;
  1241. patch_ad1881(ac97);
  1242. ac97->build_ops = &patch_ad1888_build_ops;
  1243. /* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
  1244. /* it seems that most vendors connect line-out connector to headphone out of AC'97 */
  1245. /* AD-compatible mode */
  1246. /* Stereo mutes enabled */
  1247. misc = snd_ac97_read(ac97, AC97_AD_MISC);
  1248. snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
  1249. AC97_AD198X_LOSEL |
  1250. AC97_AD198X_HPSEL |
  1251. AC97_AD198X_MSPLT |
  1252. AC97_AD198X_AC97NC);
  1253. ac97->flags |= AC97_STEREO_MUTES;
  1254. return 0;
  1255. }
  1256. static int patch_ad1980_specific(ac97_t *ac97)
  1257. {
  1258. int err;
  1259. if ((err = patch_ad1888_specific(ac97)) < 0)
  1260. return err;
  1261. return patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
  1262. }
  1263. static struct snd_ac97_build_ops patch_ad1980_build_ops = {
  1264. .build_post_spdif = patch_ad198x_post_spdif,
  1265. .build_specific = patch_ad1980_specific,
  1266. #ifdef CONFIG_PM
  1267. .resume = ad18xx_resume
  1268. #endif
  1269. };
  1270. int patch_ad1980(ac97_t * ac97)
  1271. {
  1272. patch_ad1888(ac97);
  1273. ac97->build_ops = &patch_ad1980_build_ops;
  1274. return 0;
  1275. }
  1276. static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = {
  1277. AC97_SINGLE("Center/LFE Jack as Mic", AC97_AD_SERIAL_CFG, 9, 1, 0),
  1278. AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0)
  1279. };
  1280. static int patch_ad1985_specific(ac97_t *ac97)
  1281. {
  1282. int err;
  1283. if ((err = patch_ad1980_specific(ac97)) < 0)
  1284. return err;
  1285. return patch_build_controls(ac97, snd_ac97_ad1985_controls, ARRAY_SIZE(snd_ac97_ad1985_controls));
  1286. }
  1287. static struct snd_ac97_build_ops patch_ad1985_build_ops = {
  1288. .build_post_spdif = patch_ad198x_post_spdif,
  1289. .build_specific = patch_ad1985_specific,
  1290. #ifdef CONFIG_PM
  1291. .resume = ad18xx_resume
  1292. #endif
  1293. };
  1294. int patch_ad1985(ac97_t * ac97)
  1295. {
  1296. unsigned short misc;
  1297. patch_ad1881(ac97);
  1298. ac97->build_ops = &patch_ad1985_build_ops;
  1299. misc = snd_ac97_read(ac97, AC97_AD_MISC);
  1300. /* switch front/surround line-out/hp-out */
  1301. /* center/LFE, mic in 3.75V mode */
  1302. /* AD-compatible mode */
  1303. /* Stereo mutes enabled */
  1304. /* in accordance with ADI driver: misc | 0x5c28 */
  1305. snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
  1306. AC97_AD198X_VREFH |
  1307. AC97_AD198X_LOSEL |
  1308. AC97_AD198X_HPSEL |
  1309. AC97_AD198X_CLDIS |
  1310. AC97_AD198X_LODIS |
  1311. AC97_AD198X_MSPLT |
  1312. AC97_AD198X_AC97NC);
  1313. ac97->flags |= AC97_STEREO_MUTES;
  1314. /* on AD1985 rev. 3, AC'97 revision bits are zero */
  1315. ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
  1316. return 0;
  1317. }
  1318. /*
  1319. * realtek ALC65x/850 codecs
  1320. */
  1321. static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
  1322. {
  1323. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1324. ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
  1325. return 0;
  1326. }
  1327. static int snd_ac97_alc650_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
  1328. {
  1329. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1330. int change, val;
  1331. val = !!(snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10));
  1332. change = (ucontrol->value.integer.value[0] != val);
  1333. if (change) {
  1334. /* disable/enable vref */
  1335. snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
  1336. ucontrol->value.integer.value[0] ? (1 << 12) : 0);
  1337. /* turn on/off center-on-mic */
  1338. snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
  1339. ucontrol->value.integer.value[0] ? (1 << 10) : 0);
  1340. /* GPIO0 high for mic */
  1341. snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
  1342. ucontrol->value.integer.value[0] ? 0 : 0x100);
  1343. }
  1344. return change;
  1345. }
  1346. static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
  1347. AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
  1348. AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
  1349. AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
  1350. AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
  1351. /* 4: Analog Input To Surround */
  1352. /* 5: Analog Input To Center/LFE */
  1353. /* 6: Independent Master Volume Right */
  1354. /* 7: Independent Master Volume Left */
  1355. /* 8: reserved */
  1356. AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
  1357. /* 10: mic, see below */
  1358. /* 11-13: in IEC958 controls */
  1359. AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
  1360. #if 0 /* always set in patch_alc650 */
  1361. AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
  1362. AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
  1363. AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
  1364. AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
  1365. AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
  1366. AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
  1367. #endif
  1368. {
  1369. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1370. .name = "Mic As Center/LFE",
  1371. .info = snd_ac97_info_volsw,
  1372. .get = snd_ac97_alc650_mic_get,
  1373. .put = snd_ac97_alc650_mic_put,
  1374. .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
  1375. },
  1376. };
  1377. static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
  1378. AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
  1379. AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
  1380. /* disable this controls since it doesn't work as expected */
  1381. /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
  1382. };
  1383. static int patch_alc650_specific(ac97_t * ac97)
  1384. {
  1385. int err;
  1386. if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650))) < 0)
  1387. return err;
  1388. if (ac97->ext_id & AC97_EI_SPDIF) {
  1389. if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
  1390. return err;
  1391. }
  1392. return 0;
  1393. }
  1394. static struct snd_ac97_build_ops patch_alc650_ops = {
  1395. .build_specific = patch_alc650_specific
  1396. };
  1397. int patch_alc650(ac97_t * ac97)
  1398. {
  1399. unsigned short val;
  1400. ac97->build_ops = &patch_alc650_ops;
  1401. /* determine the revision */
  1402. val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
  1403. if (val < 3)
  1404. ac97->id = 0x414c4720; /* Old version */
  1405. else if (val < 0x10)
  1406. ac97->id = 0x414c4721; /* D version */
  1407. else if (val < 0x20)
  1408. ac97->id = 0x414c4722; /* E version */
  1409. else if (val < 0x30)
  1410. ac97->id = 0x414c4723; /* F version */
  1411. /* revision E or F */
  1412. /* FIXME: what about revision D ? */
  1413. ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
  1414. ac97->id == 0x414c4723);
  1415. /* enable AC97_ALC650_GPIO_SETUP, AC97_ALC650_CLOCK for R/W */
  1416. snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
  1417. snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
  1418. /* Enable SPDIF-IN only on Rev.E and above */
  1419. val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
  1420. /* SPDIF IN with pin 47 */
  1421. if (ac97->spec.dev_flags)
  1422. val |= 0x03; /* enable */
  1423. else
  1424. val &= ~0x03; /* disable */
  1425. snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK, val);
  1426. /* set default: slot 3,4,7,8,6,9
  1427. spdif-in monitor off, analog-spdif off, spdif-in off
  1428. center on mic off, surround on line-in off
  1429. downmix off, duplicate front off
  1430. */
  1431. snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 0);
  1432. /* set GPIO0 for mic bias */
  1433. /* GPIO0 pin output, no interrupt, high */
  1434. snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP,
  1435. snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP) | 0x01);
  1436. snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
  1437. (snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x100) & ~0x10);
  1438. /* full DAC volume */
  1439. snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
  1440. snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
  1441. return 0;
  1442. }
  1443. static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
  1444. {
  1445. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1446. ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
  1447. return 0;
  1448. }
  1449. static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
  1450. {
  1451. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1452. /* misc control; vrefout disable */
  1453. snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
  1454. ucontrol->value.integer.value[0] ? (1 << 12) : 0);
  1455. return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
  1456. ucontrol->value.integer.value[0] ? (1 << 10) : 0,
  1457. 0);
  1458. }
  1459. static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = {
  1460. AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
  1461. AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0),
  1462. {
  1463. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1464. .name = "Mic As Center/LFE",
  1465. .info = snd_ac97_info_volsw,
  1466. .get = snd_ac97_alc655_mic_get,
  1467. .put = snd_ac97_alc655_mic_put,
  1468. .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
  1469. },
  1470. };
  1471. static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  1472. {
  1473. static char *texts_655[3] = { "PCM", "Analog In", "IEC958 In" };
  1474. static char *texts_658[4] = { "PCM", "Analog1 In", "Analog2 In", "IEC958 In" };
  1475. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1476. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  1477. uinfo->count = 1;
  1478. uinfo->value.enumerated.items = ac97->spec.dev_flags ? 4 : 3;
  1479. if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
  1480. uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
  1481. strcpy(uinfo->value.enumerated.name,
  1482. ac97->spec.dev_flags ?
  1483. texts_658[uinfo->value.enumerated.item] :
  1484. texts_655[uinfo->value.enumerated.item]);
  1485. return 0;
  1486. }
  1487. static int alc655_iec958_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  1488. {
  1489. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1490. unsigned short val;
  1491. val = ac97->regs[AC97_ALC650_MULTICH];
  1492. val = (val >> 12) & 3;
  1493. if (ac97->spec.dev_flags && val == 3)
  1494. val = 0;
  1495. ucontrol->value.enumerated.item[0] = val;
  1496. return 0;
  1497. }
  1498. static int alc655_iec958_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  1499. {
  1500. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1501. return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
  1502. (unsigned short)ucontrol->value.enumerated.item[0] << 12,
  1503. 0);
  1504. }
  1505. static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc655[] = {
  1506. AC97_PAGE_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0, 0),
  1507. /* disable this controls since it doesn't work as expected */
  1508. /* AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0), */
  1509. {
  1510. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1511. .name = "IEC958 Playback Route",
  1512. .info = alc655_iec958_route_info,
  1513. .get = alc655_iec958_route_get,
  1514. .put = alc655_iec958_route_put,
  1515. },
  1516. };
  1517. static int patch_alc655_specific(ac97_t * ac97)
  1518. {
  1519. int err;
  1520. if ((err = patch_build_controls(ac97, snd_ac97_controls_alc655, ARRAY_SIZE(snd_ac97_controls_alc655))) < 0)
  1521. return err;
  1522. if (ac97->ext_id & AC97_EI_SPDIF) {
  1523. if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
  1524. return err;
  1525. }
  1526. return 0;
  1527. }
  1528. static struct snd_ac97_build_ops patch_alc655_ops = {
  1529. .build_specific = patch_alc655_specific
  1530. };
  1531. int patch_alc655(ac97_t * ac97)
  1532. {
  1533. unsigned int val;
  1534. ac97->spec.dev_flags = (ac97->id == 0x414c4780); /* ALC658 */
  1535. ac97->build_ops = &patch_alc655_ops;
  1536. /* assume only page 0 for writing cache */
  1537. snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
  1538. /* adjust default values */
  1539. val = snd_ac97_read(ac97, 0x7a); /* misc control */
  1540. if (ac97->id == 0x414c4780) /* ALC658 */
  1541. val &= ~(1 << 1); /* Pin 47 is spdif input pin */
  1542. else /* ALC655 */
  1543. val |= (1 << 1); /* Pin 47 is spdif input pin */
  1544. val &= ~(1 << 12); /* vref enable */
  1545. snd_ac97_write_cache(ac97, 0x7a, val);
  1546. /* set default: spdif-in enabled,
  1547. spdif-in monitor off, spdif-in PCM off
  1548. center on mic off, surround on line-in off
  1549. duplicate front off
  1550. */
  1551. snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
  1552. /* full DAC volume */
  1553. snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
  1554. snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
  1555. return 0;
  1556. }
  1557. #define AC97_ALC850_JACK_SELECT 0x76
  1558. #define AC97_ALC850_MISC1 0x7a
  1559. static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
  1560. {
  1561. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1562. ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2;
  1563. return 0;
  1564. }
  1565. static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
  1566. {
  1567. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1568. /* SURR 1kOhm (bit4), Amp (bit5) */
  1569. snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
  1570. ucontrol->value.integer.value[0] ? (1<<5) : (1<<4));
  1571. /* LINE-IN = 0, SURROUND = 2 */
  1572. return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
  1573. ucontrol->value.integer.value[0] ? (2<<12) : (0<<12));
  1574. }
  1575. static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
  1576. {
  1577. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1578. ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2;
  1579. return 0;
  1580. }
  1581. static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
  1582. {
  1583. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1584. /* Vref disable (bit12), 1kOhm (bit13) */
  1585. snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
  1586. ucontrol->value.integer.value[0] ? (1<<12) : (1<<13));
  1587. /* MIC-IN = 1, CENTER-LFE = 2 */
  1588. return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
  1589. ucontrol->value.integer.value[0] ? (2<<4) : (1<<4));
  1590. }
  1591. static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = {
  1592. AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
  1593. {
  1594. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1595. .name = "Line-In As Surround",
  1596. .info = snd_ac97_info_volsw,
  1597. .get = ac97_alc850_surround_get,
  1598. .put = ac97_alc850_surround_put,
  1599. .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
  1600. },
  1601. {
  1602. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1603. .name = "Mic As Center/LFE",
  1604. .info = snd_ac97_info_volsw,
  1605. .get = ac97_alc850_mic_get,
  1606. .put = ac97_alc850_mic_put,
  1607. .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
  1608. },
  1609. };
  1610. static int patch_alc850_specific(ac97_t *ac97)
  1611. {
  1612. int err;
  1613. if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0)
  1614. return err;
  1615. if (ac97->ext_id & AC97_EI_SPDIF) {
  1616. if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
  1617. return err;
  1618. }
  1619. return 0;
  1620. }
  1621. static struct snd_ac97_build_ops patch_alc850_ops = {
  1622. .build_specific = patch_alc850_specific
  1623. };
  1624. int patch_alc850(ac97_t *ac97)
  1625. {
  1626. ac97->build_ops = &patch_alc850_ops;
  1627. ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
  1628. /* assume only page 0 for writing cache */
  1629. snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
  1630. /* adjust default values */
  1631. /* set default: spdif-in enabled,
  1632. spdif-in monitor off, spdif-in PCM off
  1633. center on mic off, surround on line-in off
  1634. duplicate front off
  1635. */
  1636. snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
  1637. /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
  1638. * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on
  1639. */
  1640. snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|
  1641. (1<<7)|(0<<12)|(1<<13)|(0<<14));
  1642. /* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable,
  1643. * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute
  1644. */
  1645. snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|
  1646. (1<<11)|(0<<12)|(1<<15));
  1647. /* full DAC volume */
  1648. snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
  1649. snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
  1650. return 0;
  1651. }
  1652. /*
  1653. * C-Media CM97xx codecs
  1654. */
  1655. static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
  1656. AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
  1657. AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
  1658. };
  1659. static int patch_cm9738_specific(ac97_t * ac97)
  1660. {
  1661. return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));
  1662. }
  1663. static struct snd_ac97_build_ops patch_cm9738_ops = {
  1664. .build_specific = patch_cm9738_specific
  1665. };
  1666. int patch_cm9738(ac97_t * ac97)
  1667. {
  1668. ac97->build_ops = &patch_cm9738_ops;
  1669. /* FIXME: can anyone confirm below? */
  1670. /* CM9738 has no PCM volume although the register reacts */
  1671. ac97->flags |= AC97_HAS_NO_PCM_VOL;
  1672. snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
  1673. return 0;
  1674. }
  1675. static int snd_ac97_cmedia_spdif_playback_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  1676. {
  1677. static char *texts[] = { "Analog", "Digital" };
  1678. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  1679. uinfo->count = 1;
  1680. uinfo->value.enumerated.items = 2;
  1681. if (uinfo->value.enumerated.item > 1)
  1682. uinfo->value.enumerated.item = 1;
  1683. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  1684. return 0;
  1685. }
  1686. static int snd_ac97_cmedia_spdif_playback_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  1687. {
  1688. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1689. unsigned short val;
  1690. val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
  1691. ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
  1692. return 0;
  1693. }
  1694. static int snd_ac97_cmedia_spdif_playback_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  1695. {
  1696. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1697. return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
  1698. 0x01 << 1,
  1699. (ucontrol->value.enumerated.item[0] & 0x01) << 1);
  1700. }
  1701. static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
  1702. /* BIT 0: SPDI_EN - always true */
  1703. { /* BIT 1: SPDIFS */
  1704. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1705. .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
  1706. .info = snd_ac97_cmedia_spdif_playback_source_info,
  1707. .get = snd_ac97_cmedia_spdif_playback_source_get,
  1708. .put = snd_ac97_cmedia_spdif_playback_source_put,
  1709. },
  1710. /* BIT 2: IG_SPIV */
  1711. AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
  1712. /* BIT 3: SPI2F */
  1713. AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
  1714. /* BIT 4: SPI2SDI */
  1715. AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),
  1716. /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
  1717. };
  1718. static int snd_ac97_cm9739_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  1719. {
  1720. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1721. if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
  1722. ucontrol->value.integer.value[0] = 1;
  1723. else
  1724. ucontrol->value.integer.value[0] = 0;
  1725. return 0;
  1726. }
  1727. static int snd_ac97_cm9739_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  1728. {
  1729. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1730. return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
  1731. ucontrol->value.integer.value[0] ?
  1732. 0x1000 : 0x2000);
  1733. }
  1734. static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
  1735. AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),
  1736. {
  1737. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1738. .name = "Mic As Center/LFE",
  1739. .info = snd_ac97_info_volsw,
  1740. .get = snd_ac97_cm9739_center_mic_get,
  1741. .put = snd_ac97_cm9739_center_mic_put,
  1742. .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
  1743. },
  1744. };
  1745. static int patch_cm9739_specific(ac97_t * ac97)
  1746. {
  1747. return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));
  1748. }
  1749. static int patch_cm9739_post_spdif(ac97_t * ac97)
  1750. {
  1751. return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
  1752. }
  1753. static struct snd_ac97_build_ops patch_cm9739_ops = {
  1754. .build_specific = patch_cm9739_specific,
  1755. .build_post_spdif = patch_cm9739_post_spdif
  1756. };
  1757. int patch_cm9739(ac97_t * ac97)
  1758. {
  1759. unsigned short val;
  1760. ac97->build_ops = &patch_cm9739_ops;
  1761. /* CM9739/A has no Master and PCM volume although the register reacts */
  1762. ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;
  1763. snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);
  1764. snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
  1765. /* check spdif */
  1766. val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
  1767. if (val & AC97_EA_SPCV) {
  1768. /* enable spdif in */
  1769. snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
  1770. snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);
  1771. ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
  1772. } else {
  1773. ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */
  1774. ac97->rates[AC97_RATES_SPDIF] = 0;
  1775. }
  1776. /* set-up multi channel */
  1777. /* bit 14: 0 = SPDIF, 1 = EAPD */
  1778. /* bit 13: enable internal vref output for mic */
  1779. /* bit 12: disable center/lfe (swithable) */
  1780. /* bit 10: disable surround/line (switchable) */
  1781. /* bit 9: mix 2 surround off */
  1782. /* bit 4: undocumented; 0 mutes the CM9739A, which defaults to 1 */
  1783. /* bit 3: undocumented; surround? */
  1784. /* bit 0: dB */
  1785. val = snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) & (1 << 4);
  1786. val |= (1 << 3);
  1787. val |= (1 << 13);
  1788. if (! (ac97->ext_id & AC97_EI_SPDIF))
  1789. val |= (1 << 14);
  1790. snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val);
  1791. /* FIXME: set up GPIO */
  1792. snd_ac97_write_cache(ac97, 0x70, 0x0100);
  1793. snd_ac97_write_cache(ac97, 0x72, 0x0020);
  1794. /* Special exception for ASUS W1000/CMI9739. It does not have an SPDIF in. */
  1795. if (ac97->pci &&
  1796. ac97->subsystem_vendor == 0x1043 &&
  1797. ac97->subsystem_device == 0x1843) {
  1798. snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
  1799. snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) & ~0x01);
  1800. snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN,
  1801. snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) | (1 << 14));
  1802. }
  1803. return 0;
  1804. }
  1805. #define AC97_CM9761_MULTI_CHAN 0x64
  1806. #define AC97_CM9761_SPDIF_CTRL 0x6c
  1807. static int snd_ac97_cm9761_linein_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  1808. {
  1809. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1810. if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x0400)
  1811. ucontrol->value.integer.value[0] = 1;
  1812. else
  1813. ucontrol->value.integer.value[0] = 0;
  1814. return 0;
  1815. }
  1816. static int snd_ac97_cm9761_linein_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  1817. {
  1818. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1819. unsigned short vals[2][2] = {
  1820. { 0x0008, 0x0400 }, /* off, on */
  1821. { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */
  1822. };
  1823. return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x0408,
  1824. vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
  1825. }
  1826. static int snd_ac97_cm9761_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  1827. {
  1828. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1829. if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
  1830. ucontrol->value.integer.value[0] = 1;
  1831. else
  1832. ucontrol->value.integer.value[0] = 0;
  1833. if (ac97->spec.dev_flags) /* 9761-82 rev.B */
  1834. ucontrol->value.integer.value[0] = !ucontrol->value.integer.value[0];
  1835. return 0;
  1836. }
  1837. static int snd_ac97_cm9761_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  1838. {
  1839. ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
  1840. unsigned short vals[2][2] = {
  1841. { 0x2000, 0x1880 }, /* off, on */
  1842. { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */
  1843. };
  1844. return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3880,
  1845. vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
  1846. }
  1847. static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
  1848. {
  1849. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1850. .name = "Line-In As Surround",
  1851. .info = snd_ac97_info_volsw,
  1852. .get = snd_ac97_cm9761_linein_rear_get,
  1853. .put = snd_ac97_cm9761_linein_rear_put,
  1854. .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
  1855. },
  1856. {
  1857. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1858. .name = "Mic As Center/LFE",
  1859. .info = snd_ac97_info_volsw,
  1860. .get = snd_ac97_cm9761_center_mic_get,
  1861. .put = snd_ac97_cm9761_center_mic_put,
  1862. .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
  1863. },
  1864. };
  1865. static int patch_cm9761_specific(ac97_t * ac97)
  1866. {
  1867. return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
  1868. }
  1869. static struct snd_ac97_build_ops patch_cm9761_ops = {
  1870. .build_specific = patch_cm9761_specific,
  1871. .build_post_spdif = patch_cm9739_post_spdif /* hope it's identical... */
  1872. };
  1873. int patch_cm9761(ac97_t *ac97)
  1874. {
  1875. unsigned short val;
  1876. /* CM9761 has no PCM volume although the register reacts */
  1877. /* Master volume seems to have _some_ influence on the analog
  1878. * input sounds
  1879. */
  1880. ac97->flags |= /*AC97_HAS_NO_MASTER_VOL |*/ AC97_HAS_NO_PCM_VOL;
  1881. snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808);
  1882. snd_ac97_write_cache(ac97, AC97_PCM, 0x8808);
  1883. ac97->spec.dev_flags = 0; /* 1 = model 82 revision B */
  1884. if (ac97->id == AC97_ID_CM9761_82) {
  1885. unsigned short tmp;
  1886. /* check page 1, reg 0x60 */
  1887. val = snd_ac97_read(ac97, AC97_INT_PAGING);
  1888. snd_ac97_write_cache(ac97, AC97_INT_PAGING, (val & ~0x0f) | 0x01);
  1889. tmp = snd_ac97_read(ac97, 0x60);
  1890. ac97->spec.dev_flags = tmp & 1; /* revision B? */
  1891. snd_ac97_write_cache(ac97, AC97_INT_PAGING, val);
  1892. }
  1893. ac97->build_ops = &patch_cm9761_ops;
  1894. /* enable spdif */
  1895. /* force the SPDIF bit in ext_id - codec doesn't set this bit! */
  1896. ac97->ext_id |= AC97_EI_SPDIF;
  1897. /* to be sure: we overwrite the ext status bits */
  1898. snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
  1899. /* Don't set 0x0200 here. This results in the silent analog output */
  1900. snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009);
  1901. ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
  1902. /* set-up multi channel */
  1903. /* bit 15: pc master beep off
  1904. * bit 14: ??
  1905. * bit 13: vref ctl [= cm9739]
  1906. * bit 12: center/mic [= cm9739] (reverted on rev B)
  1907. * bit 11: ?? (mic/center/lfe) (reverted on rev B)
  1908. * bit 10: suddound/line [= cm9739]
  1909. * bit 9: mix 2 surround
  1910. * bit 8: ?
  1911. * bit 7: ?? (mic/center/lfe)
  1912. * bit 4: ?? (front)
  1913. * bit 3: ?? (line-in/rear share) (revereted with rev B)
  1914. * bit 2: ?? (surround)
  1915. * bit 1: front mic
  1916. * bit 0: mic boost
  1917. */
  1918. #if 0
  1919. if (ac97->spec.dev_flags)
  1920. val = 0x0214;
  1921. else
  1922. val = 0x321c;
  1923. #endif
  1924. val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN);
  1925. val |= (1 << 4); /* front on */
  1926. snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
  1927. /* FIXME: set up GPIO */
  1928. snd_ac97_write_cache(ac97, 0x70, 0x0100);
  1929. snd_ac97_write_cache(ac97, 0x72, 0x0020);
  1930. return 0;
  1931. }
  1932. /*
  1933. * VIA VT1616 codec
  1934. */
  1935. static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {
  1936. AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
  1937. AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
  1938. AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
  1939. AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
  1940. };
  1941. static int patch_vt1616_specific(ac97_t * ac97)
  1942. {
  1943. int err;
  1944. if (snd_ac97_try_bit(ac97, 0x5a, 9))
  1945. if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1)) < 0)
  1946. return err;
  1947. if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0)
  1948. return err;
  1949. return 0;
  1950. }
  1951. static struct snd_ac97_build_ops patch_vt1616_ops = {
  1952. .build_specific = patch_vt1616_specific
  1953. };
  1954. int patch_vt1616(ac97_t * ac97)
  1955. {
  1956. ac97->build_ops = &patch_vt1616_ops;
  1957. return 0;
  1958. }
  1959. static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = {
  1960. AC97_SINGLE("Line-In As Surround", 0x76, 9, 1, 0),
  1961. AC97_SINGLE("Mic As Center/LFE", 0x76, 10, 1, 0),
  1962. };
  1963. static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = {
  1964. AC97_SINGLE("IEC958 Capture Switch", 0x76, 11, 1, 0),
  1965. AC97_SINGLE("Analog to IEC958 Output", 0x76, 12, 1, 0),
  1966. AC97_SINGLE("IEC958 Input Monitor", 0x76, 13, 1, 0),
  1967. };
  1968. static int patch_it2646_specific(ac97_t * ac97)
  1969. {
  1970. int err;
  1971. if ((err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646))) < 0)
  1972. return err;
  1973. if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_it2646, ARRAY_SIZE(snd_ac97_spdif_controls_it2646))) < 0)
  1974. return err;
  1975. return 0;
  1976. }
  1977. static struct snd_ac97_build_ops patch_it2646_ops = {
  1978. .build_specific = patch_it2646_specific
  1979. };
  1980. int patch_it2646(ac97_t * ac97)
  1981. {
  1982. ac97->build_ops = &patch_it2646_ops;
  1983. /* full DAC volume */
  1984. snd_ac97_write_cache(ac97, 0x5E, 0x0808);
  1985. snd_ac97_write_cache(ac97, 0x7A, 0x0808);
  1986. return 0;
  1987. }
  1988. /* Si3036/8 specific registers */
  1989. #define AC97_SI3036_CHIP_ID 0x5a
  1990. int mpatch_si3036(ac97_t * ac97)
  1991. {
  1992. //printk("mpatch_si3036: chip id = %x\n", snd_ac97_read(ac97, 0x5a));
  1993. snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
  1994. snd_ac97_write_cache(ac97, 0x68, 0);
  1995. return 0;
  1996. }