blob: d50398039162766dc8fd09830bdbb7cebeb2f84f [file] [log] [blame]
Jörg Hohensohn8f8fbac2004-10-15 21:41:46 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 * Physical interface of the Philips TEA5767 in Archos Ondio
10 *
Jörg Hohensohn4adf9292004-10-17 23:24:18 +000011 * Copyright (C) 2002 by Linus Nielsen Feltzing
Jörg Hohensohn8f8fbac2004-10-15 21:41:46 +000012 *
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20#include "lcd.h"
21#include "sh7034.h"
22#include "kernel.h"
23#include "thread.h"
24#include "debug.h"
25#include "system.h"
26
27#ifdef CONFIG_TUNER
28
Jörg Hohensohn4adf9292004-10-17 23:24:18 +000029
30/* cute little functions, atomic read-modify-write */
31/* SDA is PB4 */
32#define SDA_LO and_b(~0x10, &PBDRL)
33#define SDA_HI or_b(0x10, &PBDRL)
34#define SDA_INPUT and_b(~0x10, &PBIORL)
35#define SDA_OUTPUT or_b(0x10, &PBIORL)
36#define SDA (PBDR & 0x0010)
37
38/* SCL is PB1 */
39#define SCL_INPUT and_b(~0x02, &PBIORL)
40#define SCL_OUTPUT or_b(0x02, &PBIORL)
41#define SCL_LO and_b(~0x02, &PBDRL)
42#define SCL_HI or_b(0x02, &PBDRL)
43#define SCL (PBDR & 0x0002)
44
45/* arbitrary delay loop */
46#define DELAY do { int _x; for(_x=0;_x<20;_x++);} while (0)
47
48
49static void fmradio_i2c_start(void)
Jörg Hohensohn8f8fbac2004-10-15 21:41:46 +000050{
Jörg Hohensohn4adf9292004-10-17 23:24:18 +000051 SDA_OUTPUT;
52 SDA_HI;
53 SCL_HI;
54 SDA_LO;
55 DELAY;
56 SCL_LO;
Jörg Hohensohn8f8fbac2004-10-15 21:41:46 +000057}
58
Jörg Hohensohn4adf9292004-10-17 23:24:18 +000059static void fmradio_i2c_stop(void)
Jörg Hohensohn8f8fbac2004-10-15 21:41:46 +000060{
Jörg Hohensohn4adf9292004-10-17 23:24:18 +000061 SDA_LO;
62 SCL_HI;
63 DELAY;
64 SDA_HI;
65}
66
67
68static void fmradio_i2c_ack(int bit)
69{
70 /* Here's the deal. The slave is slow, and sometimes needs to wait
71 before it can receive the acknowledge. Therefore it forces the clock
72 low until it is ready. We need to poll the clock line until it goes
73 high before we release the ack. */
74
75 SCL_LO; /* Set the clock low */
76 if ( bit )
77 {
78 SDA_HI;
79 }
80 else
81 {
82 SDA_LO;
83 }
84
85 SCL_INPUT; /* Set the clock to input */
86 while(!SCL) /* and wait for the slave to release it */
87 sleep_thread();
88 wake_up_thread();
89
90 DELAY;
91 SCL_OUTPUT;
92 SCL_LO;
93}
94
95static int fmradio_i2c_getack(void)
96{
97 int ret = 1;
98
99 /* Here's the deal. The slave is slow, and sometimes needs to wait
100 before it can send the acknowledge. Therefore it forces the clock
101 low until it is ready. We need to poll the clock line until it goes
102 high before we read the ack. */
103
104 SDA_INPUT; /* And set to input */
105 SCL_INPUT; /* Set the clock to input */
106 while(!SCL) /* and wait for the slave to release it */
107 sleep_thread();
108 wake_up_thread();
109
110 if (SDA)
111 /* ack failed */
112 ret = 0;
113
114 SCL_OUTPUT;
115 SCL_LO;
116 SDA_HI;
117 SDA_OUTPUT;
118 return ret;
119}
120
121static void fmradio_i2c_outb(unsigned char byte)
122{
123 int i;
124
125 /* clock out each bit, MSB first */
126 for ( i=0x80; i; i>>=1 ) {
127 if ( i & byte )
128 {
129 SDA_HI;
130 }
131 else
132 {
133 SDA_LO;
134 }
135 SCL_HI;
136 SCL_LO;
137 }
138
139 SDA_HI;
140}
141
142static unsigned char fmradio_i2c_inb(int ack)
143{
144 int i;
145 unsigned char byte = 0;
146
147 /* clock in each bit, MSB first */
148 for ( i=0x80; i; i>>=1 ) {
149 SDA_INPUT; /* And set to input */
150 SCL_HI;
151 if ( SDA )
152 byte |= i;
153 SCL_LO;
154 SDA_OUTPUT;
155 }
156
157 fmradio_i2c_ack(ack);
158
159 return byte;
160}
161
162int fmradio_i2c_write(int address, const unsigned char* buf, int count)
163{
164 int i,x=0;
165
166 fmradio_i2c_start();
167 fmradio_i2c_outb(address & 0xfe);
168 if (fmradio_i2c_getack())
169 {
170 for (i=0; i<count; i++)
171 {
172 fmradio_i2c_outb(buf[i]);
173 if (!fmradio_i2c_getack())
174 {
175 x=-2;
176 break;
177 }
178 }
179 }
180 else
181 {
182 debugf("fmradio_i2c_write() - no ack\n");
183 x=-1;
184 }
185 fmradio_i2c_stop();
186 return x;
187}
188
189int fmradio_i2c_read(int address, unsigned char* buf, int count)
190{
191 int i,x=0;
192
193 fmradio_i2c_start();
194 fmradio_i2c_outb(address | 1);
195 if (fmradio_i2c_getack()) {
196 for (i=0; i<count; i++) {
197 buf[i] = fmradio_i2c_inb(0);
198 }
199 }
200 else
201 x=-1;
202 fmradio_i2c_stop();
203 return x;
Jörg Hohensohn8f8fbac2004-10-15 21:41:46 +0000204}
205
206#endif