All pastes #1883063 Raw Edit

Unnamed

public text v1 · immutable
#1883063 ·published 2010-06-14 18:27 UTC
rendered paste body
Index: apps/debug_menu.c
===================================================================
--- apps/debug_menu.c	(revision 26846)
+++ apps/debug_menu.c	(working copy)
@@ -2369,25 +2369,16 @@
 #endif /* TEA5767 */
 #if (CONFIG_TUNER & SI4700)
     struct si4700_dbg_info nfo;
+    int i;
     si4700_dbg_info(&nfo);
     simplelist_addline(SIMPLELIST_ADD_LINE, "SI4700 regs:");
     /* Registers */
-    simplelist_addline(SIMPLELIST_ADD_LINE,
-             "%04X %04X %04X %04X",
-             (unsigned)nfo.regs[0], (unsigned)nfo.regs[1],
-             (unsigned)nfo.regs[2], (unsigned)nfo.regs[3]);
-    simplelist_addline(SIMPLELIST_ADD_LINE,
-             "%04X %04X %04X %04X",
-             (unsigned)nfo.regs[4], (unsigned)nfo.regs[5],
-             (unsigned)nfo.regs[6], (unsigned)nfo.regs[7]);
-    simplelist_addline(SIMPLELIST_ADD_LINE,
-             "%04X %04X %04X %04X",
-             (unsigned)nfo.regs[8], (unsigned)nfo.regs[9],
-             (unsigned)nfo.regs[10], (unsigned)nfo.regs[11]);
-    simplelist_addline(SIMPLELIST_ADD_LINE,
-             "%04X %04X %04X %04X",
-             (unsigned)nfo.regs[12], (unsigned)nfo.regs[13],
-             (unsigned)nfo.regs[14], (unsigned)nfo.regs[15]);
+    for (i = 0; i < 8; i++) {
+        simplelist_addline(SIMPLELIST_ADD_LINE,
+                 "%04X %04X %04X %04X",
+                 (unsigned)nfo.regs[4*i], (unsigned)nfo.regs[4*i+1],
+                 (unsigned)nfo.regs[4*i+2], (unsigned)nfo.regs[4*i+3]);
+    }
 #endif /* SI4700 */
     return ACTION_REDRAW;
 }
@@ -2400,7 +2391,8 @@
     simplelist_addline(SIMPLELIST_ADD_LINE, "HW detected: %s",
                        radio_hardware_present() ? "yes" : "no");
 
-    info.action_callback = radio_hardware_present()?radio_callback : NULL;
+//    info.action_callback = radio_hardware_present()?radio_callback : NULL;
+    info.action_callback = radio_callback;
     info.hide_selection = true;
     return simplelist_show_list(&info);
 }
Index: firmware/export/si4700.h
===================================================================
--- firmware/export/si4700.h	(revision 26846)
+++ firmware/export/si4700.h	(working copy)
@@ -38,7 +38,7 @@
 
 struct si4700_dbg_info
 {
-    uint16_t regs[16];  /* Read registers */
+    uint16_t regs[32];  /* Read registers */
 };
 
 void si4700_init(void);
Index: firmware/drivers/tuner/si4700.c
===================================================================
--- firmware/drivers/tuner/si4700.c	(revision 26846)
+++ firmware/drivers/tuner/si4700.c	(working copy)
@@ -7,9 +7,10 @@
  *                     \/            \/     \/    \/            \/
  * $Id$
  *
- * Tuner "middleware" for Silicon Labs SI4700 chip
+ * Tuner "middleware" for Unidentified Silicon Labs chip present in some
+ * Sansa Clip+ players
  *
- * Copyright (C) 2008 Nils Wallmnius
+ * Copyright (C) 2010 Bertrik Sikken
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -30,200 +31,73 @@
 #include "fmradio.h"
 #include "fmradio_i2c.h" /* physical interface driver */
 
