summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-07-14 22:00:50 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-07-14 22:00:50 +0000
commitdc051248be106c783da15f41295691095f7c18f2 (patch)
treec885ec1307eada2361af145f07e1eef9b44f23c1 /firmware
parenta42a346789bff0d13457d19b22e4e0004be7e479 (diff)
downloadrockbox-dc051248be106c783da15f41295691095f7c18f2.tar.gz
rockbox-dc051248be106c783da15f41295691095f7c18f2.zip
e200: Tuner driver needs to yield alot and also be mutexed. FM debug screen got broken again and was ignoring cancellation and not drawing the lines.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13896 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/tuner/lv24020lp.c152
-rw-r--r--firmware/export/lv24020lp.h9
-rw-r--r--firmware/export/power.h1
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/power-e200.c15
-rw-r--r--firmware/tuner.c14
5 files changed, 135 insertions, 56 deletions
diff --git a/firmware/drivers/tuner/lv24020lp.c b/firmware/drivers/tuner/lv24020lp.c
index 9ec68f9a27..79d38443f2 100644
--- a/firmware/drivers/tuner/lv24020lp.c
+++ b/firmware/drivers/tuner/lv24020lp.c
@@ -24,6 +24,7 @@
#include "thread.h"
#include "kernel.h"
#include "tuner.h" /* tuner abstraction interface */
+#include "power.h"
#include "fmradio.h" /* physical interface driver */
#include "sound.h"
#include "pp5024.h"
@@ -31,6 +32,8 @@
#ifndef BOOTLOADER
+static struct mutex tuner_mtx;
+
#if 0
/* define to enable tuner logging */
#define SANYO_TUNER_LOG
@@ -338,6 +341,10 @@ static void lv24020lp_write(unsigned int address, unsigned int data)
break;
}
+ /* Check if interface is turned on */
+ if (!(tuner_status & TUNER_POWERED))
+ return;
+
address = lv24020lp_begin_write(address);
/* data first */
@@ -365,6 +372,10 @@ static unsigned int lv24020lp_read(unsigned int address)
int i;
unsigned int toread;
+ /* Check if interface is turned on */
+ if (!(tuner_status & TUNER_POWERED))
+ return 0;
+
address = lv24020lp_begin_write(address);
/* address */
@@ -433,9 +444,6 @@ static int tuner_measure(unsigned char type, int scale, int duration)
{
int64_t finval;
- if (!tuner_awake())
- return 0;
-
/* enable measuring */
lv24020lp_write_or(MSRC_SEL, type);
lv24020lp_write_and(CNT_CTRL, ~CNT_SEL);
@@ -463,19 +471,20 @@ static int tuner_measure(unsigned char type, int scale, int duration)
else
finval = scale*finval / duration;
+ /* This function takes a loooong time and other stuff needs
+ running by now */
+ yield();
+
return (int)finval;
}
/* set the FM oscillator frequency */
-static void set_frequency(int freq)
+static bool set_frequency(int freq)
{
int coef, cap_value, osc_value;
int f1, f2, x1, x2;
int count;
- if (!tuner_awake())
- return;
-
TUNER_LOG_OPEN();
TUNER_LOG("set_frequency(%d)\n", freq);
@@ -579,6 +588,8 @@ static void set_frequency(int freq)
TUNER_LOG("\n");
TUNER_LOG_SYNC();
+
+ return true;
}
static void fine_step_tune(int (*setcmp)(int regval), int regval, int step)
@@ -639,10 +650,10 @@ static int if_setcmp(int regval)
/* This register is bounces around by a few hundred Hz and doesn't seem
to be precisely tuneable. Just do 110000 +/- 500 since it's not very
critical it seems. */
- if (abs(if_set - 109500) <= 500)
+ if (abs(if_set - 110000) <= 500)
return 0;
- return if_set < 109500 ? -1 : 1;
+ return if_set < 110000 ? -1 : 1;
}
static int sd_setcmp(int regval)
@@ -666,8 +677,6 @@ static void set_sleep(bool sleep)
(TUNER_PRESENT | TUNER_POWERED))
return;
- tuner_status |= TUNER_AWAKE;
-
enable_afc(false);
/* 2. Calibrate the IF frequency at 110 kHz: */
@@ -702,9 +711,79 @@ static void set_sleep(bool sleep)
lv24020lp_write(STEREO_CTRL, FMCS_SET(7) | AUTOSSR);
lv24020lp_write(PW_SCTRL, SS_CTRL_SET(3) | SM_CTRL_SET(1) |
PW_RAD);
+
+ tuner_status |= TUNER_AWAKE;
+}
+
+static int lp24020lp_tuned(void)
+{
+ return RSS_FS(lv24020lp_read(RADIO_STAT)) < 0x1f;
+}
+
+static int lv24020lp_debug_info(int setting)
+{
+ int val = -1;
+
+ if (setting >= LV24020LP_DEBUG_FIRST && setting <= LV24020LP_DEBUG_LAST)
+ {
+ val = 0;
+
+ if (tuner_awake())
+ {
+ switch (setting)
+ {
+ /* tuner-specific debug info */
+ case LV24020LP_CTRL_STAT:
+ val = lv24020lp_read(CTRL_STAT);
+ break;
+
+ case LV24020LP_REG_STAT:
+ val = lv24020lp_read(RADIO_STAT);
+ break;
+
+ case LV24020LP_MSS_FM:
+ val = tuner_measure(MSS_FM, 1, 16);
+ break;
+
+ case LV24020LP_MSS_IF:
+ val = tuner_measure(MSS_IF, 1000, 16);
+ break;
+
+ case LV24020LP_MSS_SD:
+ val = tuner_measure(MSS_SD, 1000, 16);
+ break;
+
+ case LV24020LP_IF_SET:
+ val = if_set;
+ break;
+
+ case LV24020LP_SD_SET:
+ val = sd_set;
+ break;
+ }
+ }
+ }
+
+ return val;
}
/** Public interfaces **/
+void lv24020lp_init(void)
+{
+ mutex_init(&tuner_mtx);
+}
+
+void lv24020lp_lock(void)
+{
+ mutex_lock(&tuner_mtx);
+}
+
+void lv24020lp_unlock(void)
+{
+ mutex_unlock(&tuner_mtx);
+}
+
+/* This function expects the driver to be locked externally */
void lv24020lp_power(bool status)
{
static const unsigned char tuner_defaults[][2] =
@@ -734,7 +813,7 @@ void lv24020lp_power(bool status)
if (status)
{
- tuner_status |= TUNER_POWERED | TUNER_PRESENCE_CHECKED;
+ tuner_status |= (TUNER_PRESENCE_CHECKED | TUNER_POWERED);
/* if tuner is present, CHIP ID is 0x09 */
if (lv24020lp_read(CHIP_ID) == 0x09)
@@ -750,16 +829,16 @@ void lv24020lp_power(bool status)
lv24020lp_write(tuner_defaults[i][0], tuner_defaults[i][1]);
/* Complete the startup calibration if the tuner is woken */
- udelay(100000);
+ sleep(HZ/10);
}
}
else
{
+ tuner_status &= ~(TUNER_POWERED | TUNER_AWAKE);
+
/* Power off */
if (tuner_status & TUNER_PRESENT)
lv24020lp_write_and(PW_SCTRL, ~PW_RAD);
-
- tuner_status &= ~(TUNER_POWERED | TUNER_AWAKE);
}
}
@@ -767,6 +846,8 @@ int lv24020lp_set(int setting, int value)
{
int val = 1;
+ mutex_lock(&tuner_mtx);
+
switch(setting)
{
case RADIO_SLEEP:
@@ -780,7 +861,7 @@ int lv24020lp_set(int setting, int value)
case RADIO_SCAN_FREQUENCY:
/* TODO: really implement this */
set_frequency(value);
- val = lv24020lp_get(RADIO_TUNED);
+ val = lp24020lp_tuned();
break;
case RADIO_MUTE:
@@ -791,13 +872,11 @@ int lv24020lp_set(int setting, int value)
break;
case RADIO_REGION:
- {
if (lv24020lp_region_data[value])
lv24020lp_write_or(AUDIO_CTRL2, DEEMP);
else
lv24020lp_write_and(AUDIO_CTRL2, ~DEEMP);
break;
- }
case RADIO_FORCE_MONO:
if (value)
@@ -807,9 +886,11 @@ int lv24020lp_set(int setting, int value)
break;
default:
- val = -1;
+ value = -1;
}
+ mutex_unlock(&tuner_mtx);
+
return val;
}
@@ -817,11 +898,13 @@ int lv24020lp_get(int setting)
{
int val = -1;
+ mutex_lock(&tuner_mtx);
+
switch(setting)
{
case RADIO_TUNED:
/* TODO: really implement this */
- val = RSS_FS(lv24020lp_read(RADIO_STAT)) < 0x1f;
+ val = lp24020lp_tuned();
break;
case RADIO_STEREO:
@@ -833,38 +916,21 @@ int lv24020lp_get(int setting)
bool fmstatus = true;
if (!(tuner_status & TUNER_PRESENCE_CHECKED))
- fmstatus = tuner_power(true);
+ fmstatus = tuner_power_nolock(true);
val = (tuner_status & TUNER_PRESENT) != 0;
if (!fmstatus)
- tuner_power(false);
+ tuner_power_nolock(false);
break;
}
- /* tuner-specific debug info */
- case LV24020LP_CTRL_STAT:
- return lv24020lp_read(CTRL_STAT);
-
- case LV24020LP_REG_STAT:
- return lv24020lp_read(RADIO_STAT);
-
- case LV24020LP_MSS_FM:
- return tuner_measure(MSS_FM, 1, 16);
-
- case LV24020LP_MSS_IF:
- return tuner_measure(MSS_IF, 1000, 16);
-
- case LV24020LP_MSS_SD:
- return tuner_measure(MSS_SD, 1000, 16);
-
- case LV24020LP_IF_SET:
- return if_set;
-
- case LV24020LP_SD_SET:
- return sd_set;
+ default:
+ val = lv24020lp_debug_info(setting);
}
+ mutex_unlock(&tuner_mtx);
+
return val;
}
#endif /* BOOTLOADER */
diff --git a/firmware/export/lv24020lp.h b/firmware/export/lv24020lp.h
index 0fc39b18df..7d24435353 100644
--- a/firmware/export/lv24020lp.h
+++ b/firmware/export/lv24020lp.h
@@ -32,16 +32,17 @@
#define LV24020LP_IF_SET (RADIO_GET_CHIP_FIRST+5)
#define LV24020LP_SD_SET (RADIO_GET_CHIP_FIRST+6)
-struct lv24020lp_region_data
-{
- unsigned char deemphasis;
-} __attribute__((packed));
+#define LV24020LP_DEBUG_FIRST LV24020LP_CTRL_STAT
+#define LV24020LP_DEBUG_LAST LV24020LP_SD_SET
const unsigned char lv24020lp_region_data[TUNER_NUM_REGIONS];
int lv24020lp_set(int setting, int value);
int lv24020lp_get(int setting);
void lv24020lp_power(bool status);
+void lv24020lp_init(void);
+void lv24020lp_lock(void);
+void lv24020lp_unlock(void);
#ifndef CONFIG_TUNER_MULTI
#define tuner_set lv24020lp_set
diff --git a/firmware/export/power.h b/firmware/export/power.h
index 8ecff6c51e..fbc3ded3c1 100644
--- a/firmware/export/power.h
+++ b/firmware/export/power.h
@@ -49,6 +49,7 @@ bool spdif_powered(void);
#if CONFIG_TUNER
extern bool tuner_power(bool status);
+extern bool tuner_power_nolock(bool status);
extern bool tuner_powered(void);
#endif
diff --git a/firmware/target/arm/sandisk/sansa-e200/power-e200.c b/firmware/target/arm/sandisk/sansa-e200/power-e200.c
index 002dcb8407..2745f0ba50 100644
--- a/firmware/target/arm/sandisk/sansa-e200/power-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/power-e200.c
@@ -66,9 +66,11 @@ void ide_power_enable(bool on)
/** Tuner **/
static bool powered = false;
-bool tuner_power(bool status)
+bool tuner_power_nolock(bool status)
{
- bool old_status = powered;
+ bool old_status;
+
+ old_status = powered;
if (status != old_status)
{
@@ -115,6 +117,15 @@ bool tuner_power(bool status)
return old_status;
}
+bool tuner_power(bool status)
+{
+ bool old_status;
+ lv24020lp_lock();
+ old_status = tuner_power_nolock(status);
+ lv24020lp_unlock();
+ return old_status;
+}
+
bool tuner_powered(void)
{
return powered;
diff --git a/firmware/tuner.c b/firmware/tuner.c
index 1ee42a5355..4f3ddc0c73 100644
--- a/firmware/tuner.c
+++ b/firmware/tuner.c
@@ -60,13 +60,15 @@ const struct tea5767_region_data tea5767_region_data[TUNER_NUM_REGIONS] =
#ifdef CONFIG_TUNER_MULTI
int (*tuner_set)(int setting, int value);
int (*tuner_get)(int setting);
-#define TUNER_TYPE_CASE(type, set, get, region_data) \
+#define TUNER_TYPE_CASE(type, set, get, ...) \
case type: \
tuner_set = set; \
tuner_get = get; \
+ __VA_ARGS__; \
break;
#else
-#define TUNER_TYPE_CASE(type, set, get, region_data)
+#define TUNER_TYPE_CASE(type, set, get, ...) \
+ __VA_ARGS__;
#endif /* CONFIG_TUNER_MULTI */
void tuner_init(void)
@@ -79,19 +81,17 @@ void tuner_init(void)
TUNER_TYPE_CASE(LV24020LP,
lv24020lp_set,
lv24020lp_get,
- lv24020lp_region_data)
+ lv24020lp_init())
#endif
#if (CONFIG_TUNER & TEA5767)
TUNER_TYPE_CASE(TEA5767,
tea5767_set,
- tea5767_get,
- tea5767_region_data)
+ tea5767_get)
#endif
#if (CONFIG_TUNER & S1A0903X01)
TUNER_TYPE_CASE(S1A0903X01,
s1a0903x01_set,
- s1a0903x01_get,
- NULL)
+ s1a0903x01_get)
#endif
}
}