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