summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2006-07-21 08:42:28 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2006-07-21 08:42:28 +0000
commited4d7a33bdeba5ce11512ee617398a2840797203 (patch)
tree1027077148ace8e13c8fa49ae3794b2038a2d67a
parente8818efbe9c814ad3b46ee0e5d0ae250b7c96cf4 (diff)
downloadrockbox-ed4d7a33bdeba5ce11512ee617398a2840797203.tar.gz
rockbox-ed4d7a33bdeba5ce11512ee617398a2840797203.zip
Patch #5347 by Rani Hod - Adds FM radio and recording features to the iAudio X5.
Also includes a rewrite of the Coldfire I2C driver to include both read and write. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10272 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/main.c4
-rw-r--r--apps/recorder/radio.c57
-rw-r--r--apps/recorder/recording.c16
-rw-r--r--firmware/drivers/fmradio_i2c.c17
-rw-r--r--firmware/drivers/i2c-coldfire.c229
-rw-r--r--firmware/drivers/tlv320.c119
-rw-r--r--firmware/drivers/uda1380.c26
-rw-r--r--firmware/export/config-iaudiox5.h7
-rw-r--r--firmware/export/fmradio_i2c.h4
-rw-r--r--firmware/export/i2c-coldfire.h10
-rw-r--r--firmware/export/sound.h2
-rw-r--r--firmware/export/tlv320.h3
-rw-r--r--firmware/pcm_record.c83
-rw-r--r--firmware/sound.c25
-rw-r--r--firmware/target/coldfire/iaudio/x5/power-x5.c14
15 files changed, 449 insertions, 167 deletions
diff --git a/apps/main.c b/apps/main.c
index 4f31cdb58a..8ee6adfe4f 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -72,7 +72,7 @@
72#else 72#else
73#define pcmbuf_init() 73#define pcmbuf_init()
74#endif 74#endif
75#if (defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)) && !defined(SIMULATOR) 75#if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
76#include "pcm_record.h" 76#include "pcm_record.h"
77#define SETTINGS_RESET BUTTON_REC 77#define SETTINGS_RESET BUTTON_REC
78#endif 78#endif
@@ -425,7 +425,7 @@ void init(void)
425 talk_init(); 425 talk_init();
426 426
427 audio_init(); 427 audio_init();
428#if (defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)) && !defined(SIMULATOR) 428#if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
429 pcm_rec_init(); 429 pcm_rec_init();
430#endif 430#endif
431 431
diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c
index 291079b4b0..a29620b46c 100644
--- a/apps/recorder/radio.c
+++ b/apps/recorder/radio.c
@@ -64,7 +64,13 @@
64#ifdef CONFIG_TUNER 64#ifdef CONFIG_TUNER
65 65
66#if CONFIG_CODEC == SWCODEC 66#if CONFIG_CODEC == SWCODEC
67#ifdef HAVE_UDA1380
67#include "uda1380.h" 68#include "uda1380.h"
69#endif
70#ifdef HAVE_TLV320
71#include "tlv320.h"
72#endif
73
68#include "pcm_record.h" 74#include "pcm_record.h"
69#endif 75#endif
70 76
@@ -109,6 +115,35 @@
109#define FM_STOP BUTTON_OFF 115#define FM_STOP BUTTON_OFF
110#define FM_RC_STOP BUTTON_RC_STOP 116#define FM_RC_STOP BUTTON_RC_STOP
111 117
118#elif (CONFIG_KEYPAD == IAUDIO_X5_PAD)
119/* pause/play - short PLAY */
120#define FM_PLAY_PRE BUTTON_PLAY
121#define FM_RC_PLAY_PRE BUTTON_RC_PLAY
122#define FM_PLAY (BUTTON_PLAY | BUTTON_REL)
123#define FM_RC_PLAY (BUTTON_RC_PLAY | BUTTON_REL)
124/* preset/scan mode - long PLAY */
125#define FM_MODE (BUTTON_PLAY | BUTTON_REPEAT)
126#define FM_RC_MODE (BUTTON_RC_PLAY | BUTTON_REPEAT)
127/* preset menu - short SELECT */
128#define FM_PRESET_PRE BUTTON_SELECT
129#define FM_RC_PRESET_PRE BUTTON_RC_MENU
130#define FM_PRESET (BUTTON_SELECT | BUTTON_REL)
131#define FM_RC_PRESET (BUTTON_RC_MENU | BUTTON_REL)
132/* fm menu - long SELECT */
133#define FM_MENU (BUTTON_SELECT | BUTTON_REPEAT)
134#define FM_RC_MENU (BUTTON_RC_MENU | BUTTON_REPEAT)
135/* main menu(exit radio while playing) - REC */
136#define FM_EXIT_PRE BUTTON_REC
137#define FM_EXIT (BUTTON_REC | BUTTON_REL)
138#define FM_RC_EXIT_PRE BUTTON_RC_MODE
139#define FM_RC_EXIT (BUTTON_RC_MODE | BUTTON_REL)
140/* prev/next preset on the remote - REW/FF */
141#define FM_NEXT_PRESET (BUTTON_RC_FF | BUTTON_REL)
142#define FM_PREV_PRESET (BUTTON_RC_REW | BUTTON_REL)
143/* stop and exit radio - ON */
144#define FM_STOP BUTTON_POWER
145#define FM_RC_STOP (BUTTON_RC_MODE | BUTTON_REPEAT)
146
112#elif CONFIG_KEYPAD == ONDIO_PAD /* restricted keypad */ 147#elif CONFIG_KEYPAD == ONDIO_PAD /* restricted keypad */
113#define FM_MENU (BUTTON_MENU | BUTTON_REPEAT) 148#define FM_MENU (BUTTON_MENU | BUTTON_REPEAT)
114#define FM_RECORD_DBLPRE BUTTON_MENU 149#define FM_RECORD_DBLPRE BUTTON_MENU
@@ -158,7 +193,7 @@ int radio_get(int setting);
158#if CONFIG_TUNER == S1A0903X01 /* FM recorder */ 193#if CONFIG_TUNER == S1A0903X01 /* FM recorder */
159#define radio_set samsung_set 194#define radio_set samsung_set
160#define radio_get samsung_get 195#define radio_get samsung_get
161#elif CONFIG_TUNER == TEA5767 /* Iriver */ 196#elif CONFIG_TUNER == TEA5767 /* iriver, iaudio */
162#define radio_set philips_set 197#define radio_set philips_set
163#define radio_get philips_get 198#define radio_get philips_get
164#elif CONFIG_TUNER == (S1A0903X01 | TEA5767) /* OndioFM */ 199#elif CONFIG_TUNER == (S1A0903X01 | TEA5767) /* OndioFM */
@@ -387,8 +422,15 @@ bool radio_screen(void)
387 422
388#else 423#else
389 peak_meter_enabled = false; 424 peak_meter_enabled = false;
425
426#ifdef HAVE_UDA1380
390 uda1380_enable_recording(false); 427 uda1380_enable_recording(false);
391 uda1380_set_monitor(true); 428 uda1380_set_monitor(true);
429#elif defined(HAVE_TLV320)
430 //tlv320_enable_recording(false);
431 tlv320_set_recvol(23, 23, AUDIO_GAIN_LINEIN); /* 0dB */
432 tlv320_set_monitor(true);
433#endif
392 434
393 /* Set the input multiplexer to FM */ 435 /* Set the input multiplexer to FM */
394 pcm_rec_mux(1); 436 pcm_rec_mux(1);
@@ -971,7 +1013,7 @@ bool radio_screen(void)
971 while(1) 1013 while(1)
972 { 1014 {
973 button = button_get(true); 1015 button = button_get(true);
974 if(button == (BUTTON_OFF | BUTTON_REL)) 1016 if(button == (FM_STOP | BUTTON_REL))
975 break; 1017 break;
976 } 1018 }
977 } 1019 }
@@ -1004,6 +1046,11 @@ bool radio_screen(void)
1004 radio_stop(); 1046 radio_stop();
1005#ifndef SIMULATOR /* SIMULATOR. Catch FMRADIO_OFF status for the sim. */ 1047#ifndef SIMULATOR /* SIMULATOR. Catch FMRADIO_OFF status for the sim. */
1006#if CONFIG_CODEC == SWCODEC 1048#if CONFIG_CODEC == SWCODEC
1049#ifdef HAVE_TLV320
1050 //tlv320_disable_recording();
1051 tlv320_set_monitor(false);
1052#endif
1053
1007 pcm_rec_mux(0); /* Line In */ 1054 pcm_rec_mux(0); /* Line In */
1008 peak_meter_enabled = true; 1055 peak_meter_enabled = true;
1009#endif 1056#endif
@@ -1320,7 +1367,7 @@ int handle_radio_presets_cb(int key, int m)
1320 key = BUTTON_NONE; 1367 key = BUTTON_NONE;
1321 break; 1368 break;
1322#endif 1369#endif
1323#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) 1370#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) && (CONFIG_KEYPAD != IAUDIO_X5_PAD)
1324#ifdef FM_PRESET 1371#ifdef FM_PRESET
1325 case FM_PRESET: 1372 case FM_PRESET:
1326 menu_draw(m); 1373 menu_draw(m);
@@ -1565,7 +1612,7 @@ int radio_menu_cb(int key, int m)
1565 (void)m; 1612 (void)m;
1566 switch(key) 1613 switch(key)
1567 { 1614 {
1568#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) 1615#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) && (CONFIG_KEYPAD != IAUDIO_X5_PAD)
1569#ifdef MENU_ENTER2 1616#ifdef MENU_ENTER2
1570 case MENU_ENTER2: 1617 case MENU_ENTER2:
1571#endif 1618#endif
@@ -1574,7 +1621,7 @@ int radio_menu_cb(int key, int m)
1574 key = BUTTON_NONE; /* eat the downpress, next menu reacts on release */ 1621 key = BUTTON_NONE; /* eat the downpress, next menu reacts on release */
1575 break; 1622 break;
1576 1623
1577#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) 1624#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) && (CONFIG_KEYPAD != IAUDIO_X5_PAD)
1578#ifdef MENU_ENTER2 1625#ifdef MENU_ENTER2
1579 case MENU_ENTER2 | BUTTON_REL: 1626 case MENU_ENTER2 | BUTTON_REL:
1580#endif 1627#endif
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index 09ec0f43f5..d4094a2511 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -34,6 +34,9 @@
34#ifdef HAVE_UDA1380 34#ifdef HAVE_UDA1380
35#include "uda1380.h" 35#include "uda1380.h"
36#endif 36#endif
37#ifdef HAVE_TLV320
38#include "tlv320.h"
39#endif
37 40
38#include "mp3_playback.h" 41#include "mp3_playback.h"
39#include "mas.h" 42#include "mas.h"
@@ -109,6 +112,16 @@
109#define REC_RC_PREV BUTTON_RC_REW 112#define REC_RC_PREV BUTTON_RC_REW
110#define REC_RC_SETTINGS BUTTON_RC_MODE 113#define REC_RC_SETTINGS BUTTON_RC_MODE
111 114
115#elif (CONFIG_KEYPAD == IAUDIO_X5_PAD)
116#define REC_SHUTDOWN (BUTTON_POWER | BUTTON_REPEAT)
117#define REC_STOPEXIT BUTTON_POWER
118#define REC_RECPAUSE BUTTON_REC
119#define REC_INC BUTTON_RIGHT
120#define REC_DEC BUTTON_LEFT
121#define REC_NEXT BUTTON_DOWN
122#define REC_PREV BUTTON_UP
123#define REC_SETTINGS BUTTON_PLAY
124
112#elif CONFIG_KEYPAD == GMINI100_PAD 125#elif CONFIG_KEYPAD == GMINI100_PAD
113#define REC_SHUTDOWN (BUTTON_OFF | BUTTON_REPEAT) 126#define REC_SHUTDOWN (BUTTON_OFF | BUTTON_REPEAT)
114#define REC_STOPEXIT BUTTON_OFF 127#define REC_STOPEXIT BUTTON_OFF
@@ -362,6 +375,9 @@ bool recording_screen(void)
362 audio_stop(); 375 audio_stop();
363 /* Set peak meter to recording mode */ 376 /* Set peak meter to recording mode */
364 peak_meter_playback(false); 377 peak_meter_playback(false);
378#ifdef IAUDIO_X5
379 pcm_rec_mux(0); /* select line-in (not radio) */
380#endif
365 381
366#if defined(HAVE_SPDIF_IN) && !defined(SIMULATOR) 382#if defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
367 if (global_settings.rec_source == SOURCE_SPDIF) 383 if (global_settings.rec_source == SOURCE_SPDIF)
diff --git a/firmware/drivers/fmradio_i2c.c b/firmware/drivers/fmradio_i2c.c
index 2475084696..6f87e15b3e 100644
--- a/firmware/drivers/fmradio_i2c.c
+++ b/firmware/drivers/fmradio_i2c.c
@@ -27,6 +27,22 @@
27 27
28#if (CONFIG_TUNER & TEA5767) 28#if (CONFIG_TUNER & TEA5767)
29#if (CONFIG_I2C == I2C_COLDFIRE) 29#if (CONFIG_I2C == I2C_COLDFIRE)
30
31#ifdef IAUDIO_X5
32#include "i2c-coldfire.h"
33
34int fmradio_i2c_write(unsigned char address, const unsigned char* buf,
35 int count)
36{
37 return i2c_write(I2C_IFACE_0, address, buf, count);
38}
39
40int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
41{
42 return i2c_read(I2C_IFACE_0, address, buf, count);
43}
44#else
45
30/* cute little functions, atomic read-modify-write */ 46/* cute little functions, atomic read-modify-write */
31/* SDA is GPIO1,23 */ 47/* SDA is GPIO1,23 */
32 48
@@ -242,6 +258,7 @@ int fmradio_i2c_read(int address, unsigned char* buf, int count)
242 fmradio_i2c_stop(); 258 fmradio_i2c_stop();
243 return x; 259 return x;
244} 260}
261#endif /* ! IAUDIO_X5 */
245#else 262#else
246/* cute little functions, atomic read-modify-write */ 263/* cute little functions, atomic read-modify-write */
247/* SDA is PB4 */ 264/* SDA is PB4 */
diff --git a/firmware/drivers/i2c-coldfire.c b/firmware/drivers/i2c-coldfire.c
index 47aeba757f..a628ce5f0e 100644
--- a/firmware/drivers/i2c-coldfire.c
+++ b/firmware/drivers/i2c-coldfire.c
@@ -5,6 +5,7 @@
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 *
8 * $Id$ 9 * $Id$
9 * 10 *
10 * Copyright (C) 2005 by Andy Young 11 * Copyright (C) 2005 by Andy Young
@@ -23,17 +24,16 @@
23#include "system.h" 24#include "system.h"
24#include "i2c-coldfire.h" 25#include "i2c-coldfire.h"
25 26
26#define I2C_DEVICE_1 ((volatile unsigned char *)&MADR)
27#define I2C_DEVICE_2 ((volatile unsigned char *)&MADR2)
28 27
29/* Local functions definitions */ 28/* --- Local functions - declarations --- */
29
30static int i2c_start(volatile unsigned char *iface);
31static int i2c_wait_for_slave(volatile unsigned char *iface);
32static int i2c_outb(volatile unsigned char *iface, unsigned char byte);
33inline void i2c_stop(volatile unsigned char *iface);
30 34
31static int i2c_write_byte(int device, unsigned char data);
32static int i2c_gen_start(int device);
33static void i2c_gen_stop(int device);
34static volatile unsigned char *i2c_get_addr(int device);
35 35
36/* Public functions */ 36/* --- Public functions - implementation --- */
37 37
38void i2c_init(void) 38void i2c_init(void)
39{ 39{
@@ -55,14 +55,15 @@ void i2c_init(void)
55#endif 55#endif
56 56
57 /* I2C Clock divisor = 160 => 124.1556 MHz / 2 / 160 = 388.08 kHz */ 57 /* I2C Clock divisor = 160 => 124.1556 MHz / 2 / 160 = 388.08 kHz */
58 MFDR = 0x0d; 58 MFDR = 0x0d;
59 MFDR2 = 0x0d; 59 MFDR2 = 0x0d;
60 60
61#ifdef IAUDIO_X5 61#ifdef IAUDIO_X5
62 MBCR = IEN; /* Enable interface */ 62 MBCR = IEN; /* Enable interface */
63 MBCR2 = IEN;
63#endif 64#endif
64 65
65#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) 66#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
66 /* Audio Codec */ 67 /* Audio Codec */
67 MBDR = 0; /* iRiver firmware does this */ 68 MBDR = 0; /* iRiver firmware does this */
68 MBCR = IEN; /* Enable interface */ 69 MBCR = IEN; /* Enable interface */
@@ -72,109 +73,169 @@ void i2c_init(void)
72void i2c_close(void) 73void i2c_close(void)
73{ 74{
74 MBCR = 0; 75 MBCR = 0;
76 MBCR2 = 0;
75} 77}
76 78
77/** 79/*
78 * Writes bytes to the selected device. 80 * Writes bytes to a I2C device.
79 * 81 *
80 * Use device=1 for bus 1 at 0x40000280 82 * Returns number of bytes successfully sent or a negative value on error.
81 * Use device=2 for bus 2 at 0x80000440
82 *
83 * Returns number of bytes successfully send or -1 if START failed
84 */ 83 */
85int i2c_write(int device, unsigned char *buf, int count) 84int i2c_write(volatile unsigned char *iface, unsigned char addr,
85 const unsigned char *buf, int count)
86{ 86{
87 int i; 87 int i, rc;
88 int rc;
89 88
90 rc = i2c_gen_start(device); 89 if ( ! count)
90 return 0;
91
92 rc = i2c_start(iface);
91 if (rc < 0) 93 if (rc < 0)
94 return rc;
95
96 rc = i2c_outb(iface, addr & 0xfe);
97 if (rc < 0)
98 return rc;
99
100 for (i = 0; i < count; i++)
92 { 101 {
93 logf("i2c: gen_start failed (d=%d)", device); 102 rc = i2c_outb(iface, *buf++);
94 return rc*10 - 1;
95 }
96
97 for (i=0; i<count; i++)
98 {
99 rc = i2c_write_byte(device, buf[i]);
100 if (rc < 0) 103 if (rc < 0)
101 { 104 return rc;
102 logf("i2c: write failed at (d=%d,i=%d)", device, i);
103 return rc*10 - 2;
104 }
105 } 105 }
106 106 i2c_stop(iface);
107 i2c_gen_stop(device); 107
108
109 return count; 108 return count;
110} 109}
111 110
112/* Write a byte to the interface, returns 0 on success, -1 otherwise. */ 111/*
113int i2c_write_byte(int device, unsigned char data) 112 * Reads bytes from a I2C device.
113 *
114 * Returns number of bytes successfully received or a negative value on error.
115 */
116int i2c_read(volatile unsigned char *iface, unsigned char addr,
117 unsigned char *buf, int count)
114{ 118{
115 volatile unsigned char *regs = i2c_get_addr(device); 119 int i, rc;
116 120
117 long count = 0; 121 if ( ! count)
122 return 0;
123
124 rc = i2c_start(iface);
125 if (rc < 0)
126 return rc;
118 127
119 regs[O_MBDR] = data; /* Write data byte */ 128 rc = i2c_outb(iface, addr | 1);
129 if (rc < 0)
130 return rc;
131
132 /* Switch to Rx mode */
133 iface[O_MBCR] &= ~MTX;
134 iface[O_MBCR] &= ~TXAK;
135
136 /* Dummy read */
137 rc = (int) iface[O_MBDR];
138
139 for (i = 0; i < count; i++)
140 {
141 rc = i2c_wait_for_slave(iface);
142 if (rc < 0)
143 return rc;
120 144
121 /* Wait for bus busy */ 145 if (i == count-2)
122 while (!(regs[O_MBSR] & IBB) && count < MAX_LOOP) 146 /* Don't ACK the next-to-last byte */
123 count++; 147 iface[O_MBCR] |= TXAK;
148
149 if (i == count-1)
150 /* Generate STOP before reading last byte */
151 i2c_stop(iface);
124 152
125 if (count >= MAX_LOOP) 153 *buf++ = iface[O_MBDR];
126 return -1; 154 }
155 return count;
156}
127 157
128 count = 0; 158/* --- Local functions - implementation --- */
129 159
130 /* Wait for interrupt flag */ 160/* Begin I2C session on the given interface.
131 while (!(regs[O_MBSR] & IFF) && count < MAX_LOOP) 161 *
132 count++; 162 * Returns 0 on success, negative value on error.
163 */
164int i2c_start(volatile unsigned char *iface)
165{
166 /* Wait for bus to become free */
167 int j = MAX_LOOP;
168 while (--j && (iface[O_MBSR] & IBB))
169 ;
170 if (!j)
171 {
172 logf("i2c: bus is busy (iface=%08x)", iface);
173 return -1;
174 }
175
176 /* Generate START and prepare for write */
177 iface[O_MBCR] |= (MSTA | TXAK | MTX);
178
179 return 0;
180}
133 181
134 if (count >= MAX_LOOP) 182/* Wait for slave to act on given I2C interface.
183 *
184 * Returns 0 on success, negative value on error.
185 */
186int i2c_wait_for_slave(volatile unsigned char *iface)
187{
188 int j = MAX_LOOP;
189 while (--j && ! (iface[O_MBSR] & IFF))
190 ;
191 if (!j)
192 {
193 logf("i2c: IFF not set (iface=%08x)", iface);
194 i2c_stop(iface);
135 return -2; 195 return -2;
136 196 }
137 regs[O_MBSR] &= ~IFF; /* Clear interrupt flag */ 197
138 198 /* Clear interrupt flag */
139 if (!(regs[O_MBSR] & ICF)) /* Check that transfer is complete */ 199 iface[O_MBSR] &= ~IFF;
140 return -3; 200
141
142 if (regs[O_MBSR] & RXAK) /* Check that the byte has been ACKed */
143 return -4;
144
145 return 0; 201 return 0;
146} 202}
147 203
148 204/* Write the given byte to the given I2C interface.
149/* Returns 0 on success, -1 on failure */ 205 *
150int i2c_gen_start(int device) 206 * Returns 0 on success, negative value on error.
207 */
208int i2c_outb(volatile unsigned char *iface, unsigned char byte)
151{ 209{
152 volatile unsigned char *regs = i2c_get_addr(device); 210 int rc;
153 long count = 0;
154
155 /* Wait for bus to become free */
156 while ((regs[O_MBSR] & IBB) && (count < MAX_LOOP))
157 count++;
158
159 if (count >= MAX_LOOP)
160 return -1;
161 211
162 regs[O_MBCR] |= MSTA | MTX; /* Generate START */ 212 iface[O_MBDR] = byte;
163 213
214 rc = i2c_wait_for_slave(iface);
215 if (rc < 0)
216 return rc;
217
218 /* Check that transfer is complete */
219 if ( !(iface[O_MBSR] & ICF))
220 {
221 logf("i2c: transfer error (iface=%08x)", iface);
222 i2c_stop(iface);
223 return -3;
224 }
225
226 /* Check that the byte has been ACKed */
227 if (iface[O_MBSR] & RXAK)
228 {
229 logf("i2c: no ACK (iface=%08x)", iface);
230 i2c_stop(iface);
231 return -4;
232 }
233
164 return 0; 234 return 0;
165}
166
167void i2c_gen_stop(int device)
168{
169 volatile unsigned char *regs = i2c_get_addr(device);
170 regs[O_MBCR] &= ~MSTA; /* Clear MSTA to generate STOP */
171} 235}
172 236
173 237/* End I2C session on the given interface. */
174volatile unsigned char *i2c_get_addr(int device) 238inline void i2c_stop(volatile unsigned char *iface)
175{ 239{
176 if (device == 1) 240 iface[O_MBCR] &= ~MSTA;
177 return I2C_DEVICE_1;
178
179 return I2C_DEVICE_2;
180} 241}
diff --git a/firmware/drivers/tlv320.c b/firmware/drivers/tlv320.c
index 8ef32919ce..39cd2a5536 100644
--- a/firmware/drivers/tlv320.c
+++ b/firmware/drivers/tlv320.c
@@ -28,6 +28,7 @@
28#include "string.h" 28#include "string.h"
29#include "file.h" 29#include "file.h"
30#include "buffer.h" 30#include "buffer.h"
31#include "audio.h"
31 32
32#include "i2c-coldfire.h" 33#include "i2c-coldfire.h"
33#include "tlv320.h" 34#include "tlv320.h"
@@ -46,14 +47,13 @@ unsigned tlv320_regs[0xf];
46 47
47void tlv320_write_reg(unsigned reg, unsigned value) 48void tlv320_write_reg(unsigned reg, unsigned value)
48{ 49{
49 unsigned char data[3]; 50 unsigned char data[2];
50 51
51 data[0] = TLV320_ADDR;
52 /* The register address is the high 7 bits and the data the low 9 bits */ 52 /* The register address is the high 7 bits and the data the low 9 bits */
53 data[1] = (reg << 1) | ((value >> 8) & 1); 53 data[0] = (reg << 1) | ((value >> 8) & 1);
54 data[2] = value & 0xff; 54 data[1] = value & 0xff;
55 55
56 if (i2c_write(1, data, 3) != 3) 56 if (i2c_write(I2C_IFACE_0, TLV320_ADDR, data, 2) != 2)
57 { 57 {
58 logf("tlv320 error reg=0x%x", reg); 58 logf("tlv320 error reg=0x%x", reg);
59 return; 59 return;
@@ -73,15 +73,16 @@ void tlv320_init(void)
73 73
74 /* Initialize all registers */ 74 /* Initialize all registers */
75 75
76 tlv320_write_reg(REG_PC, 0x00); /* All ON */ 76 tlv320_write_reg(REG_PC, PC_ADC|PC_MIC|PC_LINE); /* All ON except ADC, MIC and LINE */
77 tlv320_set_linein_vol(0, 0); 77 tlv320_set_recvol(0, 0, AUDIO_GAIN_MIC);
78 tlv320_set_recvol(0, 0, AUDIO_GAIN_LINEIN);
78 tlv320_mute(true); 79 tlv320_mute(true);
79 tlv320_write_reg(REG_AAP, AAP_DAC|AAP_MICM); 80 tlv320_write_reg(REG_AAP, AAP_DAC|AAP_MICM);
80 tlv320_write_reg(REG_DAP, 0x00); /* No deemphasis */ 81 tlv320_write_reg(REG_DAP, 0x00); /* No deemphasis */
81 tlv320_write_reg(REG_DAIF, DAIF_IWL_16|DAIF_FOR_I2S); 82 tlv320_write_reg(REG_DAIF, DAIF_IWL_16|DAIF_FOR_I2S);
82 tlv320_set_headphone_vol(0, 0); 83 tlv320_set_headphone_vol(0, 0);
83 tlv320_write_reg(REG_DIA, DIA_ACT); 84 tlv320_write_reg(REG_DIA, DIA_ACT);
84 tlv320_write_reg(REG_SRC, (8 << 2)); /* 44.1kHz */ 85 tlv320_write_reg(REG_SRC, (1 << 5)); /* 44.1kHz */
85} 86}
86 87
87/** 88/**
@@ -114,18 +115,30 @@ void tlv320_set_headphone_vol(int vol_l, int vol_r)
114} 115}
115 116
116/** 117/**
117 * Sets left and right linein volume (31(max) to 0(muted)) 118 * Set recording volume
119 *
120 * Line in : 0 .. 31 => Volume -34.5 .. 12 dB
121 * Mic (left): 0 .. 1 => Volume 0 .. 20 dB
122 *
118 */ 123 */
119void tlv320_set_linein_vol(int vol_l, int vol_r) 124void tlv320_set_recvol(int left, int right, int type)
120{ 125{
121 unsigned value_l = tlv320_regs[REG_LLIV]; 126 if (type == AUDIO_GAIN_MIC)
122 unsigned value_r = tlv320_regs[REG_RLIV]; 127 {
123 128 unsigned value_aap = tlv320_regs[REG_AAP];
124 value_l |= LLIV_LIV(vol_l); 129
125 value_r |= RLIV_RIV(vol_r); 130 if (left)
126 131 value_aap |= AAP_MICB; /* Enable mic boost (20dB) */
127 tlv320_write_reg(REG_LLIV, value_l); 132 else
128 tlv320_write_reg(REG_RLIV, value_r); 133 value_aap &= ~AAP_MICB;
134
135 tlv320_write_reg(REG_AAP, value_aap);
136
137 } else if (type == AUDIO_GAIN_LINEIN)
138 {
139 tlv320_write_reg(REG_LLIV, LLIV_LIV(left));
140 tlv320_write_reg(REG_RLIV, RLIV_RIV(right));
141 }
129} 142}
130 143
131/** 144/**
@@ -148,10 +161,11 @@ void tlv320_mute(bool mute)
148 value_r = RHV_RHV(tlv320.vol_r); 161 value_r = RHV_RHV(tlv320.vol_r);
149 } 162 }
150 163
151 tlv320_write_reg(REG_LHV, value_r); 164 tlv320_write_reg(REG_LHV, value_l);
152 tlv320_write_reg(REG_RHV, value_r); 165 tlv320_write_reg(REG_RHV, value_r);
153} 166}
154 167
168/* Nice shutdown of TLV320 codec */
155void tlv320_close() 169void tlv320_close()
156{ 170{
157 tlv320_write_reg(REG_PC, 0xFF); /* All OFF */ 171 tlv320_write_reg(REG_PC, 0xFF); /* All OFF */
@@ -159,35 +173,66 @@ void tlv320_close()
159 173
160void tlv320_enable_recording(bool source_mic) 174void tlv320_enable_recording(bool source_mic)
161{ 175{
162 unsigned value_pc = tlv320_regs[REG_PC]; 176 unsigned value_daif = tlv320_regs[REG_DAIF];
163 unsigned value_aap = tlv320_regs[REG_AAP]; 177 unsigned value_aap, value_pc;
164 178
165 /* select source*/
166 if (source_mic) 179 if (source_mic)
167 { 180 {
168 value_aap &= ~AAP_INSEL; 181 /* select mic and enable mic boost (20 dB) */
169 value_pc |= PC_MIC; 182 value_aap = AAP_DAC | AAP_INSEL | AAP_MICB;
183 value_pc = PC_LINE; /* power down line-in */
170 } 184 }
171 else 185 else
172 { 186 {
173 value_aap |= AAP_INSEL; 187 value_aap = AAP_DAC | AAP_MICM;
174 value_pc |= PC_LINE; 188 value_pc = PC_MIC; /* power down mic */
175 } 189 }
176 190
177 /* poweron adc */ 191 tlv320_write_reg(REG_PC, value_pc);
178 value_pc |= PC_ADC; 192 sleep(HZ/8);
179 193
180 tlv320_write_reg(REG_AAP, value_aap); 194 tlv320_write_reg(REG_AAP, value_aap);
181 tlv320_write_reg(REG_PC, value_pc); 195 sleep(HZ/8);
196
197 /* Enable MASTER mode (start sending I2S data to the CPU) */
198 value_daif |= DAIF_MS;
199 tlv320_write_reg(REG_DAIF, value_daif);
182} 200}
183 201
184void tlv320_disable_recording() 202void tlv320_disable_recording()
185{ 203{
186 unsigned value = tlv320_regs[REG_PC]; 204 unsigned value_pc = tlv320_regs[REG_PC];
187 205 unsigned value_aap = tlv320_regs[REG_AAP];
188 /* powerdown mic, linein and adc */ 206 unsigned value_daif = tlv320_regs[REG_DAIF];
189 value &= ~(PC_MIC | PC_LINE | PC_ADC); 207
208 value_daif &= ~DAIF_MS; /* disable MASTER mode */
209 tlv320_write_reg(REG_DAIF, value_daif);
210
211 value_aap |= AAP_MICM; /* mute mic */
212 tlv320_write_reg(REG_PC, value_aap);
213
214 value_pc |= (PC_MIC|PC_LINE|PC_ADC); /* power down mic, line-in and adc */
215 tlv320_write_reg(REG_PC, value_pc);
216
217 sleep(HZ/8);
218}
190 219
191 /* powerdown mic, linein and adc */ 220void tlv320_set_monitor(bool enable)
192 tlv320_write_reg(REG_PC, value); 221{
222 unsigned value_aap, value_pc;
223 if (enable)
224 {
225 value_aap = AAP_BYPASS | AAP_MICM;
226 value_pc = (PC_MIC|PC_DAC|PC_ADC); /* power down mic, dac and adc */
227 }
228 else
229 {
230 value_aap = AAP_DAC | AAP_MICM;
231 value_pc = (PC_MIC|PC_LINE|PC_ADC); /* power down mic, line-in and adc */
232 }
233 tlv320_write_reg(REG_AAP, value_aap);
234 tlv320_write_reg(REG_PC, value_pc);
235
236 sleep(HZ/8);
193} 237}
238
diff --git a/firmware/drivers/uda1380.c b/firmware/drivers/uda1380.c
index ef19dcf1c5..241a117385 100644
--- a/firmware/drivers/uda1380.c
+++ b/firmware/drivers/uda1380.c
@@ -76,14 +76,13 @@ unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] =
76/* Returns 0 if register was written or -1 if write failed */ 76/* Returns 0 if register was written or -1 if write failed */
77int uda1380_write_reg(unsigned char reg, unsigned short value) 77int uda1380_write_reg(unsigned char reg, unsigned short value)
78{ 78{
79 unsigned char data[4]; 79 unsigned char data[3];
80 80
81 data[0] = UDA1380_ADDR; 81 data[0] = reg;
82 data[1] = reg; 82 data[1] = value >> 8;
83 data[2] = value >> 8; 83 data[2] = value & 0xff;
84 data[3] = value & 0xff;
85 84
86 if (i2c_write(1, data, 4) != 4) 85 if (i2c_write(I2C_IFACE_0, UDA1380_ADDR, data, 3) != 3)
87 { 86 {
88 DEBUGF("uda1380 error reg=0x%x", reg); 87 DEBUGF("uda1380 error reg=0x%x", reg);
89 return -1; 88 return -1;
@@ -322,21 +321,20 @@ void uda1380_set_recvol(int left, int right, int type)
322 { 321 {
323 /* for this order we can combine both registers, 322 /* for this order we can combine both registers,
324 making the glitch even smaller */ 323 making the glitch even smaller */
325 unsigned char data[6]; 324 unsigned char data[5];
326 unsigned short value_dec; 325 unsigned short value_dec;
327 unsigned short value_pga; 326 unsigned short value_pga;
328 value_dec = DEC_VOLL(left) | DEC_VOLR(right); 327 value_dec = DEC_VOLL(left) | DEC_VOLR(right);
329 value_pga = (uda1380_regs[REG_PGA] & ~PGA_GAIN_MASK) 328 value_pga = (uda1380_regs[REG_PGA] & ~PGA_GAIN_MASK)
330 | PGA_GAINL(left_ag) | PGA_GAINR(right_ag); 329 | PGA_GAINL(left_ag) | PGA_GAINR(right_ag);
331 330
332 data[0] = UDA1380_ADDR; 331 data[0] = REG_DEC_VOL;
333 data[1] = REG_DEC_VOL; 332 data[1] = value_dec >> 8;
334 data[2] = value_dec >> 8; 333 data[2] = value_dec & 0xff;
335 data[3] = value_dec & 0xff; 334 data[3] = value_pga >> 8;
336 data[4] = value_pga >> 8; 335 data[4] = value_pga & 0xff;
337 data[5] = value_pga & 0xff;
338 336
339 if (i2c_write(1, data, 6) != 6) 337 if (i2c_write(I2C_IFACE_0, UDA1380_ADDR, data, 5) != 5)
340 { 338 {
341 DEBUGF("uda1380 error reg=combi rec gain"); 339 DEBUGF("uda1380 error reg=combi rec gain");
342 } 340 }
diff --git a/firmware/export/config-iaudiox5.h b/firmware/export/config-iaudiox5.h
index d224b3b45e..cd77dc3c48 100644
--- a/firmware/export/config-iaudiox5.h
+++ b/firmware/export/config-iaudiox5.h
@@ -6,7 +6,7 @@
6#define MODEL_NUMBER 10 6#define MODEL_NUMBER 10
7 7
8/* define this if you have recording possibility */ 8/* define this if you have recording possibility */
9/*#define HAVE_RECORDING 1*/ 9#define HAVE_RECORDING 1
10 10
11/* define this if you have a bitmap LCD display */ 11/* define this if you have a bitmap LCD display */
12#define HAVE_LCD_BITMAP 1 12#define HAVE_LCD_BITMAP 1
@@ -53,6 +53,11 @@
53/* The number of bytes reserved for loadable plugins */ 53/* The number of bytes reserved for loadable plugins */
54#define PLUGIN_BUFFER_SIZE 0x80000 54#define PLUGIN_BUFFER_SIZE 0x80000
55 55
56/* FM Tuner */
57#define CONFIG_TUNER TEA5767
58#define CONFIG_TUNER_XTAL 32768
59
60
56#define BATTERY_CAPACITY_DEFAULT 950 /* default battery capacity */ 61#define BATTERY_CAPACITY_DEFAULT 950 /* default battery capacity */
57 62
58#ifndef SIMULATOR 63#ifndef SIMULATOR
diff --git a/firmware/export/fmradio_i2c.h b/firmware/export/fmradio_i2c.h
index b7007a80dd..6483594d04 100644
--- a/firmware/export/fmradio_i2c.h
+++ b/firmware/export/fmradio_i2c.h
@@ -20,7 +20,7 @@
20#ifndef FMRADIO_I2C_H 20#ifndef FMRADIO_I2C_H
21#define FMRADIO_I2C_H 21#define FMRADIO_I2C_H
22 22
23int fmradio_i2c_write(int address, const unsigned char* buf, int count); 23int fmradio_i2c_write(unsigned char address, const unsigned char* buf, int count);
24int fmradio_i2c_read(int address, unsigned char* buf, int count); 24int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count);
25 25
26#endif 26#endif
diff --git a/firmware/export/i2c-coldfire.h b/firmware/export/i2c-coldfire.h
index d4a5781116..544a3169cf 100644
--- a/firmware/export/i2c-coldfire.h
+++ b/firmware/export/i2c-coldfire.h
@@ -26,10 +26,18 @@
26#ifndef _I2C_COLDFIRE_H 26#ifndef _I2C_COLDFIRE_H
27#define _I2C_COLDFIRE_H 27#define _I2C_COLDFIRE_H
28 28
29#include "cpu.h"
30
29void i2c_init(void); 31void i2c_init(void);
30int i2c_write(int device, unsigned char *buf, int count); 32int i2c_read (volatile unsigned char *iface, unsigned char addr,
33 unsigned char *buf, int count);
34int i2c_write(volatile unsigned char *iface, unsigned char addr,
35 const unsigned char *buf, int count);
31void i2c_close(void); 36void i2c_close(void);
37void i2c_adjust_prescale(int multiplier);
32 38
39#define I2C_IFACE_0 ((volatile unsigned char *)&MADR)
40#define I2C_IFACE_1 ((volatile unsigned char *)&MADR2)
33 41
34#define MAX_LOOP 0x100 /* TODO: select a better value */ 42#define MAX_LOOP 0x100 /* TODO: select a better value */
35 43
diff --git a/firmware/export/sound.h b/firmware/export/sound.h
index a49cb99263..33175e4166 100644
--- a/firmware/export/sound.h
+++ b/firmware/export/sound.h
@@ -36,7 +36,7 @@ enum {
36 SOUND_MDB_ENABLE, 36 SOUND_MDB_ENABLE,
37 SOUND_SUPERBASS, 37 SOUND_SUPERBASS,
38#endif 38#endif
39#if CONFIG_CODEC == MAS3587F || defined(HAVE_UDA1380) 39#if CONFIG_CODEC == MAS3587F || defined(HAVE_UDA1380) || defined(HAVE_TLV320)
40 SOUND_LEFT_GAIN, 40 SOUND_LEFT_GAIN,
41 SOUND_RIGHT_GAIN, 41 SOUND_RIGHT_GAIN,
42 SOUND_MIC_GAIN, 42 SOUND_MIC_GAIN,
diff --git a/firmware/export/tlv320.h b/firmware/export/tlv320.h
index 93a79780c0..45ebfee569 100644
--- a/firmware/export/tlv320.h
+++ b/firmware/export/tlv320.h
@@ -26,11 +26,12 @@ extern void tlv320_init(void);
26extern void tlv320_reset(void); 26extern void tlv320_reset(void);
27extern void tlv320_enable_output(bool enable); 27extern void tlv320_enable_output(bool enable);
28extern void tlv320_set_headphone_vol(int vol_l, int vol_r); 28extern void tlv320_set_headphone_vol(int vol_l, int vol_r);
29extern void tlv320_set_linein_vol(int vol_l, int vol_r); 29extern void tlv320_set_recvol(int left, int right, int type);
30extern void tlv320_mute(bool mute); 30extern void tlv320_mute(bool mute);
31extern void tlv320_close(void); 31extern void tlv320_close(void);
32extern void tlv320_enable_recording(bool source_mic); 32extern void tlv320_enable_recording(bool source_mic);
33extern void tlv320_disable_recording(void); 33extern void tlv320_disable_recording(void);
34extern void tlv320_set_monitor(bool enable);
34 35
35#define HEADPHONE_MUTE 0x30 /* 0110000 = -73db */ 36#define HEADPHONE_MUTE 0x30 /* 0110000 = -73db */
36 37
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c
index 2d9c65a7e4..fee2bbd35b 100644
--- a/firmware/pcm_record.c
+++ b/firmware/pcm_record.c
@@ -31,7 +31,12 @@
31#include "cpu.h" 31#include "cpu.h"
32#include "i2c.h" 32#include "i2c.h"
33#include "power.h" 33#include "power.h"
34#ifdef HAVE_UDA1380
34#include "uda1380.h" 35#include "uda1380.h"
36#endif
37#ifdef HAVE_TLV320
38#include "tlv320.h"
39#endif
35#include "system.h" 40#include "system.h"
36#include "usb.h" 41#include "usb.h"
37 42
@@ -51,14 +56,14 @@ extern int boost_counter; /* used for boost check */
51 56
52/***************************************************************************/ 57/***************************************************************************/
53 58
54static volatile bool is_recording; /* We are recording */ 59static bool is_recording; /* We are recording */
55static volatile bool is_stopping; /* Are we going to stop */ 60static bool is_stopping; /* Are we going to stop */
56static volatile bool is_paused; /* We have paused */ 61static bool is_paused; /* We have paused */
57static volatile bool is_error; /* An error has occured */ 62static bool is_error; /* An error has occured */
58 63
59static volatile unsigned long num_rec_bytes; /* Num bytes recorded */ 64static unsigned long num_rec_bytes; /* Num bytes recorded */
60static volatile unsigned long num_file_bytes; /* Num bytes written to current file */ 65static unsigned long num_file_bytes; /* Num bytes written to current file */
61static volatile int error_count; /* Number of DMA errors */ 66static int error_count; /* Number of DMA errors */
62 67
63static long record_start_time; /* Value of current_tick when recording was started */ 68static long record_start_time; /* Value of current_tick when recording was started */
64static long pause_start_time; /* Value of current_tick when pause was started */ 69static long pause_start_time; /* Value of current_tick when pause was started */
@@ -69,7 +74,7 @@ static int rec_source; /* Current recording source */
69static int wav_file; 74static int wav_file;
70static char recording_filename[MAX_PATH]; 75static char recording_filename[MAX_PATH];
71 76
72static volatile bool init_done, close_done, record_done, stop_done, pause_done, resume_done, new_file_done; 77static bool init_done, close_done, record_done, stop_done, pause_done, resume_done, new_file_done;
73 78
74static short peak_left, peak_right; 79static short peak_left, peak_right;
75 80
@@ -90,16 +95,23 @@ static unsigned int rec_buffer_offset;
90static unsigned char *rec_buffer; /* Circular recording buffer */ 95static unsigned char *rec_buffer; /* Circular recording buffer */
91static int num_chunks; /* Number of chunks available in rec_buffer */ 96static int num_chunks; /* Number of chunks available in rec_buffer */
92 97
93 98#ifdef IAUDIO_X5
99#define SET_IIS_PLAY(x) IIS1CONFIG = (x);
100#define SET_IIS_REC(x) IIS1CONFIG = (x);
101#else
102#define SET_IIS_PLAY(x) IIS2CONFIG = (x);
103#define SET_IIS_REC(x) IIS1CONFIG = (x);
104#endif
105
94/* 106/*
95 Overrun occures when DMA needs to write a new chunk and write_index == read_index 107 Overrun occures when DMA needs to write a new chunk and write_index == read_index
96 Solution to this is to optimize pcmrec_callback, use cpu_boost or save to disk 108 Solution to this is to optimize pcmrec_callback, use cpu_boost or save to disk
97 more often. 109 more often.
98*/ 110*/
99 111
100static volatile int write_index; /* Current chunk the DMA is writing to */ 112static int write_index; /* Current chunk the DMA is writing to */
101static volatile int read_index; /* Oldest chunk that is not written to disk */ 113static int read_index; /* Oldest chunk that is not written to disk */
102static volatile int read2_index; /* Latest chunk that has not been converted to little endian */ 114static int read2_index; /* Latest chunk that has not been converted to little endian */
103static long pre_record_ticks; /* pre-record time expressed in ticks */ 115static long pre_record_ticks; /* pre-record time expressed in ticks */
104static int pre_record_chunks; /* pre-record time expressed in chunks */ 116static int pre_record_chunks; /* pre-record time expressed in chunks */
105 117
@@ -137,7 +149,7 @@ void pcm_rec_init(void)
137 149
138 150
139/* Initializes recording: 151/* Initializes recording:
140 * - Set up the UDA1380 for recording 152 * - Set up the UDA1380/TLV320 for recording
141 * - Prepare for DMA transfers 153 * - Prepare for DMA transfers
142 */ 154 */
143 155
@@ -292,14 +304,26 @@ void audio_set_recording_options(int frequency, int quality,
292 case 0: 304 case 0:
293 /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */ 305 /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */
294 DATAINCONTROL = 0xc020; 306 DATAINCONTROL = 0xc020;
307
308#ifdef HAVE_UDA1380
295 uda1380_enable_recording(true); 309 uda1380_enable_recording(true);
310#endif
311#ifdef HAVE_TLV320
312 tlv320_enable_recording(true);
313#endif
296 break; 314 break;
297 315
298 /* line-in */ 316 /* line-in */
299 case 1: 317 case 1:
300 /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */ 318 /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */
301 DATAINCONTROL = 0xc020; 319 DATAINCONTROL = 0xc020;
320
321#ifdef HAVE_UDA1380
302 uda1380_enable_recording(false); 322 uda1380_enable_recording(false);
323#endif
324#ifdef HAVE_TLV320
325 tlv320_enable_recording(false);
326#endif
303 break; 327 break;
304#ifdef HAVE_SPDIF_IN 328#ifdef HAVE_SPDIF_IN
305 /* SPDIF */ 329 /* SPDIF */
@@ -322,7 +346,8 @@ void audio_set_recording_options(int frequency, int quality,
322 346
323 /* Monitoring: route the signals through the coldfire audio interface. */ 347 /* Monitoring: route the signals through the coldfire audio interface. */
324 348
325 IIS2CONFIG = 0x800; /* Reset before reprogram */ 349 SET_IIS_PLAY(0x800); /* Reset before reprogram */
350
326#ifdef HAVE_SPDIF_IN 351#ifdef HAVE_SPDIF_IN
327 if (source == 2) { 352 if (source == 2) {
328 /* SCLK2 = Audioclk/4 (can't use EBUin clock), TXSRC = EBU1rcv, 64 bclk/wclk */ 353 /* SCLK2 = Audioclk/4 (can't use EBUin clock), TXSRC = EBU1rcv, 64 bclk/wclk */
@@ -340,21 +365,27 @@ void audio_set_recording_options(int frequency, int quality,
340 } 365 }
341#else 366#else
342 /* SCLK2 follow IIS1 (UDA clock), TXSRC = IIS1rcv, 64 bclk/wclk */ 367 /* SCLK2 follow IIS1 (UDA clock), TXSRC = IIS1rcv, 64 bclk/wclk */
343 IIS2CONFIG = (8 << 12) | (4 << 8) | (4 << 2); 368 SET_IIS_PLAY( (8 << 12) | (4 << 8) | (4 << 2) );
344#endif 369#endif
345} 370}
346 371
347 372
348/** 373/**
349 * Note that microphone is mono, only left value is used 374 * Note that microphone is mono, only left value is used
350 * See uda1380_set_recvol() for exact ranges. 375 * See {uda1380,tlv320}_set_recvol() for exact ranges.
351 * 376 *
352 * @param type 0=line-in (radio), 1=mic 377 * @param type 0=line-in (radio), 1=mic
353 * 378 *
354 */ 379 */
355void audio_set_recording_gain(int left, int right, int type) 380void audio_set_recording_gain(int left, int right, int type)
356{ 381{
382 //logf("rcmrec: t=%d l=%d r=%d", type, left, right);
383#ifdef HAVE_UDA1380
357 uda1380_set_recvol(left, right, type); 384 uda1380_set_recvol(left, right, type);
385#endif
386#ifdef HAVE_TLV320
387 tlv320_set_recvol(left, right, type);
388#endif
358} 389}
359 390
360 391
@@ -987,7 +1018,7 @@ static void pcmrec_init(void)
987 1018
988 logf("num_chunks: %d", num_chunks); 1019 logf("num_chunks: %d", num_chunks);
989 1020
990 IIS1CONFIG = 0x800; /* Stop any playback */ 1021 SET_IIS_PLAY(0x800); /* Stop any playback */
991 AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */ 1022 AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */
992 DATAINCONTROL = 0xc000; /* Generate Interrupt when 6 samples in fifo */ 1023 DATAINCONTROL = 0xc000; /* Generate Interrupt when 6 samples in fifo */
993 1024
@@ -1007,7 +1038,12 @@ static void pcmrec_init(void)
1007 1038
1008static void pcmrec_close(void) 1039static void pcmrec_close(void)
1009{ 1040{
1041#ifdef HAVE_UDA1380
1010 uda1380_disable_recording(); 1042 uda1380_disable_recording();
1043#endif
1044#ifdef HAVE_TLV320
1045 tlv320_disable_recording();
1046#endif
1011 1047
1012#ifdef HAVE_SPDIF_POWER 1048#ifdef HAVE_SPDIF_POWER
1013 spdif_power_enable(spdif_power_setting); 1049 spdif_power_enable(spdif_power_setting);
@@ -1091,7 +1127,7 @@ void pcm_rec_mux(int source)
1091 1127
1092 or_l(0x40000000, &GPIO_ENABLE); 1128 or_l(0x40000000, &GPIO_ENABLE);
1093 or_l(0x40000000, &GPIO_FUNCTION); 1129 or_l(0x40000000, &GPIO_FUNCTION);
1094#else 1130#elif defined(IRIVER_H100_SERIES)
1095 if(source == 0) 1131 if(source == 0)
1096 and_l(~0x00800000, &GPIO_OUT); /* Line In */ 1132 and_l(~0x00800000, &GPIO_OUT); /* Line In */
1097 else 1133 else
@@ -1099,5 +1135,16 @@ void pcm_rec_mux(int source)
1099 1135
1100 or_l(0x00800000, &GPIO_ENABLE); 1136 or_l(0x00800000, &GPIO_ENABLE);
1101 or_l(0x00800000, &GPIO_FUNCTION); 1137 or_l(0x00800000, &GPIO_FUNCTION);
1138
1139#elif defined(IAUDIO_X5)
1140 if(source == 0)
1141 or_l((1<<29), &GPIO_OUT); /* Line In */
1142 else
1143 and_l(~(1<<29), &GPIO_OUT); /* FM radio */
1144
1145 or_l((1<<29), &GPIO_ENABLE);
1146 or_l((1<<29), &GPIO_FUNCTION);
1147
1148 /* iAudio x5 */
1102#endif 1149#endif
1103} 1150}
diff --git a/firmware/sound.c b/firmware/sound.c
index 057cfc0995..5e4cd5db48 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -111,7 +111,11 @@ static const struct sound_settings_info sound_settings_table[] = {
111 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL}, 111 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
112 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL}, 112 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0, NULL},
113 [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16, NULL}, 113 [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16, NULL},
114#endif 114#elif defined(HAVE_TLV320)
115 [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23, NULL},
116 [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23, NULL},
117 [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 1, NULL},
118 #endif
115}; 119};
116 120
117const char *sound_unit(int setting) 121const char *sound_unit(int setting)
@@ -901,6 +905,25 @@ int sound_val2phys(int setting, int value)
901 break; 905 break;
902 } 906 }
903 return result; 907 return result;
908#elif defined(HAVE_TLV320)
909 int result = 0;
910
911 switch(setting)
912 {
913 case SOUND_LEFT_GAIN:
914 case SOUND_RIGHT_GAIN:
915 result = (value - 23) * 15; /* (x - 23)/1.5 *10 */
916 break;
917
918 case SOUND_MIC_GAIN:
919 result = value * 200; /* 0 or 20 dB */
920 break;
921
922 default:
923 result = value;
924 break;
925 }
926 return result;
904#else 927#else
905 (void)setting; 928 (void)setting;
906 return value; 929 return value;
diff --git a/firmware/target/coldfire/iaudio/x5/power-x5.c b/firmware/target/coldfire/iaudio/x5/power-x5.c
index 14236cbb37..4199993637 100644
--- a/firmware/target/coldfire/iaudio/x5/power-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/power-x5.c
@@ -64,6 +64,20 @@ void power_off(void)
64 yield(); 64 yield();
65} 65}
66 66
67static bool powered = false;
68
69bool radio_powered()
70{
71 return powered;
72}
73
74bool radio_power(bool status)
75{
76 bool old_status = powered;
77 powered = status;
78 return old_status;
79}
80
67#else 81#else
68 82
69bool charger_inserted(void) 83bool charger_inserted(void)