Lines Matching +full:tx +full:- +full:only
1 // SPDX-License-Identifier: GPL-2.0+
3 * Driver for Analog Devices ADV748X CSI-2 Transmitter
10 #include <media/v4l2-ctrls.h>
11 #include <media/v4l2-device.h>
12 #include <media/v4l2-ioctl.h>
25 int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx, unsigned int vc) in adv748x_csi2_set_virtual_channel() argument
27 return tx_write(tx, ADV748X_CSI_VC_REF, vc << ADV748X_CSI_VC_REF_SHIFT); in adv748x_csi2_set_virtual_channel()
33 * @tx: CSI2 private entity
36 * @src_pad: Pad number of source to link to this @tx
42 static int adv748x_csi2_register_link(struct adv748x_csi2 *tx, in adv748x_csi2_register_link() argument
50 if (!src->v4l2_dev) { in adv748x_csi2_register_link()
56 ret = media_create_pad_link(&src->entity, src_pad, in adv748x_csi2_register_link()
57 &tx->sd.entity, ADV748X_CSI2_SINK, in adv748x_csi2_register_link()
63 tx->src = src; in adv748x_csi2_register_link()
68 /* -----------------------------------------------------------------------------
104 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); in adv748x_csi2_registered() local
105 struct adv748x_state *state = tx->state; in adv748x_csi2_registered()
108 adv_dbg(state, "Registered %s (%s)", is_txa(tx) ? "TXA":"TXB", in adv748x_csi2_registered()
109 sd->name); in adv748x_csi2_registered()
112 * Link TXA to AFE and HDMI, and TXB to AFE only as TXB cannot output in adv748x_csi2_registered()
115 * The HDMI->TXA link is enabled by default, as is the AFE->TXB one. in adv748x_csi2_registered()
118 ret = adv748x_csi2_register_link(tx, sd->v4l2_dev, in adv748x_csi2_registered()
119 &state->afe.sd, in adv748x_csi2_registered()
121 is_txb(tx)); in adv748x_csi2_registered()
125 /* TXB can output AFE signals only. */ in adv748x_csi2_registered()
126 if (is_txb(tx)) in adv748x_csi2_registered()
127 state->afe.tx = tx; in adv748x_csi2_registered()
130 /* Register link to HDMI for TXA only. */ in adv748x_csi2_registered()
131 if (is_txb(tx) || !is_hdmi_enabled(state)) in adv748x_csi2_registered()
134 ret = adv748x_csi2_register_link(tx, sd->v4l2_dev, &state->hdmi.sd, in adv748x_csi2_registered()
140 state->hdmi.tx = tx; in adv748x_csi2_registered()
150 /* -----------------------------------------------------------------------------
156 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); in adv748x_csi2_s_stream() local
159 src = adv748x_get_remote_sd(&tx->pads[ADV748X_CSI2_SINK]); in adv748x_csi2_s_stream()
161 return -EPIPE; in adv748x_csi2_s_stream()
170 /* -----------------------------------------------------------------------------
181 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); in adv748x_csi2_enum_mbus_code() local
182 const unsigned int *codes = is_txa(tx) ? in adv748x_csi2_enum_mbus_code()
185 size_t num_fmts = is_txa(tx) ? ARRAY_SIZE(adv748x_csi2_txa_fmts) in adv748x_csi2_enum_mbus_code()
192 if (code->pad == ADV748X_CSI2_SOURCE) { in adv748x_csi2_enum_mbus_code()
195 if (code->index) in adv748x_csi2_enum_mbus_code()
196 return -EINVAL; in adv748x_csi2_enum_mbus_code()
199 code->code = fmt->code; in adv748x_csi2_enum_mbus_code()
204 if (code->index >= num_fmts) in adv748x_csi2_enum_mbus_code()
205 return -EINVAL; in adv748x_csi2_enum_mbus_code()
207 code->code = codes[code->index]; in adv748x_csi2_enum_mbus_code()
212 static bool adv748x_csi2_is_fmt_supported(struct adv748x_csi2 *tx, u32 code) in adv748x_csi2_is_fmt_supported() argument
214 const unsigned int *codes = is_txa(tx) ? in adv748x_csi2_is_fmt_supported()
217 size_t num_fmts = is_txa(tx) ? ARRAY_SIZE(adv748x_csi2_txa_fmts) in adv748x_csi2_is_fmt_supported()
232 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); in adv748x_csi2_set_format() local
235 if (sdformat->pad == ADV748X_CSI2_SOURCE) in adv748x_csi2_set_format()
242 if (!adv748x_csi2_is_fmt_supported(tx, sdformat->format.code)) in adv748x_csi2_set_format()
243 sdformat->format.code = MEDIA_BUS_FMT_UYVY8_1X16; in adv748x_csi2_set_format()
245 mbusformat = v4l2_subdev_state_get_format(sd_state, sdformat->pad); in adv748x_csi2_set_format()
246 *mbusformat = sdformat->format; in adv748x_csi2_set_format()
250 *mbusformat = sdformat->format; in adv748x_csi2_set_format()
258 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); in adv748x_csi2_get_mbus_config() local
261 return -EINVAL; in adv748x_csi2_get_mbus_config()
263 config->type = V4L2_MBUS_CSI2_DPHY; in adv748x_csi2_get_mbus_config()
264 config->bus.mipi_csi2.num_data_lanes = tx->active_lanes; in adv748x_csi2_get_mbus_config()
276 /* -----------------------------------------------------------------------------
285 /* -----------------------------------------------------------------------------
291 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); in adv748x_csi2_set_pixelrate() local
293 if (!tx->pixel_rate) in adv748x_csi2_set_pixelrate()
294 return -EINVAL; in adv748x_csi2_set_pixelrate()
296 return v4l2_ctrl_s_ctrl_int64(tx->pixel_rate, rate); in adv748x_csi2_set_pixelrate()
301 switch (ctrl->id) { in adv748x_csi2_s_ctrl()
305 return -EINVAL; in adv748x_csi2_s_ctrl()
313 static int adv748x_csi2_init_controls(struct adv748x_csi2 *tx) in adv748x_csi2_init_controls() argument
316 v4l2_ctrl_handler_init(&tx->ctrl_hdl, 1); in adv748x_csi2_init_controls()
318 tx->pixel_rate = v4l2_ctrl_new_std(&tx->ctrl_hdl, in adv748x_csi2_init_controls()
323 tx->sd.ctrl_handler = &tx->ctrl_hdl; in adv748x_csi2_init_controls()
324 if (tx->ctrl_hdl.error) { in adv748x_csi2_init_controls()
325 v4l2_ctrl_handler_free(&tx->ctrl_hdl); in adv748x_csi2_init_controls()
326 return tx->ctrl_hdl.error; in adv748x_csi2_init_controls()
329 return v4l2_ctrl_handler_setup(&tx->ctrl_hdl); in adv748x_csi2_init_controls()
332 int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) in adv748x_csi2_init() argument
336 if (!is_tx_enabled(tx)) in adv748x_csi2_init()
339 adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops, in adv748x_csi2_init()
341 is_txa(tx) ? "txa" : "txb"); in adv748x_csi2_init()
344 tx->sd.internal_ops = &adv748x_csi2_internal_ops; in adv748x_csi2_init()
346 tx->pads[ADV748X_CSI2_SINK].flags = MEDIA_PAD_FL_SINK; in adv748x_csi2_init()
347 tx->pads[ADV748X_CSI2_SOURCE].flags = MEDIA_PAD_FL_SOURCE; in adv748x_csi2_init()
349 ret = media_entity_pads_init(&tx->sd.entity, ADV748X_CSI2_NR_PADS, in adv748x_csi2_init()
350 tx->pads); in adv748x_csi2_init()
354 ret = v4l2_async_subdev_endpoint_add(&tx->sd, in adv748x_csi2_init()
355 of_fwnode_handle(state->endpoints[tx->port])); in adv748x_csi2_init()
359 ret = adv748x_csi2_init_controls(tx); in adv748x_csi2_init()
363 tx->sd.state_lock = &state->mutex; in adv748x_csi2_init()
364 ret = v4l2_subdev_init_finalize(&tx->sd); in adv748x_csi2_init()
368 ret = v4l2_async_register_subdev(&tx->sd); in adv748x_csi2_init()
375 v4l2_ctrl_handler_free(&tx->ctrl_hdl); in adv748x_csi2_init()
377 v4l2_subdev_cleanup(&tx->sd); in adv748x_csi2_init()
379 media_entity_cleanup(&tx->sd.entity); in adv748x_csi2_init()
384 void adv748x_csi2_cleanup(struct adv748x_csi2 *tx) in adv748x_csi2_cleanup() argument
386 if (!is_tx_enabled(tx)) in adv748x_csi2_cleanup()
389 v4l2_async_unregister_subdev(&tx->sd); in adv748x_csi2_cleanup()
390 media_entity_cleanup(&tx->sd.entity); in adv748x_csi2_cleanup()
391 v4l2_ctrl_handler_free(&tx->ctrl_hdl); in adv748x_csi2_cleanup()
392 v4l2_subdev_cleanup(&tx->sd); in adv748x_csi2_cleanup()