1 // SPDX-License-Identifier: GPL-2.0+
3 * Driver for Analog Devices ADV748X CSI-2 Transmitter
5 * Copyright (C) 2017 Renesas Electronics Corp.
8 #include <linux/module.h>
9 #include <linux/mutex.h>
11 #include <media/v4l2-ctrls.h>
12 #include <media/v4l2-device.h>
13 #include <media/v4l2-ioctl.h>
17 int adv748x_csi2_set_virtual_channel(struct adv748x_csi2
*tx
, unsigned int vc
)
19 return tx_write(tx
, ADV748X_CSI_VC_REF
, vc
<< ADV748X_CSI_VC_REF_SHIFT
);
23 * adv748x_csi2_register_link : Register and link internal entities
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
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.
34 static int adv748x_csi2_register_link(struct adv748x_csi2
*tx
,
35 struct v4l2_device
*v4l2_dev
,
36 struct v4l2_subdev
*src
,
43 ret
= v4l2_device_register_subdev(v4l2_dev
, src
);
48 ret
= media_create_pad_link(&src
->entity
, src_pad
,
49 &tx
->sd
.entity
, ADV748X_CSI2_SINK
,
50 enable
? MEDIA_LNK_FL_ENABLED
: 0);
60 /* -----------------------------------------------------------------------------
61 * v4l2_subdev_internal_ops
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.
68 static int adv748x_csi2_registered(struct v4l2_subdev
*sd
)
70 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
71 struct adv748x_state
*state
= tx
->state
;
74 adv_dbg(state
, "Registered %s (%s)", is_txa(tx
) ? "TXA":"TXB",
78 * Link TXA to AFE and HDMI, and TXB to AFE only as TXB cannot output
81 * The HDMI->TXA link is enabled by default, as is the AFE->TXB one.
83 if (is_afe_enabled(state
)) {
84 ret
= adv748x_csi2_register_link(tx
, sd
->v4l2_dev
,
91 /* TXB can output AFE signals only. */
96 /* Register link to HDMI for TXA only. */
97 if (is_txb(tx
) || !is_hdmi_enabled(state
))
100 ret
= adv748x_csi2_register_link(tx
, sd
->v4l2_dev
, &state
->hdmi
.sd
,
101 ADV748X_HDMI_SOURCE
, true);
105 /* The default HDMI output is TXA. */
111 static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops
= {
112 .registered
= adv748x_csi2_registered
,
115 /* -----------------------------------------------------------------------------
116 * v4l2_subdev_video_ops
119 static int adv748x_csi2_s_stream(struct v4l2_subdev
*sd
, int enable
)
121 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
122 struct v4l2_subdev
*src
;
124 src
= adv748x_get_remote_sd(&tx
->pads
[ADV748X_CSI2_SINK
]);
128 return v4l2_subdev_call(src
, video
, s_stream
, enable
);
131 static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops
= {
132 .s_stream
= adv748x_csi2_s_stream
,
135 /* -----------------------------------------------------------------------------
136 * v4l2_subdev_pad_ops
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.
142 static struct v4l2_mbus_framefmt
*
143 adv748x_csi2_get_pad_format(struct v4l2_subdev
*sd
,
144 struct v4l2_subdev_pad_config
*cfg
,
145 unsigned int pad
, u32 which
)
147 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
149 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
150 return v4l2_subdev_get_try_format(sd
, cfg
, pad
);
155 static int adv748x_csi2_get_format(struct v4l2_subdev
*sd
,
156 struct v4l2_subdev_pad_config
*cfg
,
157 struct v4l2_subdev_format
*sdformat
)
159 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
160 struct adv748x_state
*state
= tx
->state
;
161 struct v4l2_mbus_framefmt
*mbusformat
;
163 mbusformat
= adv748x_csi2_get_pad_format(sd
, cfg
, sdformat
->pad
,
168 mutex_lock(&state
->mutex
);
170 sdformat
->format
= *mbusformat
;
172 mutex_unlock(&state
->mutex
);
177 static int adv748x_csi2_set_format(struct v4l2_subdev
*sd
,
178 struct v4l2_subdev_pad_config
*cfg
,
179 struct v4l2_subdev_format
*sdformat
)
181 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
182 struct adv748x_state
*state
= tx
->state
;
183 struct v4l2_mbus_framefmt
*mbusformat
;
186 mbusformat
= adv748x_csi2_get_pad_format(sd
, cfg
, sdformat
->pad
,
191 mutex_lock(&state
->mutex
);
193 if (sdformat
->pad
== ADV748X_CSI2_SOURCE
) {
194 const struct v4l2_mbus_framefmt
*sink_fmt
;
196 sink_fmt
= adv748x_csi2_get_pad_format(sd
, cfg
,
205 sdformat
->format
= *sink_fmt
;
208 *mbusformat
= sdformat
->format
;
211 mutex_unlock(&state
->mutex
);
216 static int adv748x_csi2_get_mbus_config(struct v4l2_subdev
*sd
, unsigned int pad
,
217 struct v4l2_mbus_config
*config
)
219 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
221 if (pad
!= ADV748X_CSI2_SOURCE
)
224 config
->type
= V4L2_MBUS_CSI2_DPHY
;
225 switch (tx
->active_lanes
) {
227 config
->flags
= V4L2_MBUS_CSI2_1_LANE
;
231 config
->flags
= V4L2_MBUS_CSI2_2_LANE
;
235 config
->flags
= V4L2_MBUS_CSI2_3_LANE
;
239 config
->flags
= V4L2_MBUS_CSI2_4_LANE
;
246 static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops
= {
247 .get_fmt
= adv748x_csi2_get_format
,
248 .set_fmt
= adv748x_csi2_set_format
,
249 .get_mbus_config
= adv748x_csi2_get_mbus_config
,
252 /* -----------------------------------------------------------------------------
256 static const struct v4l2_subdev_ops adv748x_csi2_ops
= {
257 .video
= &adv748x_csi2_video_ops
,
258 .pad
= &adv748x_csi2_pad_ops
,
261 /* -----------------------------------------------------------------------------
262 * Subdev module and controls
265 int adv748x_csi2_set_pixelrate(struct v4l2_subdev
*sd
, s64 rate
)
267 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
272 return v4l2_ctrl_s_ctrl_int64(tx
->pixel_rate
, rate
);
275 static int adv748x_csi2_s_ctrl(struct v4l2_ctrl
*ctrl
)
278 case V4L2_CID_PIXEL_RATE
:
285 static const struct v4l2_ctrl_ops adv748x_csi2_ctrl_ops
= {
286 .s_ctrl
= adv748x_csi2_s_ctrl
,
289 static int adv748x_csi2_init_controls(struct adv748x_csi2
*tx
)
292 v4l2_ctrl_handler_init(&tx
->ctrl_hdl
, 1);
294 tx
->pixel_rate
= v4l2_ctrl_new_std(&tx
->ctrl_hdl
,
295 &adv748x_csi2_ctrl_ops
,
296 V4L2_CID_PIXEL_RATE
, 1, INT_MAX
,
299 tx
->sd
.ctrl_handler
= &tx
->ctrl_hdl
;
300 if (tx
->ctrl_hdl
.error
) {
301 v4l2_ctrl_handler_free(&tx
->ctrl_hdl
);
302 return tx
->ctrl_hdl
.error
;
305 return v4l2_ctrl_handler_setup(&tx
->ctrl_hdl
);
308 int adv748x_csi2_init(struct adv748x_state
*state
, struct adv748x_csi2
*tx
)
312 if (!is_tx_enabled(tx
))
315 adv748x_subdev_init(&tx
->sd
, state
, &adv748x_csi2_ops
,
316 MEDIA_ENT_F_VID_IF_BRIDGE
,
317 is_txa(tx
) ? "txa" : "txb");
319 /* Ensure that matching is based upon the endpoint fwnodes */
320 tx
->sd
.fwnode
= of_fwnode_handle(state
->endpoints
[tx
->port
]);
322 /* Register internal ops for incremental subdev registration */
323 tx
->sd
.internal_ops
= &adv748x_csi2_internal_ops
;
325 tx
->pads
[ADV748X_CSI2_SINK
].flags
= MEDIA_PAD_FL_SINK
;
326 tx
->pads
[ADV748X_CSI2_SOURCE
].flags
= MEDIA_PAD_FL_SOURCE
;
328 ret
= media_entity_pads_init(&tx
->sd
.entity
, ADV748X_CSI2_NR_PADS
,
333 ret
= adv748x_csi2_init_controls(tx
);
337 ret
= v4l2_async_register_subdev(&tx
->sd
);
344 v4l2_ctrl_handler_free(&tx
->ctrl_hdl
);
346 media_entity_cleanup(&tx
->sd
.entity
);
351 void adv748x_csi2_cleanup(struct adv748x_csi2
*tx
)
353 if (!is_tx_enabled(tx
))
356 v4l2_async_unregister_subdev(&tx
->sd
);
357 media_entity_cleanup(&tx
->sd
.entity
);
358 v4l2_ctrl_handler_free(&tx
->ctrl_hdl
);