From 1fea6f6b22af74e904d918fff4cebec345529f4b Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Sat, 27 Dec 2008 19:18:50 +0000 Subject: Make si4700 tuner driver more sane with bit and field defines and entirely hide strange i2c interface from code with write/set/clear/masked functionality. On Gigabeat S use by-the-book busmode selection and GPIO lines. Implement some primitive station detection, debug registers in screen, and misc. changes to tie things together. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19600 a1c6a512-1295-4272-9138-f99709370657 --- .../arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c | 75 +++++++++++++++++++++- firmware/target/arm/imx31/gigabeat-s/power-imx31.c | 43 +++++-------- 2 files changed, 91 insertions(+), 27 deletions(-) (limited to 'firmware/target/arm/imx31/gigabeat-s') 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 index 154e13f9a7..7646402435 100644 --- a/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c @@ -21,6 +21,7 @@ ****************************************************************************/ #include "config.h" #include "system.h" +#include "mc13783.h" #include "i2c-imx31.h" #include "fmradio_i2c.h" @@ -33,9 +34,77 @@ static struct i2c_node si4700_i2c_node = .addr = (0x20), }; +void fmradio_i2c_init(void) +{ + /* RST: LOW */ + imx31_regclr32(&GPIO1_DR, (1 << 26)); + /* RST: OUT */ + imx31_regset32(&GPIO1_GDIR, (1 << 26)); + + /* I2C2 SCL: IN, I2C2: SDA IN */ + imx31_regclr32(&GPIO2_GDIR, (3 << 14)); + /* I2C2 SCL LO, I2C2 SDA LO */ + imx31_regclr32(&GPIO2_DR, (3 << 14)); + + /* open-drain pins - external pullups on PCB. Pullup default but + * disabled */ + imx31_regmod32(&SW_PAD_CTL_DSR_DTE1_RI_DTE1_DCD_DTE1, + /* RI_DTE1 (I2C2_SCLK) */ + SW_PAD_CTL_IO2w(SW_PAD_CTL_PUE_PKE_DISABLE | + SW_PAD_CTL_PUS_UP_100K | + SW_PAD_CTL_HYS | + SW_PAD_CTL_ODE) | + /* DCD_DTE1 (I2C2_SDA) */ + SW_PAD_CTL_IO1w(SW_PAD_CTL_PUE_PKE_DISABLE | + SW_PAD_CTL_PUS_UP_100K | + SW_PAD_CTL_HYS | + SW_PAD_CTL_ODE), + SW_PAD_CTL_IO2 | SW_PAD_CTL_IO1); + /* set outputs to I2C2 */ + imx31_regmod32(&SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2, + /* RI_DTE1 => I2C2_SCLK */ + SW_MUX_CTL_SIG4w(SW_MUX_OUT_ALT2 | SW_MUX_IN_ALT2) | + /* DCD_DTE1 => I2C2_SDA */ + SW_MUX_CTL_SIG3w(SW_MUX_OUT_ALT2 | SW_MUX_IN_ALT2), + SW_MUX_CTL_SIG4 | SW_MUX_CTL_SIG3); +} + void fmradio_i2c_enable(bool enable) { - i2c_enable_node(&si4700_i2c_node, enable); + if (enable) + { + uint32_t io_pin_mux = SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2; + /* place in GPIO mode to hold SDIO low during RESET release, + * SEN1 should be high already (pullup) and GPIO3 left alone */ + imx31_regset32(&GPIO2_GDIR, (1 << 15)); /* SDIO OUT */ + /* I2C2_SDA => MCU2_15 */ + imx31_regmod32(&SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2, + SW_MUX_CTL_SIG3w(SW_MUX_OUT_GPIO_DR | SW_MUX_IN_GPIO_PSR_ISR), + SW_MUX_CTL_SIG3); + /* enable CLK32KMCU clock */ + mc13783_set(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN); + /* enable the fm chip (release RESET) */ + imx31_regset32(&GPIO1_DR, (1 << 26)); + sleep(HZ/100); + /* busmode should be selected - OK to release SDIO */ + imx31_regclr32(&GPIO2_GDIR, (1 << 15)); /* SDIO IN */ + /* restore pin mux (DCD_DTE1 => I2C2_SDA) */ + imx31_regmod32(&SW_MUX_CTL_RI_DTE1_DCD_DTE1_DTR_DCE2_RXD2, + io_pin_mux, SW_MUX_CTL_SIG3); + /* the si4700 is the only thing connected to i2c2 so + we can diable the i2c module when not in use */ + i2c_enable_node(&si4700_i2c_node, true); + } + else + { + /* the si4700 is the only thing connected to i2c2 so + we can diable the i2c module when not in use */ + i2c_enable_node(&si4700_i2c_node, false); + /* disable the fm chip */ + imx31_regclr32(&GPIO1_DR, (1 << 26)); + /* disable CLK32KMCU clock */ + mc13783_clear(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN); + } } int fmradio_i2c_write(unsigned char address, const unsigned char* buf, int count) @@ -52,3 +121,7 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) return 0; } +int si4700_st(void) +{ + return (GPIO1_DR & (1 << 28)) >> 28; +} diff --git a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c index 727b38bd96..b29d3cd0fb 100644 --- a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c @@ -98,37 +98,24 @@ bool ide_powered(void) } #if CONFIG_TUNER +static bool tuner_on = false; + bool tuner_power(bool status) { - static bool tuner_powered = false; - - if (status == tuner_powered) - return status; - - tuner_powered = status; - - if (status) - { - /* the si4700 is the only thing connected to i2c2 so - we can diable the i2c module when not in use */ - fmradio_i2c_enable(true); - /* enable the fm chip */ - imx31_regset32(&GPIO1_DR, (1 << 26)); - /* enable CLK32KMCU clock */ - mc13783_set(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN); - } - else + if (status != tuner_on) { - /* the si4700 is the only thing connected to i2c2 so - we can diable the i2c module when not in use */ - fmradio_i2c_enable(false); - /* disable the fm chip */ - imx31_regclr32(&GPIO1_DR, (1 << 26)); - /* disable CLK32KMCU clock */ - mc13783_clear(MC13783_POWER_CONTROL0, MC13783_CLK32KMCUEN); + tuner_on = status; + /* Handle power and pin setup */ + fmradio_i2c_enable(status); + status = !status; } - return !status; + return status; +} + +bool tuner_powered(void) +{ + return tuner_on; } #endif /* #if CONFIG_TUNER */ @@ -151,6 +138,10 @@ void power_off(void) void power_init(void) { +#if CONFIG_TUNER + fmradio_i2c_init(); +#endif + /* Poll initial state */ charger_main_detect_event(); -- cgit v1.2.3