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