Sansa AMS: Time has shown that switching between 16 and 32bit mode costs much time...
[kugel-rb.git] / firmware / target / arm / as3525 / ascodec-as3525.c
blob3019ffdd15da9404a9c75bf8b00c86d38e4f431d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Bertrik Sikken
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 Provides access to the codec/charger/rtc/adc part of the as3525.
24 This part is on address 0x46 of the internal i2c bus in the as3525.
25 Registers in the codec part seem to be nearly identical to the registers
26 in the AS3514 (used in the "v1" versions of the sansa c200 and e200).
28 I2C register description:
29 * I2C2_CNTRL needs to be set to 0x51 for transfers to work at all.
30 bit 0: ? possibly related to using ACKs during transfers
31 bit 1: direction of transfer (0 = write, 1 = read)
32 bit 2: use 2-byte slave address
33 * I2C2_IMR, I2C2_RIS, I2C2_MIS, I2C2_INT_CLR interrupt bits:
34 bit 2: byte read interrupt
35 bit 3: byte write interrupt
36 bit 4: ? possibly some kind of error status
37 bit 7: ACK error
38 * I2C2_SR (status register) indicates in bit 0 if a transfer is busy.
39 * I2C2_SLAD0 contains the i2c slave address to read from / write to.
40 * I2C2_CPSR0/1 is the divider from the peripheral clock to the i2c clock.
41 * I2C2_DACNT sets the number of bytes to transfer and actually starts it.
43 When a transfer is attempted to a non-existing i2c slave address,
44 interrupt bit 7 is raised and DACNT is not decremented after the transfer.
47 #include "ascodec-target.h"
48 #include "clock-target.h"
49 #include "kernel.h"
50 #include "as3525.h"
51 #include "i2c.h"
53 #define I2C2_DATA *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x00))
54 #define I2C2_SLAD0 *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x04))
55 #define I2C2_CNTRL *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x0C))
56 #define I2C2_DACNT *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x10))
57 #define I2C2_CPSR0 *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x1C))
58 #define I2C2_CPSR1 *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x20))
59 #define I2C2_IMR *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x24))
60 #define I2C2_RIS *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x28))
61 #define I2C2_MIS *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x2C))
62 #define I2C2_SR *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x30))
63 #define I2C2_INT_CLR *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x40))
64 #define I2C2_SADDR *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x44))
66 static struct mutex as_mtx;
68 void i2c_init(void)
72 /* initialises the internal i2c bus and prepares for transfers to the codec */
73 void ascodec_init(void)
75 int prescaler;
77 /* enable clock */
78 CGU_PERI |= CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE;
80 /* prescaler for i2c clock */
81 prescaler = AS3525_I2C_PRESCALER;
82 I2C2_CPSR0 = prescaler & 0xFF; /* 8 lsb */
83 I2C2_CPSR1 = (prescaler >> 8) & 0x3; /* 2 msb */
85 /* set i2c slave address of codec part */
86 I2C2_SLAD0 = AS3514_I2C_ADDR << 1;
88 I2C2_CNTRL = 0x51;
90 mutex_init(&as_mtx);
94 /* returns != 0 when busy */
95 static int i2c_busy(void)
97 return (I2C2_SR & 1);
100 /* returns 0 on success, <0 otherwise */
101 int ascodec_write(unsigned int index, unsigned int value)
103 ascodec_lock();
105 /* wait if still busy */
106 while (i2c_busy());
108 if (index == AS3514_CVDD_DCDC3) {
109 /* prevent setting of the LREG_CP_not bit */
110 value &= ~(1 << 5);
113 /* start transfer */
114 I2C2_SADDR = index;
115 I2C2_CNTRL &= ~(1 << 1);
116 I2C2_DATA = value;
117 I2C2_DACNT = 1;
119 /* wait for transfer */
120 while (I2C2_DACNT != 0);
122 ascodec_unlock();
124 return 0;
128 /* returns value read on success, <0 otherwise */
129 int ascodec_read(unsigned int index)
131 int data;
133 ascodec_lock();
135 /* wait if still busy */
136 while (i2c_busy());
138 /* start transfer */
139 I2C2_SADDR = index;
140 I2C2_CNTRL |= (1 << 1);
141 I2C2_DACNT = 1;
143 /* wait for transfer*/
144 while (I2C2_DACNT != 0);
145 data = I2C2_DATA;
147 ascodec_unlock();
149 return data;
152 int ascodec_readbytes(int index, int len, unsigned char *data)
154 int i;
156 ascodec_lock();
158 for(i=0; i<len; i++)
160 int temp = ascodec_read(index+i);
161 if(temp == -1)
162 break;
163 else
164 data[i] = temp;
167 ascodec_unlock();
169 return i;
172 void ascodec_lock(void)
174 mutex_lock(&as_mtx);
177 void ascodec_unlock(void)
179 mutex_unlock(&as_mtx);