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