sb16_csp.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220
  1. /*
  2. * Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
  3. * Takashi Iwai <tiwai@suse.de>
  4. *
  5. * SB16ASP/AWE32 CSP control
  6. *
  7. * CSP microcode loader:
  8. * alsa-tools/sb16_csp/
  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/control.h>
  31. #include <sound/info.h>
  32. #include <sound/sb16_csp.h>
  33. #include <sound/initval.h>
  34. MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
  35. MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor");
  36. MODULE_LICENSE("GPL");
  37. #ifdef SNDRV_LITTLE_ENDIAN
  38. #define CSP_HDR_VALUE(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
  39. #else
  40. #define CSP_HDR_VALUE(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
  41. #endif
  42. #define RIFF_HEADER CSP_HDR_VALUE('R', 'I', 'F', 'F')
  43. #define CSP__HEADER CSP_HDR_VALUE('C', 'S', 'P', ' ')
  44. #define LIST_HEADER CSP_HDR_VALUE('L', 'I', 'S', 'T')
  45. #define FUNC_HEADER CSP_HDR_VALUE('f', 'u', 'n', 'c')
  46. #define CODE_HEADER CSP_HDR_VALUE('c', 'o', 'd', 'e')
  47. #define INIT_HEADER CSP_HDR_VALUE('i', 'n', 'i', 't')
  48. #define MAIN_HEADER CSP_HDR_VALUE('m', 'a', 'i', 'n')
  49. /*
  50. * RIFF data format
  51. */
  52. struct riff_header {
  53. __u32 name;
  54. __u32 len;
  55. };
  56. struct desc_header {
  57. struct riff_header info;
  58. __u16 func_nr;
  59. __u16 VOC_type;
  60. __u16 flags_play_rec;
  61. __u16 flags_16bit_8bit;
  62. __u16 flags_stereo_mono;
  63. __u16 flags_rates;
  64. };
  65. /*
  66. * prototypes
  67. */
  68. static void snd_sb_csp_free(struct snd_hwdep *hw);
  69. static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file);
  70. static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg);
  71. static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file);
  72. static int csp_detect(struct snd_sb *chip, int *version);
  73. static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val);
  74. static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val);
  75. static int read_register(struct snd_sb *chip, unsigned char reg);
  76. static int set_mode_register(struct snd_sb *chip, unsigned char mode);
  77. static int get_version(struct snd_sb *chip);
  78. static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
  79. struct snd_sb_csp_microcode __user * code);
  80. static int snd_sb_csp_unload(struct snd_sb_csp * p);
  81. static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags);
  82. static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode);
  83. static int snd_sb_csp_check_version(struct snd_sb_csp * p);
  84. static int snd_sb_csp_use(struct snd_sb_csp * p);
  85. static int snd_sb_csp_unuse(struct snd_sb_csp * p);
  86. static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels);
  87. static int snd_sb_csp_stop(struct snd_sb_csp * p);
  88. static int snd_sb_csp_pause(struct snd_sb_csp * p);
  89. static int snd_sb_csp_restart(struct snd_sb_csp * p);
  90. static int snd_sb_qsound_build(struct snd_sb_csp * p);
  91. static void snd_sb_qsound_destroy(struct snd_sb_csp * p);
  92. static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p);
  93. static int init_proc_entry(struct snd_sb_csp * p, int device);
  94. static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer);
  95. /*
  96. * Detect CSP chip and create a new instance
  97. */
  98. int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep)
  99. {
  100. struct snd_sb_csp *p;
  101. int version, err;
  102. struct snd_hwdep *hw;
  103. if (rhwdep)
  104. *rhwdep = NULL;
  105. if (csp_detect(chip, &version))
  106. return -ENODEV;
  107. if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0)
  108. return err;
  109. if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) {
  110. snd_device_free(chip->card, hw);
  111. return -ENOMEM;
  112. }
  113. p->chip = chip;
  114. p->version = version;
  115. /* CSP operators */
  116. p->ops.csp_use = snd_sb_csp_use;
  117. p->ops.csp_unuse = snd_sb_csp_unuse;
  118. p->ops.csp_autoload = snd_sb_csp_autoload;
  119. p->ops.csp_start = snd_sb_csp_start;
  120. p->ops.csp_stop = snd_sb_csp_stop;
  121. p->ops.csp_qsound_transfer = snd_sb_csp_qsound_transfer;
  122. mutex_init(&p->access_mutex);
  123. sprintf(hw->name, "CSP v%d.%d", (version >> 4), (version & 0x0f));
  124. hw->iface = SNDRV_HWDEP_IFACE_SB16CSP;
  125. hw->private_data = p;
  126. hw->private_free = snd_sb_csp_free;
  127. /* operators - only write/ioctl */
  128. hw->ops.open = snd_sb_csp_open;
  129. hw->ops.ioctl = snd_sb_csp_ioctl;
  130. hw->ops.release = snd_sb_csp_release;
  131. /* create a proc entry */
  132. init_proc_entry(p, device);
  133. if (rhwdep)
  134. *rhwdep = hw;
  135. return 0;
  136. }
  137. /*
  138. * free_private for hwdep instance
  139. */
  140. static void snd_sb_csp_free(struct snd_hwdep *hwdep)
  141. {
  142. int i;
  143. struct snd_sb_csp *p = hwdep->private_data;
  144. if (p) {
  145. if (p->running & SNDRV_SB_CSP_ST_RUNNING)
  146. snd_sb_csp_stop(p);
  147. for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i)
  148. release_firmware(p->csp_programs[i]);
  149. kfree(p);
  150. }
  151. }
  152. /* ------------------------------ */
  153. /*
  154. * open the device exclusively
  155. */
  156. static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file)
  157. {
  158. struct snd_sb_csp *p = hw->private_data;
  159. return (snd_sb_csp_use(p));
  160. }
  161. /*
  162. * ioctl for hwdep device:
  163. */
  164. static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg)
  165. {
  166. struct snd_sb_csp *p = hw->private_data;
  167. struct snd_sb_csp_info info;
  168. struct snd_sb_csp_start start_info;
  169. int err;
  170. snd_assert(p != NULL, return -EINVAL);
  171. if (snd_sb_csp_check_version(p))
  172. return -ENODEV;
  173. switch (cmd) {
  174. /* get information */
  175. case SNDRV_SB_CSP_IOCTL_INFO:
  176. *info.codec_name = *p->codec_name;
  177. info.func_nr = p->func_nr;
  178. info.acc_format = p->acc_format;
  179. info.acc_channels = p->acc_channels;
  180. info.acc_width = p->acc_width;
  181. info.acc_rates = p->acc_rates;
  182. info.csp_mode = p->mode;
  183. info.run_channels = p->run_channels;
  184. info.run_width = p->run_width;
  185. info.version = p->version;
  186. info.state = p->running;
  187. if (copy_to_user((void __user *)arg, &info, sizeof(info)))
  188. err = -EFAULT;
  189. else
  190. err = 0;
  191. break;
  192. /* load CSP microcode */
  193. case SNDRV_SB_CSP_IOCTL_LOAD_CODE:
  194. err = (p->running & SNDRV_SB_CSP_ST_RUNNING ?
  195. -EBUSY : snd_sb_csp_riff_load(p, (struct snd_sb_csp_microcode __user *) arg));
  196. break;
  197. case SNDRV_SB_CSP_IOCTL_UNLOAD_CODE:
  198. err = (p->running & SNDRV_SB_CSP_ST_RUNNING ?
  199. -EBUSY : snd_sb_csp_unload(p));
  200. break;
  201. /* change CSP running state */
  202. case SNDRV_SB_CSP_IOCTL_START:
  203. if (copy_from_user(&start_info, (void __user *) arg, sizeof(start_info)))
  204. err = -EFAULT;
  205. else
  206. err = snd_sb_csp_start(p, start_info.sample_width, start_info.channels);
  207. break;
  208. case SNDRV_SB_CSP_IOCTL_STOP:
  209. err = snd_sb_csp_stop(p);
  210. break;
  211. case SNDRV_SB_CSP_IOCTL_PAUSE:
  212. err = snd_sb_csp_pause(p);
  213. break;
  214. case SNDRV_SB_CSP_IOCTL_RESTART:
  215. err = snd_sb_csp_restart(p);
  216. break;
  217. default:
  218. err = -ENOTTY;
  219. break;
  220. }
  221. return err;
  222. }
  223. /*
  224. * close the device
  225. */
  226. static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file)
  227. {
  228. struct snd_sb_csp *p = hw->private_data;
  229. return (snd_sb_csp_unuse(p));
  230. }
  231. /* ------------------------------ */
  232. /*
  233. * acquire device
  234. */
  235. static int snd_sb_csp_use(struct snd_sb_csp * p)
  236. {
  237. mutex_lock(&p->access_mutex);
  238. if (p->used) {
  239. mutex_unlock(&p->access_mutex);
  240. return -EAGAIN;
  241. }
  242. p->used++;
  243. mutex_unlock(&p->access_mutex);
  244. return 0;
  245. }
  246. /*
  247. * release device
  248. */
  249. static int snd_sb_csp_unuse(struct snd_sb_csp * p)
  250. {
  251. mutex_lock(&p->access_mutex);
  252. p->used--;
  253. mutex_unlock(&p->access_mutex);
  254. return 0;
  255. }
  256. /*
  257. * load microcode via ioctl:
  258. * code is user-space pointer
  259. */
  260. static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
  261. struct snd_sb_csp_microcode __user * mcode)
  262. {
  263. struct snd_sb_csp_mc_header info;
  264. unsigned char __user *data_ptr;
  265. unsigned char __user *data_end;
  266. unsigned short func_nr = 0;
  267. struct riff_header file_h, item_h, code_h;
  268. __u32 item_type;
  269. struct desc_header funcdesc_h;
  270. unsigned long flags;
  271. int err;
  272. if (copy_from_user(&info, mcode, sizeof(info)))
  273. return -EFAULT;
  274. data_ptr = mcode->data;
  275. if (copy_from_user(&file_h, data_ptr, sizeof(file_h)))
  276. return -EFAULT;
  277. if ((file_h.name != RIFF_HEADER) ||
  278. (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
  279. snd_printd("%s: Invalid RIFF header\n", __FUNCTION__);
  280. return -EINVAL;
  281. }
  282. data_ptr += sizeof(file_h);
  283. data_end = data_ptr + le32_to_cpu(file_h.len);
  284. if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
  285. return -EFAULT;
  286. if (item_type != CSP__HEADER) {
  287. snd_printd("%s: Invalid RIFF file type\n", __FUNCTION__);
  288. return -EINVAL;
  289. }
  290. data_ptr += sizeof (item_type);
  291. for (; data_ptr < data_end; data_ptr += le32_to_cpu(item_h.len)) {
  292. if (copy_from_user(&item_h, data_ptr, sizeof(item_h)))
  293. return -EFAULT;
  294. data_ptr += sizeof(item_h);
  295. if (item_h.name != LIST_HEADER)
  296. continue;
  297. if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
  298. return -EFAULT;
  299. switch (item_type) {
  300. case FUNC_HEADER:
  301. if (copy_from_user(&funcdesc_h, data_ptr + sizeof(item_type), sizeof(funcdesc_h)))
  302. return -EFAULT;
  303. func_nr = le16_to_cpu(funcdesc_h.func_nr);
  304. break;
  305. case CODE_HEADER:
  306. if (func_nr != info.func_req)
  307. break; /* not required function, try next */
  308. data_ptr += sizeof(item_type);
  309. /* destroy QSound mixer element */
  310. if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) {
  311. snd_sb_qsound_destroy(p);
  312. }
  313. /* Clear all flags */
  314. p->running = 0;
  315. p->mode = 0;
  316. /* load microcode blocks */
  317. for (;;) {
  318. if (data_ptr >= data_end)
  319. return -EINVAL;
  320. if (copy_from_user(&code_h, data_ptr, sizeof(code_h)))
  321. return -EFAULT;
  322. /* init microcode blocks */
  323. if (code_h.name != INIT_HEADER)
  324. break;
  325. data_ptr += sizeof(code_h);
  326. err = snd_sb_csp_load_user(p, data_ptr, le32_to_cpu(code_h.len),
  327. SNDRV_SB_CSP_LOAD_INITBLOCK);
  328. if (err)
  329. return err;
  330. data_ptr += le32_to_cpu(code_h.len);
  331. }
  332. /* main microcode block */
  333. if (copy_from_user(&code_h, data_ptr, sizeof(code_h)))
  334. return -EFAULT;
  335. if (code_h.name != MAIN_HEADER) {
  336. snd_printd("%s: Missing 'main' microcode\n", __FUNCTION__);
  337. return -EINVAL;
  338. }
  339. data_ptr += sizeof(code_h);
  340. err = snd_sb_csp_load_user(p, data_ptr,
  341. le32_to_cpu(code_h.len), 0);
  342. if (err)
  343. return err;
  344. /* fill in codec header */
  345. strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name));
  346. p->func_nr = func_nr;
  347. p->mode = le16_to_cpu(funcdesc_h.flags_play_rec);
  348. switch (le16_to_cpu(funcdesc_h.VOC_type)) {
  349. case 0x0001: /* QSound decoder */
  350. if (le16_to_cpu(funcdesc_h.flags_play_rec) == SNDRV_SB_CSP_MODE_DSP_WRITE) {
  351. if (snd_sb_qsound_build(p) == 0)
  352. /* set QSound flag and clear all other mode flags */
  353. p->mode = SNDRV_SB_CSP_MODE_QSOUND;
  354. }
  355. p->acc_format = 0;
  356. break;
  357. case 0x0006: /* A Law codec */
  358. p->acc_format = SNDRV_PCM_FMTBIT_A_LAW;
  359. break;
  360. case 0x0007: /* Mu Law codec */
  361. p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW;
  362. break;
  363. case 0x0011: /* what Creative thinks is IMA ADPCM codec */
  364. case 0x0200: /* Creative ADPCM codec */
  365. p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM;
  366. break;
  367. case 201: /* Text 2 Speech decoder */
  368. /* TODO: Text2Speech handling routines */
  369. p->acc_format = 0;
  370. break;
  371. case 0x0202: /* Fast Speech 8 codec */
  372. case 0x0203: /* Fast Speech 10 codec */
  373. p->acc_format = SNDRV_PCM_FMTBIT_SPECIAL;
  374. break;
  375. default: /* other codecs are unsupported */
  376. p->acc_format = p->acc_width = p->acc_rates = 0;
  377. p->mode = 0;
  378. snd_printd("%s: Unsupported CSP codec type: 0x%04x\n",
  379. __FUNCTION__,
  380. le16_to_cpu(funcdesc_h.VOC_type));
  381. return -EINVAL;
  382. }
  383. p->acc_channels = le16_to_cpu(funcdesc_h.flags_stereo_mono);
  384. p->acc_width = le16_to_cpu(funcdesc_h.flags_16bit_8bit);
  385. p->acc_rates = le16_to_cpu(funcdesc_h.flags_rates);
  386. /* Decouple CSP from IRQ and DMAREQ lines */
  387. spin_lock_irqsave(&p->chip->reg_lock, flags);
  388. set_mode_register(p->chip, 0xfc);
  389. set_mode_register(p->chip, 0x00);
  390. spin_unlock_irqrestore(&p->chip->reg_lock, flags);
  391. /* finished loading successfully */
  392. p->running = SNDRV_SB_CSP_ST_LOADED; /* set LOADED flag */
  393. return 0;
  394. }
  395. }
  396. snd_printd("%s: Function #%d not found\n", __FUNCTION__, info.func_req);
  397. return -EINVAL;
  398. }
  399. /*
  400. * unload CSP microcode
  401. */
  402. static int snd_sb_csp_unload(struct snd_sb_csp * p)
  403. {
  404. if (p->running & SNDRV_SB_CSP_ST_RUNNING)
  405. return -EBUSY;
  406. if (!(p->running & SNDRV_SB_CSP_ST_LOADED))
  407. return -ENXIO;
  408. /* clear supported formats */
  409. p->acc_format = 0;
  410. p->acc_channels = p->acc_width = p->acc_rates = 0;
  411. /* destroy QSound mixer element */
  412. if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) {
  413. snd_sb_qsound_destroy(p);
  414. }
  415. /* clear all flags */
  416. p->running = 0;
  417. p->mode = 0;
  418. return 0;
  419. }
  420. /*
  421. * send command sequence to DSP
  422. */
  423. static inline int command_seq(struct snd_sb *chip, const unsigned char *seq, int size)
  424. {
  425. int i;
  426. for (i = 0; i < size; i++) {
  427. if (!snd_sbdsp_command(chip, seq[i]))
  428. return -EIO;
  429. }
  430. return 0;
  431. }
  432. /*
  433. * set CSP codec parameter
  434. */
  435. static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val)
  436. {
  437. unsigned char dsp_cmd[3];
  438. dsp_cmd[0] = 0x05; /* CSP set codec parameter */
  439. dsp_cmd[1] = val; /* Parameter value */
  440. dsp_cmd[2] = par; /* Parameter */
  441. command_seq(chip, dsp_cmd, 3);
  442. snd_sbdsp_command(chip, 0x03); /* DSP read? */
  443. if (snd_sbdsp_get_byte(chip) != par)
  444. return -EIO;
  445. return 0;
  446. }
  447. /*
  448. * set CSP register
  449. */
  450. static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val)
  451. {
  452. unsigned char dsp_cmd[3];
  453. dsp_cmd[0] = 0x0e; /* CSP set register */
  454. dsp_cmd[1] = reg; /* CSP Register */
  455. dsp_cmd[2] = val; /* value */
  456. return command_seq(chip, dsp_cmd, 3);
  457. }
  458. /*
  459. * read CSP register
  460. * return < 0 -> error
  461. */
  462. static int read_register(struct snd_sb *chip, unsigned char reg)
  463. {
  464. unsigned char dsp_cmd[2];
  465. dsp_cmd[0] = 0x0f; /* CSP read register */
  466. dsp_cmd[1] = reg; /* CSP Register */
  467. command_seq(chip, dsp_cmd, 2);
  468. return snd_sbdsp_get_byte(chip); /* Read DSP value */
  469. }
  470. /*
  471. * set CSP mode register
  472. */
  473. static int set_mode_register(struct snd_sb *chip, unsigned char mode)
  474. {
  475. unsigned char dsp_cmd[2];
  476. dsp_cmd[0] = 0x04; /* CSP set mode register */
  477. dsp_cmd[1] = mode; /* mode */
  478. return command_seq(chip, dsp_cmd, 2);
  479. }
  480. /*
  481. * Detect CSP
  482. * return 0 if CSP exists.
  483. */
  484. static int csp_detect(struct snd_sb *chip, int *version)
  485. {
  486. unsigned char csp_test1, csp_test2;
  487. unsigned long flags;
  488. int result = -ENODEV;
  489. spin_lock_irqsave(&chip->reg_lock, flags);
  490. set_codec_parameter(chip, 0x00, 0x00);
  491. set_mode_register(chip, 0xfc); /* 0xfc = ?? */
  492. csp_test1 = read_register(chip, 0x83);
  493. set_register(chip, 0x83, ~csp_test1);
  494. csp_test2 = read_register(chip, 0x83);
  495. if (csp_test2 != (csp_test1 ^ 0xff))
  496. goto __fail;
  497. set_register(chip, 0x83, csp_test1);
  498. csp_test2 = read_register(chip, 0x83);
  499. if (csp_test2 != csp_test1)
  500. goto __fail;
  501. set_mode_register(chip, 0x00); /* 0x00 = ? */
  502. *version = get_version(chip);
  503. snd_sbdsp_reset(chip); /* reset DSP after getversion! */
  504. if (*version >= 0x10 && *version <= 0x1f)
  505. result = 0; /* valid version id */
  506. __fail:
  507. spin_unlock_irqrestore(&chip->reg_lock, flags);
  508. return result;
  509. }
  510. /*
  511. * get CSP version number
  512. */
  513. static int get_version(struct snd_sb *chip)
  514. {
  515. unsigned char dsp_cmd[2];
  516. dsp_cmd[0] = 0x08; /* SB_DSP_!something! */
  517. dsp_cmd[1] = 0x03; /* get chip version id? */
  518. command_seq(chip, dsp_cmd, 2);
  519. return (snd_sbdsp_get_byte(chip));
  520. }
  521. /*
  522. * check if the CSP version is valid
  523. */
  524. static int snd_sb_csp_check_version(struct snd_sb_csp * p)
  525. {
  526. if (p->version < 0x10 || p->version > 0x1f) {
  527. snd_printd("%s: Invalid CSP version: 0x%x\n", __FUNCTION__, p->version);
  528. return 1;
  529. }
  530. return 0;
  531. }
  532. /*
  533. * download microcode to CSP (microcode should have one "main" block).
  534. */
  535. static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int size, int load_flags)
  536. {
  537. int status, i;
  538. int err;
  539. int result = -EIO;
  540. unsigned long flags;
  541. spin_lock_irqsave(&p->chip->reg_lock, flags);
  542. snd_sbdsp_command(p->chip, 0x01); /* CSP download command */
  543. if (snd_sbdsp_get_byte(p->chip)) {
  544. snd_printd("%s: Download command failed\n", __FUNCTION__);
  545. goto __fail;
  546. }
  547. /* Send CSP low byte (size - 1) */
  548. snd_sbdsp_command(p->chip, (unsigned char)(size - 1));
  549. /* Send high byte */
  550. snd_sbdsp_command(p->chip, (unsigned char)((size - 1) >> 8));
  551. /* send microcode sequence */
  552. /* load from kernel space */
  553. while (size--) {
  554. if (!snd_sbdsp_command(p->chip, *buf++))
  555. goto __fail;
  556. }
  557. if (snd_sbdsp_get_byte(p->chip))
  558. goto __fail;
  559. if (load_flags & SNDRV_SB_CSP_LOAD_INITBLOCK) {
  560. i = 0;
  561. /* some codecs (FastSpeech) take some time to initialize */
  562. while (1) {
  563. snd_sbdsp_command(p->chip, 0x03);
  564. status = snd_sbdsp_get_byte(p->chip);
  565. if (status == 0x55 || ++i >= 10)
  566. break;
  567. udelay (10);
  568. }
  569. if (status != 0x55) {
  570. snd_printd("%s: Microcode initialization failed\n", __FUNCTION__);
  571. goto __fail;
  572. }
  573. } else {
  574. /*
  575. * Read mixer register SB_DSP4_DMASETUP after loading 'main' code.
  576. * Start CSP chip if no 16bit DMA channel is set - some kind
  577. * of autorun or perhaps a bugfix?
  578. */
  579. spin_lock(&p->chip->mixer_lock);
  580. status = snd_sbmixer_read(p->chip, SB_DSP4_DMASETUP);
  581. spin_unlock(&p->chip->mixer_lock);
  582. if (!(status & (SB_DMASETUP_DMA7 | SB_DMASETUP_DMA6 | SB_DMASETUP_DMA5))) {
  583. err = (set_codec_parameter(p->chip, 0xaa, 0x00) ||
  584. set_codec_parameter(p->chip, 0xff, 0x00));
  585. snd_sbdsp_reset(p->chip); /* really! */
  586. if (err)
  587. goto __fail;
  588. set_mode_register(p->chip, 0xc0); /* c0 = STOP */
  589. set_mode_register(p->chip, 0x70); /* 70 = RUN */
  590. }
  591. }
  592. result = 0;
  593. __fail:
  594. spin_unlock_irqrestore(&p->chip->reg_lock, flags);
  595. return result;
  596. }
  597. static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags)
  598. {
  599. int err = -ENOMEM;
  600. unsigned char *kbuf = kmalloc(size, GFP_KERNEL);
  601. if (kbuf) {
  602. if (copy_from_user(kbuf, buf, size))
  603. err = -EFAULT;
  604. else
  605. err = snd_sb_csp_load(p, kbuf, size, load_flags);
  606. kfree(kbuf);
  607. }
  608. return err;
  609. }
  610. #define FIRMWARE_IN_THE_KERNEL
  611. #ifdef FIRMWARE_IN_THE_KERNEL
  612. #include "sb16_csp_codecs.h"
  613. static const struct firmware snd_sb_csp_static_programs[] = {
  614. { .data = mulaw_main, .size = sizeof mulaw_main },
  615. { .data = alaw_main, .size = sizeof alaw_main },
  616. { .data = ima_adpcm_init, .size = sizeof ima_adpcm_init },
  617. { .data = ima_adpcm_playback, .size = sizeof ima_adpcm_playback },
  618. { .data = ima_adpcm_capture, .size = sizeof ima_adpcm_capture },
  619. };
  620. #endif
  621. static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags)
  622. {
  623. static const char *const names[] = {
  624. "sb16/mulaw_main.csp",
  625. "sb16/alaw_main.csp",
  626. "sb16/ima_adpcm_init.csp",
  627. "sb16/ima_adpcm_playback.csp",
  628. "sb16/ima_adpcm_capture.csp",
  629. };
  630. const struct firmware *program;
  631. int err;
  632. BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT);
  633. program = p->csp_programs[index];
  634. if (!program) {
  635. err = request_firmware(&program, names[index],
  636. p->chip->card->dev);
  637. if (err >= 0)
  638. p->csp_programs[index] = program;
  639. else {
  640. #ifdef FIRMWARE_IN_THE_KERNEL
  641. program = &snd_sb_csp_static_programs[index];
  642. #else
  643. return err;
  644. #endif
  645. }
  646. }
  647. return snd_sb_csp_load(p, program->data, program->size, flags);
  648. }
  649. /*
  650. * autoload hardware codec if necessary
  651. * return 0 if CSP is loaded and ready to run (p->running != 0)
  652. */
  653. static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode)
  654. {
  655. unsigned long flags;
  656. int err = 0;
  657. /* if CSP is running or manually loaded then exit */
  658. if (p->running & (SNDRV_SB_CSP_ST_RUNNING | SNDRV_SB_CSP_ST_LOADED))
  659. return -EBUSY;
  660. /* autoload microcode only if requested hardware codec is not already loaded */
  661. if (((1 << pcm_sfmt) & p->acc_format) && (play_rec_mode & p->mode)) {
  662. p->running = SNDRV_SB_CSP_ST_AUTO;
  663. } else {
  664. switch (pcm_sfmt) {
  665. case SNDRV_PCM_FORMAT_MU_LAW:
  666. err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_MULAW, 0);
  667. p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW;
  668. p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE;
  669. break;
  670. case SNDRV_PCM_FORMAT_A_LAW:
  671. err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ALAW, 0);
  672. p->acc_format = SNDRV_PCM_FMTBIT_A_LAW;
  673. p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE;
  674. break;
  675. case SNDRV_PCM_FORMAT_IMA_ADPCM:
  676. err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ADPCM_INIT,
  677. SNDRV_SB_CSP_LOAD_INITBLOCK);
  678. if (err)
  679. break;
  680. if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) {
  681. err = snd_sb_csp_firmware_load
  682. (p, CSP_PROGRAM_ADPCM_PLAYBACK, 0);
  683. p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE;
  684. } else {
  685. err = snd_sb_csp_firmware_load
  686. (p, CSP_PROGRAM_ADPCM_CAPTURE, 0);
  687. p->mode = SNDRV_SB_CSP_MODE_DSP_READ;
  688. }
  689. p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM;
  690. break;
  691. default:
  692. /* Decouple CSP from IRQ and DMAREQ lines */
  693. if (p->running & SNDRV_SB_CSP_ST_AUTO) {
  694. spin_lock_irqsave(&p->chip->reg_lock, flags);
  695. set_mode_register(p->chip, 0xfc);
  696. set_mode_register(p->chip, 0x00);
  697. spin_unlock_irqrestore(&p->chip->reg_lock, flags);
  698. p->running = 0; /* clear autoloaded flag */
  699. }
  700. return -EINVAL;
  701. }
  702. if (err) {
  703. p->acc_format = 0;
  704. p->acc_channels = p->acc_width = p->acc_rates = 0;
  705. p->running = 0; /* clear autoloaded flag */
  706. p->mode = 0;
  707. return (err);
  708. } else {
  709. p->running = SNDRV_SB_CSP_ST_AUTO; /* set autoloaded flag */
  710. p->acc_width = SNDRV_SB_CSP_SAMPLE_16BIT; /* only 16 bit data */
  711. p->acc_channels = SNDRV_SB_CSP_MONO | SNDRV_SB_CSP_STEREO;
  712. p->acc_rates = SNDRV_SB_CSP_RATE_ALL; /* HW codecs accept all rates */
  713. }
  714. }
  715. return (p->running & SNDRV_SB_CSP_ST_AUTO) ? 0 : -ENXIO;
  716. }
  717. /*
  718. * start CSP
  719. */
  720. static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels)
  721. {
  722. unsigned char s_type; /* sample type */
  723. unsigned char mixL, mixR;
  724. int result = -EIO;
  725. unsigned long flags;
  726. if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) {
  727. snd_printd("%s: Microcode not loaded\n", __FUNCTION__);
  728. return -ENXIO;
  729. }
  730. if (p->running & SNDRV_SB_CSP_ST_RUNNING) {
  731. snd_printd("%s: CSP already running\n", __FUNCTION__);
  732. return -EBUSY;
  733. }
  734. if (!(sample_width & p->acc_width)) {
  735. snd_printd("%s: Unsupported PCM sample width\n", __FUNCTION__);
  736. return -EINVAL;
  737. }
  738. if (!(channels & p->acc_channels)) {
  739. snd_printd("%s: Invalid number of channels\n", __FUNCTION__);
  740. return -EINVAL;
  741. }
  742. /* Mute PCM volume */
  743. spin_lock_irqsave(&p->chip->mixer_lock, flags);
  744. mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV);
  745. mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);
  746. snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);
  747. snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);
  748. spin_lock(&p->chip->reg_lock);
  749. set_mode_register(p->chip, 0xc0); /* c0 = STOP */
  750. set_mode_register(p->chip, 0x70); /* 70 = RUN */
  751. s_type = 0x00;
  752. if (channels == SNDRV_SB_CSP_MONO)
  753. s_type = 0x11; /* 000n 000n (n = 1 if mono) */
  754. if (sample_width == SNDRV_SB_CSP_SAMPLE_8BIT)
  755. s_type |= 0x22; /* 00dX 00dX (d = 1 if 8 bit samples) */
  756. if (set_codec_parameter(p->chip, 0x81, s_type)) {
  757. snd_printd("%s: Set sample type command failed\n", __FUNCTION__);
  758. goto __fail;
  759. }
  760. if (set_codec_parameter(p->chip, 0x80, 0x00)) {
  761. snd_printd("%s: Codec start command failed\n", __FUNCTION__);
  762. goto __fail;
  763. }
  764. p->run_width = sample_width;
  765. p->run_channels = channels;
  766. p->running |= SNDRV_SB_CSP_ST_RUNNING;
  767. if (p->mode & SNDRV_SB_CSP_MODE_QSOUND) {
  768. set_codec_parameter(p->chip, 0xe0, 0x01);
  769. /* enable QSound decoder */
  770. set_codec_parameter(p->chip, 0x00, 0xff);
  771. set_codec_parameter(p->chip, 0x01, 0xff);
  772. p->running |= SNDRV_SB_CSP_ST_QSOUND;
  773. /* set QSound startup value */
  774. snd_sb_csp_qsound_transfer(p);
  775. }
  776. result = 0;
  777. __fail:
  778. spin_unlock(&p->chip->reg_lock);
  779. /* restore PCM volume */
  780. snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);
  781. snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);
  782. spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
  783. return result;
  784. }
  785. /*
  786. * stop CSP
  787. */
  788. static int snd_sb_csp_stop(struct snd_sb_csp * p)
  789. {
  790. int result;
  791. unsigned char mixL, mixR;
  792. unsigned long flags;
  793. if (!(p->running & SNDRV_SB_CSP_ST_RUNNING))
  794. return 0;
  795. /* Mute PCM volume */
  796. spin_lock_irqsave(&p->chip->mixer_lock, flags);
  797. mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV);
  798. mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);
  799. snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);
  800. snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);
  801. spin_lock(&p->chip->reg_lock);
  802. if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
  803. set_codec_parameter(p->chip, 0xe0, 0x01);
  804. /* disable QSound decoder */
  805. set_codec_parameter(p->chip, 0x00, 0x00);
  806. set_codec_parameter(p->chip, 0x01, 0x00);
  807. p->running &= ~SNDRV_SB_CSP_ST_QSOUND;
  808. }
  809. result = set_mode_register(p->chip, 0xc0); /* c0 = STOP */
  810. spin_unlock(&p->chip->reg_lock);
  811. /* restore PCM volume */
  812. snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);
  813. snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);
  814. spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
  815. if (!(result))
  816. p->running &= ~(SNDRV_SB_CSP_ST_PAUSED | SNDRV_SB_CSP_ST_RUNNING);
  817. return result;
  818. }
  819. /*
  820. * pause CSP codec and hold DMA transfer
  821. */
  822. static int snd_sb_csp_pause(struct snd_sb_csp * p)
  823. {
  824. int result;
  825. unsigned long flags;
  826. if (!(p->running & SNDRV_SB_CSP_ST_RUNNING))
  827. return -EBUSY;
  828. spin_lock_irqsave(&p->chip->reg_lock, flags);
  829. result = set_codec_parameter(p->chip, 0x80, 0xff);
  830. spin_unlock_irqrestore(&p->chip->reg_lock, flags);
  831. if (!(result))
  832. p->running |= SNDRV_SB_CSP_ST_PAUSED;
  833. return result;
  834. }
  835. /*
  836. * restart CSP codec and resume DMA transfer
  837. */
  838. static int snd_sb_csp_restart(struct snd_sb_csp * p)
  839. {
  840. int result;
  841. unsigned long flags;
  842. if (!(p->running & SNDRV_SB_CSP_ST_PAUSED))
  843. return -EBUSY;
  844. spin_lock_irqsave(&p->chip->reg_lock, flags);
  845. result = set_codec_parameter(p->chip, 0x80, 0x00);
  846. spin_unlock_irqrestore(&p->chip->reg_lock, flags);
  847. if (!(result))
  848. p->running &= ~SNDRV_SB_CSP_ST_PAUSED;
  849. return result;
  850. }
  851. /* ------------------------------ */
  852. /*
  853. * QSound mixer control for PCM
  854. */
  855. static int snd_sb_qsound_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  856. {
  857. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  858. uinfo->count = 1;
  859. uinfo->value.integer.min = 0;
  860. uinfo->value.integer.max = 1;
  861. return 0;
  862. }
  863. static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  864. {
  865. struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
  866. ucontrol->value.integer.value[0] = p->q_enabled ? 1 : 0;
  867. return 0;
  868. }
  869. static int snd_sb_qsound_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  870. {
  871. struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
  872. unsigned long flags;
  873. int change;
  874. unsigned char nval;
  875. nval = ucontrol->value.integer.value[0] & 0x01;
  876. spin_lock_irqsave(&p->q_lock, flags);
  877. change = p->q_enabled != nval;
  878. p->q_enabled = nval;
  879. spin_unlock_irqrestore(&p->q_lock, flags);
  880. return change;
  881. }
  882. static int snd_sb_qsound_space_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  883. {
  884. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  885. uinfo->count = 2;
  886. uinfo->value.integer.min = 0;
  887. uinfo->value.integer.max = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;
  888. return 0;
  889. }
  890. static int snd_sb_qsound_space_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  891. {
  892. struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
  893. unsigned long flags;
  894. spin_lock_irqsave(&p->q_lock, flags);
  895. ucontrol->value.integer.value[0] = p->qpos_left;
  896. ucontrol->value.integer.value[1] = p->qpos_right;
  897. spin_unlock_irqrestore(&p->q_lock, flags);
  898. return 0;
  899. }
  900. static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  901. {
  902. struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
  903. unsigned long flags;
  904. int change;
  905. unsigned char nval1, nval2;
  906. nval1 = ucontrol->value.integer.value[0];
  907. if (nval1 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT)
  908. nval1 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;
  909. nval2 = ucontrol->value.integer.value[1];
  910. if (nval2 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT)
  911. nval2 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;
  912. spin_lock_irqsave(&p->q_lock, flags);
  913. change = p->qpos_left != nval1 || p->qpos_right != nval2;
  914. p->qpos_left = nval1;
  915. p->qpos_right = nval2;
  916. p->qpos_changed = change;
  917. spin_unlock_irqrestore(&p->q_lock, flags);
  918. return change;
  919. }
  920. static struct snd_kcontrol_new snd_sb_qsound_switch = {
  921. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  922. .name = "3D Control - Switch",
  923. .info = snd_sb_qsound_switch_info,
  924. .get = snd_sb_qsound_switch_get,
  925. .put = snd_sb_qsound_switch_put
  926. };
  927. static struct snd_kcontrol_new snd_sb_qsound_space = {
  928. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  929. .name = "3D Control - Space",
  930. .info = snd_sb_qsound_space_info,
  931. .get = snd_sb_qsound_space_get,
  932. .put = snd_sb_qsound_space_put
  933. };
  934. static int snd_sb_qsound_build(struct snd_sb_csp * p)
  935. {
  936. struct snd_card *card;
  937. int err;
  938. snd_assert(p != NULL, return -EINVAL);
  939. card = p->chip->card;
  940. p->qpos_left = p->qpos_right = SNDRV_SB_CSP_QSOUND_MAX_RIGHT / 2;
  941. p->qpos_changed = 0;
  942. spin_lock_init(&p->q_lock);
  943. if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0)
  944. goto __error;
  945. if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0)
  946. goto __error;
  947. return 0;
  948. __error:
  949. snd_sb_qsound_destroy(p);
  950. return err;
  951. }
  952. static void snd_sb_qsound_destroy(struct snd_sb_csp * p)
  953. {
  954. struct snd_card *card;
  955. unsigned long flags;
  956. snd_assert(p != NULL, return);
  957. card = p->chip->card;
  958. down_write(&card->controls_rwsem);
  959. if (p->qsound_switch)
  960. snd_ctl_remove(card, p->qsound_switch);
  961. if (p->qsound_space)
  962. snd_ctl_remove(card, p->qsound_space);
  963. up_write(&card->controls_rwsem);
  964. /* cancel pending transfer of QSound parameters */
  965. spin_lock_irqsave (&p->q_lock, flags);
  966. p->qpos_changed = 0;
  967. spin_unlock_irqrestore (&p->q_lock, flags);
  968. }
  969. /*
  970. * Transfer qsound parameters to CSP,
  971. * function should be called from interrupt routine
  972. */
  973. static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p)
  974. {
  975. int err = -ENXIO;
  976. spin_lock(&p->q_lock);
  977. if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
  978. set_codec_parameter(p->chip, 0xe0, 0x01);
  979. /* left channel */
  980. set_codec_parameter(p->chip, 0x00, p->qpos_left);
  981. set_codec_parameter(p->chip, 0x02, 0x00);
  982. /* right channel */
  983. set_codec_parameter(p->chip, 0x00, p->qpos_right);
  984. set_codec_parameter(p->chip, 0x03, 0x00);
  985. err = 0;
  986. }
  987. p->qpos_changed = 0;
  988. spin_unlock(&p->q_lock);
  989. return err;
  990. }
  991. /* ------------------------------ */
  992. /*
  993. * proc interface
  994. */
  995. static int init_proc_entry(struct snd_sb_csp * p, int device)
  996. {
  997. char name[16];
  998. struct snd_info_entry *entry;
  999. sprintf(name, "cspD%d", device);
  1000. if (! snd_card_proc_new(p->chip->card, name, &entry))
  1001. snd_info_set_text_ops(entry, p, info_read);
  1002. return 0;
  1003. }
  1004. static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
  1005. {
  1006. struct snd_sb_csp *p = entry->private_data;
  1007. snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f));
  1008. snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'),
  1009. ((p->running & SNDRV_SB_CSP_ST_PAUSED) ? 'P' : '-'),
  1010. ((p->running & SNDRV_SB_CSP_ST_RUNNING) ? 'R' : '-'),
  1011. ((p->running & SNDRV_SB_CSP_ST_LOADED) ? 'L' : '-'));
  1012. if (p->running & SNDRV_SB_CSP_ST_LOADED) {
  1013. snd_iprintf(buffer, "Codec: %s [func #%d]\n", p->codec_name, p->func_nr);
  1014. snd_iprintf(buffer, "Sample rates: ");
  1015. if (p->acc_rates == SNDRV_SB_CSP_RATE_ALL) {
  1016. snd_iprintf(buffer, "All\n");
  1017. } else {
  1018. snd_iprintf(buffer, "%s%s%s%s\n",
  1019. ((p->acc_rates & SNDRV_SB_CSP_RATE_8000) ? "8000Hz " : ""),
  1020. ((p->acc_rates & SNDRV_SB_CSP_RATE_11025) ? "11025Hz " : ""),
  1021. ((p->acc_rates & SNDRV_SB_CSP_RATE_22050) ? "22050Hz " : ""),
  1022. ((p->acc_rates & SNDRV_SB_CSP_RATE_44100) ? "44100Hz" : ""));
  1023. }
  1024. if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) {
  1025. snd_iprintf(buffer, "QSound decoder %sabled\n",
  1026. p->q_enabled ? "en" : "dis");
  1027. } else {
  1028. snd_iprintf(buffer, "PCM format ID: 0x%x (%s/%s) [%s/%s] [%s/%s]\n",
  1029. p->acc_format,
  1030. ((p->acc_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? "16bit" : "-"),
  1031. ((p->acc_width & SNDRV_SB_CSP_SAMPLE_8BIT) ? "8bit" : "-"),
  1032. ((p->acc_channels & SNDRV_SB_CSP_MONO) ? "mono" : "-"),
  1033. ((p->acc_channels & SNDRV_SB_CSP_STEREO) ? "stereo" : "-"),
  1034. ((p->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) ? "playback" : "-"),
  1035. ((p->mode & SNDRV_SB_CSP_MODE_DSP_READ) ? "capture" : "-"));
  1036. }
  1037. }
  1038. if (p->running & SNDRV_SB_CSP_ST_AUTO) {
  1039. snd_iprintf(buffer, "Autoloaded Mu-Law, A-Law or Ima-ADPCM hardware codec\n");
  1040. }
  1041. if (p->running & SNDRV_SB_CSP_ST_RUNNING) {
  1042. snd_iprintf(buffer, "Processing %dbit %s PCM samples\n",
  1043. ((p->run_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? 16 : 8),
  1044. ((p->run_channels & SNDRV_SB_CSP_MONO) ? "mono" : "stereo"));
  1045. }
  1046. if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
  1047. snd_iprintf(buffer, "Qsound position: left = 0x%x, right = 0x%x\n",
  1048. p->qpos_left, p->qpos_right);
  1049. }
  1050. }
  1051. /* */
  1052. EXPORT_SYMBOL(snd_sb_csp_new);
  1053. /*
  1054. * INIT part
  1055. */
  1056. static int __init alsa_sb_csp_init(void)
  1057. {
  1058. return 0;
  1059. }
  1060. static void __exit alsa_sb_csp_exit(void)
  1061. {
  1062. }
  1063. module_init(alsa_sb_csp_init)
  1064. module_exit(alsa_sb_csp_exit)