2 * Driver for Analog Devices ADV748X CSI-2 Transmitter
4 * Copyright (C) 2017 Renesas Electronics Corp.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
12 #include <linux/module.h>
13 #include <linux/mutex.h>
15 #include <media/v4l2-ctrls.h>
16 #include <media/v4l2-device.h>
17 #include <media/v4l2-ioctl.h>
21 static bool is_txa(struct adv748x_csi2
*tx
)
23 return tx
== &tx
->state
->txa
;
26 static int adv748x_csi2_set_virtual_channel(struct adv748x_csi2
*tx
,
29 return tx_write(tx
, ADV748X_CSI_VC_REF
, vc
<< ADV748X_CSI_VC_REF_SHIFT
);
33 * adv748x_csi2_register_link : Register and link internal entities
35 * @tx: CSI2 private entity
36 * @v4l2_dev: Video registration device
37 * @src: Source subdevice to establish link
38 * @src_pad: Pad number of source to link to this @tx
40 * Ensure that the subdevice is registered against the v4l2_device, and link the
41 * source pad to the sink pad of the CSI2 bus entity.
43 static int adv748x_csi2_register_link(struct adv748x_csi2
*tx
,
44 struct v4l2_device
*v4l2_dev
,
45 struct v4l2_subdev
*src
,
48 int enabled
= MEDIA_LNK_FL_ENABLED
;
52 * Dynamic linking of the AFE is not supported.
53 * Register the links as immutable.
55 enabled
|= MEDIA_LNK_FL_IMMUTABLE
;
58 ret
= v4l2_device_register_subdev(v4l2_dev
, src
);
63 return media_create_pad_link(&src
->entity
, src_pad
,
64 &tx
->sd
.entity
, ADV748X_CSI2_SINK
,
68 /* -----------------------------------------------------------------------------
69 * v4l2_subdev_internal_ops
71 * We use the internal registered operation to be able to ensure that our
72 * incremental subdevices (not connected in the forward path) can be registered
73 * against the resulting video path and media device.
76 static int adv748x_csi2_registered(struct v4l2_subdev
*sd
)
78 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
79 struct adv748x_state
*state
= tx
->state
;
81 adv_dbg(state
, "Registered %s (%s)", is_txa(tx
) ? "TXA":"TXB",
85 * The adv748x hardware allows the AFE to route through the TXA, however
86 * this is not currently supported in this driver.
88 * Link HDMI->TXA, and AFE->TXB directly.
91 return adv748x_csi2_register_link(tx
, sd
->v4l2_dev
,
95 return adv748x_csi2_register_link(tx
, sd
->v4l2_dev
,
101 static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops
= {
102 .registered
= adv748x_csi2_registered
,
105 /* -----------------------------------------------------------------------------
106 * v4l2_subdev_video_ops
109 static int adv748x_csi2_s_stream(struct v4l2_subdev
*sd
, int enable
)
111 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
112 struct v4l2_subdev
*src
;
114 src
= adv748x_get_remote_sd(&tx
->pads
[ADV748X_CSI2_SINK
]);
118 return v4l2_subdev_call(src
, video
, s_stream
, enable
);
121 static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops
= {
122 .s_stream
= adv748x_csi2_s_stream
,
125 /* -----------------------------------------------------------------------------
126 * v4l2_subdev_pad_ops
128 * The CSI2 bus pads are ignorant to the data sizes or formats.
129 * But we must support setting the pad formats for format propagation.
132 static struct v4l2_mbus_framefmt
*
133 adv748x_csi2_get_pad_format(struct v4l2_subdev
*sd
,
134 struct v4l2_subdev_pad_config
*cfg
,
135 unsigned int pad
, u32 which
)
137 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
139 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
140 return v4l2_subdev_get_try_format(sd
, cfg
, pad
);
145 static int adv748x_csi2_get_format(struct v4l2_subdev
*sd
,
146 struct v4l2_subdev_pad_config
*cfg
,
147 struct v4l2_subdev_format
*sdformat
)
149 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
150 struct adv748x_state
*state
= tx
->state
;
151 struct v4l2_mbus_framefmt
*mbusformat
;
153 mbusformat
= adv748x_csi2_get_pad_format(sd
, cfg
, sdformat
->pad
,
158 mutex_lock(&state
->mutex
);
160 sdformat
->format
= *mbusformat
;
162 mutex_unlock(&state
->mutex
);
167 static int adv748x_csi2_set_format(struct v4l2_subdev
*sd
,
168 struct v4l2_subdev_pad_config
*cfg
,
169 struct v4l2_subdev_format
*sdformat
)
171 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
172 struct adv748x_state
*state
= tx
->state
;
173 struct v4l2_mbus_framefmt
*mbusformat
;
176 mbusformat
= adv748x_csi2_get_pad_format(sd
, cfg
, sdformat
->pad
,
181 mutex_lock(&state
->mutex
);
183 if (sdformat
->pad
== ADV748X_CSI2_SOURCE
) {
184 const struct v4l2_mbus_framefmt
*sink_fmt
;
186 sink_fmt
= adv748x_csi2_get_pad_format(sd
, cfg
,
195 sdformat
->format
= *sink_fmt
;
198 *mbusformat
= sdformat
->format
;
201 mutex_unlock(&state
->mutex
);
206 static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops
= {
207 .get_fmt
= adv748x_csi2_get_format
,
208 .set_fmt
= adv748x_csi2_set_format
,
211 /* -----------------------------------------------------------------------------
215 static const struct v4l2_subdev_ops adv748x_csi2_ops
= {
216 .video
= &adv748x_csi2_video_ops
,
217 .pad
= &adv748x_csi2_pad_ops
,
220 /* -----------------------------------------------------------------------------
221 * Subdev module and controls
224 int adv748x_csi2_set_pixelrate(struct v4l2_subdev
*sd
, s64 rate
)
226 struct adv748x_csi2
*tx
= adv748x_sd_to_csi2(sd
);
231 return v4l2_ctrl_s_ctrl_int64(tx
->pixel_rate
, rate
);
234 static int adv748x_csi2_s_ctrl(struct v4l2_ctrl
*ctrl
)
237 case V4L2_CID_PIXEL_RATE
:
244 static const struct v4l2_ctrl_ops adv748x_csi2_ctrl_ops
= {
245 .s_ctrl
= adv748x_csi2_s_ctrl
,
248 static int adv748x_csi2_init_controls(struct adv748x_csi2
*tx
)
251 v4l2_ctrl_handler_init(&tx
->ctrl_hdl
, 1);
253 tx
->pixel_rate
= v4l2_ctrl_new_std(&tx
->ctrl_hdl
,
254 &adv748x_csi2_ctrl_ops
,
255 V4L2_CID_PIXEL_RATE
, 1, INT_MAX
,
258 tx
->sd
.ctrl_handler
= &tx
->ctrl_hdl
;
259 if (tx
->ctrl_hdl
.error
) {
260 v4l2_ctrl_handler_free(&tx
->ctrl_hdl
);
261 return tx
->ctrl_hdl
.error
;
264 return v4l2_ctrl_handler_setup(&tx
->ctrl_hdl
);
267 int adv748x_csi2_init(struct adv748x_state
*state
, struct adv748x_csi2
*tx
)
269 struct device_node
*ep
;
272 /* We can not use container_of to get back to the state with two TXs */
274 tx
->page
= is_txa(tx
) ? ADV748X_PAGE_TXA
: ADV748X_PAGE_TXB
;
276 ep
= state
->endpoints
[is_txa(tx
) ? ADV748X_PORT_TXA
: ADV748X_PORT_TXB
];
278 adv_err(state
, "No endpoint found for %s\n",
279 is_txa(tx
) ? "txa" : "txb");
283 /* Initialise the virtual channel */
284 adv748x_csi2_set_virtual_channel(tx
, 0);
286 adv748x_subdev_init(&tx
->sd
, state
, &adv748x_csi2_ops
,
287 MEDIA_ENT_F_VID_IF_BRIDGE
,
288 is_txa(tx
) ? "txa" : "txb");
290 /* Ensure that matching is based upon the endpoint fwnodes */
291 tx
->sd
.fwnode
= of_fwnode_handle(ep
);
293 /* Register internal ops for incremental subdev registration */
294 tx
->sd
.internal_ops
= &adv748x_csi2_internal_ops
;
296 tx
->pads
[ADV748X_CSI2_SINK
].flags
= MEDIA_PAD_FL_SINK
;
297 tx
->pads
[ADV748X_CSI2_SOURCE
].flags
= MEDIA_PAD_FL_SOURCE
;
299 ret
= media_entity_pads_init(&tx
->sd
.entity
, ADV748X_CSI2_NR_PADS
,
304 ret
= adv748x_csi2_init_controls(tx
);
308 ret
= v4l2_async_register_subdev(&tx
->sd
);
315 v4l2_ctrl_handler_free(&tx
->ctrl_hdl
);
317 media_entity_cleanup(&tx
->sd
.entity
);
322 void adv748x_csi2_cleanup(struct adv748x_csi2
*tx
)
324 v4l2_async_unregister_subdev(&tx
->sd
);
325 media_entity_cleanup(&tx
->sd
.entity
);
326 v4l2_ctrl_handler_free(&tx
->ctrl_hdl
);