Saturday, August 22, 2009

OmniVision OV9640 hacking - part IV

I recently had some talk with Guennadi Liakhovetski (aka. the soc-camera maintainer and v4l2 guru) about this driver. He pointed out that there will certainly be a large amount of changes going into 2.6.32 affecting the soc-camera API and advised me to prepare the driver for those. Besides that, we found out there are certain differences between OV9640 and OV9650, so support for the later one was dropped (it was never tested anyway). For that model there's another driver scheduled for merge written by Stefan Herbrechtsmeier. Subsequent changes are mostly because of the API change. There are also some minor cleanups and changes in logic of the driver.

The patch got split into three separate patches, but prior to applying those, you need to apply a patchset available here (LINK) on top of linux-next (in case you run into merge issues, git reset --hard to commit hash in 0000-base) . The OV9640 patches are then available here:
  • Patch adding support for RGB555X and RGB565X formats into pxa-camera (LINK)
  • OV9640 support adding patch (LINK)
  • Patch adding support for the camera into PalmZ72 platform file (LINK)

Friday, August 21, 2009

Marvell Libertas CF8305 partly supported

So after my own private hackathon I held for last two weeks and where OpenBSD gained support for Palm hardware to some extent, I felt the urge to fix some hardware to work with Linux. And there was a perfect candidate for that, the WiFi card in Palm LifeDrive. That damn little piece of silicon bothered me for more than two years already, but just a few hours ago, I cracked the nut there at least.

The Marvell Libertas CF8305 is actually a very ancient piece of silicon and runs Marvell proprietary firmware version 3.0 . Being this old, the card has various issues which later models (like CF8381 and CF8385) do not have. The first difference from the later models is that this card runs only an one-stage firmware, but that's luckily loaded the same way as a helper firmware on the later models. The second-stage firmware isn't loaded at all on this card.

Next issue on the list happens when accessing registers of the card. It seems the card can not do an unaligned accesses to it's registers which means the driver has to access only odd addresses. Accesses to even addresses doesn't work - in case of reading the returned value is the one of the nearest lower odd address. But luckily, there is only one such unaligned access happening in the whole if_cs.c part of the driver and that is when reading the SCRATCH_PAD register which has address 0x3F . And this can be easily worked around by doing a 16bit read of address 0x3E and bit-shifting the result by 8 to the right.

This was the easy part, but the horrible bugs are still waiting. Apparently, with the first problem fixed, the firmware can be loaded and the card seem to respond to some commands, so far so good. What the card really does not like though is a command with code 0x0006 aka. CMD_802_11_SCAN. Once that command is sent to the card, the card plain hangs and all you can do is remove the driver, eject the card and reinsert it (there's no hardware eject so use 'pccardctl eject' and 'pccardctl insert'). The real problem here is, once the card is brought up (for instance by 'ifconfig eth0 up', the driver itself issues the SCAN command - or at least that's what it does when configured into Ad-Hoc mode. This can be worked around by editing 'drivers/net/wireless/libertas/scan.c' and commenting out 'ret = __lbs_cmd(priv, CMD_802_11_SCAN...);' at around line 333.

With the hack above, it's possible at least for the card to serve as a node in an Ad-Hoc network. But that's not the last limitation it has. It's impossible for now to reconfigure the card once brought up. Since in case you do that, the command 0x002b aka. CMD_802_11_AD_HOC_START will fail and again hanging the whole card.

Other than that, if the card is configured by 'iwconfig' and then brought up by 'ifconfig', it seems to be possible to establish at least the Ad-Hoc network. Well there are still some very hard limitations, but at least there are some signs of life from the card and it can't get any worse now.

Here's the patch for the if_cs.c file: LINK
And here's a picture of a working WiFi on Palm LifeDrive:

Friday, August 7, 2009

OmniVision OV9640 hacking - part ]|[

I spent the last few days tracking down some really weird issues with the OV9640 driver. The major problem was a bright stripe, exactly 90px from the top of the photo. But it only occurred on photos in 640x480 and lower resolution. Also, there were other problems like brightness too dim in certain resolutions, swapped colors, i2c glitches etc. Interestingly enough, I haven't met such issues at the 1280x960 resolution.

The bright stripe was in the end caused by the camera not being ready right after reconfiguration. A little delay pretty much solved it, but it might need some further investigation still. Tinkering some more with the chips' registers, I also managed to eliminate most of the color-swap related problem as well as improve overall image quality.

But then there was that i2c problem. It was pretty hard to even notice it since writing the chip registers worked. The problem popped up when I tried reading the registers back though. It returned total nonsense. Further investigation came up with the chip not being able to communicate in SMBUS-mode so I switched to i2c-mode and it worked like a charm.

Anyway, with the problems listed above solved, the driver reached something that can be called a beta-state. It can now do capture in both RGB565X and VYUY (though it could be better in the RGB565X, the VYUY is fine). Sadly, the RGB555X is still not there, but I wonder if anyone will actually be missing it since there are those two higher-quality formats.

The patch is available here. Actually, I upload a new version of the patch from time to time and the old version of the patch gets overwritten so there might pop up a new version of the driver between blog entries announcing it. Though the changes are often very minor.

Monday, August 3, 2009

OmniVision OV9640 hacking - part ][

So once the i2c problem was partly solved, I started putting together a driver for the camera chip. It's in an alpha-state currently, which means some things are still missing/doesn't work/are untested etc., but it can already make photos! Some examples follow.

This is a RGB565 photo of a monoscope.

This is a VYUY photo of a monoscope.

Here comes a list of the problems so far:
  • The image quality is still a little bad in case of VYUY, more bad in case of RGB565 and it doesn't work for RGB555 yet. This needs some further work.
  • Some of the advanced features of the OV96xx are missing altogether.
If you still haven't lost your interest, here are the patches:

Saturday, August 1, 2009

OmniVision OV9640 hacking

I've been hacking on this camera module in last three days or so. Whew, it gave me quite a pain especially because of the SCCB interface (which is renamed i2c), but I finally defeated it. This chip can be found for example in Palm Zire72. I made some hardware research to figure out what GPIOs drive it. the results are:
  • GPIO56 - PWDN
  • GPIO57 - RESET
  • GPIO91 - DVDD
Ok, with this knowledge, it's simple to setup PXA QCI and read some data from the chip. With a little effort I was able to make a photo using the fswebcam tool. Though the colours were totally off and messed up because the camera chip wasn't configured at all. And here came the main problem.

The problem was, when I tried to communicate with the chip using i2c-pxa driver (the native PXA I2C driver), it didn't work. The i2c driver complained about timeouts etc. Just a while ago, I got quite crazy idea to give the i2c-gpio driver (this one toggles GPIOs to emulate i2c behaviour) a go. To my surprise, it worked. I was able to read registers of the chip and all. So this is it, the whole solution was to use the i2c-gpio driver instead of i2c-pxa.

But here comes another question - why ... why does it work with i2c-gpio and doesn't with i2c-pxa ? I think the problem might be with I2C and QCI clocks supplied to the module (speed, sychro, ... who knows). But interestingly enough, PalmOS seems to use the PXA I2C. So this makes the whole situation even more confusing. So in the end, this will need some further investigation, but at least the camera is working somehow and I can start writing a proper driver for it.