From: Alexander Stein <alexander.stein@ew.tq-group.com>
To: "linux-media@vger.kernel.org" <linux-media@vger.kernel.org>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
dl-linux-imx <linux-imx@nxp.com>,
"G.N. Zhou (OSS)" <guoniu.zhou@oss.nxp.com>,
"G.N. Zhou (OSS)" <guoniu.zhou@oss.nxp.com>
Cc: "mchehab@kernel.org" <mchehab@kernel.org>,
"laurent.pinchart@ideasonboard.com"
<laurent.pinchart@ideasonboard.com>,
"robh+dt@kernel.org" <robh+dt@kernel.org>,
"krzysztof.kozlowski+dt@linaro.org"
<krzysztof.kozlowski+dt@linaro.org>,
"conor+dt@kernel.org" <conor+dt@kernel.org>,
"jacopo.mondi@ideasonboard.com" <jacopo.mondi@ideasonboard.com>
Subject: Re: [PATCH 2/2] media: nxp: add driver for i.MX93 MIPI CSI-2 controller and D-PHY
Date: Wed, 05 Jul 2023 08:50:25 +0200 [thread overview]
Message-ID: <9364454.T7Z3S40VBb@steina-w> (raw)
In-Reply-To: <AS8PR04MB908081139CF737C06AAD1284FA2FA@AS8PR04MB9080.eurprd04.prod.outlook.com>
Hi Guoniu,
thanks for the fast response.
Am Mittwoch, 5. Juli 2023, 05:52:05 CEST schrieb G.N. Zhou (OSS):
> Hi Alexander,
>
> Thanks for your comments.
>
> [snip]
> > > +
> > > +/* Set default high speed frequency range to 1.5Gbps */
> > > +#define DPHY_DEFAULT_FREQRANGE 0x2c
> > > +
> > > +enum imx93_csi_clks {
> > > + PER,
> > > + PIXEL,
> > > + PHY_CFG,
> > > +};
> > > +
> > > +enum model {
> > > + DWC_CSI2RX_IMX93,
> > > +};
> > > +
> > > +enum dwc_csi2rx_intf {
> > > + DWC_CSI2RX_INTF_IDI,
> >
> >
> > This is unused, what is it intented for?
>
>
> DesignWare Core MIPI CSI-2 support both IDI and IPI interface. For i.MX93 it
> use IPI as interface with ISI(gasket) and I reserved IDI here on the one
> hand support full features of the MIPI CSI-2 IP as more as possible, on the
> other hand, NXP i.MX95 MIPI CSI-2 remove IPI and use IDI as the interface.
I don't know about the differences on IPI and IDI, but it looks like both
i.MX93 and i.MX95 use the same MIPI-CSI2 IP core, but have a different glue
layer. So IPI and IDI specifics seem to be SoC specific as well. Did I get
something wrong?
> [snip]
> > > ------------------------------------------------------------------------
> > > ---
-- + * Debug
> > > + */
> > > +
> > > +static void dwc_csi_clear_counters(struct dwc_csi_device *csidev)
> > > +{
> > > + unsigned long flags;
> > > + unsigned int i;
> > > +
> > > + spin_lock_irqsave(&csidev->slock, flags);
> > > +
> > > + for (i = 0; i < csidev->pdata->num_events; ++i)
> > > + csidev->events[i].counter = 0;
> > > +
> > > + spin_unlock_irqrestore(&csidev->slock, flags);
> > > +}
> > > +
> > > +static void dwc_csi_log_counters(struct dwc_csi_device *csidev)
> > > +{
> > > + unsigned int num_events = csidev->pdata->num_events;
> > > + unsigned long flags;
> > > + unsigned int i;
> > > +
> > > + spin_lock_irqsave(&csidev->slock, flags);
> > > +
> > > + for (i = 0; i < num_events; ++i) {
> > > + if (csidev->events[i].counter > 0)
> > > + dev_info(csidev->dev, "%s events: %d\n",
> > > + csidev->events[i].name,
> > > + csidev->events[i].counter);
> > > + }
> > > +
> > > + spin_unlock_irqrestore(&csidev->slock, flags);
> > > +}
> > > +
> > > +static void dwc_csi_dump_regs(struct dwc_csi_device *csidev)
> > > +{
> > > +#define DWC_MIPI_CSIS_DEBUG_REG(name) {name,
> >
> > #name}
> >
> > > + static const struct {
> > > + u32 offset;
> > > + const char * const name;
> > > + } registers[] = {
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_VERSION),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_N_LANES),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_HOST_RESETN),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_INT_ST_MAIN),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_DPHY_SHUTDOWNZ),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_DPHY_RSTZ),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_DPHY_RX_STATUS),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_DPHY_STOPSTATE),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_DPHY_TEST_CTRL0),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_DPHY_TEST_CTRL1),
> > > +
> >
> > DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_PPI_PG_PATTERN_VRES),
> >
> > > +
> >
> > DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_PPI_PG_PATTERN_HRES),
> >
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_PPI_PG_CONFIG),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_PPI_PG_ENABLE),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_PPI_PG_STATUS),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_IPI_MODE),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_IPI_VCID),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_IPI_DATA_TYPE),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_IPI_MEM_FLUSH),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_IPI_SOFTRSTN),
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_IPI_ADV_FEATURES),
> > > +
> >
> > DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_INT_ST_DPHY_FATAL),
> >
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_INT_ST_PKT_FATAL),
> > > +
> >
> > DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_INT_ST_DPHY_FATAL),
> >
> > > + DWC_MIPI_CSIS_DEBUG_REG(CSI2RX_INT_ST_IPI_FATAL),
> > > + };
> > > +
> > > + unsigned int i;
> > > + u32 cfg;
> > > +
> > > + dev_dbg(csidev->dev, "--- REGISTERS ---\n");
> > > +
> > > + for (i = 0; i < ARRAY_SIZE(registers); i++) {
> > > + cfg = dwc_csi_read(csidev, registers[i].offset);
> > > + dev_dbg(csidev->dev, "%14s[0x%02x]: 0x%08x\n",
> > > + registers[i].name, registers[i].offset, cfg);
> > > + }
> > > +}
These register dumps also look like a good candidate for
v4l2_subdev_core_ops.log_status callback. VIDIOC_LOG_STATUS ioctl that is.
> [snip]
> > > +static int dwc_csi_subdev_set_fmt(struct v4l2_subdev *sd,
> > > + struct v4l2_subdev_state *sd_state,
> > > + struct v4l2_subdev_format
> >
> > *sdformat)
> >
> > > +{
> > > + struct dwc_csi_device *csidev = sd_to_dwc_csi_device(sd);
> > > + struct dwc_csi_pix_format const *csi_fmt;
> > > + struct v4l2_mbus_framefmt *fmt;
> > > + unsigned int align;
> > > +
> > > + /*
> > > + * The CSIS can't transcode in any way, the source format can't
> > > be
> > > + * modified.
> > > + */
> > > + if (sdformat->pad == DWC_CSI2RX_PAD_SOURCE)
> > > + return dwc_csi_subdev_get_fmt(sd, sd_state, sdformat);
> > > +
> > > + if (sdformat->pad != DWC_CSI2RX_PAD_SINK)
> > > + return -EINVAL;
> > > +
> > > + /*
> > > + * Validate the media bus code and clamp and align the size.
> > > + *
> > > + * The total number of bits per line must be a multiple of 8. We
> >
> > thus
> >
> > > + * need to align the width for formats that are not multiples of
> > > 8
> > > + * bits.
> > > + */
> > > + csi_fmt = find_csi_format(sdformat->format.code);
> > > + if (!csi_fmt)
> > > + csi_fmt = &dwc_csi_formats[0];
> > > +
> > > + switch (csi_fmt->width % 8) {
> > > + case 0:
> > > + align = 0;
> > > + break;
> > > + case 4:
> > > + align = 1;
> > > + break;
> > > + case 2:
> > > + case 6:
> > > + align = 2;
> > > + break;
> > > + default:
> > > + /* 1, 3, 5, 7 */
> > > + align = 3;
> > > + break;
> > > + }
> >
> >
> > Is this switch-case actually necessary? If the bits per line have to be a
> > multiple of 8, IMHO calling v4l_bound_align_image() with walign=3 should
> > be enough for all cases.
>
>
> Yes it's. walign=3 can cover all cases as you said but can't handle precise
> control and cause unnecessary memory waste.
Right, it's about _bits_ per line, not pixel per line. So your calculation
seems sensible.
> [snip]
> > > +static int dwc_csi_async_register(struct dwc_csi_device *csidev)
> > > +{
> > > + struct v4l2_fwnode_endpoint vep = {
> > > + .bus_type = V4L2_MBUS_CSI2_DPHY,
> > > + };
> > > + struct v4l2_async_subdev *asd;
> > > + struct fwnode_handle *ep;
> > > + unsigned int i;
> > > + int ret;
> > > +
> > > + v4l2_async_nf_init(&csidev->notifier);
> > > +
> > > + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csidev->dev), 0,
> >
> > 0,
> >
> > > +
> >
> > FWNODE_GRAPH_ENDPOINT_NEXT);
> >
> > > + if (!ep)
> > > + return -ENOTCONN;
> > > +
> > > + ret = v4l2_fwnode_endpoint_parse(ep, &vep);
> > > + if (ret)
> > > + goto err_parse;
> > > +
> > > + for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) {
> > > + if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) {
> > > + dev_err(csidev->dev,
> > > + "data lanes reordering is not
> >
> > supported");
> >
> > > + ret = -EINVAL;
> > > + goto err_parse;
> > > + }
> > > + }
> > > +
> > > + csidev->bus = vep.bus.mipi_csi2;
> > > +
> > > + if (fwnode_property_read_u32(ep, "fsl,hsfreqrange",
> > > + &csidev->hsfreqrange))
> > > + csidev->hsfreqrange = DPHY_DEFAULT_FREQRANGE;
> > > +
> > > + dev_dbg(csidev->dev, "data lanes: %d\n", csidev-
> > >
> > >bus.num_data_lanes);
> > >
> > > + dev_dbg(csidev->dev, "flags: 0x%08x\n", csidev->bus.flags);
> > > + dev_dbg(csidev->dev, "high speed frequency range: 0x%X\n",
> > > csidev->hsfreqrange); +
> > > + asd = v4l2_async_nf_add_fwnode_remote(&csidev->notifier, ep,
> > > + struct
> >
> > v4l2_async_subdev);
> >
> > > + if (IS_ERR(asd)) {
> > > + ret = PTR_ERR(asd);
> > > + goto err_parse;
> > > + }
> > > +
> > > + fwnode_handle_put(ep);
> > > +
> > > + csidev->notifier.ops = &dwc_csi_notify_ops;
> > > +
> > > + ret = v4l2_async_subdev_nf_register(&csidev->sd,
> > > &csidev->notifier);
> > > + if (ret)
> > > + return ret;
> >
> >
> > I'm not sure which part causes the following message:
> >
> > > dwc-mipi-csi2 4ae00000.mipi-csi: Consider updating driver dwc-mipi-csi2
> > > to
> >
> > match on endpoints
> >
> > But as this is a new driver, this should be addressed.
>
>
> Sure. Could you help to share the steps about how to reproduce it?
Sure, I assume this depends how your OF graph looks like. This is the one I
used, stripped some of the (irrelevant) camera properties.
&lpi2c5 {
camera@1a {
compatible = "sony,imx327lqr";
reg = <0x1a>;
port {
sony_imx327: endpoint {
remote-endpoint = <&mipi_to_isi>;
data-lanes = <1 2>;
clock-lanes = <0>;
clock-noncontinuous = <1>;
link-frequencies = /bits/ 64 <445500000 297000000>;
};
};
};
};
/ {
soc@0 {
mipi_csi: mipi-csi@4ae00000 {
compatible = "fsl,imx93-mipi-csi2";
reg = <0x4ae00000 0x10000>;
interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX93_CLK_MIPI_CSI_GATE>,
<&clk IMX93_CLK_CAM_PIX>,
<&clk IMX93_CLK_MIPI_PHY_CFG>;
clock-names = "per", "pixel", "phy_cfg";
power-domains = <&media_blk_ctrl IMX93_MEDIABLK_PD_MIPI_CSI>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
mipi_from_sensor: endpoint {
data-lanes = <1 2>;
fsl,hsfreqrange = <0x2c>;
};
};
port@1 {
reg = <1>;
mipi_to_isi: endpoint {
remote-endpoint = <&isi_in>;
};
};
};
};
};
};
As you can see the link speed is either 445.5MHz or 297Mhz. Does this mean I
have to set fsl,hsfreqrange to 0x16 or 0x14?
> [snip]
> > > +void dphy_rx_test_code_config(struct dwc_csi_device *csidev)
> > > +{
> > > + u32 val;
> > > + u8 dphy_val;
> > > +
> > > + /* Set testclr=1'b0 */
> > > + val = dwc_csi_read(csidev, CSI2RX_DPHY_TEST_CTRL0);
> > > + val &= ~CSI2RX_DPHY_TEST_CTRL0_TEST_CLR;
> > > + dwc_csi_write(csidev, CSI2RX_DPHY_TEST_CTRL0, val);
> > > +
> > > + /* Enable hsfreqrange_ovr_en and set hsfreqrange */
> > > + dphy_rx_write(csidev, DPHY_RX_SYS_0,
> >
> > HSFREQRANGE_OVR_EN_RW);
> >
> > > + dphy_rx_write(csidev, DPHY_RX_SYS_1,
> > > + HSFREQRANGE_OVR_RW(csidev->hsfreqrange));
> > > +
> > > + /* Enable timebase_ovr_en */
> > > + dphy_val = dphy_rx_read(csidev, DPHY_RX_SYS_1);
> > > + dphy_val |= TIMEBASE_OVR_EN_RW;
> > > + dphy_rx_write(csidev, DPHY_RX_SYS_1, dphy_val);
> > > +
> > > + /* Set cfgclkfreqrange */
> > > + dphy_rx_write(csidev, DPHY_RX_SYS_2,
> > > + TIMEBASE_OVR_RW(csidev->cfgclkfreqrange + 0x44));
> >
> >
> > RM Rev 2. mentions that depending on cfgclkfreqrange another
> > configuration,
called counter_for_des_en_config_if, also needs to be
> > set. Is this missing here?
>
>
> It isn't needed from my experiment result.
Okay, I'm just doing guesswork trying to figure out why I get those D-PHY
errors.
> >
> >
> > > +}
> > > +
> > > +void dphy_rx_power_off(struct dwc_csi_device *csidev)
> > > +{
> > > + dwc_csi_write(csidev, CSI2RX_DPHY_RSTZ, 0x0);
> > > + dwc_csi_write(csidev, CSI2RX_DPHY_SHUTDOWNZ, 0x0);
> > > +}
> > > +
> > > +void dphy_rx_test_code_dump(struct dwc_csi_device *csidev)
> > > +{
> > > +#define DPHY_DEBUG_REG(name) {name, #name}
> > > + static const struct {
> > > + u32 offset;
> > > + const char * const name;
> > > + } test_codes[] = {
> > > + DPHY_DEBUG_REG(DPHY_RX_SYS_0),
> > > + DPHY_DEBUG_REG(DPHY_RX_SYS_1),
> > > + DPHY_DEBUG_REG(DPHY_RX_SYS_2),
> > > + };
> > > + unsigned int i;
> > > +
> > > + for (i = 0; i < ARRAY_SIZE(test_codes); i++)
> > > + dev_dbg(csidev->dev, "%14s[0x%02x]: 0x%02x\n",
> > > + test_codes[i].name, test_codes[i].offset,
> > > + dphy_rx_read(csidev, test_codes[i].offset));
> > > +}
> >
> >
> > Could you also provide a complete DT configuration? I tried myself, but I
> > just ended up in getting errors while trying to use a MIPI-CSI camera
> > dwc-mipi-csi2 4ae00000.mipi-csi: IPI Interface Fatal Error events:
> > 2800064
> > dwc-mipi-csi2 4ae00000.mipi-csi: PHY Error events: 2174
> > dwc-mipi-csi2 4ae00000.mipi-csi: IPI Interface Fatal Error events:
> > 2800064
> > dwc-mipi-csi2 4ae00000.mipi-csi: PHY Error events: 2174
>
>
> Sure, I can provide full patches that use i.MX93 platform with AP1302 if you
> are interested.
> Will send you in another mails.
Thanks.
Best regards,
Alexander
--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/
prev parent reply other threads:[~2023-07-05 6:52 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-03 11:37 [PATCH 0/2] media: nxp: add i.MX93 MIPI CSI-2 support guoniu.zhou
2023-07-03 11:37 ` [PATCH 1/2] media: dt-bindings: Add binding doc for i.MX93 MIPI CSI-2 guoniu.zhou
2023-07-04 8:38 ` Alexander Stein
2023-07-05 1:36 ` G.N. Zhou (OSS)
2023-07-05 21:23 ` Laurent Pinchart
2023-07-06 10:08 ` G.N. Zhou (OSS)
2023-07-04 16:53 ` Conor Dooley
2023-07-05 1:30 ` G.N. Zhou (OSS)
2023-07-05 21:08 ` Conor Dooley
2023-07-03 11:37 ` [PATCH 2/2] media: nxp: add driver for i.MX93 MIPI CSI-2 controller and D-PHY guoniu.zhou
2023-07-04 9:23 ` Alexander Stein
2023-07-05 3:52 ` G.N. Zhou (OSS)
2023-07-05 6:50 ` Alexander Stein [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9364454.T7Z3S40VBb@steina-w \
--to=alexander.stein@ew.tq-group.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=guoniu.zhou@oss.nxp.com \
--cc=jacopo.mondi@ideasonboard.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-imx@nxp.com \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.