Linux Audio

Check our new training course

Loading...
v3.1
  1/*
  2 * linux/arch/m68k/amiga/amisound.c
  3 *
  4 * amiga sound driver for Linux/m68k
  5 *
  6 * This file is subject to the terms and conditions of the GNU General Public
  7 * License.  See the file COPYING in the main directory of this archive
  8 * for more details.
  9 */
 10
 11#include <linux/jiffies.h>
 12#include <linux/timer.h>
 13#include <linux/init.h>
 14#include <linux/string.h>
 15#include <linux/module.h>
 16
 17#include <asm/system.h>
 18#include <asm/amigahw.h>
 19
 20static unsigned short *snd_data;
 21static const signed char sine_data[] = {
 22	0,  39,  75,  103,  121,  127,  121,  103,  75,  39,
 23	0, -39, -75, -103, -121, -127, -121, -103, -75, -39
 24};
 25#define DATA_SIZE	ARRAY_SIZE(sine_data)
 26
 27#define custom amiga_custom
 28
 29    /*
 30     * The minimum period for audio may be modified by the frame buffer
 31     * device since it depends on htotal (for OCS/ECS/AGA)
 32     */
 33
 34volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
 35EXPORT_SYMBOL(amiga_audio_min_period);
 36
 37#define MAX_PERIOD	(65535)
 38
 39
 40    /*
 41     *	Current period (set by dmasound.c)
 42     */
 43
 44unsigned short amiga_audio_period = MAX_PERIOD;
 45EXPORT_SYMBOL(amiga_audio_period);
 46
 47static unsigned long clock_constant;
 48
 49void __init amiga_init_sound(void)
 50{
 51	static struct resource beep_res = { .name = "Beep" };
 52
 53	snd_data = amiga_chip_alloc_res(sizeof(sine_data), &beep_res);
 54	if (!snd_data) {
 55		printk (KERN_CRIT "amiga init_sound: failed to allocate chipmem\n");
 56		return;
 57	}
 58	memcpy (snd_data, sine_data, sizeof(sine_data));
 59
 60	/* setup divisor */
 61	clock_constant = (amiga_colorclock+DATA_SIZE/2)/DATA_SIZE;
 62
 63	/* without amifb, turn video off and enable high quality sound */
 64#ifndef CONFIG_FB_AMIGA
 65	amifb_video_off();
 66#endif
 67}
 68
 69static void nosound( unsigned long ignored );
 70static DEFINE_TIMER(sound_timer, nosound, 0, 0);
 71
 72void amiga_mksound( unsigned int hz, unsigned int ticks )
 73{
 74	unsigned long flags;
 75
 76	if (!snd_data)
 77		return;
 78
 79	local_irq_save(flags);
 80	del_timer( &sound_timer );
 81
 82	if (hz > 20 && hz < 32767) {
 83		unsigned long period = (clock_constant / hz);
 84
 85		if (period < amiga_audio_min_period)
 86			period = amiga_audio_min_period;
 87		if (period > MAX_PERIOD)
 88			period = MAX_PERIOD;
 89
 90		/* setup pointer to data, period, length and volume */
 91		custom.aud[2].audlc = snd_data;
 92		custom.aud[2].audlen = sizeof(sine_data)/2;
 93		custom.aud[2].audper = (unsigned short)period;
 94		custom.aud[2].audvol = 32; /* 50% of maxvol */
 95
 96		if (ticks) {
 97			sound_timer.expires = jiffies + ticks;
 98			add_timer( &sound_timer );
 99		}
100
101		/* turn on DMA for audio channel 2 */
102		custom.dmacon = DMAF_SETCLR | DMAF_AUD2;
103
104	} else
105		nosound( 0 );
106
107	local_irq_restore(flags);
108}
109
110
111static void nosound( unsigned long ignored )
112{
113	/* turn off DMA for audio channel 2 */
114	custom.dmacon = DMAF_AUD2;
115	/* restore period to previous value after beeping */
116	custom.aud[2].audper = amiga_audio_period;
117}
v5.4
  1/*
  2 * linux/arch/m68k/amiga/amisound.c
  3 *
  4 * amiga sound driver for Linux/m68k
  5 *
  6 * This file is subject to the terms and conditions of the GNU General Public
  7 * License.  See the file COPYING in the main directory of this archive
  8 * for more details.
  9 */
 10
 11#include <linux/jiffies.h>
 12#include <linux/timer.h>
 13#include <linux/init.h>
 14#include <linux/string.h>
 15#include <linux/module.h>
 16
 
 17#include <asm/amigahw.h>
 18
 19static unsigned short *snd_data;
 20static const signed char sine_data[] = {
 21	0,  39,  75,  103,  121,  127,  121,  103,  75,  39,
 22	0, -39, -75, -103, -121, -127, -121, -103, -75, -39
 23};
 24#define DATA_SIZE	ARRAY_SIZE(sine_data)
 25
 26#define custom amiga_custom
 27
 28    /*
 29     * The minimum period for audio may be modified by the frame buffer
 30     * device since it depends on htotal (for OCS/ECS/AGA)
 31     */
 32
 33volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
 34EXPORT_SYMBOL(amiga_audio_min_period);
 35
 36#define MAX_PERIOD	(65535)
 37
 38
 39    /*
 40     *	Current period (set by dmasound.c)
 41     */
 42
 43unsigned short amiga_audio_period = MAX_PERIOD;
 44EXPORT_SYMBOL(amiga_audio_period);
 45
 46static unsigned long clock_constant;
 47
 48void __init amiga_init_sound(void)
 49{
 50	static struct resource beep_res = { .name = "Beep" };
 51
 52	snd_data = amiga_chip_alloc_res(sizeof(sine_data), &beep_res);
 53	if (!snd_data) {
 54		pr_crit("amiga init_sound: failed to allocate chipmem\n");
 55		return;
 56	}
 57	memcpy (snd_data, sine_data, sizeof(sine_data));
 58
 59	/* setup divisor */
 60	clock_constant = (amiga_colorclock+DATA_SIZE/2)/DATA_SIZE;
 61
 62	/* without amifb, turn video off and enable high quality sound */
 63#ifndef CONFIG_FB_AMIGA
 64	amifb_video_off();
 65#endif
 66}
 67
 68static void nosound(struct timer_list *unused);
 69static DEFINE_TIMER(sound_timer, nosound);
 70
 71void amiga_mksound( unsigned int hz, unsigned int ticks )
 72{
 73	unsigned long flags;
 74
 75	if (!snd_data)
 76		return;
 77
 78	local_irq_save(flags);
 79	del_timer( &sound_timer );
 80
 81	if (hz > 20 && hz < 32767) {
 82		unsigned long period = (clock_constant / hz);
 83
 84		if (period < amiga_audio_min_period)
 85			period = amiga_audio_min_period;
 86		if (period > MAX_PERIOD)
 87			period = MAX_PERIOD;
 88
 89		/* setup pointer to data, period, length and volume */
 90		custom.aud[2].audlc = snd_data;
 91		custom.aud[2].audlen = sizeof(sine_data)/2;
 92		custom.aud[2].audper = (unsigned short)period;
 93		custom.aud[2].audvol = 32; /* 50% of maxvol */
 94
 95		if (ticks) {
 96			sound_timer.expires = jiffies + ticks;
 97			add_timer( &sound_timer );
 98		}
 99
100		/* turn on DMA for audio channel 2 */
101		custom.dmacon = DMAF_SETCLR | DMAF_AUD2;
102
103	} else
104		nosound( 0 );
105
106	local_irq_restore(flags);
107}
108
109
110static void nosound(struct timer_list *unused)
111{
112	/* turn off DMA for audio channel 2 */
113	custom.dmacon = DMAF_AUD2;
114	/* restore period to previous value after beeping */
115	custom.aud[2].audper = amiga_audio_period;
116}