Linux Audio

Check our new training course

Loading...
v6.2
  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}
v6.13.7
  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}