Radio and radio recording for Samsung YH-920.

There is no simple method to detect radio through the 3-wire interface, so it's
not implemented for the YH-925 for now. YH-920 always has a radio.

Change-Id: Iea484d752915fcd40dbbbd7dbbf13e81aaf548db
This commit is contained in:
Szymon Dziok 2014-06-17 23:13:15 +00:00
parent 0c3dca1f33
commit eacd76cb80
11 changed files with 335 additions and 44 deletions

View File

@ -296,6 +296,27 @@ static const struct button_mapping button_context_keyboard[] = {
LAST_ITEM_IN_LIST
}; /* button_context_keyboard */
#if CONFIG_TUNER
static const struct button_mapping button_context_radio[] = {
{ ACTION_FM_MENU, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT },
{ ACTION_FM_EXIT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_FM_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY },
{ ACTION_FM_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_FM_PRESET, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT},
{ ACTION_FM_MODE, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_SETTINGS_INC, BUTTON_UP, BUTTON_NONE },
{ ACTION_SETTINGS_INCREPEAT,BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE },
{ ACTION_SETTINGS_DECREPEAT,BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_NEXT, BUTTON_FFWD, BUTTON_NONE },
{ ACTION_STD_NEXTREPEAT, BUTTON_FFWD|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_STD_PREV, BUTTON_REW, BUTTON_NONE },
{ ACTION_STD_PREVREPEAT, BUTTON_REW|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS)
}; /* button_context_radio */
#endif
const struct button_mapping* get_context_mapping(int context)
{
switch (context)
@ -342,6 +363,10 @@ const struct button_mapping* get_context_mapping(int context)
return button_context_recscreen;
case CONTEXT_KEYBOARD:
return button_context_keyboard;
}
#if CONFIG_TUNER
case CONTEXT_FM:
return button_context_radio;
#endif
}
return button_context_standard;
}

View File

@ -91,7 +91,8 @@
#define FM_RECORD
#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD) ||\
(CONFIG_KEYPAD == SANSA_FUZE_PAD) || (CONFIG_KEYPAD == SANSA_CLIP_PAD)
(CONFIG_KEYPAD == SANSA_FUZE_PAD) || (CONFIG_KEYPAD == SANSA_CLIP_PAD) ||\
(CONFIG_KEYPAD == SAMSUNG_YH920_PAD)
#define FM_MENU
#define FM_PRESET
#define FM_STOP

View File

@ -1705,6 +1705,7 @@ target/arm/samsung/yh920/backlight-yh920.c
target/arm/samsung/yh920/lcd-yh920.c
target/arm/samsung/yh920/lcd-as-yh920.S
target/arm/samsung/yh920/powermgmt-yh920.c
target/arm/samsung/fmradio-yh92x.c
#endif /* SAMSUNG_YH920 */
#ifdef SAMSUNG_YH925

View File

