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 static bool is_txa(struct adv748x_csi2 *tx) 18 { 19 return tx == &tx->state->txa; 20 } 21 22 static int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx, 23 unsigned int vc) 24 { 25 return tx_write(tx, ADV748X_CSI_VC_REF, vc << ADV748X_CSI_VC_REF_SHIFT); 26 } 27 28 /** 29 * adv748x_csi2_register_link : Register and link internal entities 30 * 31 * @tx: CSI2 private entity 32 * @v4l2_dev: Video registration device 33 * @src: Source subdevice to establish link 34 * @src_pad: Pad number of source to link to this @tx 35 * 36 * Ensure that the subdevice is registered against the v4l2_device, and link the 37 * source pad to the sink pad of the CSI2 bus entity. 38 */ 39 static int adv748x_csi2_register_link(struct adv748x_csi2 *tx, 40 struct v4l2_device *v4l2_dev, 41 struct v4l2_subdev *src, 42 unsigned int src_pad) 43 { 44 int enabled = MEDIA_LNK_FL_ENABLED; 45 int ret; 46 47 /* 48 * Dynamic linking of the AFE is not supported. 49 * Register the links as immutable. 50 */ 51 enabled |= MEDIA_LNK_FL_IMMUTABLE; 52 53 if (!src->v4l2_dev) { 54 ret = v4l2_device_register_subdev(v4l2_dev, src); 55 if (ret) 56 return ret; 57 } 58 59 return media_create_pad_link(&src->entity, src_pad, 60 &tx->sd.entity, ADV748X_CSI2_SINK, 61 enabled); 62 } 63 64 /* ----------------------------------------------------------------------------- 65 * v4l2_subdev_internal_ops 66 * 67 * We use the internal registered operation to be able to ensure that our 68 * incremental subdevices (not connected in the forward path) can be registered 69 * against the resulting video path and media device. 70 */ 71 72 static int adv748x_csi2_registered(struct v4l2_subdev *sd) 73 { 74 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); 75 struct adv748x_state *state = tx->state; 76 77 adv_dbg(state, "Registered %s (%s)", is_txa(tx) ? "TXA":"TXB", 78 sd->name); 79 80 /* 81 * The adv748x hardware allows the AFE to route through the TXA, however 82 * this is not currently supported in this driver. 83 * 84 * Link HDMI->TXA, and AFE->TXB directly. 85 */ 86 if (is_txa(tx)) { 87 return adv748x_csi2_register_link(tx, sd->v4l2_dev, 88 &state->hdmi.sd, 89 ADV748X_HDMI_SOURCE); 90 } else { 91 return adv748x_csi2_register_link(tx, sd->v4l2_dev, 92 &state->afe.sd, 93 ADV748X_AFE_SOURCE); 94 } 95 } 96 97 static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops = { 98 .registered = adv748x_csi2_registered, 99 }; 100 101 /* ----------------------------------------------------------------------------- 102 * v4l2_subdev_video_ops 103 */ 104 105 static int adv748x_csi2_s_stream(struct v4l2_subdev *sd, int enable) 106 { 107 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); 108 struct v4l2_subdev *src; 109 110 src = adv748x_get_remote_sd(&tx->pads[ADV748X_CSI2_SINK]); 111 if (!src) 112 return -EPIPE; 113 114 return v4l2_subdev_call(src, video, s_stream, enable); 115 } 116 117 static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops = { 118 .s_stream = adv748x_csi2_s_stream, 119 }; 120 121 /* ----------------------------------------------------------------------------- 122 * v4l2_subdev_pad_ops 123 * 124 * The CSI2 bus pads are ignorant to the data sizes or formats. 125 * But we must support setting the pad formats for format propagation. 126 */ 127 128 static struct v4l2_mbus_framefmt * 129 adv748x_csi2_get_pad_format(struct v4l2_subdev *sd, 130 struct v4l2_subdev_pad_config *cfg, 131 unsigned int pad, u32 which) 132 { 133 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); 134 135 if (which == V4L2_SUBDEV_FORMAT_TRY) 136 return v4l2_subdev_get_try_format(sd, cfg, pad); 137 138 return &tx->format; 139 } 140 141 static int adv748x_csi2_get_format(struct v4l2_subdev *sd, 142 struct v4l2_subdev_pad_config *cfg, 143 struct v4l2_subdev_format *sdformat) 144 { 145 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); 146 struct adv748x_state *state = tx->state; 147 struct v4l2_mbus_framefmt *mbusformat; 148 149 mbusformat = adv748x_csi2_get_pad_format(sd, cfg, sdformat->pad, 150 sdformat->which); 151 if (!mbusformat) 152 return -EINVAL; 153 154 mutex_lock(&state->mutex); 155 156 sdformat->format = *mbusformat; 157 158 mutex_unlock(&state->mutex); 159 160 return 0; 161 } 162 163 static int adv748x_csi2_set_format(struct v4l2_subdev *sd, 164 struct v4l2_subdev_pad_config *cfg, 165 struct v4l2_subdev_format *sdformat) 166 { 167 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); 168 struct adv748x_state *state = tx->state; 169 struct v4l2_mbus_framefmt *mbusformat; 170 int ret = 0; 171 172 mbusformat = adv748x_csi2_get_pad_format(sd, cfg, sdformat->pad, 173 sdformat->which); 174 if (!mbusformat) 175 return -EINVAL; 176 177 mutex_lock(&state->mutex); 178 179 if (sdformat->pad == ADV748X_CSI2_SOURCE) { 180 const struct v4l2_mbus_framefmt *sink_fmt; 181 182 sink_fmt = adv748x_csi2_get_pad_format(sd, cfg, 183 ADV748X_CSI2_SINK, 184 sdformat->which); 185 186 if (!sink_fmt) { 187 ret = -EINVAL; 188 goto unlock; 189 } 190 191 sdformat->format = *sink_fmt; 192 } 193 194 *mbusformat = sdformat->format; 195 196 unlock: 197 mutex_unlock(&state->mutex); 198 199 return ret; 200 } 201 202 static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { 203 .get_fmt = adv748x_csi2_get_format, 204 .set_fmt = adv748x_csi2_set_format, 205 }; 206 207 /* ----------------------------------------------------------------------------- 208 * v4l2_subdev_ops 209 */ 210 211 static const struct v4l2_subdev_ops adv748x_csi2_ops = { 212 .video = &adv748x_csi2_video_ops, 213 .pad = &adv748x_csi2_pad_ops, 214 }; 215 216 /* ----------------------------------------------------------------------------- 217 * Subdev module and controls 218 */ 219 220 int adv748x_csi2_set_pixelrate(struct v4l2_subdev *sd, s64 rate) 221 { 222 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); 223 224 if (!tx->pixel_rate) 225 return -EINVAL; 226 227 return v4l2_ctrl_s_ctrl_int64(tx->pixel_rate, rate); 228 } 229 230 static int adv748x_csi2_s_ctrl(struct v4l2_ctrl *ctrl) 231 { 232 switch (ctrl->id) { 233 case V4L2_CID_PIXEL_RATE: 234 return 0; 235 default: 236 return -EINVAL; 237 } 238 } 239 240 static const struct v4l2_ctrl_ops adv748x_csi2_ctrl_ops = { 241 .s_ctrl = adv748x_csi2_s_ctrl, 242 }; 243 244 static int adv748x_csi2_init_controls(struct adv748x_csi2 *tx) 245 { 246 247 v4l2_ctrl_handler_init(&tx->ctrl_hdl, 1); 248 249 tx->pixel_rate = v4l2_ctrl_new_std(&tx->ctrl_hdl, 250 &adv748x_csi2_ctrl_ops, 251 V4L2_CID_PIXEL_RATE, 1, INT_MAX, 252 1, 1); 253 254 tx->sd.ctrl_handler = &tx->ctrl_hdl; 255 if (tx->ctrl_hdl.error) { 256 v4l2_ctrl_handler_free(&tx->ctrl_hdl); 257 return tx->ctrl_hdl.error; 258 } 259 260 return v4l2_ctrl_handler_setup(&tx->ctrl_hdl); 261 } 262 263 int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) 264 { 265 int ret; 266 267 if (!is_tx_enabled(tx)) 268 return 0; 269 270 /* Initialise the virtual channel */ 271 adv748x_csi2_set_virtual_channel(tx, 0); 272 273 adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops, 274 MEDIA_ENT_F_VID_IF_BRIDGE, 275 is_txa(tx) ? "txa" : "txb"); 276 277 /* Ensure that matching is based upon the endpoint fwnodes */ 278 tx->sd.fwnode = of_fwnode_handle(state->endpoints[tx->port]); 279 280 /* Register internal ops for incremental subdev registration */ 281 tx->sd.internal_ops = &adv748x_csi2_internal_ops; 282 283 tx->pads[ADV748X_CSI2_SINK].flags = MEDIA_PAD_FL_SINK; 284 tx->pads[ADV748X_CSI2_SOURCE].flags = MEDIA_PAD_FL_SOURCE; 285 286 ret = media_entity_pads_init(&tx->sd.entity, ADV748X_CSI2_NR_PADS, 287 tx->pads); 288 if (ret) 289 return ret; 290 291 ret = adv748x_csi2_init_controls(tx); 292 if (ret) 293 goto err_free_media; 294 295 ret = v4l2_async_register_subdev(&tx->sd); 296 if (ret) 297 goto err_free_ctrl; 298 299 return 0; 300 301 err_free_ctrl: 302 v4l2_ctrl_handler_free(&tx->ctrl_hdl); 303 err_free_media: 304 media_entity_cleanup(&tx->sd.entity); 305 306 return ret; 307 } 308 309 void adv748x_csi2_cleanup(struct adv748x_csi2 *tx) 310 { 311 if (!is_tx_enabled(tx)) 312 return; 313 314 v4l2_async_unregister_subdev(&tx->sd); 315 media_entity_cleanup(&tx->sd.entity); 316 v4l2_ctrl_handler_free(&tx->ctrl_hdl); 317 } 318