aureon.c 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948
  1. /*
  2. * ALSA driver for ICEnsemble VT1724 (Envy24HT)
  3. *
  4. * Lowlevel functions for Terratec Aureon cards
  5. *
  6. * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. *
  22. *
  23. * NOTES:
  24. *
  25. * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data.
  26. * both wm and akm codecs are pretty similar, so we can integrate
  27. * both controls in the future, once if wm codecs are reused in
  28. * many boards.
  29. *
  30. * - DAC digital volumes are not implemented in the mixer.
  31. * if they show better response than DAC analog volumes, we can use them
  32. * instead.
  33. *
  34. * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
  35. * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
  36. *
  37. * version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
  38. * added 64x/128x oversampling switch (should be 64x only for 96khz)
  39. * fixed some recording labels (still need to check the rest)
  40. * recording is working probably thanks to correct wm8770 initialization
  41. *
  42. * version 0.5: Initial release:
  43. * working: analog output, mixer, headphone amplifier switch
  44. * not working: prety much everything else, at least i could verify that
  45. * we have no digital output, no capture, pretty bad clicks and poops
  46. * on mixer switch and other coll stuff.
  47. *
  48. */
  49. #include <sound/driver.h>
  50. #include <asm/io.h>
  51. #include <linux/delay.h>
  52. #include <linux/interrupt.h>
  53. #include <linux/init.h>
  54. #include <linux/slab.h>
  55. #include <sound/core.h>
  56. #include "ice1712.h"
  57. #include "envy24ht.h"
  58. #include "aureon.h"
  59. /* WM8770 registers */
  60. #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
  61. #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
  62. #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
  63. #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
  64. #define WM_PHASE_SWAP 0x12 /* DAC phase */
  65. #define WM_DAC_CTRL1 0x13 /* DAC control bits */
  66. #define WM_MUTE 0x14 /* mute controls */
  67. #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
  68. #define WM_INT_CTRL 0x16 /* interface control */
  69. #define WM_MASTER 0x17 /* master clock and mode */
  70. #define WM_POWERDOWN 0x18 /* power-down controls */
  71. #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
  72. #define WM_ADC_MUX 0x1b /* input MUX */
  73. #define WM_OUT_MUX1 0x1c /* output MUX */
  74. #define WM_OUT_MUX2 0x1e /* output MUX */
  75. #define WM_RESET 0x1f /* software reset */
  76. /* CS8415A registers */
  77. #define CS8415_CTRL1 0x01
  78. #define CS8415_CTRL2 0x02
  79. #define CS8415_QSUB 0x14
  80. #define CS8415_RATIO 0x1E
  81. #define CS8415_C_BUFFER 0x20
  82. #define CS8415_ID 0x7F
  83. static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, unsigned short val) {
  84. unsigned int tmp;
  85. /* Send address to XILINX chip */
  86. tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
  87. snd_ice1712_gpio_write(ice, tmp);
  88. udelay(10);
  89. tmp |= AUREON_AC97_ADDR;
  90. snd_ice1712_gpio_write(ice, tmp);
  91. udelay(10);
  92. tmp &= ~AUREON_AC97_ADDR;
  93. snd_ice1712_gpio_write(ice, tmp);
  94. udelay(10);
  95. /* Send low-order byte to XILINX chip */
  96. tmp &= ~AUREON_AC97_DATA_MASK;
  97. tmp |= val & AUREON_AC97_DATA_MASK;
  98. snd_ice1712_gpio_write(ice, tmp);
  99. udelay(10);
  100. tmp |= AUREON_AC97_DATA_LOW;
  101. snd_ice1712_gpio_write(ice, tmp);
  102. udelay(10);
  103. tmp &= ~AUREON_AC97_DATA_LOW;
  104. snd_ice1712_gpio_write(ice, tmp);
  105. udelay(10);
  106. /* Send high-order byte to XILINX chip */
  107. tmp &= ~AUREON_AC97_DATA_MASK;
  108. tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
  109. snd_ice1712_gpio_write(ice, tmp);
  110. udelay(10);
  111. tmp |= AUREON_AC97_DATA_HIGH;
  112. snd_ice1712_gpio_write(ice, tmp);
  113. udelay(10);
  114. tmp &= ~AUREON_AC97_DATA_HIGH;
  115. snd_ice1712_gpio_write(ice, tmp);
  116. udelay(10);
  117. /* Instruct XILINX chip to parse the data to the STAC9744 chip */
  118. tmp |= AUREON_AC97_COMMIT;
  119. snd_ice1712_gpio_write(ice, tmp);
  120. udelay(10);
  121. tmp &= ~AUREON_AC97_COMMIT;
  122. snd_ice1712_gpio_write(ice, tmp);
  123. udelay(10);
  124. /* Store the data in out private buffer */
  125. ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
  126. }
  127. static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
  128. {
  129. return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
  130. }
  131. /*
  132. * Initialize STAC9744 chip
  133. */
  134. static int aureon_ac97_init (struct snd_ice1712 *ice) {
  135. int i;
  136. static unsigned short ac97_defaults[] = {
  137. 0x00, 0x9640,
  138. 0x02, 0x8000,
  139. 0x04, 0x8000,
  140. 0x06, 0x8000,
  141. 0x0C, 0x8008,
  142. 0x0E, 0x8008,
  143. 0x10, 0x8808,
  144. 0x12, 0x8808,
  145. 0x14, 0x8808,
  146. 0x16, 0x8808,
  147. 0x18, 0x8808,
  148. 0x1C, 0x8000,
  149. 0x26, 0x000F,
  150. 0x28, 0x0201,
  151. 0x2C, 0xBB80,
  152. 0x32, 0xBB80,
  153. 0x7C, 0x8384,
  154. 0x7E, 0x7644,
  155. (unsigned short)-1
  156. };
  157. unsigned int tmp;
  158. /* Cold reset */
  159. tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
  160. snd_ice1712_gpio_write(ice, tmp);
  161. udelay(3);
  162. tmp &= ~AUREON_AC97_RESET;
  163. snd_ice1712_gpio_write(ice, tmp);
  164. udelay(3);
  165. tmp |= AUREON_AC97_RESET;
  166. snd_ice1712_gpio_write(ice, tmp);
  167. udelay(3);
  168. memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744));
  169. for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
  170. ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
  171. aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
  172. return 0;
  173. }
  174. #define AUREON_AC97_STEREO 0x80
  175. /*
  176. * AC'97 volume controls
  177. */
  178. static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  179. {
  180. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  181. uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
  182. uinfo->value.integer.min = 0;
  183. uinfo->value.integer.max = 31;
  184. return 0;
  185. }
  186. static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  187. {
  188. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  189. unsigned short vol;
  190. down(&ice->gpio_mutex);
  191. vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
  192. ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
  193. if (kcontrol->private_value & AUREON_AC97_STEREO)
  194. ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
  195. up(&ice->gpio_mutex);
  196. return 0;
  197. }
  198. static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  199. {
  200. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  201. unsigned short ovol, nvol;
  202. int change;
  203. snd_ice1712_save_gpio_status(ice);
  204. ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
  205. nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
  206. if (kcontrol->private_value & AUREON_AC97_STEREO)
  207. nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
  208. nvol |= ovol & ~0x1F1F;
  209. if ((change = (ovol != nvol)))
  210. aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
  211. snd_ice1712_restore_gpio_status(ice);
  212. return change;
  213. }
  214. /*
  215. * AC'97 mute controls
  216. */
  217. #define aureon_ac97_mute_info aureon_mono_bool_info
  218. static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  219. {
  220. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  221. down(&ice->gpio_mutex);
  222. ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
  223. up(&ice->gpio_mutex);
  224. return 0;
  225. }
  226. static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  227. {
  228. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  229. unsigned short ovol, nvol;
  230. int change;
  231. snd_ice1712_save_gpio_status(ice);
  232. ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
  233. nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
  234. if ((change = (ovol != nvol)))
  235. aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
  236. snd_ice1712_restore_gpio_status(ice);
  237. return change;
  238. }
  239. /*
  240. * AC'97 mute controls
  241. */
  242. #define aureon_ac97_micboost_info aureon_mono_bool_info
  243. static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  244. {
  245. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  246. down(&ice->gpio_mutex);
  247. ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
  248. up(&ice->gpio_mutex);
  249. return 0;
  250. }
  251. static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  252. {
  253. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  254. unsigned short ovol, nvol;
  255. int change;
  256. snd_ice1712_save_gpio_status(ice);
  257. ovol = aureon_ac97_read(ice, AC97_MIC);
  258. nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
  259. if ((change = (ovol != nvol)))
  260. aureon_ac97_write(ice, AC97_MIC, nvol);
  261. snd_ice1712_restore_gpio_status(ice);
  262. return change;
  263. }
  264. /*
  265. * write data in the SPI mode
  266. */
  267. static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
  268. {
  269. unsigned int tmp;
  270. int i;
  271. tmp = snd_ice1712_gpio_read(ice);
  272. snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
  273. AUREON_WM_CS|AUREON_CS8415_CS));
  274. tmp |= AUREON_WM_RW;
  275. tmp &= ~cs;
  276. snd_ice1712_gpio_write(ice, tmp);
  277. udelay(1);
  278. for (i = bits - 1; i >= 0; i--) {
  279. tmp &= ~AUREON_SPI_CLK;
  280. snd_ice1712_gpio_write(ice, tmp);
  281. udelay(1);
  282. if (data & (1 << i))
  283. tmp |= AUREON_SPI_MOSI;
  284. else
  285. tmp &= ~AUREON_SPI_MOSI;
  286. snd_ice1712_gpio_write(ice, tmp);
  287. udelay(1);
  288. tmp |= AUREON_SPI_CLK;
  289. snd_ice1712_gpio_write(ice, tmp);
  290. udelay(1);
  291. }
  292. tmp &= ~AUREON_SPI_CLK;
  293. tmp |= cs;
  294. snd_ice1712_gpio_write(ice, tmp);
  295. udelay(1);
  296. tmp |= AUREON_SPI_CLK;
  297. snd_ice1712_gpio_write(ice, tmp);
  298. udelay(1);
  299. }
  300. /*
  301. * Read data in SPI mode
  302. */
  303. static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
  304. int i, j;
  305. unsigned int tmp;
  306. tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
  307. snd_ice1712_gpio_write(ice, tmp);
  308. tmp &= ~cs;
  309. snd_ice1712_gpio_write(ice, tmp);
  310. udelay(1);
  311. for (i=bits-1; i>=0; i--) {
  312. if (data & (1 << i))
  313. tmp |= AUREON_SPI_MOSI;
  314. else
  315. tmp &= ~AUREON_SPI_MOSI;
  316. snd_ice1712_gpio_write(ice, tmp);
  317. udelay(1);
  318. tmp |= AUREON_SPI_CLK;
  319. snd_ice1712_gpio_write(ice, tmp);
  320. udelay(1);
  321. tmp &= ~AUREON_SPI_CLK;
  322. snd_ice1712_gpio_write(ice, tmp);
  323. udelay(1);
  324. }
  325. for (j=0; j<size; j++) {
  326. unsigned char outdata = 0;
  327. for (i=7; i>=0; i--) {
  328. tmp = snd_ice1712_gpio_read(ice);
  329. outdata <<= 1;
  330. outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
  331. udelay(1);
  332. tmp |= AUREON_SPI_CLK;
  333. snd_ice1712_gpio_write(ice, tmp);
  334. udelay(1);
  335. tmp &= ~AUREON_SPI_CLK;
  336. snd_ice1712_gpio_write(ice, tmp);
  337. udelay(1);
  338. }
  339. buffer[j] = outdata;
  340. }
  341. tmp |= cs;
  342. snd_ice1712_gpio_write(ice, tmp);
  343. }
  344. static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) {
  345. unsigned char val;
  346. aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
  347. aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
  348. return val;
  349. }
  350. static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, unsigned char *buffer, int size) {
  351. aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
  352. aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
  353. }
  354. static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, unsigned char val) {
  355. aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
  356. }
  357. /*
  358. * get the current register value of WM codec
  359. */
  360. static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
  361. {
  362. reg <<= 1;
  363. return ((unsigned short)ice->akm[0].images[reg] << 8) |
  364. ice->akm[0].images[reg + 1];
  365. }
  366. /*
  367. * set the register value of WM codec
  368. */
  369. static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
  370. {
  371. aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
  372. }
  373. /*
  374. * set the register value of WM codec and remember it
  375. */
  376. static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
  377. {
  378. wm_put_nocache(ice, reg, val);
  379. reg <<= 1;
  380. ice->akm[0].images[reg] = val >> 8;
  381. ice->akm[0].images[reg + 1] = val;
  382. }
  383. /*
  384. */
  385. static int aureon_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
  386. {
  387. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  388. uinfo->count = 1;
  389. uinfo->value.integer.min = 0;
  390. uinfo->value.integer.max = 1;
  391. return 0;
  392. }
  393. /*
  394. * AC'97 master playback mute controls (Mute on WM8770 chip)
  395. */
  396. #define aureon_ac97_mmute_info aureon_mono_bool_info
  397. static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  398. {
  399. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  400. down(&ice->gpio_mutex);
  401. ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
  402. up(&ice->gpio_mutex);
  403. return 0;
  404. }
  405. static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
  406. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  407. unsigned short ovol, nvol;
  408. int change;
  409. snd_ice1712_save_gpio_status(ice);
  410. ovol = wm_get(ice, WM_OUT_MUX1);
  411. nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
  412. if ((change = (ovol != nvol)))
  413. wm_put(ice, WM_OUT_MUX1, nvol);
  414. snd_ice1712_restore_gpio_status(ice);
  415. return change;
  416. }
  417. /*
  418. * Logarithmic volume values for WM8770
  419. * Computed as 20 * Log10(255 / x)
  420. */
  421. static unsigned char wm_vol[256] = {
  422. 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
  423. 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
  424. 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
  425. 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
  426. 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
  427. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
  428. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  429. 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
  430. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  431. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  432. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  433. 0, 0
  434. };
  435. #define WM_VOL_MAX (sizeof(wm_vol) - 1)
  436. #define WM_VOL_MUTE 0x8000
  437. static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
  438. {
  439. unsigned char nvol;
  440. if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
  441. nvol = 0;
  442. else
  443. nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
  444. wm_put(ice, index, nvol);
  445. wm_put_nocache(ice, index, 0x180 | nvol);
  446. }
  447. /*
  448. * DAC mute control
  449. */
  450. #define wm_pcm_mute_info aureon_mono_bool_info
  451. static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  452. {
  453. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  454. down(&ice->gpio_mutex);
  455. ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
  456. up(&ice->gpio_mutex);
  457. return 0;
  458. }
  459. static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  460. {
  461. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  462. unsigned short nval, oval;
  463. int change;
  464. snd_ice1712_save_gpio_status(ice);
  465. oval = wm_get(ice, WM_MUTE);
  466. nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
  467. if ((change = (nval != oval)))
  468. wm_put(ice, WM_MUTE, nval);
  469. snd_ice1712_restore_gpio_status(ice);
  470. return change;
  471. }
  472. /*
  473. * Master volume attenuation mixer control
  474. */
  475. static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  476. {
  477. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  478. uinfo->count = 2;
  479. uinfo->value.integer.min = 0;
  480. uinfo->value.integer.max = WM_VOL_MAX;
  481. return 0;
  482. }
  483. static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  484. {
  485. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  486. int i;
  487. for (i=0; i<2; i++)
  488. ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
  489. return 0;
  490. }
  491. static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  492. {
  493. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  494. int ch, change = 0;
  495. snd_ice1712_save_gpio_status(ice);
  496. for (ch = 0; ch < 2; ch++) {
  497. if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
  498. int dac;
  499. ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
  500. ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
  501. for (dac = 0; dac < ice->num_total_dacs; dac += 2)
  502. wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
  503. ice->spec.aureon.vol[dac + ch],
  504. ice->spec.aureon.master[ch]);
  505. change = 1;
  506. }
  507. }
  508. snd_ice1712_restore_gpio_status(ice);
  509. return change;
  510. }
  511. /*
  512. * DAC volume attenuation mixer control
  513. */
  514. static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  515. {
  516. int voices = kcontrol->private_value >> 8;
  517. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  518. uinfo->count = voices;
  519. uinfo->value.integer.min = 0; /* mute (-101dB) */
  520. uinfo->value.integer.max = 0x7F; /* 0dB */
  521. return 0;
  522. }
  523. static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  524. {
  525. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  526. int i, ofs, voices;
  527. voices = kcontrol->private_value >> 8;
  528. ofs = kcontrol->private_value & 0xff;
  529. for (i = 0; i < voices; i++)
  530. ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
  531. return 0;
  532. }
  533. static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  534. {
  535. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  536. int i, idx, ofs, voices;
  537. int change = 0;
  538. voices = kcontrol->private_value >> 8;
  539. ofs = kcontrol->private_value & 0xff;
  540. snd_ice1712_save_gpio_status(ice);
  541. for (i = 0; i < voices; i++) {
  542. idx = WM_DAC_ATTEN + ofs + i;
  543. if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
  544. ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
  545. ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
  546. wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
  547. ice->spec.aureon.master[i]);
  548. change = 1;
  549. }
  550. }
  551. snd_ice1712_restore_gpio_status(ice);
  552. return change;
  553. }
  554. /*
  555. * WM8770 mute control
  556. */
  557. static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
  558. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  559. uinfo->count = kcontrol->private_value >> 8;
  560. uinfo->value.integer.min = 0;
  561. uinfo->value.integer.max = 1;
  562. return 0;
  563. }
  564. static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  565. {
  566. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  567. int voices, ofs, i;
  568. voices = kcontrol->private_value >> 8;
  569. ofs = kcontrol->private_value & 0xFF;
  570. for (i = 0; i < voices; i++)
  571. ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
  572. return 0;
  573. }
  574. static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  575. {
  576. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  577. int change = 0, voices, ofs, i;
  578. voices = kcontrol->private_value >> 8;
  579. ofs = kcontrol->private_value & 0xFF;
  580. snd_ice1712_save_gpio_status(ice);
  581. for (i = 0; i < voices; i++) {
  582. int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
  583. if (ucontrol->value.integer.value[i] != val) {
  584. ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
  585. ice->spec.aureon.vol[ofs + i] |=
  586. ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
  587. wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
  588. ice->spec.aureon.master[i]);
  589. change = 1;
  590. }
  591. }
  592. snd_ice1712_restore_gpio_status(ice);
  593. return change;
  594. }
  595. /*
  596. * WM8770 master mute control
  597. */
  598. static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
  599. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  600. uinfo->count = 2;
  601. uinfo->value.integer.min = 0;
  602. uinfo->value.integer.max = 1;
  603. return 0;
  604. }
  605. static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  606. {
  607. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  608. ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
  609. ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
  610. return 0;
  611. }
  612. static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  613. {
  614. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  615. int change = 0, i;
  616. snd_ice1712_save_gpio_status(ice);
  617. for (i = 0; i < 2; i++) {
  618. int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
  619. if (ucontrol->value.integer.value[i] != val) {
  620. int dac;
  621. ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
  622. ice->spec.aureon.master[i] |=
  623. ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
  624. for (dac = 0; dac < ice->num_total_dacs; dac += 2)
  625. wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
  626. ice->spec.aureon.vol[dac + i],
  627. ice->spec.aureon.master[i]);
  628. change = 1;
  629. }
  630. }
  631. snd_ice1712_restore_gpio_status(ice);
  632. return change;
  633. }
  634. /* digital master volume */
  635. #define PCM_0dB 0xff
  636. #define PCM_RES 128 /* -64dB */
  637. #define PCM_MIN (PCM_0dB - PCM_RES)
  638. static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  639. {
  640. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  641. uinfo->count = 1;
  642. uinfo->value.integer.min = 0; /* mute (-64dB) */
  643. uinfo->value.integer.max = PCM_RES; /* 0dB */
  644. return 0;
  645. }
  646. static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  647. {
  648. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  649. unsigned short val;
  650. down(&ice->gpio_mutex);
  651. val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
  652. val = val > PCM_MIN ? (val - PCM_MIN) : 0;
  653. ucontrol->value.integer.value[0] = val;
  654. up(&ice->gpio_mutex);
  655. return 0;
  656. }
  657. static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  658. {
  659. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  660. unsigned short ovol, nvol;
  661. int change = 0;
  662. snd_ice1712_save_gpio_status(ice);
  663. nvol = ucontrol->value.integer.value[0];
  664. nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
  665. ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
  666. if (ovol != nvol) {
  667. wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
  668. wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
  669. change = 1;
  670. }
  671. snd_ice1712_restore_gpio_status(ice);
  672. return change;
  673. }
  674. /*
  675. * ADC mute control
  676. */
  677. static int wm_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  678. {
  679. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  680. uinfo->count = 2;
  681. uinfo->value.integer.min = 0;
  682. uinfo->value.integer.max = 1;
  683. return 0;
  684. }
  685. static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  686. {
  687. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  688. unsigned short val;
  689. int i;
  690. down(&ice->gpio_mutex);
  691. for (i = 0; i < 2; i++) {
  692. val = wm_get(ice, WM_ADC_GAIN + i);
  693. ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
  694. }
  695. up(&ice->gpio_mutex);
  696. return 0;
  697. }
  698. static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  699. {
  700. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  701. unsigned short new, old;
  702. int i, change = 0;
  703. snd_ice1712_save_gpio_status(ice);
  704. for (i = 0; i < 2; i++) {
  705. old = wm_get(ice, WM_ADC_GAIN + i);
  706. new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
  707. if (new != old) {
  708. wm_put(ice, WM_ADC_GAIN + i, new);
  709. change = 1;
  710. }
  711. }
  712. snd_ice1712_restore_gpio_status(ice);
  713. return change;
  714. }
  715. /*
  716. * ADC gain mixer control
  717. */
  718. static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  719. {
  720. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  721. uinfo->count = 2;
  722. uinfo->value.integer.min = 0; /* -12dB */
  723. uinfo->value.integer.max = 0x1f; /* 19dB */
  724. return 0;
  725. }
  726. static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  727. {
  728. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  729. int i, idx;
  730. unsigned short vol;
  731. down(&ice->gpio_mutex);
  732. for (i = 0; i < 2; i++) {
  733. idx = WM_ADC_GAIN + i;
  734. vol = wm_get(ice, idx) & 0x1f;
  735. ucontrol->value.integer.value[i] = vol;
  736. }
  737. up(&ice->gpio_mutex);
  738. return 0;
  739. }
  740. static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  741. {
  742. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  743. int i, idx;
  744. unsigned short ovol, nvol;
  745. int change = 0;
  746. snd_ice1712_save_gpio_status(ice);
  747. for (i = 0; i < 2; i++) {
  748. idx = WM_ADC_GAIN + i;
  749. nvol = ucontrol->value.integer.value[i];
  750. ovol = wm_get(ice, idx);
  751. if ((ovol & 0x1f) != nvol) {
  752. wm_put(ice, idx, nvol | (ovol & ~0x1f));
  753. change = 1;
  754. }
  755. }
  756. snd_ice1712_restore_gpio_status(ice);
  757. return change;
  758. }
  759. /*
  760. * ADC input mux mixer control
  761. */
  762. static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  763. {
  764. static char *texts[] = {
  765. "CD", //AIN1
  766. "Aux", //AIN2
  767. "Line", //AIN3
  768. "Mic", //AIN4
  769. "AC97" //AIN5
  770. };
  771. static char *universe_texts[] = {
  772. "Aux1", //AIN1
  773. "CD", //AIN2
  774. "Phono", //AIN3
  775. "Line", //AIN4
  776. "Aux2", //AIN5
  777. "Mic", //AIN6
  778. "Aux3", //AIN7
  779. "AC97" //AIN8
  780. };
  781. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  782. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  783. uinfo->count = 2;
  784. if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
  785. uinfo->value.enumerated.items = 8;
  786. if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
  787. uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
  788. strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
  789. }
  790. else {
  791. uinfo->value.enumerated.items = 5;
  792. if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
  793. uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
  794. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  795. }
  796. return 0;
  797. }
  798. static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  799. {
  800. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  801. unsigned short val;
  802. down(&ice->gpio_mutex);
  803. val = wm_get(ice, WM_ADC_MUX);
  804. ucontrol->value.integer.value[0] = val & 7;
  805. ucontrol->value.integer.value[1] = (val >> 4) & 7;
  806. up(&ice->gpio_mutex);
  807. return 0;
  808. }
  809. static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  810. {
  811. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  812. unsigned short oval, nval;
  813. int change;
  814. snd_ice1712_save_gpio_status(ice);
  815. oval = wm_get(ice, WM_ADC_MUX);
  816. nval = oval & ~0x77;
  817. nval |= ucontrol->value.integer.value[0] & 7;
  818. nval |= (ucontrol->value.integer.value[1] & 7) << 4;
  819. change = (oval != nval);
  820. if (change)
  821. wm_put(ice, WM_ADC_MUX, nval);
  822. snd_ice1712_restore_gpio_status(ice);
  823. return change;
  824. }
  825. /*
  826. * CS8415 Input mux
  827. */
  828. static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  829. {
  830. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  831. static char *aureon_texts[] = {
  832. "CD", //RXP0
  833. "Optical" //RXP1
  834. };
  835. static char *prodigy_texts[] = {
  836. "CD",
  837. "Coax"
  838. };
  839. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  840. uinfo->count = 1;
  841. uinfo->value.enumerated.items = 2;
  842. if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
  843. uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
  844. if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
  845. strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
  846. else
  847. strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
  848. return 0;
  849. }
  850. static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  851. {
  852. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  853. //snd_ice1712_save_gpio_status(ice);
  854. //val = aureon_cs8415_get(ice, CS8415_CTRL2);
  855. ucontrol->value.integer.value[0] = ice->spec.aureon.cs8415_mux;
  856. //snd_ice1712_restore_gpio_status(ice);
  857. return 0;
  858. }
  859. static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  860. {
  861. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  862. unsigned short oval, nval;
  863. int change;
  864. snd_ice1712_save_gpio_status(ice);
  865. oval = aureon_cs8415_get(ice, CS8415_CTRL2);
  866. nval = oval & ~0x07;
  867. nval |= ucontrol->value.integer.value[0] & 7;
  868. change = (oval != nval);
  869. if (change)
  870. aureon_cs8415_put(ice, CS8415_CTRL2, nval);
  871. snd_ice1712_restore_gpio_status(ice);
  872. ice->spec.aureon.cs8415_mux = ucontrol->value.integer.value[0];
  873. return change;
  874. }
  875. static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  876. {
  877. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  878. uinfo->count = 1;
  879. uinfo->value.integer.min = 0;
  880. uinfo->value.integer.max = 192000;
  881. return 0;
  882. }
  883. static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  884. {
  885. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  886. unsigned char ratio;
  887. ratio = aureon_cs8415_get(ice, CS8415_RATIO);
  888. ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
  889. return 0;
  890. }
  891. /*
  892. * CS8415A Mute
  893. */
  894. static int aureon_cs8415_mute_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  895. {
  896. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  897. uinfo->count = 1;
  898. return 0;
  899. }
  900. static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  901. {
  902. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  903. snd_ice1712_save_gpio_status(ice);
  904. ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
  905. snd_ice1712_restore_gpio_status(ice);
  906. return 0;
  907. }
  908. static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  909. {
  910. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  911. unsigned char oval, nval;
  912. int change;
  913. snd_ice1712_save_gpio_status(ice);
  914. oval = aureon_cs8415_get(ice, CS8415_CTRL1);
  915. if (ucontrol->value.integer.value[0])
  916. nval = oval & ~0x20;
  917. else
  918. nval = oval | 0x20;
  919. if ((change = (oval != nval)))
  920. aureon_cs8415_put(ice, CS8415_CTRL1, nval);
  921. snd_ice1712_restore_gpio_status(ice);
  922. return change;
  923. }
  924. /*
  925. * CS8415A Q-Sub info
  926. */
  927. static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
  928. uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
  929. uinfo->count = 10;
  930. return 0;
  931. }
  932. static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
  933. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  934. snd_ice1712_save_gpio_status(ice);
  935. aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
  936. snd_ice1712_restore_gpio_status(ice);
  937. return 0;
  938. }
  939. static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
  940. uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
  941. uinfo->count = 1;
  942. return 0;
  943. }
  944. static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
  945. memset(ucontrol->value.iec958.status, 0xFF, 24);
  946. return 0;
  947. }
  948. static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
  949. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  950. snd_ice1712_save_gpio_status(ice);
  951. aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
  952. snd_ice1712_restore_gpio_status(ice);
  953. return 0;
  954. }
  955. /*
  956. * Headphone Amplifier
  957. */
  958. static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
  959. {
  960. unsigned int tmp, tmp2;
  961. tmp2 = tmp = snd_ice1712_gpio_read(ice);
  962. if (enable)
  963. tmp |= AUREON_HP_SEL;
  964. else
  965. tmp &= ~ AUREON_HP_SEL;
  966. if (tmp != tmp2) {
  967. snd_ice1712_gpio_write(ice, tmp);
  968. return 1;
  969. }
  970. return 0;
  971. }
  972. static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
  973. {
  974. unsigned int tmp = snd_ice1712_gpio_read(ice);
  975. return ( tmp & AUREON_HP_SEL )!= 0;
  976. }
  977. #define aureon_hpamp_info aureon_mono_bool_info
  978. static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  979. {
  980. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  981. ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
  982. return 0;
  983. }
  984. static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  985. {
  986. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  987. return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
  988. }
  989. /*
  990. * Deemphasis
  991. */
  992. #define aureon_deemp_info aureon_mono_bool_info
  993. static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  994. {
  995. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  996. ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
  997. return 0;
  998. }
  999. static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  1000. {
  1001. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  1002. int temp, temp2;
  1003. temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
  1004. if (ucontrol->value.integer.value[0])
  1005. temp |= 0xf;
  1006. else
  1007. temp &= ~0xf;
  1008. if (temp != temp2) {
  1009. wm_put(ice, WM_DAC_CTRL2, temp);
  1010. return 1;
  1011. }
  1012. return 0;
  1013. }
  1014. /*
  1015. * ADC Oversampling
  1016. */
  1017. static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
  1018. {
  1019. static char *texts[2] = { "128x", "64x" };
  1020. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  1021. uinfo->count = 1;
  1022. uinfo->value.enumerated.items = 2;
  1023. if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
  1024. uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
  1025. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  1026. return 0;
  1027. }
  1028. static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  1029. {
  1030. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  1031. ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
  1032. return 0;
  1033. }
  1034. static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  1035. {
  1036. int temp, temp2;
  1037. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  1038. temp2 = temp = wm_get(ice, WM_MASTER);
  1039. if (ucontrol->value.enumerated.item[0])
  1040. temp |= 0x8;
  1041. else
  1042. temp &= ~0x8;
  1043. if (temp != temp2) {
  1044. wm_put(ice, WM_MASTER, temp);
  1045. return 1;
  1046. }
  1047. return 0;
  1048. }
  1049. /*
  1050. * mixers
  1051. */
  1052. static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
  1053. {
  1054. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1055. .name = "Master Playback Switch",
  1056. .info = wm_master_mute_info,
  1057. .get = wm_master_mute_get,
  1058. .put = wm_master_mute_put
  1059. },
  1060. {
  1061. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1062. .name = "Master Playback Volume",
  1063. .info = wm_master_vol_info,
  1064. .get = wm_master_vol_get,
  1065. .put = wm_master_vol_put
  1066. },
  1067. {
  1068. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1069. .name = "Front Playback Switch",
  1070. .info = wm_mute_info,
  1071. .get = wm_mute_get,
  1072. .put = wm_mute_put,
  1073. .private_value = (2 << 8) | 0
  1074. },
  1075. {
  1076. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1077. .name = "Front Playback Volume",
  1078. .info = wm_vol_info,
  1079. .get = wm_vol_get,
  1080. .put = wm_vol_put,
  1081. .private_value = (2 << 8) | 0
  1082. },
  1083. {
  1084. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1085. .name = "Rear Playback Switch",
  1086. .info = wm_mute_info,
  1087. .get = wm_mute_get,
  1088. .put = wm_mute_put,
  1089. .private_value = (2 << 8) | 2
  1090. },
  1091. {
  1092. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1093. .name = "Rear Playback Volume",
  1094. .info = wm_vol_info,
  1095. .get = wm_vol_get,
  1096. .put = wm_vol_put,
  1097. .private_value = (2 << 8) | 2
  1098. },
  1099. {
  1100. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1101. .name = "Center Playback Switch",
  1102. .info = wm_mute_info,
  1103. .get = wm_mute_get,
  1104. .put = wm_mute_put,
  1105. .private_value = (1 << 8) | 4
  1106. },
  1107. {
  1108. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1109. .name = "Center Playback Volume",
  1110. .info = wm_vol_info,
  1111. .get = wm_vol_get,
  1112. .put = wm_vol_put,
  1113. .private_value = (1 << 8) | 4
  1114. },
  1115. {
  1116. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1117. .name = "LFE Playback Switch",
  1118. .info = wm_mute_info,
  1119. .get = wm_mute_get,
  1120. .put = wm_mute_put,
  1121. .private_value = (1 << 8) | 5
  1122. },
  1123. {
  1124. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1125. .name = "LFE Playback Volume",
  1126. .info = wm_vol_info,
  1127. .get = wm_vol_get,
  1128. .put = wm_vol_put,
  1129. .private_value = (1 << 8) | 5
  1130. },
  1131. {
  1132. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1133. .name = "Side Playback Switch",
  1134. .info = wm_mute_info,
  1135. .get = wm_mute_get,
  1136. .put = wm_mute_put,
  1137. .private_value = (2 << 8) | 6
  1138. },
  1139. {
  1140. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1141. .name = "Side Playback Volume",
  1142. .info = wm_vol_info,
  1143. .get = wm_vol_get,
  1144. .put = wm_vol_put,
  1145. .private_value = (2 << 8) | 6
  1146. }
  1147. };
  1148. static struct snd_kcontrol_new wm_controls[] __devinitdata = {
  1149. {
  1150. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1151. .name = "PCM Playback Switch",
  1152. .info = wm_pcm_mute_info,
  1153. .get = wm_pcm_mute_get,
  1154. .put = wm_pcm_mute_put
  1155. },
  1156. {
  1157. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1158. .name = "PCM Playback Volume",
  1159. .info = wm_pcm_vol_info,
  1160. .get = wm_pcm_vol_get,
  1161. .put = wm_pcm_vol_put
  1162. },
  1163. {
  1164. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1165. .name = "Capture Switch",
  1166. .info = wm_adc_mute_info,
  1167. .get = wm_adc_mute_get,
  1168. .put = wm_adc_mute_put,
  1169. },
  1170. {
  1171. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1172. .name = "Capture Volume",
  1173. .info = wm_adc_vol_info,
  1174. .get = wm_adc_vol_get,
  1175. .put = wm_adc_vol_put
  1176. },
  1177. {
  1178. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1179. .name = "Capture Source",
  1180. .info = wm_adc_mux_info,
  1181. .get = wm_adc_mux_get,
  1182. .put = wm_adc_mux_put,
  1183. .private_value = 5
  1184. },
  1185. {
  1186. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1187. .name = "External Amplifier",
  1188. .info = aureon_hpamp_info,
  1189. .get = aureon_hpamp_get,
  1190. .put = aureon_hpamp_put
  1191. },
  1192. {
  1193. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1194. .name = "DAC Deemphasis Switch",
  1195. .info = aureon_deemp_info,
  1196. .get = aureon_deemp_get,
  1197. .put = aureon_deemp_put
  1198. },
  1199. {
  1200. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1201. .name = "ADC Oversampling",
  1202. .info = aureon_oversampling_info,
  1203. .get = aureon_oversampling_get,
  1204. .put = aureon_oversampling_put
  1205. }
  1206. };
  1207. static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
  1208. {
  1209. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1210. .name = "AC97 Playback Switch",
  1211. .info = aureon_ac97_mmute_info,
  1212. .get = aureon_ac97_mmute_get,
  1213. .put = aureon_ac97_mmute_put,
  1214. .private_value = AC97_MASTER
  1215. },
  1216. {
  1217. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1218. .name = "AC97 Playback Volume",
  1219. .info = aureon_ac97_vol_info,
  1220. .get = aureon_ac97_vol_get,
  1221. .put = aureon_ac97_vol_put,
  1222. .private_value = AC97_MASTER|AUREON_AC97_STEREO
  1223. },
  1224. {
  1225. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1226. .name = "CD Playback Switch",
  1227. .info = aureon_ac97_mute_info,
  1228. .get = aureon_ac97_mute_get,
  1229. .put = aureon_ac97_mute_put,
  1230. .private_value = AC97_CD
  1231. },
  1232. {
  1233. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1234. .name = "CD Playback Volume",
  1235. .info = aureon_ac97_vol_info,
  1236. .get = aureon_ac97_vol_get,
  1237. .put = aureon_ac97_vol_put,
  1238. .private_value = AC97_CD|AUREON_AC97_STEREO
  1239. },
  1240. {
  1241. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1242. .name = "Aux Playback Switch",
  1243. .info = aureon_ac97_mute_info,
  1244. .get = aureon_ac97_mute_get,
  1245. .put = aureon_ac97_mute_put,
  1246. .private_value = AC97_AUX,
  1247. },
  1248. {
  1249. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1250. .name = "Aux Playback Volume",
  1251. .info = aureon_ac97_vol_info,
  1252. .get = aureon_ac97_vol_get,
  1253. .put = aureon_ac97_vol_put,
  1254. .private_value = AC97_AUX|AUREON_AC97_STEREO
  1255. },
  1256. {
  1257. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1258. .name = "Line Playback Switch",
  1259. .info = aureon_ac97_mute_info,
  1260. .get = aureon_ac97_mute_get,
  1261. .put = aureon_ac97_mute_put,
  1262. .private_value = AC97_LINE
  1263. },
  1264. {
  1265. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1266. .name = "Line Playback Volume",
  1267. .info = aureon_ac97_vol_info,
  1268. .get = aureon_ac97_vol_get,
  1269. .put = aureon_ac97_vol_put,
  1270. .private_value = AC97_LINE|AUREON_AC97_STEREO
  1271. },
  1272. {
  1273. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1274. .name = "Mic Playback Switch",
  1275. .info = aureon_ac97_mute_info,
  1276. .get = aureon_ac97_mute_get,
  1277. .put = aureon_ac97_mute_put,
  1278. .private_value = AC97_MIC
  1279. },
  1280. {
  1281. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1282. .name = "Mic Playback Volume",
  1283. .info = aureon_ac97_vol_info,
  1284. .get = aureon_ac97_vol_get,
  1285. .put = aureon_ac97_vol_put,
  1286. .private_value = AC97_MIC
  1287. },
  1288. {
  1289. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1290. .name = "Mic Boost (+20dB)",
  1291. .info = aureon_ac97_micboost_info,
  1292. .get = aureon_ac97_micboost_get,
  1293. .put = aureon_ac97_micboost_put
  1294. }
  1295. };
  1296. static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
  1297. {
  1298. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1299. .name = "AC97 Playback Switch",
  1300. .info = aureon_ac97_mmute_info,
  1301. .get = aureon_ac97_mmute_get,
  1302. .put = aureon_ac97_mmute_put,
  1303. .private_value = AC97_MASTER
  1304. },
  1305. {
  1306. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1307. .name = "AC97 Playback Volume",
  1308. .info = aureon_ac97_vol_info,
  1309. .get = aureon_ac97_vol_get,
  1310. .put = aureon_ac97_vol_put,
  1311. .private_value = AC97_MASTER|AUREON_AC97_STEREO
  1312. },
  1313. {
  1314. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1315. .name = "CD Playback Switch",
  1316. .info = aureon_ac97_mute_info,
  1317. .get = aureon_ac97_mute_get,
  1318. .put = aureon_ac97_mute_put,
  1319. .private_value = AC97_AUX
  1320. },
  1321. {
  1322. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1323. .name = "CD Playback Volume",
  1324. .info = aureon_ac97_vol_info,
  1325. .get = aureon_ac97_vol_get,
  1326. .put = aureon_ac97_vol_put,
  1327. .private_value = AC97_AUX|AUREON_AC97_STEREO
  1328. },
  1329. {
  1330. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1331. .name = "Phono Playback Switch",
  1332. .info = aureon_ac97_mute_info,
  1333. .get = aureon_ac97_mute_get,
  1334. .put = aureon_ac97_mute_put,
  1335. .private_value = AC97_CD,
  1336. },
  1337. {
  1338. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1339. .name = "Phono Playback Volume",
  1340. .info = aureon_ac97_vol_info,
  1341. .get = aureon_ac97_vol_get,
  1342. .put = aureon_ac97_vol_put,
  1343. .private_value = AC97_CD|AUREON_AC97_STEREO
  1344. },
  1345. {
  1346. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1347. .name = "Line Playback Switch",
  1348. .info = aureon_ac97_mute_info,
  1349. .get = aureon_ac97_mute_get,
  1350. .put = aureon_ac97_mute_put,
  1351. .private_value = AC97_LINE
  1352. },
  1353. {
  1354. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1355. .name = "Line Playback Volume",
  1356. .info = aureon_ac97_vol_info,
  1357. .get = aureon_ac97_vol_get,
  1358. .put = aureon_ac97_vol_put,
  1359. .private_value = AC97_LINE|AUREON_AC97_STEREO
  1360. },
  1361. {
  1362. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1363. .name = "Mic Playback Switch",
  1364. .info = aureon_ac97_mute_info,
  1365. .get = aureon_ac97_mute_get,
  1366. .put = aureon_ac97_mute_put,
  1367. .private_value = AC97_MIC
  1368. },
  1369. {
  1370. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1371. .name = "Mic Playback Volume",
  1372. .info = aureon_ac97_vol_info,
  1373. .get = aureon_ac97_vol_get,
  1374. .put = aureon_ac97_vol_put,
  1375. .private_value = AC97_MIC
  1376. },
  1377. {
  1378. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1379. .name = "Mic Boost (+20dB)",
  1380. .info = aureon_ac97_micboost_info,
  1381. .get = aureon_ac97_micboost_get,
  1382. .put = aureon_ac97_micboost_put
  1383. },
  1384. {
  1385. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1386. .name = "Aux Playback Switch",
  1387. .info = aureon_ac97_mute_info,
  1388. .get = aureon_ac97_mute_get,
  1389. .put = aureon_ac97_mute_put,
  1390. .private_value = AC97_VIDEO,
  1391. },
  1392. {
  1393. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1394. .name = "Aux Playback Volume",
  1395. .info = aureon_ac97_vol_info,
  1396. .get = aureon_ac97_vol_get,
  1397. .put = aureon_ac97_vol_put,
  1398. .private_value = AC97_VIDEO|AUREON_AC97_STEREO
  1399. }
  1400. };
  1401. static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
  1402. {
  1403. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1404. .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
  1405. .info = aureon_cs8415_mute_info,
  1406. .get = aureon_cs8415_mute_get,
  1407. .put = aureon_cs8415_mute_put
  1408. },
  1409. {
  1410. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1411. .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
  1412. .info = aureon_cs8415_mux_info,
  1413. .get = aureon_cs8415_mux_get,
  1414. .put = aureon_cs8415_mux_put,
  1415. },
  1416. {
  1417. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  1418. .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
  1419. .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
  1420. .info = aureon_cs8415_qsub_info,
  1421. .get = aureon_cs8415_qsub_get,
  1422. },
  1423. {
  1424. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  1425. .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
  1426. .access = SNDRV_CTL_ELEM_ACCESS_READ,
  1427. .info = aureon_cs8415_spdif_info,
  1428. .get = aureon_cs8415_mask_get
  1429. },
  1430. {
  1431. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  1432. .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
  1433. .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
  1434. .info = aureon_cs8415_spdif_info,
  1435. .get = aureon_cs8415_spdif_get
  1436. },
  1437. {
  1438. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  1439. .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
  1440. .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
  1441. .info = aureon_cs8415_rate_info,
  1442. .get = aureon_cs8415_rate_get
  1443. }
  1444. };
  1445. static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
  1446. {
  1447. unsigned int i, counts;
  1448. int err;
  1449. counts = ARRAY_SIZE(aureon_dac_controls);
  1450. if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
  1451. counts -= 2; /* no side */
  1452. for (i = 0; i < counts; i++) {
  1453. err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
  1454. if (err < 0)
  1455. return err;
  1456. }
  1457. for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
  1458. err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
  1459. if (err < 0)
  1460. return err;
  1461. }
  1462. if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
  1463. for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
  1464. err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
  1465. if (err < 0)
  1466. return err;
  1467. }
  1468. }
  1469. else {
  1470. for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
  1471. err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
  1472. if (err < 0)
  1473. return err;
  1474. }
  1475. }
  1476. {
  1477. unsigned char id;
  1478. snd_ice1712_save_gpio_status(ice);
  1479. id = aureon_cs8415_get(ice, CS8415_ID);
  1480. if (id != 0x41)
  1481. snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
  1482. else if ((id & 0x0F) != 0x01)
  1483. snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
  1484. else {
  1485. for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
  1486. struct snd_kcontrol *kctl;
  1487. err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
  1488. if (err < 0)
  1489. return err;
  1490. if (i > 1)
  1491. kctl->id.device = ice->pcm->device;
  1492. }
  1493. }
  1494. snd_ice1712_restore_gpio_status(ice);
  1495. }
  1496. return 0;
  1497. }
  1498. /*
  1499. * initialize the chip
  1500. */
  1501. static int __devinit aureon_init(struct snd_ice1712 *ice)
  1502. {
  1503. static unsigned short wm_inits_aureon[] = {
  1504. /* These come first to reduce init pop noise */
  1505. 0x1b, 0x044, /* ADC Mux (AC'97 source) */
  1506. 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
  1507. 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
  1508. 0x18, 0x000, /* All power-up */
  1509. 0x16, 0x122, /* I2S, normal polarity, 24bit */
  1510. 0x17, 0x022, /* 256fs, slave mode */
  1511. 0x00, 0, /* DAC1 analog mute */
  1512. 0x01, 0, /* DAC2 analog mute */
  1513. 0x02, 0, /* DAC3 analog mute */
  1514. 0x03, 0, /* DAC4 analog mute */
  1515. 0x04, 0, /* DAC5 analog mute */
  1516. 0x05, 0, /* DAC6 analog mute */
  1517. 0x06, 0, /* DAC7 analog mute */
  1518. 0x07, 0, /* DAC8 analog mute */
  1519. 0x08, 0x100, /* master analog mute */
  1520. 0x09, 0xff, /* DAC1 digital full */
  1521. 0x0a, 0xff, /* DAC2 digital full */
  1522. 0x0b, 0xff, /* DAC3 digital full */
  1523. 0x0c, 0xff, /* DAC4 digital full */
  1524. 0x0d, 0xff, /* DAC5 digital full */
  1525. 0x0e, 0xff, /* DAC6 digital full */
  1526. 0x0f, 0xff, /* DAC7 digital full */
  1527. 0x10, 0xff, /* DAC8 digital full */
  1528. 0x11, 0x1ff, /* master digital full */
  1529. 0x12, 0x000, /* phase normal */
  1530. 0x13, 0x090, /* unmute DAC L/R */
  1531. 0x14, 0x000, /* all unmute */
  1532. 0x15, 0x000, /* no deemphasis, no ZFLG */
  1533. 0x19, 0x000, /* -12dB ADC/L */
  1534. 0x1a, 0x000, /* -12dB ADC/R */
  1535. (unsigned short)-1
  1536. };
  1537. static unsigned short wm_inits_prodigy[] = {
  1538. /* These come first to reduce init pop noise */
  1539. 0x1b, 0x000, /* ADC Mux */
  1540. 0x1c, 0x009, /* Out Mux1 */
  1541. 0x1d, 0x009, /* Out Mux2 */
  1542. 0x18, 0x000, /* All power-up */
  1543. 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
  1544. 0x17, 0x006, /* 128fs, slave mode */
  1545. 0x00, 0, /* DAC1 analog mute */
  1546. 0x01, 0, /* DAC2 analog mute */
  1547. 0x02, 0, /* DAC3 analog mute */
  1548. 0x03, 0, /* DAC4 analog mute */
  1549. 0x04, 0, /* DAC5 analog mute */
  1550. 0x05, 0, /* DAC6 analog mute */
  1551. 0x06, 0, /* DAC7 analog mute */
  1552. 0x07, 0, /* DAC8 analog mute */
  1553. 0x08, 0x100, /* master analog mute */
  1554. 0x09, 0x7f, /* DAC1 digital full */
  1555. 0x0a, 0x7f, /* DAC2 digital full */
  1556. 0x0b, 0x7f, /* DAC3 digital full */
  1557. 0x0c, 0x7f, /* DAC4 digital full */
  1558. 0x0d, 0x7f, /* DAC5 digital full */
  1559. 0x0e, 0x7f, /* DAC6 digital full */
  1560. 0x0f, 0x7f, /* DAC7 digital full */
  1561. 0x10, 0x7f, /* DAC8 digital full */
  1562. 0x11, 0x1FF, /* master digital full */
  1563. 0x12, 0x000, /* phase normal */
  1564. 0x13, 0x090, /* unmute DAC L/R */
  1565. 0x14, 0x000, /* all unmute */
  1566. 0x15, 0x000, /* no deemphasis, no ZFLG */
  1567. 0x19, 0x000, /* -12dB ADC/L */
  1568. 0x1a, 0x000, /* -12dB ADC/R */
  1569. (unsigned short)-1
  1570. };
  1571. static unsigned short cs_inits[] = {
  1572. 0x0441, /* RUN */
  1573. 0x0180, /* no mute, OMCK output on RMCK pin */
  1574. 0x0201, /* S/PDIF source on RXP1 */
  1575. 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
  1576. (unsigned short)-1
  1577. };
  1578. unsigned int tmp;
  1579. unsigned short *p;
  1580. int err, i;
  1581. if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
  1582. ice->num_total_dacs = 6;
  1583. ice->num_total_adcs = 2;
  1584. } else {
  1585. /* aureon 7.1 and prodigy 7.1 */
  1586. ice->num_total_dacs = 8;
  1587. ice->num_total_adcs = 2;
  1588. }
  1589. /* to remeber the register values of CS8415 */
  1590. ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
  1591. if (! ice->akm)
  1592. return -ENOMEM;
  1593. ice->akm_codecs = 1;
  1594. if ((err = aureon_ac97_init(ice)) != 0)
  1595. return err;
  1596. snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
  1597. /* reset the wm codec as the SPI mode */
  1598. snd_ice1712_save_gpio_status(ice);
  1599. snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
  1600. tmp = snd_ice1712_gpio_read(ice);
  1601. tmp &= ~AUREON_WM_RESET;
  1602. snd_ice1712_gpio_write(ice, tmp);
  1603. udelay(1);
  1604. tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
  1605. snd_ice1712_gpio_write(ice, tmp);
  1606. udelay(1);
  1607. tmp |= AUREON_WM_RESET;
  1608. snd_ice1712_gpio_write(ice, tmp);
  1609. udelay(1);
  1610. /* initialize WM8770 codec */
  1611. if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
  1612. p = wm_inits_prodigy;
  1613. else
  1614. p = wm_inits_aureon;
  1615. for (; *p != (unsigned short)-1; p += 2)
  1616. wm_put(ice, p[0], p[1]);
  1617. /* initialize CS8415A codec */
  1618. for (p = cs_inits; *p != (unsigned short)-1; p++)
  1619. aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
  1620. ice->spec.aureon.cs8415_mux = 1;
  1621. aureon_set_headphone_amp(ice, 1);
  1622. snd_ice1712_restore_gpio_status(ice);
  1623. ice->spec.aureon.master[0] = WM_VOL_MUTE;
  1624. ice->spec.aureon.master[1] = WM_VOL_MUTE;
  1625. for (i = 0; i < ice->num_total_dacs; i++) {
  1626. ice->spec.aureon.vol[i] = WM_VOL_MUTE;
  1627. wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
  1628. }
  1629. return 0;
  1630. }
  1631. /*
  1632. * Aureon boards don't provide the EEPROM data except for the vendor IDs.
  1633. * hence the driver needs to sets up it properly.
  1634. */
  1635. static unsigned char aureon51_eeprom[] __devinitdata = {
  1636. 0x0a, /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
  1637. 0x80, /* ACLINK: I2S */
  1638. 0xfc, /* I2S: vol, 96k, 24bit, 192k */
  1639. 0xc3, /* SPDIF: out-en, out-int, spdif-in */
  1640. 0xff, /* GPIO_DIR */
  1641. 0xff, /* GPIO_DIR1 */
  1642. 0x5f, /* GPIO_DIR2 */
  1643. 0x00, /* GPIO_MASK */
  1644. 0x00, /* GPIO_MASK1 */
  1645. 0x00, /* GPIO_MASK2 */
  1646. 0x00, /* GPIO_STATE */
  1647. 0x00, /* GPIO_STATE1 */
  1648. 0x00, /* GPIO_STATE2 */
  1649. };
  1650. static unsigned char aureon71_eeprom[] __devinitdata = {
  1651. 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
  1652. 0x80, /* ACLINK: I2S */
  1653. 0xfc, /* I2S: vol, 96k, 24bit, 192k */
  1654. 0xc3, /* SPDIF: out-en, out-int, spdif-in */
  1655. 0xff, /* GPIO_DIR */
  1656. 0xff, /* GPIO_DIR1 */
  1657. 0x5f, /* GPIO_DIR2 */
  1658. 0x00, /* GPIO_MASK */
  1659. 0x00, /* GPIO_MASK1 */
  1660. 0x00, /* GPIO_MASK2 */
  1661. 0x00, /* GPIO_STATE */
  1662. 0x00, /* GPIO_STATE1 */
  1663. 0x00, /* GPIO_STATE2 */
  1664. };
  1665. static unsigned char prodigy71_eeprom[] __devinitdata = {
  1666. 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
  1667. 0x80, /* ACLINK: I2S */
  1668. 0xfc, /* I2S: vol, 96k, 24bit, 192k */
  1669. 0xc3, /* SPDIF: out-en, out-int, spdif-in */
  1670. 0xff, /* GPIO_DIR */
  1671. 0xff, /* GPIO_DIR1 */
  1672. 0x5f, /* GPIO_DIR2 */
  1673. 0x00, /* GPIO_MASK */
  1674. 0x00, /* GPIO_MASK1 */
  1675. 0x00, /* GPIO_MASK2 */
  1676. 0x00, /* GPIO_STATE */
  1677. 0x00, /* GPIO_STATE1 */
  1678. 0x00, /* GPIO_STATE2 */
  1679. };
  1680. /* entry point */
  1681. struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
  1682. {
  1683. .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
  1684. .name = "Terratec Aureon 5.1-Sky",
  1685. .model = "aureon51",
  1686. .chip_init = aureon_init,
  1687. .build_controls = aureon_add_controls,
  1688. .eeprom_size = sizeof(aureon51_eeprom),
  1689. .eeprom_data = aureon51_eeprom,
  1690. .driver = "Aureon51",
  1691. },
  1692. {
  1693. .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
  1694. .name = "Terratec Aureon 7.1-Space",
  1695. .model = "aureon71",
  1696. .chip_init = aureon_init,
  1697. .build_controls = aureon_add_controls,
  1698. .eeprom_size = sizeof(aureon71_eeprom),
  1699. .eeprom_data = aureon71_eeprom,
  1700. .driver = "Aureon71",
  1701. },
  1702. {
  1703. .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
  1704. .name = "Terratec Aureon 7.1-Universe",
  1705. .model = "universe",
  1706. .chip_init = aureon_init,
  1707. .build_controls = aureon_add_controls,
  1708. .eeprom_size = sizeof(aureon71_eeprom),
  1709. .eeprom_data = aureon71_eeprom,
  1710. .driver = "Aureon71Universe",
  1711. },
  1712. {
  1713. .subvendor = VT1724_SUBDEVICE_PRODIGY71,
  1714. .name = "Audiotrak Prodigy 7.1",
  1715. .model = "prodigy71",
  1716. .chip_init = aureon_init,
  1717. .build_controls = aureon_add_controls,
  1718. .eeprom_size = sizeof(prodigy71_eeprom),
  1719. .eeprom_data = prodigy71_eeprom,
  1720. .driver = "Prodigy71", /* should be identical with Aureon71 */
  1721. },
  1722. { } /* terminator */
  1723. };