@ -221,34 +221,64 @@ void audiohw_set_frequency(int fsel)
}
#if defined(HAVE_RECORDING)
void audiohw_enable_recording(bool source_mic)
void audiohw_set_recsrc(int source)
{
if (source_mic)
switch(source)
{
/* enable mic power supply */
case AUDIO_SRC_PLAYBACK:
/* disable mic power supply */
#if defined(SAMSUNG_YH920) || defined(SAMSUNG_YH925)
/* additionally select external mic */
akc_set(AK4537_MIC, MPWRE | MSEL);
akc_clear(AK4537_MIC, MPWRE);
#else
akc_set(AK4537_MIC, MPWRI);
akc_clear(AK4537_MIC, MPWRI);
#endif
/* power down ADC, mic preamp and line amp */
akc_clear(AK4537_PM1, PMADL | PMMICL | PMIPGL);
akc_clear(AK4537_PM3, PMADR | PMMICR | PMIPGR);
/* mic out is connected to line1 input */
akc_clear(AK4537_PM3, INL | INR);
/* break ADC -> DAC connection */
akc_clear(AK4537_MODE2, LOOP);
break;
#if (INPUT_SRC_CAPS & SRC_CAP_FMRADIO)
case AUDIO_SRC_FMRADIO:
/* disable mic power supply */
#if defined(SAMSUNG_YH920) || defined(SAMSUNG_YH925)
akc_clear(AK4537_MIC, MPWRE);
#else
akc_clear(AK4537_MIC, MPWRI);
#endif
/* disable mic preamp */
akc_clear(AK4537_PM1, PMMICL);
/* Select line2 input: Radio */
akc_set(AK4537_PM3, INL | INR);
/* route ALC output to ADC input */
akc_set(AK4537_MIC, MICAD);
/* set ALC (automatic level control) to manual mode */
akc_clear(AK4537_ALC1, ALC1);
/* set gain control to 'dependent' (left&right at the same time) */
akc_clear(AK4537_MIC, IPGAC);
/* power up mic preamp, left channel ADC and line in */
akc_set(AK4537_PM1, PMMICL | PMIPGL | PMADL);
/* power up right channel ADC and line in */
/* set gain control to independent left & right gain */
akc_set(AK4537_MIC, IPGAC);
/* power up left channel input and ADC */
akc_set(AK4537_PM1, PMADL | PMIPGL);
/* power up right channel input and ADC */
akc_set(AK4537_PM3, PMADR | PMIPGR);
}
else
{
/* set line in vol = 0 dB */
akc_write(AK4537_IPGAL, 0x2f);
akc_write(AK4537_IPGAR, 0x2f);
/* ADC -> DAC, external data to DAC ignored */
akc_set(AK4537_MODE2, LOOP);
break;
#endif /* INPUT_SRC_CAPS & SRC_CAP_FMRADIO */
#if (INPUT_SRC_CAPS & SRC_CAP_LINEIN)
case AUDIO_SRC_LINEIN:
/* disable mic power supply */
#if defined(SAMSUNG_YH920) || defined(SAMSUNG_YH925)
akc_clear(AK4537_MIC, MPWRE);
@ -272,25 +302,44 @@ void audiohw_enable_recording(bool source_mic)
akc_set(AK4537_PM1, PMADL | PMIPGL);
/* power up right channel input and ADC */
akc_set(AK4537_PM3, PMADR | PMIPGR);
}
/* ADC -> DAC, external data to DAC ignored */
akc_set(AK4537_MODE2, LOOP);
}
void audiohw_disable_recording(void)
{
/* disable mic power supply */
/* ADC -> DAC, external data to DAC ignored */
akc_set(AK4537_MODE2, LOOP);
break;
#endif /* INPUT_SRC_CAPS & SRC_CAP_LINEIN */
#if (INPUT_SRC_CAPS & SRC_CAP_MIC)
case AUDIO_SRC_MIC:
/* enable mic power supply */
#if defined(SAMSUNG_YH920) || defined(SAMSUNG_YH925)
akc_clear(AK4537_MIC, MPWRE);
/* additionally select external mic */
akc_set(AK4537_MIC, MPWRE | MSEL);
#else
akc_clear(AK4537_MIC, MPWRI);
akc_set(AK4537_MIC, MPWRI);
#endif
/* power down ADC, mic preamp and line amp */
akc_clear(AK4537_PM1, PMADL | PMMICL | PMIPGL);
akc_clear(AK4537_PM3, PMADR | PMMICR | PMIPGR);
/* break ADC -> DAC connection */
akc_clear(AK4537_MODE2, LOOP);
/* mic out is connected to line1 input */
akc_clear(AK4537_PM3, INL | INR);
/* route ALC output to ADC input */
akc_set(AK4537_MIC, MICAD);
/* set ALC (automatic level control) to manual mode */
akc_clear(AK4537_ALC1, ALC1);
/* set gain control to 'dependent' (left&right at the same time) */
akc_clear(AK4537_MIC, IPGAC);
/* power up mic preamp, left channel ADC and line in */
akc_set(AK4537_PM1, PMMICL | PMIPGL | PMADL);
/* power up right channel ADC and line in */
akc_set(AK4537_PM3, PMADR | PMIPGR);
/* ADC -> DAC, external data to DAC ignored */
akc_set(AK4537_MODE2, LOOP);
break;
#endif /* INPUT_SRC_CAPS & SRC_CAP_MIC) */
} /* switch(source) */
}
void audiohw_set_recvol(int left, int right, int type)
@ -331,9 +380,4 @@ void audiohw_set_recvol(int left, int right, int type)
return;
}
}
void audiohw_set_monitor(bool enable)
{
(void)enable;
}
#endif /* HAVE_RECORDING */

View File

