All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Heiko Stübner" <heiko@sntech.de>
To: neil.armstrong@linaro.org
Cc: andy.yan@rock-chips.com, maarten.lankhorst@linux.intel.com,
	mripard@kernel.org, tzimmermann@suse.de, robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, andrzej.hajda@intel.com,
	rfoss@kernel.org, Laurent.pinchart@ideasonboard.com,
	jonas@kwiboo.se, jernej.skrabec@gmail.com,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org,
	quentin.schulz@cherry.de,
	Heiko Stuebner <heiko.stuebner@cherry.de>
Subject: Re: [PATCH 1/3] drm/bridge/synopsys: Add MIPI DSI2 host controller bridge
Date: Tue, 26 Nov 2024 15:46:50 +0100	[thread overview]
Message-ID: <1909309.CQOukoFCf9@diego> (raw)
In-Reply-To: <881f2820-ff18-4d60-8bf3-f8cca1be5914@linaro.org>

Hi,

Am Mittwoch, 6. November 2024, 14:54:39 CET schrieb neil.armstrong@linaro.org:
> > +#define UPDATE(v, h, l)			(((v) << (l)) & GENMASK((h), (l)))
> 
> I'm not super fan of this macro, overall I thinkg you should switch to
> regmap and make use of regmap_update_bits and drop dsi2_write/read wrappers
> to readl/writel.

Yep you're right. That macro acutally is just FIELD_PREP in disguise ;-)
So I've gone with that (and regmap).


> <snip>
> 
> > +
> > +static struct dw_mipi_dsi2 *
> > +__dw_mipi_dsi2_probe(struct platform_device *pdev,
> > +		     const struct dw_mipi_dsi2_plat_data *plat_data)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct reset_control *apb_rst;
> > +	struct dw_mipi_dsi2 *dsi2;
> > +	int ret;
> > +
> > +	dsi2 = devm_kzalloc(dev, sizeof(*dsi2), GFP_KERNEL);
> > +	if (!dsi2)
> > +		return ERR_PTR(-ENOMEM);
> > +
> > +	dsi2->dev = dev;
> > +	dsi2->plat_data = plat_data;
> > +
> > +	if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps ||
> > +	    !plat_data->phy_ops->get_timing)
> > +		return dev_err_ptr_probe(dev, -ENODEV, "Phy not properly configured\n");
> > +
> > +	if (!plat_data->base) {
> > +		dsi2->base = devm_platform_ioremap_resource(pdev, 0);
> > +		if (IS_ERR(dsi2->base))
> > +			return ERR_PTR(-ENODEV);
> > +	} else {
> > +		dsi2->base = plat_data->base;
> > +	}
> > +
> > +	dsi2->pclk = devm_clk_get(dev, "pclk");
> > +	if (IS_ERR(dsi2->pclk))
> > +		return dev_err_cast_probe(dev, dsi2->pclk, "Unable to get pclk\n");
> > +
> > +	dsi2->sys_clk = devm_clk_get(dev, "sys");
> > +	if (IS_ERR(dsi2->sys_clk))
> > +		return dev_err_cast_probe(dev, dsi2->sys_clk, "Unable to get sys_clk\n");
> > +
> > +	/*
> > +	 * Note that the reset was not defined in the initial device tree, so
> > +	 * we have to be prepared for it not being found.
> > +	 */
> > +	apb_rst = devm_reset_control_get_optional_exclusive(dev, "apb");
> > +	if (IS_ERR(apb_rst))
> > +		return dev_err_cast_probe(dev, apb_rst, "Unable to get reset control\n");
> > +
> > +	if (apb_rst) {
> > +		ret = clk_prepare_enable(dsi2->pclk);
> > +		if (ret) {
> > +			dev_err(dev, "%s: Failed to enable pclk\n", __func__);
> > +			return ERR_PTR(ret);
> > +		}
> > +
> > +		reset_control_assert(apb_rst);
> > +		usleep_range(10, 20);
> > +		reset_control_deassert(apb_rst);
> > +
> > +		clk_disable_unprepare(dsi2->pclk);
> > +	}
> > +
> > +	pm_runtime_enable(dev);
> > +
> > +	dsi2->dsi_host.ops = &dw_mipi_dsi2_host_ops;
> > +	dsi2->dsi_host.dev = dev;
> > +	ret = mipi_dsi_host_register(&dsi2->dsi_host);
> > +	if (ret) {
> > +		dev_err(dev, "Failed to register MIPI host: %d\n", ret);
> > +		pm_runtime_disable(dev);
> > +		return ERR_PTR(ret);
> > +	}
> > +
> > +	dsi2->bridge.driver_private = dsi2;
> > +	dsi2->bridge.funcs = &dw_mipi_dsi2_bridge_funcs;
> > +	dsi2->bridge.of_node = pdev->dev.of_node;
> > +
> > +	return dsi2;
> > +}
> > +
> > +static void __dw_mipi_dsi2_remove(struct dw_mipi_dsi2 *dsi2)
> > +{
> > +	mipi_dsi_host_unregister(&dsi2->dsi_host);
> > +
> > +	pm_runtime_disable(dsi2->dev);
> > +}
> > +
> > +/*
> > + * Probe/remove API, used from platforms based on the DRM bridge API.
> > + */
> > +struct dw_mipi_dsi2 *
> > +dw_mipi_dsi2_probe(struct platform_device *pdev,
> > +		   const struct dw_mipi_dsi2_plat_data *plat_data)
> > +{
> > +	return __dw_mipi_dsi2_probe(pdev, plat_data);
> > +}
> > +EXPORT_SYMBOL_GPL(dw_mipi_dsi2_probe);
> > +
> > +void dw_mipi_dsi2_remove(struct dw_mipi_dsi2 *dsi2)
> > +{
> > +	__dw_mipi_dsi2_remove(dsi2);
> > +}
> > +EXPORT_SYMBOL_GPL(dw_mipi_dsi2_remove);
> 
> Since it's not use yet, you should probably drop those since it's dead
> code.

Though it is used. The Rockchip glue in patch 3 calls 
	dsi2->dmd = dw_mipi_dsi2_probe(pdev, &dsi2->pdata);
in its dw_mipi_dsi2_rockchip_probe() and
	dw_mipi_dsi2_remove(dsi2->dmd);
in its dw_mipi_dsi2_rockchip_remove() for the whole bridge setup

Similarly the below bind/unbind functions are called for the bridge-attach
from the component part of the Rockchip glue.

Which is the same way the dsi1 driver handles things right now.


> > +
> > +/*
> > + * Bind/unbind API, used from platforms based on the component framework.
> > + */
> > +int dw_mipi_dsi2_bind(struct dw_mipi_dsi2 *dsi2, struct drm_encoder *encoder)
> > +{
> > +	return drm_bridge_attach(encoder, &dsi2->bridge, NULL, 0);
> > +}
> > +EXPORT_SYMBOL_GPL(dw_mipi_dsi2_bind);
> > +
> > +void dw_mipi_dsi2_unbind(struct dw_mipi_dsi2 *dsi2)
> > +{
> > +}
> > +EXPORT_SYMBOL_GPL(dw_mipi_dsi2_unbind);

[...]

> > +struct dw_mipi_dsi2 *dw_mipi_dsi2_probe(struct platform_device *pdev,
> > +					const struct dw_mipi_dsi2_plat_data *plat_data);
> > +void dw_mipi_dsi2_remove(struct dw_mipi_dsi2 *dsi2);
> > +int dw_mipi_dsi2_bind(struct dw_mipi_dsi2 *dsi2, struct drm_encoder *encoder);
> > +void dw_mipi_dsi2_unbind(struct dw_mipi_dsi2 *dsi2);
> > +
> > +#endif /* __DW_MIPI_DSI2__ */
> 
> Overall the driver is very close to dw-mipi-dsi, si it's overall good!

that was the intention ... so that I don't introduce issues that were
already solved elsewhere ;-) .

Heiko




WARNING: multiple messages have this Message-ID (diff)
From: "Heiko Stübner" <heiko@sntech.de>
To: neil.armstrong@linaro.org
Cc: andy.yan@rock-chips.com, maarten.lankhorst@linux.intel.com,
	mripard@kernel.org, tzimmermann@suse.de, robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, andrzej.hajda@intel.com,
	rfoss@kernel.org, Laurent.pinchart@ideasonboard.com,
	jonas@kwiboo.se, jernej.skrabec@gmail.com,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org,
	quentin.schulz@cherry.de,
	Heiko Stuebner <heiko.stuebner@cherry.de>
Subject: Re: [PATCH 1/3] drm/bridge/synopsys: Add MIPI DSI2 host controller bridge
Date: Tue, 26 Nov 2024 15:46:50 +0100	[thread overview]
Message-ID: <1909309.CQOukoFCf9@diego> (raw)
In-Reply-To: <881f2820-ff18-4d60-8bf3-f8cca1be5914@linaro.org>

Hi,

Am Mittwoch, 6. November 2024, 14:54:39 CET schrieb neil.armstrong@linaro.org:
> > +#define UPDATE(v, h, l)			(((v) << (l)) & GENMASK((h), (l)))
> 
> I'm not super fan of this macro, overall I thinkg you should switch to
> regmap and make use of regmap_update_bits and drop dsi2_write/read wrappers
> to readl/writel.

