wtm.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. * ALSA driver for ICEnsemble VT1724 (Envy24HT)
  3. *
  4. * Lowlevel functions for Ego Sys Waveterminal 192M
  5. *
  6. * Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com>
  7. * Some functions are taken from the Prodigy192 driver
  8. * source
  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 <asm/io.h>
  27. #include <linux/delay.h>
  28. #include <linux/interrupt.h>
  29. #include <linux/init.h>
  30. #include <linux/slab.h>
  31. #include <sound/core.h>
  32. #include "ice1712.h"
  33. #include "envy24ht.h"
  34. #include "wtm.h"
  35. #include "stac946x.h"
  36. /*
  37. * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
  38. */
  39. static inline void stac9460_put(struct snd_ice1712 *ice, int reg,
  40. unsigned char val)
  41. {
  42. snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
  43. }
  44. static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
  45. {
  46. return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
  47. }
  48. /*
  49. * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
  50. */
  51. static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
  52. unsigned char val)
  53. {
  54. snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
  55. }
  56. static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
  57. {
  58. return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
  59. }
  60. /*
  61. * DAC mute control
  62. */
  63. #define stac9460_dac_mute_info snd_ctl_boolean_mono_info
  64. static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
  65. struct snd_ctl_elem_value *ucontrol)
  66. {
  67. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  68. unsigned char val;
  69. int idx, id;
  70. if (kcontrol->private_value) {
  71. idx = STAC946X_MASTER_VOLUME;
  72. id = 0;
  73. } else {
  74. id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  75. idx = id + STAC946X_LF_VOLUME;
  76. }
  77. if (id < 6)
  78. val = stac9460_get(ice, idx);
  79. else
  80. val = stac9460_2_get(ice,idx - 6);
  81. ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
  82. return 0;
  83. }
  84. static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
  85. struct snd_ctl_elem_value *ucontrol)
  86. {
  87. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  88. unsigned char new, old;
  89. int id, idx;
  90. int change;
  91. if (kcontrol->private_value) {
  92. idx = STAC946X_MASTER_VOLUME;
  93. old = stac9460_get(ice, idx);
  94. new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
  95. (old & ~0x80);
  96. change = (new != old);
  97. if (change) {
  98. stac9460_put(ice, idx, new);
  99. stac9460_2_put(ice, idx, new);
  100. }
  101. } else {
  102. id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  103. idx = id + STAC946X_LF_VOLUME;
  104. if (id < 6)
  105. old = stac9460_get(ice, idx);
  106. else
  107. old = stac9460_2_get(ice, idx - 6);
  108. new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
  109. (old & ~0x80);
  110. change = (new != old);
  111. if (change) {
  112. if (id < 6)
  113. stac9460_put(ice, idx, new);
  114. else
  115. stac9460_2_put(ice, idx - 6, new);
  116. }
  117. }
  118. return change;
  119. }
  120. /*
  121. * DAC volume attenuation mixer control
  122. */
  123. static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
  124. struct snd_ctl_elem_info *uinfo)
  125. {
  126. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  127. uinfo->count = 1;
  128. uinfo->value.integer.min = 0; /* mute */
  129. uinfo->value.integer.max = 0x7f; /* 0dB */
  130. return 0;
  131. }
  132. static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
  133. struct snd_ctl_elem_value *ucontrol)
  134. {
  135. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  136. int idx, id;
  137. unsigned char vol;
  138. if (kcontrol->private_value) {
  139. idx = STAC946X_MASTER_VOLUME;
  140. id = 0;
  141. } else {
  142. id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  143. idx = id + STAC946X_LF_VOLUME;
  144. }
  145. if (id < 6)
  146. vol = stac9460_get(ice, idx) & 0x7f;
  147. else
  148. vol = stac9460_2_get(ice, idx - 6) & 0x7f;
  149. ucontrol->value.integer.value[0] = 0x7f - vol;
  150. return 0;
  151. }
  152. static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
  153. struct snd_ctl_elem_value *ucontrol)
  154. {
  155. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  156. int idx, id;
  157. unsigned char tmp, ovol, nvol;
  158. int change;
  159. if (kcontrol->private_value) {
  160. idx = STAC946X_MASTER_VOLUME;
  161. nvol = ucontrol->value.integer.value[0];
  162. tmp = stac9460_get(ice, idx);
  163. ovol = 0x7f - (tmp & 0x7f);
  164. change = (ovol != nvol);
  165. if (change) {
  166. stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
  167. stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
  168. }
  169. } else {
  170. id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  171. idx = id + STAC946X_LF_VOLUME;
  172. nvol = ucontrol->value.integer.value[0];
  173. if (id < 6)
  174. tmp = stac9460_get(ice, idx);
  175. else
  176. tmp = stac9460_2_get(ice, idx - 6);
  177. ovol = 0x7f - (tmp & 0x7f);
  178. change = (ovol != nvol);
  179. if (change) {
  180. if (id < 6)
  181. stac9460_put(ice, idx, (0x7f - nvol) |
  182. (tmp & 0x80));
  183. else
  184. stac9460_2_put(ice, idx-6, (0x7f - nvol) |
  185. (tmp & 0x80));
  186. }
  187. }
  188. return change;
  189. }
  190. /*
  191. * ADC mute control
  192. */
  193. #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info
  194. static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
  195. struct snd_ctl_elem_value *ucontrol)
  196. {
  197. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  198. unsigned char val;
  199. int i, id;
  200. id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  201. if (id == 0) {
  202. for (i = 0; i < 2; ++i) {
  203. val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
  204. ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
  205. }
  206. } else {
  207. for (i = 0; i < 2; ++i) {
  208. val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);
  209. ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
  210. }
  211. }
  212. return 0;
  213. }
  214. static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
  215. struct snd_ctl_elem_value *ucontrol)
  216. {
  217. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  218. unsigned char new, old;
  219. int i, reg, id;
  220. int change;
  221. id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  222. if (id == 0) {
  223. for (i = 0; i < 2; ++i) {
  224. reg = STAC946X_MIC_L_VOLUME + i;
  225. old = stac9460_get(ice, reg);
  226. new = (~ucontrol->value.integer.value[i]<<7&0x80) |
  227. (old&~0x80);
  228. change = (new != old);
  229. if (change)
  230. stac9460_put(ice, reg, new);
  231. }
  232. } else {
  233. for (i = 0; i < 2; ++i) {
  234. reg = STAC946X_MIC_L_VOLUME + i;
  235. old = stac9460_2_get(ice, reg);
  236. new = (~ucontrol->value.integer.value[i]<<7&0x80) |
  237. (old&~0x80);
  238. change = (new != old);
  239. if (change)
  240. stac9460_2_put(ice, reg, new);
  241. }
  242. }
  243. return change;
  244. }
  245. /*
  246. *ADC gain mixer control
  247. */
  248. static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
  249. struct snd_ctl_elem_info *uinfo)
  250. {
  251. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  252. uinfo->count = 2;
  253. uinfo->value.integer.min = 0; /* 0dB */
  254. uinfo->value.integer.max = 0x0f; /* 22.5dB */
  255. return 0;
  256. }
  257. static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
  258. struct snd_ctl_elem_value *ucontrol)
  259. {
  260. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  261. int i, reg, id;
  262. unsigned char vol;
  263. id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  264. if (id == 0) {
  265. for (i = 0; i < 2; ++i) {
  266. reg = STAC946X_MIC_L_VOLUME + i;
  267. vol = stac9460_get(ice, reg) & 0x0f;
  268. ucontrol->value.integer.value[i] = 0x0f - vol;
  269. }
  270. } else {
  271. for (i = 0; i < 2; ++i) {
  272. reg = STAC946X_MIC_L_VOLUME + i;
  273. vol = stac9460_2_get(ice, reg) & 0x0f;
  274. ucontrol->value.integer.value[i] = 0x0f - vol;
  275. }
  276. }
  277. return 0;
  278. }
  279. static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
  280. struct snd_ctl_elem_value *ucontrol)
  281. {
  282. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  283. int i, reg, id;
  284. unsigned char ovol, nvol;
  285. int change;
  286. id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  287. if (id == 0) {
  288. for (i = 0; i < 2; ++i) {
  289. reg = STAC946X_MIC_L_VOLUME + i;
  290. nvol = ucontrol->value.integer.value[i];
  291. ovol = 0x0f - stac9460_get(ice, reg);
  292. change = ((ovol & 0x0f) != nvol);
  293. if (change)
  294. stac9460_put(ice, reg, (0x0f - nvol) |
  295. (ovol & ~0x0f));
  296. }
  297. } else {
  298. for (i = 0; i < 2; ++i) {
  299. reg = STAC946X_MIC_L_VOLUME + i;
  300. nvol = ucontrol->value.integer.value[i];
  301. ovol = 0x0f - stac9460_2_get(ice, reg);
  302. change = ((ovol & 0x0f) != nvol);
  303. if (change)
  304. stac9460_2_put(ice, reg, (0x0f - nvol) |
  305. (ovol & ~0x0f));
  306. }
  307. }
  308. return change;
  309. }
  310. /*
  311. * MIC / LINE switch fonction
  312. */
  313. #define stac9460_mic_sw_info snd_ctl_boolean_mono_info
  314. static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
  315. struct snd_ctl_elem_value *ucontrol)
  316. {
  317. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  318. unsigned char val;
  319. int id;
  320. id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  321. if (id == 0)
  322. val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
  323. else
  324. val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
  325. ucontrol->value.integer.value[0] = ~val>>7 & 0x1;
  326. return 0;
  327. }
  328. static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
  329. struct snd_ctl_elem_value *ucontrol)
  330. {
  331. struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  332. unsigned char new, old;
  333. int change, id;
  334. id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  335. if (id == 0)
  336. old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
  337. else
  338. old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
  339. new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80);
  340. change = (new != old);
  341. if (change) {
  342. if (id == 0)
  343. stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
  344. else
  345. stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
  346. }
  347. return change;
  348. }
  349. /*
  350. * Control tabs
  351. */
  352. static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
  353. {
  354. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  355. .name = "Master Playback Switch",
  356. .info = stac9460_dac_mute_info,
  357. .get = stac9460_dac_mute_get,
  358. .put = stac9460_dac_mute_put,
  359. .private_value = 1
  360. },
  361. {
  362. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  363. .name = "Master Playback Volume",
  364. .info = stac9460_dac_vol_info,
  365. .get = stac9460_dac_vol_get,
  366. .put = stac9460_dac_vol_put,
  367. .private_value = 1,
  368. },
  369. {
  370. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  371. .name = "MIC/Line switch",
  372. .count = 2,
  373. .info = stac9460_mic_sw_info,
  374. .get = stac9460_mic_sw_get,
  375. .put = stac9460_mic_sw_put,
  376. },
  377. {
  378. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  379. .name = "DAC Switch",
  380. .count = 8,
  381. .info = stac9460_dac_mute_info,
  382. .get = stac9460_dac_mute_get,
  383. .put = stac9460_dac_mute_put,
  384. },
  385. {
  386. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  387. .name = "DAC Volume",
  388. .count = 8,
  389. .info = stac9460_dac_vol_info,
  390. .get = stac9460_dac_vol_get,
  391. .put = stac9460_dac_vol_put,
  392. },
  393. {
  394. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  395. .name = "ADC Switch",
  396. .count = 2,
  397. .info = stac9460_adc_mute_info,
  398. .get = stac9460_adc_mute_get,
  399. .put = stac9460_adc_mute_put,
  400. },
  401. {
  402. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  403. .name = "ADC Volume",
  404. .count = 2,
  405. .info = stac9460_adc_vol_info,
  406. .get = stac9460_adc_vol_get,
  407. .put = stac9460_adc_vol_put,
  408. }
  409. };
  410. /*INIT*/
  411. static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
  412. {
  413. unsigned int i;
  414. int err;
  415. for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {
  416. err = snd_ctl_add(ice->card,
  417. snd_ctl_new1(&stac9640_controls[i], ice));
  418. if (err < 0)
  419. return err;
  420. }
  421. return 0;
  422. }
  423. static int __devinit wtm_init(struct snd_ice1712 *ice)
  424. {
  425. static unsigned short stac_inits_prodigy[] = {
  426. STAC946X_RESET, 0,
  427. (unsigned short)-1
  428. };
  429. unsigned short *p;
  430. /*WTM 192M*/
  431. ice->num_total_dacs = 8;
  432. ice->num_total_adcs = 4;
  433. ice->force_rdma1 = 1;
  434. /*initialize codec*/
  435. p = stac_inits_prodigy;
  436. for (; *p != (unsigned short)-1; p += 2) {
  437. stac9460_put(ice, p[0], p[1]);
  438. stac9460_2_put(ice, p[0], p[1]);
  439. }
  440. return 0;
  441. }
  442. static unsigned char wtm_eeprom[] __devinitdata = {
  443. 0x47, /*SYSCONF: clock 192KHz, 4ADC, 8DAC */
  444. 0x80, /* ACLINK : I2S */
  445. 0xf8, /* I2S: vol; 96k, 24bit, 192k */
  446. 0xc1 /*SPDIF: out-en, spidf ext out*/,
  447. 0x9f, /* GPIO_DIR */
  448. 0xff, /* GPIO_DIR1 */
  449. 0x7f, /* GPIO_DIR2 */
  450. 0x9f, /* GPIO_MASK */
  451. 0xff, /* GPIO_MASK1 */
  452. 0x7f, /* GPIO_MASK2 */
  453. 0x16, /* GPIO_STATE */
  454. 0x80, /* GPIO_STATE1 */
  455. 0x00, /* GPIO_STATE2 */
  456. };
  457. /*entry point*/
  458. struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
  459. {
  460. .subvendor = VT1724_SUBDEVICE_WTM,
  461. .name = "ESI Waveterminal 192M",
  462. .model = "WT192M",
  463. .chip_init = wtm_init,
  464. .build_controls = wtm_add_controls,
  465. .eeprom_size = sizeof(wtm_eeprom),
  466. .eeprom_data = wtm_eeprom,
  467. },
  468. {} /*terminator*/
  469. };