s3c6410_pcm.c 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. /*
  2. * Common audio handling for the SA11x0 processor
  3. *
  4. * Copyright (C) 2007, Ryu Euiyoul <ryu.real@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License.
  8. *
  9. * This module handles the generic buffering/DMA/mmap audio interface for
  10. * codecs connected to the SA1100 chip. All features depending on specific
  11. * hardware implementations like supported audio formats or samplerates are
  12. * relegated to separate specific modules.
  13. *
  14. */
  15. #include <linux/module.h>
  16. #include <linux/init.h>
  17. #include <linux/types.h>
  18. #include <linux/fs.h>
  19. #include <linux/mm.h>
  20. #include <linux/slab.h>
  21. #include <linux/sched.h>
  22. #include <linux/poll.h>
  23. #include <linux/device.h>
  24. #include <linux/errno.h>
  25. #include <linux/sound.h>
  26. #include <linux/soundcard.h>
  27. #include <linux/sysrq.h>
  28. #include <linux/device.h>
  29. #include <linux/dma-mapping.h>
  30. #include <asm/uaccess.h>
  31. #include <asm/io.h>
  32. #include <asm/delay.h>
  33. #include <asm/hardware.h>
  34. #include <asm/semaphore.h>
  35. #include <asm/dma.h>
  36. #include <asm/arch/dma.h>
  37. #include <asm/arch/regs-iis.h>
  38. #include <asm/arch/regs-ac97.h>
  39. #include "s3c6400_pcm.h"
  40. #undef DEBUG
  41. //#define DEBUG
  42. #ifdef DEBUG
  43. #define DPRINTK printk
  44. #else
  45. #define DPRINTK( x... )
  46. #endif
  47. #define AUDIO_NAME "s3c-audio"
  48. #define AUDIO_NBFRAGS_DEFAULT 8
  49. //#define AUDIO_FRAGSIZE_DEFAULT 8192
  50. #define AUDIO_FRAGSIZE_DEFAULT 0x1000
  51. #define AUDIO_ACTIVE(state) ((state)->rd_ref || (state)->wr_ref)
  52. void audio_dma_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,
  53. int size, enum s3c2410_dma_buffresult result);
  54. /*
  55. * DMA processing
  56. */
  57. static struct s3c2410_dma_client s3cplay_dma_client = {
  58. .name = "s3c-play",
  59. };
  60. static struct s3c2410_dma_client s3cmic_dma_client = {
  61. .name = "s3c-recmic",
  62. };
  63. static int s3c_iis_dma_init(audio_stream_t *s,int mode)
  64. {
  65. if(mode == 0)
  66. {
  67. /* play channel */
  68. s3c2410_dma_devconfig(s->subchannel,
  69. S3C2410_DMASRC_MEM, 0, S3C_IIS0TXD_PHYS);
  70. } else if(mode ==1)
  71. {
  72. /* capture channel */
  73. s3c2410_dma_devconfig(s->subchannel,
  74. S3C2410_DMASRC_HW, 0, S3C_IIS0RXD_PHYS);
  75. } else {
  76. printk("Error : mode set\n");
  77. }
  78. s3c2410_dma_config(s->subchannel, 4, 0);
  79. s3c2410_dma_set_buffdone_fn(s->subchannel, audio_dma_callback);
  80. s3c2410_dma_setflags(s->subchannel, S3C2410_DMAF_AUTOSTART);
  81. return 0;
  82. }
  83. static u_int audio_get_dma_pos(audio_stream_t *s)
  84. {
  85. int dma_srcpos,dma_dstpos;
  86. audio_buf_t *b = &s->buffers[s->dma_tail];
  87. u_int offset;
  88. if (b->dma_ref) {
  89. s3c2410_dma_getposition(s->subchannel, &dma_srcpos, &dma_dstpos);
  90. offset = dma_srcpos - b->dma_addr;
  91. if (offset >= s->fragsize)
  92. offset = s->fragsize - 4;
  93. } else if (s->pending_frags) {
  94. offset = b->offset;
  95. } else {
  96. offset = 0;
  97. }
  98. return offset;
  99. }
  100. static void audio_stop_dma(audio_stream_t *s)
  101. {
  102. u_int pos;
  103. unsigned long flags;
  104. audio_buf_t *b;
  105. if (!s->buffers)
  106. return;
  107. local_irq_save(flags);
  108. s->stopped = 1;
  109. pos = audio_get_dma_pos(s);
  110. s3c2410_dma_ctrl(s->subchannel, S3C2410_DMAOP_FLUSH);
  111. local_irq_restore(flags);
  112. /* back up pointers to be ready to restart from the same spot */
  113. while (s->dma_head != s->dma_tail) {
  114. b = &s->buffers[s->dma_head];
  115. if (b->dma_ref) {
  116. b->dma_ref = 0;
  117. b->offset = 0;
  118. }
  119. s->pending_frags++;
  120. if (s->dma_head == 0)
  121. s->dma_head = s->nbfrags;
  122. s->dma_head--;
  123. }
  124. b = &s->buffers[s->dma_head];
  125. if (b->dma_ref) {
  126. b->offset = pos;
  127. b->dma_ref = 0;
  128. }
  129. }
  130. static void audio_reset(audio_stream_t *s)
  131. {
  132. if (s->buffers) {
  133. audio_stop_dma(s);
  134. s->buffers[s->dma_head].offset = 0;
  135. s->buffers[s->usr_head].offset = 0;
  136. s->usr_head = s->dma_head;
  137. s->pending_frags = 0;
  138. sema_init(&s->sem, s->nbfrags);
  139. }
  140. s->active = 0;
  141. s->stopped = 0;
  142. }
  143. static void audio_process_dma(audio_stream_t *s)
  144. {
  145. while (s->pending_frags) {
  146. audio_buf_t *b = &s->buffers[s->dma_head];
  147. u_int dma_size = s->fragsize - b->offset;
  148. s3c2410_dma_enqueue(s->subchannel, (void *) s,
  149. b->dma_addr+b->offset,dma_size);
  150. b->dma_ref++;
  151. b->offset += dma_size;
  152. if (b->offset >= s->fragsize) {
  153. s->pending_frags--;
  154. if (++s->dma_head >= s->nbfrags)
  155. s->dma_head = 0;
  156. }
  157. }
  158. }
  159. void audio_dma_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,
  160. int size, enum s3c2410_dma_buffresult result)
  161. {
  162. audio_stream_t *s = (audio_stream_t *)buf_id;
  163. audio_buf_t *b = &s->buffers[s->dma_tail];
  164. if (!s->buffers) {
  165. printk(KERN_CRIT "elfin: received DMA IRQ for non existent buffers!\n");
  166. return;
  167. } else if (b->dma_ref && --b->dma_ref == 0 && b->offset >= s->fragsize) {
  168. /* This fragment is done */
  169. b->offset = 0;
  170. s->bytecount += s->fragsize;
  171. s->fragcount++;
  172. if (++s->dma_tail >= s->nbfrags)
  173. s->dma_tail = 0;
  174. if (!s->mapped)
  175. up(&s->sem);
  176. else
  177. s->pending_frags++;
  178. wake_up(&s->wq);
  179. }
  180. audio_process_dma(s);
  181. }
  182. static int copy_to_user_stereo_mono(char *to, char *from, int count)
  183. {
  184. int ind, fact;
  185. if(!count)
  186. return 0;
  187. if(from[6] && from[7] && !from[5] && !from[4]) //check for the nonzero channel
  188. fact = 0;
  189. else
  190. fact = 1;
  191. ind = 0;
  192. while(ind < count){
  193. if(ind%2){
  194. *(from + ind) = *(from + 2*ind +1);
  195. *(from + ind) = *(from + 2*ind -1);
  196. }else{
  197. *(from + ind) = *(from + 2*ind +2);
  198. *(from + ind) = *(from + 2*ind -0);
  199. }
  200. ind++;
  201. }
  202. return copy_to_user(to, from, count);
  203. }
  204. static int copy_from_user_mono_stereo(char *to, const char *from, int count)
  205. {
  206. int ind;
  207. if(copy_from_user(to, from, count))
  208. return -EFAULT;
  209. ind = count - 1;
  210. while(ind){
  211. if(ind%2){
  212. *(to + 2*ind + 1) = *(to + ind);
  213. *(to + 2*ind - 1) = *(to + ind); // R;
  214. }else{
  215. *(to + 2*ind + 2) = *(to + ind);
  216. *(to + 2*ind + 0) = *(to + ind); // R;
  217. }
  218. ind--;
  219. }
  220. return 0;
  221. }
  222. /*
  223. * Buffer creation/destruction
  224. */
  225. static void audio_discard_buf(audio_stream_t * s)
  226. {
  227. DPRINTK("audio_discard_buf\n");
  228. /* ensure DMA isn't using those buffers */
  229. audio_reset(s);
  230. if (s->buffers) {
  231. int frag;
  232. for (frag = 0; frag < s->nbfrags; frag++) {
  233. if (!s->buffers[frag].master)
  234. continue;
  235. dma_free_coherent(s->dev,
  236. s->buffers[frag].master,
  237. s->buffers[frag].data, s->buffers[frag].dma_addr);
  238. }
  239. kfree(s->buffers);
  240. s->buffers = NULL;
  241. }
  242. }
  243. static int audio_setup_buf(audio_stream_t * s)
  244. {
  245. int frag;
  246. int dmasize = 0;
  247. char *dmabuf = NULL;
  248. dma_addr_t dmaphys = 0;
  249. if (s->buffers)
  250. return -EBUSY;
  251. s->buffers = kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
  252. if (!s->buffers)
  253. goto err;
  254. memset(s->buffers, 0, sizeof(audio_buf_t) * s->nbfrags);
  255. for (frag = 0; frag < s->nbfrags; frag++) {
  256. audio_buf_t *b = &s->buffers[frag];
  257. /*
  258. * Let's allocate non-cached memory for DMA buffers.
  259. * We try to allocate all memory at once.
  260. * If this fails (a common reason is memory fragmentation),
  261. * then we allocate more smaller buffers.
  262. */
  263. if (!dmasize) {
  264. dmasize = (s->nbfrags - frag) * s->fragsize;
  265. do {
  266. dmabuf = dma_alloc_coherent(s->dev, dmasize, &dmaphys, GFP_KERNEL);
  267. if (!dmabuf)
  268. dmasize -= s->fragsize;
  269. } while (!dmabuf && dmasize);
  270. if (!dmabuf)
  271. goto err;
  272. b->master = dmasize;
  273. memzero(dmabuf, dmasize);
  274. }
  275. b->data = dmabuf;
  276. b->dma_addr = dmaphys;
  277. DPRINTK("buf %d: start %p dma %#08x\n", frag, b->data, b->dma_addr);
  278. dmabuf += s->fragsize;
  279. dmaphys += s->fragsize;
  280. dmasize -= s->fragsize;
  281. }
  282. s->usr_head = s->dma_head = s->dma_tail = 0;
  283. s->bytecount = 0;
  284. s->fragcount = 0;
  285. sema_init(&s->sem, s->nbfrags);
  286. return 0;
  287. err:
  288. printk(AUDIO_NAME ": unable to allocate audio memory\n ");
  289. audio_discard_buf(s);
  290. return -ENOMEM;
  291. }
  292. /*
  293. * Driver interface functions
  294. */
  295. static int audio_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
  296. {
  297. const char *buffer0 = buffer;
  298. audio_state_t *state = file->private_data;
  299. audio_stream_t *s = state->output_stream;
  300. int chunksize, ret = 0;
  301. unsigned long flags;
  302. DPRINTK("audio_write: count=%d\n", count);
  303. if (s->mapped)
  304. return -ENXIO;
  305. if (!s->buffers && audio_setup_buf(s))
  306. return -ENOMEM;
  307. while (count > 0) {
  308. audio_buf_t *b = &s->buffers[s->usr_head];
  309. /* Wait for a buffer to become free */
  310. if (file->f_flags & O_NONBLOCK) {
  311. ret = -EAGAIN;
  312. if (down_trylock(&s->sem))
  313. break;
  314. } else {
  315. ret = -ERESTARTSYS;
  316. if (down_interruptible(&s->sem))
  317. break;
  318. }
  319. /* Feed the current buffer */
  320. if(state->sound_mode == MONO) {
  321. /* mono mode play back */
  322. if(count > s->fragsize/2)
  323. chunksize = s->fragsize/2;
  324. else
  325. chunksize = count;
  326. if (copy_from_user_mono_stereo(b->data + b->offset, buffer, chunksize)) {
  327. up(&s->sem);
  328. return -EFAULT;
  329. }
  330. b->offset += chunksize*2;
  331. } else {
  332. /* stereo mode play back */
  333. chunksize = s->fragsize - b->offset;
  334. if (chunksize > count)
  335. chunksize = count;
  336. DPRINTK("write %d to %d\n", chunksize, s->usr_head);
  337. if (copy_from_user(b->data + b->offset, buffer, chunksize)) {
  338. up(&s->sem);
  339. return -EFAULT;
  340. }
  341. b->offset += chunksize;
  342. }
  343. count -= chunksize;
  344. buffer += chunksize;
  345. if (b->offset < s->fragsize) {
  346. up(&s->sem);
  347. break;
  348. }
  349. /* Update pointers and send current fragment to DMA */
  350. b->offset = 0;
  351. if (++s->usr_head >= s->nbfrags)
  352. s->usr_head = 0;
  353. local_irq_save(flags);
  354. s->pending_frags++;
  355. s->active = 1;
  356. audio_process_dma(s);
  357. local_irq_restore(flags);
  358. }
  359. if ((buffer - buffer0))
  360. ret = buffer - buffer0;
  361. DPRINTK("audio_write: return=%d\n", ret);
  362. return ret;
  363. }
  364. static void audio_prime_rx(audio_state_t *state)
  365. {
  366. audio_stream_t *is = state->input_stream;
  367. unsigned long flags;
  368. local_irq_save(flags);
  369. is->pending_frags = is->nbfrags;
  370. sema_init(&is->sem, 0);
  371. is->active = 1;
  372. audio_process_dma(is);
  373. local_irq_restore(flags);
  374. }
  375. static int audio_read(struct file *file, char *buffer, size_t count, loff_t * ppos)
  376. {
  377. char *buffer0 = buffer;
  378. audio_state_t *state = file->private_data;
  379. audio_stream_t *s = state->input_stream;
  380. int chunksize, ret = 0;
  381. unsigned long flags;
  382. DPRINTK("audio_read: count=%d\n", count);
  383. if (s->mapped)
  384. return -ENXIO;
  385. if (!s->active) {
  386. if (!s->buffers && audio_setup_buf(s))
  387. return -ENOMEM;
  388. audio_prime_rx(state);
  389. }
  390. while (count > 0) {
  391. audio_buf_t *b = &s->buffers[s->usr_head];
  392. /* Wait for a buffer to become full */
  393. if (file->f_flags & O_NONBLOCK) {
  394. ret = -EAGAIN;
  395. if (down_trylock(&s->sem))
  396. break;
  397. } else {
  398. ret = -ERESTARTSYS;
  399. if (down_interruptible(&s->sem))
  400. break;
  401. }
  402. /* Grab data from the current buffer */
  403. if(state->sound_mode == MONO) {
  404. chunksize = (s->fragsize - b->offset)/2;
  405. if(chunksize > count)
  406. chunksize = count/2;
  407. if(copy_to_user_stereo_mono(buffer, b->data + b->offset, chunksize)) {
  408. up(&s->sem);
  409. return -EFAULT;
  410. }
  411. b->offset += chunksize * 2;
  412. } else {
  413. /* stereo mode play back */
  414. chunksize = s->fragsize - b->offset;
  415. if (chunksize > count)
  416. chunksize = count;
  417. #if 0
  418. DPRINTK("%s:%d buffer 0x%x data 0x%x offset 0x%x chunksize 0x%x, count 0x%x\n"
  419. ,__FUNCTION__, __LINE__
  420. ,*buffer, *b->data, b->offset, chunksize, count);
  421. #endif
  422. if (copy_to_user(buffer, b->data + b->offset, chunksize)) {
  423. /* to , from , n */
  424. up(&s->sem);
  425. return -EFAULT;
  426. }
  427. b->offset += chunksize;
  428. }
  429. buffer += chunksize;
  430. count -= chunksize;
  431. if (b->offset < s->fragsize) {
  432. up(&s->sem);
  433. break;
  434. }
  435. /* Update pointers and return current fragment to DMA */
  436. b->offset = 0;
  437. if (++s->usr_head >= s->nbfrags)
  438. s->usr_head = 0;
  439. local_irq_save(flags);
  440. s->pending_frags++;
  441. audio_process_dma(s);
  442. local_irq_restore(flags);
  443. }
  444. if ((buffer - buffer0))
  445. ret = buffer - buffer0;
  446. DPRINTK("audio_read: return=%d\n", ret);
  447. return ret;
  448. }
  449. static int audio_sync(struct file *file)
  450. {
  451. audio_state_t *state = file->private_data;
  452. audio_stream_t *s = state->output_stream;
  453. audio_buf_t *b;
  454. u_int shiftval = 0;
  455. unsigned long flags;
  456. DECLARE_WAITQUEUE(wait, current);
  457. DPRINTK("audio_sync\n");
  458. if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped)
  459. return 0;
  460. /*
  461. * Send current buffer if it contains data. Be sure to send
  462. * a full sample count.
  463. */
  464. b = &s->buffers[s->usr_head];
  465. if (b->offset &= ~3) {
  466. down(&s->sem);
  467. /*
  468. * HACK ALERT !
  469. * To avoid increased complexity in the rest of the code
  470. * where full fragment sizes are assumed, we cheat a little
  471. * with the start pointer here and don't forget to restore
  472. * it later.
  473. */
  474. shiftval = s->fragsize - b->offset;
  475. b->offset = shiftval;
  476. b->dma_addr -= shiftval;
  477. s->bytecount -= shiftval;
  478. if (++s->usr_head >= s->nbfrags)
  479. s->usr_head = 0;
  480. local_irq_save(flags);
  481. s->pending_frags++;
  482. audio_process_dma(s);
  483. local_irq_restore(flags);
  484. }
  485. /* Let's wait for all buffers to complete */
  486. set_current_state(TASK_INTERRUPTIBLE);
  487. add_wait_queue(&s->wq, &wait);
  488. while (s->pending_frags && s->dma_tail != s->usr_head && !signal_pending(current)) {
  489. schedule();
  490. set_current_state(TASK_INTERRUPTIBLE);
  491. }
  492. set_current_state(TASK_RUNNING);
  493. remove_wait_queue(&s->wq, &wait);
  494. /* undo the pointer hack above */
  495. if (shiftval) {
  496. local_irq_save(flags);
  497. b->dma_addr += shiftval;
  498. /* ensure sane DMA code behavior if not yet processed */
  499. if (b->offset != 0)
  500. b->offset = s->fragsize;
  501. local_irq_restore(flags);
  502. }
  503. return 0;
  504. }
  505. static int audio_mmap(struct file *file, struct vm_area_struct *vma)
  506. {
  507. audio_state_t *state = file->private_data;
  508. audio_stream_t *s;
  509. unsigned long size, vma_addr;
  510. int i, ret;
  511. if (vma->vm_pgoff != 0)
  512. return -EINVAL;
  513. if (vma->vm_flags & VM_WRITE) {
  514. if (!state->wr_ref)
  515. return -EINVAL;;
  516. s = state->output_stream;
  517. } else if (vma->vm_flags & VM_READ) {
  518. if (!state->rd_ref)
  519. return -EINVAL;
  520. s = state->input_stream;
  521. } else
  522. return -EINVAL;
  523. if (s->mapped)
  524. return -EINVAL;
  525. size = vma->vm_end - vma->vm_start;
  526. if (size != s->fragsize * s->nbfrags)
  527. return -EINVAL;
  528. if (!s->buffers && audio_setup_buf(s))
  529. return -ENOMEM;
  530. vma_addr = vma->vm_start;
  531. for (i = 0; i < s->nbfrags; i++) {
  532. audio_buf_t *buf = &s->buffers[i];
  533. if (!buf->master)
  534. continue;
  535. ret = remap_pfn_range(vma, vma_addr, buf->dma_addr, buf->master, vma->vm_page_prot);
  536. if (ret)
  537. return ret;
  538. vma_addr += buf->master;
  539. }
  540. s->mapped = 1;
  541. return 0;
  542. }
  543. static unsigned int audio_poll(struct file *file, struct poll_table_struct *wait)
  544. {
  545. audio_state_t *state = file->private_data;
  546. audio_stream_t *is = state->input_stream;
  547. audio_stream_t *os = state->output_stream;
  548. unsigned int mask = 0;
  549. DPRINTK("audio_poll(): mode=%s%s\n",
  550. (file->f_mode & FMODE_READ) ? "r" : "", (file->f_mode & FMODE_WRITE) ? "w" : "");
  551. if (file->f_mode & FMODE_READ) {
  552. /* Start audio input if not already active */
  553. if (!is->active) {
  554. if (!is->buffers && audio_setup_buf(is))
  555. return -ENOMEM;
  556. audio_prime_rx(state);
  557. }
  558. poll_wait(file, &is->wq, wait);
  559. }
  560. if (file->f_mode & FMODE_WRITE) {
  561. if (!os->buffers && audio_setup_buf(os))
  562. return -ENOMEM;
  563. poll_wait(file, &os->wq, wait);
  564. }
  565. if (file->f_mode & FMODE_READ)
  566. if (( is->mapped && is->bytecount > 0))
  567. mask |= POLLIN | POLLRDNORM;
  568. if (file->f_mode & FMODE_WRITE)
  569. if (( os->mapped && os->bytecount > 0))
  570. mask |= POLLOUT | POLLWRNORM;
  571. DPRINTK("audio_poll() returned mask of %s%s\n",
  572. (mask & POLLIN) ? "r" : "", (mask & POLLOUT) ? "w" : "");
  573. return mask;
  574. }
  575. static loff_t audio_llseek(struct file *file, loff_t offset, int origin)
  576. {
  577. return -ESPIPE;
  578. }
  579. static int audio_set_fragments(audio_stream_t *s, int val)
  580. {
  581. if (s->active)
  582. return -EBUSY;
  583. if (s->buffers)
  584. audio_discard_buf(s);
  585. s->nbfrags = (val >> 16) & 0x7FFF;
  586. val &= 0xffff;
  587. if (val < 4)
  588. val = 4;
  589. if (val > 15)
  590. val = 15;
  591. s->fragsize = 1 << val;
  592. if (s->nbfrags < 2)
  593. s->nbfrags = 2;
  594. if (s->nbfrags * s->fragsize > 128 * 1024)
  595. s->nbfrags = 128 * 1024 / s->fragsize;
  596. if (audio_setup_buf(s))
  597. return -ENOMEM;
  598. return val|(s->nbfrags << 16);
  599. }
  600. static int audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
  601. {
  602. audio_state_t *state = file->private_data;
  603. audio_stream_t *os = state->output_stream;
  604. audio_stream_t *is = state->input_stream;
  605. audio_buf_info inf = { 0, };
  606. long val;
  607. /* dispatch based on command */
  608. switch (cmd) {
  609. case OSS_GETVERSION:
  610. return put_user(SOUND_VERSION, (int *)arg);
  611. case SNDCTL_DSP_GETBLKSIZE:
  612. if (file->f_mode & FMODE_WRITE)
  613. return put_user(os->fragsize, (int *)arg);
  614. else
  615. return put_user(is->fragsize, (int *)arg);
  616. case SNDCTL_DSP_GETCAPS:
  617. val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
  618. if (is && os)
  619. val |= DSP_CAP_DUPLEX;
  620. return put_user(val, (int *)arg);
  621. case SNDCTL_DSP_SETFRAGMENT:
  622. if (get_user(val, (long *) arg))
  623. return -EFAULT;
  624. if (file->f_mode & FMODE_READ) {
  625. int ret = audio_set_fragments(is, val);
  626. if (ret < 0)
  627. return ret;
  628. ret = put_user(ret, (int *)arg);
  629. if (ret)
  630. return ret;
  631. }
  632. if (file->f_mode & FMODE_WRITE) {
  633. int ret = audio_set_fragments(os, val);
  634. if (ret < 0)
  635. return ret;
  636. ret = put_user(ret, (int *)arg);
  637. if (ret)
  638. return ret;
  639. }
  640. return 0;
  641. case SNDCTL_DSP_SYNC:
  642. return audio_sync(file);
  643. case SNDCTL_DSP_SETDUPLEX:
  644. return 0;
  645. case SNDCTL_DSP_POST:
  646. return 0;
  647. case SNDCTL_DSP_GETTRIGGER:
  648. val = 0;
  649. if (file->f_mode & FMODE_READ && is->active && !is->stopped)
  650. val |= PCM_ENABLE_INPUT;
  651. if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
  652. val |= PCM_ENABLE_OUTPUT;
  653. return put_user(val, (int *)arg);
  654. case SNDCTL_DSP_SETTRIGGER:
  655. if (get_user(val, (int *)arg))
  656. return -EFAULT;
  657. if (file->f_mode & FMODE_READ) {
  658. if (val & PCM_ENABLE_INPUT) {
  659. unsigned long flags;
  660. if (!is->active) {
  661. if (!is->buffers && audio_setup_buf(is))
  662. return -ENOMEM;
  663. audio_prime_rx(state);
  664. }
  665. local_irq_save(flags);
  666. is->stopped = 0;
  667. audio_process_dma(is);
  668. local_irq_restore(flags);
  669. } else {
  670. audio_stop_dma(is);
  671. }
  672. }
  673. if (file->f_mode & FMODE_WRITE) {
  674. if (val & PCM_ENABLE_OUTPUT) {
  675. unsigned long flags;
  676. if (!os->buffers && audio_setup_buf(os))
  677. return -ENOMEM;
  678. local_irq_save(flags);
  679. if (os->mapped && !os->pending_frags) {
  680. os->pending_frags = os->nbfrags;
  681. sema_init(&os->sem, 0);
  682. os->active = 1;
  683. }
  684. os->stopped = 0;
  685. audio_process_dma(os);
  686. local_irq_restore(flags);
  687. } else {
  688. audio_stop_dma(os);
  689. }
  690. }
  691. return 0;
  692. case SNDCTL_DSP_GETOPTR:
  693. case SNDCTL_DSP_GETIPTR:
  694. {
  695. count_info inf = { 0, };
  696. audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
  697. int bytecount, offset;
  698. unsigned long flags;
  699. if ((s == is && !(file->f_mode & FMODE_READ)) ||
  700. (s == os && !(file->f_mode & FMODE_WRITE)))
  701. return -EINVAL;
  702. if (s->active) {
  703. local_irq_save(flags);
  704. offset = audio_get_dma_pos(s);
  705. inf.ptr = s->dma_tail * s->fragsize + offset;
  706. bytecount = s->bytecount + offset;
  707. s->bytecount = -offset;
  708. inf.blocks = s->fragcount;
  709. s->fragcount = 0;
  710. local_irq_restore(flags);
  711. if (bytecount < 0)
  712. bytecount = 0;
  713. inf.bytes = bytecount;
  714. }
  715. return copy_to_user((void *)arg, &inf, sizeof(inf));
  716. }
  717. case SNDCTL_DSP_GETOSPACE:
  718. {
  719. audio_stream_t *s = os;
  720. if (!(file->f_mode & FMODE_WRITE))
  721. return -EINVAL;
  722. if (!s->buffers && audio_setup_buf(s))
  723. return -ENOMEM;
  724. inf.bytes = s->fragsize * s->free_bufnum;
  725. inf.fragments = s->free_bufnum;
  726. inf.fragsize = s->fragsize;
  727. inf.fragstotal = s->nbfrags;
  728. return copy_to_user((void *) arg, &inf, sizeof(inf));
  729. }
  730. case SNDCTL_DSP_GETISPACE:
  731. {
  732. audio_stream_t *s = is;
  733. if (!(file->f_mode & FMODE_READ))
  734. return -EINVAL;
  735. if (!s->buffers && audio_setup_buf(s))
  736. return -ENOMEM;
  737. inf.bytes = s->fragsize * s->free_bufnum;
  738. inf.fragments = s->free_bufnum;
  739. inf.fragsize = s->fragsize;
  740. inf.fragstotal = s->nbfrags;
  741. return copy_to_user((void *) arg, &inf, sizeof(inf));
  742. }
  743. case SNDCTL_DSP_NONBLOCK:
  744. file->f_flags |= O_NONBLOCK;
  745. return 0;
  746. case SNDCTL_DSP_RESET:
  747. if (file->f_mode & FMODE_READ) {
  748. audio_reset(is);
  749. }
  750. if (file->f_mode & FMODE_WRITE) {
  751. audio_reset(os);
  752. }
  753. return 0;
  754. default:
  755. /*
  756. * Let the client of this module handle the
  757. * non generic ioctls
  758. */
  759. return state->client_ioctl(inode, file, cmd, arg);
  760. }
  761. return 0;
  762. }
  763. static int audio_release(struct inode *inode, struct file *file)
  764. {
  765. audio_state_t *state = file->private_data;
  766. audio_stream_t *os = state->output_stream;
  767. audio_stream_t *is = state->input_stream;
  768. DPRINTK("audio_release\n");
  769. down(&state->sem);
  770. if (file->f_mode & FMODE_READ) {
  771. audio_discard_buf(is);
  772. s3c2410_dma_free(is->subchannel, &s3cmic_dma_client);
  773. /*
  774. s3c2410_dma_free(is->subchannel, &s3cline_dma_client);
  775. */
  776. state->rd_ref = 0;
  777. }
  778. if (file->f_mode & FMODE_WRITE) {
  779. audio_sync(file);
  780. audio_discard_buf(os);
  781. s3c2410_dma_free( os->subchannel, &s3cplay_dma_client);
  782. state->wr_ref = 0;
  783. }
  784. if (!AUDIO_ACTIVE(state)) {
  785. if (state->hw_shutdown)
  786. state->hw_shutdown(state->data);
  787. }
  788. up(&state->sem);
  789. return 0;
  790. }
  791. #ifdef CONFIG_PM
  792. int s3c64xx_audio_suspend(audio_state_t * s, u32 state, u32 level)
  793. {
  794. if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) {
  795. audio_stream_t *is = s->input_stream;
  796. audio_stream_t *os = s->output_stream;
  797. int stopstate;
  798. if (is) {
  799. stopstate = is->stopped;
  800. audio_stop_dma(is);
  801. s3c_dma_ctrl(is->dma, is->subchannel, S3C_DMAOP_FLUSH);
  802. is->stopped = stopstate;
  803. }
  804. if (os) {
  805. stopstate = os->stopped;
  806. audio_stop_dma(os);
  807. s3c_dma_ctrl(os->dma, os->subchannel, S3C_DMAOP_FLUSH);
  808. os->stopped = stopstate;
  809. }
  810. if (AUDIO_ACTIVE(s) && s->hw_shutdown)
  811. s->hw_shutdown(s->data);
  812. }
  813. return 0;
  814. }
  815. int s3c64xx_audio_resume(audio_state_t * s, u32 level)
  816. {
  817. printk("%s\n", __FUNCTION__);
  818. #if 0
  819. if (level == RESUME_ENABLE) {
  820. audio_stream_t *is = s->input_stream;
  821. audio_stream_t *os = s->output_stream;
  822. if (AUDIO_ACTIVE(s) && s->hw_init)
  823. s->hw_init(s->data);
  824. if (os && os->dma_regs) {
  825. //DMA_RESET(os);
  826. audio_process_dma(os);
  827. }
  828. if (is && is->dma_regs) {
  829. //DMA_RESET(is);
  830. audio_process_dma(is);
  831. }
  832. }
  833. #endif
  834. return 0;
  835. }
  836. EXPORT_SYMBOL(s3c64xx_audio_suspend);
  837. EXPORT_SYMBOL(s3c64xx_audio_resume);
  838. #else
  839. #define s3c64xx_audio_suspend() NULL
  840. #define s3c64xx_audio_resume() NULL
  841. #endif
  842. /* structure file_operations changed to const.
  843. */
  844. static const struct file_operations s3c_f_ops =
  845. {
  846. .release = audio_release,
  847. .write = audio_write,
  848. .read = audio_read,
  849. .mmap = audio_mmap,
  850. .poll = audio_poll,
  851. .ioctl = audio_ioctl,
  852. .llseek = audio_llseek
  853. };
  854. int s3c_audio_attach(struct inode *inode, struct file *file,
  855. audio_state_t *state)
  856. {
  857. audio_stream_t *os = state->output_stream;
  858. audio_stream_t *is = state->input_stream;
  859. int err, need_tx_dma=0;
  860. DPRINTK("audio_open\n");
  861. down(&state->sem);
  862. /* access control */
  863. err = -ENODEV;
  864. if ((file->f_mode & FMODE_WRITE) && !os)
  865. goto out;
  866. if ((file->f_mode & FMODE_READ) && !is)
  867. goto out;
  868. err = -EBUSY;
  869. if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
  870. goto out;
  871. if ((file->f_mode & FMODE_READ) && state->rd_ref)
  872. goto out;
  873. err = -EINVAL;
  874. if ((file->f_mode & FMODE_READ) && state->need_tx_for_rx && !os)
  875. goto out;
  876. if(file->f_mode & FMODE_READ)
  877. file->f_mode = FMODE_READ;
  878. DPRINTK("%s, f_mode = 0x%x\n", __FUNCTION__, file->f_mode);
  879. /* request DMA channels */
  880. if (file->f_mode & FMODE_WRITE) {
  881. if(s3c2410_dma_request(os->subchannel,
  882. &s3cplay_dma_client, NULL)) {
  883. printk(KERN_WARNING "unable to get DMA channel.\n" );
  884. err = -EBUSY;
  885. goto out;
  886. }
  887. need_tx_dma = 1;
  888. err = s3c_iis_dma_init(os,0);
  889. if(err)
  890. goto out;
  891. } else if (file->f_mode & FMODE_READ) {
  892. if(s3c2410_dma_request(is->subchannel,
  893. &s3cmic_dma_client, NULL)) {
  894. printk(KERN_WARNING "unable to get DMA channel.\n" );
  895. err = -EBUSY;
  896. if (need_tx_dma)
  897. s3c2410_dma_free(os->subchannel, &s3cplay_dma_client);
  898. s3c2410_dma_free(is->subchannel, &s3cmic_dma_client);
  899. goto out;
  900. }
  901. err = s3c_iis_dma_init(is,1);
  902. if(err)
  903. goto out;
  904. } else {
  905. printk("Error : audio set\n");
  906. goto out;
  907. }
  908. /* now complete initialisation */
  909. if (!AUDIO_ACTIVE(state)) {
  910. if (state->hw_init)
  911. state->hw_init(state->data);
  912. }
  913. if ((file->f_mode & FMODE_WRITE)) {
  914. state->wr_ref = 1;
  915. audio_reset(os);
  916. os->fragsize = AUDIO_FRAGSIZE_DEFAULT;
  917. os->nbfrags = AUDIO_NBFRAGS_DEFAULT;
  918. os->free_bufnum = AUDIO_NBFRAGS_DEFAULT;
  919. os->mapped = 0;
  920. init_waitqueue_head(&os->wq);
  921. } else if (file->f_mode & FMODE_READ) {
  922. state->rd_ref = 1;
  923. audio_reset(is);
  924. is->fragsize = AUDIO_FRAGSIZE_DEFAULT;
  925. is->nbfrags = AUDIO_NBFRAGS_DEFAULT;
  926. is->free_bufnum = AUDIO_NBFRAGS_DEFAULT;
  927. is->mapped = 0;
  928. init_waitqueue_head(&is->wq);
  929. } else {
  930. printk("Error : audio set\n");
  931. goto out;
  932. }
  933. file->private_data = state;
  934. file->f_op = &s3c_f_ops;
  935. err = 0;
  936. out:
  937. up(&state->sem);
  938. return err;
  939. }
  940. EXPORT_SYMBOL(s3c_audio_attach);
  941. MODULE_AUTHOR("Ryu Euiyoul");
  942. MODULE_DESCRIPTION("Common audio handling for the Samsung AP");
  943. MODULE_LICENSE("GPL");