1e58f3082SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0+
23e89586aSKieran Bingham /*
33e89586aSKieran Bingham  * Driver for Analog Devices ADV748X CSI-2 Transmitter
43e89586aSKieran Bingham  *
53e89586aSKieran Bingham  * Copyright (C) 2017 Renesas Electronics Corp.
63e89586aSKieran Bingham  */
73e89586aSKieran Bingham 
83e89586aSKieran Bingham #include <linux/module.h>
93e89586aSKieran Bingham #include <linux/mutex.h>
103e89586aSKieran Bingham 
113e89586aSKieran Bingham #include <media/v4l2-ctrls.h>
123e89586aSKieran Bingham #include <media/v4l2-device.h>
133e89586aSKieran Bingham #include <media/v4l2-ioctl.h>
143e89586aSKieran Bingham 
153e89586aSKieran Bingham #include "adv748x.h"
163e89586aSKieran Bingham 
adv748x_csi2_set_virtual_channel(struct adv748x_csi2 * tx,unsigned int vc)1742bff048SNiklas Söderlund int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx, unsigned int vc)
183e89586aSKieran Bingham {
193e89586aSKieran Bingham 	return tx_write(tx, ADV748X_CSI_VC_REF, vc << ADV748X_CSI_VC_REF_SHIFT);
203e89586aSKieran Bingham }
213e89586aSKieran Bingham 
223e89586aSKieran Bingham /**
233e89586aSKieran Bingham  * adv748x_csi2_register_link : Register and link internal entities
243e89586aSKieran Bingham  *
253e89586aSKieran Bingham  * @tx: CSI2 private entity
263e89586aSKieran Bingham  * @v4l2_dev: Video registration device
273e89586aSKieran Bingham  * @src: Source subdevice to establish link
283e89586aSKieran Bingham  * @src_pad: Pad number of source to link to this @tx
2921325e19SJacopo Mondi  * @enable: Link enabled flag
303e89586aSKieran Bingham  *
313e89586aSKieran Bingham  * Ensure that the subdevice is registered against the v4l2_device, and link the
323e89586aSKieran Bingham  * source pad to the sink pad of the CSI2 bus entity.
333e89586aSKieran Bingham  */
adv748x_csi2_register_link(struct adv748x_csi2 * tx,struct v4l2_device * v4l2_dev,struct v4l2_subdev * src,unsigned int src_pad,bool enable)343e89586aSKieran Bingham static int adv748x_csi2_register_link(struct adv748x_csi2 *tx,
353e89586aSKieran Bingham 				      struct v4l2_device *v4l2_dev,
363e89586aSKieran Bingham 				      struct v4l2_subdev *src,
3721325e19SJacopo Mondi 				      unsigned int src_pad,
3821325e19SJacopo Mondi 				      bool enable)
393e89586aSKieran Bingham {
403e89586aSKieran Bingham 	int ret;
413e89586aSKieran Bingham 
423e89586aSKieran Bingham 	if (!src->v4l2_dev) {
433e89586aSKieran Bingham 		ret = v4l2_device_register_subdev(v4l2_dev, src);
443e89586aSKieran Bingham 		if (ret)
453e89586aSKieran Bingham 			return ret;
463e89586aSKieran Bingham 	}
473e89586aSKieran Bingham 
483361b9c4SJacopo Mondi 	ret = media_create_pad_link(&src->entity, src_pad,
493e89586aSKieran Bingham 				    &tx->sd.entity, ADV748X_CSI2_SINK,
5021325e19SJacopo Mondi 				    enable ? MEDIA_LNK_FL_ENABLED : 0);
513361b9c4SJacopo Mondi 	if (ret)
523361b9c4SJacopo Mondi 		return ret;
533361b9c4SJacopo Mondi 
543361b9c4SJacopo Mondi 	if (enable)
553361b9c4SJacopo Mondi 		tx->src = src;
563361b9c4SJacopo Mondi 
573361b9c4SJacopo Mondi 	return 0;
583e89586aSKieran Bingham }
593e89586aSKieran Bingham 
603e89586aSKieran Bingham /* -----------------------------------------------------------------------------
613e89586aSKieran Bingham  * v4l2_subdev_internal_ops
623e89586aSKieran Bingham  *
633e89586aSKieran Bingham  * We use the internal registered operation to be able to ensure that our
643e89586aSKieran Bingham  * incremental subdevices (not connected in the forward path) can be registered
653e89586aSKieran Bingham  * against the resulting video path and media device.
663e89586aSKieran Bingham  */
673e89586aSKieran Bingham 
adv748x_csi2_registered(struct v4l2_subdev * sd)683e89586aSKieran Bingham static int adv748x_csi2_registered(struct v4l2_subdev *sd)
693e89586aSKieran Bingham {
703e89586aSKieran Bingham 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
713e89586aSKieran Bingham 	struct adv748x_state *state = tx->state;
7221325e19SJacopo Mondi 	int ret;
733e89586aSKieran Bingham 
743e89586aSKieran Bingham 	adv_dbg(state, "Registered %s (%s)", is_txa(tx) ? "TXA":"TXB",
753e89586aSKieran Bingham 			sd->name);
763e89586aSKieran Bingham 
773e89586aSKieran Bingham 	/*
7821325e19SJacopo Mondi 	 * Link TXA to AFE and HDMI, and TXB to AFE only as TXB cannot output
7921325e19SJacopo Mondi 	 * HDMI.
803e89586aSKieran Bingham 	 *
8121325e19SJacopo Mondi 	 * The HDMI->TXA link is enabled by default, as is the AFE->TXB one.
823e89586aSKieran Bingham 	 */
8321325e19SJacopo Mondi 	if (is_afe_enabled(state)) {
8421325e19SJacopo Mondi 		ret = adv748x_csi2_register_link(tx, sd->v4l2_dev,
853e89586aSKieran Bingham 						 &state->afe.sd,
8621325e19SJacopo Mondi 						 ADV748X_AFE_SOURCE,
8721325e19SJacopo Mondi 						 is_txb(tx));
8821325e19SJacopo Mondi 		if (ret)
8921325e19SJacopo Mondi 			return ret;
90a33df6acSJacopo Mondi 
91a33df6acSJacopo Mondi 		/* TXB can output AFE signals only. */
92a33df6acSJacopo Mondi 		if (is_txb(tx))
93a33df6acSJacopo Mondi 			state->afe.tx = tx;
9421325e19SJacopo Mondi 	}
9521325e19SJacopo Mondi 
9621325e19SJacopo Mondi 	/* Register link to HDMI for TXA only. */
9721325e19SJacopo Mondi 	if (is_txb(tx) || !is_hdmi_enabled(state))
981e2cb06fSJacopo Mondi 		return 0;
9921325e19SJacopo Mondi 
100a33df6acSJacopo Mondi 	ret = adv748x_csi2_register_link(tx, sd->v4l2_dev, &state->hdmi.sd,
10121325e19SJacopo Mondi 					 ADV748X_HDMI_SOURCE, true);
102a33df6acSJacopo Mondi 	if (ret)
103a33df6acSJacopo Mondi 		return ret;
104a33df6acSJacopo Mondi 
105a33df6acSJacopo Mondi 	/* The default HDMI output is TXA. */
106a33df6acSJacopo Mondi 	state->hdmi.tx = tx;
107a33df6acSJacopo Mondi 
108a33df6acSJacopo Mondi 	return 0;
1093e89586aSKieran Bingham }
1103e89586aSKieran Bingham 
1113e89586aSKieran Bingham static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops = {
1123e89586aSKieran Bingham 	.registered = adv748x_csi2_registered,
1133e89586aSKieran Bingham };
1143e89586aSKieran Bingham 
1153e89586aSKieran Bingham /* -----------------------------------------------------------------------------
1163e89586aSKieran Bingham  * v4l2_subdev_video_ops
1173e89586aSKieran Bingham  */
1183e89586aSKieran Bingham 
adv748x_csi2_s_stream(struct v4l2_subdev * sd,int enable)1193e89586aSKieran Bingham static int adv748x_csi2_s_stream(struct v4l2_subdev *sd, int enable)
1203e89586aSKieran Bingham {
1213e89586aSKieran Bingham 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
1223e89586aSKieran Bingham 	struct v4l2_subdev *src;
1233e89586aSKieran Bingham 
1243e89586aSKieran Bingham 	src = adv748x_get_remote_sd(&tx->pads[ADV748X_CSI2_SINK]);
1253e89586aSKieran Bingham 	if (!src)
1263e89586aSKieran Bingham 		return -EPIPE;
1273e89586aSKieran Bingham 
1283e89586aSKieran Bingham 	return v4l2_subdev_call(src, video, s_stream, enable);
1293e89586aSKieran Bingham }
1303e89586aSKieran Bingham 
1313e89586aSKieran Bingham static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops = {
1323e89586aSKieran Bingham 	.s_stream = adv748x_csi2_s_stream,
1333e89586aSKieran Bingham };
1343e89586aSKieran Bingham 
1353e89586aSKieran Bingham /* -----------------------------------------------------------------------------
1363e89586aSKieran Bingham  * v4l2_subdev_pad_ops
1373e89586aSKieran Bingham  *
1383e89586aSKieran Bingham  * The CSI2 bus pads are ignorant to the data sizes or formats.
1393e89586aSKieran Bingham  * But we must support setting the pad formats for format propagation.
1403e89586aSKieran Bingham  */
1413e89586aSKieran Bingham 
1423e89586aSKieran Bingham 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)1433e89586aSKieran Bingham adv748x_csi2_get_pad_format(struct v4l2_subdev *sd,
1440d346d2aSTomi Valkeinen 			    struct v4l2_subdev_state *sd_state,
1453e89586aSKieran Bingham 			    unsigned int pad, u32 which)
1463e89586aSKieran Bingham {
1473e89586aSKieran Bingham 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
1483e89586aSKieran Bingham 
1493e89586aSKieran Bingham 	if (which == V4L2_SUBDEV_FORMAT_TRY)
1500d346d2aSTomi Valkeinen 		return v4l2_subdev_get_try_format(sd, sd_state, pad);
1513e89586aSKieran Bingham 
1523e89586aSKieran Bingham 	return &tx->format;
1533e89586aSKieran Bingham }
1543e89586aSKieran Bingham 
adv748x_csi2_get_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * sdformat)1553e89586aSKieran Bingham static int adv748x_csi2_get_format(struct v4l2_subdev *sd,
1560d346d2aSTomi Valkeinen 				   struct v4l2_subdev_state *sd_state,
1573e89586aSKieran Bingham 				   struct v4l2_subdev_format *sdformat)
1583e89586aSKieran Bingham {
1593e89586aSKieran Bingham 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
1603e89586aSKieran Bingham 	struct adv748x_state *state = tx->state;
1613e89586aSKieran Bingham 	struct v4l2_mbus_framefmt *mbusformat;
1623e89586aSKieran Bingham 
1630d346d2aSTomi Valkeinen 	mbusformat = adv748x_csi2_get_pad_format(sd, sd_state, sdformat->pad,
1643e89586aSKieran Bingham 						 sdformat->which);
1653e89586aSKieran Bingham 	if (!mbusformat)
1663e89586aSKieran Bingham 		return -EINVAL;
1673e89586aSKieran Bingham 
1683e89586aSKieran Bingham 	mutex_lock(&state->mutex);
1693e89586aSKieran Bingham 
1703e89586aSKieran Bingham 	sdformat->format = *mbusformat;
1713e89586aSKieran Bingham 
1723e89586aSKieran Bingham 	mutex_unlock(&state->mutex);
1733e89586aSKieran Bingham 
1743e89586aSKieran Bingham 	return 0;
1753e89586aSKieran Bingham }
1763e89586aSKieran Bingham 
adv748x_csi2_set_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * sdformat)1773e89586aSKieran Bingham static int adv748x_csi2_set_format(struct v4l2_subdev *sd,
1780d346d2aSTomi Valkeinen 				   struct v4l2_subdev_state *sd_state,
1793e89586aSKieran Bingham 				   struct v4l2_subdev_format *sdformat)
1803e89586aSKieran Bingham {
1813e89586aSKieran Bingham 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
1823e89586aSKieran Bingham 	struct adv748x_state *state = tx->state;
1833e89586aSKieran Bingham 	struct v4l2_mbus_framefmt *mbusformat;
1843e89586aSKieran Bingham 	int ret = 0;
1853e89586aSKieran Bingham 
1860d346d2aSTomi Valkeinen 	mbusformat = adv748x_csi2_get_pad_format(sd, sd_state, sdformat->pad,
1873e89586aSKieran Bingham 						 sdformat->which);
1883e89586aSKieran Bingham 	if (!mbusformat)
1893e89586aSKieran Bingham 		return -EINVAL;
1903e89586aSKieran Bingham 
1913e89586aSKieran Bingham 	mutex_lock(&state->mutex);
1923e89586aSKieran Bingham 
1933e89586aSKieran Bingham 	if (sdformat->pad == ADV748X_CSI2_SOURCE) {
1943e89586aSKieran Bingham 		const struct v4l2_mbus_framefmt *sink_fmt;
1953e89586aSKieran Bingham 
1960d346d2aSTomi Valkeinen 		sink_fmt = adv748x_csi2_get_pad_format(sd, sd_state,
1973e89586aSKieran Bingham 						       ADV748X_CSI2_SINK,
1983e89586aSKieran Bingham 						       sdformat->which);
1993e89586aSKieran Bingham 
2003e89586aSKieran Bingham 		if (!sink_fmt) {
2013e89586aSKieran Bingham 			ret = -EINVAL;
2023e89586aSKieran Bingham 			goto unlock;
2033e89586aSKieran Bingham 		}
2043e89586aSKieran Bingham 
2053e89586aSKieran Bingham 		sdformat->format = *sink_fmt;
2063e89586aSKieran Bingham 	}
2073e89586aSKieran Bingham 
2083e89586aSKieran Bingham 	*mbusformat = sdformat->format;
2093e89586aSKieran Bingham 
2103e89586aSKieran Bingham unlock:
2113e89586aSKieran Bingham 	mutex_unlock(&state->mutex);
2123e89586aSKieran Bingham 
2133e89586aSKieran Bingham 	return ret;
2143e89586aSKieran Bingham }
2153e89586aSKieran Bingham 
adv748x_csi2_get_mbus_config(struct v4l2_subdev * sd,unsigned int pad,struct v4l2_mbus_config * config)216a61b1b5dSJacopo Mondi static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
217a61b1b5dSJacopo Mondi 					struct v4l2_mbus_config *config)
218a61b1b5dSJacopo Mondi {
219a61b1b5dSJacopo Mondi 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
220a61b1b5dSJacopo Mondi 
221a61b1b5dSJacopo Mondi 	if (pad != ADV748X_CSI2_SOURCE)
222a61b1b5dSJacopo Mondi 		return -EINVAL;
223a61b1b5dSJacopo Mondi 
224a61b1b5dSJacopo Mondi 	config->type = V4L2_MBUS_CSI2_DPHY;
2256a7bdd89SLaurent Pinchart 	config->bus.mipi_csi2.num_data_lanes = tx->active_lanes;
226a61b1b5dSJacopo Mondi 
227a61b1b5dSJacopo Mondi 	return 0;
228a61b1b5dSJacopo Mondi }
229a61b1b5dSJacopo Mondi 
2303e89586aSKieran Bingham static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = {
2313e89586aSKieran Bingham 	.get_fmt = adv748x_csi2_get_format,
2323e89586aSKieran Bingham 	.set_fmt = adv748x_csi2_set_format,
233a61b1b5dSJacopo Mondi 	.get_mbus_config = adv748x_csi2_get_mbus_config,
2343e89586aSKieran Bingham };
2353e89586aSKieran Bingham 
2363e89586aSKieran Bingham /* -----------------------------------------------------------------------------
2373e89586aSKieran Bingham  * v4l2_subdev_ops
2383e89586aSKieran Bingham  */
2393e89586aSKieran Bingham 
2403e89586aSKieran Bingham static const struct v4l2_subdev_ops adv748x_csi2_ops = {
2413e89586aSKieran Bingham 	.video = &adv748x_csi2_video_ops,
2423e89586aSKieran Bingham 	.pad = &adv748x_csi2_pad_ops,
2433e89586aSKieran Bingham };
2443e89586aSKieran Bingham 
2453e89586aSKieran Bingham /* -----------------------------------------------------------------------------
2463e89586aSKieran Bingham  * Subdev module and controls
2473e89586aSKieran Bingham  */
2483e89586aSKieran Bingham 
adv748x_csi2_set_pixelrate(struct v4l2_subdev * sd,s64 rate)2493e89586aSKieran Bingham int adv748x_csi2_set_pixelrate(struct v4l2_subdev *sd, s64 rate)
2503e89586aSKieran Bingham {
251b0fe7778SKieran Bingham 	struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
2523e89586aSKieran Bingham 
253b0fe7778SKieran Bingham 	if (!tx->pixel_rate)
2543e89586aSKieran Bingham 		return -EINVAL;
2553e89586aSKieran Bingham 
256b0fe7778SKieran Bingham 	return v4l2_ctrl_s_ctrl_int64(tx->pixel_rate, rate);
2573e89586aSKieran Bingham }
2583e89586aSKieran Bingham 
adv748x_csi2_s_ctrl(struct v4l2_ctrl * ctrl)2593e89586aSKieran Bingham static int adv748x_csi2_s_ctrl(struct v4l2_ctrl *ctrl)
2603e89586aSKieran Bingham {
2613e89586aSKieran Bingham 	switch (ctrl->id) {
2623e89586aSKieran Bingham 	case V4L2_CID_PIXEL_RATE:
2633e89586aSKieran Bingham 		return 0;
2643e89586aSKieran Bingham 	default:
2653e89586aSKieran Bingham 		return -EINVAL;
2663e89586aSKieran Bingham 	}
2673e89586aSKieran Bingham }
2683e89586aSKieran Bingham 
2693e89586aSKieran Bingham static const struct v4l2_ctrl_ops adv748x_csi2_ctrl_ops = {
2703e89586aSKieran Bingham 	.s_ctrl = adv748x_csi2_s_ctrl,
2713e89586aSKieran Bingham };
2723e89586aSKieran Bingham 
adv748x_csi2_init_controls(struct adv748x_csi2 * tx)2733e89586aSKieran Bingham static int adv748x_csi2_init_controls(struct adv748x_csi2 *tx)
2743e89586aSKieran Bingham {
2753e89586aSKieran Bingham 
2763e89586aSKieran Bingham 	v4l2_ctrl_handler_init(&tx->ctrl_hdl, 1);
2773e89586aSKieran Bingham 
278b0fe7778SKieran Bingham 	tx->pixel_rate = v4l2_ctrl_new_std(&tx->ctrl_hdl,
279b0fe7778SKieran Bingham 					   &adv748x_csi2_ctrl_ops,
280b0fe7778SKieran Bingham 					   V4L2_CID_PIXEL_RATE, 1, INT_MAX,
281b0fe7778SKieran Bingham 					   1, 1);
2823e89586aSKieran Bingham 
2833e89586aSKieran Bingham 	tx->sd.ctrl_handler = &tx->ctrl_hdl;
2843e89586aSKieran Bingham 	if (tx->ctrl_hdl.error) {
2853e89586aSKieran Bingham 		v4l2_ctrl_handler_free(&tx->ctrl_hdl);
2863e89586aSKieran Bingham 		return tx->ctrl_hdl.error;
2873e89586aSKieran Bingham 	}
2883e89586aSKieran Bingham 
2893e89586aSKieran Bingham 	return v4l2_ctrl_handler_setup(&tx->ctrl_hdl);
2903e89586aSKieran Bingham }
2913e89586aSKieran Bingham 
adv748x_csi2_init(struct adv748x_state * state,struct adv748x_csi2 * tx)2923e89586aSKieran Bingham int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
2933e89586aSKieran Bingham {
2943e89586aSKieran Bingham 	int ret;
2953e89586aSKieran Bingham 
296eccf442cSJacopo Mondi 	if (!is_tx_enabled(tx))
297eccf442cSJacopo Mondi 		return 0;
2983e89586aSKieran Bingham 
2993e89586aSKieran Bingham 	adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops,
300b7bf15c4SSteve Longerbeam 			    MEDIA_ENT_F_VID_IF_BRIDGE,
3013e89586aSKieran Bingham 			    is_txa(tx) ? "txa" : "txb");
3023e89586aSKieran Bingham 
3033e89586aSKieran Bingham 	/* Register internal ops for incremental subdev registration */
3043e89586aSKieran Bingham 	tx->sd.internal_ops = &adv748x_csi2_internal_ops;
3053e89586aSKieran Bingham 
3063e89586aSKieran Bingham 	tx->pads[ADV748X_CSI2_SINK].flags = MEDIA_PAD_FL_SINK;
3073e89586aSKieran Bingham 	tx->pads[ADV748X_CSI2_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
3083e89586aSKieran Bingham 
3093e89586aSKieran Bingham 	ret = media_entity_pads_init(&tx->sd.entity, ADV748X_CSI2_NR_PADS,
3103e89586aSKieran Bingham 				     tx->pads);
3113e89586aSKieran Bingham 	if (ret)
3123e89586aSKieran Bingham 		return ret;
3133e89586aSKieran Bingham 
314*1e345458SSakari Ailus 	ret = v4l2_async_subdev_endpoint_add(&tx->sd,
315*1e345458SSakari Ailus 					     of_fwnode_handle(state->endpoints[tx->port]));
3163e89586aSKieran Bingham 	if (ret)
3173e89586aSKieran Bingham 		goto err_free_media;
3183e89586aSKieran Bingham 
319*1e345458SSakari Ailus 	ret = adv748x_csi2_init_controls(tx);
320*1e345458SSakari Ailus 	if (ret)
321*1e345458SSakari Ailus 		goto err_cleanup_subdev;
322*1e345458SSakari Ailus 
3233e89586aSKieran Bingham 	ret = v4l2_async_register_subdev(&tx->sd);
3243e89586aSKieran Bingham 	if (ret)
3253e89586aSKieran Bingham 		goto err_free_ctrl;
3263e89586aSKieran Bingham 
3273e89586aSKieran Bingham 	return 0;
3283e89586aSKieran Bingham 
3293e89586aSKieran Bingham err_free_ctrl:
3303e89586aSKieran Bingham 	v4l2_ctrl_handler_free(&tx->ctrl_hdl);
331*1e345458SSakari Ailus err_cleanup_subdev:
332*1e345458SSakari Ailus 	v4l2_subdev_cleanup(&tx->sd);
3333e89586aSKieran Bingham err_free_media:
3343e89586aSKieran Bingham 	media_entity_cleanup(&tx->sd.entity);
3353e89586aSKieran Bingham 
3363e89586aSKieran Bingham 	return ret;
3373e89586aSKieran Bingham }
3383e89586aSKieran Bingham 
adv748x_csi2_cleanup(struct adv748x_csi2 * tx)3393e89586aSKieran Bingham void adv748x_csi2_cleanup(struct adv748x_csi2 *tx)
3403e89586aSKieran Bingham {
341eccf442cSJacopo Mondi 	if (!is_tx_enabled(tx))
342eccf442cSJacopo Mondi 		return;
343eccf442cSJacopo Mondi 
3443e89586aSKieran Bingham 	v4l2_async_unregister_subdev(&tx->sd);
3453e89586aSKieran Bingham 	media_entity_cleanup(&tx->sd.entity);
3463e89586aSKieran Bingham 	v4l2_ctrl_handler_free(&tx->ctrl_hdl);
347*1e345458SSakari Ailus 	v4l2_subdev_cleanup(&tx->sd);
3483e89586aSKieran Bingham }
349