@ -27,7 +27,9 @@
#include "power.h"
#include "tuner.h" /* tuner abstraction interface */
#include "fmradio.h"
#include "fmradio_i2c.h" /* physical interface driver */
#include "fmradio_i2c.h" /* physical interface driver - i2c */
#include "fmradio_3wire.h" /* physical interface driver - 3-wire bus */
#if defined(PHILIPS_HDD1630) || defined(ONDA_VX747) || defined(ONDA_VX777) || defined(PHILIPS_HDD6330)
#define I2C_ADR 0x60
@ -109,7 +111,11 @@ int tea5767_set(int setting, int value)
if(setting == RADIO_SLEEP && !value)
tuner_power(true); /* wakeup */
#if defined(CONFIG_TUNER_3WIRE)
fmradio_3wire_write(write_bytes);
#else
fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes));
#endif
if(setting == RADIO_SLEEP && value)
tuner_power(false); /* sleep */
return 1;
@ -121,7 +127,11 @@ int tea5767_get(int setting)
unsigned char read_bytes[5];
int val = -1; /* default for unsupported query */
#if defined(CONFIG_TUNER_3WIRE)
fmradio_3wire_read(read_bytes);
#else
fmradio_i2c_read(I2C_ADR, read_bytes, sizeof(read_bytes));
#endif
switch(setting)
{
@ -141,7 +151,7 @@ int tea5767_get(int setting)
case RADIO_STEREO:
val = read_bytes[2] >> 7;
break;
case RADIO_RSSI:
val = 10 + 3*(read_bytes[3] >> 4);
break;
@ -161,15 +171,22 @@ int tea5767_get(int setting)
void tea5767_init(void)
{
/* save binsize by only detecting presence for targets where it may be absent */
#if defined(PHILIPS_HDD1630) || defined(PHILIPS_HDD6330)
#if defined(PHILIPS_HDD1630) || defined(PHILIPS_HDD6330) || defined(SAMSUNG_YH920)
unsigned char buf[5];
unsigned char chipid;
/* init chipid register with 0xFF in case fmradio_i2c_read fails silently */
buf[3] = 0xFF;
tuner_power(true);
if (fmradio_i2c_read(I2C_ADR, buf, sizeof(buf)) < 0) {
/* no i2c device detected */
#if defined(CONFIG_TUNER_3WIRE)
int res = fmradio_3wire_read(buf);
#else
int res = fmradio_i2c_read(I2C_ADR, buf, sizeof(buf));
#endif
if (res < 0) {
/* no device detected on bus */
tuner_present = false;
} else {
/* check chip id */
@ -182,6 +199,10 @@ void tea5767_init(void)
void tea5767_dbg_info(struct tea5767_dbg_info *info)
{
#if defined(CONFIG_TUNER_3WIRE)
fmradio_3wire_read(info->read_regs);
#else
fmradio_i2c_read(I2C_ADR, info->read_regs, 5);
#endif
memcpy(info->write_regs, write_bytes, 5);
}

View File

@ -34,6 +34,8 @@ AUDIOHW_SETTING(RIGHT_GAIN, "dB", 0, 1, -23, 12, 0)
/* mic gain: +15dB fixed +20dB switchable mic preamp gain
and the line stage of -23..+12dB make a total range of -8..+47dB */
AUDIOHW_SETTING(MIC_GAIN, "dB", 0, 1, -8, 47, 20)
void audiohw_set_recsrc(int source);
#endif /* HAVE_RECORDING */
#define AKC_NUM_REGS 0x11

View File

@ -11,7 +11,7 @@
/* 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_48 | SAMPR_CAP_44 | SAMPR_CAP_32 | \
@ -133,6 +133,12 @@
/* AK4537 has no tone controls, so we use the software ones */
#define HAVE_SW_TONE_CONTROLS
/* FM Tuner */
#define CONFIG_TUNER TEA5767
#define CONFIG_TUNER_XTAL 32768
/* Define this if the tuner uses 3-wire bus instead of classic i2c */
#define CONFIG_TUNER_3WIRE
#define AB_REPEAT_ENABLE
#define BATTERY_CAPACITY_DEFAULT 1550 /* default battery capacity */

View File

@ -0,0 +1,33 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
* Physical interface of the Philips TEA5767
*
* Copyright (C) 2014 by Szymon Dziok
*
* 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.
*
****************************************************************************/
#ifndef FMRADIO_TRIWIRE_H
#define FMRADIO_TRIWIRE_H
#include "config.h" /* for INIT_ATTR */
#include <stdbool.h>
void fmradio_3wire_init(void) INIT_ATTR;
void fmradio_3wire_enable(bool enable);
int fmradio_3wire_write(const unsigned char* buf);
int fmradio_3wire_read(unsigned char* buf);
#endif

View File

@ -30,6 +30,25 @@ void audio_set_output_source(int source)
source = AUDIO_SRC_PLAYBACK;
} /* audio_set_output_source */
#ifdef HAVE_AK4537
void audio_input_mux(int source, unsigned flags)
{
(void)flags;
/* Prevent pops from unneeded switching */
static int last_source = AUDIO_SRC_PLAYBACK;
#ifdef HAVE_FMRADIO_REC
bool recording = flags & SRCF_RECORDING;
if ((source == AUDIO_SRC_FMRADIO) && (!recording))
audiohw_set_recvol(0, 0, AUDIO_GAIN_LINEIN); /* Set line-in vol to 0dB*/
#endif
if (source != last_source)
audiohw_set_recsrc(source);
last_source = source;
}
#else
void audio_input_mux(int source, unsigned flags)
{
(void)flags;
@ -132,4 +151,6 @@ void audio_input_mux(int source, unsigned flags)
last_source = source;
} /* audio_input_mux */
#endif
#endif /* INPUT_SRC_CAPS != 0 */

View File

@ -0,0 +1,120 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
* Physical interface of the Philips TEA5767 in Samsung YH-92x
*
* Copyright (C) 2014 by Szymon Dziok
*
* 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 "config.h"
#include "system.h"
#include "cpu.h"
#include "fmradio_3wire.h"
#define CLOCK_EN GPIO_SET_BITWISE(GPIOL_ENABLE, 0x10)
#define CLOCK_OUT GPIO_SET_BITWISE(GPIOL_OUTPUT_EN, 0x10)
#define CLOCK_LO GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_VAL, 0x10)
#define CLOCK_HI GPIO_SET_BITWISE(GPIOL_OUTPUT_VAL, 0x10)
#define DATA (GPIOL_INPUT_VAL & 0x08)
#define DATA_EN GPIO_SET_BITWISE(GPIOL_ENABLE, 0x08)
#define DATA_IN GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_EN, 0x08)
#define DATA_OUT GPIO_SET_BITWISE(GPIOL_OUTPUT_EN, 0x08)
#define DATA_LO GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_VAL, 0x08)
#define DATA_HI GPIO_SET_BITWISE(GPIOL_OUTPUT_VAL, 0x08)
#define READWRITE_EN GPIO_SET_BITWISE(GPIOL_ENABLE, 0x01)
#define READWRITE_OUT GPIO_SET_BITWISE(GPIOL_OUTPUT_EN, 0x01)
#define READWRITE_LO GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_VAL, 0x01)
#define READWRITE_HI GPIO_SET_BITWISE(GPIOL_OUTPUT_VAL, 0x01)
#define DELAY1 udelay(1)
#define DELAY2 udelay(2)
void fmradio_3wire_init(void)
{
READWRITE_EN;
READWRITE_OUT;
DATA_EN;
DATA_IN;
CLOCK_EN;
CLOCK_HI;
CLOCK_OUT;
DELAY2;
}
int fmradio_3wire_write(const unsigned char* buf)
{
int i, j;
CLOCK_LO;
READWRITE_LO;
DELAY2;
READWRITE_HI;
DELAY1;
DATA_OUT;
/* 5 bytes to the tuner */
for (j = 0; j < 5; j++)
{
for (i = 7; i >= 0; i--)
{
if ((buf[j] >> i) & 0x1) DATA_HI;
else DATA_LO;
DELAY1;
CLOCK_HI;
DELAY2;
CLOCK_LO;
DELAY1;
}
}
READWRITE_LO;
return j;
}
int fmradio_3wire_read(unsigned char* buf)
{
int i, j;
CLOCK_LO;
READWRITE_HI;
DELAY2;
READWRITE_LO;
DELAY2;
DATA_IN;
/* 5 bytes from the tuner */
for (j = 0; j < 5; j++)
{
buf[j] = 0;
for (i = 7; i >= 0; i--)
{
buf[j] |= ((DATA >> 3) << i);
CLOCK_HI;
DELAY2;
CLOCK_LO;
DELAY2;
}
}
READWRITE_HI;
return j;
}

View File

@ -20,7 +20,7 @@
****************************************************************************/
/* Created from power.c using some iPod code, and some custom stuff based on
GPIO analysis
GPIO analysis
*/
#include "config.h"
@ -32,9 +32,26 @@
#include "power.h"
#include "logf.h"
#include "usb.h"
#include "fmradio_3wire.h"
#if CONFIG_TUNER
bool tuner_power(bool status)
{
GPIO_SET_BITWISE(GPIOL_ENABLE, 0x04);
GPIO_SET_BITWISE(GPIOL_OUTPUT_EN, 0x04);
if (status)
GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_VAL, 0x04);
else
GPIO_SET_BITWISE(GPIOL_OUTPUT_VAL, 0x04);
return status;
}
#endif
void power_init(void)
{
#if CONFIG_TUNER
fmradio_3wire_init();
#endif
}
unsigned int power_input_status(void)