[PATCH] Revert "lib: fix direction bit in GPIO code"

David Kozub zub at linux.fjfi.cvut.cz
Tue Nov 7 18:38:21 UTC 2017

On Fri, 27 Oct 2017, Oliver Jowett wrote:

> The original commit fixes configuring the direction of the GPIO pins on the
> 2832 so it actually works. The FC0012 failure is probably a side-effect of
> the direction bits now really being set.


I ran into the same issue with my RTL dongle with FC0012 tuner (0bda:2838 
Realtek Semiconductor Corp. RTL2838 DVB-T).

After some poking around I think the reason for the tuner not being found 
is that the tuner reset (or, perhaps, just power) pin is connect to GPIO 
4, not to GPIO 5 as the code assumes. Making the following change makes 
rtl_test find the tuner for me:

diff --git a/src/librtlsdr.c b/src/librtlsdr.c
index b369a5d..4fb2128 100644
--- a/src/librtlsdr.c
+++ b/src/librtlsdr.c
@@ -1565,11 +1565,11 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t 

         /* initialise GPIOs */
-       rtlsdr_set_gpio_output(dev, 5);
+       rtlsdr_set_gpio_output(dev, 4);

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

         reg = rtlsdr_i2c_read_reg(dev, FC2580_I2C_ADDR, 
         if ((reg & 0x7f) == FC2580_CHECK_VAL) {

> The tuner initialization does this:
> rtlsdr_set_gpio_output(dev, 5); /* should set GPIO 5 to output mode, but
> actually does not touch the direction bits and instead turns on GPIO output
> 5 */

It did more than that: it also sets all other GPIO outputs to 0. If tuner 
reset is connect to GPIO 4 with 1 meaning reset and 0 normal operation, 
this brings the tuner from reset.

I added some traces and I see the values after plugging in the tuner, just 
after the call rtlsdr_set_i2c_repeater(dev, 1) in rtlsdr_open, are:

GPD = 0x06
GPOE = 0x19
GPO = 0x18

so in my understanding initially:
* GPIOs 1 and 2 are set to INPUT
* GPIOs 0, 3 and 4 are set to OUTPUT
* output GPIOs 3 and 4 are set to 1, GPIO 0 is set to 0

With the code before the GPIO fix (ba64a745) the call 
rtlsdr_set_gpio_output(dev, 5) read GPD and set its value to GPO while 
dropping the 5-th bit from the GPD value. So it assigs the value 6 to GPO. 
This sets all output GPIOs to 0: GPIOs 3 and 4 are dropped to 0. Then it 
sets GPOE to the previous value of GPOE plus the 5th bit, so it sets GPIO 
5 to output and its output value is 0 because of the previous write.

> rtlsdr_set_gpio_bit(dev, 5, 1);   /* turns on GPIO 5 output */
> rtlsdr_set_gpio_bit(dev, 5, 0);   /* turns off GPIO 5 output */

In my understanding this then did the expected: it toggled GPIO 5.

> I don't know the reset state of the 2832 offhand but assuming GPIO 5 is not
> set as an output on reset, then that tuner reset was doing nothing much
> before the GPIO fix.

I think the rtlsdr_write_reg(dev, SYSB, GPOE, r | gpio, 1) did set GPIO 5 
to output. But it's quite possible I got lost in trying to follow this.

> Maybe the FC0012 takes a while to settle after a reset, so when it really
> gets reset the detection immediately afterwards fails. You could try
> commenting out those three lines and see if anything changes.

I tried both commenting out the GPIO direction + toggle and I also tried 
adding a sleep after the set of GPIO 5 to 0 and still the tuner is not 

I don't know where does the value 5 come from. Is it possible some other 
dongles have the tuner at GPIO 5? Or is it really supposed to be GPIO 4 
and it worked with 5 by accident - by pulling GPIO 4 to 0 accidentally?

A friend of mine looked at the PCB of the dongle I'm using and he found 
out that GPIO 4 seems to be connected - via a transistor - to the TC0012. 
GPIO 5 didn't seem to be connected - at least not in an obvious way - to 
the tuner. I have to say this was just a quick look, so we could have 
missed things.

Also, as there's a transistor in between... could it be that GPIO 4 is not 
really tuner reset, but tuner power? But this would be rather 
philosophical point. Either way, from my tests, GPIO 4 has to be set to 0 
for the tuner to be reachable.

Should I send a patch that changes the tuner GPIO from 5 to 4? Or do you 
see a better way of solving this?

Best regards,

More information about the osmocom-sdr mailing list