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