xref: /linux/drivers/media/i2c/adv748x/adv748x-csi2.c (revision 55d0969c451159cff86949b38c39171cab962069)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Driver for Analog Devices ADV748X CSI-2 Transmitter
4  *
5  * Copyright (C) 2017 Renesas Electronics Corp.
6  */
7 
8 #include <linux/module.h>
9 
10 #include <media/v4l2-ctrls.h>
11 #include <media/v4l2-device.h>
12 #include <media/v4l2-ioctl.h>
13 
14 #include "adv748x.h"
15 
16 static const unsigned int adv748x_csi2_txa_fmts[] = {
17 	MEDIA_BUS_FMT_UYVY8_1X16,
18 	MEDIA_BUS_FMT_RGB888_1X24,
19 };
20 
21 static const unsigned int adv748x_csi2_txb_fmts[] = {
22 	MEDIA_BUS_FMT_UYVY8_1X16,
23 };
24 
25 int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx, unsigned int vc)
26 {
27 	return tx_write(tx, ADV748X_CSI_VC_REF, vc << ADV748X_CSI_VC_REF_SHIFT);
28 }
29 
30 /**
31  * adv748x_csi2_register_link : Register and link internal entities
32  *
33  * @tx: CSI2 private entity
34  * @v4l2_dev: Video registration device
35  * @src: Source subdevice to establish link
36  * @src_pad: Pad number of source to link to this @tx
37  * @enable: Link enabled flag
38  *
39  * Ensure that the subdevice is registered against the v4l2_device, and link the
40  * source pad to the sink pad of the CSI2 bus entity.
41  */
42 static int adv748x_csi2_register_link(struct adv748x_csi2 *tx,
43 				      struct v4l2_device *v4l2_dev,
44 				      struct v4l2_subdev *src,
45 				      unsigned int src_pad,
46 				      bool enable)
47 {
48 	int ret;
49 
50 	if (!src->v4l2_dev) {
51 		ret = v4l2_device_register_subdev(v4l2_dev, src);
52 		if (ret)
53 			return ret;
54 	}
55 
56 	ret = media_create_pad_link(&src->entity, src_pad,
57 				    &tx->sd.entity, ADV748X_CSI2_SINK,
58 				    enable ? MEDIA_LNK_FL_ENABLED : 0);
59 	if (ret)
60 		return ret;
61 
62 	if (enable)
63 		tx->src = src;
64 
65 	return 0;
66 }
67 
68 /* -----------------------------------------------------------------------------
69  * v4l2_subdev_internal_ops
70  */
71 
72 static int adv748x_csi2_init_state(struct v4l2_subdev *sd,
73 				   struct v4l2_subdev_state *state)
74 {
75 	static const struct v4l2_mbus_framefmt adv748x_csi2_default_fmt = {
76 		.width		= 1280,
77 		.height		= 720,
78 		.code		= MEDIA_BUS_FMT_UYVY8_1X16,
79 		.colorspace	= V4L2_COLORSPACE_SRGB,
80 		.field		= V4L2_FIELD_NONE,
81 		.ycbcr_enc	= V4L2_YCBCR_ENC_DEFAULT,
82 		.quantization	= V4L2_QUANTIZATION_DEFAULT,
83 		.xfer_func	= V4L2_XFER_FUNC_DEFAULT,
84 	};
85 	struct v4l2_mbus_framefmt *fmt;
86 
87 	fmt = v4l2_subdev_state_get_format(state, ADV748X_CSI2_SINK);
88 	*fmt = adv748x_csi2_default_fmt;
89 
90 	fmt = v4l2_subdev_state_get_format(state, ADV748X_CSI2_SOURCE);
91 	*fmt = adv748x_csi2_default_fmt;
92 
93 	return 0;
94 }
95 
96 /*
97  * We use the internal registered operation to be able to ensure that our
98  * incremental subdevices (not connected in the forward path) can be registered
99  * against the resulting video path and media device.
100  */
101 
102 static int adv748x_csi2_registered(struct v4l2_subdev *sd)
103 {
104 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
105 	struct adv748x_state *state = tx->state;
106 	int ret;
107 
108 	adv_dbg(state, "Registered %s (%s)", is_txa(tx) ? "TXA":"TXB",
109 			sd->name);
110 
111 	/*
112 	 * Link TXA to AFE and HDMI, and TXB to AFE only as TXB cannot output
113 	 * HDMI.
114 	 *
115 	 * The HDMI->TXA link is enabled by default, as is the AFE->TXB one.
116 	 */
117 	if (is_afe_enabled(state)) {
118 		ret = adv748x_csi2_register_link(tx, sd->v4l2_dev,
119 						 &state->afe.sd,
120 						 ADV748X_AFE_SOURCE,
121 						 is_txb(tx));
122 		if (ret)
123 			return ret;
124 
125 		/* TXB can output AFE signals only. */
126 		if (is_txb(tx))
127 			state->afe.tx = tx;
128 	}
129 
130 	/* Register link to HDMI for TXA only. */
131 	if (is_txb(tx) || !is_hdmi_enabled(state))
132 		return 0;
133 
134 	ret = adv748x_csi2_register_link(tx, sd->v4l2_dev, &state->hdmi.sd,
135 					 ADV748X_HDMI_SOURCE, true);
136 	if (ret)
137 		return ret;
138 
139 	/* The default HDMI output is TXA. */
140 	state->hdmi.tx = tx;
141 
142 	return 0;
143 }
144 
145 static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops = {
146 	.init_state = adv748x_csi2_init_state,
147 	.registered = adv748x_csi2_registered,
148 };
149 
150 /* -----------------------------------------------------------------------------
151  * v4l2_subdev_video_ops
152  */
153 
154 static int adv748x_csi2_s_stream(struct v4l2_subdev *sd, int enable)
155 {
156 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
157 	struct v4l2_subdev *src;
158 
159 	src = adv748x_get_remote_sd(&tx->pads[ADV748X_CSI2_SINK]);
160 	if (!src)
161 		return -EPIPE;
162 
163 	return v4l2_subdev_call(src, video, s_stream, enable);
164 }
165 
166 static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops = {
167 	.s_stream = adv748x_csi2_s_stream,
168 };
169 
170 /* -----------------------------------------------------------------------------
171  * v4l2_subdev_pad_ops
172  *
173  * The CSI2 bus pads are ignorant to the data sizes or formats.
174  * But we must support setting the pad formats for format propagation.
175  */
176 
177 static int adv748x_csi2_enum_mbus_code(struct v4l2_subdev *sd,
178 				       struct v4l2_subdev_state *sd_state,
179 				       struct v4l2_subdev_mbus_code_enum *code)
180 {
181 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
182 	const unsigned int *codes = is_txa(tx) ?
183 				    adv748x_csi2_txa_fmts :
184 				    adv748x_csi2_txb_fmts;
185 	size_t num_fmts = is_txa(tx) ? ARRAY_SIZE(adv748x_csi2_txa_fmts)
186 				     : ARRAY_SIZE(adv748x_csi2_txb_fmts);
187 
188 	/*
189 	 * The format available on the source pad is the one applied on the sink
190 	 * pad.
191 	 */
192 	if (code->pad == ADV748X_CSI2_SOURCE) {
193 		struct v4l2_mbus_framefmt *fmt;
194 
195 		if (code->index)
196 			return -EINVAL;
197 
198 		fmt = v4l2_subdev_state_get_format(sd_state, ADV748X_CSI2_SINK);
199 		code->code = fmt->code;
200 
201 		return 0;
202 	}
203 
204 	if (code->index >= num_fmts)
205 		return -EINVAL;
206 
207 	code->code = codes[code->index];
208 
209 	return 0;
210 }
211 
212 static bool adv748x_csi2_is_fmt_supported(struct adv748x_csi2 *tx, u32 code)
213 {
214 	const unsigned int *codes = is_txa(tx) ?
215 				    adv748x_csi2_txa_fmts :
216 				    adv748x_csi2_txb_fmts;
217 	size_t num_fmts = is_txa(tx) ? ARRAY_SIZE(adv748x_csi2_txa_fmts)
218 				     : ARRAY_SIZE(adv748x_csi2_txb_fmts);
219 
220 	for (unsigned int i = 0; i < num_fmts; i++) {
221 		if (codes[i] == code)
222 			return true;
223 	}
224 
225 	return false;
226 }
227 
228 static int adv748x_csi2_set_format(struct v4l2_subdev *sd,
229 				   struct v4l2_subdev_state *sd_state,
230 				   struct v4l2_subdev_format *sdformat)
231 {
232 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
233 	struct v4l2_mbus_framefmt *mbusformat;
234 
235 	if (sdformat->pad == ADV748X_CSI2_SOURCE)
236 		return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
237 
238 	/*
239 	 * Make sure the format is supported, if not default it to
240 	 * UYVY8 as it's supported by both TXes.
241 	 */
242 	if (!adv748x_csi2_is_fmt_supported(tx, sdformat->format.code))
243 		sdformat->format.code = MEDIA_BUS_FMT_UYVY8_1X16;
244 
245 	mbusformat = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
246 	*mbusformat = sdformat->format;
247 
248 	/* Propagate format to the source pad. */
249 	mbusformat = v4l2_subdev_state_get_format(sd_state, ADV748X_CSI2_SOURCE);
250 	*mbusformat = sdformat->format;
251 
252 	return 0;
253 }
254 
255 static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
256 					struct v4l2_mbus_config *config)
257 {
258 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
259 
260 	if (pad != ADV748X_CSI2_SOURCE)
261 		return -EINVAL;
262 
263 	config->type = V4L2_MBUS_CSI2_DPHY;
264 	config->bus.mipi_csi2.num_data_lanes = tx->active_lanes;
265 
266 	return 0;
267 }
268 
269 static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = {
270 	.enum_mbus_code = adv748x_csi2_enum_mbus_code,
271 	.get_fmt = v4l2_subdev_get_fmt,
272 	.set_fmt = adv748x_csi2_set_format,
273 	.get_mbus_config = adv748x_csi2_get_mbus_config,
274 };
275 
276 /* -----------------------------------------------------------------------------
277  * v4l2_subdev_ops
278  */
279 
280 static const struct v4l2_subdev_ops adv748x_csi2_ops = {
281 	.video = &adv748x_csi2_video_ops,
282 	.pad = &adv748x_csi2_pad_ops,
283 };
284 
285 /* -----------------------------------------------------------------------------
286  * Subdev module and controls
287  */
288 
289 int adv748x_csi2_set_pixelrate(struct v4l2_subdev *sd, s64 rate)
290 {
291 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
292 
293 	if (!tx->pixel_rate)
294 		return -EINVAL;
295 
296 	return v4l2_ctrl_s_ctrl_int64(tx->pixel_rate, rate);
297 }
298 
299 static int adv748x_csi2_s_ctrl(struct v4l2_ctrl *ctrl)
300 {
301 	switch (ctrl->id) {
302 	case V4L2_CID_PIXEL_RATE:
303 		return 0;
304 	default:
305 		return -EINVAL;
306 	}
307 }
308 
309 static const struct v4l2_ctrl_ops adv748x_csi2_ctrl_ops = {
310 	.s_ctrl = adv748x_csi2_s_ctrl,
311 };
312 
313 static int adv748x_csi2_init_controls(struct adv748x_csi2 *tx)
314 {
315 
316 	v4l2_ctrl_handler_init(&tx->ctrl_hdl, 1);
317 
318 	tx->pixel_rate = v4l2_ctrl_new_std(&tx->ctrl_hdl,
319 					   &adv748x_csi2_ctrl_ops,
320 					   V4L2_CID_PIXEL_RATE, 1, INT_MAX,
321 					   1, 1);
322 
323 	tx->sd.ctrl_handler = &tx->ctrl_hdl;
324 	if (tx->ctrl_hdl.error) {
325 		v4l2_ctrl_handler_free(&tx->ctrl_hdl);
326 		return tx->ctrl_hdl.error;
327 	}
328 
329 	return v4l2_ctrl_handler_setup(&tx->ctrl_hdl);
330 }
331 
332 int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
333 {
334 	int ret;
335 
336 	if (!is_tx_enabled(tx))
337 		return 0;
338 
339 	adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops,
340 			    MEDIA_ENT_F_VID_IF_BRIDGE,
341 			    is_txa(tx) ? "txa" : "txb");
342 
343 	/* Register internal ops for incremental subdev registration */
344 	tx->sd.internal_ops = &adv748x_csi2_internal_ops;
345 
346 	tx->pads[ADV748X_CSI2_SINK].flags = MEDIA_PAD_FL_SINK;
347 	tx->pads[ADV748X_CSI2_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
348 
349 	ret = media_entity_pads_init(&tx->sd.entity, ADV748X_CSI2_NR_PADS,
350 				     tx->pads);
351 	if (ret)
352 		return ret;
353 
354 	ret = v4l2_async_subdev_endpoint_add(&tx->sd,
355 					     of_fwnode_handle(state->endpoints[tx->port]));
356 	if (ret)
357 		goto err_free_media;
358 
359 	ret = adv748x_csi2_init_controls(tx);
360 	if (ret)
361 		goto err_cleanup_subdev;
362 
363 	tx->sd.state_lock = &state->mutex;
364 	ret = v4l2_subdev_init_finalize(&tx->sd);
365 	if (ret)
366 		goto err_free_ctrl;
367 
368 	ret = v4l2_async_register_subdev(&tx->sd);
369 	if (ret)
370 		goto err_free_ctrl;
371 
372 	return 0;
373 
374 err_free_ctrl:
375 	v4l2_ctrl_handler_free(&tx->ctrl_hdl);
376 err_cleanup_subdev:
377 	v4l2_subdev_cleanup(&tx->sd);
378 err_free_media:
379 	media_entity_cleanup(&tx->sd.entity);
380 
381 	return ret;
382 }
383 
384 void adv748x_csi2_cleanup(struct adv748x_csi2 *tx)
385 {
386 	if (!is_tx_enabled(tx))
387 		return;
388 
389 	v4l2_async_unregister_subdev(&tx->sd);
390 	media_entity_cleanup(&tx->sd.entity);
391 	v4l2_ctrl_handler_free(&tx->ctrl_hdl);
392 	v4l2_subdev_cleanup(&tx->sd);
393 }
394