xref: /openbmc/linux/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c (revision 5ee9cd065836e5934710ca35653bce7905add20b)
18082e2f4SPaul Elder // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
28082e2f4SPaul Elder /*
38082e2f4SPaul Elder  * Rockchip ISP1 Driver - CSI-2 Receiver
48082e2f4SPaul Elder  *
58082e2f4SPaul Elder  * Copyright (C) 2019 Collabora, Ltd.
68082e2f4SPaul Elder  * Copyright (C) 2022 Ideas on Board
78082e2f4SPaul Elder  *
88082e2f4SPaul Elder  * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd.
98082e2f4SPaul Elder  * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
108082e2f4SPaul Elder  */
118082e2f4SPaul Elder 
12a81138afSLaurent Pinchart #include <linux/delay.h>
138082e2f4SPaul Elder #include <linux/device.h>
14b298f059SPaul Elder #include <linux/lockdep.h>
158082e2f4SPaul Elder #include <linux/phy/phy.h>
168082e2f4SPaul Elder #include <linux/phy/phy-mipi-dphy.h>
178082e2f4SPaul Elder 
188082e2f4SPaul Elder #include <media/v4l2-ctrls.h>
19b298f059SPaul Elder #include <media/v4l2-fwnode.h>
208082e2f4SPaul Elder 
218082e2f4SPaul Elder #include "rkisp1-common.h"
228082e2f4SPaul Elder #include "rkisp1-csi.h"
238082e2f4SPaul Elder 
24b298f059SPaul Elder #define RKISP1_CSI_DEV_NAME	RKISP1_DRIVER_NAME "_csi"
25b298f059SPaul Elder 
26b298f059SPaul Elder #define RKISP1_CSI_DEF_FMT	MEDIA_BUS_FMT_SRGGB10_1X10
27b298f059SPaul Elder 
to_rkisp1_csi(struct v4l2_subdev * sd)28b298f059SPaul Elder static inline struct rkisp1_csi *to_rkisp1_csi(struct v4l2_subdev *sd)
29b298f059SPaul Elder {
30b298f059SPaul Elder 	return container_of(sd, struct rkisp1_csi, sd);
31b298f059SPaul Elder }
32b298f059SPaul Elder 
33b298f059SPaul Elder static struct v4l2_mbus_framefmt *
rkisp1_csi_get_pad_fmt(struct rkisp1_csi * csi,struct v4l2_subdev_state * sd_state,unsigned int pad,u32 which)34b298f059SPaul Elder rkisp1_csi_get_pad_fmt(struct rkisp1_csi *csi,
35b298f059SPaul Elder 		       struct v4l2_subdev_state *sd_state,
36b298f059SPaul Elder 		       unsigned int pad, u32 which)
37b298f059SPaul Elder {
38b298f059SPaul Elder 	struct v4l2_subdev_state state = {
39b298f059SPaul Elder 		.pads = csi->pad_cfg
40b298f059SPaul Elder 	};
41b298f059SPaul Elder 
42b298f059SPaul Elder 	lockdep_assert_held(&csi->lock);
43b298f059SPaul Elder 
44b298f059SPaul Elder 	if (which == V4L2_SUBDEV_FORMAT_TRY)
45b298f059SPaul Elder 		return v4l2_subdev_get_try_format(&csi->sd, sd_state, pad);
46b298f059SPaul Elder 	else
47b298f059SPaul Elder 		return v4l2_subdev_get_try_format(&csi->sd, &state, pad);
48b298f059SPaul Elder }
49b298f059SPaul Elder 
rkisp1_csi_link_sensor(struct rkisp1_device * rkisp1,struct v4l2_subdev * sd,struct rkisp1_sensor_async * s_asd,unsigned int source_pad)5098bfd0cdSLaurent Pinchart int rkisp1_csi_link_sensor(struct rkisp1_device *rkisp1, struct v4l2_subdev *sd,
5198bfd0cdSLaurent Pinchart 			   struct rkisp1_sensor_async *s_asd,
5298bfd0cdSLaurent Pinchart 			   unsigned int source_pad)
5398bfd0cdSLaurent Pinchart {
5498bfd0cdSLaurent Pinchart 	struct rkisp1_csi *csi = &rkisp1->csi;
5598bfd0cdSLaurent Pinchart 	int ret;
5698bfd0cdSLaurent Pinchart 
5798bfd0cdSLaurent Pinchart 	s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler,
5898bfd0cdSLaurent Pinchart 						V4L2_CID_PIXEL_RATE);
5998bfd0cdSLaurent Pinchart 	if (!s_asd->pixel_rate_ctrl) {
6098bfd0cdSLaurent Pinchart 		dev_err(rkisp1->dev, "No pixel rate control in subdev %s\n",
6198bfd0cdSLaurent Pinchart 			sd->name);
6298bfd0cdSLaurent Pinchart 		return -EINVAL;
6398bfd0cdSLaurent Pinchart 	}
6498bfd0cdSLaurent Pinchart 
6598bfd0cdSLaurent Pinchart 	/* Create the link from the sensor to the CSI receiver. */
6698bfd0cdSLaurent Pinchart 	ret = media_create_pad_link(&sd->entity, source_pad,
6798bfd0cdSLaurent Pinchart 				    &csi->sd.entity, RKISP1_CSI_PAD_SINK,
6898bfd0cdSLaurent Pinchart 				    !s_asd->index ? MEDIA_LNK_FL_ENABLED : 0);
6998bfd0cdSLaurent Pinchart 	if (ret) {
7098bfd0cdSLaurent Pinchart 		dev_err(csi->rkisp1->dev, "failed to link src pad of %s\n",
7198bfd0cdSLaurent Pinchart 			sd->name);
7298bfd0cdSLaurent Pinchart 		return ret;
7398bfd0cdSLaurent Pinchart 	}
7498bfd0cdSLaurent Pinchart 
7598bfd0cdSLaurent Pinchart 	return 0;
7698bfd0cdSLaurent Pinchart }
7798bfd0cdSLaurent Pinchart 
rkisp1_csi_config(struct rkisp1_csi * csi,const struct rkisp1_sensor_async * sensor)78c5045943SLaurent Pinchart static int rkisp1_csi_config(struct rkisp1_csi *csi,
793061c659SLaurent Pinchart 			     const struct rkisp1_sensor_async *sensor)
808082e2f4SPaul Elder {
818082e2f4SPaul Elder 	struct rkisp1_device *rkisp1 = csi->rkisp1;
82c5045943SLaurent Pinchart 	unsigned int lanes = sensor->lanes;
838082e2f4SPaul Elder 	u32 mipi_ctrl;
848082e2f4SPaul Elder 
858082e2f4SPaul Elder 	if (lanes < 1 || lanes > 4)
868082e2f4SPaul Elder 		return -EINVAL;
878082e2f4SPaul Elder 
888082e2f4SPaul Elder 	mipi_ctrl = RKISP1_CIF_MIPI_CTRL_NUM_LANES(lanes - 1) |
898082e2f4SPaul Elder 		    RKISP1_CIF_MIPI_CTRL_SHUTDOWNLANES(0xf) |
908082e2f4SPaul Elder 		    RKISP1_CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP |
918082e2f4SPaul Elder 		    RKISP1_CIF_MIPI_CTRL_CLOCKLANE_ENA;
928082e2f4SPaul Elder 
938082e2f4SPaul Elder 	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_CTRL, mipi_ctrl);
948082e2f4SPaul Elder 
958082e2f4SPaul Elder 	/* V12 could also use a newer csi2-host, but we don't want that yet */
968082e2f4SPaul Elder 	if (rkisp1->info->isp_ver == RKISP1_V12)
978082e2f4SPaul Elder 		rkisp1_write(rkisp1, RKISP1_CIF_ISP_CSI0_CTRL0, 0);
988082e2f4SPaul Elder 
998082e2f4SPaul Elder 	/* Configure Data Type and Virtual Channel */
1008082e2f4SPaul Elder 	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMG_DATA_SEL,
101b298f059SPaul Elder 		     RKISP1_CIF_MIPI_DATA_SEL_DT(csi->sink_fmt->mipi_dt) |
1028082e2f4SPaul Elder 		     RKISP1_CIF_MIPI_DATA_SEL_VC(0));
1038082e2f4SPaul Elder 
1048082e2f4SPaul Elder 	/* Clear MIPI interrupts */
1058082e2f4SPaul Elder 	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_ICR, ~0);
1068082e2f4SPaul Elder 
1078082e2f4SPaul Elder 	/*
1088082e2f4SPaul Elder 	 * Disable RKISP1_CIF_MIPI_ERR_DPHY interrupt here temporary for
1098082e2f4SPaul Elder 	 * isp bus may be dead when switch isp.
1108082e2f4SPaul Elder 	 */
1118082e2f4SPaul Elder 	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC,
1128082e2f4SPaul Elder 		     RKISP1_CIF_MIPI_FRAME_END | RKISP1_CIF_MIPI_ERR_CSI |
1138082e2f4SPaul Elder 		     RKISP1_CIF_MIPI_ERR_DPHY |
1148082e2f4SPaul Elder 		     RKISP1_CIF_MIPI_SYNC_FIFO_OVFLW(0x03) |
1158082e2f4SPaul Elder 		     RKISP1_CIF_MIPI_ADD_DATA_OVFLW);
1168082e2f4SPaul Elder 
1178082e2f4SPaul Elder 	dev_dbg(rkisp1->dev, "\n  MIPI_CTRL 0x%08x\n"
1188082e2f4SPaul Elder 		"  MIPI_IMG_DATA_SEL 0x%08x\n"
1198082e2f4SPaul Elder 		"  MIPI_STATUS 0x%08x\n"
1208082e2f4SPaul Elder 		"  MIPI_IMSC 0x%08x\n",
1218082e2f4SPaul Elder 		rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL),
1228082e2f4SPaul Elder 		rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMG_DATA_SEL),
1238082e2f4SPaul Elder 		rkisp1_read(rkisp1, RKISP1_CIF_MIPI_STATUS),
1248082e2f4SPaul Elder 		rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC));
1258082e2f4SPaul Elder 
1268082e2f4SPaul Elder 	return 0;
1278082e2f4SPaul Elder }
1288082e2f4SPaul Elder 
rkisp1_csi_enable(struct rkisp1_csi * csi)1290c0b9f9cSLaurent Pinchart static void rkisp1_csi_enable(struct rkisp1_csi *csi)
130039a7342SLaurent Pinchart {
131039a7342SLaurent Pinchart 	struct rkisp1_device *rkisp1 = csi->rkisp1;
132039a7342SLaurent Pinchart 	u32 val;
133039a7342SLaurent Pinchart 
134039a7342SLaurent Pinchart 	val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL);
135039a7342SLaurent Pinchart 	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_CTRL,
136039a7342SLaurent Pinchart 		     val | RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA);
137039a7342SLaurent Pinchart }
138039a7342SLaurent Pinchart 
rkisp1_csi_disable(struct rkisp1_csi * csi)1390c0b9f9cSLaurent Pinchart static void rkisp1_csi_disable(struct rkisp1_csi *csi)
140039a7342SLaurent Pinchart {
141039a7342SLaurent Pinchart 	struct rkisp1_device *rkisp1 = csi->rkisp1;
142039a7342SLaurent Pinchart 	u32 val;
143039a7342SLaurent Pinchart 
144fab48343STomi Valkeinen 	/* Mask MIPI interrupts. */
145039a7342SLaurent Pinchart 	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC, 0);
146fab48343STomi Valkeinen 
147fab48343STomi Valkeinen 	/* Flush posted writes */
148fab48343STomi Valkeinen 	rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC);
149fab48343STomi Valkeinen 
150fab48343STomi Valkeinen 	/*
151fab48343STomi Valkeinen 	 * Wait until the IRQ handler has ended. The IRQ handler may get called
152fab48343STomi Valkeinen 	 * even after this, but it will return immediately as the MIPI
153fab48343STomi Valkeinen 	 * interrupts have been masked.
154fab48343STomi Valkeinen 	 */
155fab48343STomi Valkeinen 	synchronize_irq(rkisp1->irqs[RKISP1_IRQ_MIPI]);
156fab48343STomi Valkeinen 
157fab48343STomi Valkeinen 	/* Clear MIPI interrupt status */
158039a7342SLaurent Pinchart 	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_ICR, ~0);
159039a7342SLaurent Pinchart 
160039a7342SLaurent Pinchart 	val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL);
161039a7342SLaurent Pinchart 	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_CTRL,
162039a7342SLaurent Pinchart 		     val & (~RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA));
163039a7342SLaurent Pinchart }
164039a7342SLaurent Pinchart 
rkisp1_csi_start(struct rkisp1_csi * csi,const struct rkisp1_sensor_async * sensor)16598bfd0cdSLaurent Pinchart static int rkisp1_csi_start(struct rkisp1_csi *csi,
1663061c659SLaurent Pinchart 			    const struct rkisp1_sensor_async *sensor)
1678082e2f4SPaul Elder {
1688082e2f4SPaul Elder 	struct rkisp1_device *rkisp1 = csi->rkisp1;
1698082e2f4SPaul Elder 	union phy_configure_opts opts;
1708082e2f4SPaul Elder 	struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
1718082e2f4SPaul Elder 	s64 pixel_clock;
172039a7342SLaurent Pinchart 	int ret;
173039a7342SLaurent Pinchart 
174c5045943SLaurent Pinchart 	ret = rkisp1_csi_config(csi, sensor);
175039a7342SLaurent Pinchart 	if (ret)
176039a7342SLaurent Pinchart 		return ret;
1778082e2f4SPaul Elder 
1788082e2f4SPaul Elder 	pixel_clock = v4l2_ctrl_g_ctrl_int64(sensor->pixel_rate_ctrl);
1798082e2f4SPaul Elder 	if (!pixel_clock) {
1808082e2f4SPaul Elder 		dev_err(rkisp1->dev, "Invalid pixel rate value\n");
1818082e2f4SPaul Elder 		return -EINVAL;
1828082e2f4SPaul Elder 	}
1838082e2f4SPaul Elder 
184b298f059SPaul Elder 	phy_mipi_dphy_get_default_config(pixel_clock, csi->sink_fmt->bus_width,
1858082e2f4SPaul Elder 					 sensor->lanes, cfg);
1868082e2f4SPaul Elder 	phy_set_mode(csi->dphy, PHY_MODE_MIPI_DPHY);
1878082e2f4SPaul Elder 	phy_configure(csi->dphy, &opts);
1888082e2f4SPaul Elder 	phy_power_on(csi->dphy);
1898082e2f4SPaul Elder 
1900c0b9f9cSLaurent Pinchart 	rkisp1_csi_enable(csi);
191039a7342SLaurent Pinchart 
192a81138afSLaurent Pinchart 	/*
193a81138afSLaurent Pinchart 	 * CIF spec says to wait for sufficient time after enabling
194a81138afSLaurent Pinchart 	 * the MIPI interface and before starting the sensor output.
195a81138afSLaurent Pinchart 	 */
196a81138afSLaurent Pinchart 	usleep_range(1000, 1200);
197a81138afSLaurent Pinchart 
1988082e2f4SPaul Elder 	return 0;
1998082e2f4SPaul Elder }
2008082e2f4SPaul Elder 
rkisp1_csi_stop(struct rkisp1_csi * csi)20198bfd0cdSLaurent Pinchart static void rkisp1_csi_stop(struct rkisp1_csi *csi)
2028082e2f4SPaul Elder {
2030c0b9f9cSLaurent Pinchart 	rkisp1_csi_disable(csi);
204039a7342SLaurent Pinchart 
2058082e2f4SPaul Elder 	phy_power_off(csi->dphy);
2068082e2f4SPaul Elder }
2078082e2f4SPaul Elder 
rkisp1_csi_isr(int irq,void * ctx)2080c0b9f9cSLaurent Pinchart irqreturn_t rkisp1_csi_isr(int irq, void *ctx)
2098082e2f4SPaul Elder {
2108082e2f4SPaul Elder 	struct device *dev = ctx;
2118082e2f4SPaul Elder 	struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
2128082e2f4SPaul Elder 	u32 val, status;
2138082e2f4SPaul Elder 
214*b39b4d20STomi Valkeinen 	if (!rkisp1->irqs_enabled)
215*b39b4d20STomi Valkeinen 		return IRQ_NONE;
216*b39b4d20STomi Valkeinen 
2178082e2f4SPaul Elder 	status = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_MIS);
2188082e2f4SPaul Elder 	if (!status)
2198082e2f4SPaul Elder 		return IRQ_NONE;
2208082e2f4SPaul Elder 
2218082e2f4SPaul Elder 	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_ICR, status);
2228082e2f4SPaul Elder 
2238082e2f4SPaul Elder 	/*
2248082e2f4SPaul Elder 	 * Disable DPHY errctrl interrupt, because this dphy
2258082e2f4SPaul Elder 	 * erctrl signal is asserted until the next changes
2268082e2f4SPaul Elder 	 * of line state. This time is may be too long and cpu
2278082e2f4SPaul Elder 	 * is hold in this interrupt.
2288082e2f4SPaul Elder 	 */
2298082e2f4SPaul Elder 	if (status & RKISP1_CIF_MIPI_ERR_CTRL(0x0f)) {
2308082e2f4SPaul Elder 		val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC);
2318082e2f4SPaul Elder 		rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC,
2328082e2f4SPaul Elder 			     val & ~RKISP1_CIF_MIPI_ERR_CTRL(0x0f));
2338082e2f4SPaul Elder 		rkisp1->csi.is_dphy_errctrl_disabled = true;
2348082e2f4SPaul Elder 	}
2358082e2f4SPaul Elder 
2368082e2f4SPaul Elder 	/*
2378082e2f4SPaul Elder 	 * Enable DPHY errctrl interrupt again, if mipi have receive
2388082e2f4SPaul Elder 	 * the whole frame without any error.
2398082e2f4SPaul Elder 	 */
2408082e2f4SPaul Elder 	if (status == RKISP1_CIF_MIPI_FRAME_END) {
2418082e2f4SPaul Elder 		/*
2428082e2f4SPaul Elder 		 * Enable DPHY errctrl interrupt again, if mipi have receive
2438082e2f4SPaul Elder 		 * the whole frame without any error.
2448082e2f4SPaul Elder 		 */
2458082e2f4SPaul Elder 		if (rkisp1->csi.is_dphy_errctrl_disabled) {
2468082e2f4SPaul Elder 			val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC);
2478082e2f4SPaul Elder 			val |= RKISP1_CIF_MIPI_ERR_CTRL(0x0f);
2488082e2f4SPaul Elder 			rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC, val);
2498082e2f4SPaul Elder 			rkisp1->csi.is_dphy_errctrl_disabled = false;
2508082e2f4SPaul Elder 		}
2518082e2f4SPaul Elder 	} else {
2528082e2f4SPaul Elder 		rkisp1->debug.mipi_error++;
2538082e2f4SPaul Elder 	}
2548082e2f4SPaul Elder 
2558082e2f4SPaul Elder 	return IRQ_HANDLED;
2568082e2f4SPaul Elder }
2578082e2f4SPaul Elder 
258b298f059SPaul Elder /* ----------------------------------------------------------------------------
259b298f059SPaul Elder  * Subdev pad operations
260b298f059SPaul Elder  */
261b298f059SPaul Elder 
rkisp1_csi_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)262b298f059SPaul Elder static int rkisp1_csi_enum_mbus_code(struct v4l2_subdev *sd,
263b298f059SPaul Elder 				     struct v4l2_subdev_state *sd_state,
264b298f059SPaul Elder 				     struct v4l2_subdev_mbus_code_enum *code)
265b298f059SPaul Elder {
266b298f059SPaul Elder 	struct rkisp1_csi *csi = to_rkisp1_csi(sd);
267b298f059SPaul Elder 	unsigned int i;
268b298f059SPaul Elder 	int pos = 0;
269b298f059SPaul Elder 
270b298f059SPaul Elder 	if (code->pad == RKISP1_CSI_PAD_SRC) {
271b298f059SPaul Elder 		const struct v4l2_mbus_framefmt *sink_fmt;
272b298f059SPaul Elder 
273b298f059SPaul Elder 		if (code->index)
274b298f059SPaul Elder 			return -EINVAL;
275b298f059SPaul Elder 
276b298f059SPaul Elder 		mutex_lock(&csi->lock);
277b298f059SPaul Elder 
278b298f059SPaul Elder 		sink_fmt = rkisp1_csi_get_pad_fmt(csi, sd_state,
279b298f059SPaul Elder 						  RKISP1_CSI_PAD_SINK,
280b298f059SPaul Elder 						  code->which);
281b298f059SPaul Elder 		code->code = sink_fmt->code;
282b298f059SPaul Elder 
283b298f059SPaul Elder 		mutex_unlock(&csi->lock);
284b298f059SPaul Elder 
285b298f059SPaul Elder 		return 0;
286b298f059SPaul Elder 	}
287b298f059SPaul Elder 
288b298f059SPaul Elder 	for (i = 0; ; i++) {
289b298f059SPaul Elder 		const struct rkisp1_mbus_info *fmt =
290b298f059SPaul Elder 			rkisp1_mbus_info_get_by_index(i);
291b298f059SPaul Elder 
292b298f059SPaul Elder 		if (!fmt)
293b298f059SPaul Elder 			return -EINVAL;
294b298f059SPaul Elder 
295b298f059SPaul Elder 		if (!(fmt->direction & RKISP1_ISP_SD_SINK))
296b298f059SPaul Elder 			continue;
297b298f059SPaul Elder 
298b298f059SPaul Elder 		if (code->index == pos) {
299b298f059SPaul Elder 			code->code = fmt->mbus_code;
300b298f059SPaul Elder 			return 0;
301b298f059SPaul Elder 		}
302b298f059SPaul Elder 
303b298f059SPaul Elder 		pos++;
304b298f059SPaul Elder 	}
305b298f059SPaul Elder 
306b298f059SPaul Elder 	return -EINVAL;
307b298f059SPaul Elder }
308b298f059SPaul Elder 
rkisp1_csi_init_config(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state)309b298f059SPaul Elder static int rkisp1_csi_init_config(struct v4l2_subdev *sd,
310b298f059SPaul Elder 				  struct v4l2_subdev_state *sd_state)
311b298f059SPaul Elder {
312b298f059SPaul Elder 	struct v4l2_mbus_framefmt *sink_fmt, *src_fmt;
313b298f059SPaul Elder 
314b298f059SPaul Elder 	sink_fmt = v4l2_subdev_get_try_format(sd, sd_state,
315b298f059SPaul Elder 					      RKISP1_CSI_PAD_SINK);
316b298f059SPaul Elder 	src_fmt = v4l2_subdev_get_try_format(sd, sd_state,
317b298f059SPaul Elder 					     RKISP1_CSI_PAD_SRC);
318b298f059SPaul Elder 
319b298f059SPaul Elder 	sink_fmt->width = RKISP1_DEFAULT_WIDTH;
320b298f059SPaul Elder 	sink_fmt->height = RKISP1_DEFAULT_HEIGHT;
321b298f059SPaul Elder 	sink_fmt->field = V4L2_FIELD_NONE;
322b298f059SPaul Elder 	sink_fmt->code = RKISP1_CSI_DEF_FMT;
323b298f059SPaul Elder 
324b298f059SPaul Elder 	*src_fmt = *sink_fmt;
325b298f059SPaul Elder 
326b298f059SPaul Elder 	return 0;
327b298f059SPaul Elder }
328b298f059SPaul Elder 
rkisp1_csi_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)329b298f059SPaul Elder static int rkisp1_csi_get_fmt(struct v4l2_subdev *sd,
330b298f059SPaul Elder 			      struct v4l2_subdev_state *sd_state,
331b298f059SPaul Elder 			      struct v4l2_subdev_format *fmt)
332b298f059SPaul Elder {
333b298f059SPaul Elder 	struct rkisp1_csi *csi = to_rkisp1_csi(sd);
334b298f059SPaul Elder 
335b298f059SPaul Elder 	mutex_lock(&csi->lock);
336b298f059SPaul Elder 	fmt->format = *rkisp1_csi_get_pad_fmt(csi, sd_state, fmt->pad,
337b298f059SPaul Elder 					      fmt->which);
338b298f059SPaul Elder 	mutex_unlock(&csi->lock);
339b298f059SPaul Elder 
340b298f059SPaul Elder 	return 0;
341b298f059SPaul Elder }
342b298f059SPaul Elder 
rkisp1_csi_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)343b298f059SPaul Elder static int rkisp1_csi_set_fmt(struct v4l2_subdev *sd,
344b298f059SPaul Elder 			      struct v4l2_subdev_state *sd_state,
345b298f059SPaul Elder 			      struct v4l2_subdev_format *fmt)
346b298f059SPaul Elder {
347b298f059SPaul Elder 	struct rkisp1_csi *csi = to_rkisp1_csi(sd);
348b298f059SPaul Elder 	const struct rkisp1_mbus_info *mbus_info;
349b298f059SPaul Elder 	struct v4l2_mbus_framefmt *sink_fmt, *src_fmt;
350b298f059SPaul Elder 
351b298f059SPaul Elder 	/* The format on the source pad always matches the sink pad. */
352b298f059SPaul Elder 	if (fmt->pad == RKISP1_CSI_PAD_SRC)
353b298f059SPaul Elder 		return rkisp1_csi_get_fmt(sd, sd_state, fmt);
354b298f059SPaul Elder 
355b298f059SPaul Elder 	mutex_lock(&csi->lock);
356b298f059SPaul Elder 
357b298f059SPaul Elder 	sink_fmt = rkisp1_csi_get_pad_fmt(csi, sd_state, RKISP1_CSI_PAD_SINK,
358b298f059SPaul Elder 					  fmt->which);
359b298f059SPaul Elder 
360b298f059SPaul Elder 	sink_fmt->code = fmt->format.code;
361b298f059SPaul Elder 
362b298f059SPaul Elder 	mbus_info = rkisp1_mbus_info_get_by_code(sink_fmt->code);
363b298f059SPaul Elder 	if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SINK)) {
364b298f059SPaul Elder 		sink_fmt->code = RKISP1_CSI_DEF_FMT;
365b298f059SPaul Elder 		mbus_info = rkisp1_mbus_info_get_by_code(sink_fmt->code);
366b298f059SPaul Elder 	}
367b298f059SPaul Elder 
368b298f059SPaul Elder 	sink_fmt->width = clamp_t(u32, fmt->format.width,
369b298f059SPaul Elder 				  RKISP1_ISP_MIN_WIDTH,
370b298f059SPaul Elder 				  RKISP1_ISP_MAX_WIDTH);
371b298f059SPaul Elder 	sink_fmt->height = clamp_t(u32, fmt->format.height,
372b298f059SPaul Elder 				   RKISP1_ISP_MIN_HEIGHT,
373b298f059SPaul Elder 				   RKISP1_ISP_MAX_HEIGHT);
374b298f059SPaul Elder 
375b298f059SPaul Elder 	fmt->format = *sink_fmt;
376b298f059SPaul Elder 
377b298f059SPaul Elder 	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
378b298f059SPaul Elder 		csi->sink_fmt = mbus_info;
379b298f059SPaul Elder 
380b298f059SPaul Elder 	/* Propagate the format to the source pad. */
381b298f059SPaul Elder 	src_fmt = rkisp1_csi_get_pad_fmt(csi, sd_state, RKISP1_CSI_PAD_SRC,
382b298f059SPaul Elder 					 fmt->which);
383b298f059SPaul Elder 	*src_fmt = *sink_fmt;
384b298f059SPaul Elder 
385b298f059SPaul Elder 	mutex_unlock(&csi->lock);
386b298f059SPaul Elder 
387b298f059SPaul Elder 	return 0;
388b298f059SPaul Elder }
389b298f059SPaul Elder 
390b298f059SPaul Elder /* ----------------------------------------------------------------------------
391b298f059SPaul Elder  * Subdev video operations
392b298f059SPaul Elder  */
393b298f059SPaul Elder 
rkisp1_csi_s_stream(struct v4l2_subdev * sd,int enable)394b298f059SPaul Elder static int rkisp1_csi_s_stream(struct v4l2_subdev *sd, int enable)
395b298f059SPaul Elder {
396b298f059SPaul Elder 	struct rkisp1_csi *csi = to_rkisp1_csi(sd);
397b298f059SPaul Elder 	struct rkisp1_device *rkisp1 = csi->rkisp1;
398b298f059SPaul Elder 	struct rkisp1_sensor_async *source_asd;
399c91fd7b7SSakari Ailus 	struct v4l2_async_connection *asc;
400b298f059SPaul Elder 	struct media_pad *source_pad;
401b298f059SPaul Elder 	struct v4l2_subdev *source;
402b298f059SPaul Elder 	int ret;
403b298f059SPaul Elder 
404b298f059SPaul Elder 	if (!enable) {
405b298f059SPaul Elder 		v4l2_subdev_call(csi->source, video, s_stream, false);
406b298f059SPaul Elder 
407b298f059SPaul Elder 		rkisp1_csi_stop(csi);
408b298f059SPaul Elder 
409b298f059SPaul Elder 		return 0;
410b298f059SPaul Elder 	}
411b298f059SPaul Elder 
412b298f059SPaul Elder 	source_pad = media_entity_remote_source_pad_unique(&sd->entity);
413b298f059SPaul Elder 	if (IS_ERR(source_pad)) {
414b298f059SPaul Elder 		dev_dbg(rkisp1->dev, "Failed to get source for CSI: %ld\n",
415b298f059SPaul Elder 			PTR_ERR(source_pad));
416b298f059SPaul Elder 		return -EPIPE;
417b298f059SPaul Elder 	}
418b298f059SPaul Elder 
419b298f059SPaul Elder 	source = media_entity_to_v4l2_subdev(source_pad->entity);
420b298f059SPaul Elder 	if (!source) {
421b298f059SPaul Elder 		/* This should really not happen, so is not worth a message. */
422b298f059SPaul Elder 		return -EPIPE;
423b298f059SPaul Elder 	}
424b298f059SPaul Elder 
425c91fd7b7SSakari Ailus 	asc = v4l2_async_connection_unique(source);
426c91fd7b7SSakari Ailus 	if (!asc)
427c91fd7b7SSakari Ailus 		return -EPIPE;
428c91fd7b7SSakari Ailus 
429c91fd7b7SSakari Ailus 	source_asd = container_of(asc, struct rkisp1_sensor_async, asd);
430b298f059SPaul Elder 	if (source_asd->mbus_type != V4L2_MBUS_CSI2_DPHY)
431b298f059SPaul Elder 		return -EINVAL;
432b298f059SPaul Elder 
433b298f059SPaul Elder 	mutex_lock(&csi->lock);
434b298f059SPaul Elder 	ret = rkisp1_csi_start(csi, source_asd);
435b298f059SPaul Elder 	mutex_unlock(&csi->lock);
436b298f059SPaul Elder 	if (ret)
437b298f059SPaul Elder 		return ret;
438b298f059SPaul Elder 
439b298f059SPaul Elder 	ret = v4l2_subdev_call(source, video, s_stream, true);
440b298f059SPaul Elder 	if (ret) {
441b298f059SPaul Elder 		rkisp1_csi_stop(csi);
442b298f059SPaul Elder 		return ret;
443b298f059SPaul Elder 	}
444b298f059SPaul Elder 
445b298f059SPaul Elder 	csi->source = source;
446b298f059SPaul Elder 
447b298f059SPaul Elder 	return 0;
448b298f059SPaul Elder }
449b298f059SPaul Elder 
450b298f059SPaul Elder /* ----------------------------------------------------------------------------
451b298f059SPaul Elder  * Registration
452b298f059SPaul Elder  */
453b298f059SPaul Elder 
454b298f059SPaul Elder static const struct media_entity_operations rkisp1_csi_media_ops = {
455b298f059SPaul Elder 	.link_validate = v4l2_subdev_link_validate,
456b298f059SPaul Elder };
457b298f059SPaul Elder 
458b298f059SPaul Elder static const struct v4l2_subdev_video_ops rkisp1_csi_video_ops = {
459b298f059SPaul Elder 	.s_stream = rkisp1_csi_s_stream,
460b298f059SPaul Elder };
461b298f059SPaul Elder 
462b298f059SPaul Elder static const struct v4l2_subdev_pad_ops rkisp1_csi_pad_ops = {
463b298f059SPaul Elder 	.enum_mbus_code = rkisp1_csi_enum_mbus_code,
464b298f059SPaul Elder 	.init_cfg = rkisp1_csi_init_config,
465b298f059SPaul Elder 	.get_fmt = rkisp1_csi_get_fmt,
466b298f059SPaul Elder 	.set_fmt = rkisp1_csi_set_fmt,
467b298f059SPaul Elder };
468b298f059SPaul Elder 
469b298f059SPaul Elder static const struct v4l2_subdev_ops rkisp1_csi_ops = {
470b298f059SPaul Elder 	.video = &rkisp1_csi_video_ops,
471b298f059SPaul Elder 	.pad = &rkisp1_csi_pad_ops,
472b298f059SPaul Elder };
473b298f059SPaul Elder 
rkisp1_csi_register(struct rkisp1_device * rkisp1)474b298f059SPaul Elder int rkisp1_csi_register(struct rkisp1_device *rkisp1)
475b298f059SPaul Elder {
476b298f059SPaul Elder 	struct rkisp1_csi *csi = &rkisp1->csi;
477b298f059SPaul Elder 	struct v4l2_subdev_state state = {};
478b298f059SPaul Elder 	struct media_pad *pads;
479b298f059SPaul Elder 	struct v4l2_subdev *sd;
480b298f059SPaul Elder 	int ret;
481b298f059SPaul Elder 
482b298f059SPaul Elder 	csi->rkisp1 = rkisp1;
483b298f059SPaul Elder 	mutex_init(&csi->lock);
484b298f059SPaul Elder 
485b298f059SPaul Elder 	sd = &csi->sd;
486b298f059SPaul Elder 	v4l2_subdev_init(sd, &rkisp1_csi_ops);
487b298f059SPaul Elder 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
488b298f059SPaul Elder 	sd->entity.ops = &rkisp1_csi_media_ops;
489b298f059SPaul Elder 	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
490b298f059SPaul Elder 	sd->owner = THIS_MODULE;
491b298f059SPaul Elder 	strscpy(sd->name, RKISP1_CSI_DEV_NAME, sizeof(sd->name));
492b298f059SPaul Elder 
493b298f059SPaul Elder 	pads = csi->pads;
494b298f059SPaul Elder 	pads[RKISP1_CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK |
495b298f059SPaul Elder 					  MEDIA_PAD_FL_MUST_CONNECT;
496b298f059SPaul Elder 	pads[RKISP1_CSI_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE |
497b298f059SPaul Elder 					 MEDIA_PAD_FL_MUST_CONNECT;
498b298f059SPaul Elder 
499b298f059SPaul Elder 	csi->sink_fmt = rkisp1_mbus_info_get_by_code(RKISP1_CSI_DEF_FMT);
500b298f059SPaul Elder 
501b298f059SPaul Elder 	ret = media_entity_pads_init(&sd->entity, RKISP1_CSI_PAD_NUM, pads);
502b298f059SPaul Elder 	if (ret)
503b298f059SPaul Elder 		goto error;
504b298f059SPaul Elder 
505b298f059SPaul Elder 	state.pads = csi->pad_cfg;
506b298f059SPaul Elder 	rkisp1_csi_init_config(sd, &state);
507b298f059SPaul Elder 
508b298f059SPaul Elder 	ret = v4l2_device_register_subdev(&csi->rkisp1->v4l2_dev, sd);
509b298f059SPaul Elder 	if (ret) {
510b298f059SPaul Elder 		dev_err(sd->dev, "Failed to register csi receiver subdev\n");
511b298f059SPaul Elder 		goto error;
512b298f059SPaul Elder 	}
513b298f059SPaul Elder 
514b298f059SPaul Elder 	return 0;
515b298f059SPaul Elder 
516b298f059SPaul Elder error:
517b298f059SPaul Elder 	media_entity_cleanup(&sd->entity);
518b298f059SPaul Elder 	mutex_destroy(&csi->lock);
519b298f059SPaul Elder 	csi->rkisp1 = NULL;
520b298f059SPaul Elder 	return ret;
521b298f059SPaul Elder }
522b298f059SPaul Elder 
rkisp1_csi_unregister(struct rkisp1_device * rkisp1)523b298f059SPaul Elder void rkisp1_csi_unregister(struct rkisp1_device *rkisp1)
524b298f059SPaul Elder {
525b298f059SPaul Elder 	struct rkisp1_csi *csi = &rkisp1->csi;
526b298f059SPaul Elder 
527b298f059SPaul Elder 	if (!csi->rkisp1)
528b298f059SPaul Elder 		return;
529b298f059SPaul Elder 
530b298f059SPaul Elder 	v4l2_device_unregister_subdev(&csi->sd);
531b298f059SPaul Elder 	media_entity_cleanup(&csi->sd.entity);
532b298f059SPaul Elder 	mutex_destroy(&csi->lock);
533b298f059SPaul Elder }
534b298f059SPaul Elder 
rkisp1_csi_init(struct rkisp1_device * rkisp1)5358082e2f4SPaul Elder int rkisp1_csi_init(struct rkisp1_device *rkisp1)
5368082e2f4SPaul Elder {
5378082e2f4SPaul Elder 	struct rkisp1_csi *csi = &rkisp1->csi;
5388082e2f4SPaul Elder 
5398082e2f4SPaul Elder 	csi->rkisp1 = rkisp1;
5408082e2f4SPaul Elder 
5418082e2f4SPaul Elder 	csi->dphy = devm_phy_get(rkisp1->dev, "dphy");
5428082e2f4SPaul Elder 	if (IS_ERR(csi->dphy))
5438082e2f4SPaul Elder 		return dev_err_probe(rkisp1->dev, PTR_ERR(csi->dphy),
5448082e2f4SPaul Elder 				     "Couldn't get the MIPI D-PHY\n");
5458082e2f4SPaul Elder 
5468082e2f4SPaul Elder 	phy_init(csi->dphy);
5478082e2f4SPaul Elder 
5488082e2f4SPaul Elder 	return 0;
5498082e2f4SPaul Elder }
5508082e2f4SPaul Elder 
rkisp1_csi_cleanup(struct rkisp1_device * rkisp1)5518082e2f4SPaul Elder void rkisp1_csi_cleanup(struct rkisp1_device *rkisp1)
5528082e2f4SPaul Elder {
5538082e2f4SPaul Elder 	struct rkisp1_csi *csi = &rkisp1->csi;
5548082e2f4SPaul Elder 
5558082e2f4SPaul Elder 	phy_exit(csi->dphy);
5568082e2f4SPaul Elder }
557