From: Cosmin Tanislav <demonsingur@gmail.com>
To: Sakari Ailus <sakari.ailus@linux.intel.com>
Cc: "Tomi Valkeinen" <tomi.valkeinen+renesas@ideasonboard.com>,
"Mauro Carvalho Chehab" <mchehab@kernel.org>,
"Rob Herring" <robh@kernel.org>,
"Niklas Söderlund" <niklas.soderlund@ragnatech.se>,
"Julien Massot" <julien.massot@collabora.com>,
"Laurent Pinchart" <laurent.pinchart@ideasonboard.com>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Linus Walleij" <linus.walleij@linaro.org>,
"open list:MAXIM GMSL2 SERIALIZERS AND DESERIALIZERS"
<linux-media@vger.kernel.org>,
"open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS"
<devicetree@vger.kernel.org>,
"open list" <linux-kernel@vger.kernel.org>,
"moderated list:ARM64 PORT (AARCH64 ARCHITECTURE)"
<linux-arm-kernel@lists.infradead.org>,
"open list:STAGING SUBSYSTEM" <linux-staging@lists.linux.dev>,
"open list:GPIO
SUBSYSTEM:Keyword:(devm_)?gpio_(request|free|direction|get|set)"
<linux-gpio@vger.kernel.org>,
"Cosmin Tanislav" <cosmin.tanislav@analog.com>
Subject: Re: [PATCH v4 15/19] media: i2c: add Maxim GMSL2/3 serializer and deserializer drivers
Date: Tue, 24 Jun 2025 18:34:58 +0300 [thread overview]
Message-ID: <42fdeee8-a23e-4499-83c6-77d50418cff2@gmail.com> (raw)
In-Reply-To: <aFpnU8EHGt14UMHC@kekkonen.localdomain>
On 6/24/25 11:52 AM, Sakari Ailus wrote:
> Hi Cosmin,
>
> Thanks for the set.
>
> This patch is pretty massive. Could you split it into the serialiser and
> deserialiser frameworks and then invididual drivers using it (six-ish
> patches in total)?
>
I'll try to split it up for easier review, thanks.
I'll strip some of the context so I can answer easier.
The comments I stripped out are things I'll do without discussion.
...
>> +struct max9296a_chip_info {
>> + unsigned int max_register;
>> + unsigned int versions;
>> + unsigned int modes;
>> + unsigned int num_pipes;
>> + unsigned int pipe_hw_ids[MAX9296A_PIPES_NUM];
>> + unsigned int phy_hw_ids[MAX9296A_PHYS_NUM];
>> + unsigned int num_phys;
>> + unsigned int num_links;
>> + struct max_phys_configs phys_configs;
>> + bool use_atr;
>> + bool has_per_link_reset;
>> + bool phy0_lanes_0_1_on_second_phy;
>> + bool polarity_on_physical_lanes;
>> + bool needs_single_link_version;
>> + bool needs_unique_stream_id;
>> + bool supports_cphy;
>> + bool supports_phy_log;
>> + bool adjust_rlms;
>> + bool fix_tx_ids;
>> +
>> + enum max_gmsl_mode tpg_mode;
>> +
>> + int (*set_pipe_stream_id)(struct max_des *des, struct max_des_pipe
*pipe,
>> + unsigned int stream_id);
>> + int (*set_pipe_enable)(struct max_des *des, struct max_des_pipe *pipe,
>> + bool enable);
>> + int (*set_pipe_link)(struct max_des *des, struct max_des_pipe *pipe,
>> + struct max_des_link *link);
>> + int (*set_pipe_tunnel_phy)(struct max_des *des, struct
max_des_pipe *pipe,
>> + struct max_des_phy *phy);
>> + int (*set_pipe_tunnel_enable)(struct max_des *des, struct
max_des_pipe *pipe,
>> + bool enable);
>
> Given this many callbacks, having an operations struct for them seems
> appropriate.
>
Are you proposing adding another struct just to put these ops inside?
What I could do is use the existing struct max_des_ops and assign the
appropriate members in it, and then put whatever is left that's not
needed for the common framework in struct max9296a_chip_info, and add
a pointer to the struct max_des_ops instance it struct
max9296a_chip_info.
...
>> +static int max9296a_log_phy_status(struct max_des *des,
>> + struct max_des_phy *phy, const char *name)
>> +{
>> + struct max9296a_priv *priv = des_to_priv(des);
>> + unsigned int index = phy->index;
>> + unsigned int val;
>> + int ret;
>> +
>> + if (!priv->info->supports_phy_log)
>> + return 0;
>> +
>> + ret = regmap_read(priv->regmap, MAX9296A_MIPI_PHY18, &val);
>> + if (ret)
>> + return ret;
>> +
>> + pr_info("%s: \tcsi2_pkt_cnt: %lu\n", name,
>> + field_get(MAX9296A_MIPI_PHY18_CSI2_TX_PKT_CNT(index), val));
>> +
>> + ret = regmap_read(priv->regmap, MAX9296A_MIPI_PHY20(index), &val);
>> + if (ret)
>> + return ret;
>> +
>> + pr_info("%s: \tphy_pkt_cnt: %u\n", name, val);
>
> dev_info()?
>
I initially used pr_info() with the subdev name passed from core
framwork to be consistent with the rest of the prints which use
v4l2_info().
I'll see how using dev_info() looks like, it would be nice if it would
match the v4l2_info() format, even though v4l2-ctl --log-status doesn't
care since all it looks for is `START STATUS`.
>> +
>> + return 0;
>> +}
>> +
>> +static int max9296a_set_enable(struct max_des *des, bool enable)
>> +{
>> + struct max9296a_priv *priv = des_to_priv(des);
>> +
>> + return regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP12,
>> + MAX9296A_BACKTOP12_CSI_OUT_EN, enable);
>> +}
>> +
>> +static int max9296a_init_phy(struct max_des *des, struct
max_des_phy *phy)
>> +{
>> + struct max9296a_priv *priv = des_to_priv(des);
>> + bool is_cphy = phy->bus_type == V4L2_MBUS_CSI2_CPHY;
>> + unsigned int num_data_lanes = phy->mipi.num_data_lanes;
>> + unsigned int dpll_freq = phy->link_frequency * 2;
>> + unsigned int num_hw_data_lanes;
>> + unsigned int hw_index = max9296a_phy_id(priv, phy);
>> + unsigned int index = phy->index;
>> + unsigned int used_data_lanes = 0;
>> + unsigned int val;
>
> For register values, please use a type that explicitly specifies the
number
> of bits, e.g. u32.
>
I used the type of the argument received by the regmap methods.
...
>> +static int max9296a_reset_link(struct max9296a_priv *priv, unsigned
int index)
>> +{
>> + unsigned int reg, mask;
>> +
>> + if (index == 0) {
>> + reg = MAX9296A_CTRL0;
>> + mask = MAX9296A_CTRL0_RESET_ONESHOT;
>> + } else {
>> + reg = MAX9296A_CTRL2;
>> + mask = MAX9296A_CTRL2_RESET_ONESHOT_B;
>> + }
>
> I might use an array for this.
>
> Is index guaranteed to be 0 or 1?
>
Should be, yes, but using an array for just two indices would cause a
bit of indirection when looking at the code. If it was more I would have
used one.
>> +
>> + return regmap_set_bits(priv->regmap, reg, mask);
>> +}
>> +
>> +static int max9296a_init_link_rlms(struct max9296a_priv *priv,
>> + struct max_des_link *link)
>> +{
>> + unsigned int index = link->index;
>> + int ret;
>> +
>> + /*
>> + * These settings are described as required on datasheet page 53
>> + * for MAX96714.
>> + */
>> +
>> + ret = regmap_write(priv->regmap, MAX9296A_RLMS3E(index), 0xfd);
>> + if (ret)
>> + return ret;
>
> You could also do:
>
> if (!ret)
> ret = ...;
>
> And return ret at the end. It's one line less per call. Up to you.
>
>> +
>> + ret = regmap_write(priv->regmap, MAX9296A_RLMS3F(index), 0x3d);
>
> What are these magic numbers? Could we have human-readable names for
them?
>
> The register names seem pretty opaque, too. Some explanation here would
> seem reasonable.
>
They're extracted from the datasheet of MAX96714, the values are
undocumented, but they're necessary to "optimize performance" of the
GMSL link. I'll add a comment stating the datasheet page and section.
...
>> diff --git a/drivers/media/i2c/maxim-serdes/max_des.c
b/drivers/media/i2c/maxim-serdes/max_des.c
>> new file mode 100644
>> index 000000000000..6a45f42fe033
>> --- /dev/null
>> +++ b/drivers/media/i2c/maxim-serdes/max_des.c
>> @@ -0,0 +1,3108 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Maxim GMSL2 Deserializer Driver
>
> How about naming the file maxim-deserialiser? I'd use e.g. "maxim_des"
> prefix for the functions. Just "max" is quite generic.
>
max_des seems explicit enough. The max naming comes from the common
prefix in the name of the chips, eg: MAX96724, MAX96717, not from Maxim.
If I intended it to come from maxim, I would have obviously used maxim_,
since that's what vendor-prefixes.yaml specifies.
Although they were initially made by Maxim, Analog Devices bought Maxim,
so using maxim_ would make as much sense as using adi_.
Switching to maxim_ would only lengthen the name of the functions,
types, symbols, macros, etc, and at least register/masks macros are
already extremely long.
...
>> +static int max_des_parse_src_dt_endpoint(struct max_des_priv *priv,
>> + struct max_des_phy *phy,
>> + struct fwnode_handle *fwnode)
>> +{
>> + struct max_des *des = priv->des;
>> + u32 pad = max_des_phy_to_pad(des, phy);
>> + struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type =
V4L2_MBUS_UNKNOWN };
>> + struct v4l2_mbus_config_mipi_csi2 *mipi = &v4l2_ep.bus.mipi_csi2;
>> + enum v4l2_mbus_type bus_type;
>> + struct fwnode_handle *ep;
>> + u64 link_frequency;
>> + unsigned int i;
>> + int ret;
>> +
>> + ep = fwnode_graph_get_endpoint_by_id(fwnode, pad, 0, 0);
>> + if (!ep)
>> + return 0;
>> +
>> + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &v4l2_ep);
>> + fwnode_handle_put(ep);
>> + if (ret) {
>> + dev_err(priv->dev, "Could not parse endpoint on port %u\n", pad);
>> + return ret;
>> + }
>> +
>> + bus_type = v4l2_ep.bus_type;
>> + if (bus_type != V4L2_MBUS_CSI2_DPHY &&
>> + bus_type != V4L2_MBUS_CSI2_CPHY) {
>> + v4l2_fwnode_endpoint_free(&v4l2_ep);
>> + dev_err(priv->dev, "Unsupported bus-type %u on port %u\n",
>> + pad, bus_type);
>> + return -EINVAL;
>> + }
>> +
>> + ret = 0;
>
> ret is already 0 here.
>
>> + if (v4l2_ep.nr_of_link_frequencies == 0)
>> + link_frequency = MAX_DES_LINK_FREQUENCY_DEFAULT;
>
> Isn't this required in DT?
>
Required from a schema standpoint or a code standpoint?
Code:
rval = fwnode_property_count_u64(fwnode, "link-frequencies");
if (rval > 0) {
}
No rval <= 0 case.
And I don't think I made it required in the schema.
...
next prev parent reply other threads:[~2025-06-24 15:35 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-18 9:58 [PATCH v4 00/19] media: i2c: add Maxim GMSL2/3 serializer and deserializer drivers Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 01/19] media: mc: Add INTERNAL pad flag Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 02/19] dt-bindings: media: i2c: max96717: add myself as maintainer Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 03/19] dt-bindings: media: i2c: max96717: add support for I2C ATR Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 04/19] dt-bindings: media: i2c: max96717: add support for pinctrl/pinconf Cosmin Tanislav
2025-06-24 18:58 ` Linus Walleij
2025-06-27 19:38 ` Rob Herring
2025-06-18 9:58 ` [PATCH v4 05/19] dt-bindings: media: i2c: max96717: add support for MAX9295A Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 06/19] dt-bindings: media: i2c: max96717: add support for MAX96793 Cosmin Tanislav
2025-06-24 16:14 ` Martin Hecht
2025-06-24 16:20 ` Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 07/19] dt-bindings: media: i2c: max96712: add myself as maintainer Cosmin Tanislav
2025-06-19 10:31 ` Niklas Söderlund
2025-06-18 9:58 ` [PATCH v4 08/19] dt-bindings: media: i2c: max96712: use pattern properties for ports Cosmin Tanislav
2025-06-19 11:17 ` Niklas Söderlund
2025-06-18 9:58 ` [PATCH v4 09/19] dt-bindings: media: i2c: max96712: add support for I2C ATR Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 10/19] dt-bindings: media: i2c: max96712: add support for POC supplies Cosmin Tanislav
2025-06-19 13:32 ` Niklas Söderlund
2025-06-18 9:58 ` [PATCH v4 11/19] dt-bindings: media: i2c: max96712: add support for MAX96724F/R Cosmin Tanislav
2025-06-19 13:33 ` Niklas Söderlund
2025-06-18 9:58 ` [PATCH v4 12/19] dt-bindings: media: i2c: max96714: add myself as maintainer Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 13/19] dt-bindings: media: i2c: max96714: add support for MAX96714R Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 14/19] dt-bindings: media: i2c: add MAX9296A, MAX96716A, MAX96792A Cosmin Tanislav
2025-06-18 13:00 ` Rob Herring (Arm)
2025-06-18 9:58 ` [PATCH v4 15/19] media: i2c: add Maxim GMSL2/3 serializer and deserializer drivers Cosmin Tanislav
2025-06-19 18:30 ` Jakub Kostiw
2025-06-24 8:52 ` Sakari Ailus
2025-06-24 15:34 ` Cosmin Tanislav [this message]
2025-06-28 18:10 ` Sakari Ailus
2025-06-18 9:58 ` [PATCH v4 16/19] arm64: defconfig: disable deprecated MAX96712 driver Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 17/19] staging: media: remove " Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 18/19] media: i2c: remove MAX96717 driver Cosmin Tanislav
2025-06-18 9:58 ` [PATCH v4 19/19] media: i2c: remove MAX96714 driver Cosmin Tanislav
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=42fdeee8-a23e-4499-83c6-77d50418cff2@gmail.com \
--to=demonsingur@gmail.com \
--cc=cosmin.tanislav@analog.com \
--cc=devicetree@vger.kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=julien.massot@collabora.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linus.walleij@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-staging@lists.linux.dev \
--cc=mchehab@kernel.org \
--cc=niklas.soderlund@ragnatech.se \
--cc=robh@kernel.org \
--cc=sakari.ailus@linux.intel.com \
--cc=tomi.valkeinen+renesas@ideasonboard.com \
/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).