xref: /linux/drivers/media/platform/cadence/cdns-csi2tx.c (revision 3036bc45364f98515a2c446d7fac2c34dcfbeff4)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Driver for Cadence MIPI-CSI2 TX Controller
4  *
5  * Copyright (C) 2017-2018 Cadence Design Systems Inc.
6  */
7 
8 #include <linux/clk.h>
9 #include <linux/delay.h>
10 #include <linux/io.h>
11 #include <linux/module.h>
12 #include <linux/mutex.h>
13 #include <linux/of.h>
14 #include <linux/of_graph.h>
15 #include <linux/platform_device.h>
16 
17 #include <media/v4l2-ctrls.h>
18 #include <media/v4l2-device.h>
19 #include <media/v4l2-fwnode.h>
20 #include <media/v4l2-subdev.h>
21 
22 #define CSI2TX_DEVICE_CONFIG_REG	0x00
23 #define CSI2TX_DEVICE_CONFIG_STREAMS_MASK	GENMASK(6, 4)
24 #define CSI2TX_DEVICE_CONFIG_HAS_DPHY		BIT(3)
25 #define CSI2TX_DEVICE_CONFIG_LANES_MASK		GENMASK(2, 0)
26 
27 #define CSI2TX_CONFIG_REG		0x20
28 #define CSI2TX_CONFIG_CFG_REQ			BIT(2)
29 #define CSI2TX_CONFIG_SRST_REQ			BIT(1)
30 
31 #define CSI2TX_DPHY_CFG_REG		0x28
32 #define CSI2TX_DPHY_CFG_CLK_RESET		BIT(16)
33 #define CSI2TX_DPHY_CFG_LANE_RESET(n)		BIT((n) + 12)
34 #define CSI2TX_DPHY_CFG_MODE_MASK		GENMASK(9, 8)
35 #define CSI2TX_DPHY_CFG_MODE_LPDT		(2 << 8)
36 #define CSI2TX_DPHY_CFG_MODE_HS			(1 << 8)
37 #define CSI2TX_DPHY_CFG_MODE_ULPS		(0 << 8)
38 #define CSI2TX_DPHY_CFG_CLK_ENABLE		BIT(4)
39 #define CSI2TX_DPHY_CFG_LANE_ENABLE(n)		BIT(n)
40 
41 #define CSI2TX_DPHY_CLK_WAKEUP_REG	0x2c
42 #define CSI2TX_DPHY_CLK_WAKEUP_ULPS_CYCLES(n)	((n) & 0xffff)
43 
44 #define CSI2TX_DT_CFG_REG(n)		(0x80 + (n) * 8)
45 #define CSI2TX_DT_CFG_DT(n)			(((n) & 0x3f) << 2)
46 
47 #define CSI2TX_DT_FORMAT_REG(n)		(0x84 + (n) * 8)
48 #define CSI2TX_DT_FORMAT_BYTES_PER_LINE(n)	(((n) & 0xffff) << 16)
49 #define CSI2TX_DT_FORMAT_MAX_LINE_NUM(n)	((n) & 0xffff)
50 
51 #define CSI2TX_STREAM_IF_CFG_REG(n)	(0x100 + (n) * 4)
52 #define CSI2TX_STREAM_IF_CFG_FILL_LEVEL(n)	((n) & 0x1f)
53 
54 #define CSI2TX_LANES_MAX	4
55 #define CSI2TX_STREAMS_MAX	4
56 
57 enum csi2tx_pads {
58 	CSI2TX_PAD_SOURCE,
59 	CSI2TX_PAD_SINK_STREAM0,
60 	CSI2TX_PAD_SINK_STREAM1,
61 	CSI2TX_PAD_SINK_STREAM2,
62 	CSI2TX_PAD_SINK_STREAM3,
63 	CSI2TX_PAD_MAX,
64 };
65 
66 struct csi2tx_fmt {
67 	u32	mbus;
68 	u32	dt;
69 	u32	bpp;
70 };
71 
72 struct csi2tx_priv {
73 	struct device			*dev;
74 	unsigned int			count;
75 
76 	/*
77 	 * Used to prevent race conditions between multiple,
78 	 * concurrent calls to start and stop.
79 	 */
80 	struct mutex			lock;
81 
82 	void __iomem			*base;
83 
84 	struct clk			*esc_clk;
85 	struct clk			*p_clk;
86 	struct clk			*pixel_clk[CSI2TX_STREAMS_MAX];
87 
88 	struct v4l2_subdev		subdev;
89 	struct media_pad		pads[CSI2TX_PAD_MAX];
90 	struct v4l2_mbus_framefmt	pad_fmts[CSI2TX_PAD_MAX];
91 
92 	bool				has_internal_dphy;
93 	u8				lanes[CSI2TX_LANES_MAX];
94 	unsigned int			num_lanes;
95 	unsigned int			max_lanes;
96 	unsigned int			max_streams;
97 };
98 
99 static const struct csi2tx_fmt csi2tx_formats[] = {
100 	{
101 		.mbus	= MEDIA_BUS_FMT_UYVY8_1X16,
102 		.bpp	= 2,
103 		.dt	= 0x1e,
104 	},
105 	{
106 		.mbus	= MEDIA_BUS_FMT_RGB888_1X24,
107 		.bpp	= 3,
108 		.dt	= 0x24,
109 	},
110 };
111 
112 static const struct v4l2_mbus_framefmt fmt_default = {
113 	.width		= 1280,
114 	.height		= 720,
115 	.code		= MEDIA_BUS_FMT_RGB888_1X24,
116 	.field		= V4L2_FIELD_NONE,
117 	.colorspace	= V4L2_COLORSPACE_DEFAULT,
118 };
119 
120 static inline
121 struct csi2tx_priv *v4l2_subdev_to_csi2tx(struct v4l2_subdev *subdev)
122 {
123 	return container_of(subdev, struct csi2tx_priv, subdev);
124 }
125 
126 static const struct csi2tx_fmt *csi2tx_get_fmt_from_mbus(u32 mbus)
127 {
128 	unsigned int i;
129 
130 	for (i = 0; i < ARRAY_SIZE(csi2tx_formats); i++)
131 		if (csi2tx_formats[i].mbus == mbus)
132 			return &csi2tx_formats[i];
133 
134 	return NULL;
135 }
136 
137 static int csi2tx_enum_mbus_code(struct v4l2_subdev *subdev,
138 				 struct v4l2_subdev_pad_config *cfg,
139 				 struct v4l2_subdev_mbus_code_enum *code)
140 {
141 	if (code->pad || code->index >= ARRAY_SIZE(csi2tx_formats))
142 		return -EINVAL;
143 
144 	code->code = csi2tx_formats[code->index].mbus;
145 
146 	return 0;
147 }
148 
149 static struct v4l2_mbus_framefmt *
150 __csi2tx_get_pad_format(struct v4l2_subdev *subdev,
151 			struct v4l2_subdev_pad_config *cfg,
152 			struct v4l2_subdev_format *fmt)
153 {
154 	struct csi2tx_priv *csi2tx = v4l2_subdev_to_csi2tx(subdev);
155 
156 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
157 		return v4l2_subdev_get_try_format(subdev, cfg,
158 						  fmt->pad);
159 
160 	return &csi2tx->pad_fmts[fmt->pad];
161 }
162 
163 static int csi2tx_get_pad_format(struct v4l2_subdev *subdev,
164 				 struct v4l2_subdev_pad_config *cfg,
165 				 struct v4l2_subdev_format *fmt)
166 {
167 	const struct v4l2_mbus_framefmt *format;
168 
169 	/* Multiplexed pad? */
170 	if (fmt->pad == CSI2TX_PAD_SOURCE)
171 		return -EINVAL;
172 
173 	format = __csi2tx_get_pad_format(subdev, cfg, fmt);
174 	if (!format)
175 		return -EINVAL;
176 
177 	fmt->format = *format;
178 
179 	return 0;
180 }
181 
182 static int csi2tx_set_pad_format(struct v4l2_subdev *subdev,
183 				 struct v4l2_subdev_pad_config *cfg,
184 				 struct v4l2_subdev_format *fmt)
185 {
186 	const struct v4l2_mbus_framefmt *src_format = &fmt->format;
187 	struct v4l2_mbus_framefmt *dst_format;
188 
189 	/* Multiplexed pad? */
190 	if (fmt->pad == CSI2TX_PAD_SOURCE)
191 		return -EINVAL;
192 
193 	if (!csi2tx_get_fmt_from_mbus(fmt->format.code))
194 		src_format = &fmt_default;
195 
196 	dst_format = __csi2tx_get_pad_format(subdev, cfg, fmt);
197 	if (!dst_format)
198 		return -EINVAL;
199 
200 	*dst_format = *src_format;
201 
202 	return 0;
203 }
204 
205 static const struct v4l2_subdev_pad_ops csi2tx_pad_ops = {
206 	.enum_mbus_code	= csi2tx_enum_mbus_code,
207 	.get_fmt	= csi2tx_get_pad_format,
208 	.set_fmt	= csi2tx_set_pad_format,
209 };
210 
211 static void csi2tx_reset(struct csi2tx_priv *csi2tx)
212 {
213 	writel(CSI2TX_CONFIG_SRST_REQ, csi2tx->base + CSI2TX_CONFIG_REG);
214 
215 	udelay(10);
216 }
217 
218 static int csi2tx_start(struct csi2tx_priv *csi2tx)
219 {
220 	struct media_entity *entity = &csi2tx->subdev.entity;
221 	struct media_link *link;
222 	unsigned int i;
223 	u32 reg;
224 
225 	csi2tx_reset(csi2tx);
226 
227 	writel(CSI2TX_CONFIG_CFG_REQ, csi2tx->base + CSI2TX_CONFIG_REG);
228 
229 	udelay(10);
230 
231 	/* Configure our PPI interface with the D-PHY */
232 	writel(CSI2TX_DPHY_CLK_WAKEUP_ULPS_CYCLES(32),
233 	       csi2tx->base + CSI2TX_DPHY_CLK_WAKEUP_REG);
234 
235 	/* Put our lanes (clock and data) out of reset */
236 	reg = CSI2TX_DPHY_CFG_CLK_RESET | CSI2TX_DPHY_CFG_MODE_LPDT;
237 	for (i = 0; i < csi2tx->num_lanes; i++)
238 		reg |= CSI2TX_DPHY_CFG_LANE_RESET(csi2tx->lanes[i]);
239 	writel(reg, csi2tx->base + CSI2TX_DPHY_CFG_REG);
240 
241 	udelay(10);
242 
243 	/* Enable our (clock and data) lanes */
244 	reg |= CSI2TX_DPHY_CFG_CLK_ENABLE;
245 	for (i = 0; i < csi2tx->num_lanes; i++)
246 		reg |= CSI2TX_DPHY_CFG_LANE_ENABLE(csi2tx->lanes[i]);
247 	writel(reg, csi2tx->base + CSI2TX_DPHY_CFG_REG);
248 
249 	udelay(10);
250 
251 	/* Switch to HS mode */
252 	reg &= ~CSI2TX_DPHY_CFG_MODE_MASK;
253 	writel(reg | CSI2TX_DPHY_CFG_MODE_HS,
254 	       csi2tx->base + CSI2TX_DPHY_CFG_REG);
255 
256 	udelay(10);
257 
258 	/*
259 	 * Create a static mapping between the CSI virtual channels
260 	 * and the input streams.
261 	 *
262 	 * This should be enhanced, but v4l2 lacks the support for
263 	 * changing that mapping dynamically at the moment.
264 	 *
265 	 * We're protected from the userspace setting up links at the
266 	 * same time by the upper layer having called
267 	 * media_pipeline_start().
268 	 */
269 	list_for_each_entry(link, &entity->links, list) {
270 		struct v4l2_mbus_framefmt *mfmt;
271 		const struct csi2tx_fmt *fmt;
272 		unsigned int stream;
273 		int pad_idx = -1;
274 
275 		/* Only consider our enabled input pads */
276 		for (i = CSI2TX_PAD_SINK_STREAM0; i < CSI2TX_PAD_MAX; i++) {
277 			struct media_pad *pad = &csi2tx->pads[i];
278 
279 			if ((pad == link->sink) &&
280 			    (link->flags & MEDIA_LNK_FL_ENABLED)) {
281 				pad_idx = i;
282 				break;
283 			}
284 		}
285 
286 		if (pad_idx < 0)
287 			continue;
288 
289 		mfmt = &csi2tx->pad_fmts[pad_idx];
290 		fmt = csi2tx_get_fmt_from_mbus(mfmt->code);
291 		if (!fmt)
292 			continue;
293 
294 		stream = pad_idx - CSI2TX_PAD_SINK_STREAM0;
295 
296 		/*
297 		 * We use the stream ID there, but it's wrong.
298 		 *
299 		 * A stream could very well send a data type that is
300 		 * not equal to its stream ID. We need to find a
301 		 * proper way to address it.
302 		 */
303 		writel(CSI2TX_DT_CFG_DT(fmt->dt),
304 		       csi2tx->base + CSI2TX_DT_CFG_REG(stream));
305 
306 		writel(CSI2TX_DT_FORMAT_BYTES_PER_LINE(mfmt->width * fmt->bpp) |
307 		       CSI2TX_DT_FORMAT_MAX_LINE_NUM(mfmt->height + 1),
308 		       csi2tx->base + CSI2TX_DT_FORMAT_REG(stream));
309 
310 		/*
311 		 * TODO: This needs to be calculated based on the
312 		 * output CSI2 clock rate.
313 		 */
314 		writel(CSI2TX_STREAM_IF_CFG_FILL_LEVEL(4),
315 		       csi2tx->base + CSI2TX_STREAM_IF_CFG_REG(stream));
316 	}
317 
318 	/* Disable the configuration mode */
319 	writel(0, csi2tx->base + CSI2TX_CONFIG_REG);
320 
321 	return 0;
322 }
323 
324 static void csi2tx_stop(struct csi2tx_priv *csi2tx)
325 {
326 	writel(CSI2TX_CONFIG_CFG_REQ | CSI2TX_CONFIG_SRST_REQ,
327 	       csi2tx->base + CSI2TX_CONFIG_REG);
328 }
329 
330 static int csi2tx_s_stream(struct v4l2_subdev *subdev, int enable)
331 {
332 	struct csi2tx_priv *csi2tx = v4l2_subdev_to_csi2tx(subdev);
333 	int ret = 0;
334 
335 	mutex_lock(&csi2tx->lock);
336 
337 	if (enable) {
338 		/*
339 		 * If we're not the first users, there's no need to
340 		 * enable the whole controller.
341 		 */
342 		if (!csi2tx->count) {
343 			ret = csi2tx_start(csi2tx);
344 			if (ret)
345 				goto out;
346 		}
347 
348 		csi2tx->count++;
349 	} else {
350 		csi2tx->count--;
351 
352 		/*
353 		 * Let the last user turn off the lights.
354 		 */
355 		if (!csi2tx->count)
356 			csi2tx_stop(csi2tx);
357 	}
358 
359 out:
360 	mutex_unlock(&csi2tx->lock);
361 	return ret;
362 }
363 
364 static const struct v4l2_subdev_video_ops csi2tx_video_ops = {
365 	.s_stream	= csi2tx_s_stream,
366 };
367 
368 static const struct v4l2_subdev_ops csi2tx_subdev_ops = {
369 	.pad		= &csi2tx_pad_ops,
370 	.video		= &csi2tx_video_ops,
371 };
372 
373 static int csi2tx_get_resources(struct csi2tx_priv *csi2tx,
374 				struct platform_device *pdev)
375 {
376 	struct resource *res;
377 	unsigned int i;
378 	u32 dev_cfg;
379 
380 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
381 	csi2tx->base = devm_ioremap_resource(&pdev->dev, res);
382 	if (IS_ERR(csi2tx->base))
383 		return PTR_ERR(csi2tx->base);
384 
385 	csi2tx->p_clk = devm_clk_get(&pdev->dev, "p_clk");
386 	if (IS_ERR(csi2tx->p_clk)) {
387 		dev_err(&pdev->dev, "Couldn't get p_clk\n");
388 		return PTR_ERR(csi2tx->p_clk);
389 	}
390 
391 	csi2tx->esc_clk = devm_clk_get(&pdev->dev, "esc_clk");
392 	if (IS_ERR(csi2tx->esc_clk)) {
393 		dev_err(&pdev->dev, "Couldn't get the esc_clk\n");
394 		return PTR_ERR(csi2tx->esc_clk);
395 	}
396 
397 	clk_prepare_enable(csi2tx->p_clk);
398 	dev_cfg = readl(csi2tx->base + CSI2TX_DEVICE_CONFIG_REG);
399 	clk_disable_unprepare(csi2tx->p_clk);
400 
401 	csi2tx->max_lanes = dev_cfg & CSI2TX_DEVICE_CONFIG_LANES_MASK;
402 	if (csi2tx->max_lanes > CSI2TX_LANES_MAX) {
403 		dev_err(&pdev->dev, "Invalid number of lanes: %u\n",
404 			csi2tx->max_lanes);
405 		return -EINVAL;
406 	}
407 
408 	csi2tx->max_streams = (dev_cfg & CSI2TX_DEVICE_CONFIG_STREAMS_MASK) >> 4;
409 	if (csi2tx->max_streams > CSI2TX_STREAMS_MAX) {
410 		dev_err(&pdev->dev, "Invalid number of streams: %u\n",
411 			csi2tx->max_streams);
412 		return -EINVAL;
413 	}
414 
415 	csi2tx->has_internal_dphy = !!(dev_cfg & CSI2TX_DEVICE_CONFIG_HAS_DPHY);
416 
417 	for (i = 0; i < csi2tx->max_streams; i++) {
418 		char clk_name[16];
419 
420 		snprintf(clk_name, sizeof(clk_name), "pixel_if%u_clk", i);
421 		csi2tx->pixel_clk[i] = devm_clk_get(&pdev->dev, clk_name);
422 		if (IS_ERR(csi2tx->pixel_clk[i])) {
423 			dev_err(&pdev->dev, "Couldn't get clock %s\n",
424 				clk_name);
425 			return PTR_ERR(csi2tx->pixel_clk[i]);
426 		}
427 	}
428 
429 	return 0;
430 }
431 
432 static int csi2tx_check_lanes(struct csi2tx_priv *csi2tx)
433 {
434 	struct v4l2_fwnode_endpoint v4l2_ep;
435 	struct device_node *ep;
436 	int ret;
437 
438 	ep = of_graph_get_endpoint_by_regs(csi2tx->dev->of_node, 0, 0);
439 	if (!ep)
440 		return -EINVAL;
441 
442 	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &v4l2_ep);
443 	if (ret) {
444 		dev_err(csi2tx->dev, "Could not parse v4l2 endpoint\n");
445 		goto out;
446 	}
447 
448 	if (v4l2_ep.bus_type != V4L2_MBUS_CSI2) {
449 		dev_err(csi2tx->dev, "Unsupported media bus type: 0x%x\n",
450 			v4l2_ep.bus_type);
451 		ret = -EINVAL;
452 		goto out;
453 	}
454 
455 	csi2tx->num_lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes;
456 	if (csi2tx->num_lanes > csi2tx->max_lanes) {
457 		dev_err(csi2tx->dev,
458 			"Current configuration uses more lanes than supported\n");
459 		ret = -EINVAL;
460 		goto out;
461 	}
462 
463 	memcpy(csi2tx->lanes, v4l2_ep.bus.mipi_csi2.data_lanes,
464 	       sizeof(csi2tx->lanes));
465 
466 out:
467 	of_node_put(ep);
468 	return ret;
469 }
470 
471 static int csi2tx_probe(struct platform_device *pdev)
472 {
473 	struct csi2tx_priv *csi2tx;
474 	unsigned int i;
475 	int ret;
476 
477 	csi2tx = kzalloc(sizeof(*csi2tx), GFP_KERNEL);
478 	if (!csi2tx)
479 		return -ENOMEM;
480 	platform_set_drvdata(pdev, csi2tx);
481 	mutex_init(&csi2tx->lock);
482 	csi2tx->dev = &pdev->dev;
483 
484 	ret = csi2tx_get_resources(csi2tx, pdev);
485 	if (ret)
486 		goto err_free_priv;
487 
488 	v4l2_subdev_init(&csi2tx->subdev, &csi2tx_subdev_ops);
489 	csi2tx->subdev.owner = THIS_MODULE;
490 	csi2tx->subdev.dev = &pdev->dev;
491 	csi2tx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
492 	snprintf(csi2tx->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s.%s",
493 		 KBUILD_MODNAME, dev_name(&pdev->dev));
494 
495 	ret = csi2tx_check_lanes(csi2tx);
496 	if (ret)
497 		goto err_free_priv;
498 
499 	/* Create our media pads */
500 	csi2tx->subdev.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
501 	csi2tx->pads[CSI2TX_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
502 	for (i = CSI2TX_PAD_SINK_STREAM0; i < CSI2TX_PAD_MAX; i++)
503 		csi2tx->pads[i].flags = MEDIA_PAD_FL_SINK;
504 
505 	/*
506 	 * Only the input pads are considered to have a format at the
507 	 * moment. The CSI link can multiplex various streams with
508 	 * different formats, and we can't expose this in v4l2 right
509 	 * now.
510 	 */
511 	for (i = CSI2TX_PAD_SINK_STREAM0; i < CSI2TX_PAD_MAX; i++)
512 		csi2tx->pad_fmts[i] = fmt_default;
513 
514 	ret = media_entity_pads_init(&csi2tx->subdev.entity, CSI2TX_PAD_MAX,
515 				     csi2tx->pads);
516 	if (ret)
517 		goto err_free_priv;
518 
519 	ret = v4l2_async_register_subdev(&csi2tx->subdev);
520 	if (ret < 0)
521 		goto err_free_priv;
522 
523 	dev_info(&pdev->dev,
524 		 "Probed CSI2TX with %u/%u lanes, %u streams, %s D-PHY\n",
525 		 csi2tx->num_lanes, csi2tx->max_lanes, csi2tx->max_streams,
526 		 csi2tx->has_internal_dphy ? "internal" : "no");
527 
528 	return 0;
529 
530 err_free_priv:
531 	kfree(csi2tx);
532 	return ret;
533 }
534 
535 static int csi2tx_remove(struct platform_device *pdev)
536 {
537 	struct csi2tx_priv *csi2tx = platform_get_drvdata(pdev);
538 
539 	v4l2_async_unregister_subdev(&csi2tx->subdev);
540 	kfree(csi2tx);
541 
542 	return 0;
543 }
544 
545 static const struct of_device_id csi2tx_of_table[] = {
546 	{ .compatible = "cdns,csi2tx" },
547 	{ },
548 };
549 MODULE_DEVICE_TABLE(of, csi2tx_of_table);
550 
551 static struct platform_driver csi2tx_driver = {
552 	.probe	= csi2tx_probe,
553 	.remove	= csi2tx_remove,
554 
555 	.driver	= {
556 		.name		= "cdns-csi2tx",
557 		.of_match_table	= csi2tx_of_table,
558 	},
559 };
560 module_platform_driver(csi2tx_driver);
561 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin.com>");
562 MODULE_DESCRIPTION("Cadence CSI2-TX controller");
563 MODULE_LICENSE("GPL");
564