Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 8374

Troubleshooting • Re: CM4: Device Tree overlay for PR2000K CSI-2 decoder not loading on kernel 6.12 (dtoverlay shows “No overlays loaded”)

$
0
0
Thank you for the detailed feedback — it really helped narrow things down significantly. I want to confirm what has now been corrected based on your instructions, and where I am currently blocked.

Corrections made based on your feedback
1. Unicam port definition (single port only)

You are correct — Unicam has a single port, not a ports {} container.
I corrected the overlay accordingly, removing the multi-port structure and aligning with your example.

2. I²C enable (i2c0mux / i2c0if)

I am intentionally relying on firmware enablement:

dtparam=i2c_vc=on


in config.txt, rather than duplicating i2c0mux / i2c0if nodes in the overlay.
This is now explicit and understood.

3. Source pad format support (V4L2 subdevice)

I implemented full source-pad format handling in the PR2000K driver so that Unicam can correctly filter CSI-2 data types:

enum_mbus_code

get_fmt

set_fmt

The driver fixes the output to YUYV 8-bit (MEDIA_BUS_FMT_YUYV8_2X8), matching what Unicam expects.

4. Lane count vs datasheet

Per the PR2000K datasheet:

1080p requires 4 CSI lanes

720p supports 2 CSI lanes

To stay datasheet-correct, I switched to 720p + 2-lane mode, and explicitly programmed the PR2000K:

Register 0x47 = 0x10 // 2-lane mode


The DTS also uses:

data-lanes = <1 2>;

5. Debug evidence requested

I collected exactly what you asked for:

v4l2-ctl --log-status

memtool md 0xfe801000+0x50

Results show:

Detected resolution: 0x0
Programmed stride: 0
Write pointer: 00000000


This indicates Unicam is running but no CSI symbols (FS/LS) are detected.

Current status (where I am blocked)
What is working

Device Tree overlay is applied by firmware

PR2000K node exists in live DT

Driver probes successfully

Async notifier completes

Media graph is instantiated:

pr2000k 0-005c
pad0: SOURCE -> unicam-image:0 [ENABLED]


/dev/video0 exists

s_stream(1) is called on the PR2000K subdevice

What is not working

Unicam never detects Frame Start / Line Start

Detected resolution remains 0x0

STREAMON fails with -EINVAL

No buffers are dequeued to userspace

Given the above, this now appears to be at the CSI PHY / electrical boundary (clock lane, data lane polarity/order, or wiring), not DT topology or V4L2 subdevice integration.

Full code for reference (as requested)
✅ Device Tree Overlay (pr2000k-unicam.dts)

Code:

/dts-v1/;/plugin/;/ {    compatible = "brcm,bcm2711";    fragment@0 {        target = <&i2c_vc>;        __overlay__ {            status = "okay";            #address-cells = <1>;            #size-cells = <0>;            pr2000k: pr2000k@5c {                compatible = "pixelplus,pr2000k";                reg = <0x5c>;                status = "okay";                port {                    pr2000k_out: endpoint {                        remote-endpoint = <&unicam_ep>;                        bus-type = <4>;          /* CSI-2 */                        clock-lanes = <0>;                        data-lanes  = <1 2>;    /* 2-lane mode */                    };                };            };        };    };    fragment@1 {        target = <&csi1>;        __overlay__ {            status = "okay";            brcm,media-controller;            port {                unicam_ep: endpoint {                    remote-endpoint = <&pr2000k_out>;                    bus-type = <4>;      /* CSI-2 */                    clock-lanes = <0>;                    data-lanes  = <1 2>;                };            };        };    };};
✅ PR2000K V4L2 Subdevice Driver (pr2000k.c)

Code:

// SPDX-License-Identifier: GPL-2.0#include <linux/module.h>#include <linux/i2c.h>#include <linux/delay.h>#include <media/v4l2-subdev.h>#include <media/v4l2-device.h>struct pr2000k {    struct v4l2_subdev sd;    struct v4l2_mbus_framefmt fmt;};static inline struct pr2000k *to_pr2000k(struct v4l2_subdev *sd){    return container_of(sd, struct pr2000k, sd);}static int pr2000k_enum_mbus_code(struct v4l2_subdev *sd,                                  struct v4l2_subdev_state *state,                                  struct v4l2_subdev_mbus_code_enum *code){    if (code->index)        return -EINVAL;    code->code = MEDIA_BUS_FMT_YUYV8_2X8;    return 0;}static int pr2000k_get_fmt(struct v4l2_subdev *sd,                            struct v4l2_subdev_state *state,                            struct v4l2_subdev_format *fmt){    struct pr2000k *priv = to_pr2000k(sd);    fmt->format = priv->fmt;    return 0;}static int pr2000k_set_fmt(struct v4l2_subdev *sd,                            struct v4l2_subdev_state *state,                            struct v4l2_subdev_format *fmt){    struct pr2000k *priv = to_pr2000k(sd);    priv->fmt.width  = 1280;    priv->fmt.height = 720;    priv->fmt.code   = MEDIA_BUS_FMT_YUYV8_2X8;    priv->fmt.field  = V4L2_FIELD_NONE;    priv->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;    fmt->format = priv->fmt;    return 0;}static int pr2000k_s_stream(struct v4l2_subdev *sd, int enable){    struct i2c_client *client = v4l2_get_subdevdata(sd);    if (enable) {        i2c_smbus_write_byte_data(client, 0xff, 0x00);        i2c_smbus_write_byte_data(client, 0x47, 0x10); /* 2-lane mode */        i2c_smbus_write_byte_data(client, 0x2f, 0x01); /* test pattern */        i2c_smbus_write_byte_data(client, 0x01, 0x01); /* CSI enable */    }    return 0;}static const struct v4l2_subdev_video_ops pr2000k_video_ops = {    .s_stream = pr2000k_s_stream,};static const struct v4l2_subdev_pad_ops pr2000k_pad_ops = {    .enum_mbus_code = pr2000k_enum_mbus_code,    .get_fmt = pr2000k_get_fmt,    .set_fmt = pr2000k_set_fmt,};static const struct v4l2_subdev_ops pr2000k_ops = {    .video = &pr2000k_video_ops,    .pad   = &pr2000k_pad_ops,};static int pr2000k_probe(struct i2c_client *client){    struct pr2000k *priv;    priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);    if (!priv)        return -ENOMEM;    v4l2_i2c_subdev_init(&priv->sd, client, &pr2000k_ops);    priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;    priv->fmt.width  = 1280;    priv->fmt.height = 720;    priv->fmt.code   = MEDIA_BUS_FMT_YUYV8_2X8;    i2c_set_clientdata(client, &priv->sd);    return v4l2_async_register_subdev_sensor(&priv->sd);}static void pr2000k_remove(struct i2c_client *client){    struct v4l2_subdev *sd = i2c_get_clientdata(client);    v4l2_async_unregister_subdev(sd);}static const struct of_device_id pr2000k_of_match[] = {    { .compatible = "pixelplus,pr2000k" },    { }};MODULE_DEVICE_TABLE(of, pr2000k_of_match);static struct i2c_driver pr2000k_driver = {    .driver = {        .name = "pr2000k",        .of_match_table = pr2000k_of_match,    },    .probe = pr2000k_probe,    .remove = pr2000k_remove,};module_i2c_driver(pr2000k_driver);MODULE_LICENSE("GPL");
Final note

At this stage, all DT and V4L2 integration points appear correct.
If there is anything specific in Unicam’s CSI PHY expectations (clock polarity, lane swap, etc.) that you recommend checking next, I would appreciate guidance.

Thank you again for the detailed review.

Statistics: Posted by mukam — Tue Jan 06, 2026 1:06 pm



Viewing all articles
Browse latest Browse all 8374

Trending Articles