Commit 7e03417a authored by Peter Teichmann's avatar Peter Teichmann Committed by Russell King

[ARM PATCH] 1718/1: vidc.c: remove vidc_mksound, add external reference clock

Patch from Peter Teichmann

vidc_mksound causes the kernel to crash badly when executed. As it does not do anything useful I did not take the time to find out why, but removed it.

The vidc does have an external reference clock that is used to generate 44100/20050/10025kHz sample rates. The code is changed in a way that it uses that reference clock that can better approximate the desired clock.

If we can approximate the desired rate to more than 1/256 accuracy, we return the desired rate instead of the real rate. This is to assist using some programs that for instance believe they need exacly 8kHz which we can not have, but we can have 8.018kHz which is pretty close so that nobody would notice the difference.
parent b2570560
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#endif #endif
#define VIDC_SOUND_CLOCK (250000) #define VIDC_SOUND_CLOCK (250000)
#define VIDC_SOUND_CLOCK_EXT (176400)
/* /*
* When using SERIAL SOUND mode (external DAC), the number of physical * When using SERIAL SOUND mode (external DAC), the number of physical
...@@ -81,17 +82,9 @@ static unsigned char vidc_level_r[SOUND_MIXER_NRDEVICES] = { ...@@ -81,17 +82,9 @@ static unsigned char vidc_level_r[SOUND_MIXER_NRDEVICES] = {
static unsigned int vidc_audio_volume_l; /* left PCM vol, 0 - 65536 */ static unsigned int vidc_audio_volume_l; /* left PCM vol, 0 - 65536 */
static unsigned int vidc_audio_volume_r; /* right PCM vol, 0 - 65536 */ static unsigned int vidc_audio_volume_r; /* right PCM vol, 0 - 65536 */
static void (*old_mksound)(unsigned int hz, unsigned int ticks);
extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
extern void vidc_update_filler(int bits, int channels); extern void vidc_update_filler(int bits, int channels);
extern int softoss_dev; extern int softoss_dev;
static void
vidc_mksound(unsigned int hz, unsigned int ticks)
{
// printk("BEEP - %d %d!\n", hz, ticks);
}
static void static void
vidc_mixer_set(int mdev, unsigned int level) vidc_mixer_set(int mdev, unsigned int level)
{ {
...@@ -193,28 +186,50 @@ static unsigned int vidc_audio_set_format(int dev, unsigned int fmt) ...@@ -193,28 +186,50 @@ static unsigned int vidc_audio_set_format(int dev, unsigned int fmt)
return vidc_audio_format; return vidc_audio_format;
} }
#define my_abs(i) ((i)<0 ? -(i) : (i))
static int vidc_audio_set_speed(int dev, int rate) static int vidc_audio_set_speed(int dev, int rate)
{ {
if (rate) { if (rate) {
unsigned int hwctrl, hwrate; unsigned int hwctrl, hwrate, hwrate_ext, rate_int, rate_ext;
unsigned int diff_int, diff_ext;
unsigned int newsize, new2size; unsigned int newsize, new2size;
/* hwctrl = 0x00000003;
* If we have selected 44.1kHz, use the DAC clock.
*/ /* Using internal clock */
if (0 && rate == 44100) { hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
hwctrl = 0x00000002; if (hwrate < 3)
hwrate = 3; hwrate = 3;
if (hwrate > 255)
hwrate = 255;
/* Using exernal clock */
hwrate_ext = (((VIDC_SOUND_CLOCK_EXT * 2) / rate) + 1) >> 1;
if (hwrate_ext < 3)
hwrate_ext = 3;
if (hwrate_ext > 255)
hwrate_ext = 255;
rate_int = VIDC_SOUND_CLOCK / hwrate;
rate_ext = VIDC_SOUND_CLOCK_EXT / hwrate_ext;
/* Chose between external and internal clock */
diff_int = my_abs(rate_ext-rate);
diff_ext = my_abs(rate_int-rate);
if (diff_ext < diff_int) {
/*printk("VIDC: external %d %d %d\n", rate, rate_ext, hwrate_ext);*/
hwrate=hwrate_ext;
hwctrl=0x00000002;
/* Allow roughly 0.4% tolerance */
if (diff_ext > (rate/256))
rate=rate_ext;
} else { } else {
hwctrl = 0x00000003; /*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/
hwctrl=0x00000003;
hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1; /* Allow rougly 0.4% tolerance */
if (hwrate < 3) if (diff_int > (rate/256))
hwrate = 3; rate=rate_int;
if (hwrate > 255)
hwrate = 255;
rate = VIDC_SOUND_CLOCK / hwrate;
} }
vidc_writel(0xb0000000 | (hwrate - 2)); vidc_writel(0xb0000000 | (hwrate - 2));
...@@ -226,13 +241,14 @@ static int vidc_audio_set_speed(int dev, int rate) ...@@ -226,13 +241,14 @@ static int vidc_audio_set_speed(int dev, int rate)
if (newsize > 4096) if (newsize > 4096)
newsize = 4096; newsize = 4096;
for (new2size = 128; new2size < newsize; new2size <<= 1); for (new2size = 128; new2size < newsize; new2size <<= 1);
if (new2size - newsize > newsize - (new2size >> 1)) if (new2size - newsize > newsize - (new2size >> 1))
new2size >>= 1; new2size >>= 1;
if (new2size > 4096) { if (new2size > 4096) {
printk(KERN_ERR "VIDC: error: dma buffer (%d) %d > 4K\n", printk(KERN_ERR "VIDC: error: dma buffer (%d) %d > 4K\n",
newsize, new2size); newsize, new2size);
new2size = 4096; new2size = 4096;
} }
/*printk("VIDC: dma size %d\n", new2size);*/
dma_bufsize = new2size; dma_bufsize = new2size;
vidc_audio_rate = rate; vidc_audio_rate = rate;
} }
...@@ -471,8 +487,6 @@ static void __init attach_vidc(struct address_info *hw_config) ...@@ -471,8 +487,6 @@ static void __init attach_vidc(struct address_info *hw_config)
printk(KERN_ERR "%s: IRQ %d is in use\n", name, hw_config->irq); printk(KERN_ERR "%s: IRQ %d is in use\n", name, hw_config->irq);
goto irq_failed; goto irq_failed;
} }
old_mksound = kd_mksound;
kd_mksound = vidc_mksound;
vidc_adev = adev; vidc_adev = adev;
vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8)); vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8));
...@@ -510,9 +524,6 @@ static void __exit unload_vidc(struct address_info *hw_config) ...@@ -510,9 +524,6 @@ static void __exit unload_vidc(struct address_info *hw_config)
vidc_adev = -1; vidc_adev = -1;
if (old_mksound)
kd_mksound = old_mksound;
free_irq(hw_config->irq, &dma_start); free_irq(hw_config->irq, &dma_start);
sound_free_dma(hw_config->dma); sound_free_dma(hw_config->dma);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment