raspberrypi / linux

Kernel source tree for Raspberry Pi-provided kernel builds. Issues unrelated to the linux kernel should be posted on the community forum at https://forums.raspberrypi.com/
Other
11.15k stars 4.99k forks source link

OV9281 External Trigger Support #5349

Open fxweidinger opened 1 year ago

fxweidinger commented 1 year ago

Hi!

In one of our Projects, we use the Arducam OV9281. We want to transition to libcamera, since they have deprecated their MIPI Driver.

Now for the actual problem: Our product relies on the external trigger functionality. After skimming through this repo and a bit of trial-and-error, I'm not really sure this is supported in libcamera with this module. I've seen that #5260 e6a7eed8db3c41fce11d8bf7005819f1f302a9ee added support for the OV7251 external trigger, so maybe the process would be similar?

6by9 commented 1 year ago

I thought I'd already added it, but don't see such a patch.

OV9281 was a downstream patch. Full support has now been merged into the mainline ov9282 driver, so currently from 6.2 we will be using that. I suspect I'll backport it to 6.1 as well. Changes aren't going to be made to the ov9281 driver on 5.15 now.

The process will be near identical to ov7251, but the registers involved may be different. I'll see what I can dig out.

Seeing as this repo is a request for a Linux kernel driver change, https://github.com/raspberrypi/linux is the appropriate repo. I'll see if I can find someone with appropriate permissions to move this issue.

fxweidinger commented 1 year ago

Ah, I'm sorry, I had both repos open and got confused when opening the issue... I was wondering why the Commit Hash wouldn't link automatically, that explains it. Sounds like good news though, thanks!

fxweidinger commented 1 year ago
@6by9 So I looked into this a little: The way I see it, the only changes to be made are: Register Desc.
0x3030 0x04 Bit[2]: External trigger snapshot mode
0x3666 0x00 Bit[3:0]: Internal frame sync input select 0x0:From FSIN pin, used for both frame sync and frame trigger function 0xA: Fixed value 0
  1. Add module param for external trigger
  2. Add statement in ov9282_set_steam(...) to enable/disable the trigger https://github.com/raspberrypi/linux/blob/ddaf4dc206056ee0da4435c45db3d6a7c606b4ce/drivers/media/i2c/ov9282.c#L1035

Anything else I have perhaps overlooked? I might have some time on my hands to do this when I get my hands on a ov9281 again.

6by9 commented 1 year ago

Can I ask which driver you have been using that supports external trigger?

I've made the register changes that I'd expected to need for external trigger based on the datasheet, but the sensor keeps free-running.

fxweidinger commented 1 year ago

@6by9 We used Arducams "MIPI Userland Driver" on Raspbian Buster before. Even then I have run into weird consistency issues with the external trigger on this module, though I was able to fix them... I got my hands on a OV9281 camera module today and will do some tests tomorrow.

6by9 commented 1 year ago

Presumably that is https://github.com/ArduCAM/MIPI_Camera/

In which case https://github.com/ArduCAM/MIPI_Camera/blob/master/RPI/ov9281_external_trigger.c#L16 looks interesting. The most confusing part being {0x0100, 0x00}, which actually sets the camera into standby mode, not streaming.

If you can confirm that the old stack really does still work, then that would be a useful stepping stone.

fxweidinger commented 1 year ago

I can confirm that it works with these register settings on Buster: {0x4F00, 0x01}, {0x3030, 0x04}, {0x303F, 0x01}, {0x302C, 0x00}, {0x302F, 0x7F}, {0x3823, 0x00}, {0x0100, 0x00}, I just had a look into it. As far as I understand from my limited access to the datasheet and some sniffing the sensor needs to be in "software standby" aka "sleep mode" in order for external trigger to work...

Jason-xy commented 1 year ago

Thank you very much for your answer. Following this register configuration, I successfully enabled the external trigger mode of ov9281 in Linux for Tegra and obtained stable images. The following is my configuration code:

static int ov9281_set_trigger_mode(struct ov9281 *priv, s32 val)
{
    struct device *dev = &priv->i2c_client->dev;
    ov9281_reg regs[8];
    u8 mode = (u8)val;
    int err = 0;

    dev_dbg(dev, "%s: trigger_mode: %d\n", __func__, val);

    if (mode == OV9281_MAX_TRIGGER_MODE)
    {
        regs[0].addr = OV9281_PWR_CTRL_ADDR; // 0x4F00
        regs[0].val = 0x01;
        regs[1].addr = OV9281_LOW_PWR_MODE_CTRL_ADDR; // 0x3030
        regs[1].val = 0x04;
        regs[2].addr = OV9281_ACT_FRM_NUM_ADDR; // 0x303F
        regs[2].val = 0x01;
        regs[3].addr = 0x302C;
        regs[3].val = 0x00;
        regs[4].addr = 0x302F;
        regs[4].val = 0x7F;
        regs[5].addr = 0x3823;
        regs[5].val = 0x00;
        regs[6].addr = OV9281_SC_MODE_SELECT_ADDR; //0x0100
        regs[6].val = 0x00;
        regs[7].addr = OV9281_TABLE_END;
        regs[7].val = 0;

        ov9281_set_group_hold(priv);
        err = ov9281_write_table(priv, regs);
        if (err)
            goto fail;
    }
    return 0;

fail:
    dev_dbg(dev, "%s: TRIGGER_MODE control error\n", __func__);
    return err;
}
enlighten-ch commented 9 months ago

hi, which device did you used for trigger signal? I used custom board which outputs active low signal, which seems not compatible with the ov9281 chip (active high) could you tell me your setup? thanks.