librtlsdr: FC0012 tuner regression

David Basden shigawire at
Sun Feb 4 11:39:02 UTC 2018


I recently found my dongle with the FC0012 again after having lost it for a
couple of years, and noticed the tuner wasn't detecting on recent builds
(by recent, it looks like at least a year and a half ago. :) )

There were a few other posts around that I saw with the same issue so I dug
into the problem a bit.  It looks it was a behavioural regression in
commit ba64a7459a43652354990855176a7d8dad5b9d54
which was a actually bugfix in the GPIO direction setting code (see below
for the commit comment).   The bugfix patch references which

The reason this regressed the FC0012 tuner support is that in tuner
detection code, before the probe for the FC00012 there are a few lines:

        /* initialise GPIOs */
        rtlsdr_set_gpio_output(dev, 5);

        /* reset tuner before probing */
        rtlsdr_set_gpio_bit(dev, 5, 1);
        rtlsdr_set_gpio_bit(dev, 5, 0);

Looking at one of the early (ugly) patches I wrote trying to get the FC0012
working, This is the original code before cleaned up:  :

+ if (tuner_type == TUNER_FC0012) {
+ dump_rtl_regs();
+ DEBUGF("reset fs0012 tuner... ");
+ /* the fs0012 has it's RESET line hooked up to GPIO5
+ *
+ * If we don't set GPIO5 to an output and leave it floating,
+ * the tuner never comes up (just stays in RESET state)
+ *
+ * GPIO6 controls the V/U band filter, so we should set that
+ * to an output too
+ */
+ r = rtl_read_reg(SYSB, GPD, 1);
+ r &= (~(0x30)); rtl_write_reg(SYSB, GPO, r, 1);
+ r = rtl_read_reg(SYSB, GPOE, 1);
+ r |= 0x30; rtl_write_reg(SYSB, GPOE, r, 1);
+ /* Do reset */
+ rtl_set_gpio_bit(5,1);
+ rtl_set_gpio_bit(5,0);
+ dump_rtl_regs();
+ }

This code was eventually abstracted out to The bug in the code above
described in,
linked to in the commit log of the ba64a7459a43652354990855176a7d8dad5b9d54
fixing the same bug.

The code was cleaned up eventually abstracted into rtl_sdr_set_output(),
which had the same typo as my original code: I wrote back the GPD register
to GPO.   This accidentally worked enough to fix the specific case I was
wanting (to stop the RESET line of the FC0012 floating), but didn't
actually write to the GPIO direction register.

This is as far as I've gotten so far. I don't really have a good setup
right now for debugging much further right this moment, but I at least know
where the problem is.  I don't have a copy of the RTL datasheet, or easy
access to anything to measure the levels on that line, but assuming that
the bugfix is the correct behaviour, and the buggy code is undefined
behaviour, it's quite possible that I've managed to get the GPIO5 into a
state just enough to get keep the FC0012 out of reset.

Looking at some of the forum posts, and checking myself,  if the older code
runs once, the tuner will be just fine until the dongle loses power.  Then
as GPIO5 is not set up into a state for the FC0012 to be happy, it will not
come up again.   This seems to have made the problem harder to debug (I
don't know if I would have not known where to look if I had not already hit
the problem when originally porting the driver)

Flipping the gpio bits the other direction is not working, so I'm going to
have to look at it further, but I figured I should at least post to say
where the bug was even if I haven't gotten a solution yet.
If I'm missing anything obvious there, please let me know



(commit for bugfix where fc0012 tuner regressed.)

commit ba64a7459a43652354990855176a7d8dad5b9d54
Author: Lucas Teske <lucas at>
Date:   Wed Aug 17 20:31:33 2016 -0300

    lib: fix direction bit in GPIO code


    * Removed unnecessary comment of old code.
    Signed-off-by: Fabian P. Schmidt <kerel-fs at>
    Signed-off-by: Steve Markgraf <steve at>

:040000 040000 12c5ea73db04c45699d7befa2c5916ae074a1999
2d08166fe31338f5ff90186272b40bc6ed3254fa M src
(HEAD) davidb at grey:~/Personal/sdr/rtl-sdr$
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the osmocom-sdr mailing list