-/* some models use the internal 32 kHz oscillator which needs special attention
-   during initialisation, power-up and power-down.
-*/
-#if defined(SANSA_CLIP) || defined(SANSA_E200V2) || defined(SANSA_FUZE) || defined(SANSA_C200V2)
-#define USE_INTERNAL_OSCILLATOR
-#elif defined(TOSHIBA_GIGABEAT_S)
-#define SI4700_GPIO_SETUP (SYSCONFIG1_GPIO1_HI_Z | \
-                           SYSCONFIG1_GPIO2_HI_Z | \
-                           SYSCONFIG1_GPIO3_MO_ST_I)
-extern int si4700_st(void);
-#endif
+#define SEEK_THRESHOLD 0x10
 
-#ifndef SI4700_GPIO_SETUP
-#define SI4700_GPIO_SETUP 0
-#endif
-
-#define SEEK_THRESHOLD 0x16
-
 #define I2C_ADR 0x20
 
 /** Registers and bits - "x" denotes Si4702/03 only (so they say) **/
-#define DEVICEID    0x0
-#define CHIPID      0x1
 #define POWERCFG    0x2
 #define CHANNEL     0x3
 #define SYSCONFIG1  0x4
 #define SYSCONFIG2  0x5
 #define SYSCONFIG3  0x6
-#define TEST1       0x7
-#define TEST2       0x8
-#define BOOTCONFIG  0x9
-#define STATUSRSSI  0xA
-#define READCHAN    0xB
-#define RDSA        0xC /* x */
-#define RDSB        0xD /* x */
-#define RDSC        0xE /* x */
-#define RDSD        0xF /* x */
 
-/* DEVICEID (0x0) */
-#define DEVICEID_PN         (0xf << 12)
-    /* 0x01 = Si4700/01 */
-    /* 0x01 = Si4702/03 */
-#define DEVICEID_MFGID      (0xfff << 0)
-    /* always 0x242 */
+#define READCHAN    0xA
+#define STATUSRSSI  0xB
+#define IDENT       0xC
 
-/* CHIPID (0x1) */
 
-#if 0 /* Informational */
-/* Si4700/01 */
-#define CHIPID_REV          (0x3f << 10)
-#define CHIPID_DEV          (0x1 << 9)
-    /* 0 before powerup */
-    /* 0 after powerup = Si4700 */
-    /* 1 after powerup = Si4701 */
-#define CHIPID_FIRMWARE     (0xff << 0)
-
-/* Si4702/03 */
-#define CHIPID_REV          (0x3f << 10)
-#define CHIPID_DEV          (0xf << 6)
-    /* 0000 before PU = Si4702 */
-    /* 0001 after PU = Si4702 */
-    /* 1000 before PU = Si4703 */
-    /* 1001 after PU = Si4703 */
-#define CHIPID_FIRMWARE     (0x3f << 0)
-#endif /* 0 */
-
 /* POWERCFG (0x2) */
-#define POWERCFG_DSMUTE     (0x1 << 15)
 #define POWERCFG_DMUTE      (0x1 << 14)
 #define POWERCFG_MONO       (0x1 << 13)
-#define POWERCFG_RDSM       (0x1 << 11) /* x */
-#define POWERCFG_SKMODE     (0x1 << 10)
-#define POWERCFG_SEEKUP     (0x1 <<  9)
-#define POWERCFG_SEEK       (0x1 <<  8)
-#define POWERCFG_DISABLE    (0x1 <<  6)
 #define POWERCFG_ENABLE     (0x1 <<  0)
 
 /* CHANNEL (0x3) */
-#define CHANNEL_TUNE        (0x1 << 15)
-#define CHANNEL_CHAN        (0x3ff << 0)
-    #define CHANNEL_CHANw(x) ((x) & CHANNEL_CHAN)
+#define CHANNEL_CHAN        (0x3ff << 6)
+    #define CHANNEL_CHANw(x) (((x) << 6) & CHANNEL_CHAN)
+#define CHANNEL_TUNE        (0x1 << 4)
+#define CHANNEL_BAND        (0x3 << 2)
+    #define CHANNEL_BANDw(x)        (((x) << 2) & CHANNEL_BAND)
+    #define CHANNEL_BANDr(x)        (((x) & CHANNEL_BAND) >> 2)
+    #define CHANNEL_BAND_875_1080   (0x0 << 2) /* tenth-megahertz */
+    #define CHANNEL_BAND_760_1080   (0x1 << 2)
+    #define CHANNEL_BAND_760_900    (0x2 << 2)
+#define CHANNEL_SPACE       (0x3 << 0)
+    #define CHANNEL_SPACEw(x)  (((x) << 0) & CHANNEL_SPACE)
+    #define CHANNEL_SPACEr(x)  (((x) & CHANNEL_SPACE) >> 0)
+    #define CHANNEL_SPACE_200KHZ    (0x0 << 0)
+    #define CHANNEL_SPACE_100KHZ    (0x1 << 0)
+    #define CHANNEL_SPACE_50KHZ     (0x2 << 0)
 
 /* SYSCONFIG1 (0x4) */
-#define SYSCONFIG1_RDSIEN   (0x1 << 15) /* x */
-#define SYSCONFIG1_STCIEN   (0x1 << 14)
-#define SYSCONFIG1_RDS      (0x1 << 12) /* x */
 #define SYSCONFIG1_DE       (0x1 << 11)
-#define SYSCONFIG1_AGCD     (0x1 << 10)
-#define SYSCONFIG1_BLNDADJ  (0x3 <<  6)
-    #define SYSCONFIG1_BLNDADJ_31_39_RSSI (0x0 << 6)
-    #define SYSCONFIG1_BLNDADJ_37_55_RSSI (0x1 << 6)
-    #define SYSCONFIG1_BLNDADJ_19_37_RSSI (0x2 << 6)
-    #define SYSCONFIG1_BLNDADJ_25_43_RSSI (0x3 << 6)
-#define SYSCONFIG1_GPIO3    (0x3 <<  4)
-    #define SYSCONFIG1_GPIO3_HI_Z       (0x0 << 4)
-    #define SYSCONFIG1_GPIO3_MO_ST_I    (0x1 << 4)
-    #define SYSCONFIG1_GPIO3_LOW        (0x2 << 4)
-    #define SYSCONFIG1_GPIO3_HI         (0x3 << 4)
-#define SYSCONFIG1_GPIO2    (0x3 <<  2)
-    #define SYSCONFIG1_GPIO2_HI_Z       (0x0 << 2)
-    #define SYSCONFIG1_GPIO2_STC_RDS_I  (0x1 << 2)
-    #define SYSCONFIG1_GPIO2_LOW        (0x2 << 2)
-    #define SYSCONFIG1_GPIO2_HI         (0x3 << 2)
-#define SYSCONFIG1_GPIO1    (0x3 <<  0)
-    #define SYSCONFIG1_GPIO1_HI_Z       (0x0 << 0)
-    #define SYSCONFIG1_GPIO1_LOW        (0x2 << 0)
-    #define SYSCONFIG1_GPIO1_HI         (0x3 << 0)
 
-/* SYSCONFIG2 (0x5) */
-#define SYSCONFIG2_SEEKTH   (0xff << 8)
-    #define SYSCONFIG2_SKEETHw(x) (((x) << 8) & SYSCONFIG2_SEEKTH)
-#define SYSCONFIG2_BAND     (0x3 << 6)
-    #define SYSCONFIG2_BANDw(x)   (((x) << 6) & SYSCONFIG2_BAND)
-    #define SYSCONFIG2_BANDr(x)   (((x) & SYSCONFIG2_BAND) >> 6)
-    #define SYSCONFIG2_BAND_875_1080    (0x0 << 6) /* tenth-megahertz */
-    #define SYSCONFIG2_BAND_760_1080    (0x1 << 6)
-    #define SYSCONFIG2_BAND_760_900     (0x2 << 6)
-#define SYSCONFIG2_SPACE    (0x3 << 4)
-    #define SYSCONFIG2_SPACEw(x)  (((x) << 4) & SYSCONFIG2_SPACE)
-    #define SYSCONFIG2_SPACEr(x)  (((x) & SYSCONFIG2_SPACE) >> 4)
-    #define SYSCONFIG2_SPACE_200KHZ     (0x0 << 4)
-    #define SYSCONFIG2_SPACE_100KHZ     (0x1 << 4)
-    #define SYSCONFIG2_SPACE_50KHZ      (0x2 << 4)
-/* 4700/01            0000=mute,0001=-28dBFS..2dB steps..1111= +0dBFS */
-/* 4702/03: VOLEXT=0: 0000=mute,0001=-28dBFS..2dB steps..1111= +0dBFS */
-/*          VOLEXT=1: 0000=mute,0001=-58dBFS..2dB steps..1111=-30dBFS */
-#define SYSCONFIG2_VOLUME   (0xf << 0)
-    #define SYSCONFIG2_VOLUMEw(x) ((x) & SYSCONFIG2_VOLUME)
-
-/* SYSCONFIG3 (0x6) */
-#define SYSCONFIG3_SMUTER   (0x3 << 14)
-    #define SYSCONFIG3_SMUTER_FASTEST   (0x0 << 14)
-    #define SYSCONFIG3_SMUTER_FAST      (0x1 << 14)
-    #define SYSCONFIG3_SMUTER_SLOW      (0x2 << 14)
-    #define SYSCONFIG3_SMUTER_SLOWEST   (0x3 << 14)
-#define SYSCONFIG3_SMUTEA   (0x3 << 12)
-    #define SYSCONFIG3_SMUTEA_16DB      (0x0 << 12)
-    #define SYSCONFIG3_SMUTEA_14DB      (0x1 << 12)
-    #define SYSCONFIG3_SMUTEA_12DB      (0x2 << 12)
-    #define SYSCONFIG3_SMUTEA_10DB      (0x3 << 12)
-#define SYSCONFIG3_VOLEXT   (0x1 << 8) /* x */
-#define SYSCONFIG3_SKSNR    (0xf << 4)
-    #define SYSCONFIG3_SKSNRw(x) (((x) << 4) & SYSCONFIG3_SKSNR)
-#define SYSCONFIG3_SKCNT    (0xf << 0)
-    #define SYSCONFIG3_SKCNTw(x) (((x) << 0) & SYSCONFIG3_SKCNT)
-
-/* TEST1 (0x7) */
-/* 4700/01: 15=always 0, 13:0 = write with preexisting values! */
-/* 4702/03:              13:0 = write with preexisting values! */
-#define TEST1_XOSCEN        (0x1 << 15) /* x */
-#define TEST1_AHIZEN        (0x1 << 14)
-
-/* TEST2 (0x8) */
-/* 15:0 = write with preexisting values! */
-
-/* BOOTCONFIG (0x9) */
-/* 15:0 = write with preexisting values! */
-
-/* STATUSRSSI (0xA) */
-#define STATUSRSSI_RDSR     (0x1 << 15) /* x */
-#define STATUSRSSI_STC      (0x1 << 14)
-#define STATUSRSSI_SFBL     (0x1 << 13)
-#define STATUSRSSI_AFCRL    (0x1 << 12)
-#define STATUSRSSI_RDSS     (0x1 << 11) /* x */
-#define STATUSRSSI_BLERA    (0x3 <<  9) /* x */
-#define STATUSRSSI_ST       (0x1 <<  8)
-#define STATUSRSSI_RSSI     (0xff << 0)
-    #define STATUSRSSI_RSSIr(x) ((x) & 0xff)
-
-/* READCHAN (0xB) */
-#define READCHAN_BLERB      (0x3 << 14) /* x */
-#define READCHAN_BLERC      (0x3 << 12) /* x */
-#define READCHAN_BLERD      (0x3 << 10) /* x */
+/* READCHAN (0xA) */
 #define READCHAN_READCHAN   (0x3ff << 0)
+    #define READCHAN_READCHANr(x) (((x) & READCHAN_READCHAN) >> 0)
+#define READCHAN_STC        (0x1 << 14)
 
