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/gfp.h>
21 #include <linux/init.h>
22 #include <linux/module.h>
23 #include <linux/kernel.h>
24 #include <linux/interrupt.h>
26 #include <mach/hardware.h>
29 #include <asm/hardware/iomd.h>
31 #include <asm/system.h>
33 #include "sound_config.h"
37 #define _SIOC_TYPE(x) _IOC_TYPE(x)
40 #define _SIOC_NR(x) _IOC_NR(x)
43 #define VIDC_SOUND_CLOCK (250000)
44 #define VIDC_SOUND_CLOCK_EXT (176400)
47 * When using SERIAL SOUND mode (external DAC), the number of physical
48 * channels is fixed at 2.
52 static int vidc_audio_rate
;
53 static char vidc_audio_format
;
54 static char vidc_audio_channels
;
56 static unsigned char vidc_level_l
[SOUND_MIXER_NRDEVICES
] = {
69 static unsigned char vidc_level_r
[SOUND_MIXER_NRDEVICES
] = {
82 static unsigned int vidc_audio_volume_l
; /* left PCM vol, 0 - 65536 */
83 static unsigned int vidc_audio_volume_r
; /* right PCM vol, 0 - 65536 */
85 extern void vidc_update_filler(int bits
, int channels
);
86 extern int softoss_dev
;
89 vidc_mixer_set(int mdev
, unsigned int level
)
91 unsigned int lev_l
= level
& 0x007f;
92 unsigned int lev_r
= (level
& 0x7f00) >> 8;
93 unsigned int mlev_l
, mlev_r
;
100 #define SCALE(lev,master) ((lev) * (master) * 65536 / 10000)
102 mlev_l
= vidc_level_l
[SOUND_MIXER_VOLUME
];
103 mlev_r
= vidc_level_r
[SOUND_MIXER_VOLUME
];
106 case SOUND_MIXER_VOLUME
:
107 case SOUND_MIXER_PCM
:
108 vidc_level_l
[mdev
] = lev_l
;
109 vidc_level_r
[mdev
] = lev_r
;
111 vidc_audio_volume_l
= SCALE(lev_l
, mlev_l
);
112 vidc_audio_volume_r
= SCALE(lev_r
, mlev_r
);
113 /*printk("VIDC: PCM vol %05X %05X\n", vidc_audio_volume_l, vidc_audio_volume_r);*/
119 static int vidc_mixer_ioctl(int dev
, unsigned int cmd
, void __user
*arg
)
124 if (_SIOC_TYPE(cmd
) != 'M')
127 mdev
= _SIOC_NR(cmd
);
129 if (_SIOC_DIR(cmd
) & _SIOC_WRITE
) {
130 if (get_user(val
, (unsigned int __user
*)arg
))
133 if (mdev
< SOUND_MIXER_NRDEVICES
)
134 vidc_mixer_set(mdev
, val
);
143 case SOUND_MIXER_RECSRC
:
147 case SOUND_MIXER_DEVMASK
:
148 val
= SOUND_MASK_VOLUME
| SOUND_MASK_PCM
| SOUND_MASK_SYNTH
;
151 case SOUND_MIXER_STEREODEVS
:
152 val
= SOUND_MASK_VOLUME
| SOUND_MASK_PCM
| SOUND_MASK_SYNTH
;
155 case SOUND_MIXER_RECMASK
:
159 case SOUND_MIXER_CAPS
:
164 if (mdev
< SOUND_MIXER_NRDEVICES
)
165 val
= vidc_level_l
[mdev
] | vidc_level_r
[mdev
] << 8;
170 return put_user(val
, (unsigned int __user
*)arg
) ? -EFAULT
: 0;
173 static unsigned int vidc_audio_set_format(int dev
, unsigned int fmt
)
181 vidc_audio_format
= fmt
;
182 vidc_update_filler(vidc_audio_format
, vidc_audio_channels
);
186 return vidc_audio_format
;
189 #define my_abs(i) ((i)<0 ? -(i) : (i))
191 static int vidc_audio_set_speed(int dev
, int rate
)
194 unsigned int hwctrl
, hwrate
, hwrate_ext
, rate_int
, rate_ext
;
195 unsigned int diff_int
, diff_ext
;
196 unsigned int newsize
, new2size
;
200 /* Using internal clock */
201 hwrate
= (((VIDC_SOUND_CLOCK
* 2) / rate
) + 1) >> 1;
207 /* Using exernal clock */
208 hwrate_ext
= (((VIDC_SOUND_CLOCK_EXT
* 2) / rate
) + 1) >> 1;
211 if (hwrate_ext
> 255)
214 rate_int
= VIDC_SOUND_CLOCK
/ hwrate
;
215 rate_ext
= VIDC_SOUND_CLOCK_EXT
/ hwrate_ext
;
217 /* Chose between external and internal clock */
218 diff_int
= my_abs(rate_ext
-rate
);
219 diff_ext
= my_abs(rate_int
-rate
);
220 if (diff_ext
< diff_int
) {
221 /*printk("VIDC: external %d %d %d\n", rate, rate_ext, hwrate_ext);*/
224 /* Allow roughly 0.4% tolerance */
225 if (diff_ext
> (rate
/256))
228 /*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/
230 /* Allow rougly 0.4% tolerance */
231 if (diff_int
> (rate
/256))
235 vidc_writel(0xb0000000 | (hwrate
- 2));
236 vidc_writel(0xb1000000 | hwctrl
);
238 newsize
= (10000 / hwrate
) & ~3;
243 for (new2size
= 128; new2size
< newsize
; new2size
<<= 1);
244 if (new2size
- newsize
> newsize
- (new2size
>> 1))
246 if (new2size
> 4096) {
247 printk(KERN_ERR
"VIDC: error: dma buffer (%d) %d > 4K\n",
251 /*printk("VIDC: dma size %d\n", new2size);*/
252 dma_bufsize
= new2size
;
253 vidc_audio_rate
= rate
;
255 return vidc_audio_rate
;
258 static short vidc_audio_set_channels(int dev
, short channels
)
265 vidc_audio_channels
= channels
;
266 vidc_update_filler(vidc_audio_format
, vidc_audio_channels
);
270 return vidc_audio_channels
;
276 static int vidc_audio_open(int dev
, int mode
)
278 /* This audio device does not have recording capability */
279 if (mode
== OPEN_READ
)
292 static void vidc_audio_close(int dev
)
298 * Output a block via DMA to sound device.
300 * We just set the DMA start and count; the DMA interrupt routine
301 * will take care of formatting the samples (via the appropriate
302 * vidc_filler routine), and flag via vidc_audio_dma_interrupt when
303 * more data is required.
306 vidc_audio_output_block(int dev
, unsigned long buf
, int total_count
, int one
)
308 struct dma_buffparms
*dmap
= audio_devs
[dev
]->dmap_out
;
311 local_irq_save(flags
);
312 dma_start
= buf
- (unsigned long)dmap
->raw_buf_phys
+ (unsigned long)dmap
->raw_buf
;
313 dma_count
= total_count
;
314 local_irq_restore(flags
);
318 vidc_audio_start_input(int dev
, unsigned long buf
, int count
, int intrflag
)
322 static int vidc_audio_prepare_for_input(int dev
, int bsize
, int bcount
)
327 static irqreturn_t
vidc_audio_dma_interrupt(void)
329 DMAbuf_outputintr(vidc_adev
, 1);
334 * Prepare for outputting samples.
336 * Each buffer that will be passed will be `bsize' bytes long,
337 * with a total of `bcount' buffers.
339 static int vidc_audio_prepare_for_output(int dev
, int bsize
, int bcount
)
341 struct audio_operations
*adev
= audio_devs
[dev
];
343 dma_interrupt
= NULL
;
344 adev
->dmap_out
->flags
|= DMA_NODMA
;
350 * Stop our current operation.
352 static void vidc_audio_reset(int dev
)
354 dma_interrupt
= NULL
;
357 static int vidc_audio_local_qlen(int dev
)
359 return /*dma_count !=*/ 0;
362 static void vidc_audio_trigger(int dev
, int enable_bits
)
364 struct audio_operations
*adev
= audio_devs
[dev
];
366 if (enable_bits
& PCM_ENABLE_OUTPUT
) {
367 if (!(adev
->dmap_out
->flags
& DMA_ACTIVE
)) {
370 local_irq_save(flags
);
372 /* prevent recusion */
373 adev
->dmap_out
->flags
|= DMA_ACTIVE
;
375 dma_interrupt
= vidc_audio_dma_interrupt
;
376 vidc_sound_dma_irq(0, NULL
);
377 iomd_writeb(DMA_CR_E
| 0x10, IOMD_SD0CR
);
379 local_irq_restore(flags
);
384 static struct audio_driver vidc_audio_driver
=
386 .owner
= THIS_MODULE
,
387 .open
= vidc_audio_open
,
388 .close
= vidc_audio_close
,
389 .output_block
= vidc_audio_output_block
,
390 .start_input
= vidc_audio_start_input
,
391 .prepare_for_input
= vidc_audio_prepare_for_input
,
392 .prepare_for_output
= vidc_audio_prepare_for_output
,
393 .halt_io
= vidc_audio_reset
,
394 .local_qlen
= vidc_audio_local_qlen
,
395 .trigger
= vidc_audio_trigger
,
396 .set_speed
= vidc_audio_set_speed
,
397 .set_bits
= vidc_audio_set_format
,
398 .set_channels
= vidc_audio_set_channels
401 static struct mixer_operations vidc_mixer_operations
= {
402 .owner
= THIS_MODULE
,
405 .ioctl
= vidc_mixer_ioctl
408 void vidc_update_filler(int format
, int channels
)
410 #define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3))
412 switch (TYPE(format
, channels
)) {
414 case TYPE(AFMT_U8
, 1):
415 vidc_filler
= vidc_fill_1x8_u
;
418 case TYPE(AFMT_U8
, 2):
419 vidc_filler
= vidc_fill_2x8_u
;
422 case TYPE(AFMT_S8
, 1):
423 vidc_filler
= vidc_fill_1x8_s
;
426 case TYPE(AFMT_S8
, 2):
427 vidc_filler
= vidc_fill_2x8_s
;
430 case TYPE(AFMT_S16_LE
, 1):
431 vidc_filler
= vidc_fill_1x16_s
;
434 case TYPE(AFMT_S16_LE
, 2):
435 vidc_filler
= vidc_fill_2x16_s
;
440 static void __init
attach_vidc(struct address_info
*hw_config
)
445 sprintf(name
, "VIDC %d-bit sound", hw_config
->card_subtype
);
446 conf_printf(name
, hw_config
);
447 memset(dma_buf
, 0, sizeof(dma_buf
));
449 adev
= sound_install_audiodrv(AUDIO_DRIVER_VERSION
, name
,
450 &vidc_audio_driver
, sizeof(vidc_audio_driver
),
451 DMA_AUTOMODE
, AFMT_U8
| AFMT_S8
| AFMT_S16_LE
,
452 NULL
, hw_config
->dma
, hw_config
->dma2
);
458 * 1024 bytes => 64 buffers
460 audio_devs
[adev
]->min_fragment
= 10;
461 audio_devs
[adev
]->mixer_dev
= num_mixers
;
463 audio_devs
[adev
]->mixer_dev
=
464 sound_install_mixer(MIXER_DRIVER_VERSION
,
465 name
, &vidc_mixer_operations
,
466 sizeof(vidc_mixer_operations
), NULL
);
468 if (audio_devs
[adev
]->mixer_dev
< 0)
471 for (i
= 0; i
< 2; i
++) {
472 dma_buf
[i
] = get_zeroed_page(GFP_KERNEL
);
474 printk(KERN_ERR
"%s: can't allocate required buffers\n",
478 dma_pbuf
[i
] = virt_to_phys((void *)dma_buf
[i
]);
481 if (sound_alloc_dma(hw_config
->dma
, hw_config
->name
)) {
482 printk(KERN_ERR
"%s: DMA %d is in use\n", name
, hw_config
->dma
);
486 if (request_irq(hw_config
->irq
, vidc_sound_dma_irq
, 0,
487 hw_config
->name
, &dma_start
)) {
488 printk(KERN_ERR
"%s: IRQ %d is in use\n", name
, hw_config
->irq
);
492 vidc_mixer_set(SOUND_MIXER_VOLUME
, (85 | 85 << 8));
497 sound_free_dma(hw_config
->dma
);
500 for (i
= 0; i
< 2; i
++)
501 free_page(dma_buf
[i
]);
502 sound_unload_mixerdev(audio_devs
[adev
]->mixer_dev
);
504 sound_unload_audiodev(adev
);
509 static int __init
probe_vidc(struct address_info
*hw_config
)
511 hw_config
->irq
= IRQ_DMAS0
;
512 hw_config
->dma
= DMA_VIRTUAL_SOUND
;
513 hw_config
->dma2
= -1;
514 hw_config
->card_subtype
= 16;
515 hw_config
->name
= "VIDC20";
519 static void __exit
unload_vidc(struct address_info
*hw_config
)
521 int i
, adev
= vidc_adev
;
525 free_irq(hw_config
->irq
, &dma_start
);
526 sound_free_dma(hw_config
->dma
);
529 sound_unload_mixerdev(audio_devs
[adev
]->mixer_dev
);
530 sound_unload_audiodev(adev
);
531 for (i
= 0; i
< 2; i
++)
532 free_page(dma_buf
[i
]);
536 static struct address_info cfg
;
538 static int __init
init_vidc(void)
540 if (probe_vidc(&cfg
) == 0)
548 static void __exit
cleanup_vidc(void)
553 module_init(init_vidc
);
554 module_exit(cleanup_vidc
);
556 MODULE_AUTHOR("Russell King");
557 MODULE_DESCRIPTION("VIDC20 audio driver");
558 MODULE_LICENSE("GPL");