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