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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).