2 * linux/drivers/sound/vidc.c
4 * Copyright (C) 1997-2000 by Russell King <rmk@arm.linux.org.uk>
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.
10 * VIDC20 audio driver.
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.
17 * We currently support a mixer device, but it is currently non-functional.
20 #include <linux/init.h>
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/interrupt.h>
25 #include <asm/hardware.h>
28 #include <asm/hardware/iomd.h>
30 #include <asm/system.h>
32 #include "sound_config.h"
36 #define _SIOC_TYPE(x) _IOC_TYPE(x)
39 #define _SIOC_NR(x) _IOC_NR(x)
42 #define VIDC_SOUND_CLOCK (250000)
43 #define VIDC_SOUND_CLOCK_EXT (176400)
46 * When using SERIAL SOUND mode (external DAC), the number of physical
47 * channels is fixed at 2.
51 static int vidc_audio_rate
;
52 static char vidc_audio_format
;
53 static char vidc_audio_channels
;
55 static unsigned char vidc_level_l
[SOUND_MIXER_NRDEVICES
] = {
68 static unsigned char vidc_level_r
[SOUND_MIXER_NRDEVICES
] = {
81 static unsigned int vidc_audio_volume_l
; /* left PCM vol, 0 - 65536 */
82 static unsigned int vidc_audio_volume_r
; /* right PCM vol, 0 - 65536 */
84 extern void vidc_update_filler(int bits
, int channels
);
85 extern int softoss_dev
;
88 vidc_mixer_set(int mdev
, unsigned int level
)
90 unsigned int lev_l
= level
& 0x007f;
91 unsigned int lev_r
= (level
& 0x7f00) >> 8;
92 unsigned int mlev_l
, mlev_r
;
99 #define SCALE(lev,master) ((lev) * (master) * 65536 / 10000)
101 mlev_l
= vidc_level_l
[SOUND_MIXER_VOLUME
];
102 mlev_r
= vidc_level_r
[SOUND_MIXER_VOLUME
];
105 case SOUND_MIXER_VOLUME
:
106 case SOUND_MIXER_PCM
:
107 vidc_level_l
[mdev
] = lev_l
;
108 vidc_level_r
[mdev
] = lev_r
;
110 vidc_audio_volume_l
= SCALE(lev_l
, mlev_l
);
111 vidc_audio_volume_r
= SCALE(lev_r
, mlev_r
);
112 /*printk("VIDC: PCM vol %05X %05X\n", vidc_audio_volume_l, vidc_audio_volume_r);*/
118 static int vidc_mixer_ioctl(int dev
, unsigned int cmd
, void __user
*arg
)
123 if (_SIOC_TYPE(cmd
) != 'M')
126 mdev
= _SIOC_NR(cmd
);
128 if (_SIOC_DIR(cmd
) & _SIOC_WRITE
) {
129 if (get_user(val
, (unsigned int __user
*)arg
))
132 if (mdev
< SOUND_MIXER_NRDEVICES
)
133 vidc_mixer_set(mdev
, val
);
142 case SOUND_MIXER_RECSRC
:
146 case SOUND_MIXER_DEVMASK
:
147 val
= SOUND_MASK_VOLUME
| SOUND_MASK_PCM
| SOUND_MASK_SYNTH
;
150 case SOUND_MIXER_STEREODEVS
:
151 val
= SOUND_MASK_VOLUME
| SOUND_MASK_PCM
| SOUND_MASK_SYNTH
;
154 case SOUND_MIXER_RECMASK
:
158 case SOUND_MIXER_CAPS
:
163 if (mdev
< SOUND_MIXER_NRDEVICES
)
164 val
= vidc_level_l
[mdev
] | vidc_level_r
[mdev
] << 8;
169 return put_user(val
, (unsigned int __user
*)arg
) ? -EFAULT
: 0;
172 static unsigned int vidc_audio_set_format(int dev
, unsigned int fmt
)
180 vidc_audio_format
= fmt
;
181 vidc_update_filler(vidc_audio_format
, vidc_audio_channels
);
185 return vidc_audio_format
;
188 #define my_abs(i) ((i)<0 ? -(i) : (i))
190 static int vidc_audio_set_speed(int dev
, int rate
)
193 unsigned int hwctrl
, hwrate
, hwrate_ext
, rate_int
, rate_ext
;
194 unsigned int diff_int
, diff_ext
;
195 unsigned int newsize
, new2size
;
199 /* Using internal clock */
200 hwrate
= (((VIDC_SOUND_CLOCK
* 2) / rate
) + 1) >> 1;
206 /* Using exernal clock */
207 hwrate_ext
= (((VIDC_SOUND_CLOCK_EXT
* 2) / rate
) + 1) >> 1;
210 if (hwrate_ext
> 255)
213 rate_int
= VIDC_SOUND_CLOCK
/ hwrate
;
214 rate_ext
= VIDC_SOUND_CLOCK_EXT
/ hwrate_ext
;
216 /* Chose between external and internal clock */
217 diff_int
= my_abs(rate_ext
-rate
);
218 diff_ext
= my_abs(rate_int
-rate
);
219 if (diff_ext
< diff_int
) {
220 /*printk("VIDC: external %d %d %d\n", rate, rate_ext, hwrate_ext);*/
223 /* Allow roughly 0.4% tolerance */
224 if (diff_ext
> (rate
/256))
227 /*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/
229 /* Allow rougly 0.4% tolerance */
230 if (diff_int
> (rate
/256))
234 vidc_writel(0xb0000000 | (hwrate
- 2));
235 vidc_writel(0xb1000000 | hwctrl
);
237 newsize
= (10000 / hwrate
) & ~3;
242 for (new2size
= 128; new2size
< newsize
; new2size
<<= 1);
243 if (new2size
- newsize
> newsize
- (new2size
>> 1))
245 if (new2size
> 4096) {
246 printk(KERN_ERR
"VIDC: error: dma buffer (%d) %d > 4K\n",
250 /*printk("VIDC: dma size %d\n", new2size);*/
251 dma_bufsize
= new2size
;
252 vidc_audio_rate
= rate
;
254 return vidc_audio_rate
;
257 static short vidc_audio_set_channels(int dev
, short channels
)
264 vidc_audio_channels
= channels
;
265 vidc_update_filler(vidc_audio_format
, vidc_audio_channels
);
269 return vidc_audio_channels
;
275 static int vidc_audio_open(int dev
, int mode
)
277 /* This audio device does not have recording capability */
278 if (mode
== OPEN_READ
)
291 static void vidc_audio_close(int dev
)
297 * Output a block via DMA to sound device.
299 * We just set the DMA start and count; the DMA interrupt routine
300 * will take care of formatting the samples (via the appropriate
301 * vidc_filler routine), and flag via vidc_audio_dma_interrupt when
302 * more data is required.
305 vidc_audio_output_block(int dev
, unsigned long buf
, int total_count
, int one
)
307 struct dma_buffparms
*dmap
= audio_devs
[dev
]->dmap_out
;
310 local_irq_save(flags
);
311 dma_start
= buf
- (unsigned long)dmap
->raw_buf_phys
+ (unsigned long)dmap
->raw_buf
;
312 dma_count
= total_count
;
313 local_irq_restore(flags
);
317 vidc_audio_start_input(int dev
, unsigned long buf
, int count
, int intrflag
)
321 static int vidc_audio_prepare_for_input(int dev
, int bsize
, int bcount
)
326 static irqreturn_t
vidc_audio_dma_interrupt(void)
328 DMAbuf_outputintr(vidc_adev
, 1);
333 * Prepare for outputting samples.
335 * Each buffer that will be passed will be `bsize' bytes long,
336 * with a total of `bcount' buffers.
338 static int vidc_audio_prepare_for_output(int dev
, int bsize
, int bcount
)
340 struct audio_operations
*adev
= audio_devs
[dev
];
342 dma_interrupt
= NULL
;
343 adev
->dmap_out
->flags
|= DMA_NODMA
;
349 * Stop our current operation.
351 static void vidc_audio_reset(int dev
)
353 dma_interrupt
= NULL
;
356 static int vidc_audio_local_qlen(int dev
)
358 return /*dma_count !=*/ 0;
361 static void vidc_audio_trigger(int dev
, int enable_bits
)
363 struct audio_operations
*adev
= audio_devs
[dev
];
365 if (enable_bits
& PCM_ENABLE_OUTPUT
) {
366 if (!(adev
->flags
& DMA_ACTIVE
)) {
369 local_irq_save(flags
);
371 /* prevent recusion */
372 adev
->flags
|= DMA_ACTIVE
;
374 dma_interrupt
= vidc_audio_dma_interrupt
;
375 vidc_sound_dma_irq(0, NULL
);
376 iomd_writeb(DMA_CR_E
| 0x10, IOMD_SD0CR
);
378 local_irq_restore(flags
);
383 static struct audio_driver vidc_audio_driver
=
385 .owner
= THIS_MODULE
,
386 .open
= vidc_audio_open
,
387 .close
= vidc_audio_close
,
388 .output_block
= vidc_audio_output_block
,
389 .start_input
= vidc_audio_start_input
,
390 .prepare_for_input
= vidc_audio_prepare_for_input
,
391 .prepare_for_output
= vidc_audio_prepare_for_output
,
392 .halt_io
= vidc_audio_reset
,
393 .local_qlen
= vidc_audio_local_qlen
,
394 .trigger
= vidc_audio_trigger
,
395 .set_speed
= vidc_audio_set_speed
,
396 .set_bits
= vidc_audio_set_format
,
397 .set_channels
= vidc_audio_set_channels
400 static struct mixer_operations vidc_mixer_operations
= {
401 .owner
= THIS_MODULE
,
404 .ioctl
= vidc_mixer_ioctl
407 void vidc_update_filler(int format
, int channels
)
409 #define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3))
411 switch (TYPE(format
, channels
)) {
413 case TYPE(AFMT_U8
, 1):
414 vidc_filler
= vidc_fill_1x8_u
;
417 case TYPE(AFMT_U8
, 2):
418 vidc_filler
= vidc_fill_2x8_u
;
421 case TYPE(AFMT_S8
, 1):
422 vidc_filler
= vidc_fill_1x8_s
;
425 case TYPE(AFMT_S8
, 2):
426 vidc_filler
= vidc_fill_2x8_s
;
429 case TYPE(AFMT_S16_LE
, 1):
430 vidc_filler
= vidc_fill_1x16_s
;
433 case TYPE(AFMT_S16_LE
, 2):
434 vidc_filler
= vidc_fill_2x16_s
;
439 static void __init
attach_vidc(struct address_info
*hw_config
)
444 sprintf(name
, "VIDC %d-bit sound", hw_config
->card_subtype
);
445 conf_printf(name
, hw_config
);
446 memset(dma_buf
, 0, sizeof(dma_buf
));
448 adev
= sound_install_audiodrv(AUDIO_DRIVER_VERSION
, name
,
449 &vidc_audio_driver
, sizeof(vidc_audio_driver
),
450 DMA_AUTOMODE
, AFMT_U8
| AFMT_S8
| AFMT_S16_LE
,
451 NULL
, hw_config
->dma
, hw_config
->dma2
);
457 * 1024 bytes => 64 buffers
459 audio_devs
[adev
]->min_fragment
= 10;
460 audio_devs
[adev
]->mixer_dev
= num_mixers
;
462 audio_devs
[adev
]->mixer_dev
=
463 sound_install_mixer(MIXER_DRIVER_VERSION
,
464 name
, &vidc_mixer_operations
,
465 sizeof(vidc_mixer_operations
), NULL
);
467 if (audio_devs
[adev
]->mixer_dev
< 0)
470 for (i
= 0; i
< 2; i
++) {
471 dma_buf
[i
] = get_zeroed_page(GFP_KERNEL
);
473 printk(KERN_ERR
"%s: can't allocate required buffers\n",
477 dma_pbuf
[i
] = virt_to_phys((void *)dma_buf
[i
]);
480 if (sound_alloc_dma(hw_config
->dma
, hw_config
->name
)) {
481 printk(KERN_ERR
"%s: DMA %d is in use\n", name
, hw_config
->dma
);
485 if (request_irq(hw_config
->irq
, vidc_sound_dma_irq
, 0,
486 hw_config
->name
, &dma_start
)) {
487 printk(KERN_ERR
"%s: IRQ %d is in use\n", name
, hw_config
->irq
);
491 vidc_mixer_set(SOUND_MIXER_VOLUME
, (85 | 85 << 8));
493 #if defined(CONFIG_SOUND_SOFTOSS) || defined(CONFIG_SOUND_SOFTOSS_MODULE)
499 sound_free_dma(hw_config
->dma
);
502 for (i
= 0; i
< 2; i
++)
503 free_page(dma_buf
[i
]);
504 sound_unload_mixerdev(audio_devs
[adev
]->mixer_dev
);
506 sound_unload_audiodev(adev
);
511 static int __init
probe_vidc(struct address_info
*hw_config
)
513 hw_config
->irq
= IRQ_DMAS0
;
514 hw_config
->dma
= DMA_VIRTUAL_SOUND
;
515 hw_config
->dma2
= -1;
516 hw_config
->card_subtype
= 16;
517 hw_config
->name
= "VIDC20";
521 static void __exit
unload_vidc(struct address_info
*hw_config
)
523 int i
, adev
= vidc_adev
;
527 free_irq(hw_config
->irq
, &dma_start
);
528 sound_free_dma(hw_config
->dma
);
531 sound_unload_mixerdev(audio_devs
[adev
]->mixer_dev
);
532 sound_unload_audiodev(adev
);
533 for (i
= 0; i
< 2; i
++)
534 free_page(dma_buf
[i
]);
538 static struct address_info cfg
;
540 static int __init
init_vidc(void)
542 if (probe_vidc(&cfg
) == 0)
550 static void __exit
cleanup_vidc(void)
555 module_init(init_vidc
);
556 module_exit(cleanup_vidc
);
558 MODULE_AUTHOR("Russell King");
559 MODULE_DESCRIPTION("VIDC20 audio driver");
560 MODULE_LICENSE("GPL");