Yep you're right. That macro acutally is just FIELD_PREP in disguise ;-)
So I've gone with that (and regmap).


> <snip>
> 
> > +
> > +static struct dw_mipi_dsi2 *
> > +__dw_mipi_dsi2_probe(struct platform_device *pdev,
> > +		     const struct dw_mipi_dsi2_plat_data *plat_data)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct reset_control *apb_rst;
> > +	struct dw_mipi_dsi2 *dsi2;
> > +	int ret;
> > +
> > +	dsi2 = devm_kzalloc(dev, sizeof(*dsi2), GFP_KERNEL);
> > +	if (!dsi2)
> > +		return ERR_PTR(-ENOMEM);
> > +
> > +	dsi2->dev = dev;
> > +	dsi2->plat_data = plat_data;
> > +
> > +	if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps ||
> > +	    !plat_data->phy_ops->get_timing)
> > +		return dev_err_ptr_probe(dev, -ENODEV, "Phy not properly configured\n");
> > +
> > +	if (!plat_data->base) {
> > +		dsi2->base = devm_platform_ioremap_resource(pdev, 0);
> > +		if (IS_ERR(dsi2->base))
> > +			return ERR_PTR(-ENODEV);
> > +	} else {
> > +		dsi2->base = plat_data->base;
> > +	}
> > +
> > +	dsi2->pclk = devm_clk_get(dev, "pclk");
> > +	if (IS_ERR(dsi2->pclk))
> > +		return dev_err_cast_probe(dev, dsi2->pclk, "Unable to get pclk\n");
> > +
> > +	dsi2->sys_clk = devm_clk_get(dev, "sys");
> > +	if (IS_ERR(dsi2->sys_clk))
> > +		return dev_err_cast_probe(dev, dsi2->sys_clk, "Unable to get sys_clk\n");
> > +
> > +	/*
> > +	 * Note that the reset was not defined in the initial device tree, so
> > +	 * we have to be prepared for it not being found.
> > +	 */
> > +	apb_rst = devm_reset_control_get_optional_exclusive(dev, "apb");
> > +	if (IS_ERR(apb_rst))
> > +		return dev_err_cast_probe(dev, apb_rst, "Unable to get reset control\n");
> > +
> > +	if (apb_rst) {
> > +		ret = clk_prepare_enable(dsi2->pclk);
> > +		if (ret) {
> > +			dev_err(dev, "%s: Failed to enable pclk\n", __func__);
> > +			return ERR_PTR(ret);
> > +		}
> > +
> > +		reset_control_assert(apb_rst);
> > +		usleep_range(10, 20);
> > +		reset_control_deassert(apb_rst);
> > +
> > +		clk_disable_unprepare(dsi2->pclk);
> > +	}
> > +
> > +	pm_runtime_enable(dev);
> > +
> > +	dsi2->dsi_host.ops = &dw_mipi_dsi2_host_ops;
> > +	dsi2->dsi_host.dev = dev;
> > +	ret = mipi_dsi_host_register(&dsi2->dsi_host);
> > +	if (ret) {
> > +		dev_err(dev, "Failed to register MIPI host: %d\n", ret);
> > +		pm_runtime_disable(dev);
> > +		return ERR_PTR(ret);
> > +	}
> > +
> > +	dsi2->bridge.driver_private = dsi2;
> > +	dsi2->bridge.funcs = &dw_mipi_dsi2_bridge_funcs;
> > +	dsi2->bridge.of_node = pdev->dev.of_node;
> > +
> > +	return dsi2;
> > +}
> > +
> > +static void __dw_mipi_dsi2_remove(struct dw_mipi_dsi2 *dsi2)
> > +{
> > +	mipi_dsi_host_unregister(&dsi2->dsi_host);
> > +
> > +	pm_runtime_disable(dsi2->dev);
> > +}
> > +
> > +/*
> > + * Probe/remove API, used from platforms based on the DRM bridge API.
> > + */
> > +struct dw_mipi_dsi2 *
> > +dw_mipi_dsi2_probe(struct platform_device *pdev,
> > +		   const struct dw_mipi_dsi2_plat_data *plat_data)
> > +{
> > +	return __dw_mipi_dsi2_probe(pdev, plat_data);
> > +}
> > +EXPORT_SYMBOL_GPL(dw_mipi_dsi2_probe);
> > +
> > +void dw_mipi_dsi2_remove(struct dw_mipi_dsi2 *dsi2)
> > +{
> > +	__dw_mipi_dsi2_remove(dsi2);
> > +}
> > +EXPORT_SYMBOL_GPL(dw_mipi_dsi2_remove);
> 
> Since it's not use yet, you should probably drop those since it's dead
> code.

