diff options
| author | wdenk <wdenk> | 2002-11-03 00:24:07 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2002-11-03 00:24:07 +0000 | 
| commit | c609719b8d1b2dca590e0ed499016d041203e403 (patch) | |
| tree | 7ea1755d80903ff972f312a249eb856061d40e15 /board/gen860t/beeper.c | |
| parent | 5b1d713721c3ea02549940133f09236783dda1f9 (diff) | |
| download | olio-uboot-2014.01-c609719b8d1b2dca590e0ed499016d041203e403.tar.xz olio-uboot-2014.01-c609719b8d1b2dca590e0ed499016d041203e403.zip | |
Initial revision
Diffstat (limited to 'board/gen860t/beeper.c')
| -rw-r--r-- | board/gen860t/beeper.c | 213 | 
1 files changed, 213 insertions, 0 deletions
| diff --git a/board/gen860t/beeper.c b/board/gen860t/beeper.c new file mode 100644 index 000000000..46fe66ba6 --- /dev/null +++ b/board/gen860t/beeper.c @@ -0,0 +1,213 @@ +/* + * (C) Copyright 2002 + * Keith Outwater, keith_outwater@mvis.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc8xx.h> +#include <asm/8xx_immap.h> +#include <linux/ctype.h> + +/* + * Basic beeper support for the GEN860T board.  The GEN860T includes + * an audio sounder driven by a Phillips TDA8551 amplifier.  The + * TDA8551 features a digital volume control which uses a "trinary" + * input (high/high-Z/low) to set volume.  The 860's SPKROUT pin + * drives the amplifier input. + */ + + +/* + * Initialize beeper-related hardware. Initialize timer 1 for use with + * the beeper. Use 66 Mhz internal clock with prescale of 33 to get + * 1 uS period per count. + * FIXME: we should really compute the prescale based on the reported + * core clock frequency. + */ +void +init_beeper(void) +{ +    volatile immap_t *immap  = (immap_t *)CFG_IMMR; + +	immap->im_cpmtimer.cpmt_tgcr &= ~TGCR_RST1 | TGCR_STP1; +	immap->im_cpmtimer.cpmt_tmr1 = ((33 << TMR_PS_SHIFT) & TMR_PS_MSK) +								 | TMR_OM | TMR_FRR | TMR_ICLK_IN_GEN; +	immap->im_cpmtimer.cpmt_tcn1 = 0; +	immap->im_cpmtimer.cpmt_ter1 = 0xffff; +	immap->im_cpmtimer.cpmt_tgcr |= TGCR_RST1; +} + + +/* + * Set beeper frequency.  Max allowed frequency is 2.5 KHz.  This limit + * is mostly arbitrary, but the beeper isn't really much good beyond this + * frequency. + */ +void +set_beeper_frequency(uint frequency) +{ +#define FREQ_LIMIT	2500 + +    volatile immap_t *immap  = (immap_t *)CFG_IMMR; + +	/* +	 * Compute timer ticks given desired frequency.  The timer is set up +	 * to count 0.5 uS per tick and it takes two ticks per cycle (Hz). +	 */ +	if (frequency > FREQ_LIMIT) frequency = FREQ_LIMIT; +	frequency = 1000000/frequency; +	immap->im_cpmtimer.cpmt_trr1 = (ushort)frequency; +} + + +/* + * Turn the beeper on + */ +void +beeper_on(void) +{ +    volatile immap_t *immap  = (immap_t *)CFG_IMMR; + +	immap->im_cpmtimer.cpmt_tgcr &= ~TGCR_STP1; +} + + +/* + * Turn the beeper off + */ +void +beeper_off(void) +{ +    volatile immap_t *immap  = (immap_t *)CFG_IMMR; + +	immap->im_cpmtimer.cpmt_tgcr |= TGCR_STP1; +} + + +/* + * Increase or decrease the beeper volume.  Volume can be set + * from off to full in 64 steps.  To increase volume, the output + * pin is actively driven high, then returned to tristate. + * To decrease volume, output a low on the port pin (no need to + * change pin mode to tristate) then output a high to go back to + * tristate. + */ +void +set_beeper_volume(int steps) +{ +    volatile immap_t *immap  = (immap_t *)CFG_IMMR; +	int i; + +	if (steps >= 0) { +		for (i = 0; i < (steps >= 64 ? 64 : steps); i++) { +			immap->im_cpm.cp_pbodr &= ~(0x80000000 >> 19); +			udelay(1); +			immap->im_cpm.cp_pbodr |= (0x80000000 >> 19); +			udelay(1); +		} +	} +	else { +		for (i = 0; i > (steps <= -64 ? -64 : steps); i--) { +			immap->im_cpm.cp_pbdat &= ~(0x80000000 >> 19); +			udelay(1); +			immap->im_cpm.cp_pbdat |= (0x80000000 >> 19); +			udelay(1); +		} +	} +} + + +/* + * Check the environment to see if the beeper needs beeping. + * Controlled by a sequence of the form: + * freq/delta volume/on time/off time;... where: + * freq 		= frequency in Hz (0 - 2500) + * delta volume = volume steps up or down (-64 <= vol <= 64) + * on time		= time in mS + * off time		= time in mS + * + * Return 1 on success, 0 on failure + */ +int +do_beeper(char *sequence) +{ +#define DELIMITER	';' + +int args[4]; +int i; +int val; +char *p = sequence; +char *tp; + +	/* +	 * Parse the control sequence.  This is a really simple parser +	 * without any real error checking.  You can probably blow it +	 * up really easily. +	 */ +	if (*p == '\0' || !isdigit(*p)) { +		printf("%s:%d: null or invalid string (%s)\n", +				__FILE__, __LINE__, p); +		return 0; +	} + +	i = 0; +	while (*p != '\0') { +		while (*p != DELIMITER) { +			if (i > 3) i = 0; +			val = (int) simple_strtol(p, &tp, 0); +			if (tp == p) { +				printf("%s:%d: no digits or bad format\n", +								__FILE__,__LINE__); +				return 0; +			} +			else { +				args[i] = val; +			} + +			i++; +			if (*tp == DELIMITER) +				p = tp; +			else +				p = ++tp; +		} +		p++; + +		/* +		 * Well, we got something that has a chance of being correct +		 */ +#if 0 +		for (i = 0; i < 4; i++) { +			printf("%s:%d:arg %d = %d\n", __FILE__, __LINE__, i, args[i]); +		} +		printf("\n"); +#endif + +		set_beeper_frequency(args[0]); +		set_beeper_volume(args[1]); +		beeper_on(); +		udelay(1000 * args[2]); +		beeper_off(); +		udelay(1000 * args[3]); +	} +	return 1; +} + +/* vim: set ts=4 sw=4 tw=78: */ |