blob: 768fb8293fc9068b343a451849b5e66dc36ecde9 [file] [log] [blame]
Bertrik Sikken95726a52008-10-26 13:28:52 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +00008 * $Id$
Bertrik Sikken95726a52008-10-26 13:28:52 +00009 *
10 * Copyright (C) 2008 by Bertrik Sikken
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22/*
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).
27
28 I2C register description:
29 * I2C2_CNTRL needs to be set to 0x51 for transfers to work at all.
30 bit 1 indicates direction of transfer (0 = write, 1 = read)
31 * I2C2_SR (status register) indicates in bit 0 if a transfer is busy.
32 * I2C2_SLAD0 contains the i2c slave address to read from / write to.
33 * I2C2_CPSR0/1 is the divider from the peripheral clock to the i2c clock.
34 * I2C2_DACNT sets the number of bytes to transfer and actually starts it.
35
36 When a transfer is attempted to a non-existing i2c slave address,
37 interrupt bit 7 is raised and DACNT is not decremented after the transfer.
38 */
39
Rafaël Carré22c450a2008-11-10 19:53:12 +000040#include "ascodec-target.h"
Rafaël Carré45711ac2008-12-04 20:04:31 +000041#include "clock-target.h"
Rafaël Carré02dfae02008-11-10 20:55:56 +000042#include "kernel.h"
Bertrik Sikken95726a52008-10-26 13:28:52 +000043#include "as3525.h"
44
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +000045#define I2C2_DATA *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x00))
46#define I2C2_SLAD0 *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x04))
47#define I2C2_CNTRL *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x0C))
48#define I2C2_DACNT *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x10))
49#define I2C2_CPSR0 *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x1C))
50#define I2C2_CPSR1 *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x20))
Bertrik Sikken95726a52008-10-26 13:28:52 +000051#define I2C2_IMR *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x24))
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +000052#define I2C2_RIS *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x28))
53#define I2C2_MIS *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x2C))
54#define I2C2_SR *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x30))
55#define I2C2_INT_CLR *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x40))
Bertrik Sikken95726a52008-10-26 13:28:52 +000056#define I2C2_SADDR *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x44))
57
Rafaël Carré02dfae02008-11-10 20:55:56 +000058static struct mutex as_mtx SHAREDBSS_ATTR;
Bertrik Sikken95726a52008-10-26 13:28:52 +000059
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +000060/* initialises the internal i2c bus and prepares for transfers to the codec */
Bertrik Sikken4ca4e522008-11-09 09:25:53 +000061void ascodec_init(void)
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +000062{
Bertrik Sikken95726a52008-10-26 13:28:52 +000063 /* reset device */
64 CCU_SRC = CCU_SRC_I2C_AUDIO_EN;
65 CCU_SRL = CCU_SRL_MAGIC_NUMBER;
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +000066 CCU_SRL = 0;
67
Bertrik Sikken95726a52008-10-26 13:28:52 +000068 /* enable clock */
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +000069 CGU_PERI |= CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE;
Bertrik Sikken95726a52008-10-26 13:28:52 +000070
71 /* prescaler for i2c clock */
Rafaël Carré45711ac2008-12-04 20:04:31 +000072 I2C2_CPSR0 = CLK_DIV(AS3525_PCLK_FREQ, AS3525_I2C_FREQ);
Bertrik Sikken95726a52008-10-26 13:28:52 +000073 I2C2_CPSR1 = 0; /* MSB */
74
75 /* set i2c slave address of codec part */
Rafaël Carré22c450a2008-11-10 19:53:12 +000076 I2C2_SLAD0 = AS3514_I2C_ADDR << 1;
Bertrik Sikken95726a52008-10-26 13:28:52 +000077
78 I2C2_CNTRL = 0x51;
Bertrik Sikken763aacc2008-11-23 12:24:47 +000079
80 mutex_init(&as_mtx);
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +000081}
Bertrik Sikken95726a52008-10-26 13:28:52 +000082
Bertrik Sikken95726a52008-10-26 13:28:52 +000083
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +000084/* returns != 0 when busy */
85static int i2c_busy(void)
86{
87 return (I2C2_SR & 1);
88}
89
90
91/* returns 0 on success, <0 otherwise */
Rafaël Carré02dfae02008-11-10 20:55:56 +000092int ascodec_write(unsigned int index, unsigned int value)
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +000093{
Bertrik Sikken763aacc2008-11-23 12:24:47 +000094 int retval;
95
96 ascodec_lock();
97
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +000098 /* check if still busy */
Bertrik Sikken95726a52008-10-26 13:28:52 +000099 if (i2c_busy()) {
Bertrik Sikken763aacc2008-11-23 12:24:47 +0000100 retval = -1;
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +0000101 }
Bertrik Sikken763aacc2008-11-23 12:24:47 +0000102 else {
103 if (index == AS3514_CVDD_DCDC3) {
104 /* prevent setting of the LREG_CP_not bit */
105 value &= ~(1 << 5);
106 }
107
108 /* start transfer */
109 I2C2_SADDR = index;
110 I2C2_CNTRL &= ~(1 << 1);
111 I2C2_DATA = value;
112 I2C2_DACNT = 1;
113
114 /* wait for transfer*/
115 while (i2c_busy());
116
117 retval = 0;
118 }
Bertrik Sikken95726a52008-10-26 13:28:52 +0000119
Bertrik Sikken763aacc2008-11-23 12:24:47 +0000120 ascodec_unlock();
121
122 return retval;
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +0000123}
124
Bertrik Sikken95726a52008-10-26 13:28:52 +0000125
126/* returns value read on success, <0 otherwise */
Rafaël Carré02dfae02008-11-10 20:55:56 +0000127int ascodec_read(unsigned int index)
Bertrik Sikken95726a52008-10-26 13:28:52 +0000128{
Bertrik Sikken763aacc2008-11-23 12:24:47 +0000129 int data;
130
131 ascodec_lock();
132
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +0000133 /* check if still busy */
134 if (i2c_busy()) {
Bertrik Sikken763aacc2008-11-23 12:24:47 +0000135 data = -1;
136 }
137 else {
138 /* start transfer */
139 I2C2_SADDR = index;
140 I2C2_CNTRL |= (1 << 1);
141 I2C2_DACNT = 1;
142
143 /* wait for transfer*/
144 while (i2c_busy());
145
146 data = I2C2_DATA;
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +0000147 }
Bertrik Sikken95726a52008-10-26 13:28:52 +0000148
Bertrik Sikken763aacc2008-11-23 12:24:47 +0000149 ascodec_unlock();
Bertrik Sikken95726a52008-10-26 13:28:52 +0000150
Bertrik Sikken763aacc2008-11-23 12:24:47 +0000151 return data;
Bertrik Sikkene5d72ac2008-10-26 21:21:55 +0000152}
Bertrik Sikken95726a52008-10-26 13:28:52 +0000153
Rafaël Carré02dfae02008-11-10 20:55:56 +0000154int ascodec_readbytes(int index, int len, unsigned char *data)
155{
156 int i;
157
158 ascodec_lock();
159
160 for(i=0; i<len; i++)
161 {
162 int temp = ascodec_read(index+i);
163 if(temp == -1)
164 break;
165 else
166 data[i] = temp;
167 }
168
169 ascodec_unlock();
170
171 return i;
172}
173
174void ascodec_lock(void)
175{
176 mutex_lock(&as_mtx);
177}
178
179void ascodec_unlock(void)
180{
181 mutex_unlock(&as_mtx);
182}