Though it is used. The Rockchip glue in patch 3 calls 
	dsi2->dmd = dw_mipi_dsi2_probe(pdev, &dsi2->pdata);
in its dw_mipi_dsi2_rockchip_probe() and
	dw_mipi_dsi2_remove(dsi2->dmd);
in its dw_mipi_dsi2_rockchip_remove() for the whole bridge setup

Similarly the below bind/unbind functions are called for the bridge-attach
from the component part of the Rockchip glue.

Which is the same way the dsi1 driver handles things right now.


> > +
> > +/*
> > + * Bind/unbind API, used from platforms based on the component framework.
> > + */
> > +int dw_mipi_dsi2_bind(struct dw_mipi_dsi2 *dsi2, struct drm_encoder *encoder)
> > +{
> > +	return drm_bridge_attach(encoder, &dsi2->bridge, NULL, 0);
> > +}
> > +EXPORT_SYMBOL_GPL(dw_mipi_dsi2_bind);
> > +
> > +void dw_mipi_dsi2_unbind(struct dw_mipi_dsi2 *dsi2)
> > +{
> > +}
> > +EXPORT_SYMBOL_GPL(dw_mipi_dsi2_unbind);

[...]

> > +struct dw_mipi_dsi2 *dw_mipi_dsi2_probe(struct platform_device *pdev,
> > +					const struct dw_mipi_dsi2_plat_data *plat_data);
> > +void dw_mipi_dsi2_remove(struct dw_mipi_dsi2 *dsi2);
> > +int dw_mipi_dsi2_bind(struct dw_mipi_dsi2 *dsi2, struct drm_encoder *encoder);
> > +void dw_mipi_dsi2_unbind(struct dw_mipi_dsi2 *dsi2);
> > +
> > +#endif /* __DW_MIPI_DSI2__ */
> 
> Overall the driver is very close to dw-mipi-dsi, si it's overall good!

that was the intention ... so that I don't introduce issues that were
already solved elsewhere ;-) .

Heiko



_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

  reply	other threads:[~2024-11-26 14:48 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-06 12:33 [PATCH 0/3] drm/rockchip: Add driver for the new DSI2 controller Heiko Stuebner
2024-11-06 12:33 ` Heiko Stuebner
2024-11-06 12:33 ` [PATCH 1/3] drm/bridge/synopsys: Add MIPI DSI2 host controller bridge Heiko Stuebner
2024-11-06 12:33   ` Heiko Stuebner
2024-11-06 13:09   ` Diederik de Haas
2024-11-06 13:09     ` Diederik de Haas
2024-11-06 13:54   ` neil.armstrong
2024-11-06 13:54     ` neil.armstrong
2024-11-26 14:46     ` Heiko Stübner [this message]
2024-11-26 14:46       ` Heiko Stübner
2024-11-06 12:33 ` [PATCH 2/3] dt-bindings: display: rockchip: Add schema for RK3588 DW DSI2 controller Heiko Stuebner
2024-11-06 12:33   ` Heiko Stuebner
2024-11-06 13:48   ` Rob Herring (Arm)
2024-11-06 13:48     ` Rob Herring (Arm)
2024-11-06 14:25   ` Rob Herring
2024-11-06 14:25     ` Rob Herring
2024-11-06 12:33 ` [PATCH 3/3] drm/rockchip: Add MIPI DSI2 glue driver for RK3588 Heiko Stuebner
2024-11-06 12:33   ` Heiko Stuebner
2024-11-06 13:33   ` Diederik de Haas
2024-11-06 13:33     ` Diederik de Haas
2024-11-26 13:39     ` Heiko Stübner
2024-11-26 13:39       ` Heiko Stübner
2024-11-20  9:52 ` [PATCH 0/3] drm/rockchip: Add driver for the new DSI2 controller Daniel Semkowicz
2024-11-20  9:52   ` Daniel Semkowicz

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=1909309.CQOukoFCf9@diego \
    --to=heiko@sntech.de \
    --cc=Laurent.pinchart@ideasonboard.com \
    --cc=andrzej.hajda@intel.com \
    --cc=andy.yan@rock-chips.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=heiko.stuebner@cherry.de \
    --cc=jernej.skrabec@gmail.com \
    --cc=jonas@kwiboo.se \
    --cc=krzk+dt@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=neil.armstrong@linaro.org \
    --cc=quentin.schulz@cherry.de \
    --cc=rfoss@kernel.org \
    --cc=robh@kernel.org \
    --cc=tzimmermann@suse.de \
    /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.