1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Rockchip Camera Interface (CIF) Driver 4 * 5 * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net> 6 * Copyright (C) 2025 Collabora, Ltd. 7 */ 8 9 #include <media/v4l2-common.h> 10 #include <media/v4l2-fwnode.h> 11 #include <media/v4l2-mc.h> 12 #include <media/v4l2-subdev.h> 13 14 #include "rkcif-common.h" 15 #include "rkcif-interface.h" 16 17 static inline struct rkcif_interface *to_rkcif_interface(struct v4l2_subdev *sd) 18 { 19 return container_of(sd, struct rkcif_interface, sd); 20 } 21 22 static const struct media_entity_operations rkcif_interface_media_ops = { 23 .link_validate = v4l2_subdev_link_validate, 24 .has_pad_interdep = v4l2_subdev_has_pad_interdep, 25 }; 26 27 static int rkcif_interface_set_fmt(struct v4l2_subdev *sd, 28 struct v4l2_subdev_state *state, 29 struct v4l2_subdev_format *format) 30 { 31 struct rkcif_interface *interface = to_rkcif_interface(sd); 32 const struct rkcif_input_fmt *input; 33 struct v4l2_mbus_framefmt *sink, *src; 34 struct v4l2_rect *crop; 35 u32 other_pad, other_stream; 36 int ret; 37 38 /* the format on the source pad always matches the sink pad */ 39 if (format->pad == RKCIF_IF_PAD_SRC) 40 return v4l2_subdev_get_fmt(sd, state, format); 41 42 input = rkcif_interface_find_input_fmt(interface, true, 43 format->format.code); 44 format->format.code = input->mbus_code; 45 46 sink = v4l2_subdev_state_get_format(state, format->pad, format->stream); 47 if (!sink) 48 return -EINVAL; 49 50 *sink = format->format; 51 52 /* propagate the format to the source pad */ 53 src = v4l2_subdev_state_get_opposite_stream_format(state, format->pad, 54 format->stream); 55 if (!src) 56 return -EINVAL; 57 58 *src = *sink; 59 60 ret = v4l2_subdev_routing_find_opposite_end(&state->routing, 61 format->pad, format->stream, 62 &other_pad, &other_stream); 63 if (ret) 64 return -EINVAL; 65 66 crop = v4l2_subdev_state_get_crop(state, other_pad, other_stream); 67 if (!crop) 68 return -EINVAL; 69 70 /* reset crop */ 71 crop->left = 0; 72 crop->top = 0; 73 crop->width = sink->width; 74 crop->height = sink->height; 75 76 return 0; 77 } 78 79 static int rkcif_interface_get_sel(struct v4l2_subdev *sd, 80 struct v4l2_subdev_state *state, 81 struct v4l2_subdev_selection *sel) 82 { 83 struct v4l2_mbus_framefmt *sink; 84 struct v4l2_rect *crop; 85 int ret = 0; 86 87 if (sel->pad != RKCIF_IF_PAD_SRC) 88 return -EINVAL; 89 90 sink = v4l2_subdev_state_get_opposite_stream_format(state, sel->pad, 91 sel->stream); 92 if (!sink) 93 return -EINVAL; 94 95 crop = v4l2_subdev_state_get_crop(state, sel->pad, sel->stream); 96 if (!crop) 97 return -EINVAL; 98 99 switch (sel->target) { 100 case V4L2_SEL_TGT_CROP_DEFAULT: 101 case V4L2_SEL_TGT_CROP_BOUNDS: 102 sel->r.left = 0; 103 sel->r.top = 0; 104 sel->r.width = sink->width; 105 sel->r.height = sink->height; 106 break; 107 case V4L2_SEL_TGT_CROP: 108 sel->r = *crop; 109 break; 110 default: 111 ret = -EINVAL; 112 } 113 114 return ret; 115 } 116 117 static int rkcif_interface_set_sel(struct v4l2_subdev *sd, 118 struct v4l2_subdev_state *state, 119 struct v4l2_subdev_selection *sel) 120 { 121 struct v4l2_mbus_framefmt *sink, *src; 122 struct v4l2_rect *crop; 123 124 if (sel->pad != RKCIF_IF_PAD_SRC || sel->target != V4L2_SEL_TGT_CROP) 125 return -EINVAL; 126 127 sink = v4l2_subdev_state_get_opposite_stream_format(state, sel->pad, 128 sel->stream); 129 if (!sink) 130 return -EINVAL; 131 132 src = v4l2_subdev_state_get_format(state, sel->pad, sel->stream); 133 if (!src) 134 return -EINVAL; 135 136 crop = v4l2_subdev_state_get_crop(state, sel->pad, sel->stream); 137 if (!crop) 138 return -EINVAL; 139 140 *crop = sel->r; 141 142 src->height = sel->r.height; 143 src->width = sel->r.width; 144 145 return 0; 146 } 147 148 static int rkcif_interface_set_routing(struct v4l2_subdev *sd, 149 struct v4l2_subdev_state *state, 150 enum v4l2_subdev_format_whence which, 151 struct v4l2_subdev_krouting *routing) 152 { 153 int ret; 154 155 ret = v4l2_subdev_routing_validate(sd, routing, 156 V4L2_SUBDEV_ROUTING_ONLY_1_TO_1); 157 if (ret) 158 return ret; 159 160 for (unsigned int i = 0; i < routing->num_routes; i++) { 161 const struct v4l2_subdev_route *route = &routing->routes[i]; 162 163 if (route->source_stream >= RKCIF_ID_MAX) 164 return -EINVAL; 165 } 166 167 ret = v4l2_subdev_set_routing(sd, state, routing); 168 169 return ret; 170 } 171 172 static int rkcif_interface_apply_crop(struct rkcif_stream *stream, 173 struct v4l2_subdev_state *state) 174 { 175 struct rkcif_interface *interface = stream->interface; 176 struct v4l2_rect *crop; 177 178 crop = v4l2_subdev_state_get_crop(state, RKCIF_IF_PAD_SRC, stream->id); 179 if (!crop) 180 return -EINVAL; 181 182 if (interface->set_crop) 183 interface->set_crop(stream, crop->left, crop->top); 184 185 return 0; 186 } 187 188 static int rkcif_interface_enable_streams(struct v4l2_subdev *sd, 189 struct v4l2_subdev_state *state, 190 u32 pad, u64 streams_mask) 191 { 192 struct rkcif_interface *interface = to_rkcif_interface(sd); 193 struct rkcif_stream *stream; 194 struct v4l2_subdev_route *route; 195 struct v4l2_subdev *remote_sd; 196 struct media_pad *remote_pad; 197 u64 mask; 198 199 remote_pad = 200 media_pad_remote_pad_first(&sd->entity.pads[RKCIF_IF_PAD_SINK]); 201 remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity); 202 203 /* DVP has one crop setting for all IDs */ 204 if (interface->type == RKCIF_IF_DVP) { 205 stream = &interface->streams[RKCIF_ID0]; 206 rkcif_interface_apply_crop(stream, state); 207 } else { 208 for_each_active_route(&state->routing, route) { 209 stream = &interface->streams[route->sink_stream]; 210 rkcif_interface_apply_crop(stream, state); 211 } 212 } 213 214 mask = v4l2_subdev_state_xlate_streams(state, RKCIF_IF_PAD_SINK, 215 RKCIF_IF_PAD_SRC, &streams_mask); 216 217 return v4l2_subdev_enable_streams(remote_sd, remote_pad->index, mask); 218 } 219 220 static int rkcif_interface_disable_streams(struct v4l2_subdev *sd, 221 struct v4l2_subdev_state *state, 222 u32 pad, u64 streams_mask) 223 { 224 struct v4l2_subdev *remote_sd; 225 struct media_pad *remote_pad; 226 u64 mask; 227 228 remote_pad = 229 media_pad_remote_pad_first(&sd->entity.pads[RKCIF_IF_PAD_SINK]); 230 remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity); 231 232 mask = v4l2_subdev_state_xlate_streams(state, RKCIF_IF_PAD_SINK, 233 RKCIF_IF_PAD_SRC, &streams_mask); 234 235 return v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask); 236 } 237 238 static const struct v4l2_subdev_pad_ops rkcif_interface_pad_ops = { 239 .get_fmt = v4l2_subdev_get_fmt, 240 .set_fmt = rkcif_interface_set_fmt, 241 .get_selection = rkcif_interface_get_sel, 242 .set_selection = rkcif_interface_set_sel, 243 .set_routing = rkcif_interface_set_routing, 244 .enable_streams = rkcif_interface_enable_streams, 245 .disable_streams = rkcif_interface_disable_streams, 246 }; 247 248 static const struct v4l2_subdev_ops rkcif_interface_ops = { 249 .pad = &rkcif_interface_pad_ops, 250 }; 251 252 static int rkcif_interface_init_state(struct v4l2_subdev *sd, 253 struct v4l2_subdev_state *state) 254 { 255 struct rkcif_interface *interface = to_rkcif_interface(sd); 256 struct v4l2_subdev_route routes[] = { 257 { 258 .sink_pad = RKCIF_IF_PAD_SINK, 259 .sink_stream = 0, 260 .source_pad = RKCIF_IF_PAD_SRC, 261 .source_stream = 0, 262 .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE, 263 }, 264 }; 265 struct v4l2_subdev_krouting routing = { 266 .len_routes = ARRAY_SIZE(routes), 267 .num_routes = ARRAY_SIZE(routes), 268 .routes = routes, 269 }; 270 const struct v4l2_mbus_framefmt dvp_default_format = { 271 .width = 3840, 272 .height = 2160, 273 .code = MEDIA_BUS_FMT_YUYV8_1X16, 274 .field = V4L2_FIELD_NONE, 275 .colorspace = V4L2_COLORSPACE_REC709, 276 .ycbcr_enc = V4L2_YCBCR_ENC_709, 277 .quantization = V4L2_QUANTIZATION_LIM_RANGE, 278 .xfer_func = V4L2_XFER_FUNC_NONE, 279 }; 280 const struct v4l2_mbus_framefmt mipi_default_format = { 281 .width = 3840, 282 .height = 2160, 283 .code = MEDIA_BUS_FMT_SRGGB10_1X10, 284 .field = V4L2_FIELD_NONE, 285 .colorspace = V4L2_COLORSPACE_RAW, 286 .ycbcr_enc = V4L2_YCBCR_ENC_601, 287 .quantization = V4L2_QUANTIZATION_FULL_RANGE, 288 .xfer_func = V4L2_XFER_FUNC_NONE, 289 }; 290 const struct v4l2_mbus_framefmt *default_format; 291 int ret; 292 293 default_format = (interface->type == RKCIF_IF_DVP) ? 294 &dvp_default_format : 295 &mipi_default_format; 296 297 ret = v4l2_subdev_set_routing_with_fmt(sd, state, &routing, 298 default_format); 299 300 return ret; 301 } 302 303 static const struct v4l2_subdev_internal_ops rkcif_interface_internal_ops = { 304 .init_state = rkcif_interface_init_state, 305 }; 306 307 static int rkcif_interface_add(struct rkcif_interface *interface) 308 { 309 struct rkcif_device *rkcif = interface->rkcif; 310 struct rkcif_remote *remote; 311 struct v4l2_async_notifier *ntf = &rkcif->notifier; 312 struct v4l2_fwnode_endpoint *vep = &interface->vep; 313 struct device *dev = rkcif->dev; 314 struct fwnode_handle *ep; 315 u32 dvp_clk_delay = 0; 316 int ret; 317 318 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), interface->index, 319 0, 0); 320 if (!ep) 321 return -ENODEV; 322 323 vep->bus_type = V4L2_MBUS_UNKNOWN; 324 ret = v4l2_fwnode_endpoint_parse(ep, vep); 325 if (ret) 326 goto complete; 327 328 if (interface->type == RKCIF_IF_DVP) { 329 if (vep->bus_type != V4L2_MBUS_BT656 && 330 vep->bus_type != V4L2_MBUS_PARALLEL) { 331 ret = dev_err_probe(dev, -EINVAL, 332 "unsupported bus type\n"); 333 goto complete; 334 } 335 336 fwnode_property_read_u32(ep, "rockchip,dvp-clk-delay", 337 &dvp_clk_delay); 338 interface->dvp.dvp_clk_delay = dvp_clk_delay; 339 } 340 341 remote = v4l2_async_nf_add_fwnode_remote(ntf, ep, struct rkcif_remote); 342 if (IS_ERR(remote)) { 343 ret = PTR_ERR(remote); 344 goto complete; 345 } 346 347 remote->interface = interface; 348 interface->remote = remote; 349 interface->status = RKCIF_IF_ACTIVE; 350 ret = 0; 351 352 complete: 353 fwnode_handle_put(ep); 354 355 return ret; 356 } 357 358 int rkcif_interface_register(struct rkcif_device *rkcif, 359 struct rkcif_interface *interface) 360 { 361 struct media_pad *pads = interface->pads; 362 struct v4l2_subdev *sd = &interface->sd; 363 int ret; 364 365 interface->rkcif = rkcif; 366 367 v4l2_subdev_init(sd, &rkcif_interface_ops); 368 sd->dev = rkcif->dev; 369 sd->entity.ops = &rkcif_interface_media_ops; 370 sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; 371 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS; 372 sd->internal_ops = &rkcif_interface_internal_ops; 373 sd->owner = THIS_MODULE; 374 375 if (interface->type == RKCIF_IF_DVP) 376 snprintf(sd->name, sizeof(sd->name), "rkcif-dvp0"); 377 else if (interface->type == RKCIF_IF_MIPI) 378 snprintf(sd->name, sizeof(sd->name), "rkcif-mipi%d", 379 interface->index - RKCIF_MIPI_BASE); 380 381 pads[RKCIF_IF_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 382 pads[RKCIF_IF_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE; 383 ret = media_entity_pads_init(&sd->entity, RKCIF_IF_PAD_MAX, pads); 384 if (ret) 385 goto err; 386 387 ret = v4l2_subdev_init_finalize(sd); 388 if (ret) 389 goto err_entity_cleanup; 390 391 ret = v4l2_device_register_subdev(&rkcif->v4l2_dev, sd); 392 if (ret) { 393 dev_err(sd->dev, "failed to register subdev\n"); 394 goto err_subdev_cleanup; 395 } 396 397 ret = rkcif_interface_add(interface); 398 if (ret) 399 goto err_subdev_unregister; 400 401 return 0; 402 403 err_subdev_unregister: 404 v4l2_device_unregister_subdev(sd); 405 err_subdev_cleanup: 406 v4l2_subdev_cleanup(sd); 407 err_entity_cleanup: 408 media_entity_cleanup(&sd->entity); 409 err: 410 return ret; 411 } 412 413 void rkcif_interface_unregister(struct rkcif_interface *interface) 414 { 415 struct v4l2_subdev *sd = &interface->sd; 416 417 if (interface->status != RKCIF_IF_ACTIVE) 418 return; 419 420 v4l2_device_unregister_subdev(sd); 421 v4l2_subdev_cleanup(sd); 422 media_entity_cleanup(&sd->entity); 423 } 424 425 const struct rkcif_input_fmt * 426 rkcif_interface_find_input_fmt(struct rkcif_interface *interface, bool ret_def, 427 u32 mbus_code) 428 { 429 const struct rkcif_input_fmt *fmt; 430 431 WARN_ON(interface->in_fmts_num == 0); 432 433 for (unsigned int i = 0; i < interface->in_fmts_num; i++) { 434 fmt = &interface->in_fmts[i]; 435 if (fmt->mbus_code == mbus_code) 436 return fmt; 437 } 438 if (ret_def) 439 return &interface->in_fmts[0]; 440 else 441 return NULL; 442 } 443