summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNils Wallménius <nils@rockbox.org>2008-12-09 20:48:04 +0000
committerNils Wallménius <nils@rockbox.org>2008-12-09 20:48:04 +0000
commit65f61d6cce4a5d3b52860d38a922b01fcddc70cd (patch)
tree03f8167279828845dcd4923d8184bc58d0e165da
parenta13c16271911be641539cace3ea5ea0c1440eeaf (diff)
downloadrockbox-65f61d6cce4a5d3b52860d38a922b01fcddc70cd.tar.gz
rockbox-65f61d6cce4a5d3b52860d38a922b01fcddc70cd.zip
FS#9609 FM radio support for the Gigabeat S, seeking/scanning is not yet
implemented but manual tuning works nicely. Thanks to Rafaël Carré, Bertrik Sikken and Robert Menes for suggestions and debugging help. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19372 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/keymaps/keymap-gigabeat-s.c18
-rw-r--r--apps/recorder/radio.c6
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/drivers/audio/wm8978.c12
-rw-r--r--firmware/drivers/tuner/si4700.c151
-rw-r--r--firmware/export/audio.h1
-rw-r--r--firmware/export/config-gigabeat-s.h7
-rw-r--r--firmware/export/si4700.h12
-rw-r--r--firmware/export/wm8978.h3
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c56
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c49
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/power-imx31.c30
-rw-r--r--firmware/tuner.c16
13 files changed, 354 insertions, 9 deletions
diff --git a/apps/keymaps/keymap-gigabeat-s.c b/apps/keymaps/keymap-gigabeat-s.c
index a60fd2d8a1..b0cc87011f 100644
--- a/apps/keymaps/keymap-gigabeat-s.c
+++ b/apps/keymaps/keymap-gigabeat-s.c
@@ -276,6 +276,22 @@ static const struct button_mapping button_context_keyboard[] = {
276 LAST_ITEM_IN_LIST 276 LAST_ITEM_IN_LIST
277}; /* button_context_keyboard */ 277}; /* button_context_keyboard */
278 278
279static const struct button_mapping button_context_radio[] = {
280 { ACTION_FM_MENU, BUTTON_SELECT | BUTTON_REPEAT, BUTTON_NONE },
281 { ACTION_FM_PRESET, BUTTON_SELECT | BUTTON_REL, BUTTON_SELECT },
282 { ACTION_FM_STOP, BUTTON_POWER, BUTTON_NONE },
283 { ACTION_FM_MODE, BUTTON_MENU, BUTTON_NONE },
284 { ACTION_FM_EXIT, BUTTON_BACK, BUTTON_NONE },
285 { ACTION_FM_PLAY, BUTTON_PLAY, BUTTON_NONE },
286 { ACTION_SETTINGS_INC, BUTTON_VOL_UP, BUTTON_NONE },
287 { ACTION_SETTINGS_INCREPEAT, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
288 { ACTION_SETTINGS_DEC, BUTTON_VOL_DOWN, BUTTON_NONE },
289 { ACTION_SETTINGS_DECREPEAT, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
290
291
292 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS)
293};
294
279const struct button_mapping* get_context_mapping(int context) 295const struct button_mapping* get_context_mapping(int context)
280{ 296{
281 switch (context) 297 switch (context)
@@ -319,6 +335,8 @@ const struct button_mapping* get_context_mapping(int context)
319 return button_context_pitchscreen; 335 return button_context_pitchscreen;
320 case CONTEXT_KEYBOARD: 336 case CONTEXT_KEYBOARD:
321 return button_context_keyboard; 337 return button_context_keyboard;
338 case CONTEXT_FM:
339 return button_context_radio;
322 } 340 }
323 return button_context_standard; 341 return button_context_standard;
324} 342}
diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c
index 5f9fff8d64..dee38b5475 100644
--- a/apps/recorder/radio.c
+++ b/apps/recorder/radio.c
@@ -104,13 +104,17 @@
104#define FM_MODE 104#define FM_MODE
105#define FM_EXIT 105#define FM_EXIT
106#define FM_PLAY 106#define FM_PLAY
107
108#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
109#define FM_PRESET
110#define FM_MODE
107#endif 111#endif
108 112
109#define RADIO_SCAN_MODE 0 113#define RADIO_SCAN_MODE 0
110#define RADIO_PRESET_MODE 1 114#define RADIO_PRESET_MODE 1
111 115
112static int curr_preset = -1; 116static int curr_preset = -1;
113static int curr_freq; 117static int curr_freq; /* current frequency in Hz */
114static int radio_mode = RADIO_SCAN_MODE; 118static int radio_mode = RADIO_SCAN_MODE;
115static int search_dir = 0; 119static int search_dir = 0;
116 120
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 68d10876c8..1fce6cfdb5 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -764,6 +764,8 @@ target/arm/imx31/gigabeat-s/usb-imx31.c
764target/arm/imx31/gigabeat-s/wmcodec-imx31.c 764target/arm/imx31/gigabeat-s/wmcodec-imx31.c
765#ifndef BOOTLOADER 765#ifndef BOOTLOADER
766target/arm/imx31/gigabeat-s/pcm-imx31.c 766target/arm/imx31/gigabeat-s/pcm-imx31.c
767target/arm/imx31/gigabeat-s/audio-gigabeat-s.c
768target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c
767#endif 769#endif
768#endif /* SIMULATOR */ 770#endif /* SIMULATOR */
769#endif /* GIGABEAT_S */ 771#endif /* GIGABEAT_S */
diff --git a/firmware/drivers/audio/wm8978.c b/firmware/drivers/audio/wm8978.c
index c2c19ca7be..6a7c974f43 100644
--- a/firmware/drivers/audio/wm8978.c
+++ b/firmware/drivers/audio/wm8978.c
@@ -144,12 +144,12 @@ static void wmc_write(unsigned int reg, unsigned int val)
144 wmcodec_write(reg, val); 144 wmcodec_write(reg, val);
145} 145}
146 146
147static void wmc_set(unsigned int reg, unsigned int bits) 147void wmc_set(unsigned int reg, unsigned int bits)
148{ 148{
149 wmc_write(reg, wmc_regs[reg] | bits); 149 wmc_write(reg, wmc_regs[reg] | bits);
150} 150}
151 151
152static void wmc_clear(unsigned int reg, unsigned int bits) 152void wmc_clear(unsigned int reg, unsigned int bits)
153{ 153{
154 wmc_write(reg, wmc_regs[reg] & ~bits); 154 wmc_write(reg, wmc_regs[reg] & ~bits);
155} 155}
@@ -226,6 +226,14 @@ void audiohw_postinit(void)
226 wmc_write(WMC_AUDIO_INTERFACE, WMC_WL_16 | WMC_FMT_I2S); 226 wmc_write(WMC_AUDIO_INTERFACE, WMC_WL_16 | WMC_FMT_I2S);
227 wmc_write(WMC_DAC_CONTROL, WMC_DACOSR_128 | WMC_AMUTE); 227 wmc_write(WMC_DAC_CONTROL, WMC_DACOSR_128 | WMC_AMUTE);
228 228
229 wmc_set(WMC_INPUT_CTRL, WMC_R2_2INPPGA | WMC_L2_2INPPGA);
230 wmc_set(WMC_LEFT_INP_PGA_GAIN_CTRL, 0x3f);
231 wmc_set(WMC_RIGHT_INP_PGA_GAIN_CTRL, 0x3f);
232 wmc_set(WMC_LEFT_INP_PGA_GAIN_CTRL, 1<<8);
233 wmc_set(WMC_RIGHT_INP_PGA_GAIN_CTRL, 1<<8);
234 wmc_set(WMC_LEFT_ADC_BOOST_CTRL, (7<<3));
235 wmc_set(WMC_RIGHT_ADC_BOOST_CTRL, (7<<3));
236
229 /* Specific to HW clocking */ 237 /* Specific to HW clocking */
230 wmc_write_masked(WMC_CLOCK_GEN_CTRL, WMC_BCLKDIV_4 | WMC_MS, 238 wmc_write_masked(WMC_CLOCK_GEN_CTRL, WMC_BCLKDIV_4 | WMC_MS,
231 WMC_BCLKDIV | WMC_MS | WMC_CLKSEL); 239 WMC_BCLKDIV | WMC_MS | WMC_CLKSEL);
diff --git a/firmware/drivers/tuner/si4700.c b/firmware/drivers/tuner/si4700.c
index 9233afae24..a55a8cfcc4 100644
--- a/firmware/drivers/tuner/si4700.c
+++ b/firmware/drivers/tuner/si4700.c
@@ -9,7 +9,7 @@
9 * 9 *
10 * Tuner "middleware" for Silicon Labs SI4700 chip 10 * Tuner "middleware" for Silicon Labs SI4700 chip
11 * 11 *
12 * Copyright (C) 2008 ??? 12 * Copyright (C) 2008 Nils Wallménius
13 * 13 *
14 * This program is free software; you can redistribute it and/or 14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License 15 * modify it under the terms of the GNU General Public License
@@ -29,19 +29,160 @@
29#include "fmradio.h" 29#include "fmradio.h"
30#include "fmradio_i2c.h" /* physical interface driver */ 30#include "fmradio_i2c.h" /* physical interface driver */
31 31
32#define I2C_ADR 0x20
33
34/* I2C writes start at register 02h so the first two bytes are
35 02h, next two 03h, etc. */
36static unsigned char write_bytes[8]; /* registers 02 - 05 */
37static bool tuner_present = false;
38
39void si4700_init(void)
40{
41 unsigned char read_bytes[32];
42 tuner_power(true);
43 fmradio_i2c_read(I2C_ADR, read_bytes, sizeof(read_bytes));
44
45 if ((read_bytes[12] << 8 | read_bytes[13]) == 0x1242)
46 {
47 tuner_present = true;
48 /* fill in the initial values in write_bytes */
49 memcpy(&write_bytes[0], &read_bytes[16], sizeof(write_bytes));
50 /* -6dB volume, keep everything else as default */
51 write_bytes[7] = (write_bytes[7] & ~0xf) | 0xc;
52 }
53
54 tuner_power(false);
55}
56
57static void si4700_tune(void)
58{
59 unsigned char read_bytes[1];
60
61 write_bytes[2] |= (1 << 7); /* Set TUNE high to start tuning */
62 fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes));
63
64 do
65 {
66 sleep(HZ/50);
67 fmradio_i2c_read(I2C_ADR, read_bytes, 1);
68 }
69 while (!(read_bytes[0] & (1 << 6))); /* STC high == Seek/Tune complete */
70
71 write_bytes[2] &= ~(1 << 7); /* Set TUNE low */
72 fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes));
73}
74
32/* tuner abstraction layer: set something to the tuner */ 75/* tuner abstraction layer: set something to the tuner */
33int si4700_set(int setting, int value) 76int si4700_set(int setting, int value)
34{ 77{
35 (void)setting; 78 switch(setting)
36 (void)value; 79 {
80 case RADIO_SLEEP:
81 if (value)
82 {
83 write_bytes[1] = (1 | (1 << 6)); /* ENABLE high, DISABLE high */
84 }
85 else
86 {
87 write_bytes[1] = 1; /* ENABLE high, DISABLE low */
88 }
89 break;
37 90
91 case RADIO_FREQUENCY:
92 {
93 static const unsigned int spacings[3] =
94 {
95 200000, 100000, 50000
96 };
97 unsigned int chan;
98 unsigned int spacing = spacings[(write_bytes[7] >> 4) & 3] ;
99
100 if (write_bytes[7] & (3 << 6)) /* check BAND */
101 {
102 chan = (value - 76000000) / spacing;
103 }
104 else
105 {
106 chan = (value - 87500000) / spacing;
107 }
108
109 write_bytes[2] = (write_bytes[2] & ~3) | ((chan & (3 << 8)) >> 8);
110 write_bytes[3] = (chan & 0xff);
111 fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes));
112 si4700_tune();
113 return 1;
114 }
115
116 case RADIO_SCAN_FREQUENCY:
117 si4700_set(RADIO_FREQUENCY, value);
118 return 1;
119
120 case RADIO_MUTE:
121 if (value)
122 {
123 /* mute */
124 write_bytes[0] &= ~(1 << 6);
125 }
126 else
127 {
128 /* unmute */
129 write_bytes[0] |= (1 << 6);
130 }
131 break;
132
133 case RADIO_REGION:
134 {
135 const struct si4700_region_data *rd =
136 &si4700_region_data[value];
137
138 write_bytes[4] = ((write_bytes[4] & ~(1 << 3)) | (rd->deemphasis << 3));
139 write_bytes[7] = ((write_bytes[7] & ~(3 << 6)) | (rd->band << 6));
140 write_bytes[7] = ((write_bytes[7] & ~(3 << 4)) | (rd->spacing << 4));
141 break;
142 }
143
144 case RADIO_FORCE_MONO:
145 if (value)
146 {
147 write_bytes[0] |= (1 << 5);
148 }
149 else
150 {
151 write_bytes[0] &= ~(1 << 5);
152 }
153 break;
154
155 default:
156 return -1;
157 }
158
159 fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes));
38 return 1; 160 return 1;
39} 161}
40 162
41/* tuner abstraction layer: read something from the tuner */ 163/* tuner abstraction layer: read something from the tuner */
42int si4700_get(int setting) 164int si4700_get(int setting)
43{ 165{
44 (void)setting; 166 /* I2C reads start with register 0xA */
167 unsigned char read_bytes[1];
168 int val = -1; /* default for unsupported query */
169
170 switch(setting)
171 {
172 case RADIO_PRESENT:
173 val = tuner_present ? 1 : 0;
174 break;
45 175
46 return -1; 176 case RADIO_TUNED:
177 val = 1;
178 break;
179
180 case RADIO_STEREO:
181 fmradio_i2c_read(I2C_ADR, read_bytes, sizeof(read_bytes));
182 val = (read_bytes[0] & 1); /* ST high == Stereo */
183 break;
184 }
185
186 return val;
47} 187}
188
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index 661247df2f..4f9ef1a4e1 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -23,6 +23,7 @@
23 23
24#include <stdbool.h> 24#include <stdbool.h>
25#include <sys/types.h> 25#include <sys/types.h>
26#include "config.h"
26/* These must always be included with audio.h for this to compile under 27/* These must always be included with audio.h for this to compile under
27 cetain conditions. Do it here or else spread the complication around to 28 cetain conditions. Do it here or else spread the complication around to
28 many files. */ 29 many files. */
diff --git a/firmware/export/config-gigabeat-s.h b/firmware/export/config-gigabeat-s.h
index 72b1cb76a8..c893061d0d 100644
--- a/firmware/export/config-gigabeat-s.h
+++ b/firmware/export/config-gigabeat-s.h
@@ -69,9 +69,14 @@
69/* The number of bytes reserved for loadable plugins */ 69/* The number of bytes reserved for loadable plugins */
70#define PLUGIN_BUFFER_SIZE 0x80000 70#define PLUGIN_BUFFER_SIZE 0x80000
71 71
72/* Define this if you have a SI4700 fm radio tuner */
73#define CONFIG_TUNER SI4700
74
72/* Define this if you have the WM8978 audio codec */ 75/* Define this if you have the WM8978 audio codec */
73#define HAVE_WM8978 76#define HAVE_WM8978
74 77
78#define INPUT_SRC_CAPS SRC_CAP_FMRADIO
79
75#define HW_SAMPR_CAPS (SAMPR_CAP_48 | SAMPR_CAP_44 | SAMPR_CAP_32 | \ 80#define HW_SAMPR_CAPS (SAMPR_CAP_48 | SAMPR_CAP_44 | SAMPR_CAP_32 | \
76 SAMPR_CAP_24 | SAMPR_CAP_22 | SAMPR_CAP_16 | \ 81 SAMPR_CAP_24 | SAMPR_CAP_22 | SAMPR_CAP_16 | \
77 SAMPR_CAP_12 | SAMPR_CAP_11 | SAMPR_CAP_8) 82 SAMPR_CAP_12 | SAMPR_CAP_11 | SAMPR_CAP_8)
@@ -114,7 +119,7 @@
114 119
115/* Define the bitmask of modules used */ 120/* Define the bitmask of modules used */
116#define SPI_MODULE_MASK (USE_CSPI2_MODULE) 121#define SPI_MODULE_MASK (USE_CSPI2_MODULE)
117#define I2C_MODULE_MASK (USE_I2C1_MODULE) 122#define I2C_MODULE_MASK (USE_I2C1_MODULE | USE_I2C2_MODULE)
118#define GPIO_EVENT_MASK (USE_GPIO1_EVENTS) 123#define GPIO_EVENT_MASK (USE_GPIO1_EVENTS)
119 124
120/* Define this if target has an additional number of threads specific to it */ 125/* Define this if target has an additional number of threads specific to it */
diff --git a/firmware/export/si4700.h b/firmware/export/si4700.h
index a740ae03ab..5b8001f753 100644
--- a/firmware/export/si4700.h
+++ b/firmware/export/si4700.h
@@ -25,6 +25,18 @@
25#ifndef _SI4700_H_ 25#ifndef _SI4700_H_
26#define _SI4700_H_ 26#define _SI4700_H_
27 27
28#define HAVE_RADIO_REGION
29
30struct si4700_region_data
31{
32 unsigned char deemphasis; /* 0: 50us, 1: 75us */
33 unsigned char band; /* 0: us/europe, 1: japan */
34 unsigned char spacing; /* 0: us/australia (200kHz), 1: europe/japan (100kHz), 2: (50kHz) */
35} __attribute__((packed));
36
37extern const struct si4700_region_data si4700_region_data[TUNER_NUM_REGIONS];
38
39void si4700_init(void);
28int si4700_set(int setting, int value); 40int si4700_set(int setting, int value);
29int si4700_get(int setting); 41int si4700_get(int setting);
30 42
diff --git a/firmware/export/wm8978.h b/firmware/export/wm8978.h
index f4ed46a6e2..9c54ae354d 100644
--- a/firmware/export/wm8978.h
+++ b/firmware/export/wm8978.h
@@ -30,6 +30,9 @@ int tenthdb2master(int db);
30void audiohw_set_headphone_vol(int vol_l, int vol_r); 30void audiohw_set_headphone_vol(int vol_l, int vol_r);
31void audiohw_set_frequency(int sampling_control); 31void audiohw_set_frequency(int sampling_control);
32 32
33void wmc_set(unsigned int reg, unsigned int bits);
34void wmc_clear(unsigned int reg, unsigned int bits);
35
33#define WMC_I2C_ADDR 0x34 36#define WMC_I2C_ADDR 0x34
34 37
35/* Registers */ 38/* Registers */
diff --git a/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c
new file mode 100644
index 0000000000..6dd90bfdb7
--- /dev/null
+++ b/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c
@@ -0,0 +1,56 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Nils Wallménius
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#include "wm8978.h"
22#include "audio.h"
23
24void audio_set_output_source(int source)
25{
26 (void)source; /* TODO */
27}
28
29void audio_input_mux(int source, unsigned int flags)
30{
31 (void)flags;
32 switch (source)
33 {
34 case AUDIO_SRC_PLAYBACK:
35 /* deselect bypass patths and set volume to -15dB */
36 wmc_clear(WMC_LEFT_MIXER_CTRL, (WMC_BYPL2LMIX) | (7<<2));
37 wmc_clear(WMC_RIGHT_MIXER_CTRL, (WMC_BYPR2RMIX) | (7<<2));
38 /* disable L2/R2 inputs and boost stage */
39 wmc_clear(WMC_POWER_MANAGEMENT2,
40 WMC_INPPGAENR | WMC_INPPGAENL | WMC_BOOSTENL | WMC_BOOSTENR);
41 break;
42
43 case AUDIO_SRC_FMRADIO:
44 /* enable L2/R2 inputs and boost stage */
45 wmc_set(WMC_POWER_MANAGEMENT2,
46 WMC_INPPGAENR | WMC_INPPGAENL | WMC_BOOSTENL | WMC_BOOSTENR);
47 /* select bypass patths and set volume to 0dB */
48 wmc_set(WMC_LEFT_MIXER_CTRL, (WMC_BYPL2LMIX) | (5<<2));
49 wmc_set(WMC_RIGHT_MIXER_CTRL, (WMC_BYPR2RMIX) | (5<<2));
50 break;
51
52 default:
53 source = AUDIO_SRC_PLAYBACK;
54 }
55}
56
diff --git a/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c
new file mode 100644
index 0000000000..5e5c4853dd
--- /dev/null
+++ b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c
@@ -0,0 +1,49 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 * Physical interface of the SI4700 in the Gigabeat S
10 *
11 * Copyright (C) 2008 by Nils Wallménius
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#include "config.h"
23#include "system.h"
24#include "i2c-imx31.h"
25#include "fmradio_i2c.h"
26
27struct i2c_node si4700_i2c_node =
28{
29 .num = I2C2_NUM,
30 .ifdr = I2C_IFDR_DIV192, /* 66MHz/.4MHz = 165, closest = 192 = 343750Hz */
31 /* Just hard-code for now - scaling may require
32 * updating */
33 .addr = (0x20),
34};
35
36int fmradio_i2c_write(unsigned char address, const unsigned char* buf, int count)
37{
38 (void)address;
39 i2c_write(&si4700_i2c_node, buf, count);
40 return 0;
41}
42
43int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
44{
45 (void)address;
46 i2c_read(&si4700_i2c_node, -1, buf, count);
47 return 0;
48}
49
diff --git a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c
index de7f5800e6..07e6462bfb 100644
--- a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c
@@ -26,6 +26,9 @@
26#include "backlight-target.h" 26#include "backlight-target.h"
27#include "avic-imx31.h" 27#include "avic-imx31.h"
28#include "mc13783.h" 28#include "mc13783.h"
29#include "i2c-imx31.h"
30
31extern struct i2c_node si4700_i2c_node;
29 32
30static bool charger_detect = false; 33static bool charger_detect = false;
31 34
@@ -79,6 +82,33 @@ bool ide_powered(void)
79 return (GPIO3_DR & (1 << 5)) != 0; 82 return (GPIO3_DR & (1 << 5)) != 0;
80} 83}
81 84
85#if CONFIG_TUNER
86bool tuner_power(bool status)
87{
88 if (status)
89 {
90 /* the si4700 is the only thing connected to i2c2 so
91 we can diable the i2c module when not in use */
92 i2c_enable_node(&si4700_i2c_node, true);
93 /* enable the fm chip */
94 imx31_regmod32(&GPIO1_DR, (1 << 26), (1 << 26));
95 /* enable CLK32KMCU clock */
96 mc13783_set(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN);
97 }
98 else
99 {
100 /* the si4700 is the only thing connected to i2c2 so
101 we can diable the i2c module when not in use */
102 i2c_enable_node(&si4700_i2c_node, false);
103 /* disable the fm chip */
104 imx31_regmod32(&GPIO1_DR, 0, (1 << 26));
105 /* disable CLK32KMCU clock */
106 mc13783_clear(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN);
107 }
108 return true;
109}
110#endif /* #if CONFIG_TUNER */
111
82void power_off(void) 112void power_off(void)
83{ 113{
84 /* Cut backlight */ 114 /* Cut backlight */
diff --git a/firmware/tuner.c b/firmware/tuner.c
index 6a7c1b4237..22cb981038 100644
--- a/firmware/tuner.c
+++ b/firmware/tuner.c
@@ -59,6 +59,16 @@ const struct tea5767_region_data tea5767_region_data[TUNER_NUM_REGIONS] =
59}; 59};
60#endif /* (CONFIG_TUNER & TEA5767) */ 60#endif /* (CONFIG_TUNER & TEA5767) */
61 61
62#if (CONFIG_TUNER & SI4700)
63const struct si4700_region_data si4700_region_data[TUNER_NUM_REGIONS] =
64{
65 [REGION_EUROPE] = { 0, 0, 2 }, /* 50uS, US/Europe band, 50kHz spacing */
66 [REGION_US_CANADA] = { 1, 0, 0 }, /* 75uS, US/Europe band, 200kHz spacing */
67 [REGION_JAPAN] = { 0, 1, 1 }, /* 50uS, Japanese band, 100kHz spacing */
68 [REGION_KOREA] = { 0, 0, 1 }, /* 50uS, US/Europe band, 100kHz spacing */
69};
70#endif /* (CONFIG_TUNER & SI4700) */
71
62#ifdef CONFIG_TUNER_MULTI 72#ifdef CONFIG_TUNER_MULTI
63int (*tuner_set)(int setting, int value); 73int (*tuner_set)(int setting, int value);
64int (*tuner_get)(int setting); 74int (*tuner_get)(int setting);
@@ -95,6 +105,12 @@ void tuner_init(void)
95 s1a0903x01_set, 105 s1a0903x01_set,
96 s1a0903x01_get) 106 s1a0903x01_get)
97 #endif 107 #endif
108 #if (CONFIG_TUNER & SI4700)
109 TUNER_TYPE_CASE(SI4700,
110 si4700_set,
111 si4700_get,
112 si4700_init())
113 #endif
98 } 114 }
99} 115}
100 116