Created
May 27, 2012 17:01
-
-
Save pamaury/2815083 to your computer and use it in GitHub Desktop.
stfm audio hack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/apps/debug_menu.c b/apps/debug_menu.c | |
index e611694..bf37b3a 100644 | |
--- a/apps/debug_menu.c | |
+++ b/apps/debug_menu.c | |
@@ -1873,6 +1873,11 @@ static int radio_callback(int btn, struct gui_synclist *lists) | |
struct stfm1000_dbg_info nfo; | |
stfm1000_dbg_info(&nfo); | |
simplelist_addline(SIMPLELIST_ADD_LINE, "STFM1000 regs:"); | |
+ simplelist_addline(SIMPLELIST_ADD_LINE,"tune1: 0x%x", nfo.tune1); | |
+ simplelist_addline(SIMPLELIST_ADD_LINE,"sdnominal: 0x%x", nfo.sdnominal); | |
+ simplelist_addline(SIMPLELIST_ADD_LINE,"pilottracking: 0x%x", nfo.pilottracking); | |
+ simplelist_addline(SIMPLELIST_ADD_LINE,"rssi_tone: 0x%x", nfo.rssi_tone); | |
+ simplelist_addline(SIMPLELIST_ADD_LINE,"pilotcorrection: 0x%x", nfo.pilotcorrection); | |
simplelist_addline(SIMPLELIST_ADD_LINE,"chipid: 0x%x", nfo.chipid); | |
} | |
#endif /* STFM1000 */ | |
diff --git a/firmware/SOURCES b/firmware/SOURCES | |
index c2bd459..c5e7617 100644 | |
--- a/firmware/SOURCES | |
+++ b/firmware/SOURCES | |
@@ -525,6 +525,7 @@ target/arm/imx233/lradc-imx233.c | |
target/arm/imx233/pwm-imx233.c | |
target/arm/imx233/rtc-imx233.c | |
target/arm/imx233/dcp-imx233.c | |
+target/arm/imx233/dri-imx233.c | |
# ifdef HAVE_TOUCHSCREEN | |
target/arm/imx233/touchscreen-imx233.c | |
# endif | |
diff --git a/firmware/drivers/tuner/stfm1000.c b/firmware/drivers/tuner/stfm1000.c | |
index 8626d4e..14cc9da 100644 | |
--- a/firmware/drivers/tuner/stfm1000.c | |
+++ b/firmware/drivers/tuner/stfm1000.c | |
@@ -30,12 +30,17 @@ | |
#include "fmradio.h" | |
#include "fmradio_i2c.h" /* physical interface driver */ | |
#include "stfm1000.h" | |
+#include "stfm1000-regs.h" | |
-#define STFM100_I2C_ADDR 0xc0 | |
+#include "stfm1000-tunetable.c" | |
+ | |
+static int rev_id; | |
+static int sdnominal_pivot; | |
+static bool tuner_present = false; | |
-#define CHIPID 0x80 | |
+#define STFM100_I2C_ADDR 0xc0 | |
-static int stfm1000_read_reg(uint8_t reg, uint32_t *val) | |
+static int stfm1000_read(uint8_t reg, uint32_t *val) | |
{ | |
uint8_t buf[4]; | |
buf[0] = reg; | |
@@ -46,7 +51,7 @@ static int stfm1000_read_reg(uint8_t reg, uint32_t *val) | |
return ret; | |
} | |
-static int stfm1000_write_reg(uint8_t reg, uint32_t val) | |
+static int stfm1000_write(uint8_t reg, uint32_t val) | |
{ | |
uint8_t buf[5]; | |
buf[0] = reg; | |
@@ -55,25 +60,467 @@ static int stfm1000_write_reg(uint8_t reg, uint32_t val) | |
return fmradio_i2c_write(STFM100_I2C_ADDR, buf, 5); | |
} | |
+static int stfm1000_write_masked(int reg, int val, int mask) | |
+{ | |
+ uint32_t tmp; | |
+ | |
+ stfm1000_read(reg, &tmp); | |
+ stfm1000_write(reg, (val & mask) | (tmp & ~mask)); | |
+ return 0; | |
+} | |
+ | |
+static int stfm1000_set_bits(int reg, uint32_t value) | |
+{ | |
+ return stfm1000_write_masked(reg, value, value); | |
+} | |
+ | |
+static int stfm1000_clear_bits(int reg, uint32_t value) | |
+{ | |
+ return stfm1000_write_masked(reg, ~value, value); | |
+} | |
+ | |
+static void stfm1000_set_region(int region) | |
+{ | |
+ const struct fm_region_data *rd = &fm_region_data[region]; | |
+ | |
+ if (rd->deemphasis == 50) { | |
+ stfm1000_set_bits(STFM1000_INITIALIZATION2, STFM1000_DEEMPH_50_75B); | |
+ } else { | |
+ stfm1000_clear_bits(STFM1000_INITIALIZATION2, STFM1000_DEEMPH_50_75B); | |
+ } | |
+} | |
+ | |
+ | |
+static int stfm1000_set_frequency(int freq) | |
+{ | |
+ uint32_t freq100 = freq / 100; | |
+ int tune_cap; | |
+ int i2s_clock; | |
+ int mix_reg; | |
+ int if_freq, fe_freq; | |
+ uint32_t tune1, sdnom, agc1; | |
+ const struct stfm1000_tune1 *tp; | |
+ int ret; | |
+ | |
+ if_freq = 0; | |
+ mix_reg = 1; | |
+ switch (mix_reg) { | |
+ case 0: if_freq = -2; break; | |
+ case 1: if_freq = -1; break; | |
+ case 2: if_freq = 0; break; | |
+ case 3: if_freq = 1; break; | |
+ case 4: if_freq = 2; break; | |
+ } | |
+ | |
+ fe_freq = freq100 + if_freq; | |
+ | |
+ /* clamp into range */ | |
+ if (fe_freq < STFM1000_FREQUENCY_100KHZ_MIN) | |
+ fe_freq = STFM1000_FREQUENCY_100KHZ_MIN; | |
+ else if (fe_freq > STFM1000_FREQUENCY_100KHZ_MAX) | |
+ fe_freq = STFM1000_FREQUENCY_100KHZ_MAX; | |
+ | |
+ tp = &stfm1000_tune1_table[fe_freq - STFM1000_FREQUENCY_100KHZ_MIN]; | |
+ | |
+ /* bits [14:0], [20:18] */ | |
+ tune1 = (tp->tune1 & 0x7fff) | (mix_reg << 18); | |
+ sdnom = tp->sdnom; | |
+ | |
+ agc1 = (rev_id == STFM1000_CHIP_REV_TA2) ? 0x0400 : 0x2200; | |
+ | |
+ ret = stfm1000_write_masked(STFM1000_AGC_CONTROL1, agc1, 0x3f00); | |
+ if (ret != 0) | |
+ goto err; | |
+ | |
+ ret = stfm1000_write_masked(STFM1000_TUNE1, tune1, 0xFFFF7FFF); /* do not set bit-15 */ | |
+ if (ret != 0) | |
+ goto err; | |
+ | |
+ /* keep this around */ | |
+ sdnominal_pivot = sdnom; | |
+ | |
+ ret = stfm1000_write(STFM1000_SDNOMINAL, sdnom); | |
+ if (ret != 0) | |
+ goto err; | |
+ | |
+ /* fix for seek-not-stopping on alternate tunings */ | |
+ ret = stfm1000_set_bits(STFM1000_DATAPATH, STFM1000_DB_ACCEPT); | |
+ if (ret != 0) | |
+ goto err; | |
+ | |
+ ret = stfm1000_clear_bits(STFM1000_DATAPATH, STFM1000_DB_ACCEPT); | |
+ if (ret != 0) | |
+ goto err; | |
+ | |
+ ret = stfm1000_set_bits(STFM1000_INITIALIZATION2, STFM1000_DRI_CLK_EN); | |
+ if (ret != 0) | |
+ goto err; | |
+ | |
+ /* 6MHz spur fix */ | |
+ if ((freq100 >= 778 && freq100 <= 782) || | |
+ (freq100 >= 838 && freq100 <= 842) || | |
+ (freq100 >= 898 && freq100 <= 902) || | |
+ (freq100 >= 958 && freq100 <= 962) || | |
+ (freq100 >= 1018 && freq100 <= 1022) || | |
+ (freq100 >= 1078 && freq100 <= 1080)) | |
+ i2s_clock = 5; /* 4.8MHz */ | |
+ else | |
+ i2s_clock = 4; | |
+ | |
+ ret = stfm1000_write_masked(STFM1000_DATAPATH, | |
+ STFM1000_SAI_CLK_DIV(i2s_clock), STFM1000_SAI_CLK_DIV_MASK); | |
+ if (ret != 0) | |
+ goto err; | |
+ | |
+ ret = stfm1000_set_bits(STFM1000_INITIALIZATION2, STFM1000_DRI_CLK_EN); | |
+ if (ret != 0) | |
+ goto err; | |
+ | |
+ if (tune1 & 0xf) | |
+ ret = stfm1000_set_bits(STFM1000_CLK1, STFM1000_ENABLE_TAPDELAYFIX); | |
+ else | |
+ ret = stfm1000_clear_bits(STFM1000_CLK1, STFM1000_ENABLE_TAPDELAYFIX); | |
+ | |
+ if (ret != 0) | |
+ goto err; | |
+ | |
+ tune_cap = 4744806 - (4587 * freq100); | |
+ if (tune_cap < 4) | |
+ tune_cap = 4; | |
+ ret = stfm1000_write_masked(STFM1000_LNA, STFM1000_ANTENNA_TUNECAP(tune_cap), | |
+ STFM1000_ANTENNA_TUNECAP_MASK); | |
+ if (ret != 0) | |
+ goto err; | |
+ | |
+ return 0; | |
+err: | |
+ return -1; | |
+} | |
+ | |
void stfm1000_dbg_info(struct stfm1000_dbg_info *nfo) | |
{ | |
memset(nfo, 0, sizeof(struct stfm1000_dbg_info)); | |
- stfm1000_read_reg(CHIPID, &nfo->chipid); | |
+ stfm1000_read(STFM1000_TUNE1, &nfo->tune1); | |
+ stfm1000_read(STFM1000_SDNOMINAL, &nfo->sdnominal); | |
+ stfm1000_read(STFM1000_PILOTTRACKING, &nfo->pilottracking); | |
+ stfm1000_read(STFM1000_RSSI_TONE, &nfo->rssi_tone); | |
+ stfm1000_read(STFM1000_PILOTCORRECTION, &nfo->pilotcorrection); | |
+ stfm1000_read(STFM1000_CHIPID, &nfo->chipid); | |
+} | |
+ | |
+static void stfm1000_dp_enable(bool enable) | |
+{ | |
+ if (enable) { | |
+ stfm1000_set_bits(STFM1000_DATAPATH, STFM1000_DP_EN); | |
+ sleep(1); | |
+ stfm1000_set_bits(STFM1000_DATAPATH, STFM1000_DB_ACCEPT); | |
+ stfm1000_clear_bits(STFM1000_AGC_CONTROL1, STFM1000_B2_BYPASS_AGC_CTL); | |
+ stfm1000_clear_bits(STFM1000_DATAPATH, STFM1000_DB_ACCEPT); | |
+ } else { | |
+ stfm1000_set_bits(STFM1000_DATAPATH, STFM1000_DB_ACCEPT); | |
+ stfm1000_clear_bits(STFM1000_DATAPATH, STFM1000_DP_EN); | |
+ stfm1000_set_bits(STFM1000_AGC_CONTROL1, STFM1000_B2_BYPASS_AGC_CTL); | |
+ stfm1000_clear_bits(STFM1000_PILOTTRACKING, STFM1000_B2_PILOTTRACKING_EN); | |
+ stfm1000_clear_bits(STFM1000_DATAPATH, STFM1000_DB_ACCEPT); | |
+ } | |
+} | |
+ | |
+static void stfm_dri_enable(bool enable) | |
+{ | |
+ if (enable) { | |
+ stfm1000_set_bits(STFM1000_DATAPATH, STFM1000_SAI_EN); | |
+ } else { | |
+ stfm1000_clear_bits(STFM1000_DATAPATH, STFM1000_SAI_EN); | |
+ } | |
+} | |
+ | |
+static int stfm1000_set_channel_filter(void) | |
+{ | |
+ int ret; | |
+ int bypass_setting; | |
+ | |
+ /* get near channel amplitude */ | |
+ ret = stfm1000_write_masked(STFM1000_INITIALIZATION3, | |
+ STFM1000_B2_NEAR_CHAN_MIX(0x01), | |
+ STFM1000_B2_NEAR_CHAN_MIX_MASK); | |
+ if (ret != 0) | |
+ return ret; | |
+ | |
+ sleep(10 * HZ / 1000); /* wait for the signal quality to settle */ | |
+ | |
+ bypass_setting = 0; | |
+ | |
+#if 0 | |
+ ret = stfm1000_read(STFM1000_SIGNALQUALITY, &tmp); | |
+ if (ret != 0) | |
+ return ret; | |
+ | |
+ sig_qual = (tmp & STFM1000_NEAR_CHAN_AMPLITUDE_MASK) >> | |
+ STFM1000_NEAR_CHAN_AMPLITUDE_SHIFT; | |
+ | |
+ /* check near channel amplitude vs threshold */ | |
+ if (sig_qual < stfm1000->adj_chan_th) { | |
+ /* get near channel amplitude again */ | |
+ ret = stfm1000_write_masked(stfm1000, STFM1000_INITIALIZATION3, | |
+ STFM1000_B2_NEAR_CHAN_MIX(0x05), | |
+ STFM1000_B2_NEAR_CHAN_MIX_MASK); | |
+ if (ret != 0) | |
+ return ret; | |
+ | |
+ msleep(10); /* wait for the signal quality to settle */ | |
+ | |
+ ret = stfm1000_read(stfm1000, STFM1000_SIGNALQUALITY, &tmp); | |
+ if (ret != 0) | |
+ return ret; | |
+ | |
+ sig_qual = (tmp & STFM1000_NEAR_CHAN_AMPLITUDE_MASK) >> | |
+ STFM1000_NEAR_CHAN_AMPLITUDE_SHIFT; | |
+ | |
+ if (sig_qual < stfm1000->adj_chan_th) | |
+ bypass_setting = 2; | |
+ } | |
+#endif | |
+ /* set filter settings */ | |
+ ret = stfm1000_write_masked(STFM1000_INITIALIZATION1, | |
+ STFM1000_B2_BYPASS_FILT(bypass_setting), | |
+ STFM1000_B2_BYPASS_FILT_MASK); | |
+ if (ret != 0) | |
+ return ret; | |
+ | |
+ return 0; | |
+} | |
+ | |
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*(x))) | |
+ | |
+static int stfm1000_track_pilot(void) | |
+{ | |
+ static const struct { | |
+ int delay; | |
+ uint32_t value; | |
+ } track_table[] = { | |
+ { .delay = 10, .value = 0x81b6 }, | |
+ { .delay = 6, .value = 0x82a5 }, | |
+ { .delay = 6, .value = 0x8395 }, | |
+ { .delay = 8, .value = 0x8474 }, | |
+ { .delay = 20, .value = 0x8535 }, | |
+ { .delay = 50, .value = 0x8632 }, | |
+ { .delay = 0, .value = 0x8810 }, | |
+ }; | |
+ int i; | |
+ int ret; | |
+ | |
+ for (i = 0; i < ARRAY_SIZE(track_table); i++) { | |
+ ret = stfm1000_write(STFM1000_PILOTTRACKING, track_table[i].value); | |
+ if (ret != 0) | |
+ return ret; | |
+ | |
+ if (i < ARRAY_SIZE(track_table) - 1) /* last one no delay */ | |
+ sleep(track_table[i].delay * HZ / 1000); | |
+ } | |
+ | |
+ return 0; | |
+} | |
+ | |
+static int stfm1000_optimise_channel(void) | |
+{ | |
+ int ret; | |
+ | |
+ ret = stfm1000_set_bits(STFM1000_DATAPATH, STFM1000_DB_ACCEPT); | |
+ if (ret != 0) | |
+ return ret; | |
+ | |
+ ret = stfm1000_write(STFM1000_PILOTTRACKING, | |
+ STFM1000_B2_PILOTTRACKING_EN | | |
+ STFM1000_B2_PILOTLPF_TIMECONSTANT(0x01) | | |
+ STFM1000_B2_PFDSCALE(0x0B) | | |
+ STFM1000_B2_PFDFILTER_SPEEDUP(0x06)); /* 0x000081B6 */ | |
+ if (ret != 0) | |
+ return ret; | |
+ | |
+ ret = stfm1000_set_channel_filter(); | |
+ if (ret != 0) | |
+ return ret; | |
+#if 0 | |
+ ret = SD_Look_For_Pilot(stfm1000); | |
+ if (ret != 0) | |
+ return ret; | |
+#endif | |
+// if (stfm1000->pilot_present) { | |
+ ret = stfm1000_track_pilot(); | |
+ if (ret != 0) | |
+ return ret; | |
+// } | |
+ | |
+ ret = stfm1000_clear_bits(STFM1000_DATAPATH, STFM1000_DB_ACCEPT); | |
+ if (ret != 0) | |
+ return ret; | |
+ | |
+ return 0; | |
} | |
void stfm1000_init(void) | |
{ | |
+ uint32_t val; | |
+ | |
+ /* get revision id */ | |
+ stfm1000_read(STFM1000_CHIPID, &val); | |
+ rev_id = val & 0xFF; | |
+ | |
+ /* send TB2 init sequence */ | |
+ stfm1000_write(STFM1000_REF, 0x00200000); | |
+ sleep(20 * HZ / 1000); | |
+ stfm1000_write(STFM1000_DATAPATH, 0x00010210); | |
+ stfm1000_write(STFM1000_TUNE1, 0x0004CF01); | |
+ stfm1000_write(STFM1000_SDNOMINAL, 0x1C5EBCF0); | |
+ stfm1000_write(STFM1000_PILOTTRACKING, 0x000001B6); | |
+ stfm1000_write(STFM1000_INITIALIZATION1, 0x9fb80008); | |
+ stfm1000_write(STFM1000_INITIALIZATION2, 0x8516e444 | STFM1000_DEEMPH_50_75B); | |
+ stfm1000_write(STFM1000_INITIALIZATION3, 0x1402190b); | |
+ stfm1000_write(STFM1000_INITIALIZATION4, 0x525bf052); | |
+ stfm1000_write(STFM1000_INITIALIZATION5, 0x1000d106); | |
+ stfm1000_write(STFM1000_INITIALIZATION6, 0x000062cb); | |
+ stfm1000_write(STFM1000_AGC_CONTROL1, 0x1BCB2202); | |
+ stfm1000_write(STFM1000_AGC_CONTROL2, 0x000020F0); | |
+ stfm1000_write(STFM1000_CLK1, 0x10000000); | |
+ stfm1000_write(STFM1000_CLK1, 0x20000000); | |
+ stfm1000_write(STFM1000_CLK1, 0x00000000); | |
+ stfm1000_write(STFM1000_CLK2, 0x7f000000); | |
+ stfm1000_write(STFM1000_REF, 0x00B8222D); | |
+ stfm1000_write(STFM1000_CLK1, 0x30000000); | |
+ stfm1000_write(STFM1000_CLK1, 0x30002000); | |
+ stfm1000_write(STFM1000_CLK1, 0x10002000); | |
+ stfm1000_write(STFM1000_LNA, 0x0D080009); | |
+ sleep(10 * HZ / 1000); | |
+ stfm1000_write(STFM1000_MIXFILT, 0x00008000); | |
+ stfm1000_write(STFM1000_MIXFILT, 0x00000000); | |
+ stfm1000_write(STFM1000_MIXFILT, 0x00007205); | |
+ stfm1000_write(STFM1000_ADC, 0x001B3282); | |
+ stfm1000_write(STFM1000_ATTENTION, 0x0000003F); | |
+ | |
+ stfm1000_dp_enable(true); | |
+ stfm_dri_enable(true); | |
+} | |
+ | |
+static void stfm1000_sleep(bool sleep) | |
+{ | |
+ (void)sleep; | |
+ /* no implementation yet */ | |
+} | |
+ | |
+static int stfm1000_rssi(void) | |
+{ | |
+ uint32_t rssi_dc_est; | |
+ int rssi_mantissa, rssi_exponent, rssi_decoded; | |
+ int prssi; | |
+ int rssi_log; | |
+ | |
+ stfm1000_read(STFM1000_RSSI_TONE, &rssi_dc_est); | |
+ | |
+ rssi_mantissa = (rssi_dc_est & 0xffe0) >> 5; /* 11Msb */ | |
+ rssi_exponent = rssi_dc_est & 0x001f; /* 5 lsb */ | |
+ rssi_decoded = (uint32_t)rssi_mantissa << rssi_exponent; | |
+ | |
+ /* Convert Rsst to 10log(Rssi) */ | |
+ for (prssi = 20; prssi > 0; prssi--) | |
+ if (rssi_decoded >= (1 << prssi)) | |
+ break; | |
+ | |
+ rssi_log = (3 * rssi_decoded >> prssi) + (3 * prssi - 3); | |
+ | |
+ /* clamp to positive */ | |
+ if (rssi_log < 0) | |
+ rssi_log = 0; | |
+ | |
+ /* Compensate for errors in truncation/approximation by adding 1 */ | |
+ rssi_log++; | |
+ | |
+ return rssi_log; | |
+} | |
+ | |
+static bool stfm1000_tuned(void) | |
+{ | |
+ uint32_t tmp; | |
+ int pilot; | |
+ | |
+ /* get pilot */ | |
+ stfm1000_read(STFM1000_PILOTCORRECTION, &tmp); | |
+ pilot = (tmp & STFM1000_PILOTEST_TB2_MASK) >> STFM1000_PILOTEST_TB2_SHIFT; | |
+ | |
+ /* check pilot and signal strength */ | |
+ return (pilot >= 0x1E) && (pilot < 0x80) && (stfm1000_rssi() > 28); | |
} | |
int stfm1000_set(int setting, int value) | |
{ | |
- (void) setting; | |
- (void) value; | |
- return -1; | |
+ int val = 0; | |
+ | |
+ switch (setting) { | |
+ case RADIO_SLEEP: | |
+ stfm1000_sleep(value); | |
+ break; | |
+ | |
+ case RADIO_FREQUENCY: | |
+ stfm1000_set_frequency(value / 1000); | |
+ stfm1000_optimise_channel(); | |
+ imx233_dri_enable(true); | |
+ break; | |
+ | |
+ case RADIO_SCAN_FREQUENCY: | |
+ stfm1000_set_frequency(value / 1000); | |
+ val = stfm1000_tuned(); | |
+ break; | |
+ | |
+ case RADIO_MUTE: | |
+ /* no implementation yet */ | |
+ break; | |
+ | |
+ case RADIO_REGION: | |
+ stfm1000_set_region(value); | |
+ break; | |
+ | |
+ case RADIO_FORCE_MONO: | |
+ /* no implementation yet */ | |
+ break; | |
+ | |
+ default: | |
+ val = -1; | |
+ break; | |
+ } | |
+ | |
+ return val; | |
} | |
int stfm1000_get(int setting) | |
{ | |
- (void) setting; | |
- return -1; | |
-} | |
\ No newline at end of file | |
+ int val = -1; /* default for unsupported query */ | |
+ | |
+ switch (setting) { | |
+ | |
+ case RADIO_PRESENT: | |
+ val = true; | |
+ break; | |
+ | |
+ case RADIO_TUNED: | |
+ val = stfm1000_tuned(); | |
+ break; | |
+ | |
+ case RADIO_STEREO: | |
+ val = 0; | |
+ break; | |
+#if 1 | |
+ case RADIO_RSSI: | |
+ val = stfm1000_rssi(); | |
+ break; | |
+ | |
+ case RADIO_RSSI_MIN: | |
+ val = 0; | |
+ break; | |
+ | |
+ case RADIO_RSSI_MAX: | |
+ val = 70; | |
+ break; | |
+#endif | |
+ } | |
+ | |
+ return val; | |
+} | |
diff --git a/firmware/export/stfm1000.h b/firmware/export/stfm1000.h | |
index 6c01d63..62a1dd9 100644 | |
--- a/firmware/export/stfm1000.h | |
+++ b/firmware/export/stfm1000.h | |
@@ -31,6 +31,11 @@ | |
struct stfm1000_dbg_info | |
{ | |
+ uint32_t tune1; | |
+ uint32_t sdnominal; | |
+ uint32_t pilottracking; | |
+ uint32_t rssi_tone; | |
+ uint32_t pilotcorrection; | |
uint32_t chipid; | |
}; | |
diff --git a/firmware/target/arm/imx233/creative-zenxfi2/audio-zenxfi2.c b/firmware/target/arm/imx233/creative-zenxfi2/audio-zenxfi2.c | |
index 810f1c1..7d913a9 100644 | |
--- a/firmware/target/arm/imx233/creative-zenxfi2/audio-zenxfi2.c | |
+++ b/firmware/target/arm/imx233/creative-zenxfi2/audio-zenxfi2.c | |
@@ -31,7 +31,7 @@ static int output_source = AUDIO_SRC_PLAYBACK; | |
static void select_audio_path(void) | |
{ | |
- if(input_source == AUDIO_SRC_PLAYBACK) | |
+ if(input_source == AUDIO_SRC_PLAYBACK || true) | |
imx233_audioout_select_hp_input(false); | |
else | |
imx233_audioout_select_hp_input(true); | |
diff --git a/firmware/target/arm/imx233/debug-imx233.c b/firmware/target/arm/imx233/debug-imx233.c | |
index c170139..b55a0c2 100644 | |
--- a/firmware/target/arm/imx233/debug-imx233.c | |
+++ b/firmware/target/arm/imx233/debug-imx233.c | |
@@ -32,6 +32,7 @@ | |
#include "rtc-imx233.h" | |
#include "dcp-imx233.h" | |
#include "pinctrl-imx233.h" | |
+#include "dri-imx233.h" | |
#include "string.h" | |
#define DEBUG_CANCEL BUTTON_BACK | |
@@ -46,6 +47,7 @@ static struct | |
{ "dac", APB_AUDIO_DAC }, | |
{ "ssp1", APB_SSP(1) }, | |
{ "ssp2", APB_SSP(2) }, | |
+ { "dri", APB_DRI }, | |
}; | |
static struct | |
@@ -537,12 +539,42 @@ bool dbg_hw_info_pinctrl(void) | |
} | |
} | |
+bool dbg_hw_info_dri(void) | |
+{ | |
+ lcd_setfont(FONT_SYSFIXED); | |
+ | |
+ while(1) | |
+ { | |
+ int button = get_action(CONTEXT_STD, HZ / 10); | |
+ switch(button) | |
+ { | |
+ case ACTION_STD_NEXT: | |
+ case ACTION_STD_PREV: | |
+ case ACTION_STD_OK: | |
+ case ACTION_STD_MENU: | |
+ lcd_setfont(FONT_UI); | |
+ return true; | |
+ case ACTION_STD_CANCEL: | |
+ lcd_setfont(FONT_UI); | |
+ return false; | |
+ } | |
+ | |
+ lcd_clear_display(); | |
+ struct imx233_dri_info_t info = imx233_dri_get_info(); | |
+ lcd_putsf(0, 0, "DRI"); | |
+ lcd_putsf(0, 1, "run: %d", info.running); | |
+ lcd_putsf(0, 2, "inputs: %d", info.inputs_enabled); | |
+ lcd_update(); | |
+ yield(); | |
+ } | |
+} | |
+ | |
bool dbg_hw_info(void) | |
{ | |
return dbg_hw_info_clkctrl() && dbg_hw_info_dma() && dbg_hw_info_adc() && | |
dbg_hw_info_power() && dbg_hw_info_powermgmt() && dbg_hw_info_rtc() && | |
dbg_hw_info_dcp() && dbg_hw_info_pinctrl() && dbg_hw_info_icoll() && | |
- dbg_hw_target_info(); | |
+ dbg_hw_info_dri() && dbg_hw_target_info(); | |
} | |
bool dbg_ports(void) | |
diff --git a/firmware/target/arm/imx233/dma-imx233.h b/firmware/target/arm/imx233/dma-imx233.h | |
index ee836c2..10a0d1e 100644 | |
--- a/firmware/target/arm/imx233/dma-imx233.h | |
+++ b/firmware/target/arm/imx233/dma-imx233.h | |
@@ -79,6 +79,7 @@ | |
#define HW_APBX_AUDIO_ADC 0 | |
#define HW_APBX_AUDIO_DAC 1 | |
#define HW_APBX_I2C 3 | |
+#define HW_APBX_DRI 5 | |
#define HW_APBX_BASE 0x80024000 | |
@@ -166,6 +167,7 @@ struct imx233_dma_info_t | |
#define APB_AUDIO_DAC APBX_DMA_CHANNEL(HW_APBX_AUDIO_DAC) | |
#define APB_I2C APBX_DMA_CHANNEL(HW_APBX_I2C) | |
#define APB_NAND(dev) APBH_DMA_CHANNEL(HW_APBH_NAND(dev)) | |
+#define APB_DRI APBX_DMA_CHANNEL(HW_APBX_DRI) | |
#define HW_APB_CHx_CMD__COMMAND_BM 0x3 | |
#define HW_APB_CHx_CMD__COMMAND__NO_XFER 0 | |
diff --git a/firmware/target/arm/imx233/dri-imx233.c b/firmware/target/arm/imx233/dri-imx233.c | |
new file mode 100644 | |
index 0000000..2bc2d4c | |
--- /dev/null | |
+++ b/firmware/target/arm/imx233/dri-imx233.c | |
@@ -0,0 +1,134 @@ | |
+/*************************************************************************** | |
+ * __________ __ ___. | |
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | |
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | |
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | |
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | |
+ * \/ \/ \/ \/ \/ | |
+ * $Id$ | |
+ * | |
+ * Copyright (C) 2012 by Amaury Pouly | |
+ * | |
+ * 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 "dri-imx233.h" | |
+#include "clkctrl-imx233.h" | |
+#include "system-target.h" | |
+#include "dma-imx233.h" | |
+#include "icoll-imx233.h" | |
+#include "string.h" | |
+#include "pcm.h" | |
+#include "pcm_sampr.h" | |
+ | |
+struct pcm_dma_command_t | |
+{ | |
+ struct apb_dma_command_t dma; | |
+ /* padded to next multiple of cache line size (32 bytes) */ | |
+ uint32_t pad[5]; | |
+} __attribute__((packed)) CACHEALIGN_ATTR; | |
+ | |
+struct dri_dma_command_t | |
+{ | |
+ struct apb_dma_command_t dma; | |
+ /* padded to next multiple of cache line size (32 bytes) */ | |
+ uint32_t pad[5]; | |
+} __attribute__((packed)) CACHEALIGN_ATTR; | |
+ | |
+__ENSURE_STRUCT_CACHE_FRIENDLY(struct pcm_dma_command_t) | |
+__ENSURE_STRUCT_CACHE_FRIENDLY(struct dri_dma_command_t) | |
+ | |
+static struct pcm_dma_command_t dac_dma; | |
+static struct dri_dma_command_t dri_dma; | |
+ | |
+#define DRI_BUFFER_SIZE 40000 | |
+#define DAC_BUFFER_SIZE 10000 | |
+ | |
+static uint16_t dri_buffer[DRI_BUFFER_SIZE]; | |
+static uint16_t dac_buffer[DAC_BUFFER_SIZE]; | |
+static bool pcm_playing = false; | |
+ | |
+void imx233_dri_init(void) | |
+{ | |
+ imx233_reset_block(&HW_DRI_CTRL); | |
+} | |
+ | |
+void dri_pcm_cb(const void **start, size_t *size) | |
+{ | |
+ if(pcm_playing) | |
+ { | |
+ *start = dac_buffer; | |
+ *size = DAC_BUFFER_SIZE; | |
+ } | |
+ else | |
+ { | |
+ *start = NULL; | |
+ *size = 0; | |
+ } | |
+} | |
+ | |
+void INT_DRI_DMA(void) | |
+{ | |
+ for(size_t i = 0, j = 0; i< DRI_BUFFER_SIZE && j < DAC_BUFFER_SIZE; i += 4, j += 2) | |
+ { | |
+ dac_buffer[j] = dri_buffer[i]; | |
+ dac_buffer[j + 1] = 0; | |
+ } | |
+ | |
+ imx233_dma_clear_channel_interrupt(APB_DRI); | |
+} | |
+ | |
+void imx233_dri_enable(bool en) | |
+{ | |
+ if(en) | |
+ { | |
+ imx233_reset_block(&HW_DRI_CTRL); | |
+ imx233_clkctrl_enable_xtal(XTAL_DRI, true); | |
+ pcm_set_frequency(FREQ_44); | |
+ pcm_apply_settings(); | |
+ pcm_play_data(dri_pcm_cb, NULL, dac_buffer, DAC_BUFFER_SIZE); | |
+ pcm_play_pause(true); | |
+ | |
+ imx233_dma_reset_channel(APB_DRI); | |
+ imx233_icoll_enable_interrupt(INT_SRC_DRI_DMA, true); | |
+ imx233_dma_enable_channel_interrupt(APB_DRI, true); | |
+ | |
+ dri_dma.dma.next = &dri_dma.dma; | |
+ dri_dma.dma.buffer = (void *)dri_buffer; | |
+ dri_dma.dma.cmd = HW_APB_CHx_CMD__COMMAND__WRITE | | |
+ DRI_BUFFER_SIZE << HW_APB_CHx_CMD__XFER_COUNT_BP | | |
+ HW_APB_CHx_CMD__IRQONCMPLT | | |
+ HW_APB_CHx_CMD__CHAIN; | |
+ /* dma subsystem will make sure cached stuff is written to memory */ | |
+ imx233_dma_start_command(APB_DRI, &dri_dma.dma); | |
+ | |
+ __REG_SET(HW_DRI_CTRL) = HW_DRI_CTRL__ENABLE_INPUTS | HW_DRI_CTRL__RUN | | |
+ HW_DRI_CTRL__REACQUIRE_PHASE; | |
+ } | |
+ else | |
+ { | |
+ pcm_play_stop(); | |
+ imx233_dma_enable_channel_interrupt(APB_DRI, false); | |
+ imx233_icoll_enable_interrupt(INT_SRC_DRI_DMA, false); | |
+ pcm_playing = false; | |
+ __REG_CLR(HW_DRI_CTRL) = HW_DRI_CTRL__ENABLE_INPUTS | HW_DRI_CTRL__RUN; | |
+ imx233_clkctrl_enable_xtal(XTAL_DRI, false); | |
+ } | |
+} | |
+ | |
+struct imx233_dri_info_t imx233_dri_get_info(void) | |
+{ | |
+ struct imx233_dri_info_t info; | |
+ memset(&info, 0, sizeof(info)); | |
+ | |
+ info.running = !!(HW_DRI_CTRL & HW_DRI_CTRL__RUN); | |
+ info.inputs_enabled = !!(HW_DRI_CTRL & HW_DRI_CTRL__ENABLE_INPUTS); | |
+ | |
+ return info; | |
+} | |
\ No newline at end of file | |
diff --git a/firmware/target/arm/imx233/dri-imx233.h b/firmware/target/arm/imx233/dri-imx233.h | |
new file mode 100644 | |
index 0000000..6914baa | |
--- /dev/null | |
+++ b/firmware/target/arm/imx233/dri-imx233.h | |
@@ -0,0 +1,59 @@ | |
+/*************************************************************************** | |
+ * __________ __ ___. | |
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | |
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | |
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | |
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | |
+ * \/ \/ \/ \/ \/ | |
+ * $Id$ | |
+ * | |
+ * Copyright (C) 2012 by Amaury Pouly | |
+ * | |
+ * 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 __dri_imx233__ | |
+#define __dri_imx233__ | |
+ | |
+#include "config.h" | |
+#include "cpu.h" | |
+#include "system.h" | |
+ | |
+#define HW_DRI_BASE 0x80074000 | |
+ | |
+#define HW_DRI_CTRL (*(volatile uint32_t *)(HW_DRI_BASE + 0x0)) | |
+#define HW_DRI_CTRL__RUN (1 << 0) | |
+#define HW_DRI_CTRL__REACQUIRE_PHASE (1 << 15) | |
+#define HW_DRI_CTRL__ENABLE_INPUTS (1 << 29) | |
+ | |
+#define HW_DRI_TIMING (*(volatile uint32_t *)(HW_DRI_BASE + 0x10)) | |
+#define HW_DRI_TIMING__GAP_DETECTION_INTERVAL_BP 0 | |
+#define HW_DRI_TIMING__GAP_DETECTION_INTERVAL_BM 0xff | |
+#define HW_DRI_TIMING__PILOT_REP_RATE_BP 16 | |
+#define HW_DRI_TIMING__PILOT_REP_RATE_BM (0xf << 16) | |
+ | |
+#define HW_DRI_STAT (*(volatile uint32_t *)(HW_DRI_BASE + 0x20)) | |
+ | |
+#define HW_DRI_DATA (*(volatile uint32_t *)(HW_DRI_BASE + 0x30)) | |
+ | |
+#define HW_DRI_DEBUG0 (*(volatile uint32_t *)(HW_DRI_BASE + 0x40)) | |
+ | |
+#define HW_DRI_DEBUG1 (*(volatile uint32_t *)(HW_DRI_BASE + 0x50)) | |
+ | |
+struct imx233_dri_info_t | |
+{ | |
+ bool running; | |
+ bool inputs_enabled; | |
+}; | |
+ | |
+void imx233_dri_init(void); | |
+void imx233_dri_enable(bool en); | |
+struct imx233_dri_info_t imx233_dri_get_info(void); | |
+ | |
+#endif /* __dri_imx233__ */ | |
diff --git a/firmware/target/arm/imx233/icoll-imx233.c b/firmware/target/arm/imx233/icoll-imx233.c | |
index 4e0d525..9a0e1da 100644 | |
--- a/firmware/target/arm/imx233/icoll-imx233.c | |
+++ b/firmware/target/arm/imx233/icoll-imx233.c | |
@@ -61,6 +61,8 @@ default_interrupt(INT_ADC_DMA); | |
default_interrupt(INT_ADC_ERROR); | |
default_interrupt(INT_DCP); | |
default_interrupt(INT_TOUCH_DETECT); | |
+default_interrupt(INT_DRI_DMA); | |
+default_interrupt(INT_DRI_ATTENTION); | |
void INT_RTC_1MSEC(void); | |
@@ -100,6 +102,8 @@ static isr_t isr_table[INT_SRC_NR_SOURCES] = | |
[INT_SRC_DCP] = INT_DCP, | |
[INT_SRC_TOUCH_DETECT] = INT_TOUCH_DETECT, | |
[INT_SRC_RTC_1MSEC] = INT_RTC_1MSEC, | |
+ [INT_SRC_DRI_DMA] = INT_DRI_DMA, | |
+ [INT_SRC_DRI_ATTENTION] = INT_DRI_ATTENTION, | |
}; | |
#define IRQ_STORM_DELAY 1000 /* ms */ | |
diff --git a/firmware/target/arm/imx233/icoll-imx233.h b/firmware/target/arm/imx233/icoll-imx233.h | |
index d1bf8a1..7abb0ac 100644 | |
--- a/firmware/target/arm/imx233/icoll-imx233.h | |
+++ b/firmware/target/arm/imx233/icoll-imx233.h | |
@@ -65,6 +65,8 @@ | |
#define INT_SRC_LCDIF_DMA 45 | |
#define INT_SRC_LCDIF_ERROR 46 | |
#define INT_SRC_RTC_1MSEC 48 | |
+#define INT_SRC_DRI_DMA 49 | |
+#define INT_SRC_DRI_ATTENTION 50 | |
#define INT_SRC_DCP 54 | |
#define INT_SRC_NR_SOURCES 66 | |
diff --git a/tools/configure b/tools/configure | |
index 4d3d746..da52a10 100755 | |
--- a/tools/configure | |
+++ b/tools/configure | |
@@ -2211,7 +2211,7 @@ fi | |
output="rockbox.creative" | |
bootoutput="bootloader-zenxfi2.creative" | |
appextra="gui:recorder:radio" | |
- plugins="yes" | |
+ plugins="" | |
swcodec="yes" | |
toolset=$scramblebitmaptools | |
t_cpu="arm" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment