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