sb8_main.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) by Jaroslav Kysela <[email protected]>
  4. * Uros Bizjak <[email protected]>
  5. *
  6. * Routines for control of 8-bit SoundBlaster cards and clones
  7. * Please note: I don't have access to old SB8 soundcards.
  8. *
  9. * --
  10. *
  11. * Thu Apr 29 20:36:17 BST 1999 George David Morrison <[email protected]>
  12. * DSP can't respond to commands whilst in "high speed" mode. Caused
  13. * glitching during playback. Fixed.
  14. *
  15. * Wed Jul 12 22:02:55 CEST 2000 Uros Bizjak <[email protected]>
  16. * Cleaned up and rewrote lowlevel routines.
  17. */
  18. #include <linux/io.h>
  19. #include <asm/dma.h>
  20. #include <linux/init.h>
  21. #include <linux/time.h>
  22. #include <linux/module.h>
  23. #include <sound/core.h>
  24. #include <sound/sb.h>
  25. MODULE_AUTHOR("Jaroslav Kysela <[email protected]>, Uros Bizjak <[email protected]>");
  26. MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones");
  27. MODULE_LICENSE("GPL");
  28. #define SB8_CLOCK 1000000
  29. #define SB8_DEN(v) ((SB8_CLOCK + (v) / 2) / (v))
  30. #define SB8_RATE(v) (SB8_CLOCK / SB8_DEN(v))
  31. static const struct snd_ratnum clock = {
  32. .num = SB8_CLOCK,
  33. .den_min = 1,
  34. .den_max = 256,
  35. .den_step = 1,
  36. };
  37. static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = {
  38. .nrats = 1,
  39. .rats = &clock,
  40. };
  41. static const struct snd_ratnum stereo_clocks[] = {
  42. {
  43. .num = SB8_CLOCK,
  44. .den_min = SB8_DEN(22050),
  45. .den_max = SB8_DEN(22050),
  46. .den_step = 1,
  47. },
  48. {
  49. .num = SB8_CLOCK,
  50. .den_min = SB8_DEN(11025),
  51. .den_max = SB8_DEN(11025),
  52. .den_step = 1,
  53. }
  54. };
  55. static int snd_sb8_hw_constraint_rate_channels(struct snd_pcm_hw_params *params,
  56. struct snd_pcm_hw_rule *rule)
  57. {
  58. struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  59. if (c->min > 1) {
  60. unsigned int num = 0, den = 0;
  61. int err = snd_interval_ratnum(hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE),
  62. 2, stereo_clocks, &num, &den);
  63. if (err >= 0 && den) {
  64. params->rate_num = num;
  65. params->rate_den = den;
  66. }
  67. return err;
  68. }
  69. return 0;
  70. }
  71. static int snd_sb8_hw_constraint_channels_rate(struct snd_pcm_hw_params *params,
  72. struct snd_pcm_hw_rule *rule)
  73. {
  74. struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  75. if (r->min > SB8_RATE(22050) || r->max <= SB8_RATE(11025)) {
  76. struct snd_interval t = { .min = 1, .max = 1 };
  77. return snd_interval_refine(hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS), &t);
  78. }
  79. return 0;
  80. }
  81. static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream)
  82. {
  83. unsigned long flags;
  84. struct snd_sb *chip = snd_pcm_substream_chip(substream);
  85. struct snd_pcm_runtime *runtime = substream->runtime;
  86. unsigned int mixreg, rate, size, count;
  87. unsigned char format;
  88. unsigned char stereo = runtime->channels > 1;
  89. int dma;
  90. rate = runtime->rate;
  91. switch (chip->hardware) {
  92. case SB_HW_JAZZ16:
  93. if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
  94. if (chip->mode & SB_MODE_CAPTURE_16)
  95. return -EBUSY;
  96. else
  97. chip->mode |= SB_MODE_PLAYBACK_16;
  98. }
  99. chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
  100. break;
  101. case SB_HW_PRO:
  102. if (runtime->channels > 1) {
  103. if (snd_BUG_ON(rate != SB8_RATE(11025) &&
  104. rate != SB8_RATE(22050)))
  105. return -EINVAL;
  106. chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
  107. break;
  108. }
  109. fallthrough;
  110. case SB_HW_201:
  111. if (rate > 23000) {
  112. chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
  113. break;
  114. }
  115. fallthrough;
  116. case SB_HW_20:
  117. chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
  118. break;
  119. case SB_HW_10:
  120. chip->playback_format = SB_DSP_OUTPUT;
  121. break;
  122. default:
  123. return -EINVAL;
  124. }
  125. if (chip->mode & SB_MODE_PLAYBACK_16) {
  126. format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
  127. dma = chip->dma16;
  128. } else {
  129. format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
  130. chip->mode |= SB_MODE_PLAYBACK_8;
  131. dma = chip->dma8;
  132. }
  133. size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream);
  134. count = chip->p_period_size = snd_pcm_lib_period_bytes(substream);
  135. spin_lock_irqsave(&chip->reg_lock, flags);
  136. snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON);
  137. if (chip->hardware == SB_HW_JAZZ16)
  138. snd_sbdsp_command(chip, format);
  139. else if (stereo) {
  140. /* set playback stereo mode */
  141. spin_lock(&chip->mixer_lock);
  142. mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW);
  143. snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02);
  144. spin_unlock(&chip->mixer_lock);
  145. /* Soundblaster hardware programming reference guide, 3-23 */
  146. snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT);
  147. runtime->dma_area[0] = 0x80;
  148. snd_dma_program(dma, runtime->dma_addr, 1, DMA_MODE_WRITE);
  149. /* force interrupt */
  150. snd_sbdsp_command(chip, SB_DSP_OUTPUT);
  151. snd_sbdsp_command(chip, 0);
  152. snd_sbdsp_command(chip, 0);
  153. }
  154. snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
  155. if (stereo) {
  156. snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
  157. spin_lock(&chip->mixer_lock);
  158. /* save output filter status and turn it off */
  159. mixreg = snd_sbmixer_read(chip, SB_DSP_PLAYBACK_FILT);
  160. snd_sbmixer_write(chip, SB_DSP_PLAYBACK_FILT, mixreg | 0x20);
  161. spin_unlock(&chip->mixer_lock);
  162. /* just use force_mode16 for temporary storate... */
  163. chip->force_mode16 = mixreg;
  164. } else {
  165. snd_sbdsp_command(chip, 256 - runtime->rate_den);
  166. }
  167. if (chip->playback_format != SB_DSP_OUTPUT) {
  168. if (chip->mode & SB_MODE_PLAYBACK_16)
  169. count /= 2;
  170. count--;
  171. snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
  172. snd_sbdsp_command(chip, count & 0xff);
  173. snd_sbdsp_command(chip, count >> 8);
  174. }
  175. spin_unlock_irqrestore(&chip->reg_lock, flags);
  176. snd_dma_program(dma, runtime->dma_addr,
  177. size, DMA_MODE_WRITE | DMA_AUTOINIT);
  178. return 0;
  179. }
  180. static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream,
  181. int cmd)
  182. {
  183. unsigned long flags;
  184. struct snd_sb *chip = snd_pcm_substream_chip(substream);
  185. unsigned int count;
  186. spin_lock_irqsave(&chip->reg_lock, flags);
  187. switch (cmd) {
  188. case SNDRV_PCM_TRIGGER_START:
  189. snd_sbdsp_command(chip, chip->playback_format);
  190. if (chip->playback_format == SB_DSP_OUTPUT) {
  191. count = chip->p_period_size - 1;
  192. snd_sbdsp_command(chip, count & 0xff);
  193. snd_sbdsp_command(chip, count >> 8);
  194. }
  195. break;
  196. case SNDRV_PCM_TRIGGER_STOP:
  197. if (chip->playback_format == SB_DSP_HI_OUTPUT_AUTO) {
  198. struct snd_pcm_runtime *runtime = substream->runtime;
  199. snd_sbdsp_reset(chip);
  200. if (runtime->channels > 1) {
  201. spin_lock(&chip->mixer_lock);
  202. /* restore output filter and set hardware to mono mode */
  203. snd_sbmixer_write(chip, SB_DSP_STEREO_SW, chip->force_mode16 & ~0x02);
  204. spin_unlock(&chip->mixer_lock);
  205. }
  206. } else {
  207. snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
  208. }
  209. snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
  210. }
  211. spin_unlock_irqrestore(&chip->reg_lock, flags);
  212. return 0;
  213. }
  214. static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
  215. {
  216. unsigned long flags;
  217. struct snd_sb *chip = snd_pcm_substream_chip(substream);
  218. struct snd_pcm_runtime *runtime = substream->runtime;
  219. unsigned int mixreg, rate, size, count;
  220. unsigned char format;
  221. unsigned char stereo = runtime->channels > 1;
  222. int dma;
  223. rate = runtime->rate;
  224. switch (chip->hardware) {
  225. case SB_HW_JAZZ16:
  226. if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
  227. if (chip->mode & SB_MODE_PLAYBACK_16)
  228. return -EBUSY;
  229. else
  230. chip->mode |= SB_MODE_CAPTURE_16;
  231. }
  232. chip->capture_format = SB_DSP_LO_INPUT_AUTO;
  233. break;
  234. case SB_HW_PRO:
  235. if (runtime->channels > 1) {
  236. if (snd_BUG_ON(rate != SB8_RATE(11025) &&
  237. rate != SB8_RATE(22050)))
  238. return -EINVAL;
  239. chip->capture_format = SB_DSP_HI_INPUT_AUTO;
  240. break;
  241. }
  242. chip->capture_format = (rate > 23000) ? SB_DSP_HI_INPUT_AUTO : SB_DSP_LO_INPUT_AUTO;
  243. break;
  244. case SB_HW_201:
  245. if (rate > 13000) {
  246. chip->capture_format = SB_DSP_HI_INPUT_AUTO;
  247. break;
  248. }
  249. fallthrough;
  250. case SB_HW_20:
  251. chip->capture_format = SB_DSP_LO_INPUT_AUTO;
  252. break;
  253. case SB_HW_10:
  254. chip->capture_format = SB_DSP_INPUT;
  255. break;
  256. default:
  257. return -EINVAL;
  258. }
  259. if (chip->mode & SB_MODE_CAPTURE_16) {
  260. format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
  261. dma = chip->dma16;
  262. } else {
  263. format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
  264. chip->mode |= SB_MODE_CAPTURE_8;
  265. dma = chip->dma8;
  266. }
  267. size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream);
  268. count = chip->c_period_size = snd_pcm_lib_period_bytes(substream);
  269. spin_lock_irqsave(&chip->reg_lock, flags);
  270. snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
  271. if (chip->hardware == SB_HW_JAZZ16)
  272. snd_sbdsp_command(chip, format);
  273. else if (stereo)
  274. snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT);
  275. snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
  276. if (stereo) {
  277. snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
  278. spin_lock(&chip->mixer_lock);
  279. /* save input filter status and turn it off */
  280. mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT);
  281. snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20);
  282. spin_unlock(&chip->mixer_lock);
  283. /* just use force_mode16 for temporary storate... */
  284. chip->force_mode16 = mixreg;
  285. } else {
  286. snd_sbdsp_command(chip, 256 - runtime->rate_den);
  287. }
  288. if (chip->capture_format != SB_DSP_INPUT) {
  289. if (chip->mode & SB_MODE_PLAYBACK_16)
  290. count /= 2;
  291. count--;
  292. snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
  293. snd_sbdsp_command(chip, count & 0xff);
  294. snd_sbdsp_command(chip, count >> 8);
  295. }
  296. spin_unlock_irqrestore(&chip->reg_lock, flags);
  297. snd_dma_program(dma, runtime->dma_addr,
  298. size, DMA_MODE_READ | DMA_AUTOINIT);
  299. return 0;
  300. }
  301. static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream,
  302. int cmd)
  303. {
  304. unsigned long flags;
  305. struct snd_sb *chip = snd_pcm_substream_chip(substream);
  306. unsigned int count;
  307. spin_lock_irqsave(&chip->reg_lock, flags);
  308. switch (cmd) {
  309. case SNDRV_PCM_TRIGGER_START:
  310. snd_sbdsp_command(chip, chip->capture_format);
  311. if (chip->capture_format == SB_DSP_INPUT) {
  312. count = chip->c_period_size - 1;
  313. snd_sbdsp_command(chip, count & 0xff);
  314. snd_sbdsp_command(chip, count >> 8);
  315. }
  316. break;
  317. case SNDRV_PCM_TRIGGER_STOP:
  318. if (chip->capture_format == SB_DSP_HI_INPUT_AUTO) {
  319. struct snd_pcm_runtime *runtime = substream->runtime;
  320. snd_sbdsp_reset(chip);
  321. if (runtime->channels > 1) {
  322. /* restore input filter status */
  323. spin_lock(&chip->mixer_lock);
  324. snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16);
  325. spin_unlock(&chip->mixer_lock);
  326. /* set hardware to mono mode */
  327. snd_sbdsp_command(chip, SB_DSP_MONO_8BIT);
  328. }
  329. } else {
  330. snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
  331. }
  332. snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
  333. }
  334. spin_unlock_irqrestore(&chip->reg_lock, flags);
  335. return 0;
  336. }
  337. irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip)
  338. {
  339. struct snd_pcm_substream *substream;
  340. snd_sb_ack_8bit(chip);
  341. switch (chip->mode) {
  342. case SB_MODE_PLAYBACK_16: /* ok.. playback is active */
  343. if (chip->hardware != SB_HW_JAZZ16)
  344. break;
  345. fallthrough;
  346. case SB_MODE_PLAYBACK_8:
  347. substream = chip->playback_substream;
  348. if (chip->playback_format == SB_DSP_OUTPUT)
  349. snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START);
  350. snd_pcm_period_elapsed(substream);
  351. break;
  352. case SB_MODE_CAPTURE_16:
  353. if (chip->hardware != SB_HW_JAZZ16)
  354. break;
  355. fallthrough;
  356. case SB_MODE_CAPTURE_8:
  357. substream = chip->capture_substream;
  358. if (chip->capture_format == SB_DSP_INPUT)
  359. snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START);
  360. snd_pcm_period_elapsed(substream);
  361. break;
  362. }
  363. return IRQ_HANDLED;
  364. }
  365. static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *substream)
  366. {
  367. struct snd_sb *chip = snd_pcm_substream_chip(substream);
  368. size_t ptr;
  369. int dma;
  370. if (chip->mode & SB_MODE_PLAYBACK_8)
  371. dma = chip->dma8;
  372. else if (chip->mode & SB_MODE_PLAYBACK_16)
  373. dma = chip->dma16;
  374. else
  375. return 0;
  376. ptr = snd_dma_pointer(dma, chip->p_dma_size);
  377. return bytes_to_frames(substream->runtime, ptr);
  378. }
  379. static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *substream)
  380. {
  381. struct snd_sb *chip = snd_pcm_substream_chip(substream);
  382. size_t ptr;
  383. int dma;
  384. if (chip->mode & SB_MODE_CAPTURE_8)
  385. dma = chip->dma8;
  386. else if (chip->mode & SB_MODE_CAPTURE_16)
  387. dma = chip->dma16;
  388. else
  389. return 0;
  390. ptr = snd_dma_pointer(dma, chip->c_dma_size);
  391. return bytes_to_frames(substream->runtime, ptr);
  392. }
  393. /*
  394. */
  395. static const struct snd_pcm_hardware snd_sb8_playback =
  396. {
  397. .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
  398. SNDRV_PCM_INFO_MMAP_VALID),
  399. .formats = SNDRV_PCM_FMTBIT_U8,
  400. .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
  401. SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050),
  402. .rate_min = 4000,
  403. .rate_max = 23000,
  404. .channels_min = 1,
  405. .channels_max = 1,
  406. .buffer_bytes_max = 65536,
  407. .period_bytes_min = 64,
  408. .period_bytes_max = 65536,
  409. .periods_min = 1,
  410. .periods_max = 1024,
  411. .fifo_size = 0,
  412. };
  413. static const struct snd_pcm_hardware snd_sb8_capture =
  414. {
  415. .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
  416. SNDRV_PCM_INFO_MMAP_VALID),
  417. .formats = SNDRV_PCM_FMTBIT_U8,
  418. .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
  419. SNDRV_PCM_RATE_11025),
  420. .rate_min = 4000,
  421. .rate_max = 13000,
  422. .channels_min = 1,
  423. .channels_max = 1,
  424. .buffer_bytes_max = 65536,
  425. .period_bytes_min = 64,
  426. .period_bytes_max = 65536,
  427. .periods_min = 1,
  428. .periods_max = 1024,
  429. .fifo_size = 0,
  430. };
  431. /*
  432. *
  433. */
  434. static int snd_sb8_open(struct snd_pcm_substream *substream)
  435. {
  436. struct snd_sb *chip = snd_pcm_substream_chip(substream);
  437. struct snd_pcm_runtime *runtime = substream->runtime;
  438. unsigned long flags;
  439. spin_lock_irqsave(&chip->open_lock, flags);
  440. if (chip->open) {
  441. spin_unlock_irqrestore(&chip->open_lock, flags);
  442. return -EAGAIN;
  443. }
  444. chip->open |= SB_OPEN_PCM;
  445. spin_unlock_irqrestore(&chip->open_lock, flags);
  446. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  447. chip->playback_substream = substream;
  448. runtime->hw = snd_sb8_playback;
  449. } else {
  450. chip->capture_substream = substream;
  451. runtime->hw = snd_sb8_capture;
  452. }
  453. switch (chip->hardware) {
  454. case SB_HW_JAZZ16:
  455. if (chip->dma16 == 5 || chip->dma16 == 7)
  456. runtime->hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
  457. runtime->hw.rates |= SNDRV_PCM_RATE_8000_48000;
  458. runtime->hw.rate_min = 4000;
  459. runtime->hw.rate_max = 50000;
  460. runtime->hw.channels_max = 2;
  461. break;
  462. case SB_HW_PRO:
  463. runtime->hw.rate_max = 44100;
  464. runtime->hw.channels_max = 2;
  465. snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
  466. snd_sb8_hw_constraint_rate_channels, NULL,
  467. SNDRV_PCM_HW_PARAM_CHANNELS,
  468. SNDRV_PCM_HW_PARAM_RATE, -1);
  469. snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
  470. snd_sb8_hw_constraint_channels_rate, NULL,
  471. SNDRV_PCM_HW_PARAM_RATE, -1);
  472. break;
  473. case SB_HW_201:
  474. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  475. runtime->hw.rate_max = 44100;
  476. } else {
  477. runtime->hw.rate_max = 15000;
  478. }
  479. break;
  480. default:
  481. break;
  482. }
  483. snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
  484. &hw_constraints_clock);
  485. if (chip->dma8 > 3 || chip->dma16 >= 0) {
  486. snd_pcm_hw_constraint_step(runtime, 0,
  487. SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2);
  488. snd_pcm_hw_constraint_step(runtime, 0,
  489. SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 2);
  490. runtime->hw.buffer_bytes_max = 128 * 1024 * 1024;
  491. runtime->hw.period_bytes_max = 128 * 1024 * 1024;
  492. }
  493. return 0;
  494. }
  495. static int snd_sb8_close(struct snd_pcm_substream *substream)
  496. {
  497. unsigned long flags;
  498. struct snd_sb *chip = snd_pcm_substream_chip(substream);
  499. chip->playback_substream = NULL;
  500. chip->capture_substream = NULL;
  501. spin_lock_irqsave(&chip->open_lock, flags);
  502. chip->open &= ~SB_OPEN_PCM;
  503. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  504. chip->mode &= ~SB_MODE_PLAYBACK;
  505. else
  506. chip->mode &= ~SB_MODE_CAPTURE;
  507. spin_unlock_irqrestore(&chip->open_lock, flags);
  508. return 0;
  509. }
  510. /*
  511. * Initialization part
  512. */
  513. static const struct snd_pcm_ops snd_sb8_playback_ops = {
  514. .open = snd_sb8_open,
  515. .close = snd_sb8_close,
  516. .prepare = snd_sb8_playback_prepare,
  517. .trigger = snd_sb8_playback_trigger,
  518. .pointer = snd_sb8_playback_pointer,
  519. };
  520. static const struct snd_pcm_ops snd_sb8_capture_ops = {
  521. .open = snd_sb8_open,
  522. .close = snd_sb8_close,
  523. .prepare = snd_sb8_capture_prepare,
  524. .trigger = snd_sb8_capture_trigger,
  525. .pointer = snd_sb8_capture_pointer,
  526. };
  527. int snd_sb8dsp_pcm(struct snd_sb *chip, int device)
  528. {
  529. struct snd_card *card = chip->card;
  530. struct snd_pcm *pcm;
  531. int err;
  532. size_t max_prealloc = 64 * 1024;
  533. err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm);
  534. if (err < 0)
  535. return err;
  536. sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
  537. pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
  538. pcm->private_data = chip;
  539. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops);
  540. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops);
  541. if (chip->dma8 > 3 || chip->dma16 >= 0)
  542. max_prealloc = 128 * 1024;
  543. snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
  544. card->dev, 64*1024, max_prealloc);
  545. return 0;
  546. }
  547. EXPORT_SYMBOL(snd_sb8dsp_pcm);
  548. EXPORT_SYMBOL(snd_sb8dsp_interrupt);
  549. /* sb8_midi.c */
  550. EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt);
  551. EXPORT_SYMBOL(snd_sb8dsp_midi);