162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Rockchip ISP1 Driver - CSI-2 Receiver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2019 Collabora, Ltd.
662306a36Sopenharmony_ci * Copyright (C) 2022 Ideas on Board
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd.
962306a36Sopenharmony_ci * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/delay.h>
1362306a36Sopenharmony_ci#include <linux/device.h>
1462306a36Sopenharmony_ci#include <linux/lockdep.h>
1562306a36Sopenharmony_ci#include <linux/phy/phy.h>
1662306a36Sopenharmony_ci#include <linux/phy/phy-mipi-dphy.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <media/v4l2-ctrls.h>
1962306a36Sopenharmony_ci#include <media/v4l2-fwnode.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include "rkisp1-common.h"
2262306a36Sopenharmony_ci#include "rkisp1-csi.h"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define RKISP1_CSI_DEV_NAME	RKISP1_DRIVER_NAME "_csi"
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define RKISP1_CSI_DEF_FMT	MEDIA_BUS_FMT_SRGGB10_1X10
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic inline struct rkisp1_csi *to_rkisp1_csi(struct v4l2_subdev *sd)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	return container_of(sd, struct rkisp1_csi, sd);
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistatic struct v4l2_mbus_framefmt *
3462306a36Sopenharmony_cirkisp1_csi_get_pad_fmt(struct rkisp1_csi *csi,
3562306a36Sopenharmony_ci		       struct v4l2_subdev_state *sd_state,
3662306a36Sopenharmony_ci		       unsigned int pad, u32 which)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	struct v4l2_subdev_state state = {
3962306a36Sopenharmony_ci		.pads = csi->pad_cfg
4062306a36Sopenharmony_ci	};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	lockdep_assert_held(&csi->lock);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	if (which == V4L2_SUBDEV_FORMAT_TRY)
4562306a36Sopenharmony_ci		return v4l2_subdev_get_try_format(&csi->sd, sd_state, pad);
4662306a36Sopenharmony_ci	else
4762306a36Sopenharmony_ci		return v4l2_subdev_get_try_format(&csi->sd, &state, pad);
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ciint rkisp1_csi_link_sensor(struct rkisp1_device *rkisp1, struct v4l2_subdev *sd,
5162306a36Sopenharmony_ci			   struct rkisp1_sensor_async *s_asd,
5262306a36Sopenharmony_ci			   unsigned int source_pad)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	struct rkisp1_csi *csi = &rkisp1->csi;
5562306a36Sopenharmony_ci	int ret;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler,
5862306a36Sopenharmony_ci						V4L2_CID_PIXEL_RATE);
5962306a36Sopenharmony_ci	if (!s_asd->pixel_rate_ctrl) {
6062306a36Sopenharmony_ci		dev_err(rkisp1->dev, "No pixel rate control in subdev %s\n",
6162306a36Sopenharmony_ci			sd->name);
6262306a36Sopenharmony_ci		return -EINVAL;
6362306a36Sopenharmony_ci	}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	/* Create the link from the sensor to the CSI receiver. */
6662306a36Sopenharmony_ci	ret = media_create_pad_link(&sd->entity, source_pad,
6762306a36Sopenharmony_ci				    &csi->sd.entity, RKISP1_CSI_PAD_SINK,
6862306a36Sopenharmony_ci				    !s_asd->index ? MEDIA_LNK_FL_ENABLED : 0);
6962306a36Sopenharmony_ci	if (ret) {
7062306a36Sopenharmony_ci		dev_err(csi->rkisp1->dev, "failed to link src pad of %s\n",
7162306a36Sopenharmony_ci			sd->name);
7262306a36Sopenharmony_ci		return ret;
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	return 0;
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic int rkisp1_csi_config(struct rkisp1_csi *csi,
7962306a36Sopenharmony_ci			     const struct rkisp1_sensor_async *sensor)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	struct rkisp1_device *rkisp1 = csi->rkisp1;
8262306a36Sopenharmony_ci	unsigned int lanes = sensor->lanes;
8362306a36Sopenharmony_ci	u32 mipi_ctrl;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	if (lanes < 1 || lanes > 4)
8662306a36Sopenharmony_ci		return -EINVAL;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	mipi_ctrl = RKISP1_CIF_MIPI_CTRL_NUM_LANES(lanes - 1) |
8962306a36Sopenharmony_ci		    RKISP1_CIF_MIPI_CTRL_SHUTDOWNLANES(0xf) |
9062306a36Sopenharmony_ci		    RKISP1_CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP |
9162306a36Sopenharmony_ci		    RKISP1_CIF_MIPI_CTRL_CLOCKLANE_ENA;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_CTRL, mipi_ctrl);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	/* V12 could also use a newer csi2-host, but we don't want that yet */
9662306a36Sopenharmony_ci	if (rkisp1->info->isp_ver == RKISP1_V12)
9762306a36Sopenharmony_ci		rkisp1_write(rkisp1, RKISP1_CIF_ISP_CSI0_CTRL0, 0);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	/* Configure Data Type and Virtual Channel */
10062306a36Sopenharmony_ci	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMG_DATA_SEL,
10162306a36Sopenharmony_ci		     RKISP1_CIF_MIPI_DATA_SEL_DT(csi->sink_fmt->mipi_dt) |
10262306a36Sopenharmony_ci		     RKISP1_CIF_MIPI_DATA_SEL_VC(0));
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	/* Clear MIPI interrupts */
10562306a36Sopenharmony_ci	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_ICR, ~0);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	/*
10862306a36Sopenharmony_ci	 * Disable RKISP1_CIF_MIPI_ERR_DPHY interrupt here temporary for
10962306a36Sopenharmony_ci	 * isp bus may be dead when switch isp.
11062306a36Sopenharmony_ci	 */
11162306a36Sopenharmony_ci	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC,
11262306a36Sopenharmony_ci		     RKISP1_CIF_MIPI_FRAME_END | RKISP1_CIF_MIPI_ERR_CSI |
11362306a36Sopenharmony_ci		     RKISP1_CIF_MIPI_ERR_DPHY |
11462306a36Sopenharmony_ci		     RKISP1_CIF_MIPI_SYNC_FIFO_OVFLW(0x03) |
11562306a36Sopenharmony_ci		     RKISP1_CIF_MIPI_ADD_DATA_OVFLW);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	dev_dbg(rkisp1->dev, "\n  MIPI_CTRL 0x%08x\n"
11862306a36Sopenharmony_ci		"  MIPI_IMG_DATA_SEL 0x%08x\n"
11962306a36Sopenharmony_ci		"  MIPI_STATUS 0x%08x\n"
12062306a36Sopenharmony_ci		"  MIPI_IMSC 0x%08x\n",
12162306a36Sopenharmony_ci		rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL),
12262306a36Sopenharmony_ci		rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMG_DATA_SEL),
12362306a36Sopenharmony_ci		rkisp1_read(rkisp1, RKISP1_CIF_MIPI_STATUS),
12462306a36Sopenharmony_ci		rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC));
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	return 0;
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic void rkisp1_csi_enable(struct rkisp1_csi *csi)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	struct rkisp1_device *rkisp1 = csi->rkisp1;
13262306a36Sopenharmony_ci	u32 val;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL);
13562306a36Sopenharmony_ci	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_CTRL,
13662306a36Sopenharmony_ci		     val | RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA);
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic void rkisp1_csi_disable(struct rkisp1_csi *csi)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	struct rkisp1_device *rkisp1 = csi->rkisp1;
14262306a36Sopenharmony_ci	u32 val;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	/* Mask MIPI interrupts. */
14562306a36Sopenharmony_ci	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC, 0);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	/* Flush posted writes */
14862306a36Sopenharmony_ci	rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	/*
15162306a36Sopenharmony_ci	 * Wait until the IRQ handler has ended. The IRQ handler may get called
15262306a36Sopenharmony_ci	 * even after this, but it will return immediately as the MIPI
15362306a36Sopenharmony_ci	 * interrupts have been masked.
15462306a36Sopenharmony_ci	 */
15562306a36Sopenharmony_ci	synchronize_irq(rkisp1->irqs[RKISP1_IRQ_MIPI]);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	/* Clear MIPI interrupt status */
15862306a36Sopenharmony_ci	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_ICR, ~0);
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL);
16162306a36Sopenharmony_ci	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_CTRL,
16262306a36Sopenharmony_ci		     val & (~RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA));
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic int rkisp1_csi_start(struct rkisp1_csi *csi,
16662306a36Sopenharmony_ci			    const struct rkisp1_sensor_async *sensor)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	struct rkisp1_device *rkisp1 = csi->rkisp1;
16962306a36Sopenharmony_ci	union phy_configure_opts opts;
17062306a36Sopenharmony_ci	struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
17162306a36Sopenharmony_ci	s64 pixel_clock;
17262306a36Sopenharmony_ci	int ret;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	ret = rkisp1_csi_config(csi, sensor);
17562306a36Sopenharmony_ci	if (ret)
17662306a36Sopenharmony_ci		return ret;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	pixel_clock = v4l2_ctrl_g_ctrl_int64(sensor->pixel_rate_ctrl);
17962306a36Sopenharmony_ci	if (!pixel_clock) {
18062306a36Sopenharmony_ci		dev_err(rkisp1->dev, "Invalid pixel rate value\n");
18162306a36Sopenharmony_ci		return -EINVAL;
18262306a36Sopenharmony_ci	}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	phy_mipi_dphy_get_default_config(pixel_clock, csi->sink_fmt->bus_width,
18562306a36Sopenharmony_ci					 sensor->lanes, cfg);
18662306a36Sopenharmony_ci	phy_set_mode(csi->dphy, PHY_MODE_MIPI_DPHY);
18762306a36Sopenharmony_ci	phy_configure(csi->dphy, &opts);
18862306a36Sopenharmony_ci	phy_power_on(csi->dphy);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	rkisp1_csi_enable(csi);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	/*
19362306a36Sopenharmony_ci	 * CIF spec says to wait for sufficient time after enabling
19462306a36Sopenharmony_ci	 * the MIPI interface and before starting the sensor output.
19562306a36Sopenharmony_ci	 */
19662306a36Sopenharmony_ci	usleep_range(1000, 1200);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	return 0;
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic void rkisp1_csi_stop(struct rkisp1_csi *csi)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	rkisp1_csi_disable(csi);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	phy_power_off(csi->dphy);
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ciirqreturn_t rkisp1_csi_isr(int irq, void *ctx)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	struct device *dev = ctx;
21162306a36Sopenharmony_ci	struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
21262306a36Sopenharmony_ci	u32 val, status;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	if (!rkisp1->irqs_enabled)
21562306a36Sopenharmony_ci		return IRQ_NONE;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	status = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_MIS);
21862306a36Sopenharmony_ci	if (!status)
21962306a36Sopenharmony_ci		return IRQ_NONE;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	rkisp1_write(rkisp1, RKISP1_CIF_MIPI_ICR, status);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	/*
22462306a36Sopenharmony_ci	 * Disable DPHY errctrl interrupt, because this dphy
22562306a36Sopenharmony_ci	 * erctrl signal is asserted until the next changes
22662306a36Sopenharmony_ci	 * of line state. This time is may be too long and cpu
22762306a36Sopenharmony_ci	 * is hold in this interrupt.
22862306a36Sopenharmony_ci	 */
22962306a36Sopenharmony_ci	if (status & RKISP1_CIF_MIPI_ERR_CTRL(0x0f)) {
23062306a36Sopenharmony_ci		val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC);
23162306a36Sopenharmony_ci		rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC,
23262306a36Sopenharmony_ci			     val & ~RKISP1_CIF_MIPI_ERR_CTRL(0x0f));
23362306a36Sopenharmony_ci		rkisp1->csi.is_dphy_errctrl_disabled = true;
23462306a36Sopenharmony_ci	}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	/*
23762306a36Sopenharmony_ci	 * Enable DPHY errctrl interrupt again, if mipi have receive
23862306a36Sopenharmony_ci	 * the whole frame without any error.
23962306a36Sopenharmony_ci	 */
24062306a36Sopenharmony_ci	if (status == RKISP1_CIF_MIPI_FRAME_END) {
24162306a36Sopenharmony_ci		/*
24262306a36Sopenharmony_ci		 * Enable DPHY errctrl interrupt again, if mipi have receive
24362306a36Sopenharmony_ci		 * the whole frame without any error.
24462306a36Sopenharmony_ci		 */
24562306a36Sopenharmony_ci		if (rkisp1->csi.is_dphy_errctrl_disabled) {
24662306a36Sopenharmony_ci			val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC);
24762306a36Sopenharmony_ci			val |= RKISP1_CIF_MIPI_ERR_CTRL(0x0f);
24862306a36Sopenharmony_ci			rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC, val);
24962306a36Sopenharmony_ci			rkisp1->csi.is_dphy_errctrl_disabled = false;
25062306a36Sopenharmony_ci		}
25162306a36Sopenharmony_ci	} else {
25262306a36Sopenharmony_ci		rkisp1->debug.mipi_error++;
25362306a36Sopenharmony_ci	}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	return IRQ_HANDLED;
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci/* ----------------------------------------------------------------------------
25962306a36Sopenharmony_ci * Subdev pad operations
26062306a36Sopenharmony_ci */
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_cistatic int rkisp1_csi_enum_mbus_code(struct v4l2_subdev *sd,
26362306a36Sopenharmony_ci				     struct v4l2_subdev_state *sd_state,
26462306a36Sopenharmony_ci				     struct v4l2_subdev_mbus_code_enum *code)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	struct rkisp1_csi *csi = to_rkisp1_csi(sd);
26762306a36Sopenharmony_ci	unsigned int i;
26862306a36Sopenharmony_ci	int pos = 0;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	if (code->pad == RKISP1_CSI_PAD_SRC) {
27162306a36Sopenharmony_ci		const struct v4l2_mbus_framefmt *sink_fmt;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci		if (code->index)
27462306a36Sopenharmony_ci			return -EINVAL;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci		mutex_lock(&csi->lock);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci		sink_fmt = rkisp1_csi_get_pad_fmt(csi, sd_state,
27962306a36Sopenharmony_ci						  RKISP1_CSI_PAD_SINK,
28062306a36Sopenharmony_ci						  code->which);
28162306a36Sopenharmony_ci		code->code = sink_fmt->code;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci		mutex_unlock(&csi->lock);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci		return 0;
28662306a36Sopenharmony_ci	}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	for (i = 0; ; i++) {
28962306a36Sopenharmony_ci		const struct rkisp1_mbus_info *fmt =
29062306a36Sopenharmony_ci			rkisp1_mbus_info_get_by_index(i);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci		if (!fmt)
29362306a36Sopenharmony_ci			return -EINVAL;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci		if (!(fmt->direction & RKISP1_ISP_SD_SINK))
29662306a36Sopenharmony_ci			continue;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci		if (code->index == pos) {
29962306a36Sopenharmony_ci			code->code = fmt->mbus_code;
30062306a36Sopenharmony_ci			return 0;
30162306a36Sopenharmony_ci		}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci		pos++;
30462306a36Sopenharmony_ci	}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	return -EINVAL;
30762306a36Sopenharmony_ci}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_cistatic int rkisp1_csi_init_config(struct v4l2_subdev *sd,
31062306a36Sopenharmony_ci				  struct v4l2_subdev_state *sd_state)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	struct v4l2_mbus_framefmt *sink_fmt, *src_fmt;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	sink_fmt = v4l2_subdev_get_try_format(sd, sd_state,
31562306a36Sopenharmony_ci					      RKISP1_CSI_PAD_SINK);
31662306a36Sopenharmony_ci	src_fmt = v4l2_subdev_get_try_format(sd, sd_state,
31762306a36Sopenharmony_ci					     RKISP1_CSI_PAD_SRC);
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	sink_fmt->width = RKISP1_DEFAULT_WIDTH;
32062306a36Sopenharmony_ci	sink_fmt->height = RKISP1_DEFAULT_HEIGHT;
32162306a36Sopenharmony_ci	sink_fmt->field = V4L2_FIELD_NONE;
32262306a36Sopenharmony_ci	sink_fmt->code = RKISP1_CSI_DEF_FMT;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	*src_fmt = *sink_fmt;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	return 0;
32762306a36Sopenharmony_ci}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_cistatic int rkisp1_csi_get_fmt(struct v4l2_subdev *sd,
33062306a36Sopenharmony_ci			      struct v4l2_subdev_state *sd_state,
33162306a36Sopenharmony_ci			      struct v4l2_subdev_format *fmt)
33262306a36Sopenharmony_ci{
33362306a36Sopenharmony_ci	struct rkisp1_csi *csi = to_rkisp1_csi(sd);
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	mutex_lock(&csi->lock);
33662306a36Sopenharmony_ci	fmt->format = *rkisp1_csi_get_pad_fmt(csi, sd_state, fmt->pad,
33762306a36Sopenharmony_ci					      fmt->which);
33862306a36Sopenharmony_ci	mutex_unlock(&csi->lock);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	return 0;
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic int rkisp1_csi_set_fmt(struct v4l2_subdev *sd,
34462306a36Sopenharmony_ci			      struct v4l2_subdev_state *sd_state,
34562306a36Sopenharmony_ci			      struct v4l2_subdev_format *fmt)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	struct rkisp1_csi *csi = to_rkisp1_csi(sd);
34862306a36Sopenharmony_ci	const struct rkisp1_mbus_info *mbus_info;
34962306a36Sopenharmony_ci	struct v4l2_mbus_framefmt *sink_fmt, *src_fmt;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	/* The format on the source pad always matches the sink pad. */
35262306a36Sopenharmony_ci	if (fmt->pad == RKISP1_CSI_PAD_SRC)
35362306a36Sopenharmony_ci		return rkisp1_csi_get_fmt(sd, sd_state, fmt);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	mutex_lock(&csi->lock);
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	sink_fmt = rkisp1_csi_get_pad_fmt(csi, sd_state, RKISP1_CSI_PAD_SINK,
35862306a36Sopenharmony_ci					  fmt->which);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	sink_fmt->code = fmt->format.code;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	mbus_info = rkisp1_mbus_info_get_by_code(sink_fmt->code);
36362306a36Sopenharmony_ci	if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SINK)) {
36462306a36Sopenharmony_ci		sink_fmt->code = RKISP1_CSI_DEF_FMT;
36562306a36Sopenharmony_ci		mbus_info = rkisp1_mbus_info_get_by_code(sink_fmt->code);
36662306a36Sopenharmony_ci	}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	sink_fmt->width = clamp_t(u32, fmt->format.width,
36962306a36Sopenharmony_ci				  RKISP1_ISP_MIN_WIDTH,
37062306a36Sopenharmony_ci				  RKISP1_ISP_MAX_WIDTH);
37162306a36Sopenharmony_ci	sink_fmt->height = clamp_t(u32, fmt->format.height,
37262306a36Sopenharmony_ci				   RKISP1_ISP_MIN_HEIGHT,
37362306a36Sopenharmony_ci				   RKISP1_ISP_MAX_HEIGHT);
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	fmt->format = *sink_fmt;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
37862306a36Sopenharmony_ci		csi->sink_fmt = mbus_info;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	/* Propagate the format to the source pad. */
38162306a36Sopenharmony_ci	src_fmt = rkisp1_csi_get_pad_fmt(csi, sd_state, RKISP1_CSI_PAD_SRC,
38262306a36Sopenharmony_ci					 fmt->which);
38362306a36Sopenharmony_ci	*src_fmt = *sink_fmt;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	mutex_unlock(&csi->lock);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	return 0;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci/* ----------------------------------------------------------------------------
39162306a36Sopenharmony_ci * Subdev video operations
39262306a36Sopenharmony_ci */
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_cistatic int rkisp1_csi_s_stream(struct v4l2_subdev *sd, int enable)
39562306a36Sopenharmony_ci{
39662306a36Sopenharmony_ci	struct rkisp1_csi *csi = to_rkisp1_csi(sd);
39762306a36Sopenharmony_ci	struct rkisp1_device *rkisp1 = csi->rkisp1;
39862306a36Sopenharmony_ci	struct rkisp1_sensor_async *source_asd;
39962306a36Sopenharmony_ci	struct v4l2_async_connection *asc;
40062306a36Sopenharmony_ci	struct media_pad *source_pad;
40162306a36Sopenharmony_ci	struct v4l2_subdev *source;
40262306a36Sopenharmony_ci	int ret;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	if (!enable) {
40562306a36Sopenharmony_ci		v4l2_subdev_call(csi->source, video, s_stream, false);
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci		rkisp1_csi_stop(csi);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci		return 0;
41062306a36Sopenharmony_ci	}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	source_pad = media_entity_remote_source_pad_unique(&sd->entity);
41362306a36Sopenharmony_ci	if (IS_ERR(source_pad)) {
41462306a36Sopenharmony_ci		dev_dbg(rkisp1->dev, "Failed to get source for CSI: %ld\n",
41562306a36Sopenharmony_ci			PTR_ERR(source_pad));
41662306a36Sopenharmony_ci		return -EPIPE;
41762306a36Sopenharmony_ci	}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	source = media_entity_to_v4l2_subdev(source_pad->entity);
42062306a36Sopenharmony_ci	if (!source) {
42162306a36Sopenharmony_ci		/* This should really not happen, so is not worth a message. */
42262306a36Sopenharmony_ci		return -EPIPE;
42362306a36Sopenharmony_ci	}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	asc = v4l2_async_connection_unique(source);
42662306a36Sopenharmony_ci	if (!asc)
42762306a36Sopenharmony_ci		return -EPIPE;
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	source_asd = container_of(asc, struct rkisp1_sensor_async, asd);
43062306a36Sopenharmony_ci	if (source_asd->mbus_type != V4L2_MBUS_CSI2_DPHY)
43162306a36Sopenharmony_ci		return -EINVAL;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	mutex_lock(&csi->lock);
43462306a36Sopenharmony_ci	ret = rkisp1_csi_start(csi, source_asd);
43562306a36Sopenharmony_ci	mutex_unlock(&csi->lock);
43662306a36Sopenharmony_ci	if (ret)
43762306a36Sopenharmony_ci		return ret;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	ret = v4l2_subdev_call(source, video, s_stream, true);
44062306a36Sopenharmony_ci	if (ret) {
44162306a36Sopenharmony_ci		rkisp1_csi_stop(csi);
44262306a36Sopenharmony_ci		return ret;
44362306a36Sopenharmony_ci	}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	csi->source = source;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	return 0;
44862306a36Sopenharmony_ci}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci/* ----------------------------------------------------------------------------
45162306a36Sopenharmony_ci * Registration
45262306a36Sopenharmony_ci */
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_cistatic const struct media_entity_operations rkisp1_csi_media_ops = {
45562306a36Sopenharmony_ci	.link_validate = v4l2_subdev_link_validate,
45662306a36Sopenharmony_ci};
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_cistatic const struct v4l2_subdev_video_ops rkisp1_csi_video_ops = {
45962306a36Sopenharmony_ci	.s_stream = rkisp1_csi_s_stream,
46062306a36Sopenharmony_ci};
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cistatic const struct v4l2_subdev_pad_ops rkisp1_csi_pad_ops = {
46362306a36Sopenharmony_ci	.enum_mbus_code = rkisp1_csi_enum_mbus_code,
46462306a36Sopenharmony_ci	.init_cfg = rkisp1_csi_init_config,
46562306a36Sopenharmony_ci	.get_fmt = rkisp1_csi_get_fmt,
46662306a36Sopenharmony_ci	.set_fmt = rkisp1_csi_set_fmt,
46762306a36Sopenharmony_ci};
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_cistatic const struct v4l2_subdev_ops rkisp1_csi_ops = {
47062306a36Sopenharmony_ci	.video = &rkisp1_csi_video_ops,
47162306a36Sopenharmony_ci	.pad = &rkisp1_csi_pad_ops,
47262306a36Sopenharmony_ci};
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ciint rkisp1_csi_register(struct rkisp1_device *rkisp1)
47562306a36Sopenharmony_ci{
47662306a36Sopenharmony_ci	struct rkisp1_csi *csi = &rkisp1->csi;
47762306a36Sopenharmony_ci	struct v4l2_subdev_state state = {};
47862306a36Sopenharmony_ci	struct media_pad *pads;
47962306a36Sopenharmony_ci	struct v4l2_subdev *sd;
48062306a36Sopenharmony_ci	int ret;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	csi->rkisp1 = rkisp1;
48362306a36Sopenharmony_ci	mutex_init(&csi->lock);
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	sd = &csi->sd;
48662306a36Sopenharmony_ci	v4l2_subdev_init(sd, &rkisp1_csi_ops);
48762306a36Sopenharmony_ci	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
48862306a36Sopenharmony_ci	sd->entity.ops = &rkisp1_csi_media_ops;
48962306a36Sopenharmony_ci	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
49062306a36Sopenharmony_ci	sd->owner = THIS_MODULE;
49162306a36Sopenharmony_ci	strscpy(sd->name, RKISP1_CSI_DEV_NAME, sizeof(sd->name));
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	pads = csi->pads;
49462306a36Sopenharmony_ci	pads[RKISP1_CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK |
49562306a36Sopenharmony_ci					  MEDIA_PAD_FL_MUST_CONNECT;
49662306a36Sopenharmony_ci	pads[RKISP1_CSI_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE |
49762306a36Sopenharmony_ci					 MEDIA_PAD_FL_MUST_CONNECT;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	csi->sink_fmt = rkisp1_mbus_info_get_by_code(RKISP1_CSI_DEF_FMT);
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	ret = media_entity_pads_init(&sd->entity, RKISP1_CSI_PAD_NUM, pads);
50262306a36Sopenharmony_ci	if (ret)
50362306a36Sopenharmony_ci		goto error;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	state.pads = csi->pad_cfg;
50662306a36Sopenharmony_ci	rkisp1_csi_init_config(sd, &state);
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	ret = v4l2_device_register_subdev(&csi->rkisp1->v4l2_dev, sd);
50962306a36Sopenharmony_ci	if (ret) {
51062306a36Sopenharmony_ci		dev_err(sd->dev, "Failed to register csi receiver subdev\n");
51162306a36Sopenharmony_ci		goto error;
51262306a36Sopenharmony_ci	}
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	return 0;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_cierror:
51762306a36Sopenharmony_ci	media_entity_cleanup(&sd->entity);
51862306a36Sopenharmony_ci	mutex_destroy(&csi->lock);
51962306a36Sopenharmony_ci	csi->rkisp1 = NULL;
52062306a36Sopenharmony_ci	return ret;
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_civoid rkisp1_csi_unregister(struct rkisp1_device *rkisp1)
52462306a36Sopenharmony_ci{
52562306a36Sopenharmony_ci	struct rkisp1_csi *csi = &rkisp1->csi;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	if (!csi->rkisp1)
52862306a36Sopenharmony_ci		return;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	v4l2_device_unregister_subdev(&csi->sd);
53162306a36Sopenharmony_ci	media_entity_cleanup(&csi->sd.entity);
53262306a36Sopenharmony_ci	mutex_destroy(&csi->lock);
53362306a36Sopenharmony_ci}
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ciint rkisp1_csi_init(struct rkisp1_device *rkisp1)
53662306a36Sopenharmony_ci{
53762306a36Sopenharmony_ci	struct rkisp1_csi *csi = &rkisp1->csi;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	csi->rkisp1 = rkisp1;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	csi->dphy = devm_phy_get(rkisp1->dev, "dphy");
54262306a36Sopenharmony_ci	if (IS_ERR(csi->dphy))
54362306a36Sopenharmony_ci		return dev_err_probe(rkisp1->dev, PTR_ERR(csi->dphy),
54462306a36Sopenharmony_ci				     "Couldn't get the MIPI D-PHY\n");
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	phy_init(csi->dphy);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	return 0;
54962306a36Sopenharmony_ci}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_civoid rkisp1_csi_cleanup(struct rkisp1_device *rkisp1)
55262306a36Sopenharmony_ci{
55362306a36Sopenharmony_ci	struct rkisp1_csi *csi = &rkisp1->csi;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	phy_exit(csi->dphy);
55662306a36Sopenharmony_ci}
557