summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorSzymon Dziok <b0hoon@o2.pl>2014-06-17 23:13:15 +0000
committerSzymon Dziok <b0hoon@o2.pl>2014-06-18 18:06:17 +0000
commiteacd76cb80db12adcce74980e69d116911a8cde7 (patch)
tree239344e3f9053a75eeab4253f39f6b1dae749aa6 /firmware
parent0c3dca1f33596cb10345601de32d681ed6ece972 (diff)
downloadrockbox-eacd76cb80db12adcce74980e69d116911a8cde7.tar.gz
rockbox-eacd76cb80db12adcce74980e69d116911a8cde7.zip
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
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/drivers/audio/ak4537.c114
-rw-r--r--firmware/drivers/tuner/tea5767.c31
-rw-r--r--firmware/export/ak4537.h2
-rw-r--r--firmware/export/config/samsungyh920.h8
-rw-r--r--firmware/export/fmradio_3wire.h33
-rw-r--r--firmware/target/arm/pp/audio-pp.c21
-rw-r--r--firmware/target/arm/samsung/fmradio-yh92x.c120
-rw-r--r--firmware/target/arm/samsung/power-yh82x_yh92x.c19
9 files changed, 307 insertions, 42 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 374210e30b..ef71a2b048 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -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
diff --git a/firmware/drivers/audio/ak4537.c b/firmware/drivers/audio/ak4537.c
index bea3dc7019..a42b1346d2 100644
--- a/firmware/drivers/audio/ak4537.c
+++ b/firmware/drivers/audio/ak4537.c
@@ -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 */
diff --git a/firmware/drivers/tuner/tea5767.c b/firmware/drivers/tuner/tea5767.c
index d0041f9ce1..74adb54997 100644
--- a/firmware/drivers/tuner/tea5767.c
+++ b/firmware/drivers/tuner/tea5767.c
@@ -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);
}
diff --git a/firmware/export/ak4537.h b/firmware/export/ak4537.h
index 1c09b5aa2f..0ab0ca1594 100644
--- a/firmware/export/ak4537.h
+++ b/firmware/export/ak4537.h
@@ -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
diff --git a/firmware/export/config/samsungyh920.h b/firmware/export/config/samsungyh920.h
index 7d6d590d96..d40a065e00 100644
--- a/firmware/export/config/samsungyh920.h
+++ b/firmware/export/config/samsungyh920.h
@@ -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 */
diff --git a/firmware/export/fmradio_3wire.h b/firmware/export/fmradio_3wire.h
new file mode 100644
index 0000000000..cafce9c8ec
--- /dev/null
+++ b/firmware/export/fmradio_3wire.h
@@ -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
diff --git a/firmware/target/arm/pp/audio-pp.c b/firmware/target/arm/pp/audio-pp.c
index 6b5b082cc7..76740f2e42 100644
--- a/firmware/target/arm/pp/audio-pp.c
+++ b/firmware/target/arm/pp/audio-pp.c
@@ -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 */
diff --git a/firmware/target/arm/samsung/fmradio-yh92x.c b/firmware/target/arm/samsung/fmradio-yh92x.c
new file mode 100644
index 0000000000..4637aca287
--- /dev/null
+++ b/firmware/target/arm/samsung/fmradio-yh92x.c
@@ -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;
+}
diff --git a/firmware/target/arm/samsung/power-yh82x_yh92x.c b/firmware/target/arm/samsung/power-yh82x_yh92x.c
index 021ddade4d..b6c18c5fd0 100644
--- a/firmware/target/arm/samsung/power-yh82x_yh92x.c
+++ b/firmware/target/arm/samsung/power-yh82x_yh92x.c
@@ -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)