devaudio.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. /*
  2. * SAC/UDA 1341 Audio driver for the Bitsy
  3. *
  4. * This code is covered by the Lucent Public Licence 1.02 (http://plan9.bell-labs.com/plan9dist/license.html);
  5. * see the file NOTICE in the current directory. Modifications for the Inferno environment by Vita Nuova.
  6. *
  7. * The Philips UDA 1341 sound chip is accessed through the Serial Audio
  8. * Controller (SAC) of the StrongARM SA-1110.
  9. *
  10. * The code morphs Nicolas Pitre's <nico@cam.org> Linux controller
  11. * and Ken's Soundblaster controller.
  12. *
  13. * The interface should be identical to that of devaudio.c
  14. */
  15. #include "u.h"
  16. #include "../port/lib.h"
  17. #include "mem.h"
  18. #include "dat.h"
  19. #include "fns.h"
  20. #include "../port/error.h"
  21. #include "io.h"
  22. static int debug = 0;
  23. /* UDA 1341 Registers */
  24. enum {
  25. /* Status0 register */
  26. UdaStatusDC = 0, /* 1 bit */
  27. UdaStatusIF = 1, /* 3 bits */
  28. UdaStatusSC = 4, /* 2 bits */
  29. UdaStatusRST = 6, /* 1 bit */
  30. };
  31. enum {
  32. /* Status1 register */
  33. UdaStatusPC = 0, /* 2 bits */
  34. UdaStatusDS = 2, /* 1 bit */
  35. UdaStatusPDA = 3, /* 1 bit */
  36. UdaStatusPAD = 4, /* 1 bit */
  37. UdaStatusIGS = 5, /* 1 bit */
  38. UdaStatusOGS = 6, /* 1 bit */
  39. };
  40. /*
  41. * UDA1341 L3 address and command types
  42. */
  43. enum {
  44. UDA1341_DATA0 = 0,
  45. UDA1341_DATA1,
  46. UDA1341_STATUS,
  47. UDA1341_L3Addr = 0x14,
  48. };
  49. typedef struct AQueue AQueue;
  50. typedef struct Buf Buf;
  51. typedef struct IOstate IOstate;
  52. enum
  53. {
  54. Qdir = 0,
  55. Qaudio,
  56. Qvolume,
  57. Qstatus,
  58. Qaudioctl,
  59. Fmono = 1,
  60. Fin = 2,
  61. Fout = 4,
  62. Aclosed = 0,
  63. Aread,
  64. Awrite,
  65. Vaudio = 0,
  66. Vmic,
  67. Vtreb,
  68. Vbass,
  69. Vspeed,
  70. Vfilter,
  71. Vinvert,
  72. Nvol,
  73. Bufsize = 4*1024, /* 46 ms each */
  74. Nbuf = 32, /* 1.5 seconds total */
  75. Speed = 44100,
  76. Ncmd = 50, /* max volume command words */
  77. };
  78. Dirtab
  79. audiodir[] =
  80. {
  81. ".", {Qdir, 0, QTDIR}, 0, 0555,
  82. "audio", {Qaudio}, 0, 0666,
  83. "volume", {Qvolume}, 0, 0666,
  84. "audioctl", {Qaudioctl}, 0, 0666,
  85. "audiostat",{Qstatus}, 0, 0444,
  86. };
  87. struct Buf
  88. {
  89. uchar* virt;
  90. ulong phys;
  91. uint nbytes;
  92. };
  93. struct IOstate
  94. {
  95. QLock;
  96. Lock ilock;
  97. Rendez vous;
  98. Chan *chan; /* chan of open */
  99. Dma* dma; /* dma chan, alloc on open, free on close */
  100. int bufinit; /* boolean, if buffers allocated */
  101. Buf buf[Nbuf]; /* buffers and queues */
  102. volatile Buf *current; /* next dma to finish */
  103. volatile Buf *next; /* next candidate for dma */
  104. volatile Buf *filling; /* buffer being filled */
  105. /* just be be cute (and to have defines like linux, a real operating system) */
  106. #define emptying filling
  107. };
  108. static struct
  109. {
  110. QLock;
  111. int amode; /* Aclosed/Aread/Awrite for /audio */
  112. int intr; /* boolean an interrupt has happened */
  113. int rivol[Nvol]; /* right/left input/output volumes */
  114. int livol[Nvol];
  115. int rovol[Nvol];
  116. int lovol[Nvol];
  117. uvlong totcount; /* how many bytes processed since open */
  118. vlong tottime; /* time at which totcount bytes were processed */
  119. int clockout; /* need steady output to provide input clock */
  120. IOstate i;
  121. IOstate o;
  122. } audio;
  123. static struct
  124. {
  125. ulong bytes;
  126. ulong totaldma;
  127. ulong idledma;
  128. ulong faildma;
  129. ulong samedma;
  130. } iostats;
  131. static struct
  132. {
  133. char* name;
  134. int flag;
  135. int ilval; /* initial values */
  136. int irval;
  137. } volumes[] =
  138. {
  139. [Vaudio] {"audio", Fout|Fmono, 80, 80},
  140. [Vmic] {"mic", Fin|Fmono, 0, 0},
  141. [Vtreb] {"treb", Fout|Fmono, 50, 50},
  142. [Vbass] {"bass", Fout|Fmono, 50, 50},
  143. [Vspeed] {"speed", Fin|Fout|Fmono, Speed, Speed},
  144. [Vfilter] {"filter", Fout|Fmono, 0, 0},
  145. [Vinvert] {"invert", Fin|Fout|Fmono, 0, 0},
  146. [Nvol] {0}
  147. };
  148. static void setreg(char *name, int val, int n);
  149. static char Emode[] = "illegal open mode";
  150. static char Evolume[] = "illegal volume specifier";
  151. static void
  152. bufinit(IOstate *b)
  153. {
  154. int i;
  155. if (debug) print("bufinit\n");
  156. for (i = 0; i < Nbuf; i++) {
  157. b->buf[i].virt = xspanalloc(Bufsize, CACHELINESZ, 0);
  158. b->buf[i].phys = PADDR(b->buf[i].virt);
  159. }
  160. b->bufinit = 1;
  161. };
  162. static void
  163. setempty(IOstate *b)
  164. {
  165. int i;
  166. if (debug) print("setempty\n");
  167. for (i = 0; i < Nbuf; i++) {
  168. b->buf[i].nbytes = 0;
  169. }
  170. b->filling = b->buf;
  171. b->current = b->buf;
  172. b->next = b->buf;
  173. }
  174. static int
  175. audioqnotempty(void *x)
  176. {
  177. IOstate *s = x;
  178. return dmaidle(s->dma) || s->emptying != s->current;
  179. }
  180. static int
  181. audioqnotfull(void *x)
  182. {
  183. IOstate *s = x;
  184. return dmaidle(s->dma) || s->filling != s->current;
  185. }
  186. static void
  187. audioreset(void)
  188. {
  189. /* Turn MCP operations off */
  190. MCPREG->mccr = 0;
  191. }
  192. uchar status0[1] = {0x22};
  193. uchar status1[1] = {0x80};
  194. uchar data00[1] = {0x00}; /* volume control, bits 0 – 5 */
  195. uchar data01[1] = {0x40};
  196. uchar data02[1] = {0x80};
  197. uchar data0e0[2] = {0xc0, 0xe0};
  198. uchar data0e1[2] = {0xc1, 0xe0};
  199. uchar data0e2[2] = {0xc2, 0xf2};
  200. /* there is no data0e3 */
  201. uchar data0e4[2] = {0xc4, 0xe0};
  202. uchar data0e5[2] = {0xc5, 0xe0};
  203. uchar data0e6[2] = {0xc6, 0xe3};
  204. static void
  205. enable(void)
  206. {
  207. uchar data[1];
  208. int cs;
  209. L3init();
  210. PPCREG->ppar &= ~PPAR_SPR;
  211. /* external clock and ssp configured for current samples/sec */
  212. cs = archaudiospeed(audio.livol[Vspeed], 1);
  213. status0[0] = (status0[0] & ~(3<<4)) | (cs<<4);
  214. /* Enable the audio power */
  215. archaudiopower(1);
  216. // egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 1);
  217. /* Wait for the UDA1341 to wake up */
  218. delay(100);
  219. /* Reset the chip */
  220. data[0] = status0[0] | 1<<UdaStatusRST;
  221. L3write(UDA1341_L3Addr | UDA1341_STATUS, data, 1 );
  222. archcodecreset();
  223. /* write uda 1341 status[0] */
  224. L3write(UDA1341_L3Addr | UDA1341_STATUS, status0, 1 );
  225. L3write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  226. L3write(UDA1341_L3Addr | UDA1341_DATA0, data02, 1);
  227. L3write(UDA1341_L3Addr | UDA1341_DATA0, data0e2, 2);
  228. L3write(UDA1341_L3Addr | UDA1341_DATA0, data0e6, 2 );
  229. if (debug) {
  230. print("enable: status0 = 0x%2.2ux\n", status0[0]);
  231. print("enable: status1 = 0x%2.2ux\n", status1[0]);
  232. print("enable: data02 = 0x%2.2ux\n", data02[0]);
  233. print("enable: data0e2 = 0x%4.4ux\n", data0e2[0] | data0e2[1]<<8);
  234. print("enable: data0e4 = 0x%4.4ux\n", data0e4[0] | data0e4[1]<<8);
  235. print("enable: data0e6 = 0x%4.4ux\n", data0e6[0] | data0e6[1]<<8);
  236. }
  237. }
  238. static void
  239. disable(void)
  240. {
  241. SSPREG->sscr0 = 0x031f; /* disable */
  242. }
  243. static void
  244. resetlevel(void)
  245. {
  246. int i;
  247. for(i=0; volumes[i].name; i++) {
  248. audio.lovol[i] = volumes[i].ilval;
  249. audio.rovol[i] = volumes[i].irval;
  250. audio.livol[i] = volumes[i].ilval;
  251. audio.rivol[i] = volumes[i].irval;
  252. }
  253. }
  254. static void
  255. mxvolume(void) {
  256. int *left, *right;
  257. int cs;
  258. cs = archaudiospeed(audio.livol[Vspeed], 1);
  259. status0[0] = (status0[0] & ~(3<<4)) | (cs<<4);
  260. L3write(UDA1341_L3Addr | UDA1341_STATUS, status0, 1);
  261. if(debug)
  262. print("mxvolume: status0 = %2.2ux\n", status0[0]);
  263. if(audio.amode & Aread){
  264. left = audio.livol;
  265. right = audio.rivol;
  266. if (left[Vmic]+right[Vmic] == 0) {
  267. /* Turn on automatic gain control (AGC) */
  268. data0e4[1] |= 0x10;
  269. L3write(UDA1341_L3Addr | UDA1341_DATA0, data0e4, 2 );
  270. } else {
  271. int v;
  272. /* Turn on manual gain control */
  273. v = ((left[Vmic]+right[Vmic])*0x7f/200)&0x7f;
  274. data0e4[1] &= ~0x13;
  275. data0e5[1] &= ~0x1f;
  276. data0e4[1] |= v & 0x3;
  277. data0e5[0] |= (v & 0x7c)<<6;
  278. data0e5[1] |= (v & 0x7c)>>2;
  279. L3write(UDA1341_L3Addr | UDA1341_DATA0, data0e4, 2 );
  280. L3write(UDA1341_L3Addr | UDA1341_DATA0, data0e5, 2 );
  281. }
  282. if (left[Vinvert]+right[Vinvert] == 0)
  283. status1[0] &= ~0x10;
  284. else
  285. status1[0] |= 0x10;
  286. L3write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  287. if (debug) {
  288. print("mxvolume: status1 = 0x%2.2ux\n", status1[0]);
  289. print("mxvolume: data0e4 = 0x%4.4ux\n", data0e4[0]|data0e4[0]<<8);
  290. print("mxvolume: data0e5 = 0x%4.4ux\n", data0e5[0]|data0e5[0]<<8);
  291. }
  292. }
  293. if(audio.amode & Awrite){
  294. left = audio.lovol;
  295. right = audio.rovol;
  296. data00[0] &= ~0x3f;
  297. data00[0] |= ((200-left[Vaudio]-right[Vaudio])*0x3f/200)&0x3f;
  298. if (left[Vtreb]+right[Vtreb] <= 100
  299. && left[Vbass]+right[Vbass] <= 100)
  300. /* settings neutral */
  301. data02[0] &= ~0x03;
  302. else {
  303. data02[0] |= 0x03;
  304. data01[0] &= ~0x3f;
  305. data01[0] |= ((left[Vtreb]+right[Vtreb]-100)*0x3/100)&0x03;
  306. data01[0] |= (((left[Vbass]+right[Vbass]-100)*0xf/100)&0xf)<<2;
  307. }
  308. if (left[Vfilter]+right[Vfilter] == 0)
  309. data02[0] &= ~0x10;
  310. else
  311. data02[0]|= 0x10;
  312. if (left[Vinvert]+right[Vinvert] == 0)
  313. status1[0] &= ~0x8;
  314. else
  315. status1[0] |= 0x8;
  316. L3write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  317. L3write(UDA1341_L3Addr | UDA1341_DATA0, data00, 1);
  318. L3write(UDA1341_L3Addr | UDA1341_DATA0, data01, 1);
  319. L3write(UDA1341_L3Addr | UDA1341_DATA0, data02, 1);
  320. if (debug) {
  321. print("mxvolume: status1 = 0x%2.2ux\n", status1[0]);
  322. print("mxvolume: data00 = 0x%2.2ux\n", data00[0]);
  323. print("mxvolume: data01 = 0x%2.2ux\n", data01[0]);
  324. print("mxvolume: data02 = 0x%2.2ux\n", data02[0]);
  325. }
  326. }
  327. }
  328. static void
  329. setreg(char *name, int val, int n)
  330. {
  331. uchar x[2];
  332. int i;
  333. if(strcmp(name, "pause") == 0){
  334. for(i = 0; i < n; i++)
  335. microdelay(val);
  336. return;
  337. }
  338. x[0] = val;
  339. x[1] = val>>8;
  340. switch(n){
  341. case 1:
  342. case 2:
  343. break;
  344. default:
  345. error("setreg");
  346. }
  347. if(strcmp(name, "status") == 0){
  348. L3write(UDA1341_L3Addr | UDA1341_STATUS, x, n);
  349. } else if(strcmp(name, "data0") == 0){
  350. L3write(UDA1341_L3Addr | UDA1341_DATA0, x, n);
  351. } else if(strcmp(name, "data1") == 0){
  352. L3write(UDA1341_L3Addr | UDA1341_DATA1, x, n);
  353. } else
  354. error("setreg");
  355. }
  356. static void
  357. outenable(void) {
  358. /* turn on DAC, set output gain switch */
  359. archaudioamp(1);
  360. archaudiomute(0);
  361. status1[0] |= 0x41;
  362. L3write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  363. /* set volume */
  364. data00[0] |= 0xf;
  365. L3write(UDA1341_L3Addr | UDA1341_DATA0, data00, 1);
  366. if (debug) {
  367. print("outenable: status1 = 0x%2.2ux\n", status1[0]);
  368. print("outenable: data00 = 0x%2.2ux\n", data00[0]);
  369. }
  370. }
  371. static void
  372. outdisable(void) {
  373. archaudiomute(1);
  374. dmastop(audio.o.dma);
  375. /* turn off DAC, clear output gain switch */
  376. archaudioamp(0);
  377. status1[0] &= ~0x41;
  378. L3write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  379. if (debug) {
  380. print("outdisable: status1 = 0x%2.2ux\n", status1[0]);
  381. }
  382. // egpiobits(EGPIO_audio_power, 0);
  383. }
  384. static void
  385. inenable(void) {
  386. /* turn on ADC, set input gain switch */
  387. status1[0] |= 0x22;
  388. L3write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  389. if (debug) {
  390. print("inenable: status1 = 0x%2.2ux\n", status1[0]);
  391. }
  392. }
  393. static void
  394. indisable(void) {
  395. dmastop(audio.i.dma);
  396. /* turn off ADC, clear input gain switch */
  397. status1[0] &= ~0x22;
  398. L3write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
  399. if (debug) {
  400. print("indisable: status1 = 0x%2.2ux\n", status1[0]);
  401. }
  402. }
  403. static void
  404. sendaudio(IOstate *s) {
  405. /* interrupt routine calls this too */
  406. int n;
  407. if (debug > 1) print("#A: sendaudio\n");
  408. ilock(&s->ilock);
  409. while (s->next != s->filling) {
  410. assert(s->next->nbytes);
  411. if ((n = dmastart(s->dma, (void*)s->next->phys, s->next->nbytes)) == 0) {
  412. iostats.faildma++;
  413. break;
  414. }
  415. iostats.totaldma++;
  416. switch (n) {
  417. case 1:
  418. iostats.idledma++;
  419. break;
  420. case 3:
  421. iostats.faildma++;
  422. break;
  423. }
  424. if (debug) {
  425. if (debug > 1)
  426. print("dmastart @%p\n", s->next);
  427. else
  428. iprint("+");
  429. }
  430. s->next->nbytes = 0;
  431. s->next++;
  432. if (s->next == &s->buf[Nbuf])
  433. s->next = &s->buf[0];
  434. }
  435. iunlock(&s->ilock);
  436. }
  437. static void
  438. recvaudio(IOstate *s) {
  439. /* interrupt routine calls this too */
  440. int n;
  441. if (debug > 1) print("#A: recvaudio\n");
  442. ilock(&s->ilock);
  443. while (s->next != s->emptying) {
  444. assert(s->next->nbytes == 0);
  445. if ((n = dmastart(s->dma, (void*)s->next->phys, Bufsize)) == 0) {
  446. iostats.faildma++;
  447. break;
  448. }
  449. iostats.totaldma++;
  450. switch (n) {
  451. case 1:
  452. iostats.idledma++;
  453. break;
  454. case 3:
  455. iostats.faildma++;
  456. break;
  457. }
  458. if (debug) {
  459. if (debug > 1)
  460. print("dmastart @%p\n", s->next);
  461. else
  462. iprint("+");
  463. }
  464. s->next++;
  465. if (s->next == &s->buf[Nbuf])
  466. s->next = &s->buf[0];
  467. }
  468. iunlock(&s->ilock);
  469. }
  470. static void
  471. audiopower(int flag) {
  472. IOstate *s;
  473. if (debug) {
  474. iprint("audiopower %d\n", flag);
  475. }
  476. if (flag) {
  477. /* power on only when necessary */
  478. if (audio.amode) {
  479. archaudiopower(1);
  480. enable();
  481. if (audio.amode & Aread) {
  482. inenable();
  483. s = &audio.i;
  484. dmastop(s->dma);
  485. recvaudio(s);
  486. }
  487. if (audio.amode & Awrite) {
  488. outenable();
  489. s = &audio.o;
  490. dmastop(s->dma);
  491. sendaudio(s);
  492. }
  493. mxvolume();
  494. }
  495. } else {
  496. /* power off */
  497. if (audio.amode & Aread)
  498. indisable();
  499. if (audio.amode & Awrite)
  500. outdisable();
  501. disable();
  502. archaudiopower(0);
  503. }
  504. }
  505. static void
  506. audiointr(void *x, ulong ndma) {
  507. IOstate *s = x;
  508. if (debug) {
  509. if (debug > 1)
  510. iprint("#A: audio interrupt @%p\n", s->current);
  511. else
  512. iprint("-");
  513. }
  514. /* Only interrupt routine touches s->current */
  515. s->current++;
  516. if (s->current == &s->buf[Nbuf])
  517. s->current = &s->buf[0];
  518. if (ndma > 0) {
  519. if (s == &audio.o)
  520. sendaudio(s);
  521. else if (s == &audio.i)
  522. recvaudio(s);
  523. }
  524. wakeup(&s->vous);
  525. }
  526. static void
  527. audioinit(void)
  528. {
  529. audio.amode = Aclosed;
  530. resetlevel();
  531. // powerenable(audiopower);
  532. }
  533. static Chan*
  534. audioattach(char *param)
  535. {
  536. return devattach('A', param);
  537. }
  538. static Walkqid*
  539. audiowalk(Chan *c, Chan *nc, char **name, int nname)
  540. {
  541. return devwalk(c, nc, name, nname, audiodir, nelem(audiodir), devgen);
  542. }
  543. static int
  544. audiostat(Chan *c, uchar *db, int n)
  545. {
  546. return devstat(c, db, n, audiodir, nelem(audiodir), devgen);
  547. }
  548. static Chan*
  549. audioopen(Chan *c, int mode)
  550. {
  551. IOstate *s;
  552. int omode = mode;
  553. switch((ulong)c->qid.path) {
  554. default:
  555. error(Eperm);
  556. break;
  557. case Qstatus:
  558. if((omode&7) != OREAD)
  559. error(Eperm);
  560. case Qvolume:
  561. case Qaudioctl:
  562. case Qdir:
  563. break;
  564. case Qaudio:
  565. omode = (omode & 0x7) + 1;
  566. if (omode & ~(Aread | Awrite))
  567. error(Ebadarg);
  568. qlock(&audio);
  569. if(audio.amode & omode){
  570. qunlock(&audio);
  571. error(Einuse);
  572. }
  573. enable();
  574. memset(&iostats, 0, sizeof(iostats));
  575. if (omode & Aread) {
  576. inenable();
  577. s = &audio.i;
  578. if(s->bufinit == 0)
  579. bufinit(s);
  580. setempty(s);
  581. s->emptying = &s->buf[Nbuf-1];
  582. s->chan = c;
  583. s->dma = dmasetup(DmaSSP, 1, 0, audiointr, (void*)s);
  584. audio.amode |= Aread;
  585. audio.clockout = 1;
  586. }
  587. if (omode & Awrite) {
  588. outenable();
  589. s = &audio.o;
  590. audio.amode |= Awrite;
  591. if(s->bufinit == 0)
  592. bufinit(s);
  593. setempty(s);
  594. s->chan = c;
  595. s->dma = dmasetup(DmaSSP, 0, 0, audiointr, (void*)s);
  596. audio.amode |= Awrite;
  597. }
  598. mxvolume();
  599. qunlock(&audio);
  600. if (debug) print("open done\n");
  601. break;
  602. }
  603. c = devopen(c, mode, audiodir, nelem(audiodir), devgen);
  604. c->mode = openmode(mode);
  605. c->flag |= COPEN;
  606. c->offset = 0;
  607. return c;
  608. }
  609. static void
  610. audioclose(Chan *c)
  611. {
  612. IOstate *s;
  613. switch((ulong)c->qid.path) {
  614. default:
  615. error(Eperm);
  616. break;
  617. case Qdir:
  618. case Qvolume:
  619. case Qaudioctl:
  620. case Qstatus:
  621. break;
  622. case Qaudio:
  623. if (debug > 1) print("#A: close\n");
  624. if(c->flag & COPEN) {
  625. qlock(&audio);
  626. if(waserror()){
  627. qunlock(&audio);
  628. nexterror();
  629. }
  630. if (audio.o.chan == c) {
  631. /* closing the write end */
  632. audio.amode &= ~Awrite;
  633. s = &audio.o;
  634. qlock(s);
  635. if(waserror()){
  636. qunlock(s);
  637. nexterror();
  638. }
  639. if (s->filling->nbytes) {
  640. /* send remaining partial buffer */
  641. s->filling++;
  642. if (s->filling == &s->buf[Nbuf])
  643. s->filling = &s->buf[0];
  644. sendaudio(s);
  645. }
  646. dmawait(s->dma);
  647. outdisable();
  648. setempty(s);
  649. dmafree(s->dma);
  650. qunlock(s);
  651. poperror();
  652. }
  653. if (audio.i.chan == c) {
  654. /* closing the read end */
  655. audio.amode &= ~Aread;
  656. s = &audio.i;
  657. qlock(s);
  658. if(waserror()){
  659. qunlock(s);
  660. nexterror();
  661. }
  662. indisable();
  663. setempty(s);
  664. dmafree(s->dma);
  665. qunlock(s);
  666. poperror();
  667. }
  668. if (audio.amode == 0) {
  669. /* turn audio off */
  670. archaudiopower(0);
  671. }
  672. qunlock(&audio);
  673. poperror();
  674. if (debug) {
  675. print("total dmas: %lud\n", iostats.totaldma);
  676. print("dmas while idle: %lud\n", iostats.idledma);
  677. print("dmas while busy: %lud\n", iostats.faildma);
  678. print("out of order dma: %lud\n", iostats.samedma);
  679. }
  680. }
  681. break;
  682. }
  683. }
  684. static long
  685. audioread(Chan *c, void *v, long n, vlong off)
  686. {
  687. int liv, riv, lov, rov;
  688. long m, n0;
  689. char buf[300];
  690. int j;
  691. ulong offset = off;
  692. char *p;
  693. IOstate *s;
  694. n0 = n;
  695. p = v;
  696. switch((ulong)c->qid.path) {
  697. default:
  698. error(Eperm);
  699. break;
  700. case Qdir:
  701. return devdirread(c, p, n, audiodir, nelem(audiodir), devgen);
  702. case Qaudio:
  703. if (debug > 1) print("#A: read %ld\n", n);
  704. if((audio.amode & Aread) == 0)
  705. error(Emode);
  706. s = &audio.i;
  707. qlock(s);
  708. if(waserror()){
  709. qunlock(s);
  710. nexterror();
  711. }
  712. while(n > 0) {
  713. if(s->emptying->nbytes == 0) {
  714. if (debug > 1) print("#A: emptied @%p\n", s->emptying);
  715. recvaudio(s);
  716. s->emptying++;
  717. if (s->emptying == &s->buf[Nbuf])
  718. s->emptying = s->buf;
  719. }
  720. /* wait if dma in progress */
  721. while (!dmaidle(s->dma) && s->emptying == s->current) {
  722. if (debug > 1) print("#A: sleep\n");
  723. sleep(&s->vous, audioqnotempty, s);
  724. }
  725. m = Bufsize - s->emptying->nbytes;
  726. if(m > n)
  727. m = n;
  728. memmove(p, s->emptying->virt + s->emptying->nbytes, m);
  729. s->emptying->nbytes -= m;
  730. n -= m;
  731. p += m;
  732. }
  733. poperror();
  734. qunlock(s);
  735. break;
  736. break;
  737. case Qstatus:
  738. buf[0] = 0;
  739. snprint(buf, sizeof(buf), "bytes %llud\ntime %lld\n",
  740. audio.totcount, audio.tottime);
  741. return readstr(offset, p, n, buf);
  742. case Qvolume:
  743. case Qaudioctl:
  744. j = 0;
  745. buf[0] = 0;
  746. for(m=0; volumes[m].name; m++){
  747. liv = audio.livol[m];
  748. riv = audio.rivol[m];
  749. lov = audio.lovol[m];
  750. rov = audio.rovol[m];
  751. j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name);
  752. if((volumes[m].flag & Fmono) || liv==riv && lov==rov){
  753. if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov)
  754. j += snprint(buf+j, sizeof(buf)-j, " %d", liv);
  755. else{
  756. if(volumes[m].flag & Fin)
  757. j += snprint(buf+j, sizeof(buf)-j,
  758. " in %d", liv);
  759. if(volumes[m].flag & Fout)
  760. j += snprint(buf+j, sizeof(buf)-j,
  761. " out %d", lov);
  762. }
  763. }else{
  764. if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) &&
  765. liv==lov && riv==rov)
  766. j += snprint(buf+j, sizeof(buf)-j,
  767. " left %d right %d",
  768. liv, riv);
  769. else{
  770. if(volumes[m].flag & Fin)
  771. j += snprint(buf+j, sizeof(buf)-j,
  772. " in left %d right %d",
  773. liv, riv);
  774. if(volumes[m].flag & Fout)
  775. j += snprint(buf+j, sizeof(buf)-j,
  776. " out left %d right %d",
  777. lov, rov);
  778. }
  779. }
  780. j += snprint(buf+j, sizeof(buf)-j, "\n");
  781. }
  782. return readstr(offset, p, n, buf);
  783. }
  784. return n0-n;
  785. }
  786. static long
  787. audiowrite(Chan *c, void *vp, long n, vlong)
  788. {
  789. long m, n0;
  790. int i, nf, v, left, right, in, out;
  791. char buf[255], *field[Ncmd];
  792. char *p;
  793. IOstate *a;
  794. p = vp;
  795. n0 = n;
  796. switch((ulong)c->qid.path) {
  797. default:
  798. error(Eperm);
  799. break;
  800. case Qvolume:
  801. case Qaudioctl:
  802. v = Vaudio;
  803. left = 1;
  804. right = 1;
  805. in = 1;
  806. out = 1;
  807. if(n > sizeof(buf)-1)
  808. n = sizeof(buf)-1;
  809. memmove(buf, p, n);
  810. buf[n] = '\0';
  811. n = 0;
  812. nf = getfields(buf, field, Ncmd, 1, " \t\n");
  813. for(i = 0; i < nf; i++){
  814. /*
  815. * a number is volume
  816. */
  817. if(field[i][0] >= '0' && field[i][0] <= '9') {
  818. m = strtoul(field[i], 0, 10);
  819. if(v == Vspeed){
  820. if(archaudiospeed(m, 0) < 0)
  821. error(Evolume);
  822. }else
  823. if(m < 0 || m > 100)
  824. error(Evolume);
  825. if(left && out)
  826. audio.lovol[v] = m;
  827. if(left && in)
  828. audio.livol[v] = m;
  829. if(right && out)
  830. audio.rovol[v] = m;
  831. if(right && in)
  832. audio.rivol[v] = m;
  833. goto cont0;
  834. }
  835. if(strcmp(field[i], "rate") == 0)
  836. field[i] = "speed"; /* honestly ... */
  837. for(m=0; volumes[m].name; m++) {
  838. if(strcmp(field[i], volumes[m].name) == 0) {
  839. v = m;
  840. in = 1;
  841. out = 1;
  842. left = 1;
  843. right = 1;
  844. goto cont0;
  845. }
  846. }
  847. if(strcmp(field[i], "enc") == 0) {
  848. if(++i >= nf)
  849. error(Evolume);
  850. if(strcmp(field[i], "pcm") != 0)
  851. error(Evolume);
  852. goto cont0;
  853. }
  854. if(strcmp(field[i], "bits") == 0) {
  855. if(++i >= nf)
  856. error(Evolume);
  857. if(strtol(field[i], 0, 0) != 16)
  858. error(Evolume);
  859. goto cont0;
  860. }
  861. if(strcmp(field[i], "chans") == 0) {
  862. if(++i >= nf)
  863. error(Evolume);
  864. if(strtol(field[i], 0, 0) != 2)
  865. error(Evolume);
  866. goto cont0;
  867. }
  868. if(strcmp(field[i], "reset") == 0) {
  869. resetlevel();
  870. goto cont0;
  871. }
  872. if(strcmp(field[i], "debug") == 0) {
  873. debug = debug?0:1;
  874. goto cont0;
  875. }
  876. if(strcmp(field[i], "in") == 0) {
  877. in = 1;
  878. out = 0;
  879. goto cont0;
  880. }
  881. if(strcmp(field[i], "out") == 0) {
  882. in = 0;
  883. out = 1;
  884. goto cont0;
  885. }
  886. if(strcmp(field[i], "left") == 0) {
  887. left = 1;
  888. right = 0;
  889. goto cont0;
  890. }
  891. if(strcmp(field[i], "right") == 0) {
  892. left = 0;
  893. right = 1;
  894. goto cont0;
  895. }
  896. if(strcmp(field[i], "reg") == 0) {
  897. if(nf < 3)
  898. error(Evolume);
  899. setreg(field[1], atoi(field[2]), nf == 4 ? atoi(field[3]):1);
  900. return n0;
  901. }
  902. error(Evolume);
  903. break;
  904. cont0:;
  905. }
  906. mxvolume();
  907. break;
  908. case Qaudio:
  909. if (debug > 1) print("#A: write %ld\n", n);
  910. if((audio.amode & Awrite) == 0)
  911. error(Emode);
  912. a = &audio.o;
  913. qlock(a);
  914. if(waserror()){
  915. qunlock(a);
  916. nexterror();
  917. }
  918. while(n > 0) {
  919. /* wait if dma in progress */
  920. while (!dmaidle(a->dma) && a->filling == a->current) {
  921. if (debug > 1) print("#A: sleep\n");
  922. sleep(&a->vous, audioqnotfull, a);
  923. }
  924. m = Bufsize - a->filling->nbytes;
  925. if(m > n)
  926. m = n;
  927. memmove(a->filling->virt + a->filling->nbytes, p, m);
  928. a->filling->nbytes += m;
  929. n -= m;
  930. p += m;
  931. if(a->filling->nbytes >= Bufsize) {
  932. if (debug > 1) print("#A: filled @%p\n", a->filling);
  933. a->filling++;
  934. if (a->filling == &a->buf[Nbuf])
  935. a->filling = a->buf;
  936. sendaudio(a);
  937. }
  938. }
  939. poperror();
  940. qunlock(a);
  941. break;
  942. }
  943. return n0 - n;
  944. }
  945. Dev audiodevtab = {
  946. 'A',
  947. "audio",
  948. audioreset,
  949. audioinit,
  950. devshutdown,
  951. audioattach,
  952. audiowalk,
  953. audiostat,
  954. audioopen,
  955. devcreate,
  956. audioclose,
  957. audioread,
  958. devbread,
  959. audiowrite,
  960. devbwrite,
  961. devremove,
  962. devwstat,
  963. audiopower,
  964. };