From 1d21e54fc4f586bbdfb765c90c9a64c060eeecc4 Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Thu, 10 May 2012 18:29:43 +0200 Subject: [PATCH] fuze+: add RDS support I successfully identified the STC/RDS pin as B2P27. Strangely the OF uses polling instead of interrupts but since they routed it, let's use it! On the fuze+ the fmradio i2c uses bit toggling so we can't read the RDS data in the interrupt context. Instead we defer the work to a thread. Change-Id: Iedfa425320e6c91b4351b72e97c732696bdb2b73 Reviewed-on: http://gerrit.rockbox.org/236 Reviewed-by: Bertrik Sikken Reviewed-by: Amaury Pouly --- firmware/export/config/sansafuzeplus.h | 5 +- .../sansa-fuzeplus/fmradio-i2c-fuzeplus.c | 60 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/firmware/export/config/sansafuzeplus.h b/firmware/export/config/sansafuzeplus.h index 9d7b9bf756..810cc1d6a1 100644 --- a/firmware/export/config/sansafuzeplus.h +++ b/firmware/export/config/sansafuzeplus.h @@ -77,6 +77,7 @@ #define HAVE_IMX233_CODEC #define CONFIG_TUNER SI4700 +#define HAVE_RDS_CAP /* There is no hardware tone control */ #define HAVE_SW_TONE_CONTROLS @@ -129,8 +130,8 @@ #define NUM_DRIVES 2 #define HAVE_HOTSWAP -/* Extra threads: touchpad */ -#define TARGET_EXTRA_THREADS 1 +/* Extra threads: touchpad and rds */ +#define TARGET_EXTRA_THREADS 2 /* todo */ #define BATTERY_CAPACITY_DEFAULT 550 /* default battery capacity */ diff --git a/firmware/target/arm/imx233/sansa-fuzeplus/fmradio-i2c-fuzeplus.c b/firmware/target/arm/imx233/sansa-fuzeplus/fmradio-i2c-fuzeplus.c index ee63cd35f6..7988c4cb28 100644 --- a/firmware/target/arm/imx233/sansa-fuzeplus/fmradio-i2c-fuzeplus.c +++ b/firmware/target/arm/imx233/sansa-fuzeplus/fmradio-i2c-fuzeplus.c @@ -24,12 +24,15 @@ #include "fmradio_i2c.h" #include "pinctrl-imx233.h" #include "generic_i2c.h" +#include "rds.h" +#include "si4700.h" /** * Sansa Fuze+ fmradio uses the following pins: * - B0P29 as CE apparently (active high) * - B1P24 as SDA * - B1P22 as SCL + * - B2P27 as STC/RDS */ static int fmradio_i2c_bus = -1; @@ -103,3 +106,60 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) { return i2c_read_data(fmradio_i2c_bus, address, -1, buf, count); } + +#ifdef HAVE_RDS_CAP +/* Low-level RDS Support */ +static struct semaphore rds_sema; +static uint32_t rds_stack[DEFAULT_STACK_SIZE / sizeof(uint32_t)]; + +/* RDS GPIO interrupt handler */ +static void stc_rds_callback(int bank, int pin) +{ + (void) bank; + (void) pin; + + semaphore_release(&rds_sema); +} + +/* Captures RDS data and processes it */ +static void NORETURN_ATTR rds_thread(void) +{ + uint16_t rds_data[4]; + + while(true) + { + semaphore_wait(&rds_sema, TIMEOUT_BLOCK); + if(si4700_rds_read_raw(rds_data) && rds_process(rds_data)) + si4700_rds_set_event(); + /* renable callback */ + imx233_setup_pin_irq(2, 27, true, true, false, &stc_rds_callback); + } +} + +/* true after full radio power up, and false before powering down */ +void si4700_rds_powerup(bool on) +{ + if(on) + { + imx233_pinctrl_acquire_pin(2, 27, "tuner stc/rds"); + imx233_set_pin_function(2, 27, PINCTRL_FUNCTION_GPIO); + imx233_enable_gpio_output(2, 27, false); + /* pin is set to 0 when an RDS packet has arrived */ + imx233_setup_pin_irq(2, 27, true, true, false, &stc_rds_callback); + } + else + { + imx233_setup_pin_irq(2, 27, false, false, false, NULL); + imx233_pinctrl_release_pin(2, 27, "tuner stc/rds"); + } +} + +/* One-time RDS init at startup */ +void si4700_rds_init(void) +{ + semaphore_init(&rds_sema, 1, 0); + rds_init(); + create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds" + IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU)); +} +#endif /* HAVE_RDS_CAP */