diff options
Diffstat (limited to 'package/fonera-mp3-drv/src/vs10xx.c')
-rw-r--r-- | package/fonera-mp3-drv/src/vs10xx.c | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/package/fonera-mp3-drv/src/vs10xx.c b/package/fonera-mp3-drv/src/vs10xx.c new file mode 100644 index 000000000..e7b7f68c1 --- /dev/null +++ b/package/fonera-mp3-drv/src/vs10xx.c @@ -0,0 +1,328 @@ +/* + * a.lp_mp3 - VS1011B driver for Fonera + * Copyright (c) 2007 phrozen.org - John Crispin <john@phrozen.org> + * + * 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, MA02111-1307USA + * + * Feedback, Bugs.... mail john@phrozen.org + * + */ + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/ioport.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/string.h> +#include <linux/poll.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/delay.h> + +#include <asm/io.h> +#include <asm/system.h> +#include <asm/irq.h> +#include "ar531xlnx.h" + +#define AR5315_DSLBASE 0xB1000000 +#define AR5315_GPIO_DI (AR5315_DSLBASE + 0x0088) +#define AR5315_GPIO_DO (AR5315_DSLBASE + 0x0090) +#define AR5315_GPIO_CR (AR5315_DSLBASE + 0x0098) +#define AR5315_GPIO_INT (AR5315_DSLBASE + 0x00a0) + +#define GPIO_0 1<<0 +#define GPIO_1 1<<1 +#define GPIO_2 1<<2 +#define GPIO_3 1<<3 +#define GPIO_4 1<<4 +#define GPIO_6 1<<6 +#define GPIO_7 1<<7 + +#define DREQ ((unsigned int)GPIO_7) +#define SCK ((unsigned int)GPIO_1) +#define SI ((unsigned int)GPIO_4) +#define BSYNC ((unsigned int)GPIO_3) +#define CS ((unsigned int)GPIO_0) +#define SO ((unsigned int)GPIO_6) +#define RES ((unsigned int)GPIO_2) + +#define REG_MODE 0x0 +#define REG_STATUS 0x1 +#define REG_BASS 0x2 +#define REG_CLOCKF 0x3 +#define REG_DECODETIME 0x4 +#define REG_AUDATA 0x5 +#define REG_WRAM 0x6 +#define REG_WRAMADDR 0x7 +#define REG_HDAT0 0x8 +#define REG_HDAT1 0x9 +#define REG_A1ADDR 0xa +#define REG_VOL 0xb +#define REG_A1CTRL0 0xc +#define REG_A1CTRL1 0xd +#define REG_A1CTRL2 0xe + +#define VS1011_NEEDS_DATA spi_get_bit(DREQ) +#define VS1011_NEEDS_NO_DATA (spi_get_bit(DREQ)== 0x00) +#define VS1011_WHILE_NEEDS_NO_DATA while(spi_get_bit(DREQ)== 0x00){} + +#define VS_CS_LO spi_clear_bit(CS) +#define VS_CS_HI spi_set_bit(CS) + +#define VS_BSYNC_LO spi_clear_bit(BSYNC) +#define VS_BSYNC_HI spi_set_bit(BSYNC) + +#define VS_RESET_LO spi_clear_bit(RES) +#define VS_RESET_HI spi_set_bit(RES) + +#define VS1011_READ SPI_io_vs1011b(0x03) +#define VS1011_WRITE SPI_io_vs1011b(0x02) + +void msDelay(int ms) { + int i,a; + int delayvar=10; + + for (a=0;a<ms;a++) { + for (i=0;i<33084;i++) { + delayvar*=2; + delayvar/=2; + } + } +} + +int spi_get_bit(unsigned int pin){ + return ((sysRegRead(AR5315_GPIO_DI)&pin)?(1):(0)); +} + +void spi_set_bit(unsigned int pin){ + sysRegWrite(AR5315_GPIO_DO, (sysRegRead(AR5315_GPIO_DO) | pin)); +} + +void spi_clear_bit(unsigned int pin){ + sysRegWrite(AR5315_GPIO_DO, (sysRegRead(AR5315_GPIO_DO) & ~pin)); +} + +void SPI_clock_vs1011b(void){ + spi_clear_bit(SCK); + spi_set_bit(SCK); +} + +unsigned char SPI_io_vs1011b(unsigned char byte){ + int i; + unsigned char this_bit; + unsigned char byte_out = 0; + for(i = 7; i>=0; i--){ + if(byte & (1<<i)){ + this_bit = 1; + } else { + this_bit = 0; + } + if(this_bit){ + spi_set_bit(SI); + } else { + spi_clear_bit(SI); + } + SPI_clock_vs1011b(); + byte_out += spi_get_bit(SO)<<i; + } + return byte_out; +} + +void SPI_init_vs1011(void){ + sysRegWrite(AR5315_GPIO_CR, (sysRegRead(AR5315_GPIO_CR) | SI | SCK | CS | BSYNC | RES) & ~(SO|DREQ)); + spi_clear_bit(SCK); + spi_clear_bit(SI); + VS_CS_HI; + VS_BSYNC_HI; +} + +void VS1011_send_SCI(unsigned char reg, unsigned int data){ + VS_CS_LO; + VS1011_WRITE; + SPI_io_vs1011b(reg); + SPI_io_vs1011b((data>>8)&0xff); + SPI_io_vs1011b(data&0xff); + VS_CS_HI; +} + +unsigned int VS1011_read_SCI(unsigned char reg){ + unsigned int data; + VS_CS_LO; + VS1011_READ; + SPI_io_vs1011b(reg); + data = 0; + data = SPI_io_vs1011b(0x00); + data <<= 8; + data += SPI_io_vs1011b(0x00); + VS_CS_HI; + return data; +} + +void VS1011_send_SDI(unsigned char byte){ + int i; + VS_BSYNC_LO; + for(i = 7; i>=0; i--){ + if(byte & (1<<i)){ + spi_set_bit(SI); + + } else { + spi_clear_bit(SI); + } + spi_clear_bit(SCK); + spi_set_bit(SCK); + } + VS_BSYNC_HI; +} + +void VS1011_send_SDI_32(unsigned char* data){ + int i; + VS1011_WHILE_NEEDS_NO_DATA; + for(i=0; i<32; i++){ + VS1011_send_SDI(data[i]); + } +} + +void VS1011_send_zeros(unsigned char count){ + do{ + VS1011_send_SDI(0x0); + count--; + }while(count); +} + +void VS1011_set_volume(unsigned int vol){ + VS1011_send_SCI(REG_VOL, vol); +} + +void VS1011_SW_reset(unsigned int _crystal_freq){ + unsigned int regval = 0x0804; + unsigned long int i = 0; + msDelay(100); + VS1011_send_zeros(32); + VS1011_send_SCI(REG_MODE, regval); + msDelay(10); + while((VS1011_NEEDS_NO_DATA) && (i++<0xffff)){}; + VS1011_send_SCI(REG_CLOCKF, _crystal_freq); + VS1011_send_zeros(16); + VS1011_set_volume(0x00); +} + +void VS1011_HW_reset(void){ + + VS_RESET_LO; + msDelay(1); + VS_RESET_HI; + msDelay(1); +} + +void VS1011_init(unsigned int _crystal_freq, unsigned char hw){ + if(hw){ + SPI_init_vs1011(); + } + printk("mp3_drv.ko : Init start\n"); + if(hw){ + VS1011_HW_reset(); + } + VS1011_SW_reset(_crystal_freq); + printk("mp3_drv.ko : init_ok\n"); +} + +void VS1011_sine(unsigned char state, unsigned char freq){ + VS1011_send_zeros(16); + if(state == 0x01){ + VS1011_send_SDI(0x53); + VS1011_send_SDI(0xEF); + VS1011_send_SDI(0x6E); + VS1011_send_SDI(freq); + VS1011_send_zeros(0x04); + } else { + VS1011_send_SDI(0x45); + VS1011_send_SDI(0x78); + VS1011_send_SDI(0x69); + VS1011_send_SDI(0x74); + VS1011_send_zeros(0x04); + } +} + +unsigned int VS1011_get_volume(void){ + return VS1011_read_SCI(REG_VOL); +} + +unsigned int VS1011_get_decode_time(void){ + return VS1011_read_SCI(REG_DECODETIME); +} + +const unsigned int sample_rate_values[] = {0, 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000}; + +void VS1011_get_audio_data(AUDIO_DATA* audio){ + unsigned int audata = VS1011_read_SCI(REG_AUDATA); + audio->sample_rate = sample_rate_values[(audata&0x1E00)>>9]; + audio->bitrate = audata&0x1FF; + audio->is_stereo = (audata&0x8000)>>15; +} + +void VS1011_print_registers(void){ + unsigned char i; + for(i = 0; i< 14; i++){ + unsigned int regval = VS1011_read_SCI(i); + printk("mp3_drv.ko : %d \n", regval); + } +} + +void VS1011_volume(unsigned char left, unsigned char right){ + unsigned int regval = left; + regval <<=8; + regval += right; + VS1011_send_SCI(REG_VOL, regval); +} + +void VS1011_set_bass(unsigned int regval){ + VS1011_send_SCI(REG_BASS, regval); +} + +void VS1011_set_reg(unsigned int reg, unsigned int regval){ + VS1011_send_SCI(reg, regval); +} + +/* +int vs_test(void) { + SPI_init_vs1011(); + printk("%u\n", *R_GEN_CONFIG); + VS1001_init(_crystal_freq); + VS1001_print_registers(); + VS1001_volume(0x30, 0x30); + msDelay(1000); + VS1001_sine(1, 0x30); + msDelay(1000); + VS1001_sine(0, 0); + VS1001_send_zeros(0x20); + msDelay(1000); + VS1001_sine(1, 0x30); + msDelay(1000); + VS1001_sine(0, 0); + VS1001_send_zeros(0x20); + msDelay(1000); + VS1001_sine(1, 0x30); + msDelay(1000); + VS1001_sine(0, 0); + + AUDIO_DATA a; + VS1001_get_audio_data(&a); + printk("mp3_drv.ko : rate : %d, bit : %d, stereo : %d \n", a.sample_rate, a.bitrate, a.is_stereo); + VS1001_SW_reset(_crystal_freq); + return 0; +}*/ + |