vidc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. * linux/drivers/sound/vidc.c
  3. *
  4. * Copyright (C) 1997-2000 by Russell King <rmk@arm.linux.org.uk>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * VIDC20 audio driver.
  11. *
  12. * The VIDC20 sound hardware consists of the VIDC20 itself, a DAC and a DMA
  13. * engine. The DMA transfers fixed-format (16-bit little-endian linear)
  14. * samples to the VIDC20, which then transfers this data serially to the
  15. * DACs. The samplerate is controlled by the VIDC.
  16. *
  17. * We currently support a mixer device, but it is currently non-functional.
  18. */
  19. #include <linux/gfp.h>
  20. #include <linux/init.h>
  21. #include <linux/module.h>
  22. #include <linux/kernel.h>
  23. #include <linux/interrupt.h>
  24. #include <mach/hardware.h>
  25. #include <asm/dma.h>
  26. #include <asm/io.h>
  27. #include <asm/hardware/iomd.h>
  28. #include <asm/irq.h>
  29. #include <asm/system.h>
  30. #include "sound_config.h"
  31. #include "vidc.h"
  32. #ifndef _SIOC_TYPE
  33. #define _SIOC_TYPE(x) _IOC_TYPE(x)
  34. #endif
  35. #ifndef _SIOC_NR
  36. #define _SIOC_NR(x) _IOC_NR(x)
  37. #endif
  38. #define VIDC_SOUND_CLOCK (250000)
  39. #define VIDC_SOUND_CLOCK_EXT (176400)
  40. /*
  41. * When using SERIAL SOUND mode (external DAC), the number of physical
  42. * channels is fixed at 2.
  43. */
  44. static int vidc_busy;
  45. static int vidc_adev;
  46. static int vidc_audio_rate;
  47. static char vidc_audio_format;
  48. static char vidc_audio_channels;
  49. static unsigned char vidc_level_l[SOUND_MIXER_NRDEVICES] = {
  50. 85, /* master */
  51. 50, /* bass */
  52. 50, /* treble */
  53. 0, /* synth */
  54. 75, /* pcm */
  55. 0, /* speaker */
  56. 100, /* ext line */
  57. 0, /* mic */
  58. 100, /* CD */
  59. 0,
  60. };
  61. static unsigned char vidc_level_r[SOUND_MIXER_NRDEVICES] = {
  62. 85, /* master */
  63. 50, /* bass */
  64. 50, /* treble */
  65. 0, /* synth */
  66. 75, /* pcm */
  67. 0, /* speaker */
  68. 100, /* ext line */
  69. 0, /* mic */
  70. 100, /* CD */
  71. 0,
  72. };
  73. static unsigned int vidc_audio_volume_l; /* left PCM vol, 0 - 65536 */
  74. static unsigned int vidc_audio_volume_r; /* right PCM vol, 0 - 65536 */
  75. extern void vidc_update_filler(int bits, int channels);
  76. extern int softoss_dev;
  77. static void
  78. vidc_mixer_set(int mdev, unsigned int level)
  79. {
  80. unsigned int lev_l = level & 0x007f;
  81. unsigned int lev_r = (level & 0x7f00) >> 8;
  82. unsigned int mlev_l, mlev_r;
  83. if (lev_l > 100)
  84. lev_l = 100;
  85. if (lev_r > 100)
  86. lev_r = 100;
  87. #define SCALE(lev,master) ((lev) * (master) * 65536 / 10000)
  88. mlev_l = vidc_level_l[SOUND_MIXER_VOLUME];
  89. mlev_r = vidc_level_r[SOUND_MIXER_VOLUME];
  90. switch (mdev) {
  91. case SOUND_MIXER_VOLUME:
  92. case SOUND_MIXER_PCM:
  93. vidc_level_l[mdev] = lev_l;
  94. vidc_level_r[mdev] = lev_r;
  95. vidc_audio_volume_l = SCALE(lev_l, mlev_l);
  96. vidc_audio_volume_r = SCALE(lev_r, mlev_r);
  97. /*printk("VIDC: PCM vol %05X %05X\n", vidc_audio_volume_l, vidc_audio_volume_r);*/
  98. break;
  99. }
  100. #undef SCALE
  101. }
  102. static int vidc_mixer_ioctl(int dev, unsigned int cmd, void __user *arg)
  103. {
  104. unsigned int val;
  105. unsigned int mdev;
  106. if (_SIOC_TYPE(cmd) != 'M')
  107. return -EINVAL;
  108. mdev = _SIOC_NR(cmd);
  109. if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
  110. if (get_user(val, (unsigned int __user *)arg))
  111. return -EFAULT;
  112. if (mdev < SOUND_MIXER_NRDEVICES)
  113. vidc_mixer_set(mdev, val);
  114. else
  115. return -EINVAL;
  116. }
  117. /*
  118. * Return parameters
  119. */
  120. switch (mdev) {
  121. case SOUND_MIXER_RECSRC:
  122. val = 0;
  123. break;
  124. case SOUND_MIXER_DEVMASK:
  125. val = SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH;
  126. break;
  127. case SOUND_MIXER_STEREODEVS:
  128. val = SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH;
  129. break;
  130. case SOUND_MIXER_RECMASK:
  131. val = 0;
  132. break;
  133. case SOUND_MIXER_CAPS:
  134. val = 0;
  135. break;
  136. default:
  137. if (mdev < SOUND_MIXER_NRDEVICES)
  138. val = vidc_level_l[mdev] | vidc_level_r[mdev] << 8;
  139. else
  140. return -EINVAL;
  141. }
  142. return put_user(val, (unsigned int __user *)arg) ? -EFAULT : 0;
  143. }
  144. static unsigned int vidc_audio_set_format(int dev, unsigned int fmt)
  145. {
  146. switch (fmt) {
  147. default:
  148. fmt = AFMT_S16_LE;
  149. case AFMT_U8:
  150. case AFMT_S8:
  151. case AFMT_S16_LE:
  152. vidc_audio_format = fmt;
  153. vidc_update_filler(vidc_audio_format, vidc_audio_channels);
  154. case AFMT_QUERY:
  155. break;
  156. }
  157. return vidc_audio_format;
  158. }
  159. #define my_abs(i) ((i)<0 ? -(i) : (i))
  160. static int vidc_audio_set_speed(int dev, int rate)
  161. {
  162. if (rate) {
  163. unsigned int hwctrl, hwrate, hwrate_ext, rate_int, rate_ext;
  164. unsigned int diff_int, diff_ext;
  165. unsigned int newsize, new2size;
  166. hwctrl = 0x00000003;
  167. /* Using internal clock */
  168. hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
  169. if (hwrate < 3)
  170. hwrate = 3;
  171. if (hwrate > 255)
  172. hwrate = 255;
  173. /* Using exernal clock */
  174. hwrate_ext = (((VIDC_SOUND_CLOCK_EXT * 2) / rate) + 1) >> 1;
  175. if (hwrate_ext < 3)
  176. hwrate_ext = 3;
  177. if (hwrate_ext > 255)
  178. hwrate_ext = 255;
  179. rate_int = VIDC_SOUND_CLOCK / hwrate;
  180. rate_ext = VIDC_SOUND_CLOCK_EXT / hwrate_ext;
  181. /* Chose between external and internal clock */
  182. diff_int = my_abs(rate_ext-rate);
  183. diff_ext = my_abs(rate_int-rate);
  184. if (diff_ext < diff_int) {
  185. /*printk("VIDC: external %d %d %d\n", rate, rate_ext, hwrate_ext);*/
  186. hwrate=hwrate_ext;
  187. hwctrl=0x00000002;
  188. /* Allow roughly 0.4% tolerance */
  189. if (diff_ext > (rate/256))
  190. rate=rate_ext;
  191. } else {
  192. /*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/
  193. hwctrl=0x00000003;
  194. /* Allow roughly 0.4% tolerance */
  195. if (diff_int > (rate/256))
  196. rate=rate_int;
  197. }
  198. vidc_writel(0xb0000000 | (hwrate - 2));
  199. vidc_writel(0xb1000000 | hwctrl);
  200. newsize = (10000 / hwrate) & ~3;
  201. if (newsize < 208)
  202. newsize = 208;
  203. if (newsize > 4096)
  204. newsize = 4096;
  205. for (new2size = 128; new2size < newsize; new2size <<= 1);
  206. if (new2size - newsize > newsize - (new2size >> 1))
  207. new2size >>= 1;
  208. if (new2size > 4096) {
  209. printk(KERN_ERR "VIDC: error: dma buffer (%d) %d > 4K\n",
  210. newsize, new2size);
  211. new2size = 4096;
  212. }
  213. /*printk("VIDC: dma size %d\n", new2size);*/
  214. dma_bufsize = new2size;
  215. vidc_audio_rate = rate;
  216. }
  217. return vidc_audio_rate;
  218. }
  219. static short vidc_audio_set_channels(int dev, short channels)
  220. {
  221. switch (channels) {
  222. default:
  223. channels = 2;
  224. case 1:
  225. case 2:
  226. vidc_audio_channels = channels;
  227. vidc_update_filler(vidc_audio_format, vidc_audio_channels);
  228. case 0:
  229. break;
  230. }
  231. return vidc_audio_channels;
  232. }
  233. /*
  234. * Open the device
  235. */
  236. static int vidc_audio_open(int dev, int mode)
  237. {
  238. /* This audio device does not have recording capability */
  239. if (mode == OPEN_READ)
  240. return -EPERM;
  241. if (vidc_busy)
  242. return -EBUSY;
  243. vidc_busy = 1;
  244. return 0;
  245. }
  246. /*
  247. * Close the device
  248. */
  249. static void vidc_audio_close(int dev)
  250. {
  251. vidc_busy = 0;
  252. }
  253. /*
  254. * Output a block via DMA to sound device.
  255. *
  256. * We just set the DMA start and count; the DMA interrupt routine
  257. * will take care of formatting the samples (via the appropriate
  258. * vidc_filler routine), and flag via vidc_audio_dma_interrupt when
  259. * more data is required.
  260. */
  261. static void
  262. vidc_audio_output_block(int dev, unsigned long buf, int total_count, int one)
  263. {
  264. struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
  265. unsigned long flags;
  266. local_irq_save(flags);
  267. dma_start = buf - (unsigned long)dmap->raw_buf_phys + (unsigned long)dmap->raw_buf;
  268. dma_count = total_count;
  269. local_irq_restore(flags);
  270. }
  271. static void
  272. vidc_audio_start_input(int dev, unsigned long buf, int count, int intrflag)
  273. {
  274. }
  275. static int vidc_audio_prepare_for_input(int dev, int bsize, int bcount)
  276. {
  277. return -EINVAL;
  278. }
  279. static irqreturn_t vidc_audio_dma_interrupt(void)
  280. {
  281. DMAbuf_outputintr(vidc_adev, 1);
  282. return IRQ_HANDLED;
  283. }
  284. /*
  285. * Prepare for outputting samples.
  286. *
  287. * Each buffer that will be passed will be `bsize' bytes long,
  288. * with a total of `bcount' buffers.
  289. */
  290. static int vidc_audio_prepare_for_output(int dev, int bsize, int bcount)
  291. {
  292. struct audio_operations *adev = audio_devs[dev];
  293. dma_interrupt = NULL;
  294. adev->dmap_out->flags |= DMA_NODMA;
  295. return 0;
  296. }
  297. /*
  298. * Stop our current operation.
  299. */
  300. static void vidc_audio_reset(int dev)
  301. {
  302. dma_interrupt = NULL;
  303. }
  304. static int vidc_audio_local_qlen(int dev)
  305. {
  306. return /*dma_count !=*/ 0;
  307. }
  308. static void vidc_audio_trigger(int dev, int enable_bits)
  309. {
  310. struct audio_operations *adev = audio_devs[dev];
  311. if (enable_bits & PCM_ENABLE_OUTPUT) {
  312. if (!(adev->dmap_out->flags & DMA_ACTIVE)) {
  313. unsigned long flags;
  314. local_irq_save(flags);
  315. /* prevent recusion */
  316. adev->dmap_out->flags |= DMA_ACTIVE;
  317. dma_interrupt = vidc_audio_dma_interrupt;
  318. vidc_sound_dma_irq(0, NULL);
  319. iomd_writeb(DMA_CR_E | 0x10, IOMD_SD0CR);
  320. local_irq_restore(flags);
  321. }
  322. }
  323. }
  324. static struct audio_driver vidc_audio_driver =
  325. {
  326. .owner = THIS_MODULE,
  327. .open = vidc_audio_open,
  328. .close = vidc_audio_close,
  329. .output_block = vidc_audio_output_block,
  330. .start_input = vidc_audio_start_input,
  331. .prepare_for_input = vidc_audio_prepare_for_input,
  332. .prepare_for_output = vidc_audio_prepare_for_output,
  333. .halt_io = vidc_audio_reset,
  334. .local_qlen = vidc_audio_local_qlen,
  335. .trigger = vidc_audio_trigger,
  336. .set_speed = vidc_audio_set_speed,
  337. .set_bits = vidc_audio_set_format,
  338. .set_channels = vidc_audio_set_channels
  339. };
  340. static struct mixer_operations vidc_mixer_operations = {
  341. .owner = THIS_MODULE,
  342. .id = "VIDC",
  343. .name = "VIDCsound",
  344. .ioctl = vidc_mixer_ioctl
  345. };
  346. void vidc_update_filler(int format, int channels)
  347. {
  348. #define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3))
  349. switch (TYPE(format, channels)) {
  350. default:
  351. case TYPE(AFMT_U8, 1):
  352. vidc_filler = vidc_fill_1x8_u;
  353. break;
  354. case TYPE(AFMT_U8, 2):
  355. vidc_filler = vidc_fill_2x8_u;
  356. break;
  357. case TYPE(AFMT_S8, 1):
  358. vidc_filler = vidc_fill_1x8_s;
  359. break;
  360. case TYPE(AFMT_S8, 2):
  361. vidc_filler = vidc_fill_2x8_s;
  362. break;
  363. case TYPE(AFMT_S16_LE, 1):
  364. vidc_filler = vidc_fill_1x16_s;
  365. break;
  366. case TYPE(AFMT_S16_LE, 2):
  367. vidc_filler = vidc_fill_2x16_s;
  368. break;
  369. }
  370. }
  371. static void __init attach_vidc(struct address_info *hw_config)
  372. {
  373. char name[32];
  374. int i, adev;
  375. sprintf(name, "VIDC %d-bit sound", hw_config->card_subtype);
  376. conf_printf(name, hw_config);
  377. memset(dma_buf, 0, sizeof(dma_buf));
  378. adev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, name,
  379. &vidc_audio_driver, sizeof(vidc_audio_driver),
  380. DMA_AUTOMODE, AFMT_U8 | AFMT_S8 | AFMT_S16_LE,
  381. NULL, hw_config->dma, hw_config->dma2);
  382. if (adev < 0)
  383. goto audio_failed;
  384. /*
  385. * 1024 bytes => 64 buffers
  386. */
  387. audio_devs[adev]->min_fragment = 10;
  388. audio_devs[adev]->mixer_dev = num_mixers;
  389. audio_devs[adev]->mixer_dev =
  390. sound_install_mixer(MIXER_DRIVER_VERSION,
  391. name, &vidc_mixer_operations,
  392. sizeof(vidc_mixer_operations), NULL);
  393. if (audio_devs[adev]->mixer_dev < 0)
  394. goto mixer_failed;
  395. for (i = 0; i < 2; i++) {
  396. dma_buf[i] = get_zeroed_page(GFP_KERNEL);
  397. if (!dma_buf[i]) {
  398. printk(KERN_ERR "%s: can't allocate required buffers\n",
  399. name);
  400. goto mem_failed;
  401. }
  402. dma_pbuf[i] = virt_to_phys((void *)dma_buf[i]);
  403. }
  404. if (sound_alloc_dma(hw_config->dma, hw_config->name)) {
  405. printk(KERN_ERR "%s: DMA %d is in use\n", name, hw_config->dma);
  406. goto dma_failed;
  407. }
  408. if (request_irq(hw_config->irq, vidc_sound_dma_irq, 0,
  409. hw_config->name, &dma_start)) {
  410. printk(KERN_ERR "%s: IRQ %d is in use\n", name, hw_config->irq);
  411. goto irq_failed;
  412. }
  413. vidc_adev = adev;
  414. vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8));
  415. return;
  416. irq_failed:
  417. sound_free_dma(hw_config->dma);
  418. dma_failed:
  419. mem_failed:
  420. for (i = 0; i < 2; i++)
  421. free_page(dma_buf[i]);
  422. sound_unload_mixerdev(audio_devs[adev]->mixer_dev);
  423. mixer_failed:
  424. sound_unload_audiodev(adev);
  425. audio_failed:
  426. return;
  427. }
  428. static int __init probe_vidc(struct address_info *hw_config)
  429. {
  430. hw_config->irq = IRQ_DMAS0;
  431. hw_config->dma = DMA_VIRTUAL_SOUND;
  432. hw_config->dma2 = -1;
  433. hw_config->card_subtype = 16;
  434. hw_config->name = "VIDC20";
  435. return 1;
  436. }
  437. static void __exit unload_vidc(struct address_info *hw_config)
  438. {
  439. int i, adev = vidc_adev;
  440. vidc_adev = -1;
  441. free_irq(hw_config->irq, &dma_start);
  442. sound_free_dma(hw_config->dma);
  443. if (adev >= 0) {
  444. sound_unload_mixerdev(audio_devs[adev]->mixer_dev);
  445. sound_unload_audiodev(adev);
  446. for (i = 0; i < 2; i++)
  447. free_page(dma_buf[i]);
  448. }
  449. }
  450. static struct address_info cfg;
  451. static int __init init_vidc(void)
  452. {
  453. if (probe_vidc(&cfg) == 0)
  454. return -ENODEV;
  455. attach_vidc(&cfg);
  456. return 0;
  457. }
  458. static void __exit cleanup_vidc(void)
  459. {
  460. unload_vidc(&cfg);
  461. }
  462. module_init(init_vidc);
  463. module_exit(cleanup_vidc);
  464. MODULE_AUTHOR("Russell King");
  465. MODULE_DESCRIPTION("VIDC20 audio driver");
  466. MODULE_LICENSE("GPL");