diff mbox series

[10/14] media: imx8mq-mipi-csi2: Add support for i.MX8QM

Message ID 20250131-8qxp_camera-v1-10-319402ab606a@nxp.com
State New
Headers show
Series media: imx8: add camera support | expand

Commit Message

Frank Li Jan. 31, 2025, 9:33 p.m. UTC
Add support for the common PHY interface to enable and disable the MIPI CSI
PHY. This is required for platforms like i.MX8QM, which rely on the PHY
driver for powering the MIPI CSI PHY on and off.

Add reset delay for i.MX8QM. It needs a delay after toggle reset.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/nxp/imx8mq-mipi-csi2.c | 46 +++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)
diff mbox series

Patch

diff --git a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c
index b5eae56d92f49..df34caffd4a3a 100644
--- a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c
+++ b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c
@@ -17,6 +17,7 @@ 
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
@@ -89,6 +90,8 @@  struct imx8mq_plat_data {
 	const char *name;
 	int (*enable)(struct csi_state *state, u32 hs_settle);
 	void (*disable)(struct csi_state *state);
+	bool use_phydrv: 1;
+	int reset_delay;
 };
 
 /*
@@ -125,6 +128,7 @@  struct csi_state {
 	u32 state;
 
 	struct regmap *phy_gpr;
+	struct phy *phy;
 	u8 phy_gpr_reg;
 
 	struct icc_path			*icc_path;
@@ -169,6 +173,37 @@  static const struct imx8mq_plat_data imx8mq_data = {
 	.enable = imx8mq_gpr_enable,
 };
 
+/* -----------------------------------------------------------------------------
+ * Use common PHY interface
+ */
+static int imx8_phy_enable(struct csi_state *state, u32 hs_settle)
+{
+	int ret;
+
+	ret = phy_set_speed(state->phy, hs_settle);
+	if (ret)
+		return ret;
+
+	ret = phy_power_on(state->phy);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void imx8_phy_disable(struct csi_state *state)
+{
+	phy_power_off(state->phy);
+}
+
+static const struct imx8mq_plat_data imx8qm_data = {
+	.name = "i.MX8QM",
+	.enable = imx8_phy_enable,
+	.disable = imx8_phy_disable,
+	.use_phydrv = 1,
+	.reset_delay = 10000,
+};
+
 static const struct csi2_pix_format imx8mq_mipi_csi_formats[] = {
 	/* RAW (Bayer and greyscale) formats. */
 	{
@@ -273,6 +308,8 @@  static int imx8mq_mipi_csi_sw_reset(struct csi_state *state)
 		return ret;
 	}
 
+	fsleep(state->pdata->reset_delay);
+
 	return 0;
 }
 
@@ -860,6 +897,14 @@  static int imx8mq_mipi_csi_parse_dt(struct csi_state *state)
 		return PTR_ERR(state->rst);
 	}
 
+	if (state->pdata->use_phydrv) {
+		state->phy = devm_of_phy_get_by_index(dev, dev->of_node, 0);
+		if (IS_ERR(state->phy))
+			return dev_err_probe(dev, PTR_ERR(state->phy), "Can't get mipi phy\n");
+
+		return 0;
+	}
+
 	ret = of_property_read_u32_array(np, "fsl,mipi-phy-gpr", out_val,
 					 ARRAY_SIZE(out_val));
 	if (ret) {
@@ -979,6 +1024,7 @@  static void imx8mq_mipi_csi_remove(struct platform_device *pdev)
 
 static const struct of_device_id imx8mq_mipi_csi_of_match[] = {
 	{ .compatible = "fsl,imx8mq-mipi-csi2", .data = &imx8mq_data },
+	{ .compatible = "fsl,imx8qm-mipi-csi2", .data = &imx8qm_data },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, imx8mq_mipi_csi_of_match);