cs4231.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606
  1. /* $OpenBSD: cs4231.c,v 1.35 2015/05/11 06:52:35 ratchov Exp $ */
  2. /*
  3. * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  19. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  23. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  24. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. *
  27. * Effort sponsored in part by the Defense Advanced Research Projects
  28. * Agency (DARPA) and Air Force Research Laboratory, Air Force
  29. * Materiel Command, USAF, under agreement number F30602-01-2-0537.
  30. *
  31. */
  32. /*
  33. * Driver for CS4231 based audio found in some sun4m systems (cs4231)
  34. * based on ideas from the S/Linux project and the NetBSD project.
  35. */
  36. #include <sys/param.h>
  37. #include <sys/systm.h>
  38. #include <sys/errno.h>
  39. #include <sys/ioctl.h>
  40. #include <sys/device.h>
  41. #include <sys/proc.h>
  42. #include <sys/malloc.h>
  43. #include <machine/bus.h>
  44. #include <machine/intr.h>
  45. #include <machine/autoconf.h>
  46. #include <sys/audioio.h>
  47. #include <dev/audio_if.h>
  48. #include <dev/ic/ad1848reg.h>
  49. #include <dev/ic/cs4231reg.h>
  50. #include <dev/ic/apcdmareg.h>
  51. #include <dev/sbus/sbusvar.h>
  52. #include <dev/sbus/cs4231var.h>
  53. #define CSAUDIO_DAC_LVL 0
  54. #define CSAUDIO_LINE_IN_LVL 1
  55. #define CSAUDIO_MIC_LVL 2
  56. #define CSAUDIO_CD_LVL 3
  57. #define CSAUDIO_MONITOR_LVL 4
  58. #define CSAUDIO_OUTPUT_LVL 5
  59. #define CSAUDIO_LINE_IN_MUTE 6
  60. #define CSAUDIO_DAC_MUTE 7
  61. #define CSAUDIO_CD_MUTE 8
  62. #define CSAUDIO_MIC_MUTE 9
  63. #define CSAUDIO_MONITOR_MUTE 10
  64. #define CSAUDIO_OUTPUT_MUTE 11
  65. #define CSAUDIO_REC_LVL 12
  66. #define CSAUDIO_RECORD_SOURCE 13
  67. #define CSAUDIO_OUTPUT 14
  68. #define CSAUDIO_INPUT_CLASS 15
  69. #define CSAUDIO_OUTPUT_CLASS 16
  70. #define CSAUDIO_RECORD_CLASS 17
  71. #define CSAUDIO_MONITOR_CLASS 18
  72. #define CSPORT_AUX2 0
  73. #define CSPORT_AUX1 1
  74. #define CSPORT_DAC 2
  75. #define CSPORT_LINEIN 3
  76. #define CSPORT_MONO 4
  77. #define CSPORT_MONITOR 5
  78. #define CSPORT_SPEAKER 6
  79. #define CSPORT_LINEOUT 7
  80. #define CSPORT_HEADPHONE 8
  81. #define CSPORT_MICROPHONE 9
  82. #define MIC_IN_PORT 0
  83. #define LINE_IN_PORT 1
  84. #define AUX1_IN_PORT 2
  85. #define DAC_IN_PORT 3
  86. #ifdef AUDIO_DEBUG
  87. #define DPRINTF(x) printf x
  88. #else
  89. #define DPRINTF(x)
  90. #endif
  91. #define CS_TIMEOUT 90000
  92. #define CS_PC_LINEMUTE XCTL0_ENABLE
  93. #define CS_PC_HDPHMUTE XCTL1_ENABLE
  94. #define CS_AFS_TI 0x40 /* timer interrupt */
  95. #define CS_AFS_CI 0x20 /* capture interrupt */
  96. #define CS_AFS_PI 0x10 /* playback interrupt */
  97. #define CS_AFS_CU 0x08 /* capture underrun */
  98. #define CS_AFS_CO 0x04 /* capture overrun */
  99. #define CS_AFS_PO 0x02 /* playback overrun */
  100. #define CS_AFS_PU 0x01 /* playback underrun */
  101. #define CS_WRITE(sc,r,v) \
  102. bus_space_write_1((sc)->sc_bustag, (sc)->sc_regs, (r) << 2, (v))
  103. #define CS_READ(sc,r) \
  104. bus_space_read_1((sc)->sc_bustag, (sc)->sc_regs, (r) << 2)
  105. #define APC_WRITE(sc,r,v) \
  106. bus_space_write_4(sc->sc_bustag, sc->sc_regs, r, v)
  107. #define APC_READ(sc,r) \
  108. bus_space_read_4(sc->sc_bustag, sc->sc_regs, r)
  109. int cs4231_match(struct device *, void *, void *);
  110. void cs4231_attach(struct device *, struct device *, void *);
  111. int cs4231_intr(void *);
  112. int cs4231_set_speed(struct cs4231_softc *, u_long *);
  113. void cs4231_setup_output(struct cs4231_softc *sc);
  114. void cs4231_write(struct cs4231_softc *, u_int8_t, u_int8_t);
  115. u_int8_t cs4231_read(struct cs4231_softc *, u_int8_t);
  116. /* Audio interface */
  117. int cs4231_open(void *, int);
  118. void cs4231_close(void *);
  119. int cs4231_query_encoding(void *, struct audio_encoding *);
  120. int cs4231_set_params(void *, int, int, struct audio_params *,
  121. struct audio_params *);
  122. int cs4231_round_blocksize(void *, int);
  123. int cs4231_commit_settings(void *);
  124. int cs4231_halt_output(void *);
  125. int cs4231_halt_input(void *);
  126. int cs4231_getdev(void *, struct audio_device *);
  127. int cs4231_set_port(void *, mixer_ctrl_t *);
  128. int cs4231_get_port(void *, mixer_ctrl_t *);
  129. int cs4231_query_devinfo(void *, mixer_devinfo_t *);
  130. void * cs4231_alloc(void *, int, size_t, int, int);
  131. void cs4231_free(void *, void *, int);
  132. int cs4231_get_props(void *);
  133. int cs4231_trigger_output(void *, void *, void *, int,
  134. void (*)(void *), void *, struct audio_params *);
  135. int cs4231_trigger_input(void *, void *, void *, int,
  136. void (*)(void *), void *, struct audio_params *);
  137. struct audio_hw_if cs4231_sa_hw_if = {
  138. cs4231_open,
  139. cs4231_close,
  140. 0,
  141. cs4231_query_encoding,
  142. cs4231_set_params,
  143. cs4231_round_blocksize,
  144. cs4231_commit_settings,
  145. 0,
  146. 0,
  147. 0,
  148. 0,
  149. cs4231_halt_output,
  150. cs4231_halt_input,
  151. 0,
  152. cs4231_getdev,
  153. 0,
  154. cs4231_set_port,
  155. cs4231_get_port,
  156. cs4231_query_devinfo,
  157. cs4231_alloc,
  158. cs4231_free,
  159. 0,
  160. 0,
  161. cs4231_get_props,
  162. cs4231_trigger_output,
  163. cs4231_trigger_input,
  164. 0
  165. };
  166. struct cfattach audiocs_ca = {
  167. sizeof (struct cs4231_softc), cs4231_match, cs4231_attach
  168. };
  169. struct cfdriver audiocs_cd = {
  170. NULL, "audiocs", DV_DULL
  171. };
  172. struct audio_device cs4231_device = {
  173. "SUNW,CS4231",
  174. "b",
  175. "onboard1",
  176. };
  177. int
  178. cs4231_match(struct device *parent, void *vcf, void *aux)
  179. {
  180. struct sbus_attach_args *sa = aux;
  181. return (strcmp("SUNW,CS4231", sa->sa_name) == 0);
  182. }
  183. void
  184. cs4231_attach(struct device *parent, struct device *self, void *aux)
  185. {
  186. struct sbus_attach_args *sa = aux;
  187. struct cs4231_softc *sc = (struct cs4231_softc *)self;
  188. int node;
  189. u_int32_t sbusburst, burst;
  190. node = sa->sa_node;
  191. /* Pass on the bus tags */
  192. sc->sc_bustag = sa->sa_bustag;
  193. sc->sc_dmatag = sa->sa_dmatag;
  194. /* Make sure things are sane. */
  195. if (sa->sa_nintr != 1) {
  196. printf(": expected 1 interrupt, got %d\n", sa->sa_nintr);
  197. return;
  198. }
  199. if (sa->sa_nreg != 1) {
  200. printf(": expected 1 register set, got %d\n",
  201. sa->sa_nreg);
  202. return;
  203. }
  204. if (bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_AUDIO, 0,
  205. cs4231_intr, sc, self->dv_xname) == NULL) {
  206. printf(": couldn't establish interrupt, pri %d\n",
  207. INTLEV(sa->sa_pri));
  208. return;
  209. }
  210. if (sbus_bus_map(sa->sa_bustag,
  211. sa->sa_reg[0].sbr_slot,
  212. (bus_addr_t)sa->sa_reg[0].sbr_offset,
  213. (bus_size_t)sa->sa_reg[0].sbr_size,
  214. BUS_SPACE_MAP_LINEAR, 0, &sc->sc_regs) != 0) {
  215. printf(": couldn't map registers\n");
  216. return;
  217. }
  218. sbusburst = ((struct sbus_softc *)parent)->sc_burst;
  219. if (sbusburst == 0)
  220. sbusburst = SBUS_BURST_32 - 1; /* 1->16 */
  221. burst = getpropint(node, "burst-sizes", -1);
  222. if (burst == -1)
  223. burst = sbusburst;
  224. sc->sc_burst = burst & sbusburst;
  225. printf("\n");
  226. audio_attach_mi(&cs4231_sa_hw_if, sc, &sc->sc_dev);
  227. /* Default to speaker, unmuted, reasonable volume */
  228. sc->sc_out_port = CSPORT_SPEAKER;
  229. sc->sc_in_port = CSPORT_MICROPHONE;
  230. sc->sc_mute[CSPORT_SPEAKER] = 1;
  231. sc->sc_mute[CSPORT_MONITOR] = 1;
  232. sc->sc_volume[CSPORT_SPEAKER].left = 192;
  233. sc->sc_volume[CSPORT_SPEAKER].right = 192;
  234. }
  235. /*
  236. * Write to one of the indexed registers of cs4231.
  237. */
  238. void
  239. cs4231_write(struct cs4231_softc *sc, u_int8_t r, u_int8_t v)
  240. {
  241. CS_WRITE(sc, AD1848_IADDR, r);
  242. CS_WRITE(sc, AD1848_IDATA, v);
  243. }
  244. /*
  245. * Read from one of the indexed registers of cs4231.
  246. */
  247. u_int8_t
  248. cs4231_read(struct cs4231_softc *sc, u_int8_t r)
  249. {
  250. CS_WRITE(sc, AD1848_IADDR, r);
  251. return (CS_READ(sc, AD1848_IDATA));
  252. }
  253. int
  254. cs4231_set_speed(struct cs4231_softc *sc, u_long *argp)
  255. {
  256. /*
  257. * The available speeds are in the following table. Keep the speeds in
  258. * the increasing order.
  259. */
  260. typedef struct {
  261. int speed;
  262. u_char bits;
  263. } speed_struct;
  264. u_long arg = *argp;
  265. const static speed_struct speed_table[] = {
  266. {5510, (0 << 1) | CLOCK_XTAL2},
  267. {5510, (0 << 1) | CLOCK_XTAL2},
  268. {6620, (7 << 1) | CLOCK_XTAL2},
  269. {8000, (0 << 1) | CLOCK_XTAL1},
  270. {9600, (7 << 1) | CLOCK_XTAL1},
  271. {11025, (1 << 1) | CLOCK_XTAL2},
  272. {16000, (1 << 1) | CLOCK_XTAL1},
  273. {18900, (2 << 1) | CLOCK_XTAL2},
  274. {22050, (3 << 1) | CLOCK_XTAL2},
  275. {27420, (2 << 1) | CLOCK_XTAL1},
  276. {32000, (3 << 1) | CLOCK_XTAL1},
  277. {33075, (6 << 1) | CLOCK_XTAL2},
  278. {33075, (4 << 1) | CLOCK_XTAL2},
  279. {44100, (5 << 1) | CLOCK_XTAL2},
  280. {48000, (6 << 1) | CLOCK_XTAL1},
  281. };
  282. int i, n, selected = -1;
  283. n = sizeof(speed_table) / sizeof(speed_struct);
  284. if (arg < speed_table[0].speed)
  285. selected = 0;
  286. if (arg > speed_table[n - 1].speed)
  287. selected = n - 1;
  288. for (i = 1; selected == -1 && i < n; i++) {
  289. if (speed_table[i].speed == arg)
  290. selected = i;
  291. else if (speed_table[i].speed > arg) {
  292. int diff1, diff2;
  293. diff1 = arg - speed_table[i - 1].speed;
  294. diff2 = speed_table[i].speed - arg;
  295. if (diff1 < diff2)
  296. selected = i - 1;
  297. else
  298. selected = i;
  299. }
  300. }
  301. if (selected == -1)
  302. selected = 3;
  303. sc->sc_speed_bits = speed_table[selected].bits;
  304. sc->sc_need_commit = 1;
  305. *argp = speed_table[selected].speed;
  306. return (0);
  307. }
  308. /*
  309. * Audio interface functions
  310. */
  311. int
  312. cs4231_open(void *vsc, int flags)
  313. {
  314. struct cs4231_softc *sc = vsc;
  315. int tries;
  316. if (sc->sc_open)
  317. return (EBUSY);
  318. sc->sc_open = 1;
  319. sc->sc_capture.cs_intr = NULL;
  320. sc->sc_capture.cs_arg = NULL;
  321. sc->sc_capture.cs_locked = 0;
  322. sc->sc_playback.cs_intr = NULL;
  323. sc->sc_playback.cs_arg = NULL;
  324. sc->sc_playback.cs_locked = 0;
  325. APC_WRITE(sc, APC_CSR, APC_CSR_RESET);
  326. DELAY(10);
  327. APC_WRITE(sc, APC_CSR, 0);
  328. DELAY(10);
  329. APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) | APC_CSR_CODEC_RESET);
  330. DELAY(20);
  331. APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) & (~APC_CSR_CODEC_RESET));
  332. for (tries = CS_TIMEOUT;
  333. tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
  334. DELAY(10);
  335. if (tries == 0)
  336. printf("%s: timeout waiting for reset\n", sc->sc_dev.dv_xname);
  337. /* Turn on cs4231 mode */
  338. cs4231_write(sc, SP_MISC_INFO,
  339. cs4231_read(sc, SP_MISC_INFO) | MODE2);
  340. cs4231_setup_output(sc);
  341. cs4231_write(sc, SP_PIN_CONTROL,
  342. cs4231_read(sc, SP_PIN_CONTROL) | INTERRUPT_ENABLE);
  343. return (0);
  344. }
  345. void
  346. cs4231_setup_output(struct cs4231_softc *sc)
  347. {
  348. u_int8_t pc, mi, rm, lm;
  349. pc = cs4231_read(sc, SP_PIN_CONTROL) | CS_PC_HDPHMUTE | CS_PC_LINEMUTE;
  350. mi = cs4231_read(sc, CS_MONO_IO_CONTROL) | MONO_OUTPUT_MUTE;
  351. lm = cs4231_read(sc, SP_LEFT_OUTPUT_CONTROL);
  352. lm &= ~OUTPUT_ATTEN_BITS;
  353. lm |= ((~(sc->sc_volume[CSPORT_SPEAKER].left >> 2)) &
  354. OUTPUT_ATTEN_BITS) | OUTPUT_MUTE;
  355. rm = cs4231_read(sc, SP_RIGHT_OUTPUT_CONTROL);
  356. rm &= ~OUTPUT_ATTEN_BITS;
  357. rm |= ((~(sc->sc_volume[CSPORT_SPEAKER].right >> 2)) &
  358. OUTPUT_ATTEN_BITS) | OUTPUT_MUTE;
  359. if (sc->sc_mute[CSPORT_MONITOR]) {
  360. lm &= ~OUTPUT_MUTE;
  361. rm &= ~OUTPUT_MUTE;
  362. }
  363. switch (sc->sc_out_port) {
  364. case CSPORT_HEADPHONE:
  365. if (sc->sc_mute[CSPORT_SPEAKER])
  366. pc &= ~CS_PC_HDPHMUTE;
  367. break;
  368. case CSPORT_SPEAKER:
  369. if (sc->sc_mute[CSPORT_SPEAKER])
  370. mi &= ~MONO_OUTPUT_MUTE;
  371. break;
  372. case CSPORT_LINEOUT:
  373. if (sc->sc_mute[CSPORT_SPEAKER])
  374. pc &= ~CS_PC_LINEMUTE;
  375. break;
  376. }
  377. cs4231_write(sc, SP_LEFT_OUTPUT_CONTROL, lm);
  378. cs4231_write(sc, SP_RIGHT_OUTPUT_CONTROL, rm);
  379. cs4231_write(sc, SP_PIN_CONTROL, pc);
  380. cs4231_write(sc, CS_MONO_IO_CONTROL, mi);
  381. /* XXX doesn't really belong here... */
  382. switch (sc->sc_in_port) {
  383. case CSPORT_LINEIN:
  384. pc = LINE_INPUT;
  385. break;
  386. case CSPORT_AUX1:
  387. pc = AUX_INPUT;
  388. break;
  389. case CSPORT_DAC:
  390. pc = MIXED_DAC_INPUT;
  391. break;
  392. case CSPORT_MICROPHONE:
  393. default:
  394. pc = MIC_INPUT;
  395. break;
  396. }
  397. lm = cs4231_read(sc, SP_LEFT_INPUT_CONTROL);
  398. rm = cs4231_read(sc, SP_RIGHT_INPUT_CONTROL);
  399. lm &= ~(MIXED_DAC_INPUT | ATTEN_22_5);
  400. rm &= ~(MIXED_DAC_INPUT | ATTEN_22_5);
  401. lm |= pc | (sc->sc_adc.left >> 4);
  402. rm |= pc | (sc->sc_adc.right >> 4);
  403. cs4231_write(sc, SP_LEFT_INPUT_CONTROL, lm);
  404. cs4231_write(sc, SP_RIGHT_INPUT_CONTROL, rm);
  405. }
  406. void
  407. cs4231_close(void *vsc)
  408. {
  409. struct cs4231_softc *sc = vsc;
  410. cs4231_halt_input(sc);
  411. cs4231_halt_output(sc);
  412. cs4231_write(sc, SP_PIN_CONTROL,
  413. cs4231_read(sc, SP_PIN_CONTROL) & (~INTERRUPT_ENABLE));
  414. sc->sc_open = 0;
  415. }
  416. int
  417. cs4231_query_encoding(void *vsc, struct audio_encoding *fp)
  418. {
  419. int err = 0;
  420. switch (fp->index) {
  421. case 0:
  422. strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
  423. fp->encoding = AUDIO_ENCODING_ULAW;
  424. fp->precision = 8;
  425. fp->flags = 0;
  426. break;
  427. case 1:
  428. strlcpy(fp->name, AudioEalaw, sizeof fp->name);
  429. fp->encoding = AUDIO_ENCODING_ALAW;
  430. fp->precision = 8;
  431. fp->flags = 0;
  432. break;
  433. case 2:
  434. strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
  435. fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
  436. fp->precision = 16;
  437. fp->flags = 0;
  438. break;
  439. case 3:
  440. strlcpy(fp->name, AudioEulinear, sizeof fp->name);
  441. fp->encoding = AUDIO_ENCODING_ULINEAR;
  442. fp->precision = 8;
  443. fp->flags = 0;
  444. break;
  445. case 4:
  446. strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
  447. fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
  448. fp->precision = 16;
  449. fp->flags = 0;
  450. break;
  451. case 5:
  452. strlcpy(fp->name, AudioEslinear, sizeof fp->name);
  453. fp->encoding = AUDIO_ENCODING_SLINEAR;
  454. fp->precision = 8;
  455. fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  456. break;
  457. case 6:
  458. strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
  459. fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
  460. fp->precision = 16;
  461. fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  462. break;
  463. case 7:
  464. strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
  465. fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
  466. fp->precision = 16;
  467. fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  468. break;
  469. default:
  470. err = EINVAL;
  471. }
  472. fp->bps = AUDIO_BPS(fp->precision);
  473. fp->msb = 1;
  474. return (err);
  475. }
  476. int
  477. cs4231_set_params(void *vsc, int setmode, int usemode,
  478. struct audio_params *p, struct audio_params *r)
  479. {
  480. struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
  481. int err, bits, enc = p->encoding;
  482. switch (enc) {
  483. case AUDIO_ENCODING_ULAW:
  484. if (p->precision != 8)
  485. return (EINVAL);
  486. bits = FMT_ULAW >> 5;
  487. break;
  488. case AUDIO_ENCODING_ALAW:
  489. if (p->precision != 8)
  490. return (EINVAL);
  491. bits = FMT_ALAW >> 5;
  492. break;
  493. case AUDIO_ENCODING_SLINEAR_LE:
  494. if (p->precision == 16)
  495. bits = FMT_TWOS_COMP >> 5;
  496. else
  497. return (EINVAL);
  498. break;
  499. case AUDIO_ENCODING_ULINEAR:
  500. if (p->precision != 8)
  501. return (EINVAL);
  502. bits = FMT_PCM8 >> 5;
  503. break;
  504. case AUDIO_ENCODING_SLINEAR_BE:
  505. if (p->precision == 16)
  506. bits = FMT_TWOS_COMP_BE >> 5;
  507. else
  508. return (EINVAL);
  509. break;
  510. case AUDIO_ENCODING_ULINEAR_LE:
  511. if (p->precision == 8)
  512. bits = FMT_PCM8 >> 5;
  513. else
  514. return (EINVAL);
  515. break;
  516. case AUDIO_ENCODING_ULINEAR_BE:
  517. if (p->precision == 8)
  518. bits = FMT_PCM8 >> 5;
  519. else
  520. return (EINVAL);
  521. break;
  522. default:
  523. return (EINVAL);
  524. }
  525. if (p->channels != 1 && p->channels != 2)
  526. return (EINVAL);
  527. err = cs4231_set_speed(sc, &p->sample_rate);
  528. if (err)
  529. return (err);
  530. p->bps = AUDIO_BPS(p->precision);
  531. r->bps = AUDIO_BPS(r->precision);
  532. p->msb = r->msb = 1;
  533. sc->sc_format_bits = bits;
  534. sc->sc_channels = p->channels;
  535. sc->sc_precision = p->precision;
  536. sc->sc_need_commit = 1;
  537. return (0);
  538. }
  539. int
  540. cs4231_round_blocksize(void *vsc, int blk)
  541. {
  542. return ((blk + 3) & (-4));
  543. }
  544. int
  545. cs4231_commit_settings(void *vsc)
  546. {
  547. struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
  548. int tries;
  549. u_int8_t r, fs;
  550. if (sc->sc_need_commit == 0)
  551. return (0);
  552. fs = sc->sc_speed_bits | (sc->sc_format_bits << 5);
  553. if (sc->sc_channels == 2)
  554. fs |= FMT_STEREO;
  555. /* XXX: this is called before DMA is setup, useful ? */
  556. mtx_enter(&audio_lock);
  557. r = cs4231_read(sc, SP_INTERFACE_CONFIG) | AUTO_CAL_ENABLE;
  558. CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE);
  559. CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_INTERFACE_CONFIG);
  560. CS_WRITE(sc, AD1848_IDATA, r);
  561. CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_CLOCK_DATA_FORMAT);
  562. CS_WRITE(sc, AD1848_IDATA, fs);
  563. CS_READ(sc, AD1848_IDATA);
  564. CS_READ(sc, AD1848_IDATA);
  565. tries = CS_TIMEOUT;
  566. for (tries = CS_TIMEOUT;
  567. tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
  568. DELAY(10);
  569. if (tries == 0)
  570. printf("%s: timeout committing fspb\n", sc->sc_dev.dv_xname);
  571. CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | CS_REC_FORMAT);
  572. CS_WRITE(sc, AD1848_IDATA, fs);
  573. CS_READ(sc, AD1848_IDATA);
  574. CS_READ(sc, AD1848_IDATA);
  575. for (tries = CS_TIMEOUT;
  576. tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
  577. DELAY(10);
  578. if (tries == 0)
  579. printf("%s: timeout committing cdf\n", sc->sc_dev.dv_xname);
  580. CS_WRITE(sc, AD1848_IADDR, 0);
  581. for (tries = CS_TIMEOUT;
  582. tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
  583. DELAY(10);
  584. if (tries == 0)
  585. printf("%s: timeout waiting for !mce\n", sc->sc_dev.dv_xname);
  586. CS_WRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
  587. for (tries = CS_TIMEOUT;
  588. tries && CS_READ(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG; tries--)
  589. DELAY(10);
  590. if (tries == 0)
  591. printf("%s: timeout waiting for autocalibration\n",
  592. sc->sc_dev.dv_xname);
  593. mtx_leave(&audio_lock);
  594. sc->sc_need_commit = 0;
  595. return (0);
  596. }
  597. int
  598. cs4231_halt_output(void *vsc)
  599. {
  600. struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
  601. /* XXX Kills some capture bits */
  602. mtx_enter(&audio_lock);
  603. APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) &
  604. ~(APC_CSR_EI | APC_CSR_GIE | APC_CSR_PIE |
  605. APC_CSR_EIE | APC_CSR_PDMA_GO | APC_CSR_PMIE));
  606. cs4231_write(sc, SP_INTERFACE_CONFIG,
  607. cs4231_read(sc, SP_INTERFACE_CONFIG) & (~PLAYBACK_ENABLE));
  608. sc->sc_playback.cs_locked = 0;
  609. mtx_leave(&audio_lock);
  610. return (0);
  611. }
  612. int
  613. cs4231_halt_input(void *vsc)
  614. {
  615. struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
  616. /* XXX Kills some playback bits */
  617. mtx_enter(&audio_lock);
  618. APC_WRITE(sc, APC_CSR, APC_CSR_CAPTURE_PAUSE);
  619. cs4231_write(sc, SP_INTERFACE_CONFIG,
  620. cs4231_read(sc, SP_INTERFACE_CONFIG) & (~CAPTURE_ENABLE));
  621. sc->sc_capture.cs_locked = 0;
  622. mtx_leave(&audio_lock);
  623. return (0);
  624. }
  625. int
  626. cs4231_getdev(void *vsc, struct audio_device *retp)
  627. {
  628. *retp = cs4231_device;
  629. return (0);
  630. }
  631. int
  632. cs4231_set_port(void *vsc, mixer_ctrl_t *cp)
  633. {
  634. struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
  635. int error = EINVAL;
  636. DPRINTF(("cs4231_set_port: port=%d type=%d\n", cp->dev, cp->type));
  637. switch (cp->dev) {
  638. case CSAUDIO_DAC_LVL:
  639. if (cp->type != AUDIO_MIXER_VALUE)
  640. break;
  641. if (cp->un.value.num_channels == 1)
  642. cs4231_write(sc, SP_LEFT_AUX1_CONTROL,
  643. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
  644. LINE_INPUT_ATTEN_BITS);
  645. else if (cp->un.value.num_channels == 2) {
  646. cs4231_write(sc, SP_LEFT_AUX1_CONTROL,
  647. cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
  648. LINE_INPUT_ATTEN_BITS);
  649. cs4231_write(sc, SP_RIGHT_AUX1_CONTROL,
  650. cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
  651. LINE_INPUT_ATTEN_BITS);
  652. } else
  653. break;
  654. error = 0;
  655. break;
  656. case CSAUDIO_LINE_IN_LVL:
  657. if (cp->type != AUDIO_MIXER_VALUE)
  658. break;
  659. if (cp->un.value.num_channels == 1)
  660. cs4231_write(sc, CS_LEFT_LINE_CONTROL,
  661. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
  662. AUX_INPUT_ATTEN_BITS);
  663. else if (cp->un.value.num_channels == 2) {
  664. cs4231_write(sc, CS_LEFT_LINE_CONTROL,
  665. cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
  666. AUX_INPUT_ATTEN_BITS);
  667. cs4231_write(sc, CS_RIGHT_LINE_CONTROL,
  668. cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
  669. AUX_INPUT_ATTEN_BITS);
  670. } else
  671. break;
  672. error = 0;
  673. break;
  674. case CSAUDIO_MIC_LVL:
  675. if (cp->type != AUDIO_MIXER_VALUE)
  676. break;
  677. if (cp->un.value.num_channels == 1) {
  678. #if 0
  679. cs4231_write(sc, CS_MONO_IO_CONTROL,
  680. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
  681. MONO_INPUT_ATTEN_BITS);
  682. #endif
  683. } else
  684. break;
  685. error = 0;
  686. break;
  687. case CSAUDIO_CD_LVL:
  688. if (cp->type != AUDIO_MIXER_VALUE)
  689. break;
  690. if (cp->un.value.num_channels == 1) {
  691. cs4231_write(sc, SP_LEFT_AUX2_CONTROL,
  692. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
  693. LINE_INPUT_ATTEN_BITS);
  694. } else if (cp->un.value.num_channels == 2) {
  695. cs4231_write(sc, SP_LEFT_AUX2_CONTROL,
  696. cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
  697. LINE_INPUT_ATTEN_BITS);
  698. cs4231_write(sc, SP_RIGHT_AUX2_CONTROL,
  699. cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
  700. LINE_INPUT_ATTEN_BITS);
  701. } else
  702. break;
  703. error = 0;
  704. break;
  705. case CSAUDIO_MONITOR_LVL:
  706. if (cp->type != AUDIO_MIXER_VALUE)
  707. break;
  708. if (cp->un.value.num_channels == 1)
  709. cs4231_write(sc, SP_DIGITAL_MIX,
  710. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] << 2);
  711. else
  712. break;
  713. error = 0;
  714. break;
  715. case CSAUDIO_OUTPUT_LVL:
  716. if (cp->type != AUDIO_MIXER_VALUE)
  717. break;
  718. if (cp->un.value.num_channels == 1) {
  719. sc->sc_volume[CSPORT_SPEAKER].left =
  720. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
  721. sc->sc_volume[CSPORT_SPEAKER].right =
  722. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
  723. }
  724. else if (cp->un.value.num_channels == 2) {
  725. sc->sc_volume[CSPORT_SPEAKER].left =
  726. cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
  727. sc->sc_volume[CSPORT_SPEAKER].right =
  728. cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
  729. }
  730. else
  731. break;
  732. cs4231_setup_output(sc);
  733. error = 0;
  734. break;
  735. case CSAUDIO_OUTPUT:
  736. if (cp->type != AUDIO_MIXER_ENUM)
  737. break;
  738. if (cp->un.ord != CSPORT_LINEOUT &&
  739. cp->un.ord != CSPORT_SPEAKER &&
  740. cp->un.ord != CSPORT_HEADPHONE)
  741. return (EINVAL);
  742. sc->sc_out_port = cp->un.ord;
  743. cs4231_setup_output(sc);
  744. error = 0;
  745. break;
  746. case CSAUDIO_LINE_IN_MUTE:
  747. if (cp->type != AUDIO_MIXER_ENUM)
  748. break;
  749. sc->sc_mute[CSPORT_LINEIN] = cp->un.ord ? 1 : 0;
  750. error = 0;
  751. break;
  752. case CSAUDIO_DAC_MUTE:
  753. if (cp->type != AUDIO_MIXER_ENUM)
  754. break;
  755. sc->sc_mute[CSPORT_AUX1] = cp->un.ord ? 1 : 0;
  756. error = 0;
  757. break;
  758. case CSAUDIO_CD_MUTE:
  759. if (cp->type != AUDIO_MIXER_ENUM)
  760. break;
  761. sc->sc_mute[CSPORT_AUX2] = cp->un.ord ? 1 : 0;
  762. error = 0;
  763. break;
  764. case CSAUDIO_MIC_MUTE:
  765. if (cp->type != AUDIO_MIXER_ENUM)
  766. break;
  767. sc->sc_mute[CSPORT_MONO] = cp->un.ord ? 1 : 0;
  768. error = 0;
  769. break;
  770. case CSAUDIO_MONITOR_MUTE:
  771. if (cp->type != AUDIO_MIXER_ENUM)
  772. break;
  773. sc->sc_mute[CSPORT_MONITOR] = cp->un.ord ? 1 : 0;
  774. error = 0;
  775. break;
  776. case CSAUDIO_OUTPUT_MUTE:
  777. if (cp->type != AUDIO_MIXER_ENUM)
  778. break;
  779. sc->sc_mute[CSPORT_SPEAKER] = cp->un.ord ? 1 : 0;
  780. cs4231_setup_output(sc);
  781. error = 0;
  782. break;
  783. case CSAUDIO_REC_LVL:
  784. if (cp->type != AUDIO_MIXER_VALUE)
  785. break;
  786. if (cp->un.value.num_channels == 1) {
  787. sc->sc_adc.left =
  788. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
  789. sc->sc_adc.right =
  790. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
  791. } else if (cp->un.value.num_channels == 2) {
  792. sc->sc_adc.left =
  793. cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
  794. sc->sc_adc.right =
  795. cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
  796. } else
  797. break;
  798. cs4231_setup_output(sc);
  799. error = 0;
  800. break;
  801. case CSAUDIO_RECORD_SOURCE:
  802. if (cp->type != AUDIO_MIXER_ENUM)
  803. break;
  804. if (cp->un.ord == CSPORT_MICROPHONE ||
  805. cp->un.ord == CSPORT_LINEIN ||
  806. cp->un.ord == CSPORT_AUX1 ||
  807. cp->un.ord == CSPORT_DAC) {
  808. sc->sc_in_port = cp->un.ord;
  809. error = 0;
  810. cs4231_setup_output(sc);
  811. }
  812. break;
  813. }
  814. return (error);
  815. }
  816. int
  817. cs4231_get_port(void *vsc, mixer_ctrl_t *cp)
  818. {
  819. struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
  820. int error = EINVAL;
  821. DPRINTF(("cs4231_get_port: port=%d type=%d\n", cp->dev, cp->type));
  822. switch (cp->dev) {
  823. case CSAUDIO_DAC_LVL:
  824. if (cp->type != AUDIO_MIXER_VALUE)
  825. break;
  826. if (cp->un.value.num_channels == 1)
  827. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]=
  828. cs4231_read(sc, SP_LEFT_AUX1_CONTROL) &
  829. LINE_INPUT_ATTEN_BITS;
  830. else if (cp->un.value.num_channels == 2) {
  831. cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
  832. cs4231_read(sc, SP_LEFT_AUX1_CONTROL) &
  833. LINE_INPUT_ATTEN_BITS;
  834. cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
  835. cs4231_read(sc, SP_RIGHT_AUX1_CONTROL) &
  836. LINE_INPUT_ATTEN_BITS;
  837. } else
  838. break;
  839. error = 0;
  840. break;
  841. case CSAUDIO_LINE_IN_LVL:
  842. if (cp->type != AUDIO_MIXER_VALUE)
  843. break;
  844. if (cp->un.value.num_channels == 1)
  845. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
  846. cs4231_read(sc, CS_LEFT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS;
  847. else if (cp->un.value.num_channels == 2) {
  848. cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
  849. cs4231_read(sc, CS_LEFT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS;
  850. cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
  851. cs4231_read(sc, CS_RIGHT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS;
  852. } else
  853. break;
  854. error = 0;
  855. break;
  856. case CSAUDIO_MIC_LVL:
  857. if (cp->type != AUDIO_MIXER_VALUE)
  858. break;
  859. if (cp->un.value.num_channels == 1) {
  860. #if 0
  861. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
  862. cs4231_read(sc, CS_MONO_IO_CONTROL) &
  863. MONO_INPUT_ATTEN_BITS;
  864. #endif
  865. } else
  866. break;
  867. error = 0;
  868. break;
  869. case CSAUDIO_CD_LVL:
  870. if (cp->type != AUDIO_MIXER_VALUE)
  871. break;
  872. if (cp->un.value.num_channels == 1)
  873. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
  874. cs4231_read(sc, SP_LEFT_AUX2_CONTROL) &
  875. LINE_INPUT_ATTEN_BITS;
  876. else if (cp->un.value.num_channels == 2) {
  877. cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
  878. cs4231_read(sc, SP_LEFT_AUX2_CONTROL) &
  879. LINE_INPUT_ATTEN_BITS;
  880. cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
  881. cs4231_read(sc, SP_RIGHT_AUX2_CONTROL) &
  882. LINE_INPUT_ATTEN_BITS;
  883. }
  884. else
  885. break;
  886. error = 0;
  887. break;
  888. case CSAUDIO_MONITOR_LVL:
  889. if (cp->type != AUDIO_MIXER_VALUE)
  890. break;
  891. if (cp->un.value.num_channels != 1)
  892. break;
  893. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
  894. cs4231_read(sc, SP_DIGITAL_MIX) >> 2;
  895. error = 0;
  896. break;
  897. case CSAUDIO_OUTPUT_LVL:
  898. if (cp->type != AUDIO_MIXER_VALUE)
  899. break;
  900. if (cp->un.value.num_channels == 1)
  901. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
  902. sc->sc_volume[CSPORT_SPEAKER].left;
  903. else if (cp->un.value.num_channels == 2) {
  904. cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
  905. sc->sc_volume[CSPORT_SPEAKER].left;
  906. cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
  907. sc->sc_volume[CSPORT_SPEAKER].right;
  908. }
  909. else
  910. break;
  911. error = 0;
  912. break;
  913. case CSAUDIO_LINE_IN_MUTE:
  914. if (cp->type != AUDIO_MIXER_ENUM)
  915. break;
  916. cp->un.ord = sc->sc_mute[CSPORT_LINEIN] ? 1 : 0;
  917. error = 0;
  918. break;
  919. case CSAUDIO_DAC_MUTE:
  920. if (cp->type != AUDIO_MIXER_ENUM)
  921. break;
  922. cp->un.ord = sc->sc_mute[CSPORT_AUX1] ? 1 : 0;
  923. error = 0;
  924. break;
  925. case CSAUDIO_CD_MUTE:
  926. if (cp->type != AUDIO_MIXER_ENUM)
  927. break;
  928. cp->un.ord = sc->sc_mute[CSPORT_AUX2] ? 1 : 0;
  929. error = 0;
  930. break;
  931. case CSAUDIO_MIC_MUTE:
  932. if (cp->type != AUDIO_MIXER_ENUM)
  933. break;
  934. cp->un.ord = sc->sc_mute[CSPORT_MONO] ? 1 : 0;
  935. error = 0;
  936. break;
  937. case CSAUDIO_MONITOR_MUTE:
  938. if (cp->type != AUDIO_MIXER_ENUM)
  939. break;
  940. cp->un.ord = sc->sc_mute[CSPORT_MONITOR] ? 1 : 0;
  941. error = 0;
  942. break;
  943. case CSAUDIO_OUTPUT_MUTE:
  944. if (cp->type != AUDIO_MIXER_ENUM)
  945. break;
  946. cp->un.ord = sc->sc_mute[CSPORT_SPEAKER] ? 1 : 0;
  947. error = 0;
  948. break;
  949. case CSAUDIO_REC_LVL:
  950. if (cp->type != AUDIO_MIXER_VALUE)
  951. break;
  952. if (cp->un.value.num_channels == 1) {
  953. cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
  954. sc->sc_adc.left;
  955. } else if (cp->un.value.num_channels == 2) {
  956. cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
  957. sc->sc_adc.left;
  958. cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
  959. sc->sc_adc.right;
  960. } else
  961. break;
  962. error = 0;
  963. break;
  964. case CSAUDIO_RECORD_SOURCE:
  965. if (cp->type != AUDIO_MIXER_ENUM)
  966. break;
  967. cp->un.ord = sc->sc_in_port;
  968. error = 0;
  969. break;
  970. case CSAUDIO_OUTPUT:
  971. if (cp->type != AUDIO_MIXER_ENUM)
  972. break;
  973. cp->un.ord = sc->sc_out_port;
  974. error = 0;
  975. break;
  976. }
  977. return (error);
  978. }
  979. int
  980. cs4231_query_devinfo(void *vsc, mixer_devinfo_t *dip)
  981. {
  982. int err = 0;
  983. switch (dip->index) {
  984. case CSAUDIO_MIC_LVL: /* mono/microphone mixer */
  985. dip->type = AUDIO_MIXER_VALUE;
  986. dip->mixer_class = CSAUDIO_INPUT_CLASS;
  987. dip->prev = AUDIO_MIXER_LAST;
  988. dip->next = CSAUDIO_MIC_MUTE;
  989. strlcpy(dip->label.name, AudioNmicrophone,
  990. sizeof dip->label.name);
  991. dip->un.v.num_channels = 1;
  992. strlcpy(dip->un.v.units.name, AudioNvolume,
  993. sizeof dip->un.v.units.name);
  994. break;
  995. case CSAUDIO_DAC_LVL: /* dacout */
  996. dip->type = AUDIO_MIXER_VALUE;
  997. dip->mixer_class = CSAUDIO_INPUT_CLASS;
  998. dip->prev = AUDIO_MIXER_LAST;
  999. dip->next = CSAUDIO_DAC_MUTE;
  1000. strlcpy(dip->label.name, AudioNdac,
  1001. sizeof dip->label.name);
  1002. dip->un.v.num_channels = 2;
  1003. strlcpy(dip->un.v.units.name, AudioNvolume,
  1004. sizeof dip->un.v.units.name);
  1005. break;
  1006. case CSAUDIO_LINE_IN_LVL: /* line */
  1007. dip->type = AUDIO_MIXER_VALUE;
  1008. dip->mixer_class = CSAUDIO_INPUT_CLASS;
  1009. dip->prev = AUDIO_MIXER_LAST;
  1010. dip->next = CSAUDIO_LINE_IN_MUTE;
  1011. strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
  1012. dip->un.v.num_channels = 2;
  1013. strlcpy(dip->un.v.units.name, AudioNvolume,
  1014. sizeof dip->un.v.units.name);
  1015. break;
  1016. case CSAUDIO_CD_LVL: /* cd */
  1017. dip->type = AUDIO_MIXER_VALUE;
  1018. dip->mixer_class = CSAUDIO_INPUT_CLASS;
  1019. dip->prev = AUDIO_MIXER_LAST;
  1020. dip->next = CSAUDIO_CD_MUTE;
  1021. strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
  1022. dip->un.v.num_channels = 2;
  1023. strlcpy(dip->un.v.units.name, AudioNvolume,
  1024. sizeof dip->un.v.units.name);
  1025. break;
  1026. case CSAUDIO_MONITOR_LVL: /* monitor level */
  1027. dip->type = AUDIO_MIXER_VALUE;
  1028. dip->mixer_class = CSAUDIO_MONITOR_CLASS;
  1029. dip->prev = AUDIO_MIXER_LAST;
  1030. dip->next = CSAUDIO_MONITOR_MUTE;
  1031. strlcpy(dip->label.name, AudioNmonitor,
  1032. sizeof dip->label.name);
  1033. dip->un.v.num_channels = 1;
  1034. strlcpy(dip->un.v.units.name, AudioNvolume,
  1035. sizeof dip->un.v.units.name);
  1036. break;
  1037. case CSAUDIO_OUTPUT_LVL:
  1038. dip->type = AUDIO_MIXER_VALUE;
  1039. dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
  1040. dip->prev = AUDIO_MIXER_LAST;
  1041. dip->next = CSAUDIO_OUTPUT_MUTE;
  1042. strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
  1043. dip->un.v.num_channels = 2;
  1044. strlcpy(dip->un.v.units.name, AudioNvolume,
  1045. sizeof dip->un.v.units.name);
  1046. break;
  1047. case CSAUDIO_LINE_IN_MUTE:
  1048. dip->type = AUDIO_MIXER_ENUM;
  1049. dip->mixer_class = CSAUDIO_INPUT_CLASS;
  1050. dip->prev = CSAUDIO_LINE_IN_LVL;
  1051. dip->next = AUDIO_MIXER_LAST;
  1052. goto mute;
  1053. case CSAUDIO_DAC_MUTE:
  1054. dip->type = AUDIO_MIXER_ENUM;
  1055. dip->mixer_class = CSAUDIO_INPUT_CLASS;
  1056. dip->prev = CSAUDIO_DAC_LVL;
  1057. dip->next = AUDIO_MIXER_LAST;
  1058. goto mute;
  1059. case CSAUDIO_CD_MUTE:
  1060. dip->type = AUDIO_MIXER_ENUM;
  1061. dip->mixer_class = CSAUDIO_INPUT_CLASS;
  1062. dip->prev = CSAUDIO_CD_LVL;
  1063. dip->next = AUDIO_MIXER_LAST;
  1064. goto mute;
  1065. case CSAUDIO_MIC_MUTE:
  1066. dip->type = AUDIO_MIXER_ENUM;
  1067. dip->mixer_class = CSAUDIO_INPUT_CLASS;
  1068. dip->prev = CSAUDIO_MIC_LVL;
  1069. dip->next = AUDIO_MIXER_LAST;
  1070. goto mute;
  1071. case CSAUDIO_MONITOR_MUTE:
  1072. dip->type = AUDIO_MIXER_ENUM;
  1073. dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
  1074. dip->prev = CSAUDIO_MONITOR_LVL;
  1075. dip->next = AUDIO_MIXER_LAST;
  1076. goto mute;
  1077. case CSAUDIO_OUTPUT_MUTE:
  1078. dip->type = AUDIO_MIXER_ENUM;
  1079. dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
  1080. dip->prev = CSAUDIO_OUTPUT_LVL;
  1081. dip->next = AUDIO_MIXER_LAST;
  1082. goto mute;
  1083. mute:
  1084. strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
  1085. dip->un.e.num_mem = 2;
  1086. strlcpy(dip->un.e.member[0].label.name, AudioNon,
  1087. sizeof dip->un.e.member[0].label.name);
  1088. dip->un.e.member[0].ord = 0;
  1089. strlcpy(dip->un.e.member[1].label.name, AudioNoff,
  1090. sizeof dip->un.e.member[1].label.name);
  1091. dip->un.e.member[1].ord = 1;
  1092. break;
  1093. case CSAUDIO_REC_LVL: /* record level */
  1094. dip->type = AUDIO_MIXER_VALUE;
  1095. dip->mixer_class = CSAUDIO_RECORD_CLASS;
  1096. dip->prev = AUDIO_MIXER_LAST;
  1097. dip->next = CSAUDIO_RECORD_SOURCE;
  1098. strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
  1099. dip->un.v.num_channels = 2;
  1100. strlcpy(dip->un.v.units.name, AudioNvolume,
  1101. sizeof dip->un.v.units.name);
  1102. break;
  1103. case CSAUDIO_RECORD_SOURCE:
  1104. dip->type = AUDIO_MIXER_ENUM;
  1105. dip->mixer_class = CSAUDIO_RECORD_CLASS;
  1106. dip->prev = CSAUDIO_REC_LVL;
  1107. dip->next = AUDIO_MIXER_LAST;
  1108. strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
  1109. dip->un.e.num_mem = 4;
  1110. strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone,
  1111. sizeof dip->un.e.member[0].label.name);
  1112. dip->un.e.member[0].ord = CSPORT_MICROPHONE;
  1113. strlcpy(dip->un.e.member[1].label.name, AudioNline,
  1114. sizeof dip->un.e.member[1].label.name);
  1115. dip->un.e.member[1].ord = CSPORT_LINEIN;
  1116. strlcpy(dip->un.e.member[2].label.name, AudioNcd,
  1117. sizeof dip->un.e.member[2].label.name);
  1118. dip->un.e.member[2].ord = CSPORT_AUX1;
  1119. strlcpy(dip->un.e.member[3].label.name, AudioNdac,
  1120. sizeof dip->un.e.member[3].label.name);
  1121. dip->un.e.member[3].ord = CSPORT_DAC;
  1122. break;
  1123. case CSAUDIO_OUTPUT:
  1124. dip->type = AUDIO_MIXER_ENUM;
  1125. dip->mixer_class = CSAUDIO_MONITOR_CLASS;
  1126. dip->prev = dip->next = AUDIO_MIXER_LAST;
  1127. strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
  1128. dip->un.e.num_mem = 3;
  1129. strlcpy(dip->un.e.member[0].label.name, AudioNspeaker,
  1130. sizeof dip->un.e.member[0].label.name);
  1131. dip->un.e.member[0].ord = CSPORT_SPEAKER;
  1132. strlcpy(dip->un.e.member[1].label.name, AudioNline,
  1133. sizeof dip->un.e.member[1].label.name);
  1134. dip->un.e.member[1].ord = CSPORT_LINEOUT;
  1135. strlcpy(dip->un.e.member[2].label.name, AudioNheadphone,
  1136. sizeof dip->un.e.member[2].label.name);
  1137. dip->un.e.member[2].ord = CSPORT_HEADPHONE;
  1138. break;
  1139. case CSAUDIO_INPUT_CLASS: /* input class descriptor */
  1140. dip->type = AUDIO_MIXER_CLASS;
  1141. dip->mixer_class = CSAUDIO_INPUT_CLASS;
  1142. dip->prev = AUDIO_MIXER_LAST;
  1143. dip->next = AUDIO_MIXER_LAST;
  1144. strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
  1145. break;
  1146. case CSAUDIO_OUTPUT_CLASS: /* output class descriptor */
  1147. dip->type = AUDIO_MIXER_CLASS;
  1148. dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
  1149. dip->prev = AUDIO_MIXER_LAST;
  1150. dip->next = AUDIO_MIXER_LAST;
  1151. strlcpy(dip->label.name, AudioCoutputs,
  1152. sizeof dip->label.name);
  1153. break;
  1154. case CSAUDIO_MONITOR_CLASS: /* monitor class descriptor */
  1155. dip->type = AUDIO_MIXER_CLASS;
  1156. dip->mixer_class = CSAUDIO_MONITOR_CLASS;
  1157. dip->prev = AUDIO_MIXER_LAST;
  1158. dip->next = AUDIO_MIXER_LAST;
  1159. strlcpy(dip->label.name, AudioCmonitor,
  1160. sizeof dip->label.name);
  1161. break;
  1162. case CSAUDIO_RECORD_CLASS: /* record class descriptor */
  1163. dip->type = AUDIO_MIXER_CLASS;
  1164. dip->mixer_class = CSAUDIO_RECORD_CLASS;
  1165. dip->prev = AUDIO_MIXER_LAST;
  1166. dip->next = AUDIO_MIXER_LAST;
  1167. strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
  1168. break;
  1169. default:
  1170. err = ENXIO;
  1171. }
  1172. return (err);
  1173. }
  1174. int
  1175. cs4231_get_props(void *vsc)
  1176. {
  1177. return (AUDIO_PROP_FULLDUPLEX);
  1178. }
  1179. /*
  1180. * Hardware interrupt handler
  1181. */
  1182. int
  1183. cs4231_intr(void *vsc)
  1184. {
  1185. struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
  1186. u_int32_t csr;
  1187. u_int8_t reg, status;
  1188. struct cs_dma *p;
  1189. int r = 0;
  1190. mtx_enter(&audio_lock);
  1191. csr = APC_READ(sc, APC_CSR);
  1192. APC_WRITE(sc, APC_CSR, csr);
  1193. if ((csr & APC_CSR_EIE) && (csr & APC_CSR_EI)) {
  1194. printf("%s: error interrupt\n", sc->sc_dev.dv_xname);
  1195. r = 1;
  1196. }
  1197. if ((csr & APC_CSR_PIE) && (csr & APC_CSR_PI)) {
  1198. /* playback interrupt */
  1199. r = 1;
  1200. }
  1201. if ((csr & APC_CSR_GIE) && (csr & APC_CSR_GI)) {
  1202. /* general interrupt */
  1203. status = CS_READ(sc, AD1848_STATUS);
  1204. if (status & (INTERRUPT_STATUS | SAMPLE_ERROR)) {
  1205. reg = cs4231_read(sc, CS_IRQ_STATUS);
  1206. if (reg & CS_AFS_PI) {
  1207. cs4231_write(sc, SP_LOWER_BASE_COUNT, 0xff);
  1208. cs4231_write(sc, SP_UPPER_BASE_COUNT, 0xff);
  1209. }
  1210. if (reg & CS_AFS_CI) {
  1211. cs4231_write(sc, CS_LOWER_REC_CNT, 0xff);
  1212. cs4231_write(sc, CS_UPPER_REC_CNT, 0xff);
  1213. }
  1214. CS_WRITE(sc, AD1848_STATUS, 0);
  1215. }
  1216. r = 1;
  1217. }
  1218. if (csr & (APC_CSR_PI|APC_CSR_PMI|APC_CSR_PIE|APC_CSR_PD))
  1219. r = 1;
  1220. if ((csr & APC_CSR_PMIE) && (csr & APC_CSR_PMI)) {
  1221. struct cs_channel *chan = &sc->sc_playback;
  1222. u_long nextaddr, togo;
  1223. p = chan->cs_curdma;
  1224. togo = chan->cs_segsz - chan->cs_cnt;
  1225. if (togo == 0) {
  1226. nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr;
  1227. chan->cs_cnt = togo = chan->cs_blksz;
  1228. } else {
  1229. nextaddr = APC_READ(sc, APC_PNVA) + chan->cs_blksz;
  1230. if (togo > chan->cs_blksz)
  1231. togo = chan->cs_blksz;
  1232. chan->cs_cnt += togo;
  1233. }
  1234. APC_WRITE(sc, APC_PNVA, nextaddr);
  1235. APC_WRITE(sc, APC_PNC, togo);
  1236. if (chan->cs_intr != NULL)
  1237. (*chan->cs_intr)(chan->cs_arg);
  1238. r = 1;
  1239. }
  1240. if ((csr & APC_CSR_CIE) && (csr & APC_CSR_CI)) {
  1241. if (csr & APC_CSR_CD) {
  1242. struct cs_channel *chan = &sc->sc_capture;
  1243. u_long nextaddr, togo;
  1244. p = chan->cs_curdma;
  1245. togo = chan->cs_segsz - chan->cs_cnt;
  1246. if (togo == 0) {
  1247. nextaddr =
  1248. (u_int32_t)p->dmamap->dm_segs[0].ds_addr;
  1249. chan->cs_cnt = togo = chan->cs_blksz;
  1250. } else {
  1251. nextaddr = APC_READ(sc, APC_CNVA) +
  1252. chan->cs_blksz;
  1253. if (togo > chan->cs_blksz)
  1254. togo = chan->cs_blksz;
  1255. chan->cs_cnt += togo;
  1256. }
  1257. APC_WRITE(sc, APC_CNVA, nextaddr);
  1258. APC_WRITE(sc, APC_CNC, togo);
  1259. if (chan->cs_intr != NULL)
  1260. (*chan->cs_intr)(chan->cs_arg);
  1261. }
  1262. r = 1;
  1263. }
  1264. if ((csr & APC_CSR_CMIE) && (csr & APC_CSR_CMI)) {
  1265. /* capture empty */
  1266. r = 1;
  1267. }
  1268. mtx_leave(&audio_lock);
  1269. return (r);
  1270. }
  1271. void *
  1272. cs4231_alloc(void *vsc, int direction, size_t size, int pool, int flags)
  1273. {
  1274. struct cs4231_softc *sc = (struct cs4231_softc *)vsc;
  1275. bus_dma_tag_t dmat = sc->sc_dmatag;
  1276. struct cs_dma *p;
  1277. p = (struct cs_dma *)malloc(sizeof(struct cs_dma), pool, flags);
  1278. if (p == NULL)
  1279. return (NULL);
  1280. if (bus_dmamap_create(dmat, size, 1, size, 0,
  1281. BUS_DMA_NOWAIT, &p->dmamap) != 0)
  1282. goto fail;
  1283. p->size = size;
  1284. if (bus_dmamem_alloc(dmat, size, 64*1024, 0, p->segs,
  1285. nitems(p->segs), &p->nsegs,
  1286. BUS_DMA_NOWAIT) != 0)
  1287. goto fail1;
  1288. if (bus_dmamem_map(dmat, p->segs, p->nsegs, p->size,
  1289. &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0)
  1290. goto fail2;
  1291. if (bus_dmamap_load(dmat, p->dmamap, p->addr, size, NULL,
  1292. BUS_DMA_NOWAIT) != 0)
  1293. goto fail3;
  1294. p->next = sc->sc_dmas;
  1295. sc->sc_dmas = p;
  1296. return (p->addr);
  1297. fail3:
  1298. bus_dmamem_unmap(dmat, p->addr, p->size);
  1299. fail2:
  1300. bus_dmamem_free(dmat, p->segs, p->nsegs);
  1301. fail1:
  1302. bus_dmamap_destroy(dmat, p->dmamap);
  1303. fail:
  1304. free(p, pool, 0);
  1305. return (NULL);
  1306. }
  1307. void
  1308. cs4231_free(void *vsc, void *ptr, int pool)
  1309. {
  1310. struct cs4231_softc *sc = vsc;
  1311. bus_dma_tag_t dmat = sc->sc_dmatag;
  1312. struct cs_dma *p, **pp;
  1313. for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) {
  1314. if (p->addr != ptr)
  1315. continue;
  1316. bus_dmamap_unload(dmat, p->dmamap);
  1317. bus_dmamem_unmap(dmat, p->addr, p->size);
  1318. bus_dmamem_free(dmat, p->segs, p->nsegs);
  1319. bus_dmamap_destroy(dmat, p->dmamap);
  1320. *pp = p->next;
  1321. free(p, pool, 0);
  1322. return;
  1323. }
  1324. printf("%s: attempt to free rogue pointer\n", sc->sc_dev.dv_xname);
  1325. }
  1326. int
  1327. cs4231_trigger_output(void *vsc, void *start, void *end, int blksize,
  1328. void (*intr)(void *), void *arg, struct audio_params *param)
  1329. {
  1330. struct cs4231_softc *sc = vsc;
  1331. struct cs_channel *chan = &sc->sc_playback;
  1332. struct cs_dma *p;
  1333. u_int32_t csr;
  1334. u_long n;
  1335. if (chan->cs_locked != 0) {
  1336. printf("%s: trigger_output: already running\n",
  1337. sc->sc_dev.dv_xname);
  1338. return (EINVAL);
  1339. }
  1340. chan->cs_locked = 1;
  1341. chan->cs_intr = intr;
  1342. chan->cs_arg = arg;
  1343. for (p = sc->sc_dmas; p->addr != start; p = p->next)
  1344. /*EMPTY*/;
  1345. if (p == NULL) {
  1346. printf("%s: trigger_output: bad addr: %p\n",
  1347. sc->sc_dev.dv_xname, start);
  1348. return (EINVAL);
  1349. }
  1350. n = (char *)end - (char *)start;
  1351. /*
  1352. * Do only `blksize' at a time, so audio_pint() is kept
  1353. * synchronous with us...
  1354. */
  1355. chan->cs_blksz = blksize;
  1356. chan->cs_curdma = p;
  1357. chan->cs_segsz = n;
  1358. if (n > chan->cs_blksz)
  1359. n = chan->cs_blksz;
  1360. chan->cs_cnt = n;
  1361. mtx_enter(&audio_lock);
  1362. csr = APC_READ(sc, APC_CSR);
  1363. APC_WRITE(sc, APC_PNVA, (u_long)p->dmamap->dm_segs[0].ds_addr);
  1364. APC_WRITE(sc, APC_PNC, (u_long)n);
  1365. if ((csr & APC_CSR_PDMA_GO) == 0 || (csr & APC_CSR_PPAUSE) != 0) {
  1366. APC_WRITE(sc, APC_CSR,
  1367. APC_READ(sc, APC_CSR) & ~(APC_CSR_PIE | APC_CSR_PPAUSE));
  1368. APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) |
  1369. APC_CSR_EI | APC_CSR_GIE | APC_CSR_PIE | APC_CSR_EIE |
  1370. APC_CSR_PMIE | APC_CSR_PDMA_GO);
  1371. cs4231_write(sc, SP_LOWER_BASE_COUNT, 0xff);
  1372. cs4231_write(sc, SP_UPPER_BASE_COUNT, 0xff);
  1373. cs4231_write(sc, SP_INTERFACE_CONFIG,
  1374. cs4231_read(sc, SP_INTERFACE_CONFIG) | PLAYBACK_ENABLE);
  1375. }
  1376. mtx_leave(&audio_lock);
  1377. return (0);
  1378. }
  1379. int
  1380. cs4231_trigger_input(void *vsc, void *start, void *end, int blksize,
  1381. void (*intr)(void *), void *arg, struct audio_params *param)
  1382. {
  1383. struct cs4231_softc *sc = vsc;
  1384. struct cs_channel *chan = &sc->sc_capture;
  1385. struct cs_dma *p;
  1386. u_int32_t csr;
  1387. u_long n;
  1388. if (chan->cs_locked != 0) {
  1389. printf("%s: trigger_input: already running\n",
  1390. sc->sc_dev.dv_xname);
  1391. return (EINVAL);
  1392. }
  1393. chan->cs_locked = 1;
  1394. chan->cs_intr = intr;
  1395. chan->cs_arg = arg;
  1396. for (p = sc->sc_dmas; p->addr != start; p = p->next)
  1397. /*EMPTY*/;
  1398. if (p == NULL) {
  1399. printf("%s: trigger_input: bad addr: %p\n",
  1400. sc->sc_dev.dv_xname, start);
  1401. return (EINVAL);
  1402. }
  1403. n = (char *)end - (char *)start;
  1404. /*
  1405. * Do only `blksize' at a time, so audio_cint() is kept
  1406. * synchronous with us...
  1407. */
  1408. chan->cs_blksz = blksize;
  1409. chan->cs_curdma = p;
  1410. chan->cs_segsz = n;
  1411. if (n > chan->cs_blksz)
  1412. n = chan->cs_blksz;
  1413. chan->cs_cnt = n;
  1414. mtx_enter(&audio_lock);
  1415. APC_WRITE(sc, APC_CNVA, p->dmamap->dm_segs[0].ds_addr);
  1416. APC_WRITE(sc, APC_CNC, (u_long)n);
  1417. csr = APC_READ(sc, APC_CSR);
  1418. if ((csr & APC_CSR_CDMA_GO) == 0 || (csr & APC_CSR_CPAUSE) != 0) {
  1419. csr &= APC_CSR_CPAUSE;
  1420. csr |= APC_CSR_GIE | APC_CSR_CMIE | APC_CSR_CIE | APC_CSR_EI |
  1421. APC_CSR_CDMA_GO;
  1422. APC_WRITE(sc, APC_CSR, csr);
  1423. cs4231_write(sc, CS_LOWER_REC_CNT, 0xff);
  1424. cs4231_write(sc, CS_UPPER_REC_CNT, 0xff);
  1425. cs4231_write(sc, SP_INTERFACE_CONFIG,
  1426. cs4231_read(sc, SP_INTERFACE_CONFIG) | CAPTURE_ENABLE);
  1427. }
  1428. if (APC_READ(sc, APC_CSR) & APC_CSR_CD) {
  1429. u_long nextaddr, togo;
  1430. p = chan->cs_curdma;
  1431. togo = chan->cs_segsz - chan->cs_cnt;
  1432. if (togo == 0) {
  1433. nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr;
  1434. chan->cs_cnt = togo = chan->cs_blksz;
  1435. } else {
  1436. nextaddr = APC_READ(sc, APC_CNVA) + chan->cs_blksz;
  1437. if (togo > chan->cs_blksz)
  1438. togo = chan->cs_blksz;
  1439. chan->cs_cnt += togo;
  1440. }
  1441. APC_WRITE(sc, APC_CNVA, nextaddr);
  1442. APC_WRITE(sc, APC_CNC, togo);
  1443. }
  1444. mtx_leave(&audio_lock);
  1445. return (0);
  1446. }