Archive for October, 2005
A while ago I looked around to see if the hauppauge windows driver for the remote control had any issues. I found quite a few people who claimed that it stopped responding, and that they had to reset the hauppauge software, etc and one or two pointers to a new (beta) driver on the hauppauge site. This was fairly intriguing as among the release notes it lists “i2c (IR blaster) fixes”. I managed to find time this weekend to take the driver apart, and see exactly what they did. Basically they rewrote the i2c support.
Some background, in case you aren’t familar: i2c is a low speed (varies, say ~100-400KHz) 2 wire serial bus for interconnecting various random chips. Because it’s so useful, it actually gets used all over the place to ‘glue’ various chips together on a board and then let the OS driver control them. For example, on your typical PVR-150 card you’ll find at least tuner, video encoder, IR chip and eeprom (configuration data). These are all i2c connected, and the driver talks i2c to them to program them (as well as other memory mapped registers, but let’s stick to the issue).
In some cases, the i2c protocol is implemented by special hardware on one of the chips (e.g. the bt878a chip has an i2c controller in it). This is the nice case, since the CPU doesn’t have to do much in the way of work. In the cheap case, you get to control the clock & data lines yourself from the OS (a kind of winmodem approach!). The hauppauge stuff takes the latter approach — indeed so does a bunch of other hardware. It’s so common that there is a module in the linux i2c subsystem specifically for doing this — it’s called i2c-algo-bit, and the approach is known as ‘bit-banging’. As a side issue, bit-banging takes up some constant fraction of CPU, because it has to use busy delays (it’s not possible to get microsecond accurate sleeps in the kernel, so we must run the CPU in a loop). Since these loops are constant _time_ you’ll find that whatever the CPU the IR polling (for example) takes a constant amount of time. For lirc_i2c, this works out at about 1%, and for my lirc_pvr150 module (that sends a ‘poll’ command to the receiver as well to see if it is borked or not), it’s about 2%. This is why I think the hardware approach is better, but whatever, we are stuck with it.
From the looks of the hauppauge driver changes it appears that the classical bit banging algorithm causes problems with the IR chip that the PVR-150 uses. I disassembled both the new and old drivers, and the older driver uses something very similar to the approach of i2c-algo-bit — it uses KeStallExecutionProcessor, or a busy loop, to implement delays. The newer driver dispenses with this, and instead polls the lines to see when they have become high/low and uses memory mapped register reads for stalling. I’m guessing that those reads are (roughly) constant time because they have to go across the PCI bus. I implemented the newer method, and low and behold this seems to solve my problems. I’ve not seen an IR chip reset by my lirc_pvr150 driver in 16 hours now (update: now 28), whereas I was getting them _much_ more frequently beforehand (dozens a day). This stops the remote dropping out if the chip has to reset, which it did do a few times a day for seconds at a time. So I’m happier. Anyway, if anyone else would like to try it, here’s the HOWTO part…
The HOWTO part
This patch is against the latest SVN version of ivtv. Things are changing rapidly with ivtv, and there is currently no really stable release (as you’ve probably realised). It might apply against the 0.3.8 release, if you try that and it fails let me know and I’ll post a patch against that version. It should go into the driver, eventually, if it really does sort out the IR chip issues.
Get the ivtv code from svn (you will need to apt-get install svn or whatever first!). See this page for detailed instructions.
Then reboot. Please _do not_ just rmmod ivtv & insmod ivtv — this won’t work. If you don’t want to reboot, rmmod _all_ of the ivtv modules first, especially cx25840. If you don’t do that, you’ll get an oops (then reboot, no biggie).
That’s it. You should stop seeing log messages related to resetting the IR chip, and the remote shouldn’t drop out at all. That’s the idea anyway. Any feedback would be appreciated!
I bought one of these a while ago, and discovered that the remote control didn’t work. After lots of looking at the board, and the help of an accomplished friend with a multimeter we were able to discover roughly what it does. In essence, it’s really dumb hardware There’s an IR demodulator on the end of a wire in a nice box that you put somewhere. That goes back eventually to a flip-flop. Curiously, the output from the demodulator is connected to the clock signal of the flip-flop. This causes the output to be passed through back to GPIO pin 5 of the bt878a chip, which then triggers an interrupt. I’m not clear on how it triggers an interrupt from the datasheet (it’s not GPINT, and in fact it doesn’t seem to set any status bits in INT_MASK). You then prod GPIO pin 4 which is connected to the reset line of the flip-flop. That in fact clears the interrupt, and off you go again. So basically the interrupts give you the edges of the IR pulse train.
With that information, you then have a driver time the interrupts. The supplied remote is RC5, and the edge transition bit pattern can be converted directly back to an RC5 code. Actually works quite nicely, and with a bit of tuning I have it feeling nice and smooth. Obviously the driver isn’t limited to just that remote, all you need to do is cook your own keymap. Since, weirdly, the remote seems to have the RC5 address set to TV, it interferes with my TV. So I cooked myself a keymap for another remote that I have (a Hauppauge grey remote, which is RC5 as well), and I use that instead. This nasty interrupt method seems to feel much smoother than polling the on-board IR thing on the PVR cards, although I will be working on fixing that.
I posted a linux driver to the video4linux list (one that uses the input layer, like ir-kbd-gpio or ir-kbd-i2c). You can probably find the patch in list archives (or if you are interested and can’t find it — ask and I’ll send it to you).
Anyway, it was a bit of fun and that’s my second remote control driver. I think I quite like playing with hardware.