1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2013--2024 Intel Corporation 4 */ 5 6 #include <linux/align.h> 7 #include <linux/bits.h> 8 #include <linux/bug.h> 9 #include <linux/completion.h> 10 #include <linux/container_of.h> 11 #include <linux/device.h> 12 #include <linux/list.h> 13 #include <linux/math64.h> 14 #include <linux/minmax.h> 15 #include <linux/module.h> 16 #include <linux/mutex.h> 17 #include <linux/pm_runtime.h> 18 #include <linux/spinlock.h> 19 #include <linux/string.h> 20 21 #include <media/media-entity.h> 22 #include <media/v4l2-ctrls.h> 23 #include <media/v4l2-dev.h> 24 #include <media/v4l2-fh.h> 25 #include <media/v4l2-ioctl.h> 26 #include <media/v4l2-subdev.h> 27 #include <media/videobuf2-v4l2.h> 28 29 #include "ipu6.h" 30 #include "ipu6-bus.h" 31 #include "ipu6-cpd.h" 32 #include "ipu6-fw-isys.h" 33 #include "ipu6-isys.h" 34 #include "ipu6-isys-csi2.h" 35 #include "ipu6-isys-queue.h" 36 #include "ipu6-isys-video.h" 37 #include "ipu6-platform-regs.h" 38 39 const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = { 40 { V4L2_PIX_FMT_SBGGR12, 16, 12, MEDIA_BUS_FMT_SBGGR12_1X12, 41 IPU6_FW_ISYS_FRAME_FORMAT_RAW16 }, 42 { V4L2_PIX_FMT_SGBRG12, 16, 12, MEDIA_BUS_FMT_SGBRG12_1X12, 43 IPU6_FW_ISYS_FRAME_FORMAT_RAW16 }, 44 { V4L2_PIX_FMT_SGRBG12, 16, 12, MEDIA_BUS_FMT_SGRBG12_1X12, 45 IPU6_FW_ISYS_FRAME_FORMAT_RAW16 }, 46 { V4L2_PIX_FMT_SRGGB12, 16, 12, MEDIA_BUS_FMT_SRGGB12_1X12, 47 IPU6_FW_ISYS_FRAME_FORMAT_RAW16 }, 48 { V4L2_PIX_FMT_SBGGR10, 16, 10, MEDIA_BUS_FMT_SBGGR10_1X10, 49 IPU6_FW_ISYS_FRAME_FORMAT_RAW16 }, 50 { V4L2_PIX_FMT_SGBRG10, 16, 10, MEDIA_BUS_FMT_SGBRG10_1X10, 51 IPU6_FW_ISYS_FRAME_FORMAT_RAW16 }, 52 { V4L2_PIX_FMT_SGRBG10, 16, 10, MEDIA_BUS_FMT_SGRBG10_1X10, 53 IPU6_FW_ISYS_FRAME_FORMAT_RAW16 }, 54 { V4L2_PIX_FMT_SRGGB10, 16, 10, MEDIA_BUS_FMT_SRGGB10_1X10, 55 IPU6_FW_ISYS_FRAME_FORMAT_RAW16 }, 56 { V4L2_PIX_FMT_SBGGR8, 8, 8, MEDIA_BUS_FMT_SBGGR8_1X8, 57 IPU6_FW_ISYS_FRAME_FORMAT_RAW8 }, 58 { V4L2_PIX_FMT_SGBRG8, 8, 8, MEDIA_BUS_FMT_SGBRG8_1X8, 59 IPU6_FW_ISYS_FRAME_FORMAT_RAW8 }, 60 { V4L2_PIX_FMT_SGRBG8, 8, 8, MEDIA_BUS_FMT_SGRBG8_1X8, 61 IPU6_FW_ISYS_FRAME_FORMAT_RAW8 }, 62 { V4L2_PIX_FMT_SRGGB8, 8, 8, MEDIA_BUS_FMT_SRGGB8_1X8, 63 IPU6_FW_ISYS_FRAME_FORMAT_RAW8 }, 64 { V4L2_PIX_FMT_SBGGR12P, 12, 12, MEDIA_BUS_FMT_SBGGR12_1X12, 65 IPU6_FW_ISYS_FRAME_FORMAT_RAW12 }, 66 { V4L2_PIX_FMT_SGBRG12P, 12, 12, MEDIA_BUS_FMT_SGBRG12_1X12, 67 IPU6_FW_ISYS_FRAME_FORMAT_RAW12 }, 68 { V4L2_PIX_FMT_SGRBG12P, 12, 12, MEDIA_BUS_FMT_SGRBG12_1X12, 69 IPU6_FW_ISYS_FRAME_FORMAT_RAW12 }, 70 { V4L2_PIX_FMT_SRGGB12P, 12, 12, MEDIA_BUS_FMT_SRGGB12_1X12, 71 IPU6_FW_ISYS_FRAME_FORMAT_RAW12 }, 72 { V4L2_PIX_FMT_SBGGR10P, 10, 10, MEDIA_BUS_FMT_SBGGR10_1X10, 73 IPU6_FW_ISYS_FRAME_FORMAT_RAW10 }, 74 { V4L2_PIX_FMT_SGBRG10P, 10, 10, MEDIA_BUS_FMT_SGBRG10_1X10, 75 IPU6_FW_ISYS_FRAME_FORMAT_RAW10 }, 76 { V4L2_PIX_FMT_SGRBG10P, 10, 10, MEDIA_BUS_FMT_SGRBG10_1X10, 77 IPU6_FW_ISYS_FRAME_FORMAT_RAW10 }, 78 { V4L2_PIX_FMT_SRGGB10P, 10, 10, MEDIA_BUS_FMT_SRGGB10_1X10, 79 IPU6_FW_ISYS_FRAME_FORMAT_RAW10 }, 80 { V4L2_PIX_FMT_UYVY, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16, 81 IPU6_FW_ISYS_FRAME_FORMAT_UYVY}, 82 { V4L2_PIX_FMT_YUYV, 16, 16, MEDIA_BUS_FMT_YUYV8_1X16, 83 IPU6_FW_ISYS_FRAME_FORMAT_YUYV}, 84 { V4L2_PIX_FMT_RGB565, 16, 16, MEDIA_BUS_FMT_RGB565_1X16, 85 IPU6_FW_ISYS_FRAME_FORMAT_RGB565 }, 86 { V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24, 87 IPU6_FW_ISYS_FRAME_FORMAT_RGBA888 }, 88 { V4L2_META_FMT_GENERIC_8, 8, 8, MEDIA_BUS_FMT_META_8, 89 IPU6_FW_ISYS_FRAME_FORMAT_RAW8, true }, 90 { V4L2_META_FMT_GENERIC_CSI2_10, 10, 10, MEDIA_BUS_FMT_META_10, 91 IPU6_FW_ISYS_FRAME_FORMAT_RAW10, true }, 92 { V4L2_META_FMT_GENERIC_CSI2_12, 12, 12, MEDIA_BUS_FMT_META_12, 93 IPU6_FW_ISYS_FRAME_FORMAT_RAW12, true }, 94 { V4L2_META_FMT_GENERIC_CSI2_16, 16, 16, MEDIA_BUS_FMT_META_16, 95 IPU6_FW_ISYS_FRAME_FORMAT_RAW16, true }, 96 }; 97 98 static int video_open(struct file *file) 99 { 100 struct ipu6_isys_video *av = video_drvdata(file); 101 struct ipu6_isys *isys = av->isys; 102 struct ipu6_bus_device *adev = isys->adev; 103 104 mutex_lock(&isys->mutex); 105 if (isys->need_reset) { 106 mutex_unlock(&isys->mutex); 107 dev_warn(&adev->auxdev.dev, "isys power cycle required\n"); 108 return -EIO; 109 } 110 mutex_unlock(&isys->mutex); 111 112 return v4l2_fh_open(file); 113 } 114 115 const struct ipu6_isys_pixelformat * 116 ipu6_isys_get_isys_format(u32 pixelformat, u32 type) 117 { 118 const struct ipu6_isys_pixelformat *default_pfmt = NULL; 119 unsigned int i; 120 121 for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { 122 const struct ipu6_isys_pixelformat *pfmt = &ipu6_isys_pfmts[i]; 123 124 if (type && ((!pfmt->is_meta && 125 type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || 126 (pfmt->is_meta && 127 type != V4L2_BUF_TYPE_META_CAPTURE))) 128 continue; 129 130 if (!default_pfmt) 131 default_pfmt = pfmt; 132 133 if (pfmt->pixelformat != pixelformat) 134 continue; 135 136 return pfmt; 137 } 138 139 return default_pfmt; 140 } 141 142 static int ipu6_isys_vidioc_querycap(struct file *file, void *fh, 143 struct v4l2_capability *cap) 144 { 145 struct ipu6_isys_video *av = video_drvdata(file); 146 147 strscpy(cap->driver, IPU6_ISYS_NAME, sizeof(cap->driver)); 148 strscpy(cap->card, av->isys->media_dev.model, sizeof(cap->card)); 149 150 return 0; 151 } 152 153 static int ipu6_isys_vidioc_enum_fmt(struct file *file, void *fh, 154 struct v4l2_fmtdesc *f) 155 { 156 unsigned int i, num_found; 157 158 for (i = 0, num_found = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { 159 if ((ipu6_isys_pfmts[i].is_meta && 160 f->type != V4L2_BUF_TYPE_META_CAPTURE) || 161 (!ipu6_isys_pfmts[i].is_meta && 162 f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) 163 continue; 164 165 if (f->mbus_code && f->mbus_code != ipu6_isys_pfmts[i].code) 166 continue; 167 168 if (num_found < f->index) { 169 num_found++; 170 continue; 171 } 172 173 f->flags = 0; 174 f->pixelformat = ipu6_isys_pfmts[i].pixelformat; 175 176 return 0; 177 } 178 179 return -EINVAL; 180 } 181 182 static int ipu6_isys_vidioc_enum_framesizes(struct file *file, void *fh, 183 struct v4l2_frmsizeenum *fsize) 184 { 185 unsigned int i; 186 187 if (fsize->index > 0) 188 return -EINVAL; 189 190 for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { 191 if (fsize->pixel_format != ipu6_isys_pfmts[i].pixelformat) 192 continue; 193 194 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 195 fsize->stepwise.min_width = IPU6_ISYS_MIN_WIDTH; 196 fsize->stepwise.max_width = IPU6_ISYS_MAX_WIDTH; 197 fsize->stepwise.min_height = IPU6_ISYS_MIN_HEIGHT; 198 fsize->stepwise.max_height = IPU6_ISYS_MAX_HEIGHT; 199 fsize->stepwise.step_width = 2; 200 fsize->stepwise.step_height = 2; 201 202 return 0; 203 } 204 205 return -EINVAL; 206 } 207 208 static int ipu6_isys_vidioc_g_fmt_vid_cap(struct file *file, void *fh, 209 struct v4l2_format *f) 210 { 211 struct ipu6_isys_video *av = video_drvdata(file); 212 213 f->fmt.pix = av->pix_fmt; 214 215 return 0; 216 } 217 218 static int ipu6_isys_vidioc_g_fmt_meta_cap(struct file *file, void *fh, 219 struct v4l2_format *f) 220 { 221 struct ipu6_isys_video *av = video_drvdata(file); 222 223 f->fmt.meta = av->meta_fmt; 224 225 return 0; 226 } 227 228 static void ipu6_isys_try_fmt_cap(struct ipu6_isys_video *av, u32 type, 229 u32 *format, u32 *width, u32 *height, 230 u32 *bytesperline, u32 *sizeimage) 231 { 232 const struct ipu6_isys_pixelformat *pfmt = 233 ipu6_isys_get_isys_format(*format, type); 234 235 *format = pfmt->pixelformat; 236 *width = clamp(*width, IPU6_ISYS_MIN_WIDTH, IPU6_ISYS_MAX_WIDTH); 237 *height = clamp(*height, IPU6_ISYS_MIN_HEIGHT, IPU6_ISYS_MAX_HEIGHT); 238 239 if (pfmt->bpp != pfmt->bpp_packed) 240 *bytesperline = *width * DIV_ROUND_UP(pfmt->bpp, BITS_PER_BYTE); 241 else 242 *bytesperline = DIV_ROUND_UP(*width * pfmt->bpp, BITS_PER_BYTE); 243 244 *bytesperline = ALIGN(*bytesperline, 64); 245 246 /* 247 * (height + 1) * bytesperline due to a hardware issue: the DMA unit 248 * is a power of two, and a line should be transferred as few units 249 * as possible. The result is that up to line length more data than 250 * the image size may be transferred to memory after the image. 251 * Another limitation is the GDA allocation unit size. For low 252 * resolution it gives a bigger number. Use larger one to avoid 253 * memory corruption. 254 */ 255 *sizeimage = *bytesperline * *height + 256 max(*bytesperline, 257 av->isys->pdata->ipdata->isys_dma_overshoot); 258 } 259 260 static void __ipu6_isys_vidioc_try_fmt_vid_cap(struct ipu6_isys_video *av, 261 struct v4l2_format *f) 262 { 263 ipu6_isys_try_fmt_cap(av, f->type, &f->fmt.pix.pixelformat, 264 &f->fmt.pix.width, &f->fmt.pix.height, 265 &f->fmt.pix.bytesperline, &f->fmt.pix.sizeimage); 266 267 f->fmt.pix.field = V4L2_FIELD_NONE; 268 f->fmt.pix.colorspace = V4L2_COLORSPACE_RAW; 269 f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 270 f->fmt.pix.quantization = V4L2_QUANTIZATION_DEFAULT; 271 f->fmt.pix.xfer_func = V4L2_XFER_FUNC_DEFAULT; 272 } 273 274 static int ipu6_isys_vidioc_try_fmt_vid_cap(struct file *file, void *fh, 275 struct v4l2_format *f) 276 { 277 struct ipu6_isys_video *av = video_drvdata(file); 278 279 if (vb2_is_busy(&av->aq.vbq)) 280 return -EBUSY; 281 282 __ipu6_isys_vidioc_try_fmt_vid_cap(av, f); 283 284 return 0; 285 } 286 287 static int __ipu6_isys_vidioc_try_fmt_meta_cap(struct ipu6_isys_video *av, 288 struct v4l2_format *f) 289 { 290 ipu6_isys_try_fmt_cap(av, f->type, &f->fmt.meta.dataformat, 291 &f->fmt.meta.width, &f->fmt.meta.height, 292 &f->fmt.meta.bytesperline, 293 &f->fmt.meta.buffersize); 294 295 return 0; 296 } 297 298 static int ipu6_isys_vidioc_try_fmt_meta_cap(struct file *file, void *fh, 299 struct v4l2_format *f) 300 { 301 struct ipu6_isys_video *av = video_drvdata(file); 302 303 __ipu6_isys_vidioc_try_fmt_meta_cap(av, f); 304 305 return 0; 306 } 307 308 static int ipu6_isys_vidioc_s_fmt_vid_cap(struct file *file, void *fh, 309 struct v4l2_format *f) 310 { 311 struct ipu6_isys_video *av = video_drvdata(file); 312 313 ipu6_isys_vidioc_try_fmt_vid_cap(file, fh, f); 314 av->pix_fmt = f->fmt.pix; 315 316 return 0; 317 } 318 319 static int ipu6_isys_vidioc_s_fmt_meta_cap(struct file *file, void *fh, 320 struct v4l2_format *f) 321 { 322 struct ipu6_isys_video *av = video_drvdata(file); 323 324 if (vb2_is_busy(&av->aq.vbq)) 325 return -EBUSY; 326 327 ipu6_isys_vidioc_try_fmt_meta_cap(file, fh, f); 328 av->meta_fmt = f->fmt.meta; 329 330 return 0; 331 } 332 333 static int ipu6_isys_vidioc_reqbufs(struct file *file, void *priv, 334 struct v4l2_requestbuffers *p) 335 { 336 struct ipu6_isys_video *av = video_drvdata(file); 337 int ret; 338 339 av->aq.vbq.is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(p->type); 340 av->aq.vbq.is_output = V4L2_TYPE_IS_OUTPUT(p->type); 341 342 ret = vb2_queue_change_type(&av->aq.vbq, p->type); 343 if (ret) 344 return ret; 345 346 return vb2_ioctl_reqbufs(file, priv, p); 347 } 348 349 static int ipu6_isys_vidioc_create_bufs(struct file *file, void *priv, 350 struct v4l2_create_buffers *p) 351 { 352 struct ipu6_isys_video *av = video_drvdata(file); 353 int ret; 354 355 av->aq.vbq.is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(p->format.type); 356 av->aq.vbq.is_output = V4L2_TYPE_IS_OUTPUT(p->format.type); 357 358 ret = vb2_queue_change_type(&av->aq.vbq, p->format.type); 359 if (ret) 360 return ret; 361 362 return vb2_ioctl_create_bufs(file, priv, p); 363 } 364 365 static int link_validate(struct media_link *link) 366 { 367 struct ipu6_isys_video *av = 368 container_of(link->sink, struct ipu6_isys_video, pad); 369 struct device *dev = &av->isys->adev->auxdev.dev; 370 struct v4l2_subdev_state *s_state; 371 struct v4l2_subdev *s_sd; 372 struct v4l2_mbus_framefmt *s_fmt; 373 struct media_pad *s_pad; 374 u32 s_stream, code; 375 int ret = -EPIPE; 376 377 if (!link->source->entity) 378 return ret; 379 380 s_sd = media_entity_to_v4l2_subdev(link->source->entity); 381 s_state = v4l2_subdev_get_unlocked_active_state(s_sd); 382 if (!s_state) 383 return ret; 384 385 dev_dbg(dev, "validating link \"%s\":%u -> \"%s\"\n", 386 link->source->entity->name, link->source->index, 387 link->sink->entity->name); 388 389 s_pad = media_pad_remote_pad_first(&av->pad); 390 s_stream = ipu6_isys_get_src_stream_by_src_pad(s_sd, s_pad->index); 391 392 v4l2_subdev_lock_state(s_state); 393 394 s_fmt = v4l2_subdev_state_get_format(s_state, s_pad->index, s_stream); 395 if (!s_fmt) { 396 dev_err(dev, "failed to get source pad format\n"); 397 goto unlock; 398 } 399 400 code = ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0)->code; 401 402 if (s_fmt->width != ipu6_isys_get_frame_width(av) || 403 s_fmt->height != ipu6_isys_get_frame_height(av) || 404 s_fmt->code != code) { 405 dev_dbg(dev, "format mismatch %dx%d,%x != %dx%d,%x\n", 406 s_fmt->width, s_fmt->height, s_fmt->code, 407 ipu6_isys_get_frame_width(av), 408 ipu6_isys_get_frame_height(av), code); 409 goto unlock; 410 } 411 412 v4l2_subdev_unlock_state(s_state); 413 414 return 0; 415 unlock: 416 v4l2_subdev_unlock_state(s_state); 417 418 return ret; 419 } 420 421 static void get_stream_opened(struct ipu6_isys_video *av) 422 { 423 unsigned long flags; 424 425 spin_lock_irqsave(&av->isys->streams_lock, flags); 426 av->isys->stream_opened++; 427 spin_unlock_irqrestore(&av->isys->streams_lock, flags); 428 } 429 430 static void put_stream_opened(struct ipu6_isys_video *av) 431 { 432 unsigned long flags; 433 434 spin_lock_irqsave(&av->isys->streams_lock, flags); 435 av->isys->stream_opened--; 436 spin_unlock_irqrestore(&av->isys->streams_lock, flags); 437 } 438 439 static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video *av, 440 struct ipu6_fw_isys_stream_cfg_data_abi *cfg) 441 { 442 struct media_pad *src_pad = media_pad_remote_pad_first(&av->pad); 443 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(src_pad->entity); 444 struct ipu6_fw_isys_input_pin_info_abi *input_pin; 445 struct ipu6_fw_isys_output_pin_info_abi *output_pin; 446 struct ipu6_isys_stream *stream = av->stream; 447 struct ipu6_isys_queue *aq = &av->aq; 448 struct v4l2_mbus_framefmt fmt; 449 const struct ipu6_isys_pixelformat *pfmt = 450 ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0); 451 struct v4l2_rect v4l2_crop; 452 struct ipu6_isys *isys = av->isys; 453 struct device *dev = &isys->adev->auxdev.dev; 454 int input_pins = cfg->nof_input_pins++; 455 int output_pins; 456 u32 src_stream; 457 int ret; 458 459 src_stream = ipu6_isys_get_src_stream_by_src_pad(sd, src_pad->index); 460 ret = ipu6_isys_get_stream_pad_fmt(sd, src_pad->index, src_stream, 461 &fmt); 462 if (ret < 0) { 463 dev_err(dev, "can't get stream format (%d)\n", ret); 464 return ret; 465 } 466 467 ret = ipu6_isys_get_stream_pad_crop(sd, src_pad->index, src_stream, 468 &v4l2_crop); 469 if (ret < 0) { 470 dev_err(dev, "can't get stream crop (%d)\n", ret); 471 return ret; 472 } 473 474 input_pin = &cfg->input_pins[input_pins]; 475 input_pin->input_res.width = fmt.width; 476 input_pin->input_res.height = fmt.height; 477 input_pin->dt = av->dt; 478 input_pin->bits_per_pix = pfmt->bpp_packed; 479 input_pin->mapped_dt = 0x40; /* invalid mipi data type */ 480 input_pin->mipi_decompression = 0; 481 input_pin->capture_mode = IPU6_FW_ISYS_CAPTURE_MODE_REGULAR; 482 input_pin->mipi_store_mode = pfmt->bpp == pfmt->bpp_packed ? 483 IPU6_FW_ISYS_MIPI_STORE_MODE_DISCARD_LONG_HEADER : 484 IPU6_FW_ISYS_MIPI_STORE_MODE_NORMAL; 485 input_pin->crop_first_and_last_lines = v4l2_crop.top & 1; 486 487 output_pins = cfg->nof_output_pins++; 488 aq->fw_output = output_pins; 489 stream->output_pins_queue[output_pins] = aq; 490 491 output_pin = &cfg->output_pins[output_pins]; 492 output_pin->input_pin_id = input_pins; 493 output_pin->output_res.width = ipu6_isys_get_frame_width(av); 494 output_pin->output_res.height = ipu6_isys_get_frame_height(av); 495 496 output_pin->stride = ipu6_isys_get_bytes_per_line(av); 497 if (pfmt->bpp != pfmt->bpp_packed) 498 output_pin->pt = IPU6_FW_ISYS_PIN_TYPE_RAW_SOC; 499 else 500 output_pin->pt = IPU6_FW_ISYS_PIN_TYPE_MIPI; 501 output_pin->ft = pfmt->css_pixelformat; 502 output_pin->send_irq = 1; 503 memset(output_pin->ts_offsets, 0, sizeof(output_pin->ts_offsets)); 504 output_pin->s2m_pixel_soc_pixel_remapping = 505 S2M_PIXEL_SOC_PIXEL_REMAPPING_FLAG_NO_REMAPPING; 506 output_pin->csi_be_soc_pixel_remapping = 507 CSI_BE_SOC_PIXEL_REMAPPING_FLAG_NO_REMAPPING; 508 509 output_pin->snoopable = true; 510 output_pin->error_handling_enable = false; 511 output_pin->sensor_type = isys->sensor_type++; 512 if (isys->sensor_type > isys->pdata->ipdata->sensor_type_end) 513 isys->sensor_type = isys->pdata->ipdata->sensor_type_start; 514 515 return 0; 516 } 517 518 static int start_stream_firmware(struct ipu6_isys_video *av, 519 struct ipu6_isys_buffer_list *bl) 520 { 521 struct ipu6_fw_isys_stream_cfg_data_abi *stream_cfg; 522 struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL; 523 struct ipu6_isys_stream *stream = av->stream; 524 struct device *dev = &av->isys->adev->auxdev.dev; 525 struct isys_fw_msgs *msg = NULL; 526 struct ipu6_isys_queue *aq; 527 int ret, retout, tout; 528 u16 send_type; 529 530 msg = ipu6_get_fw_msg_buf(stream); 531 if (!msg) 532 return -ENOMEM; 533 534 stream_cfg = &msg->fw_msg.stream; 535 stream_cfg->src = stream->stream_source; 536 stream_cfg->vc = stream->vc; 537 stream_cfg->isl_use = 0; 538 stream_cfg->sensor_type = IPU6_FW_ISYS_SENSOR_MODE_NORMAL; 539 540 list_for_each_entry(aq, &stream->queues, node) { 541 struct ipu6_isys_video *__av = ipu6_isys_queue_to_video(aq); 542 543 ret = ipu6_isys_fw_pin_cfg(__av, stream_cfg); 544 if (ret < 0) { 545 ipu6_put_fw_msg_buf(av->isys, (uintptr_t)stream_cfg); 546 return ret; 547 } 548 } 549 550 ipu6_fw_isys_dump_stream_cfg(dev, stream_cfg); 551 552 stream->nr_output_pins = stream_cfg->nof_output_pins; 553 554 reinit_completion(&stream->stream_open_completion); 555 556 ret = ipu6_fw_isys_complex_cmd(av->isys, stream->stream_handle, 557 stream_cfg, msg->dma_addr, 558 sizeof(*stream_cfg), 559 IPU6_FW_ISYS_SEND_TYPE_STREAM_OPEN); 560 if (ret < 0) { 561 dev_err(dev, "can't open stream (%d)\n", ret); 562 ipu6_put_fw_msg_buf(av->isys, (uintptr_t)stream_cfg); 563 return ret; 564 } 565 566 get_stream_opened(av); 567 568 tout = wait_for_completion_timeout(&stream->stream_open_completion, 569 IPU6_FW_CALL_TIMEOUT_JIFFIES); 570 571 ipu6_put_fw_msg_buf(av->isys, (uintptr_t)stream_cfg); 572 573 if (!tout) { 574 dev_err(dev, "stream open time out\n"); 575 ret = -ETIMEDOUT; 576 goto out_put_stream_opened; 577 } 578 if (stream->error) { 579 dev_err(dev, "stream open error: %d\n", stream->error); 580 ret = -EIO; 581 goto out_put_stream_opened; 582 } 583 dev_dbg(dev, "start stream: open complete\n"); 584 585 if (bl) { 586 msg = ipu6_get_fw_msg_buf(stream); 587 if (!msg) { 588 ret = -ENOMEM; 589 goto out_put_stream_opened; 590 } 591 buf = &msg->fw_msg.frame; 592 ipu6_isys_buf_to_fw_frame_buf(buf, stream, bl); 593 ipu6_isys_buffer_list_queue(bl, 594 IPU6_ISYS_BUFFER_LIST_FL_ACTIVE, 0); 595 } 596 597 reinit_completion(&stream->stream_start_completion); 598 599 if (bl) { 600 send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START_AND_CAPTURE; 601 ipu6_fw_isys_dump_frame_buff_set(dev, buf, 602 stream_cfg->nof_output_pins); 603 ret = ipu6_fw_isys_complex_cmd(av->isys, stream->stream_handle, 604 buf, msg->dma_addr, 605 sizeof(*buf), send_type); 606 } else { 607 send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START; 608 ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle, 609 send_type); 610 } 611 612 if (ret < 0) { 613 dev_err(dev, "can't start streaming (%d)\n", ret); 614 goto out_stream_close; 615 } 616 617 tout = wait_for_completion_timeout(&stream->stream_start_completion, 618 IPU6_FW_CALL_TIMEOUT_JIFFIES); 619 if (!tout) { 620 dev_err(dev, "stream start time out\n"); 621 ret = -ETIMEDOUT; 622 goto out_stream_close; 623 } 624 if (stream->error) { 625 dev_err(dev, "stream start error: %d\n", stream->error); 626 ret = -EIO; 627 goto out_stream_close; 628 } 629 dev_dbg(dev, "start stream: complete\n"); 630 631 return 0; 632 633 out_stream_close: 634 reinit_completion(&stream->stream_close_completion); 635 636 retout = ipu6_fw_isys_simple_cmd(av->isys, 637 stream->stream_handle, 638 IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE); 639 if (retout < 0) { 640 dev_dbg(dev, "can't close stream (%d)\n", retout); 641 goto out_put_stream_opened; 642 } 643 644 tout = wait_for_completion_timeout(&stream->stream_close_completion, 645 IPU6_FW_CALL_TIMEOUT_JIFFIES); 646 if (!tout) 647 dev_err(dev, "stream close time out\n"); 648 else if (stream->error) 649 dev_err(dev, "stream close error: %d\n", stream->error); 650 else 651 dev_dbg(dev, "stream close complete\n"); 652 653 out_put_stream_opened: 654 put_stream_opened(av); 655 656 return ret; 657 } 658 659 static void stop_streaming_firmware(struct ipu6_isys_video *av) 660 { 661 struct device *dev = &av->isys->adev->auxdev.dev; 662 struct ipu6_isys_stream *stream = av->stream; 663 int ret, tout; 664 665 reinit_completion(&stream->stream_stop_completion); 666 667 ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle, 668 IPU6_FW_ISYS_SEND_TYPE_STREAM_FLUSH); 669 670 if (ret < 0) { 671 dev_err(dev, "can't stop stream (%d)\n", ret); 672 return; 673 } 674 675 tout = wait_for_completion_timeout(&stream->stream_stop_completion, 676 IPU6_FW_CALL_TIMEOUT_JIFFIES); 677 if (!tout) 678 dev_warn(dev, "stream stop time out\n"); 679 else if (stream->error) 680 dev_warn(dev, "stream stop error: %d\n", stream->error); 681 else 682 dev_dbg(dev, "stop stream: complete\n"); 683 } 684 685 static void close_streaming_firmware(struct ipu6_isys_video *av) 686 { 687 struct ipu6_isys_stream *stream = av->stream; 688 struct device *dev = &av->isys->adev->auxdev.dev; 689 int ret, tout; 690 691 reinit_completion(&stream->stream_close_completion); 692 693 ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle, 694 IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE); 695 if (ret < 0) { 696 dev_err(dev, "can't close stream (%d)\n", ret); 697 return; 698 } 699 700 tout = wait_for_completion_timeout(&stream->stream_close_completion, 701 IPU6_FW_CALL_TIMEOUT_JIFFIES); 702 if (!tout) 703 dev_warn(dev, "stream close time out\n"); 704 else if (stream->error) 705 dev_warn(dev, "stream close error: %d\n", stream->error); 706 else 707 dev_dbg(dev, "close stream: complete\n"); 708 709 put_stream_opened(av); 710 } 711 712 int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av, 713 struct media_entity *source_entity, 714 int nr_queues) 715 { 716 struct ipu6_isys_stream *stream = av->stream; 717 struct ipu6_isys_csi2 *csi2; 718 719 if (WARN_ON(stream->nr_streaming)) 720 return -EINVAL; 721 722 stream->nr_queues = nr_queues; 723 atomic_set(&stream->sequence, 0); 724 725 stream->seq_index = 0; 726 memset(stream->seq, 0, sizeof(stream->seq)); 727 728 if (WARN_ON(!list_empty(&stream->queues))) 729 return -EINVAL; 730 731 stream->stream_source = stream->asd->source; 732 csi2 = ipu6_isys_subdev_to_csi2(stream->asd); 733 csi2->receiver_errors = 0; 734 stream->source_entity = source_entity; 735 736 dev_dbg(&av->isys->adev->auxdev.dev, 737 "prepare stream: external entity %s\n", 738 stream->source_entity->name); 739 740 return 0; 741 } 742 743 void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av, 744 bool state) 745 { 746 struct ipu6_isys *isys = av->isys; 747 struct ipu6_isys_csi2 *csi2 = NULL; 748 struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark; 749 struct device *dev = &isys->adev->auxdev.dev; 750 struct v4l2_mbus_framefmt format; 751 struct v4l2_subdev *esd; 752 struct v4l2_control hb = { .id = V4L2_CID_HBLANK, .value = 0 }; 753 unsigned int bpp, lanes; 754 s64 link_freq = 0; 755 u64 pixel_rate = 0; 756 int ret; 757 758 if (!state) 759 return; 760 761 esd = media_entity_to_v4l2_subdev(av->stream->source_entity); 762 763 av->watermark.width = ipu6_isys_get_frame_width(av); 764 av->watermark.height = ipu6_isys_get_frame_height(av); 765 av->watermark.sram_gran_shift = isys->pdata->ipdata->sram_gran_shift; 766 av->watermark.sram_gran_size = isys->pdata->ipdata->sram_gran_size; 767 768 ret = v4l2_g_ctrl(esd->ctrl_handler, &hb); 769 if (!ret && hb.value >= 0) 770 av->watermark.hblank = hb.value; 771 else 772 av->watermark.hblank = 0; 773 774 csi2 = ipu6_isys_subdev_to_csi2(av->stream->asd); 775 link_freq = ipu6_isys_csi2_get_link_freq(csi2); 776 if (link_freq > 0) { 777 lanes = csi2->nlanes; 778 ret = ipu6_isys_get_stream_pad_fmt(&csi2->asd.sd, 0, 779 av->source_stream, &format); 780 if (!ret) { 781 bpp = ipu6_isys_mbus_code_to_bpp(format.code); 782 pixel_rate = mul_u64_u32_div(link_freq, lanes * 2, bpp); 783 } 784 } 785 786 av->watermark.pixel_rate = pixel_rate; 787 788 if (!pixel_rate) { 789 mutex_lock(&iwake_watermark->mutex); 790 iwake_watermark->force_iwake_disable = true; 791 mutex_unlock(&iwake_watermark->mutex); 792 dev_warn(dev, "unexpected pixel_rate from %s, disable iwake.\n", 793 av->stream->source_entity->name); 794 } 795 } 796 797 static void calculate_stream_datarate(struct ipu6_isys_video *av) 798 { 799 struct video_stream_watermark *watermark = &av->watermark; 800 const struct ipu6_isys_pixelformat *pfmt = 801 ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0); 802 u32 pages_per_line, pb_bytes_per_line, pixels_per_line, bytes_per_line; 803 u64 line_time_ns, stream_data_rate; 804 u16 shift, size; 805 806 shift = watermark->sram_gran_shift; 807 size = watermark->sram_gran_size; 808 809 pixels_per_line = watermark->width + watermark->hblank; 810 line_time_ns = div_u64(pixels_per_line * NSEC_PER_SEC, 811 watermark->pixel_rate); 812 bytes_per_line = watermark->width * pfmt->bpp / 8; 813 pages_per_line = DIV_ROUND_UP(bytes_per_line, size); 814 pb_bytes_per_line = pages_per_line << shift; 815 stream_data_rate = div64_u64(pb_bytes_per_line * 1000, line_time_ns); 816 817 watermark->stream_data_rate = stream_data_rate; 818 } 819 820 void ipu6_isys_update_stream_watermark(struct ipu6_isys_video *av, bool state) 821 { 822 struct isys_iwake_watermark *iwake_watermark = 823 &av->isys->iwake_watermark; 824 825 if (!av->watermark.pixel_rate) 826 return; 827 828 if (state) { 829 calculate_stream_datarate(av); 830 mutex_lock(&iwake_watermark->mutex); 831 list_add(&av->watermark.stream_node, 832 &iwake_watermark->video_list); 833 mutex_unlock(&iwake_watermark->mutex); 834 } else { 835 av->watermark.stream_data_rate = 0; 836 mutex_lock(&iwake_watermark->mutex); 837 list_del(&av->watermark.stream_node); 838 mutex_unlock(&iwake_watermark->mutex); 839 } 840 841 update_watermark_setting(av->isys); 842 } 843 844 void ipu6_isys_put_stream(struct ipu6_isys_stream *stream) 845 { 846 struct device *dev; 847 unsigned int i; 848 unsigned long flags; 849 850 if (!stream) { 851 pr_err("ipu6-isys: no available stream\n"); 852 return; 853 } 854 855 dev = &stream->isys->adev->auxdev.dev; 856 857 spin_lock_irqsave(&stream->isys->streams_lock, flags); 858 for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) { 859 if (&stream->isys->streams[i] == stream) { 860 if (stream->isys->streams_ref_count[i] > 0) 861 stream->isys->streams_ref_count[i]--; 862 else 863 dev_warn(dev, "invalid stream %d\n", i); 864 865 break; 866 } 867 } 868 spin_unlock_irqrestore(&stream->isys->streams_lock, flags); 869 } 870 871 static struct ipu6_isys_stream * 872 ipu6_isys_get_stream(struct ipu6_isys_video *av, struct ipu6_isys_subdev *asd) 873 { 874 struct ipu6_isys_stream *stream = NULL; 875 struct ipu6_isys *isys = av->isys; 876 unsigned long flags; 877 unsigned int i; 878 u8 vc = av->vc; 879 880 if (!isys) 881 return NULL; 882 883 spin_lock_irqsave(&isys->streams_lock, flags); 884 for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) { 885 if (isys->streams_ref_count[i] && isys->streams[i].vc == vc && 886 isys->streams[i].asd == asd) { 887 isys->streams_ref_count[i]++; 888 stream = &isys->streams[i]; 889 break; 890 } 891 } 892 893 if (!stream) { 894 for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) { 895 if (!isys->streams_ref_count[i]) { 896 isys->streams_ref_count[i]++; 897 stream = &isys->streams[i]; 898 stream->vc = vc; 899 stream->asd = asd; 900 break; 901 } 902 } 903 } 904 spin_unlock_irqrestore(&isys->streams_lock, flags); 905 906 return stream; 907 } 908 909 struct ipu6_isys_stream * 910 ipu6_isys_query_stream_by_handle(struct ipu6_isys *isys, u8 stream_handle) 911 { 912 unsigned long flags; 913 struct ipu6_isys_stream *stream = NULL; 914 915 if (!isys) 916 return NULL; 917 918 if (stream_handle >= IPU6_ISYS_MAX_STREAMS) { 919 dev_err(&isys->adev->auxdev.dev, 920 "stream_handle %d is invalid\n", stream_handle); 921 return NULL; 922 } 923 924 spin_lock_irqsave(&isys->streams_lock, flags); 925 if (isys->streams_ref_count[stream_handle] > 0) { 926 isys->streams_ref_count[stream_handle]++; 927 stream = &isys->streams[stream_handle]; 928 } 929 spin_unlock_irqrestore(&isys->streams_lock, flags); 930 931 return stream; 932 } 933 934 struct ipu6_isys_stream * 935 ipu6_isys_query_stream_by_source(struct ipu6_isys *isys, int source, u8 vc) 936 { 937 struct ipu6_isys_stream *stream = NULL; 938 unsigned long flags; 939 unsigned int i; 940 941 if (!isys) 942 return NULL; 943 944 if (source < 0) { 945 dev_err(&isys->adev->auxdev.dev, 946 "query stream with invalid port number\n"); 947 return NULL; 948 } 949 950 spin_lock_irqsave(&isys->streams_lock, flags); 951 for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) { 952 if (!isys->streams_ref_count[i]) 953 continue; 954 955 if (isys->streams[i].stream_source == source && 956 isys->streams[i].vc == vc) { 957 stream = &isys->streams[i]; 958 isys->streams_ref_count[i]++; 959 break; 960 } 961 } 962 spin_unlock_irqrestore(&isys->streams_lock, flags); 963 964 return stream; 965 } 966 967 static u64 get_stream_mask_by_pipeline(struct ipu6_isys_video *__av) 968 { 969 struct media_pipeline *pipeline = 970 media_entity_pipeline(&__av->vdev.entity); 971 unsigned int i; 972 u64 stream_mask = 0; 973 974 for (i = 0; i < NR_OF_CSI2_SRC_PADS; i++) { 975 struct ipu6_isys_video *av = &__av->csi2->av[i]; 976 977 if (pipeline == media_entity_pipeline(&av->vdev.entity)) 978 stream_mask |= BIT_ULL(av->source_stream); 979 } 980 981 return stream_mask; 982 } 983 984 int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, 985 struct ipu6_isys_buffer_list *bl) 986 { 987 struct v4l2_subdev_krouting *routing; 988 struct ipu6_isys_stream *stream = av->stream; 989 struct v4l2_subdev_state *subdev_state; 990 struct device *dev = &av->isys->adev->auxdev.dev; 991 struct v4l2_subdev *sd; 992 struct media_pad *r_pad; 993 u32 sink_pad, sink_stream; 994 u64 r_stream; 995 u64 stream_mask = 0; 996 int ret = 0; 997 998 dev_dbg(dev, "set stream: %d\n", state); 999 1000 if (WARN(!stream->source_entity, "No source entity for stream\n")) 1001 return -ENODEV; 1002 1003 sd = &stream->asd->sd; 1004 r_pad = media_pad_remote_pad_first(&av->pad); 1005 r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index); 1006 1007 subdev_state = v4l2_subdev_lock_and_get_active_state(sd); 1008 routing = &subdev_state->routing; 1009 ret = v4l2_subdev_routing_find_opposite_end(routing, r_pad->index, 1010 r_stream, &sink_pad, 1011 &sink_stream); 1012 v4l2_subdev_unlock_state(subdev_state); 1013 if (ret) 1014 return ret; 1015 1016 stream_mask = get_stream_mask_by_pipeline(av); 1017 if (!state) { 1018 stop_streaming_firmware(av); 1019 1020 /* stop sub-device which connects with video */ 1021 dev_dbg(dev, "stream off entity %s pad:%d mask:0x%llx\n", 1022 sd->name, r_pad->index, stream_mask); 1023 ret = v4l2_subdev_disable_streams(sd, r_pad->index, 1024 stream_mask); 1025 if (ret) { 1026 dev_err(dev, "stream off %s failed with %d\n", sd->name, 1027 ret); 1028 return ret; 1029 } 1030 close_streaming_firmware(av); 1031 } else { 1032 ret = start_stream_firmware(av, bl); 1033 if (ret) { 1034 dev_err(dev, "start stream of firmware failed\n"); 1035 return ret; 1036 } 1037 1038 /* start sub-device which connects with video */ 1039 dev_dbg(dev, "stream on %s pad %d mask 0x%llx\n", sd->name, 1040 r_pad->index, stream_mask); 1041 ret = v4l2_subdev_enable_streams(sd, r_pad->index, stream_mask); 1042 if (ret) { 1043 dev_err(dev, "stream on %s failed with %d\n", sd->name, 1044 ret); 1045 goto out_media_entity_stop_streaming_firmware; 1046 } 1047 } 1048 1049 av->streaming = state; 1050 1051 return 0; 1052 1053 out_media_entity_stop_streaming_firmware: 1054 stop_streaming_firmware(av); 1055 1056 return ret; 1057 } 1058 1059 static const struct v4l2_ioctl_ops ipu6_v4l2_ioctl_ops = { 1060 .vidioc_querycap = ipu6_isys_vidioc_querycap, 1061 .vidioc_enum_fmt_vid_cap = ipu6_isys_vidioc_enum_fmt, 1062 .vidioc_enum_fmt_meta_cap = ipu6_isys_vidioc_enum_fmt, 1063 .vidioc_enum_framesizes = ipu6_isys_vidioc_enum_framesizes, 1064 .vidioc_g_fmt_vid_cap = ipu6_isys_vidioc_g_fmt_vid_cap, 1065 .vidioc_s_fmt_vid_cap = ipu6_isys_vidioc_s_fmt_vid_cap, 1066 .vidioc_try_fmt_vid_cap = ipu6_isys_vidioc_try_fmt_vid_cap, 1067 .vidioc_g_fmt_meta_cap = ipu6_isys_vidioc_g_fmt_meta_cap, 1068 .vidioc_s_fmt_meta_cap = ipu6_isys_vidioc_s_fmt_meta_cap, 1069 .vidioc_try_fmt_meta_cap = ipu6_isys_vidioc_try_fmt_meta_cap, 1070 .vidioc_reqbufs = ipu6_isys_vidioc_reqbufs, 1071 .vidioc_create_bufs = ipu6_isys_vidioc_create_bufs, 1072 .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 1073 .vidioc_querybuf = vb2_ioctl_querybuf, 1074 .vidioc_qbuf = vb2_ioctl_qbuf, 1075 .vidioc_dqbuf = vb2_ioctl_dqbuf, 1076 .vidioc_streamon = vb2_ioctl_streamon, 1077 .vidioc_streamoff = vb2_ioctl_streamoff, 1078 .vidioc_expbuf = vb2_ioctl_expbuf, 1079 }; 1080 1081 static const struct media_entity_operations entity_ops = { 1082 .link_validate = link_validate, 1083 }; 1084 1085 static const struct v4l2_file_operations isys_fops = { 1086 .owner = THIS_MODULE, 1087 .poll = vb2_fop_poll, 1088 .unlocked_ioctl = video_ioctl2, 1089 .mmap = vb2_fop_mmap, 1090 .open = video_open, 1091 .release = vb2_fop_release, 1092 }; 1093 1094 int ipu6_isys_fw_open(struct ipu6_isys *isys) 1095 { 1096 struct ipu6_bus_device *adev = isys->adev; 1097 const struct ipu6_isys_internal_pdata *ipdata = isys->pdata->ipdata; 1098 int ret; 1099 1100 ret = pm_runtime_resume_and_get(&adev->auxdev.dev); 1101 if (ret < 0) 1102 return ret; 1103 1104 mutex_lock(&isys->mutex); 1105 1106 if (isys->ref_count++) 1107 goto unlock; 1108 1109 ipu6_configure_spc(adev->isp, &ipdata->hw_variant, 1110 IPU6_CPD_PKG_DIR_ISYS_SERVER_IDX, isys->pdata->base, 1111 adev->pkg_dir, adev->pkg_dir_dma_addr); 1112 1113 /* 1114 * Buffers could have been left to wrong queue at last closure. 1115 * Move them now back to empty buffer queue. 1116 */ 1117 ipu6_cleanup_fw_msg_bufs(isys); 1118 1119 if (isys->fwcom) { 1120 /* 1121 * Something went wrong in previous shutdown. As we are now 1122 * restarting isys we can safely delete old context. 1123 */ 1124 dev_warn(&adev->auxdev.dev, "clearing old context\n"); 1125 ipu6_fw_isys_cleanup(isys); 1126 } 1127 1128 ret = ipu6_fw_isys_init(isys, ipdata->num_parallel_streams); 1129 if (ret < 0) 1130 goto out; 1131 1132 unlock: 1133 mutex_unlock(&isys->mutex); 1134 1135 return 0; 1136 1137 out: 1138 isys->ref_count--; 1139 mutex_unlock(&isys->mutex); 1140 pm_runtime_put(&adev->auxdev.dev); 1141 1142 return ret; 1143 } 1144 1145 void ipu6_isys_fw_close(struct ipu6_isys *isys) 1146 { 1147 mutex_lock(&isys->mutex); 1148 1149 isys->ref_count--; 1150 if (!isys->ref_count) { 1151 ipu6_fw_isys_close(isys); 1152 if (isys->fwcom) { 1153 isys->need_reset = true; 1154 dev_warn(&isys->adev->auxdev.dev, 1155 "failed to close fw isys\n"); 1156 } 1157 } 1158 1159 mutex_unlock(&isys->mutex); 1160 1161 if (isys->need_reset) 1162 pm_runtime_put_sync(&isys->adev->auxdev.dev); 1163 else 1164 pm_runtime_put(&isys->adev->auxdev.dev); 1165 } 1166 1167 int ipu6_isys_setup_video(struct ipu6_isys_video *av, 1168 struct media_entity **source_entity, int *nr_queues) 1169 { 1170 const struct ipu6_isys_pixelformat *pfmt = 1171 ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0); 1172 struct device *dev = &av->isys->adev->auxdev.dev; 1173 struct v4l2_mbus_frame_desc_entry entry; 1174 struct v4l2_subdev_route *route = NULL; 1175 struct v4l2_subdev_route *r; 1176 struct v4l2_subdev_state *state; 1177 struct ipu6_isys_subdev *asd; 1178 struct v4l2_subdev *remote_sd; 1179 struct media_pipeline *pipeline; 1180 struct media_pad *source_pad, *remote_pad; 1181 int ret = -EINVAL; 1182 1183 *nr_queues = 0; 1184 1185 remote_pad = media_pad_remote_pad_unique(&av->pad); 1186 if (IS_ERR(remote_pad)) { 1187 dev_dbg(dev, "failed to get remote pad\n"); 1188 return PTR_ERR(remote_pad); 1189 } 1190 1191 remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity); 1192 asd = to_ipu6_isys_subdev(remote_sd); 1193 source_pad = media_pad_remote_pad_first(&remote_pad->entity->pads[0]); 1194 if (!source_pad) { 1195 dev_dbg(dev, "No external source entity\n"); 1196 return -ENODEV; 1197 } 1198 1199 *source_entity = source_pad->entity; 1200 1201 /* Find the root */ 1202 state = v4l2_subdev_lock_and_get_active_state(remote_sd); 1203 for_each_active_route(&state->routing, r) { 1204 (*nr_queues)++; 1205 1206 if (r->source_pad == remote_pad->index) 1207 route = r; 1208 } 1209 1210 if (!route) { 1211 v4l2_subdev_unlock_state(state); 1212 dev_dbg(dev, "Failed to find route\n"); 1213 return -ENODEV; 1214 } 1215 av->source_stream = route->sink_stream; 1216 v4l2_subdev_unlock_state(state); 1217 1218 ret = ipu6_isys_csi2_get_remote_desc(av->source_stream, 1219 to_ipu6_isys_csi2(asd), 1220 *source_entity, &entry); 1221 if (ret == -ENOIOCTLCMD) { 1222 av->vc = 0; 1223 av->dt = ipu6_isys_mbus_code_to_mipi(pfmt->code); 1224 } else if (!ret) { 1225 dev_dbg(dev, "Framedesc: stream %u, len %u, vc %u, dt %#x\n", 1226 entry.stream, entry.length, entry.bus.csi2.vc, 1227 entry.bus.csi2.dt); 1228 1229 av->vc = entry.bus.csi2.vc; 1230 av->dt = entry.bus.csi2.dt; 1231 } else { 1232 dev_err(dev, "failed to get remote frame desc\n"); 1233 return ret; 1234 } 1235 1236 pipeline = media_entity_pipeline(&av->vdev.entity); 1237 if (!pipeline) 1238 ret = video_device_pipeline_alloc_start(&av->vdev); 1239 else 1240 ret = video_device_pipeline_start(&av->vdev, pipeline); 1241 if (ret < 0) { 1242 dev_dbg(dev, "media pipeline start failed\n"); 1243 return ret; 1244 } 1245 1246 av->stream = ipu6_isys_get_stream(av, asd); 1247 if (!av->stream) { 1248 video_device_pipeline_stop(&av->vdev); 1249 dev_err(dev, "no available stream for firmware\n"); 1250 return -EINVAL; 1251 } 1252 1253 return 0; 1254 } 1255 1256 /* 1257 * Do everything that's needed to initialise things related to video 1258 * buffer queue, video node, and the related media entity. The caller 1259 * is expected to assign isys field and set the name of the video 1260 * device. 1261 */ 1262 int ipu6_isys_video_init(struct ipu6_isys_video *av) 1263 { 1264 struct v4l2_format format = { 1265 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, 1266 .fmt.pix = { 1267 .width = 1920, 1268 .height = 1080, 1269 }, 1270 }; 1271 struct v4l2_format format_meta = { 1272 .type = V4L2_BUF_TYPE_META_CAPTURE, 1273 .fmt.meta = { 1274 .width = 1920, 1275 .height = 4, 1276 }, 1277 }; 1278 int ret; 1279 1280 mutex_init(&av->mutex); 1281 av->vdev.device_caps = V4L2_CAP_STREAMING | V4L2_CAP_IO_MC | 1282 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE; 1283 av->vdev.vfl_dir = VFL_DIR_RX; 1284 1285 ret = ipu6_isys_queue_init(&av->aq); 1286 if (ret) 1287 goto out_free_watermark; 1288 1289 av->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; 1290 ret = media_entity_pads_init(&av->vdev.entity, 1, &av->pad); 1291 if (ret) 1292 goto out_vb2_queue_release; 1293 1294 av->vdev.entity.ops = &entity_ops; 1295 av->vdev.release = video_device_release_empty; 1296 av->vdev.fops = &isys_fops; 1297 av->vdev.v4l2_dev = &av->isys->v4l2_dev; 1298 av->vdev.dev_parent = &av->isys->adev->isp->pdev->dev; 1299 if (!av->vdev.ioctl_ops) 1300 av->vdev.ioctl_ops = &ipu6_v4l2_ioctl_ops; 1301 av->vdev.queue = &av->aq.vbq; 1302 av->vdev.lock = &av->mutex; 1303 1304 __ipu6_isys_vidioc_try_fmt_vid_cap(av, &format); 1305 av->pix_fmt = format.fmt.pix; 1306 __ipu6_isys_vidioc_try_fmt_meta_cap(av, &format_meta); 1307 av->meta_fmt = format_meta.fmt.meta; 1308 1309 set_bit(V4L2_FL_USES_V4L2_FH, &av->vdev.flags); 1310 video_set_drvdata(&av->vdev, av); 1311 1312 ret = video_register_device(&av->vdev, VFL_TYPE_VIDEO, -1); 1313 if (ret) 1314 goto out_media_entity_cleanup; 1315 1316 return ret; 1317 1318 out_media_entity_cleanup: 1319 vb2_video_unregister_device(&av->vdev); 1320 media_entity_cleanup(&av->vdev.entity); 1321 1322 out_vb2_queue_release: 1323 vb2_queue_release(&av->aq.vbq); 1324 1325 out_free_watermark: 1326 mutex_destroy(&av->mutex); 1327 1328 return ret; 1329 } 1330 1331 void ipu6_isys_video_cleanup(struct ipu6_isys_video *av) 1332 { 1333 vb2_video_unregister_device(&av->vdev); 1334 media_entity_cleanup(&av->vdev.entity); 1335 mutex_destroy(&av->mutex); 1336 } 1337 1338 u32 ipu6_isys_get_format(struct ipu6_isys_video *av) 1339 { 1340 if (av->aq.vbq.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1341 return av->pix_fmt.pixelformat; 1342 1343 if (av->aq.vbq.type == V4L2_BUF_TYPE_META_CAPTURE) 1344 return av->meta_fmt.dataformat; 1345 1346 return 0; 1347 } 1348 1349 u32 ipu6_isys_get_data_size(struct ipu6_isys_video *av) 1350 { 1351 if (av->aq.vbq.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1352 return av->pix_fmt.sizeimage; 1353 1354 if (av->aq.vbq.type == V4L2_BUF_TYPE_META_CAPTURE) 1355 return av->meta_fmt.buffersize; 1356 1357 return 0; 1358 } 1359 1360 u32 ipu6_isys_get_bytes_per_line(struct ipu6_isys_video *av) 1361 { 1362 if (av->aq.vbq.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1363 return av->pix_fmt.bytesperline; 1364 1365 if (av->aq.vbq.type == V4L2_BUF_TYPE_META_CAPTURE) 1366 return av->meta_fmt.bytesperline; 1367 1368 return 0; 1369 } 1370 1371 u32 ipu6_isys_get_frame_width(struct ipu6_isys_video *av) 1372 { 1373 if (av->aq.vbq.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1374 return av->pix_fmt.width; 1375 1376 if (av->aq.vbq.type == V4L2_BUF_TYPE_META_CAPTURE) 1377 return av->meta_fmt.width; 1378 1379 return 0; 1380 } 1381 1382 u32 ipu6_isys_get_frame_height(struct ipu6_isys_video *av) 1383 { 1384 if (av->aq.vbq.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1385 return av->pix_fmt.height; 1386 1387 if (av->aq.vbq.type == V4L2_BUF_TYPE_META_CAPTURE) 1388 return av->meta_fmt.height; 1389 1390 return 0; 1391 } 1392