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);