mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
FS#8046: H10 FM tuner support. Thanks to Przemyslaw Holubowski for doing the hard work in figuring out how to communicate with the tuner.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15578 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
496027d8bb
commit
c495cdae59
9 changed files with 263 additions and 15 deletions
|
@ -305,6 +305,26 @@ const struct button_mapping button_context_recscreen[] = {
|
|||
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS)
|
||||
}; /* button_context_recscreen */
|
||||
|
||||
static const struct button_mapping button_context_radio[] = {
|
||||
{ ACTION_FM_PRESET, BUTTON_RIGHT | BUTTON_REL, BUTTON_RIGHT },
|
||||
{ ACTION_FM_MENU, BUTTON_RIGHT | BUTTON_REPEAT, BUTTON_NONE },
|
||||
{ ACTION_FM_MODE, BUTTON_LEFT, BUTTON_NONE },
|
||||
{ ACTION_FM_STOP, BUTTON_PLAY | BUTTON_REPEAT, BUTTON_PLAY },
|
||||
{ ACTION_FM_EXIT, BUTTON_POWER, BUTTON_NONE },
|
||||
{ ACTION_FM_PLAY, BUTTON_PLAY | BUTTON_REL, BUTTON_PLAY },
|
||||
{ ACTION_SETTINGS_INC, BUTTON_SCROLL_UP, BUTTON_NONE },
|
||||
{ ACTION_SETTINGS_INCREPEAT, BUTTON_SCROLL_UP|BUTTON_REPEAT, BUTTON_NONE },
|
||||
{ ACTION_SETTINGS_DEC, BUTTON_SCROLL_DOWN, BUTTON_NONE },
|
||||
{ ACTION_SETTINGS_DECREPEAT, BUTTON_SCROLL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
|
||||
{ ACTION_STD_PREV, BUTTON_REW, BUTTON_NONE },
|
||||
{ ACTION_STD_PREVREPEAT, BUTTON_REW|BUTTON_REPEAT, BUTTON_NONE },
|
||||
{ ACTION_STD_NEXT, BUTTON_FF, BUTTON_NONE },
|
||||
{ ACTION_STD_NEXTREPEAT, BUTTON_FF|BUTTON_REPEAT, BUTTON_NONE },
|
||||
|
||||
LAST_ITEM_IN_LIST
|
||||
|
||||
};
|
||||
|
||||
static const struct button_mapping* get_context_mapping_remote( int context )
|
||||
{
|
||||
context ^= CONTEXT_REMOTE;
|
||||
|
@ -385,7 +405,8 @@ const struct button_mapping* get_context_mapping(int context)
|
|||
return button_context_keyboard;
|
||||
case CONTEXT_RECSCREEN:
|
||||
return button_context_recscreen;
|
||||
|
||||
case CONTEXT_FM:
|
||||
return button_context_radio;
|
||||
default:
|
||||
return button_context_standard;
|
||||
}
|
||||
|
|
|
@ -81,6 +81,10 @@
|
|||
#define FM_NEXT_PRESET
|
||||
#define FM_PREV_PRESET
|
||||
|
||||
#elif CONFIG_KEYPAD == IRIVER_H10_PAD
|
||||
#define FM_PRESET
|
||||
#define FM_MODE
|
||||
|
||||
#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
|
||||
#define FM_PRESET
|
||||
#define FM_MODE
|
||||
|
|
|
@ -557,6 +557,7 @@ target/arm/i2s-pp.c
|
|||
target/arm/iriver/h10/adc-h10.c
|
||||
target/arm/iriver/h10/backlight-h10.c
|
||||
target/arm/iriver/h10/button-h10.c
|
||||
target/arm/iriver/h10/fmradio_i2c-h10.c
|
||||
target/arm/iriver/h10/lcd-h10_20gb.c
|
||||
target/arm/iriver/h10/power-h10.c
|
||||
target/arm/iriver/h10/powermgmt-h10.c
|
||||
|
@ -573,6 +574,7 @@ target/arm/i2s-pp.c
|
|||
target/arm/iriver/h10/adc-h10.c
|
||||
target/arm/iriver/h10/backlight-h10.c
|
||||
target/arm/iriver/h10/button-h10.c
|
||||
target/arm/iriver/h10/fmradio_i2c-h10.c
|
||||
target/arm/iriver/h10/lcd-h10_5gb.c
|
||||
target/arm/iriver/h10/power-h10.c
|
||||
target/arm/iriver/h10/powermgmt-h10.c
|
||||
|
|
|
@ -319,6 +319,15 @@ void audiohw_set_recvol(int left, int right, int type)
|
|||
|
||||
void audiohw_set_monitor(int enable)
|
||||
{
|
||||
/* TODO: Implement for FM monitoring */
|
||||
(void)enable;
|
||||
if(enable)
|
||||
{
|
||||
wm8731_regs[AAPCTRL] |= AAPCTRL_BYPASS;
|
||||
wm8731_regs[AAPCTRL] &=~ (AAPCTRL_DACSEL | AAPCTRL_SIDETONE);
|
||||
wm8731_write(AAPCTRL, wm8731_regs[AAPCTRL]);
|
||||
}
|
||||
else {
|
||||
wm8731_regs[AAPCTRL] &=~ AAPCTRL_BYPASS;
|
||||
wm8731_regs[AAPCTRL] |= AAPCTRL_DACSEL | AAPCTRL_SIDETONE;
|
||||
wm8731_write(AAPCTRL, wm8731_regs[AAPCTRL]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#define HAVE_RECORDING
|
||||
/* Define bitmask of input sources - recordable bitmask can be defined
|
||||
explicitly if different */
|
||||
#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN)
|
||||
#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO)
|
||||
|
||||
/* define the bitmask of hardware sample rates */
|
||||
#define HW_SAMPR_CAPS (SAMPR_CAP_44)
|
||||
|
@ -88,8 +88,8 @@
|
|||
#define AB_REPEAT_ENABLE 1
|
||||
|
||||
/* FM Tuner */
|
||||
/*#define CONFIG_TUNER TEA5767
|
||||
#define CONFIG_TUNER_XTAL 32768 *//* TODO: what is this? */
|
||||
#define CONFIG_TUNER TEA5767
|
||||
#define CONFIG_TUNER_XTAL 32768
|
||||
|
||||
/* Define this for LCD backlight available */
|
||||
#define HAVE_BACKLIGHT
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#define HAVE_RECORDING
|
||||
/* Define bitmask of input sources - recordable bitmask can be defined
|
||||
explicitly if different */
|
||||
#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN)
|
||||
#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO)
|
||||
|
||||
/* define the bitmask of hardware sample rates */
|
||||
#define HW_SAMPR_CAPS (SAMPR_CAP_44)
|
||||
|
@ -74,8 +74,8 @@
|
|||
#define AB_REPEAT_ENABLE 1
|
||||
|
||||
/* FM Tuner */
|
||||
/*#define CONFIG_TUNER TEA5767
|
||||
#define CONFIG_TUNER_XTAL 32768 *//* TODO: what is this? */
|
||||
#define CONFIG_TUNER TEA5767
|
||||
#define CONFIG_TUNER_XTAL 32768
|
||||
|
||||
/* Define this for LCD backlight available */
|
||||
#define HAVE_BACKLIGHT
|
||||
|
|
|
@ -35,6 +35,7 @@ void audio_input_mux(int source, unsigned flags)
|
|||
/* Prevent pops from unneeded switching */
|
||||
static int last_source = AUDIO_SRC_PLAYBACK;
|
||||
#ifdef HAVE_FMRADIO_REC
|
||||
bool recording = flags & SRCF_RECORDING;
|
||||
static bool last_recording = false;
|
||||
#endif
|
||||
|
||||
|
@ -62,6 +63,10 @@ void audio_input_mux(int source, unsigned flags)
|
|||
#endif
|
||||
#ifdef HAVE_LINEIN_REC
|
||||
case AUDIO_SRC_LINEIN: /* recording only */
|
||||
#if defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
|
||||
/* Switch line in source to line-in */
|
||||
GPIO_SET_BITWISE(GPIOB_OUTPUT_VAL, 0x04);
|
||||
#endif
|
||||
if (source != last_source)
|
||||
{
|
||||
audiohw_enable_recording(false); /* source line */
|
||||
|
@ -71,17 +76,20 @@ void audio_input_mux(int source, unsigned flags)
|
|||
#endif
|
||||
#ifdef HAVE_FMRADIO_REC
|
||||
case AUDIO_SRC_FMRADIO: /* recording and playback */
|
||||
#if defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
|
||||
/* Switch line in source to tuner */
|
||||
GPIO_CLEAR_BITWISE(GPIOB_OUTPUT_VAL, 0x04);
|
||||
#endif /* Set line-in vol to 0dB*/
|
||||
if (!recording)
|
||||
audiohw_set_recvol(0, 0, AUDIO_GAIN_LINEIN);
|
||||
audiohw_set_recvol(0x17, 0x17, AUDIO_GAIN_LINEIN);
|
||||
|
||||
if (source == last_source && recording == last_recording)
|
||||
break;
|
||||
|
||||
last_recording = recording;
|
||||
|
||||
/* I2S recording and playback */
|
||||
audiohw_enable_recording(false); /* source line */
|
||||
audiohw_set_monitor(!recording);
|
||||
audiohw_enable_recording(false); /* select line-in source */
|
||||
audiohw_set_monitor(!recording); /* enable bypass mode */
|
||||
break;
|
||||
#endif
|
||||
} /* end switch */
|
||||
|
|
206
firmware/target/arm/iriver/h10/fmradio_i2c-h10.c
Normal file
206
firmware/target/arm/iriver/h10/fmradio_i2c-h10.c
Normal file
|
@ -0,0 +1,206 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
* Physical interface of the Philips TEA5767 in iriver H10 series
|
||||
*
|
||||
* Copyright (C) 2002 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "logf.h"
|
||||
#include "system.h"
|
||||
|
||||
/* cute little functions, atomic read-modify-write */
|
||||
|
||||
#define SDA_OUTINIT GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_VAL, 0x08)
|
||||
#define SDA_HI_IN GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_EN, 0x08)
|
||||
#define SDA_LO_OUT GPIO_SET_BITWISE(GPIOD_OUTPUT_EN, 0x08)
|
||||
#define SDA (GPIOD_INPUT_VAL & 0x08)
|
||||
|
||||
#define SCL_INPUT GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_EN, 0x10)
|
||||
#define SCL_OUTPUT GPIO_SET_BITWISE(GPIOD_OUTPUT_EN, 0x10)
|
||||
#define SCL_LO GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_VAL, 0x10)
|
||||
#define SCL_HI GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL,0x10)
|
||||
#define SCL (GPIOD_INPUT_VAL & 0x10)
|
||||
|
||||
#define DELAY udelay(2)
|
||||
|
||||
static void fmradio_i2c_start(void)
|
||||
{
|
||||
SCL_HI;
|
||||
SCL_OUTPUT;
|
||||
SDA_HI_IN;
|
||||
SDA_OUTINIT;
|
||||
DELAY;
|
||||
SDA_LO_OUT;
|
||||
DELAY;
|
||||
SCL_LO;
|
||||
}
|
||||
|
||||
static void fmradio_i2c_stop(void)
|
||||
{
|
||||
SDA_LO_OUT;
|
||||
DELAY;
|
||||
SCL_HI;
|
||||
DELAY;
|
||||
SDA_HI_IN;
|
||||
}
|
||||
|
||||
/* Generate ACK or NACK */
|
||||
static void fmradio_i2c_ack(bool nack)
|
||||
{
|
||||
/* Here's the deal. The slave is slow, and sometimes needs to wait
|
||||
before it can receive the acknowledge. Therefore it forces the clock
|
||||
low until it is ready. We need to poll the clock line until it goes
|
||||
high before we release the ack.
|
||||
|
||||
In their infinite wisdom, iriver didn't pull up the SCL line, so
|
||||
we have to drive the SCL high repeatedly to simulate a pullup. */
|
||||
|
||||
if (nack)
|
||||
SDA_HI_IN;
|
||||
else
|
||||
SDA_LO_OUT;
|
||||
DELAY;
|
||||
|
||||
SCL_HI;
|
||||
do
|
||||
{
|
||||
SCL_OUTPUT; /* Set the clock to output */
|
||||
SCL_INPUT; /* Set the clock to input */
|
||||
DELAY;
|
||||
}
|
||||
while(!SCL); /* and wait for the slave to release it */
|
||||
|
||||
SCL_OUTPUT;
|
||||
SCL_LO;
|
||||
}
|
||||
|
||||
static int fmradio_i2c_getack(void)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
/* Here's the deal. The slave is slow, and sometimes needs to wait
|
||||
before it can send the acknowledge. Therefore it forces the clock
|
||||
low until it is ready. We need to poll the clock line until it goes
|
||||
high before we read the ack.
|
||||
|
||||
In their infinite wisdom, iriver didn't pull up the SCL line, so
|
||||
we have to drive the SCL high repeatedly to simulate a pullup. */
|
||||
|
||||
SDA_HI_IN;
|
||||
DELAY;
|
||||
|
||||
SCL_HI; /* set clock to high */
|
||||
do
|
||||
{
|
||||
SCL_OUTPUT; /* Set the clock to output */
|
||||
SCL_INPUT; /* Set the clock to input */
|
||||
DELAY;
|
||||
}
|
||||
while(!SCL); /* and wait for the slave to release it */
|
||||
|
||||
if (SDA)
|
||||
ret = 0; /* ack failed */
|
||||
|
||||
SCL_OUTPUT;
|
||||
SCL_LO;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fmradio_i2c_outb(unsigned char byte)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* clock out each bit, MSB first */
|
||||
for ( i=0x80; i; i>>=1 ) {
|
||||
if ( i & byte )
|
||||
SDA_HI_IN;
|
||||
else
|
||||
SDA_LO_OUT;
|
||||
DELAY;
|
||||
SCL_HI;
|
||||
DELAY;
|
||||
SCL_LO;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char fmradio_i2c_inb(void)
|
||||
{
|
||||
int i;
|
||||
unsigned char byte = 0;
|
||||
|
||||
SDA_HI_IN;
|
||||
/* clock in each bit, MSB first */
|
||||
for ( i=0x80; i; i>>=1 ) {
|
||||
DELAY;
|
||||
SCL_HI;
|
||||
DELAY;
|
||||
if ( SDA )
|
||||
byte |= i;
|
||||
SCL_LO;
|
||||
}
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
int fmradio_i2c_write(int address, const unsigned char* buf, int count)
|
||||
{
|
||||
int i,x=0;
|
||||
|
||||
fmradio_i2c_start();
|
||||
fmradio_i2c_outb(address & 0xfe);
|
||||
if (fmradio_i2c_getack())
|
||||
{
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
fmradio_i2c_outb(buf[i]);
|
||||
if (!fmradio_i2c_getack())
|
||||
{
|
||||
x=-2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logf("fmradio_i2c_write() - no ack\n");
|
||||
x=-1;
|
||||
}
|
||||
fmradio_i2c_stop();
|
||||
return x;
|
||||
}
|
||||
|
||||
int fmradio_i2c_read(int address, unsigned char* buf, int count)
|
||||
{
|
||||
int i,x=0;
|
||||
|
||||
fmradio_i2c_start();
|
||||
fmradio_i2c_outb(address | 1);
|
||||
|
||||
if (fmradio_i2c_getack())
|
||||
{
|
||||
for (i=count; i>0; i--)
|
||||
{
|
||||
*buf++ = fmradio_i2c_inb();
|
||||
fmradio_i2c_ack(i == 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
x=-1;
|
||||
fmradio_i2c_stop();
|
||||
return x;
|
||||
}
|
|
@ -35,7 +35,6 @@
|
|||
bool charger_enabled;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#if CONFIG_TUNER
|
||||
|
||||
bool tuner_power(bool status)
|
||||
|
@ -46,7 +45,6 @@ bool tuner_power(bool status)
|
|||
}
|
||||
|
||||
#endif /* #if CONFIG_TUNER */
|
||||
#endif
|
||||
|
||||
void power_init(void)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue