File Index
Files and directories
Sign in
FILE

imx8mq-mipi-csi2.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/nxp/imx8mq-mipi-csi2.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * NXP i.MX8MQ SoC series MIPI-CSI2 receiver driver
   4 *
   5 * Copyright (C) 2021 Purism SPC
   6 */
   7
   8#include <linux/bitfield.h>
   9#include <linux/clk.h>
  10#include <linux/clk-provider.h>
  11#include <linux/delay.h>
  12#include <linux/errno.h>
  13#include <linux/interconnect.h>
  14#include <linux/interrupt.h>
  15#include <linux/io.h>
  16#include <linux/kernel.h>
  17#include <linux/mfd/syscon.h>
  18#include <linux/module.h>
  19#include <linux/mutex.h>
  20#include <linux/of.h>
  21#include <linux/platform_device.h>
  22#include <linux/pm_runtime.h>
  23#include <linux/regmap.h>
  24#include <linux/regulator/consumer.h>
  25#include <linux/reset.h>
  26#include <linux/spinlock.h>
  27
  28#include <media/v4l2-common.h>
  29#include <media/v4l2-device.h>
  30#include <media/v4l2-fwnode.h>
  31#include <media/v4l2-mc.h>
  32#include <media/v4l2-subdev.h>
  33
  34#define MIPI_CSI2_DRIVER_NAME			"imx8mq-mipi-csi2"
  35#define MIPI_CSI2_SUBDEV_NAME			MIPI_CSI2_DRIVER_NAME
  36
  37#define MIPI_CSI2_PAD_SINK			0
  38#define MIPI_CSI2_PAD_SOURCE			1
  39#define MIPI_CSI2_PADS_NUM			2
  40
  41#define MIPI_CSI2_DEF_PIX_WIDTH			640
  42#define MIPI_CSI2_DEF_PIX_HEIGHT		480
  43
  44/* Register map definition */
  45
  46/* i.MX8MQ CSI-2 controller CSR */
  47#define CSI2RX_CFG_NUM_LANES			0x100
  48#define CSI2RX_CFG_DISABLE_DATA_LANES		0x104
  49#define CSI2RX_BIT_ERR				0x108
  50#define CSI2RX_IRQ_STATUS			0x10c
  51#define CSI2RX_IRQ_MASK				0x110
  52#define CSI2RX_IRQ_MASK_ALL			0x1ff
  53#define CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE	0x8
  54#define CSI2RX_ULPS_STATUS			0x114
  55#define CSI2RX_PPI_ERRSOT_HS			0x118
  56#define CSI2RX_PPI_ERRSOTSYNC_HS		0x11c
  57#define CSI2RX_PPI_ERRESC			0x120
  58#define CSI2RX_PPI_ERRSYNCESC			0x124
  59#define CSI2RX_PPI_ERRCONTROL			0x128
  60#define CSI2RX_CFG_DISABLE_PAYLOAD_0		0x12c
  61#define CSI2RX_CFG_VID_VC_IGNORE		0x180
  62#define CSI2RX_CFG_VID_VC			0x184
  63#define CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL	0x188
  64#define CSI2RX_CFG_DISABLE_PAYLOAD_1		0x130
  65
  66struct csi_state;
  67
  68enum {
  69	ST_POWERED	= 1,
  70	ST_STREAMING	= 2,
  71	ST_SUSPENDED	= 4,
  72};
  73
  74enum imx8mq_mipi_csi_clk {
  75	CSI2_CLK_CORE,
  76	CSI2_CLK_ESC,
  77	CSI2_CLK_UI,
  78	CSI2_NUM_CLKS,
  79};
  80
  81static const char * const imx8mq_mipi_csi_clk_id[CSI2_NUM_CLKS] = {
  82	[CSI2_CLK_CORE] = "core",
  83	[CSI2_CLK_ESC] = "esc",
  84	[CSI2_CLK_UI] = "ui",
  85};
  86
  87#define CSI2_NUM_CLKS	ARRAY_SIZE(imx8mq_mipi_csi_clk_id)
  88
  89struct imx8mq_plat_data {
  90	int (*enable)(struct csi_state *state, u32 hs_settle);
  91	void (*disable)(struct csi_state *state);
  92	bool use_reg_csr;
  93};
  94
  95/*
  96 * The send level configures the number of entries that must accumulate in
  97 * the Pixel FIFO before the data will be transferred to the video output.
  98 * The exact value needed for this configuration is dependent on the rate at
  99 * which the sensor transfers data to the CSI-2 Controller and the user
 100 * video clock.
 101 *
 102 * The calculation is the classical rate-in rate-out type of problem: If the
 103 * video bandwidth is 10% faster than the incoming mipi data and the video
 104 * line length is 500 pixels, then the fifo should be allowed to fill
 105 * 10% of the line length or 50 pixels. If the gap data is ok, then the level
 106 * can be set to 16 and ignored.
 107 */
 108#define CSI2RX_SEND_LEVEL			64
 109
 110struct csi_state {
 111	struct device *dev;
 112	const struct imx8mq_plat_data *pdata;
 113	void __iomem *regs;
 114	struct clk_bulk_data clks[CSI2_NUM_CLKS];
 115	struct reset_control *rst;
 116	struct regulator *mipi_phy_regulator;
 117
 118	struct v4l2_subdev sd;
 119	struct media_pad pads[MIPI_CSI2_PADS_NUM];
 120	struct v4l2_async_notifier notifier;
 121	struct v4l2_subdev *src_sd;
 122
 123	struct v4l2_mbus_config_mipi_csi2 bus;
 124
 125	struct mutex lock; /* Protect state */
 126	u32 state;
 127
 128	struct regmap *phy_gpr;
 129	u8 phy_gpr_reg;
 130
 131	struct icc_path			*icc_path;
 132	s32				icc_path_bw;
 133};
 134
 135/* -----------------------------------------------------------------------------
 136 * Format helpers
 137 */
 138
 139struct csi2_pix_format {
 140	u32 code;
 141	u8 width;
 142};
 143
 144/* -----------------------------------------------------------------------------
 145 * i.MX8MQ GPR
 146 */
 147
 148#define	GPR_CSI2_1_RX_ENABLE		BIT(13)
 149#define	GPR_CSI2_1_VID_INTFC_ENB	BIT(12)
 150#define	GPR_CSI2_1_HSEL			BIT(10)
 151#define	GPR_CSI2_1_CONT_CLK_MODE	BIT(8)
 152#define	GPR_CSI2_1_S_PRG_RXHS_SETTLE(x)	(((x) & 0x3f) << 2)
 153
 154static int imx8mq_gpr_enable(struct csi_state *state, u32 hs_settle)
 155{
 156	regmap_update_bits(state->phy_gpr,
 157			   state->phy_gpr_reg,
 158			   0x3fff,
 159			   GPR_CSI2_1_RX_ENABLE |
 160			   GPR_CSI2_1_VID_INTFC_ENB |
 161			   GPR_CSI2_1_HSEL |
 162			   GPR_CSI2_1_CONT_CLK_MODE |
 163			   GPR_CSI2_1_S_PRG_RXHS_SETTLE(hs_settle));
 164
 165	return 0;
 166}
 167
 168static const struct imx8mq_plat_data imx8mq_data = {
 169	.enable = imx8mq_gpr_enable,
 170};
 171
 172/* -----------------------------------------------------------------------------
 173 * i.MX8QXP
 174 */
 175
 176#define CSI2SS_PL_CLK_INTERVAL_US		100
 177#define CSI2SS_PL_CLK_TIMEOUT_US		100000
 178
 179#define CSI2SS_PLM_CTRL				0x0
 180#define CSI2SS_PLM_CTRL_ENABLE_PL		BIT(0)
 181#define CSI2SS_PLM_CTRL_VSYNC_OVERRIDE		BIT(9)
 182#define CSI2SS_PLM_CTRL_HSYNC_OVERRIDE		BIT(10)
 183#define CSI2SS_PLM_CTRL_VALID_OVERRIDE		BIT(11)
 184#define CSI2SS_PLM_CTRL_POLARITY_HIGH		BIT(12)
 185#define CSI2SS_PLM_CTRL_PL_CLK_RUN		BIT(31)
 186
 187#define CSI2SS_PHY_CTRL				0x4
 188#define CSI2SS_PHY_CTRL_RX_ENABLE		BIT(0)
 189#define CSI2SS_PHY_CTRL_AUTO_PD_EN		BIT(1)
 190#define CSI2SS_PHY_CTRL_DDRCLK_EN		BIT(2)
 191#define CSI2SS_PHY_CTRL_CONT_CLK_MODE		BIT(3)
 192#define CSI2SS_PHY_CTRL_RX_HS_SETTLE_MASK	GENMASK(9, 4)
 193#define CSI2SS_PHY_CTRL_RTERM_SEL		BIT(21)
 194#define CSI2SS_PHY_CTRL_PD			BIT(22)
 195
 196#define CSI2SS_DATA_TYPE_DISABLE_BF		0x38
 197#define CSI2SS_DATA_TYPE_DISABLE_BF_MASK	GENMASK(23, 0)
 198
 199#define CSI2SS_CTRL_CLK_RESET			0x44
 200#define CSI2SS_CTRL_CLK_RESET_EN		BIT(0)
 201
 202static int imx8qxp_gpr_enable(struct csi_state *state, u32 hs_settle)
 203{
 204	int ret;
 205	u32 val;
 206
 207	/* Clear format */
 208	regmap_clear_bits(state->phy_gpr, CSI2SS_DATA_TYPE_DISABLE_BF,
 209			  CSI2SS_DATA_TYPE_DISABLE_BF_MASK);
 210
 211	regmap_write(state->phy_gpr, CSI2SS_PLM_CTRL, 0x0);
 212
 213	regmap_write(state->phy_gpr, CSI2SS_PHY_CTRL,
 214		     FIELD_PREP(CSI2SS_PHY_CTRL_RX_HS_SETTLE_MASK, hs_settle) |
 215		     CSI2SS_PHY_CTRL_RX_ENABLE | CSI2SS_PHY_CTRL_DDRCLK_EN |
 216		     CSI2SS_PHY_CTRL_CONT_CLK_MODE | CSI2SS_PHY_CTRL_PD |
 217		     CSI2SS_PHY_CTRL_RTERM_SEL | CSI2SS_PHY_CTRL_AUTO_PD_EN);
 218
 219	ret = regmap_read_poll_timeout(state->phy_gpr, CSI2SS_PLM_CTRL,
 220				       val, !(val & CSI2SS_PLM_CTRL_PL_CLK_RUN),
 221				       CSI2SS_PL_CLK_INTERVAL_US,
 222				       CSI2SS_PL_CLK_TIMEOUT_US);
 223
 224	if (ret) {
 225		dev_err(state->dev, "Timeout waiting for Pixel-Link clock\n");
 226		return ret;
 227	}
 228
 229	/* Enable Pixel link Master */
 230	regmap_set_bits(state->phy_gpr, CSI2SS_PLM_CTRL,
 231			CSI2SS_PLM_CTRL_ENABLE_PL | CSI2SS_PLM_CTRL_VALID_OVERRIDE);
 232
 233	/* PHY Enable */
 234	regmap_clear_bits(state->phy_gpr, CSI2SS_PHY_CTRL,
 235			  CSI2SS_PHY_CTRL_PD | CSI2SS_PLM_CTRL_POLARITY_HIGH);
 236
 237	/* Release Reset */
 238	regmap_set_bits(state->phy_gpr, CSI2SS_CTRL_CLK_RESET, CSI2SS_CTRL_CLK_RESET_EN);
 239
 240	return ret;
 241}
 242
 243static void imx8qxp_gpr_disable(struct csi_state *state)
 244{
 245	/* Disable Pixel Link */
 246	regmap_write(state->phy_gpr, CSI2SS_PLM_CTRL, 0x0);
 247
 248	/* Disable PHY */
 249	regmap_write(state->phy_gpr, CSI2SS_PHY_CTRL, 0x0);
 250
 251	regmap_clear_bits(state->phy_gpr, CSI2SS_CTRL_CLK_RESET,
 252			  CSI2SS_CTRL_CLK_RESET_EN);
 253};
 254
 255static const struct imx8mq_plat_data imx8qxp_data = {
 256	.enable = imx8qxp_gpr_enable,
 257	.disable = imx8qxp_gpr_disable,
 258	.use_reg_csr = true,
 259};
 260
 261static const struct csi2_pix_format imx8mq_mipi_csi_formats[] = {
 262	/* RAW (Bayer and greyscale) formats. */
 263	{
 264		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
 265		.width = 8,
 266	}, {
 267		.code = MEDIA_BUS_FMT_SGBRG8_1X8,
 268		.width = 8,
 269	}, {
 270		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
 271		.width = 8,
 272	}, {
 273		.code = MEDIA_BUS_FMT_SRGGB8_1X8,
 274		.width = 8,
 275	}, {
 276		.code = MEDIA_BUS_FMT_Y8_1X8,
 277		.width = 8,
 278	}, {
 279		.code = MEDIA_BUS_FMT_SBGGR10_1X10,
 280		.width = 10,
 281	}, {
 282		.code = MEDIA_BUS_FMT_SGBRG10_1X10,
 283		.width = 10,
 284	}, {
 285		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
 286		.width = 10,
 287	}, {
 288		.code = MEDIA_BUS_FMT_SRGGB10_1X10,
 289		.width = 10,
 290	}, {
 291		.code = MEDIA_BUS_FMT_Y10_1X10,
 292		.width = 10,
 293	}, {
 294		.code = MEDIA_BUS_FMT_SBGGR12_1X12,
 295		.width = 12,
 296	}, {
 297		.code = MEDIA_BUS_FMT_SGBRG12_1X12,
 298		.width = 12,
 299	}, {
 300		.code = MEDIA_BUS_FMT_SGRBG12_1X12,
 301		.width = 12,
 302	}, {
 303		.code = MEDIA_BUS_FMT_SRGGB12_1X12,
 304		.width = 12,
 305	}, {
 306		.code = MEDIA_BUS_FMT_Y12_1X12,
 307		.width = 12,
 308	}, {
 309		.code = MEDIA_BUS_FMT_SBGGR14_1X14,
 310		.width = 14,
 311	}, {
 312		.code = MEDIA_BUS_FMT_SGBRG14_1X14,
 313		.width = 14,
 314	}, {
 315		.code = MEDIA_BUS_FMT_SGRBG14_1X14,
 316		.width = 14,
 317	}, {
 318		.code = MEDIA_BUS_FMT_SRGGB14_1X14,
 319		.width = 14,
 320	},
 321	/* YUV formats */
 322	{
 323		.code = MEDIA_BUS_FMT_YUYV8_1X16,
 324		.width = 16,
 325	}, {
 326		.code = MEDIA_BUS_FMT_UYVY8_1X16,
 327		.width = 16,
 328	}
 329};
 330
 331static const struct csi2_pix_format *find_csi2_format(u32 code)
 332{
 333	unsigned int i;
 334
 335	for (i = 0; i < ARRAY_SIZE(imx8mq_mipi_csi_formats); i++)
 336		if (code == imx8mq_mipi_csi_formats[i].code)
 337			return &imx8mq_mipi_csi_formats[i];
 338	return NULL;
 339}
 340
 341/* -----------------------------------------------------------------------------
 342 * Hardware configuration
 343 */
 344
 345static inline void imx8mq_mipi_csi_write(struct csi_state *state, u32 reg, u32 val)
 346{
 347	writel(val, state->regs + reg);
 348}
 349
 350static int imx8mq_mipi_csi_sw_reset(struct csi_state *state)
 351{
 352	int ret;
 353
 354	/*
 355	 * these are most likely self-clearing reset bits. to make it
 356	 * more clear, the reset-imx7 driver should implement the
 357	 * .reset() operation.
 358	 */
 359	ret = reset_control_assert(state->rst);
 360	if (ret < 0) {
 361		dev_err(state->dev, "Failed to assert resets: %d\n", ret);
 362		return ret;
 363	}
 364
 365	return 0;
 366}
 367
 368static void imx8mq_mipi_csi_set_params(struct csi_state *state)
 369{
 370	int lanes = state->bus.num_data_lanes;
 371
 372	imx8mq_mipi_csi_write(state, CSI2RX_CFG_NUM_LANES, lanes - 1);
 373	imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES,
 374			      (0xf << lanes) & 0xf);
 375	imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK, CSI2RX_IRQ_MASK_ALL);
 376	/*
 377	 * 0x180 bit 0 controls the Virtual Channel behaviour: when set the
 378	 * interface ignores the Virtual Channel (VC) field in received packets;
 379	 * when cleared it causes the interface to only accept packets whose VC
 380	 * matches the value to which VC is set at offset 0x184.
 381	 */
 382	imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_VC_IGNORE, 1);
 383	imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL,
 384			      CSI2RX_SEND_LEVEL);
 385}
 386
 387static int imx8mq_mipi_csi_clk_enable(struct csi_state *state)
 388{
 389	return clk_bulk_prepare_enable(CSI2_NUM_CLKS, state->clks);
 390}
 391
 392static void imx8mq_mipi_csi_clk_disable(struct csi_state *state)
 393{
 394	clk_bulk_disable_unprepare(CSI2_NUM_CLKS, state->clks);
 395}
 396
 397static int imx8mq_mipi_csi_clk_get(struct csi_state *state)
 398{
 399	unsigned int i;
 400
 401	for (i = 0; i < CSI2_NUM_CLKS; i++)
 402		state->clks[i].id = imx8mq_mipi_csi_clk_id[i];
 403
 404	return devm_clk_bulk_get(state->dev, CSI2_NUM_CLKS, state->clks);
 405}
 406
 407static int imx8mq_mipi_csi_calc_hs_settle(struct csi_state *state,
 408					  struct v4l2_subdev_state *sd_state,
 409					  u32 *hs_settle)
 410{
 411	struct media_pad *src_pad;
 412	s64 link_freq;
 413	u32 lane_rate;
 414	unsigned long esc_clk_rate;
 415	u32 min_ths_settle, max_ths_settle, ths_settle_ns, esc_clk_period_ns;
 416	const struct v4l2_mbus_framefmt *fmt;
 417	const struct csi2_pix_format *csi2_fmt;
 418
 419	src_pad = media_entity_remote_source_pad_unique(&sd_state->sd->entity);
 420	if (IS_ERR(src_pad)) {
 421		dev_err(state->dev, "can't get source pad of %s (%pe)\n",
 422			sd_state->sd->name, src_pad);
 423		return PTR_ERR(src_pad);
 424	}
 425
 426	/* Calculate the line rate from the pixel rate. */
 427
 428	fmt = v4l2_subdev_state_get_format(sd_state, MIPI_CSI2_PAD_SINK);
 429	csi2_fmt = find_csi2_format(fmt->code);
 430
 431	link_freq = v4l2_get_link_freq(src_pad, csi2_fmt->width,
 432				       state->bus.num_data_lanes * 2);
 433	if (link_freq < 0) {
 434		dev_err(state->dev, "Unable to obtain link frequency: %d\n",
 435			(int)link_freq);
 436		return link_freq;
 437	}
 438
 439	lane_rate = link_freq * 2;
 440	if (lane_rate < 80000000 || lane_rate > 1500000000) {
 441		dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate);
 442		return -EINVAL;
 443	}
 444
 445	/*
 446	 * The D-PHY specification requires Ths-settle to be in the range
 447	 * 85ns + 6*UI to 140ns + 10*UI, with the unit interval UI being half
 448	 * the clock period.
 449	 *
 450	 * The Ths-settle value is expressed in the hardware as a multiple of
 451	 * the Esc clock period:
 452	 *
 453	 * Ths-settle = (PRG_RXHS_SETTLE + 1) * Tperiod of RxClkInEsc
 454	 *
 455	 * Due to the one cycle inaccuracy introduced by rounding, the
 456	 * documentation recommends picking a value away from the boundaries.
 457	 * Let's pick the average.
 458	 */
 459	esc_clk_rate = clk_get_rate(state->clks[CSI2_CLK_ESC].clk);
 460	if (!esc_clk_rate) {
 461		dev_err(state->dev, "Could not get esc clock rate.\n");
 462		return -EINVAL;
 463	}
 464
 465	dev_dbg(state->dev, "esc clk rate: %lu\n", esc_clk_rate);
 466	esc_clk_period_ns = 1000000000 / esc_clk_rate;
 467
 468	min_ths_settle = 85 + 6 * 1000000 / (lane_rate / 1000);
 469	max_ths_settle = 140 + 10 * 1000000 / (lane_rate / 1000);
 470	ths_settle_ns = (min_ths_settle + max_ths_settle) / 2;
 471
 472	*hs_settle = ths_settle_ns / esc_clk_period_ns - 1;
 473
 474	dev_dbg(state->dev, "lane rate %u Ths_settle %u hs_settle %u\n",
 475		lane_rate, ths_settle_ns, *hs_settle);
 476
 477	return 0;
 478}
 479
 480static int imx8mq_mipi_csi_start_stream(struct csi_state *state,
 481					struct v4l2_subdev_state *sd_state)
 482{
 483	int ret;
 484	u32 hs_settle = 0;
 485
 486	ret = imx8mq_mipi_csi_sw_reset(state);
 487	if (ret)
 488		return ret;
 489
 490	imx8mq_mipi_csi_set_params(state);
 491	ret = imx8mq_mipi_csi_calc_hs_settle(state, sd_state, &hs_settle);
 492	if (ret)
 493		return ret;
 494
 495	ret = state->pdata->enable(state, hs_settle);
 496	if (ret)
 497		return ret;
 498
 499	return 0;
 500}
 501
 502static void imx8mq_mipi_csi_stop_stream(struct csi_state *state)
 503{
 504	imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, 0xf);
 505
 506	if (state->pdata->disable)
 507		state->pdata->disable(state);
 508}
 509
 510/* -----------------------------------------------------------------------------
 511 * V4L2 subdev operations
 512 */
 513
 514static struct csi_state *mipi_sd_to_csi2_state(struct v4l2_subdev *sdev)
 515{
 516	return container_of(sdev, struct csi_state, sd);
 517}
 518
 519static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable)
 520{
 521	struct csi_state *state = mipi_sd_to_csi2_state(sd);
 522	struct v4l2_subdev_state *sd_state;
 523	int ret = 0;
 524
 525	if (enable) {
 526		ret = pm_runtime_resume_and_get(state->dev);
 527		if (ret < 0)
 528			return ret;
 529	}
 530
 531	mutex_lock(&state->lock);
 532
 533	if (enable) {
 534		if (state->state & ST_SUSPENDED) {
 535			ret = -EBUSY;
 536			goto unlock;
 537		}
 538
 539		sd_state = v4l2_subdev_lock_and_get_active_state(sd);
 540		ret = imx8mq_mipi_csi_start_stream(state, sd_state);
 541		v4l2_subdev_unlock_state(sd_state);
 542
 543		if (ret < 0)
 544			goto unlock;
 545
 546		ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1);
 547		if (ret < 0)
 548			goto unlock;
 549
 550		state->state |= ST_STREAMING;
 551	} else {
 552		v4l2_subdev_call(state->src_sd, video, s_stream, 0);
 553		imx8mq_mipi_csi_stop_stream(state);
 554		state->state &= ~ST_STREAMING;
 555	}
 556
 557unlock:
 558	mutex_unlock(&state->lock);
 559
 560	if (!enable || ret < 0)
 561		pm_runtime_put(state->dev);
 562
 563	return ret;
 564}
 565
 566static int imx8mq_mipi_csi_init_state(struct v4l2_subdev *sd,
 567				      struct v4l2_subdev_state *sd_state)
 568{
 569	struct v4l2_mbus_framefmt *fmt_sink;
 570	struct v4l2_mbus_framefmt *fmt_source;
 571
 572	fmt_sink = v4l2_subdev_state_get_format(sd_state, MIPI_CSI2_PAD_SINK);
 573	fmt_source = v4l2_subdev_state_get_format(sd_state,
 574						  MIPI_CSI2_PAD_SOURCE);
 575
 576	fmt_sink->code = MEDIA_BUS_FMT_SGBRG10_1X10;
 577	fmt_sink->width = MIPI_CSI2_DEF_PIX_WIDTH;
 578	fmt_sink->height = MIPI_CSI2_DEF_PIX_HEIGHT;
 579	fmt_sink->field = V4L2_FIELD_NONE;
 580
 581	fmt_sink->colorspace = V4L2_COLORSPACE_RAW;
 582	fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace);
 583	fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace);
 584	fmt_sink->quantization =
 585		V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
 586					      fmt_sink->ycbcr_enc);
 587
 588	*fmt_source = *fmt_sink;
 589
 590	return 0;
 591}
 592
 593static int imx8mq_mipi_csi_enum_mbus_code(struct v4l2_subdev *sd,
 594					  struct v4l2_subdev_state *sd_state,
 595					  struct v4l2_subdev_mbus_code_enum *code)
 596{
 597	/*
 598	 * We can't transcode in any way, the source format is identical
 599	 * to the sink format.
 600	 */
 601	if (code->pad == MIPI_CSI2_PAD_SOURCE) {
 602		struct v4l2_mbus_framefmt *fmt;
 603
 604		if (code->index > 0)
 605			return -EINVAL;
 606
 607		fmt = v4l2_subdev_state_get_format(sd_state, code->pad);
 608		code->code = fmt->code;
 609		return 0;
 610	}
 611
 612	if (code->pad != MIPI_CSI2_PAD_SINK)
 613		return -EINVAL;
 614
 615	if (code->index >= ARRAY_SIZE(imx8mq_mipi_csi_formats))
 616		return -EINVAL;
 617
 618	code->code = imx8mq_mipi_csi_formats[code->index].code;
 619
 620	return 0;
 621}
 622
 623static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd,
 624				   struct v4l2_subdev_state *sd_state,
 625				   struct v4l2_subdev_format *sdformat)
 626{
 627	const struct csi2_pix_format *csi2_fmt;
 628	struct v4l2_mbus_framefmt *fmt;
 629
 630	/*
 631	 * The device can't transcode in any way, the source format can't be
 632	 * modified.
 633	 */
 634	if (sdformat->pad == MIPI_CSI2_PAD_SOURCE)
 635		return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
 636
 637	if (sdformat->pad != MIPI_CSI2_PAD_SINK)
 638		return -EINVAL;
 639
 640	csi2_fmt = find_csi2_format(sdformat->format.code);
 641	if (!csi2_fmt)
 642		csi2_fmt = &imx8mq_mipi_csi_formats[0];
 643
 644	fmt = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
 645
 646	fmt->code = csi2_fmt->code;
 647	fmt->width = sdformat->format.width;
 648	fmt->height = sdformat->format.height;
 649
 650	sdformat->format = *fmt;
 651
 652	/* Propagate the format from sink to source. */
 653	fmt = v4l2_subdev_state_get_format(sd_state, MIPI_CSI2_PAD_SOURCE);
 654	*fmt = sdformat->format;
 655
 656	return 0;
 657}
 658
 659static const struct v4l2_subdev_video_ops imx8mq_mipi_csi_video_ops = {
 660	.s_stream	= imx8mq_mipi_csi_s_stream,
 661};
 662
 663static const struct v4l2_subdev_pad_ops imx8mq_mipi_csi_pad_ops = {
 664	.enum_mbus_code		= imx8mq_mipi_csi_enum_mbus_code,
 665	.get_fmt		= v4l2_subdev_get_fmt,
 666	.set_fmt		= imx8mq_mipi_csi_set_fmt,
 667};
 668
 669static const struct v4l2_subdev_ops imx8mq_mipi_csi_subdev_ops = {
 670	.video	= &imx8mq_mipi_csi_video_ops,
 671	.pad	= &imx8mq_mipi_csi_pad_ops,
 672};
 673
 674static const struct v4l2_subdev_internal_ops imx8mq_mipi_csi_internal_ops = {
 675	.init_state		= imx8mq_mipi_csi_init_state,
 676};
 677
 678/* -----------------------------------------------------------------------------
 679 * Media entity operations
 680 */
 681
 682static const struct media_entity_operations imx8mq_mipi_csi_entity_ops = {
 683	.link_validate	= v4l2_subdev_link_validate,
 684	.get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
 685};
 686
 687/* -----------------------------------------------------------------------------
 688 * Async subdev notifier
 689 */
 690
 691static struct csi_state *
 692mipi_notifier_to_csi2_state(struct v4l2_async_notifier *n)
 693{
 694	return container_of(n, struct csi_state, notifier);
 695}
 696
 697static int imx8mq_mipi_csi_notify_bound(struct v4l2_async_notifier *notifier,
 698					struct v4l2_subdev *sd,
 699					struct v4l2_async_connection *asd)
 700{
 701	struct csi_state *state = mipi_notifier_to_csi2_state(notifier);
 702	struct media_pad *sink = &state->sd.entity.pads[MIPI_CSI2_PAD_SINK];
 703
 704	state->src_sd = sd;
 705
 706	return v4l2_create_fwnode_links_to_pad(sd, sink, MEDIA_LNK_FL_ENABLED |
 707					       MEDIA_LNK_FL_IMMUTABLE);
 708}
 709
 710static const struct v4l2_async_notifier_operations imx8mq_mipi_csi_notify_ops = {
 711	.bound = imx8mq_mipi_csi_notify_bound,
 712};
 713
 714static int imx8mq_mipi_csi_async_register(struct csi_state *state)
 715{
 716	struct v4l2_fwnode_endpoint vep = {
 717		.bus_type = V4L2_MBUS_CSI2_DPHY,
 718	};
 719	struct v4l2_async_connection *asd;
 720	struct fwnode_handle *ep;
 721	unsigned int i;
 722	int ret;
 723
 724	v4l2_async_subdev_nf_init(&state->notifier, &state->sd);
 725
 726	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
 727					     FWNODE_GRAPH_ENDPOINT_NEXT);
 728	if (!ep)
 729		return -ENOTCONN;
 730
 731	ret = v4l2_fwnode_endpoint_parse(ep, &vep);
 732	if (ret)
 733		goto err_parse;
 734
 735	for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) {
 736		if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) {
 737			dev_err(state->dev,
 738				"data lanes reordering is not supported");
 739			ret = -EINVAL;
 740			goto err_parse;
 741		}
 742	}
 743
 744	state->bus = vep.bus.mipi_csi2;
 745
 746	dev_dbg(state->dev, "data lanes: %d flags: 0x%08x\n",
 747		state->bus.num_data_lanes,
 748		state->bus.flags);
 749
 750	asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep,
 751					      struct v4l2_async_connection);
 752	if (IS_ERR(asd)) {
 753		ret = PTR_ERR(asd);
 754		goto err_parse;
 755	}
 756
 757	fwnode_handle_put(ep);
 758
 759	state->notifier.ops = &imx8mq_mipi_csi_notify_ops;
 760
 761	ret = v4l2_async_nf_register(&state->notifier);
 762	if (ret)
 763		return ret;
 764
 765	return v4l2_async_register_subdev(&state->sd);
 766
 767err_parse:
 768	fwnode_handle_put(ep);
 769
 770	return ret;
 771}
 772
 773/* -----------------------------------------------------------------------------
 774 * Suspend/resume
 775 */
 776
 777static void imx8mq_mipi_csi_pm_suspend(struct device *dev)
 778{
 779	struct v4l2_subdev *sd = dev_get_drvdata(dev);
 780	struct csi_state *state = mipi_sd_to_csi2_state(sd);
 781
 782	mutex_lock(&state->lock);
 783
 784	if (state->state & ST_POWERED) {
 785		imx8mq_mipi_csi_stop_stream(state);
 786		imx8mq_mipi_csi_clk_disable(state);
 787		state->state &= ~ST_POWERED;
 788	}
 789
 790	mutex_unlock(&state->lock);
 791}
 792
 793static int imx8mq_mipi_csi_pm_resume(struct device *dev)
 794{
 795	struct v4l2_subdev *sd = dev_get_drvdata(dev);
 796	struct csi_state *state = mipi_sd_to_csi2_state(sd);
 797	struct v4l2_subdev_state *sd_state;
 798	int ret = 0;
 799
 800	mutex_lock(&state->lock);
 801
 802	if (!(state->state & ST_POWERED)) {
 803		state->state |= ST_POWERED;
 804		ret = imx8mq_mipi_csi_clk_enable(state);
 805	}
 806	if (state->state & ST_STREAMING) {
 807		sd_state = v4l2_subdev_lock_and_get_active_state(sd);
 808		ret = imx8mq_mipi_csi_start_stream(state, sd_state);
 809		v4l2_subdev_unlock_state(sd_state);
 810		if (ret)
 811			goto unlock;
 812	}
 813
 814	state->state &= ~ST_SUSPENDED;
 815
 816unlock:
 817	mutex_unlock(&state->lock);
 818
 819	return ret ? -EAGAIN : 0;
 820}
 821
 822static int imx8mq_mipi_csi_suspend(struct device *dev)
 823{
 824	struct v4l2_subdev *sd = dev_get_drvdata(dev);
 825	struct csi_state *state = mipi_sd_to_csi2_state(sd);
 826
 827	imx8mq_mipi_csi_pm_suspend(dev);
 828
 829	state->state |= ST_SUSPENDED;
 830
 831	return 0;
 832}
 833
 834static int imx8mq_mipi_csi_resume(struct device *dev)
 835{
 836	struct v4l2_subdev *sd = dev_get_drvdata(dev);
 837	struct csi_state *state = mipi_sd_to_csi2_state(sd);
 838
 839	if (!(state->state & ST_SUSPENDED))
 840		return 0;
 841
 842	return imx8mq_mipi_csi_pm_resume(dev);
 843}
 844
 845static int imx8mq_mipi_csi_runtime_suspend(struct device *dev)
 846{
 847	struct v4l2_subdev *sd = dev_get_drvdata(dev);
 848	struct csi_state *state = mipi_sd_to_csi2_state(sd);
 849	int ret;
 850
 851	imx8mq_mipi_csi_pm_suspend(dev);
 852
 853	ret = icc_set_bw(state->icc_path, 0, 0);
 854	if (ret)
 855		dev_err(dev, "icc_set_bw failed with %d\n", ret);
 856
 857	return ret;
 858}
 859
 860static int imx8mq_mipi_csi_runtime_resume(struct device *dev)
 861{
 862	struct v4l2_subdev *sd = dev_get_drvdata(dev);
 863	struct csi_state *state = mipi_sd_to_csi2_state(sd);
 864	int ret;
 865
 866	ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw);
 867	if (ret) {
 868		dev_err(dev, "icc_set_bw failed with %d\n", ret);
 869		return ret;
 870	}
 871
 872	return imx8mq_mipi_csi_pm_resume(dev);
 873}
 874
 875static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = {
 876	RUNTIME_PM_OPS(imx8mq_mipi_csi_runtime_suspend,
 877		       imx8mq_mipi_csi_runtime_resume, NULL)
 878	SYSTEM_SLEEP_PM_OPS(imx8mq_mipi_csi_suspend, imx8mq_mipi_csi_resume)
 879};
 880
 881/* -----------------------------------------------------------------------------
 882 * Probe/remove & platform driver
 883 */
 884
 885static int imx8mq_mipi_csi_subdev_init(struct csi_state *state)
 886{
 887	struct v4l2_subdev *sd = &state->sd;
 888	int ret;
 889
 890	v4l2_subdev_init(sd, &imx8mq_mipi_csi_subdev_ops);
 891	sd->internal_ops = &imx8mq_mipi_csi_internal_ops;
 892	sd->owner = THIS_MODULE;
 893	snprintf(sd->name, sizeof(sd->name), "%s %s",
 894		 MIPI_CSI2_SUBDEV_NAME, dev_name(state->dev));
 895
 896	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 897
 898	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
 899	sd->entity.ops = &imx8mq_mipi_csi_entity_ops;
 900
 901	sd->dev = state->dev;
 902
 903	state->pads[MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK
 904					 | MEDIA_PAD_FL_MUST_CONNECT;
 905	state->pads[MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
 906					   | MEDIA_PAD_FL_MUST_CONNECT;
 907	ret = media_entity_pads_init(&sd->entity, MIPI_CSI2_PADS_NUM,
 908				     state->pads);
 909	if (ret)
 910		return ret;
 911
 912	ret = v4l2_subdev_init_finalize(sd);
 913	if (ret) {
 914		media_entity_cleanup(&sd->entity);
 915		return ret;
 916	}
 917
 918	return 0;
 919}
 920
 921static void imx8mq_mipi_csi_release_icc(struct platform_device *pdev)
 922{
 923	struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev);
 924	struct csi_state *state = mipi_sd_to_csi2_state(sd);
 925
 926	icc_put(state->icc_path);
 927}
 928
 929static int imx8mq_mipi_csi_init_icc(struct platform_device *pdev)
 930{
 931	struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev);
 932	struct csi_state *state = mipi_sd_to_csi2_state(sd);
 933
 934	/* Optional interconnect request */
 935	state->icc_path = of_icc_get(&pdev->dev, "dram");
 936	if (IS_ERR_OR_NULL(state->icc_path))
 937		return PTR_ERR_OR_ZERO(state->icc_path);
 938
 939	state->icc_path_bw = MBps_to_icc(700);
 940
 941	return 0;
 942}
 943
 944static int imx8mq_mipi_csi_parse_dt(struct csi_state *state)
 945{
 946	struct device *dev = state->dev;
 947	struct device_node *np = state->dev->of_node;
 948	struct device_node *node;
 949	phandle ph;
 950	u32 out_val[2];
 951	int ret = 0;
 952
 953	state->rst = devm_reset_control_array_get_exclusive(dev);
 954	if (IS_ERR(state->rst)) {
 955		dev_err(dev, "Failed to get reset: %pe\n", state->rst);
 956		return PTR_ERR(state->rst);
 957	}
 958
 959	if (state->pdata->use_reg_csr) {
 960		const struct regmap_config regmap_config = {
 961			.reg_bits = 32,
 962			.val_bits = 32,
 963			.reg_stride = 4,
 964		};
 965		void __iomem *base;
 966
 967		base = devm_platform_ioremap_resource(to_platform_device(dev), 1);
 968		if (IS_ERR(base))
 969			return dev_err_probe(dev, PTR_ERR(base), "Missing CSR register\n");
 970
 971		state->phy_gpr = devm_regmap_init_mmio(dev, base, &regmap_config);
 972		if (IS_ERR(state->phy_gpr))
 973			return dev_err_probe(dev, PTR_ERR(state->phy_gpr),
 974					     "Failed to init CSI MMIO regmap\n");
 975		return 0;
 976	}
 977
 978	ret = of_property_read_u32_array(np, "fsl,mipi-phy-gpr", out_val,
 979					 ARRAY_SIZE(out_val));
 980	if (ret) {
 981		dev_err(dev, "no fsl,mipi-phy-gpr property found: %d\n", ret);
 982		return ret;
 983	}
 984
 985	ph = *out_val;
 986
 987	node = of_find_node_by_phandle(ph);
 988	if (!node) {
 989		dev_err(dev, "Error finding node by phandle\n");
 990		return -ENODEV;
 991	}
 992	state->phy_gpr = syscon_node_to_regmap(node);
 993	of_node_put(node);
 994	if (IS_ERR(state->phy_gpr)) {
 995		dev_err(dev, "failed to get gpr regmap: %pe\n", state->phy_gpr);
 996		return PTR_ERR(state->phy_gpr);
 997	}
 998
 999	state->phy_gpr_reg = out_val[1];
1000	dev_dbg(dev, "phy gpr register set to 0x%x\n", state->phy_gpr_reg);
1001
1002	return ret;
1003}
1004
1005static int imx8mq_mipi_csi_probe(struct platform_device *pdev)
1006{
1007	struct device *dev = &pdev->dev;
1008	struct csi_state *state;
1009	int ret;
1010
1011	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
1012	if (!state)
1013		return -ENOMEM;
1014
1015	state->dev = dev;
1016
1017	state->pdata = of_device_get_match_data(dev);
1018
1019	ret = imx8mq_mipi_csi_parse_dt(state);
1020	if (ret < 0) {
1021		dev_err(dev, "Failed to parse device tree: %d\n", ret);
1022		return ret;
1023	}
1024
1025	/* Acquire resources. */
1026	state->regs = devm_platform_ioremap_resource(pdev, 0);
1027	if (IS_ERR(state->regs))
1028		return PTR_ERR(state->regs);
1029
1030	ret = imx8mq_mipi_csi_clk_get(state);
1031	if (ret < 0)
1032		return ret;
1033
1034	platform_set_drvdata(pdev, &state->sd);
1035
1036	mutex_init(&state->lock);
1037
1038	ret = imx8mq_mipi_csi_subdev_init(state);
1039	if (ret < 0)
1040		goto mutex;
1041
1042	ret = imx8mq_mipi_csi_init_icc(pdev);
1043	if (ret)
1044		goto mutex;
1045
1046	/* Enable runtime PM. */
1047	pm_runtime_enable(dev);
1048	if (!pm_runtime_enabled(dev)) {
1049		ret = imx8mq_mipi_csi_runtime_resume(dev);
1050		if (ret < 0)
1051			goto icc;
1052	}
1053
1054	ret = imx8mq_mipi_csi_async_register(state);
1055	if (ret < 0)
1056		goto cleanup;
1057
1058	return 0;
1059
1060cleanup:
1061	pm_runtime_disable(&pdev->dev);
1062	imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
1063
1064	media_entity_cleanup(&state->sd.entity);
1065	v4l2_subdev_cleanup(&state->sd);
1066	v4l2_async_nf_unregister(&state->notifier);
1067	v4l2_async_nf_cleanup(&state->notifier);
1068	v4l2_async_unregister_subdev(&state->sd);
1069icc:
1070	imx8mq_mipi_csi_release_icc(pdev);
1071mutex:
1072	mutex_destroy(&state->lock);
1073
1074	return ret;
1075}
1076
1077static void imx8mq_mipi_csi_remove(struct platform_device *pdev)
1078{
1079	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
1080	struct csi_state *state = mipi_sd_to_csi2_state(sd);
1081
1082	v4l2_async_nf_unregister(&state->notifier);
1083	v4l2_async_nf_cleanup(&state->notifier);
1084	v4l2_async_unregister_subdev(&state->sd);
1085
1086	pm_runtime_disable(&pdev->dev);
1087	imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
1088	media_entity_cleanup(&state->sd.entity);
1089	v4l2_subdev_cleanup(&state->sd);
1090	mutex_destroy(&state->lock);
1091	pm_runtime_set_suspended(&pdev->dev);
1092	imx8mq_mipi_csi_release_icc(pdev);
1093}
1094
1095static const struct of_device_id imx8mq_mipi_csi_of_match[] = {
1096	{ .compatible = "fsl,imx8mq-mipi-csi2", .data = &imx8mq_data },
1097	{ .compatible = "fsl,imx8qxp-mipi-csi2", .data = &imx8qxp_data },
1098	{ /* sentinel */ },
1099};
1100MODULE_DEVICE_TABLE(of, imx8mq_mipi_csi_of_match);
1101
1102static struct platform_driver imx8mq_mipi_csi_driver = {
1103	.probe		= imx8mq_mipi_csi_probe,
1104	.remove		= imx8mq_mipi_csi_remove,
1105	.driver		= {
1106		.of_match_table = imx8mq_mipi_csi_of_match,
1107		.name		= MIPI_CSI2_DRIVER_NAME,
1108		.pm		= pm_ptr(&imx8mq_mipi_csi_pm_ops),
1109	},
1110};
1111
1112module_platform_driver(imx8mq_mipi_csi_driver);
1113
1114MODULE_DESCRIPTION("i.MX8MQ MIPI CSI-2 receiver driver");
1115MODULE_AUTHOR("Martin Kepplinger <martin.kepplinger@puri.sm>");
1116MODULE_LICENSE("GPL v2");
~/ Read-only file preview.