From 60592165ca998875e4bc46c4396c5a123a7e9dbb Mon Sep 17 00:00:00 2001 From: Lorenzo Miori Date: Sat, 23 Feb 2013 16:59:49 +0100 Subject: Samsung YP-R0 hosted target code refactoring As per title this patch aims at splitting common target code and specific target code in a better way to support future ports within the same environment (e.g. Samsung YP-R1 where the Linux and the SoC are the same, with differences in hardware devices handling) Change-Id: I67b4918c46403b184d3d8f42ab5aae7d01037fd0 Reviewed-on: http://gerrit.rockbox.org/409 Reviewed-by: Thomas Martitz Tested-by: Thomas Martitz --- firmware/target/hosted/samsungypr/radio-ypr.c | 126 ++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 firmware/target/hosted/samsungypr/radio-ypr.c (limited to 'firmware/target/hosted/samsungypr/radio-ypr.c') diff --git a/firmware/target/hosted/samsungypr/radio-ypr.c b/firmware/target/hosted/samsungypr/radio-ypr.c new file mode 100644 index 0000000000..1929bb7c90 --- /dev/null +++ b/firmware/target/hosted/samsungypr/radio-ypr.c @@ -0,0 +1,126 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Module wrapper for SI4709 FM Radio Chip, using /dev/si470x (si4709.ko) + * Samsung YP-R0 & Samsung YP-R1 + * + * Copyright (c) 2012 Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include "stdint.h" +#include "string.h" +#include "kernel.h" + +#include "radio-ypr.h" +#include "rds.h" +#include "si4700.h" +#include "power.h" + +static int radio_dev = -1; + +void radiodev_open(void) { + radio_dev = open("/dev/si470x", O_RDWR); +} + +void radiodev_close(void) { + close(radio_dev); +} + +/* High-level registers access */ +void si4709_write_reg(int addr, uint16_t value) { + sSi4709_t r = { .addr = addr, .value = value }; + ioctl(radio_dev, IOCTL_SI4709_WRITE_BYTE, &r); +} + +uint16_t si4709_read_reg(int addr) { + sSi4709_t r = { .addr = addr, .value = 0 }; + ioctl(radio_dev, IOCTL_SI4709_READ_BYTE, &r); + return r.value; +} + +/* Low-level i2c channel access */ +int fmradio_i2c_write(unsigned char address, unsigned char* buf, int count) +{ + (void)address; + sSi4709_i2c_t r = { .size = count, .buf = buf }; + return ioctl(radio_dev, IOCTL_SI4709_I2C_WRITE, &r); +} + +int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) +{ + (void)address; + sSi4709_i2c_t r = { .size = count, .buf = buf }; + return ioctl(radio_dev, IOCTL_SI4709_I2C_READ, &r); +} + +#ifdef HAVE_RDS_CAP + +/* Register we are going to poll */ +#define STATUSRSSI 0xA +#define STATUSRSSI_RDSR (0x1 << 15) + +/* Low-level RDS Support */ +static struct event_queue rds_queue; +static uint32_t rds_stack[DEFAULT_STACK_SIZE / sizeof(uint32_t)]; +static uint16_t rds_data[4]; + +enum { + Q_POWERUP, +}; + +static void NORETURN_ATTR rds_thread(void) +{ + /* start up frozen */ + int timeout = TIMEOUT_BLOCK; + struct queue_event ev; + + while (true) { + queue_wait_w_tmo(&rds_queue, &ev, timeout); + switch (ev.id) { + case Q_POWERUP: + /* power up: timeout after 1 tick, else block indefinitely */ + timeout = ev.data ? 1 : TIMEOUT_BLOCK; + break; + case SYS_TIMEOUT: + /* Captures RDS data and processes it */ + if ((si4709_read_reg(STATUSRSSI) & STATUSRSSI_RDSR) >> 8) { + if (si4700_rds_read_raw(rds_data) && rds_process(rds_data)) + si4700_rds_set_event(); + } + break; + } + } +} + +/* true after full radio power up, and false before powering down */ +void si4700_rds_powerup(bool on) +{ + queue_post(&rds_queue, Q_POWERUP, on); +} + +/* One-time RDS init at startup */ +void si4700_rds_init(void) +{ + queue_init(&rds_queue, false); + create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds" + IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU)); + rds_init(); +} +#endif /* HAVE_RDS_CAP */ -- cgit v1.2.3