-/* RDSA-D (0xC-0xF) */
-/* 4702/03: RDS Block A-D data */
+/* STATUSRSSI (0xB) */
+#define STATUSRSSI_RSSI     (0x3F << 10)
+    #define STATUSRSSI_RSSIr(x) (((x) & STATUSRSSI_RSSI) >> 10)
+#define STATUSRSSI_AFCRL    (0x1 << 8)
 
 static bool tuner_present = false;
 static int curr_frequency = 87500000; /* Current station frequency (HZ) */
-static uint16_t cache[16];
+static uint16_t cache[32];
 
 /* reads <len> registers from radio at offset 0x0A into cache */
 static void si4700_read(int len)
 {
     int i;
-    unsigned char buf[32];
+    unsigned char buf[64];
     unsigned char *ptr = buf;
     uint16_t data;
     
     fmradio_i2c_read(I2C_ADR, buf, len * 2);
     for (i = 0; i < len; i++) {
         data = ptr[0] << 8 | ptr[1];
-        cache[(i + STATUSRSSI) & 0xF] = data;
+        cache[(i + READCHAN) & 0x1F] = data;
         ptr += 2;
     }
 }
@@ -232,12 +106,12 @@
 static void si4700_write(int len)
 {
     int i;
-    unsigned char buf[32];
+    unsigned char buf[64];
     unsigned char *ptr = buf;
     uint16_t data;
 
     for (i = 0; i < len; i++) {
-        data = cache[(i + POWERCFG) & 0xF];
+        data = cache[(i + POWERCFG) & 0x1F];
         *ptr++ = (data >> 8) & 0xFF;
         *ptr++ = data & 0xFF;
     }
@@ -249,16 +123,21 @@
  * using the 3-wire interface. */
 static uint16_t si4700_read_reg(int reg)
 {
-    si4700_read(((reg - STATUSRSSI) & 0xF) + 1);
+    si4700_read(((reg - READCHAN) & 0x1F) + 1);
     return cache[reg];
 }
 
 static void si4700_write_reg(int reg, uint16_t value)
 {
     cache[reg] = value;
-    si4700_write(((reg - POWERCFG) & 0xF) + 1);
+//    si4700_write(((reg - POWERCFG) & 0xF) + 1);
 }
 
+static void si4700_write_cache(void)
+{
+    si4700_write(5);
+}
+
 static void si4700_write_masked(int reg, uint16_t bits, uint16_t mask)
 {
     si4700_write_reg(reg, (cache[reg] & ~mask) | (bits & mask));
@@ -274,106 +153,89 @@
     si4700_write_reg(reg, cache[reg] & ~mask);
 }
 
-#if (SI4700_GPIO_SETUP & SYSCONFIG1_GPIO3) != SYSCONFIG1_GPIO3_MO_ST_I
-/* Poll i2c for the stereo status */
-static inline int si4700_st(void)
-{
-    return (si4700_read_reg(STATUSRSSI) & STATUSRSSI_ST) >> 8;
-}
-#endif
-
 static void si4700_sleep(int snooze)
 {
     if (snooze)
     {
         /** power down **/
-        /* ENABLE high, DISABLE high */
-        si4700_write_set(POWERCFG,
-                         POWERCFG_DISABLE | POWERCFG_ENABLE);
-        /* Bits self-clear once placed in powerdown. */
-        cache[POWERCFG] &= ~(POWERCFG_DISABLE | POWERCFG_ENABLE);
+        si4700_write_masked(POWERCFG, 0, 0xFF);
     }
     else
     {
-        /** power up **/
-        /* ENABLE high, DISABLE low */
-        si4700_write_masked(POWERCFG, POWERCFG_ENABLE,
-                            POWERCFG_DISABLE | POWERCFG_ENABLE);
-        sleep(110 * HZ / 1000);
-
-        /* init register cache */
-        si4700_read(16);
-
-#if SI4700_GPIO_SETUP != 0
-        si4700_write_masked(SYSCONFIG1, SI4700_GPIO_SETUP, 
-                            SYSCONFIG1_GPIO1 | SYSCONFIG1_GPIO2 |
-                            SYSCONFIG1_GPIO3);
-#endif
-        si4700_write_masked(SYSCONFIG2,
-                            SYSCONFIG2_SKEETHw(SEEK_THRESHOLD) |
-                            SYSCONFIG2_VOLUMEw(0xF),
-                            SYSCONFIG2_VOLUME | SYSCONFIG2_SEEKTH);
+        si4700_write_masked(POWERCFG, 1, 0xFF);
     }
+    si4700_write_cache();
 }
 
-void si4700_init(void)
+static const uint16_t initvals[32] = {
+    0x8110, 0x4580, 0xC401, 0x1B90, 
+    0x0400, 0x866F, 0x8000, 0x4712, 
+    0x5EC6, 0x0000, 0x406E, 0x2D80, 
+    0x5803, 0x5804, 0x5804, 0x5804,
+    
+    0x0047, 0x9000, 0xF587, 0x0009, 
+    0x00F1, 0x41C0, 0x41E0, 0x506F,
+    0x5592, 0x007D, 0x10A0, 0x0780,
+    0x311D, 0x4006, 0x1F9B, 0x4C2B, 
+#if 0   /* there only seem to be 32 registers ... */
+    0x153F, 0xAF40, 0x0481, 0x1B2A, 
+    0x2D04, 0x802F, 0x178A, 0xD349,
+    0x1142
+#endif
+};
+
+bool fmclipplus_detect(void)
 {
-    tuner_power(true);
+    return ((si4700_read_reg(IDENT) & 0xFF00) == 0x5800);
+ }
 
-    /* read all registers */
-    si4700_read(16);
-    si4700_sleep(0);
-
-    /* check device id */
-    if (cache[DEVICEID] == 0x1242)
-    {
+void si4700_init(void)
+{
+    if (fmclipplus_detect()) {
         tuner_present = true;
 
-#ifdef USE_INTERNAL_OSCILLATOR
-        /* Enable the internal oscillator
-          (Si4702-16 needs this register to be initialised to 0x100) */
-        si4700_write_set(TEST1, TEST1_XOSCEN | 0x100);
-        sleep(HZ/2);
-#endif
-    }
+        // send pre-initialisation value
+        si4700_write_reg(POWERCFG, 0x200);
+        si4700_write(2);
+        sleep(HZ * 10 / 100);
 
-    si4700_sleep(1);
-
-    tuner_power(false);
+        // write initialisation values
+        memcpy(cache, initvals, sizeof(cache));
+        si4700_write(32);
+        sleep(HZ * 70 / 1000);
+    }
 }
 
 static void si4700_set_frequency(int freq)
 {
-    static const unsigned int spacings[3] =
-    {
-          200000, /* SYSCONFIG2_SPACE_200KHZ */
-          100000, /* SYSCONFIG2_SPACE_100KHZ */
-           50000, /* SYSCONFIG2_SPACE_50KHZ  */
-    };
-    static const unsigned int bands[3] =
-    {
-        87500000, /* SYSCONFIG2_BAND_875_1080 */
-        76000000, /* SYSCONFIG2_BAND_760_1080 */
-        76000000, /* SYSCONFIG2_BAND_760_900  */
-    };
+    int i;
 
     /* check BAND and spacings */
-    int space = SYSCONFIG2_SPACEr(cache[SYSCONFIG2]);
-    int band = SYSCONFIG2_BANDr(cache[SYSCONFIG2]);
-    int chan = (freq - bands[band]) / spacings[space];
+    si4700_read_reg(STATUSRSSI);
+    int start = CHANNEL_BANDr(cache[CHANNEL]) & 1 ? 76000000 : 87000000;
+    int chan = (freq - start) / 50000;
 
     curr_frequency = freq;
 
-    si4700_write_reg(CHANNEL, CHANNEL_CHANw(chan) | CHANNEL_TUNE);
-
-    do
-    {
-        /* tuning should be done within 60 ms according to the datasheet */
-        sleep(HZ * 60 / 1000);
+    for (i = 0; i < 5; i++) {
+        /* start tune */
+        si4700_write_masked(CHANNEL, CHANNEL_CHANw(chan) | CHANNEL_TUNE, CHANNEL_CHAN | CHANNEL_TUNE);
+        si4700_write_cache();
+        
+        /* wait a bit while tuning */
+        sleep(HZ * 70 / 1000);
+        si4700_write_clear(CHANNEL, CHANNEL_TUNE); /* Set TUNE low */
+        si4700_write_cache();
+        
+        /* are we tuned yet? */
+        si4700_read_reg(STATUSRSSI);
+        if (cache[READCHAN] & READCHAN_STC) {
+            if (READCHAN_READCHANr(cache[READCHAN]) == chan) {
+                // yay tuned
+                break;
+            }
+        }
     }
-    while ((si4700_read_reg(STATUSRSSI) & STATUSRSSI_STC) == 0); /* STC high? */
-
-    si4700_write_clear(CHANNEL, CHANNEL_TUNE); /* Set TUNE low */
 }
 
 static int si4700_tuned(void)
@@ -390,15 +252,14 @@
 static void si4700_set_region(int region)
 {
     const struct si4700_region_data *rd = &si4700_region_data[region];
-    uint16_t bandspacing = SYSCONFIG2_BANDw(rd->band) |
-                           SYSCONFIG2_SPACEw(rd->spacing);
-    uint16_t oldbs = cache[SYSCONFIG2] & (SYSCONFIG2_BAND | SYSCONFIG2_SPACE);
+    uint16_t bandspacing = CHANNEL_BANDw(rd->band) |
+                           CHANNEL_SPACEw(CHANNEL_SPACE_50KHZ);
+    uint16_t oldbs = cache[CHANNEL] & (CHANNEL_BAND | CHANNEL_SPACE);
 
-    si4700_write_masked(SYSCONFIG1,
-                        rd->deemphasis ? SYSCONFIG1_DE : 0,
+    si4700_write_masked(SYSCONFIG1, rd->deemphasis ? SYSCONFIG1_DE : 0,
                         SYSCONFIG1_DE);
-    si4700_write_masked(SYSCONFIG2, bandspacing,
-                        SYSCONFIG2_BAND | SYSCONFIG2_SPACE);
+    si4700_write_masked(CHANNEL, bandspacing, CHANNEL_BAND | CHANNEL_SPACE);
+    si4700_write_cache();
 
     /* Retune if this region change would change the channel number. */
     if (oldbs != bandspacing)
@@ -408,12 +269,12 @@
 /* tuner abstraction layer: set something to the tuner */
 int si4700_set(int setting, int value)
 {
-    switch(setting)
+    switch (setting)
     {
         case RADIO_SLEEP:
-            if (value != 2)
+            if (value != 2) {
                 si4700_sleep(value);
-            /* else actually it's 'pause' */
+            }
             break;
 
         case RADIO_FREQUENCY:
@@ -427,6 +288,9 @@
         case RADIO_MUTE:
             si4700_write_masked(POWERCFG, value ? 0 : POWERCFG_DMUTE,
                                 POWERCFG_DMUTE);
+            si4700_write_masked(SYSCONFIG1, (3 << 9), (3 << 9));
+            si4700_write_masked(SYSCONFIG2, (0xF << 0), (0xF << 0));
+            si4700_write_cache();
             break;
 
         case RADIO_REGION:
@@ -436,6 +300,7 @@
         case RADIO_FORCE_MONO:
             si4700_write_masked(POWERCFG, value ? POWERCFG_MONO : 0,
                                 POWERCFG_MONO);
+            si4700_write_cache();
             break;
 
         default:
@@ -445,6 +310,11 @@
     return 1;
 }
 
+static bool si4700_st(void)
+{
+    return false;
+}
+
 /* tuner abstraction layer: read something from the tuner */
 int si4700_get(int setting)
 {
@@ -470,12 +340,7 @@
 
 void si4700_dbg_info(struct si4700_dbg_info *nfo)
 {
-    memset(nfo->regs, 0, sizeof (nfo->regs));
-
-    if (tuner_powered())
-    {
-        si4700_read(16);
-        memcpy(nfo->regs, cache, sizeof (nfo->regs));
-    }
+    si4700_read(32);
+    memcpy(nfo->regs, cache, sizeof (nfo->regs));
 }