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