2 * a.lp_mp3 - VS1011B driver for Fonera
3 * Copyright (c) 2007 phrozen.org - John Crispin <john@phrozen.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19 * Feedback, Bugs.... mail john@phrozen.org
23 #include <linux/module.h>
24 #include <linux/sched.h>
25 #include <linux/slab.h>
26 #include <linux/ioport.h>
27 #include <linux/errno.h>
28 #include <linux/kernel.h>
30 #include <linux/string.h>
31 #include <linux/poll.h>
32 #include <linux/init.h>
33 #include <linux/interrupt.h>
34 #include <linux/delay.h>
37 #include <asm/system.h>
39 #include "ar531xlnx.h"
41 #define AR5315_DSLBASE 0xB1000000
42 #define AR5315_GPIO_DI (AR5315_DSLBASE + 0x0088)
43 #define AR5315_GPIO_DO (AR5315_DSLBASE + 0x0090)
44 #define AR5315_GPIO_CR (AR5315_DSLBASE + 0x0098)
45 #define AR5315_GPIO_INT (AR5315_DSLBASE + 0x00a0)
55 #define DREQ ((unsigned int)GPIO_7)
56 #define SCK ((unsigned int)GPIO_1)
57 #define SI ((unsigned int)GPIO_4)
58 #define BSYNC ((unsigned int)GPIO_3)
59 #define CS ((unsigned int)GPIO_0)
60 #define SO ((unsigned int)GPIO_6)
61 #define RES ((unsigned int)GPIO_2)
64 #define REG_STATUS 0x1
66 #define REG_CLOCKF 0x3
67 #define REG_DECODETIME 0x4
68 #define REG_AUDATA 0x5
70 #define REG_WRAMADDR 0x7
73 #define REG_A1ADDR 0xa
75 #define REG_A1CTRL0 0xc
76 #define REG_A1CTRL1 0xd
77 #define REG_A1CTRL2 0xe
79 #define VS1011_NEEDS_DATA spi_get_bit(DREQ)
80 #define VS1011_NEEDS_NO_DATA (spi_get_bit(DREQ)== 0x00)
81 #define VS1011_WHILE_NEEDS_NO_DATA while(spi_get_bit(DREQ)== 0x00){}
83 #define VS_CS_LO spi_clear_bit(CS)
84 #define VS_CS_HI spi_set_bit(CS)
86 #define VS_BSYNC_LO spi_clear_bit(BSYNC)
87 #define VS_BSYNC_HI spi_set_bit(BSYNC)
89 #define VS_RESET_LO spi_clear_bit(RES)
90 #define VS_RESET_HI spi_set_bit(RES)
92 #define VS1011_READ SPI_io_vs1011b(0x03)
93 #define VS1011_WRITE SPI_io_vs1011b(0x02)
95 void msDelay(int ms) {
100 for (i=0;i<33084;i++) {
107 int spi_get_bit(unsigned int pin){
108 return ((sysRegRead(AR5315_GPIO_DI)&pin)?(1):(0));
111 void spi_set_bit(unsigned int pin){
112 sysRegWrite(AR5315_GPIO_DO, (sysRegRead(AR5315_GPIO_DO) | pin));
115 void spi_clear_bit(unsigned int pin){
116 sysRegWrite(AR5315_GPIO_DO, (sysRegRead(AR5315_GPIO_DO) & ~pin));
119 void SPI_clock_vs1011b(void){
124 unsigned char SPI_io_vs1011b(unsigned char byte){
126 unsigned char this_bit;
127 unsigned char byte_out = 0;
128 for(i = 7; i>=0; i--){
140 byte_out += spi_get_bit(SO)<<i;
145 void SPI_init_vs1011(void){
146 sysRegWrite(AR5315_GPIO_CR, (sysRegRead(AR5315_GPIO_CR) | SI | SCK | CS | BSYNC | RES) & ~(SO|DREQ));
153 void VS1011_send_SCI(unsigned char reg, unsigned int data){
157 SPI_io_vs1011b((data>>8)&0xff);
158 SPI_io_vs1011b(data&0xff);
162 unsigned int VS1011_read_SCI(unsigned char reg){
168 data = SPI_io_vs1011b(0x00);
170 data += SPI_io_vs1011b(0x00);
175 void VS1011_send_SDI(unsigned char byte){
178 for(i = 7; i>=0; i--){
191 void VS1011_send_SDI_32(unsigned char* data){
193 VS1011_WHILE_NEEDS_NO_DATA;
195 VS1011_send_SDI(data[i]);
199 void VS1011_send_zeros(unsigned char count){
201 VS1011_send_SDI(0x0);
206 void VS1011_set_volume(unsigned int vol){
207 VS1011_send_SCI(REG_VOL, vol);
210 void VS1011_SW_reset(unsigned int _crystal_freq){
211 unsigned int regval = 0x0804;
212 unsigned long int i = 0;
214 VS1011_send_zeros(32);
215 VS1011_send_SCI(REG_MODE, regval);
217 while((VS1011_NEEDS_NO_DATA) && (i++<0xffff)){};
218 VS1011_send_SCI(REG_CLOCKF, _crystal_freq);
219 VS1011_send_zeros(16);
220 VS1011_set_volume(0x00);
223 void VS1011_HW_reset(void){
231 void VS1011_init(unsigned int _crystal_freq, unsigned char hw){
235 printk("mp3_drv.ko : Init start\n");
239 VS1011_SW_reset(_crystal_freq);
240 printk("mp3_drv.ko : init_ok\n");
243 void VS1011_sine(unsigned char state, unsigned char freq){
244 VS1011_send_zeros(16);
246 VS1011_send_SDI(0x53);
247 VS1011_send_SDI(0xEF);
248 VS1011_send_SDI(0x6E);
249 VS1011_send_SDI(freq);
250 VS1011_send_zeros(0x04);
252 VS1011_send_SDI(0x45);
253 VS1011_send_SDI(0x78);
254 VS1011_send_SDI(0x69);
255 VS1011_send_SDI(0x74);
256 VS1011_send_zeros(0x04);
260 unsigned int VS1011_get_volume(void){
261 return VS1011_read_SCI(REG_VOL);
264 unsigned int VS1011_get_decode_time(void){
265 return VS1011_read_SCI(REG_DECODETIME);
268 const unsigned int sample_rate_values[] = {0, 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000};
270 void VS1011_get_audio_data(AUDIO_DATA* audio){
271 unsigned int audata = VS1011_read_SCI(REG_AUDATA);
272 audio->sample_rate = sample_rate_values[(audata&0x1E00)>>9];
273 audio->bitrate = audata&0x1FF;
274 audio->is_stereo = (audata&0x8000)>>15;
277 void VS1011_print_registers(void){
279 for(i = 0; i< 14; i++){
280 unsigned int regval = VS1011_read_SCI(i);
281 printk("mp3_drv.ko : %d \n", regval);
285 void VS1011_volume(unsigned char left, unsigned char right){
286 unsigned int regval = left;
289 VS1011_send_SCI(REG_VOL, regval);
292 void VS1011_set_bass(unsigned int regval){
293 VS1011_send_SCI(REG_BASS, regval);
296 void VS1011_set_reg(unsigned int reg, unsigned int regval){
297 VS1011_send_SCI(reg, regval);
303 printk("%u\n", *R_GEN_CONFIG);
304 VS1001_init(_crystal_freq);
305 VS1001_print_registers();
306 VS1001_volume(0x30, 0x30);
308 VS1001_sine(1, 0x30);
311 VS1001_send_zeros(0x20);
313 VS1001_sine(1, 0x30);
316 VS1001_send_zeros(0x20);
318 VS1001_sine(1, 0x30);
323 VS1001_get_audio_data(&a);
324 printk("mp3_drv.ko : rate : %d, bit : %d, stereo : %d \n", a.sample_rate, a.bitrate, a.is_stereo);
325 VS1001_SW_reset(_crystal_freq);