Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: intel/ipu6: support line-based metadata capture support

Some camera sensor can output the embedded data in specific data type.
This patch adds the support for metadata capture in IPU6 ISYS driver.

Signed-off-by: Hongju Wang <hongju.wang@intel.com>
Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>
Co-developed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>

authored by

Bingbu Cao and committed by
Hans Verkuil
d3bd039c 7c833d20

+298 -108
+5
drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
··· 42 42 MEDIA_BUS_FMT_SGBRG8_1X8, 43 43 MEDIA_BUS_FMT_SGRBG8_1X8, 44 44 MEDIA_BUS_FMT_SRGGB8_1X8, 45 + MEDIA_BUS_FMT_META_8, 46 + MEDIA_BUS_FMT_META_10, 47 + MEDIA_BUS_FMT_META_12, 48 + MEDIA_BUS_FMT_META_16, 49 + MEDIA_BUS_FMT_META_24, 45 50 0 46 51 }; 47 52
+23 -22
drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
··· 28 28 struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(q); 29 29 struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); 30 30 struct device *dev = &av->isys->adev->auxdev.dev; 31 - u32 size = av->pix_fmt.sizeimage; 31 + u32 size = ipu6_isys_get_data_size(av); 32 32 33 33 /* num_planes == 0: we're being called through VIDIOC_REQBUFS */ 34 34 if (!*num_planes) { ··· 49 49 struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); 50 50 struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); 51 51 struct device *dev = &av->isys->adev->auxdev.dev; 52 + u32 bytesperline = ipu6_isys_get_bytes_per_line(av); 53 + u32 height = ipu6_isys_get_frame_height(av); 54 + u32 size = ipu6_isys_get_data_size(av); 52 55 53 56 dev_dbg(dev, "buffer: %s: configured size %u, buffer size %lu\n", 54 - av->vdev.name, av->pix_fmt.sizeimage, 55 - vb2_plane_size(vb, 0)); 57 + av->vdev.name, size, vb2_plane_size(vb, 0)); 56 58 57 - if (av->pix_fmt.sizeimage > vb2_plane_size(vb, 0)) 59 + if (size > vb2_plane_size(vb, 0)) 58 60 return -EINVAL; 59 61 60 - vb2_set_plane_payload(vb, 0, av->pix_fmt.bytesperline * 61 - av->pix_fmt.height); 62 - vb->planes[0].data_offset = 0; 62 + vb2_set_plane_payload(vb, 0, bytesperline * height); 63 63 64 64 return 0; 65 65 } ··· 328 328 struct isys_fw_msgs *msg; 329 329 unsigned long flags; 330 330 dma_addr_t dma; 331 - unsigned int i; 332 331 int ret; 333 332 334 333 dev_dbg(dev, "queue buffer %u for %s\n", vb->index, av->vdev.name); 335 334 336 - for (i = 0; i < vb->num_planes; i++) { 337 - dma = vb2_dma_contig_plane_dma_addr(vb, i); 338 - dev_dbg(dev, "iova: plane %u iova %pad\n", i, &dma); 339 - } 335 + dma = vb2_dma_contig_plane_dma_addr(vb, 0); 336 + dev_dbg(dev, "iova: iova %pad\n", &dma); 340 337 341 338 spin_lock_irqsave(&aq->lock, flags); 342 339 list_add(&ib->head, &aq->incoming); ··· 406 409 struct media_pad *remote_pad = 407 410 media_pad_remote_pad_first(av->vdev.entity.pads); 408 411 struct v4l2_subdev *sd; 409 - u32 r_stream; 412 + u32 r_stream, code; 410 413 int ret; 411 414 412 415 if (!remote_pad) ··· 424 427 return ret; 425 428 } 426 429 427 - if (format.width != av->pix_fmt.width || 428 - format.height != av->pix_fmt.height) { 429 - dev_dbg(dev, "wrong width or height %ux%u (%ux%u expected)\n", 430 - av->pix_fmt.width, av->pix_fmt.height, 431 - format.width, format.height); 430 + if (format.width != ipu6_isys_get_frame_width(av) || 431 + format.height != ipu6_isys_get_frame_height(av)) { 432 + dev_err(dev, "wrong width or height %ux%u (%ux%u expected)\n", 433 + ipu6_isys_get_frame_width(av), 434 + ipu6_isys_get_frame_height(av), format.width, 435 + format.height); 432 436 return -EINVAL; 433 437 } 434 438 435 - if (format.code != av->pfmt->code) { 439 + code = ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0)->code; 440 + if (format.code != code) { 436 441 dev_dbg(dev, "wrong mbus code 0x%8.8x (0x%8.8x expected)\n", 437 - av->pfmt->code, format.code); 442 + code, format.code); 438 443 return -EINVAL; 439 444 } 440 445 ··· 508 509 struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(q); 509 510 struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); 510 511 struct device *dev = &av->isys->adev->auxdev.dev; 512 + const struct ipu6_isys_pixelformat *pfmt = 513 + ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0); 511 514 struct ipu6_isys_buffer_list __bl, *bl = NULL; 512 515 struct ipu6_isys_stream *stream; 513 516 struct media_entity *source_entity = NULL; 514 517 int nr_queues, ret; 515 518 516 519 dev_dbg(dev, "stream: %s: width %u, height %u, css pixelformat %u\n", 517 - av->vdev.name, av->pix_fmt.width, av->pix_fmt.height, 518 - av->pfmt->css_pixelformat); 520 + av->vdev.name, ipu6_isys_get_frame_width(av), 521 + ipu6_isys_get_frame_height(av), pfmt->css_pixelformat); 519 522 520 523 ret = ipu6_isys_setup_video(av, &source_entity, &nr_queues); 521 524 if (ret < 0) {
+5
drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c
··· 20 20 { 21 21 switch (code) { 22 22 case MEDIA_BUS_FMT_RGB888_1X24: 23 + case MEDIA_BUS_FMT_META_24: 23 24 return 24; 24 25 case MEDIA_BUS_FMT_RGB565_1X16: 25 26 case MEDIA_BUS_FMT_UYVY8_1X16: 26 27 case MEDIA_BUS_FMT_YUYV8_1X16: 28 + case MEDIA_BUS_FMT_META_16: 27 29 return 16; 28 30 case MEDIA_BUS_FMT_SBGGR12_1X12: 29 31 case MEDIA_BUS_FMT_SGBRG12_1X12: 30 32 case MEDIA_BUS_FMT_SGRBG12_1X12: 31 33 case MEDIA_BUS_FMT_SRGGB12_1X12: 34 + case MEDIA_BUS_FMT_META_12: 32 35 return 12; 33 36 case MEDIA_BUS_FMT_SBGGR10_1X10: 34 37 case MEDIA_BUS_FMT_SGBRG10_1X10: 35 38 case MEDIA_BUS_FMT_SGRBG10_1X10: 36 39 case MEDIA_BUS_FMT_SRGGB10_1X10: 40 + case MEDIA_BUS_FMT_META_10: 37 41 return 10; 38 42 case MEDIA_BUS_FMT_SBGGR8_1X8: 39 43 case MEDIA_BUS_FMT_SGBRG8_1X8: 40 44 case MEDIA_BUS_FMT_SGRBG8_1X8: 41 45 case MEDIA_BUS_FMT_SRGGB8_1X8: 46 + case MEDIA_BUS_FMT_META_8: 42 47 return 8; 43 48 default: 44 49 WARN_ON(1);
+255 -84
drivers/media/pci/intel/ipu6/ipu6-isys-video.c
··· 85 85 IPU6_FW_ISYS_FRAME_FORMAT_RGB565 }, 86 86 { V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24, 87 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 }, 88 96 }; 89 97 90 98 static int video_open(struct file *file) ··· 112 104 return v4l2_fh_open(file); 113 105 } 114 106 115 - static const struct ipu6_isys_pixelformat * 116 - ipu6_isys_get_pixelformat(u32 pixelformat) 107 + const struct ipu6_isys_pixelformat * 108 + ipu6_isys_get_isys_format(u32 pixelformat, u32 type) 117 109 { 110 + const struct ipu6_isys_pixelformat *default_pfmt = NULL; 118 111 unsigned int i; 119 112 120 113 for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { 121 114 const struct ipu6_isys_pixelformat *pfmt = &ipu6_isys_pfmts[i]; 122 115 123 - if (pfmt->pixelformat == pixelformat) 124 - return pfmt; 116 + if (type && ((!pfmt->is_meta && 117 + type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || 118 + (pfmt->is_meta && 119 + type != V4L2_BUF_TYPE_META_CAPTURE))) 120 + continue; 121 + 122 + if (!default_pfmt) 123 + default_pfmt = pfmt; 124 + 125 + if (pfmt->pixelformat != pixelformat) 126 + continue; 127 + 128 + return pfmt; 125 129 } 126 130 127 - return &ipu6_isys_pfmts[0]; 131 + return default_pfmt; 128 132 } 129 133 130 134 static int ipu6_isys_vidioc_querycap(struct file *file, void *fh, ··· 153 133 static int ipu6_isys_vidioc_enum_fmt(struct file *file, void *fh, 154 134 struct v4l2_fmtdesc *f) 155 135 { 156 - unsigned int i, found = 0; 136 + unsigned int i, num_found; 157 137 158 - if (f->index >= ARRAY_SIZE(ipu6_isys_pfmts)) 159 - return -EINVAL; 160 - 161 - if (!f->mbus_code) { 162 - f->flags = 0; 163 - f->pixelformat = ipu6_isys_pfmts[f->index].pixelformat; 164 - return 0; 165 - } 166 - 167 - for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { 168 - if (f->mbus_code != ipu6_isys_pfmts[i].code) 138 + for (i = 0, num_found = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { 139 + if ((ipu6_isys_pfmts[i].is_meta && 140 + f->type != V4L2_BUF_TYPE_META_CAPTURE) || 141 + (!ipu6_isys_pfmts[i].is_meta && 142 + f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) 169 143 continue; 170 144 171 - if (f->index == found) { 172 - f->flags = 0; 173 - f->pixelformat = ipu6_isys_pfmts[i].pixelformat; 174 - return 0; 145 + if (f->mbus_code && f->mbus_code != ipu6_isys_pfmts[i].code) 146 + continue; 147 + 148 + if (num_found < f->index) { 149 + num_found++; 150 + continue; 175 151 } 176 - found++; 152 + 153 + f->flags = 0; 154 + f->pixelformat = ipu6_isys_pfmts[i].pixelformat; 155 + 156 + return 0; 177 157 } 178 158 179 159 return -EINVAL; ··· 205 185 return -EINVAL; 206 186 } 207 187 208 - static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, 209 - struct v4l2_format *fmt) 188 + static int ipu6_isys_vidioc_g_fmt_vid_cap(struct file *file, void *fh, 189 + struct v4l2_format *f) 210 190 { 211 191 struct ipu6_isys_video *av = video_drvdata(file); 212 192 213 - fmt->fmt.pix = av->pix_fmt; 193 + f->fmt.pix = av->pix_fmt; 214 194 215 195 return 0; 216 196 } 217 197 218 - static const struct ipu6_isys_pixelformat * 219 - ipu6_isys_video_try_fmt_vid(struct ipu6_isys_video *av, 220 - struct v4l2_pix_format *pix_fmt) 198 + static int ipu6_isys_vidioc_g_fmt_meta_cap(struct file *file, void *fh, 199 + struct v4l2_format *f) 200 + { 201 + struct ipu6_isys_video *av = video_drvdata(file); 202 + 203 + f->fmt.meta = av->meta_fmt; 204 + 205 + return 0; 206 + } 207 + 208 + static void ipu6_isys_try_fmt_cap(struct ipu6_isys_video *av, u32 type, 209 + u32 *format, u32 *width, u32 *height, 210 + u32 *bytesperline, u32 *sizeimage) 221 211 { 222 212 const struct ipu6_isys_pixelformat *pfmt = 223 - ipu6_isys_get_pixelformat(pix_fmt->pixelformat); 213 + ipu6_isys_get_isys_format(*format, type); 224 214 225 - pix_fmt->pixelformat = pfmt->pixelformat; 226 - 227 - pix_fmt->width = clamp(pix_fmt->width, IPU6_ISYS_MIN_WIDTH, 228 - IPU6_ISYS_MAX_WIDTH); 229 - pix_fmt->height = clamp(pix_fmt->height, IPU6_ISYS_MIN_HEIGHT, 230 - IPU6_ISYS_MAX_HEIGHT); 215 + *format = pfmt->pixelformat; 216 + *width = clamp(*width, IPU6_ISYS_MIN_WIDTH, IPU6_ISYS_MAX_WIDTH); 217 + *height = clamp(*height, IPU6_ISYS_MIN_HEIGHT, IPU6_ISYS_MAX_HEIGHT); 231 218 232 219 if (pfmt->bpp != pfmt->bpp_packed) 233 - pix_fmt->bytesperline = 234 - pix_fmt->width * DIV_ROUND_UP(pfmt->bpp, BITS_PER_BYTE); 220 + *bytesperline = *width * DIV_ROUND_UP(pfmt->bpp, BITS_PER_BYTE); 235 221 else 236 - pix_fmt->bytesperline = 237 - DIV_ROUND_UP(pix_fmt->width * pfmt->bpp, BITS_PER_BYTE); 222 + *bytesperline = DIV_ROUND_UP(*width * pfmt->bpp, BITS_PER_BYTE); 238 223 239 - pix_fmt->bytesperline = ALIGN(pix_fmt->bytesperline, 240 - av->isys->line_align); 224 + *bytesperline = ALIGN(*bytesperline, av->isys->line_align); 241 225 242 226 /* 243 227 * (height + 1) * bytesperline due to a hardware issue: the DMA unit ··· 252 228 * resolution it gives a bigger number. Use larger one to avoid 253 229 * memory corruption. 254 230 */ 255 - pix_fmt->sizeimage = 256 - max(pix_fmt->sizeimage, 257 - pix_fmt->bytesperline * pix_fmt->height + 258 - max(pix_fmt->bytesperline, 259 - av->isys->pdata->ipdata->isys_dma_overshoot)); 260 - 261 - pix_fmt->field = V4L2_FIELD_NONE; 262 - 263 - pix_fmt->colorspace = V4L2_COLORSPACE_RAW; 264 - pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 265 - pix_fmt->quantization = V4L2_QUANTIZATION_DEFAULT; 266 - pix_fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; 267 - 268 - return pfmt; 231 + *sizeimage = *bytesperline * *height + 232 + max(*bytesperline, 233 + av->isys->pdata->ipdata->isys_dma_overshoot); 269 234 } 270 235 271 - static int vidioc_s_fmt_vid_cap(struct file *file, void *fh, 272 - struct v4l2_format *f) 236 + static void __ipu6_isys_vidioc_try_fmt_vid_cap(struct ipu6_isys_video *av, 237 + struct v4l2_format *f) 238 + { 239 + ipu6_isys_try_fmt_cap(av, f->type, &f->fmt.pix.pixelformat, 240 + &f->fmt.pix.width, &f->fmt.pix.height, 241 + &f->fmt.pix.bytesperline, &f->fmt.pix.sizeimage); 242 + 243 + f->fmt.pix.field = V4L2_FIELD_NONE; 244 + f->fmt.pix.colorspace = V4L2_COLORSPACE_RAW; 245 + f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 246 + f->fmt.pix.quantization = V4L2_QUANTIZATION_DEFAULT; 247 + f->fmt.pix.xfer_func = V4L2_XFER_FUNC_DEFAULT; 248 + } 249 + 250 + static int ipu6_isys_vidioc_try_fmt_vid_cap(struct file *file, void *fh, 251 + struct v4l2_format *f) 273 252 { 274 253 struct ipu6_isys_video *av = video_drvdata(file); 275 254 276 255 if (vb2_is_busy(&av->aq.vbq)) 277 256 return -EBUSY; 278 257 279 - av->pfmt = ipu6_isys_video_try_fmt_vid(av, &f->fmt.pix); 258 + __ipu6_isys_vidioc_try_fmt_vid_cap(av, f); 259 + 260 + return 0; 261 + } 262 + 263 + static int __ipu6_isys_vidioc_try_fmt_meta_cap(struct ipu6_isys_video *av, 264 + struct v4l2_format *f) 265 + { 266 + ipu6_isys_try_fmt_cap(av, f->type, &f->fmt.meta.dataformat, 267 + &f->fmt.meta.width, &f->fmt.meta.height, 268 + &f->fmt.meta.bytesperline, 269 + &f->fmt.meta.buffersize); 270 + 271 + return 0; 272 + } 273 + 274 + static int ipu6_isys_vidioc_try_fmt_meta_cap(struct file *file, void *fh, 275 + struct v4l2_format *f) 276 + { 277 + struct ipu6_isys_video *av = video_drvdata(file); 278 + 279 + __ipu6_isys_vidioc_try_fmt_meta_cap(av, f); 280 + 281 + return 0; 282 + } 283 + 284 + static int ipu6_isys_vidioc_s_fmt_vid_cap(struct file *file, void *fh, 285 + struct v4l2_format *f) 286 + { 287 + struct ipu6_isys_video *av = video_drvdata(file); 288 + 289 + ipu6_isys_vidioc_try_fmt_vid_cap(file, fh, f); 280 290 av->pix_fmt = f->fmt.pix; 281 291 282 292 return 0; 283 293 } 284 294 285 - static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, 286 - struct v4l2_format *f) 295 + static int ipu6_isys_vidioc_s_fmt_meta_cap(struct file *file, void *fh, 296 + struct v4l2_format *f) 287 297 { 288 298 struct ipu6_isys_video *av = video_drvdata(file); 289 299 290 - ipu6_isys_video_try_fmt_vid(av, &f->fmt.pix); 300 + if (vb2_is_busy(&av->aq.vbq)) 301 + return -EBUSY; 302 + 303 + ipu6_isys_vidioc_try_fmt_meta_cap(file, fh, f); 304 + av->meta_fmt = f->fmt.meta; 291 305 292 306 return 0; 307 + } 308 + 309 + static int ipu6_isys_vidioc_reqbufs(struct file *file, void *priv, 310 + struct v4l2_requestbuffers *p) 311 + { 312 + struct ipu6_isys_video *av = video_drvdata(file); 313 + int ret; 314 + 315 + av->aq.vbq.is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(p->type); 316 + av->aq.vbq.is_output = V4L2_TYPE_IS_OUTPUT(p->type); 317 + 318 + ret = vb2_queue_change_type(&av->aq.vbq, p->type); 319 + if (ret) 320 + return ret; 321 + 322 + return vb2_ioctl_reqbufs(file, priv, p); 323 + } 324 + 325 + static int ipu6_isys_vidioc_create_bufs(struct file *file, void *priv, 326 + struct v4l2_create_buffers *p) 327 + { 328 + struct ipu6_isys_video *av = video_drvdata(file); 329 + int ret; 330 + 331 + av->aq.vbq.is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(p->format.type); 332 + av->aq.vbq.is_output = V4L2_TYPE_IS_OUTPUT(p->format.type); 333 + 334 + ret = vb2_queue_change_type(&av->aq.vbq, p->format.type); 335 + if (ret) 336 + return ret; 337 + 338 + return vb2_ioctl_create_bufs(file, priv, p); 293 339 } 294 340 295 341 static int link_validate(struct media_link *link) ··· 371 277 struct v4l2_subdev *s_sd; 372 278 struct v4l2_mbus_framefmt *s_fmt; 373 279 struct media_pad *s_pad; 374 - u32 s_stream; 280 + u32 s_stream, code; 375 281 int ret = -EPIPE; 376 282 377 283 if (!link->source->entity) ··· 397 303 goto unlock; 398 304 } 399 305 400 - if (s_fmt->width != av->pix_fmt.width || 401 - s_fmt->height != av->pix_fmt.height || s_fmt->code != av->pfmt->code) { 306 + code = ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0)->code; 307 + 308 + if (s_fmt->width != ipu6_isys_get_frame_width(av) || 309 + s_fmt->height != ipu6_isys_get_frame_height(av) || 310 + s_fmt->code != code) { 402 311 dev_dbg(dev, "format mismatch %dx%d,%x != %dx%d,%x\n", 403 312 s_fmt->width, s_fmt->height, s_fmt->code, 404 - av->pix_fmt.width, av->pix_fmt.height, av->pfmt->code); 313 + ipu6_isys_get_frame_width(av), 314 + ipu6_isys_get_frame_height(av), code); 405 315 goto unlock; 406 316 } 407 317 ··· 446 348 struct ipu6_isys_stream *stream = av->stream; 447 349 struct ipu6_isys_queue *aq = &av->aq; 448 350 struct v4l2_mbus_framefmt fmt; 351 + const struct ipu6_isys_pixelformat *pfmt = 352 + ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0); 449 353 struct v4l2_rect v4l2_crop; 450 354 struct ipu6_isys *isys = av->isys; 451 355 struct device *dev = &isys->adev->auxdev.dev; ··· 475 375 input_pin->input_res.width = fmt.width; 476 376 input_pin->input_res.height = fmt.height; 477 377 input_pin->dt = av->dt; 478 - input_pin->bits_per_pix = av->pfmt->bpp_packed; 378 + input_pin->bits_per_pix = pfmt->bpp_packed; 479 379 input_pin->mapped_dt = 0x40; /* invalid mipi data type */ 480 380 input_pin->mipi_decompression = 0; 481 381 input_pin->capture_mode = IPU6_FW_ISYS_CAPTURE_MODE_REGULAR; 482 - input_pin->mipi_store_mode = av->pfmt->bpp == av->pfmt->bpp_packed ? 382 + input_pin->mipi_store_mode = pfmt->bpp == pfmt->bpp_packed ? 483 383 IPU6_FW_ISYS_MIPI_STORE_MODE_DISCARD_LONG_HEADER : 484 384 IPU6_FW_ISYS_MIPI_STORE_MODE_NORMAL; 485 385 input_pin->crop_first_and_last_lines = v4l2_crop.top & 1; ··· 491 391 492 392 output_pin = &cfg->output_pins[output_pins]; 493 393 output_pin->input_pin_id = input_pins; 494 - output_pin->output_res.width = av->pix_fmt.width; 495 - output_pin->output_res.height = av->pix_fmt.height; 394 + output_pin->output_res.width = ipu6_isys_get_frame_width(av); 395 + output_pin->output_res.height = ipu6_isys_get_frame_height(av); 496 396 497 - output_pin->stride = av->pix_fmt.bytesperline; 498 - if (av->pfmt->bpp != av->pfmt->bpp_packed) 397 + output_pin->stride = ipu6_isys_get_bytes_per_line(av); 398 + if (pfmt->bpp != pfmt->bpp_packed) 499 399 output_pin->pt = IPU6_FW_ISYS_PIN_TYPE_RAW_SOC; 500 400 else 501 401 output_pin->pt = IPU6_FW_ISYS_PIN_TYPE_MIPI; 502 - output_pin->ft = av->pfmt->css_pixelformat; 402 + output_pin->ft = pfmt->css_pixelformat; 503 403 output_pin->send_irq = 1; 504 404 memset(output_pin->ts_offsets, 0, sizeof(output_pin->ts_offsets)); 505 405 output_pin->s2m_pixel_soc_pixel_remapping = ··· 761 661 762 662 esd = media_entity_to_v4l2_subdev(av->stream->source_entity); 763 663 764 - av->watermark.width = av->pix_fmt.width; 765 - av->watermark.height = av->pix_fmt.height; 664 + av->watermark.width = ipu6_isys_get_frame_width(av); 665 + av->watermark.height = ipu6_isys_get_frame_height(av); 766 666 av->watermark.sram_gran_shift = isys->pdata->ipdata->sram_gran_shift; 767 667 av->watermark.sram_gran_size = isys->pdata->ipdata->sram_gran_size; 768 668 ··· 798 698 static void calculate_stream_datarate(struct ipu6_isys_video *av) 799 699 { 800 700 struct video_stream_watermark *watermark = &av->watermark; 801 - u32 bpp = av->pfmt->bpp; 701 + const struct ipu6_isys_pixelformat *pfmt = 702 + ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0); 802 703 u32 pages_per_line, pb_bytes_per_line, pixels_per_line, bytes_per_line; 803 704 u64 line_time_ns, stream_data_rate; 804 705 u16 shift, size; ··· 810 709 pixels_per_line = watermark->width + watermark->hblank; 811 710 line_time_ns = div_u64(pixels_per_line * NSEC_PER_SEC, 812 711 watermark->pixel_rate); 813 - bytes_per_line = watermark->width * bpp / 8; 712 + bytes_per_line = watermark->width * pfmt->bpp / 8; 814 713 pages_per_line = DIV_ROUND_UP(bytes_per_line, size); 815 714 pb_bytes_per_line = pages_per_line << shift; 816 715 stream_data_rate = div64_u64(pb_bytes_per_line * 1000, line_time_ns); ··· 1089 988 static const struct v4l2_ioctl_ops ipu6_v4l2_ioctl_ops = { 1090 989 .vidioc_querycap = ipu6_isys_vidioc_querycap, 1091 990 .vidioc_enum_fmt_vid_cap = ipu6_isys_vidioc_enum_fmt, 991 + .vidioc_enum_fmt_meta_cap = ipu6_isys_vidioc_enum_fmt, 1092 992 .vidioc_enum_framesizes = ipu6_isys_vidioc_enum_framesizes, 1093 - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, 1094 - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, 1095 - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, 1096 - .vidioc_reqbufs = vb2_ioctl_reqbufs, 1097 - .vidioc_create_bufs = vb2_ioctl_create_bufs, 993 + .vidioc_g_fmt_vid_cap = ipu6_isys_vidioc_g_fmt_vid_cap, 994 + .vidioc_s_fmt_vid_cap = ipu6_isys_vidioc_s_fmt_vid_cap, 995 + .vidioc_try_fmt_vid_cap = ipu6_isys_vidioc_try_fmt_vid_cap, 996 + .vidioc_g_fmt_meta_cap = ipu6_isys_vidioc_g_fmt_meta_cap, 997 + .vidioc_s_fmt_meta_cap = ipu6_isys_vidioc_s_fmt_meta_cap, 998 + .vidioc_try_fmt_meta_cap = ipu6_isys_vidioc_try_fmt_meta_cap, 999 + .vidioc_reqbufs = ipu6_isys_vidioc_reqbufs, 1000 + .vidioc_create_bufs = ipu6_isys_vidioc_create_bufs, 1098 1001 .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 1099 1002 .vidioc_querybuf = vb2_ioctl_querybuf, 1100 1003 .vidioc_qbuf = vb2_ioctl_qbuf, ··· 1197 1092 int ipu6_isys_setup_video(struct ipu6_isys_video *av, 1198 1093 struct media_entity **source_entity, int *nr_queues) 1199 1094 { 1095 + const struct ipu6_isys_pixelformat *pfmt = 1096 + ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0); 1200 1097 struct device *dev = &av->isys->adev->auxdev.dev; 1201 1098 struct v4l2_mbus_frame_desc_entry entry; 1202 1099 struct v4l2_subdev_route *route = NULL; ··· 1250 1143 *source_entity, &entry); 1251 1144 if (ret == -ENOIOCTLCMD) { 1252 1145 av->vc = 0; 1253 - av->dt = ipu6_isys_mbus_code_to_mipi(av->pfmt->code); 1146 + av->dt = ipu6_isys_mbus_code_to_mipi(pfmt->code); 1254 1147 } else if (!ret) { 1255 1148 dev_dbg(dev, "Framedesc: stream %u, len %u, vc %u, dt %#x\n", 1256 1149 entry.stream, entry.length, entry.bus.csi2.vc, ··· 1298 1191 .height = 1080, 1299 1192 }, 1300 1193 }; 1194 + struct v4l2_format format_meta = { 1195 + .type = V4L2_BUF_TYPE_META_CAPTURE, 1196 + .fmt.meta = { 1197 + .width = 1920, 1198 + .height = 4, 1199 + }, 1200 + }; 1301 1201 int ret; 1302 1202 1303 1203 mutex_init(&av->mutex); 1304 1204 av->vdev.device_caps = V4L2_CAP_STREAMING | V4L2_CAP_IO_MC | 1305 - V4L2_CAP_VIDEO_CAPTURE; 1205 + V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE; 1306 1206 av->vdev.vfl_dir = VFL_DIR_RX; 1307 1207 1308 1208 ret = ipu6_isys_queue_init(&av->aq); ··· 1330 1216 av->vdev.queue = &av->aq.vbq; 1331 1217 av->vdev.lock = &av->mutex; 1332 1218 1333 - ipu6_isys_video_try_fmt_vid(av, &format.fmt.pix); 1219 + __ipu6_isys_vidioc_try_fmt_vid_cap(av, &format); 1334 1220 av->pix_fmt = format.fmt.pix; 1221 + __ipu6_isys_vidioc_try_fmt_meta_cap(av, &format_meta); 1222 + av->meta_fmt = format_meta.fmt.meta; 1335 1223 1336 1224 set_bit(V4L2_FL_USES_V4L2_FH, &av->vdev.flags); 1337 1225 video_set_drvdata(&av->vdev, av); ··· 1362 1246 vb2_video_unregister_device(&av->vdev); 1363 1247 media_entity_cleanup(&av->vdev.entity); 1364 1248 mutex_destroy(&av->mutex); 1249 + } 1250 + 1251 + u32 ipu6_isys_get_format(struct ipu6_isys_video *av) 1252 + { 1253 + if (av->aq.vbq.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1254 + return av->pix_fmt.pixelformat; 1255 + 1256 + if (av->aq.vbq.type == V4L2_BUF_TYPE_META_CAPTURE) 1257 + return av->meta_fmt.dataformat; 1258 + 1259 + return 0; 1260 + } 1261 + 1262 + u32 ipu6_isys_get_data_size(struct ipu6_isys_video *av) 1263 + { 1264 + if (av->aq.vbq.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1265 + return av->pix_fmt.sizeimage; 1266 + 1267 + if (av->aq.vbq.type == V4L2_BUF_TYPE_META_CAPTURE) 1268 + return av->meta_fmt.buffersize; 1269 + 1270 + return 0; 1271 + } 1272 + 1273 + u32 ipu6_isys_get_bytes_per_line(struct ipu6_isys_video *av) 1274 + { 1275 + if (av->aq.vbq.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1276 + return av->pix_fmt.bytesperline; 1277 + 1278 + if (av->aq.vbq.type == V4L2_BUF_TYPE_META_CAPTURE) 1279 + return av->meta_fmt.bytesperline; 1280 + 1281 + return 0; 1282 + } 1283 + 1284 + u32 ipu6_isys_get_frame_width(struct ipu6_isys_video *av) 1285 + { 1286 + if (av->aq.vbq.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1287 + return av->pix_fmt.width; 1288 + 1289 + if (av->aq.vbq.type == V4L2_BUF_TYPE_META_CAPTURE) 1290 + return av->meta_fmt.width; 1291 + 1292 + return 0; 1293 + } 1294 + 1295 + u32 ipu6_isys_get_frame_height(struct ipu6_isys_video *av) 1296 + { 1297 + if (av->aq.vbq.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1298 + return av->pix_fmt.height; 1299 + 1300 + if (av->aq.vbq.type == V4L2_BUF_TYPE_META_CAPTURE) 1301 + return av->meta_fmt.height; 1302 + 1303 + return 0; 1365 1304 }
+10 -1
drivers/media/pci/intel/ipu6/ipu6-isys-video.h
··· 29 29 u32 bpp_packed; 30 30 u32 code; 31 31 u32 css_pixelformat; 32 + bool is_meta; 32 33 }; 33 34 34 35 struct sequence_info { ··· 92 91 struct media_pad pad; 93 92 struct video_device vdev; 94 93 struct v4l2_pix_format pix_fmt; 95 - const struct ipu6_isys_pixelformat *pfmt; 94 + struct v4l2_meta_format meta_fmt; 96 95 struct ipu6_isys *isys; 97 96 struct ipu6_isys_csi2 *csi2; 98 97 struct ipu6_isys_stream *stream; ··· 109 108 extern const struct ipu6_isys_pixelformat ipu6_isys_pfmts[]; 110 109 extern const struct ipu6_isys_pixelformat ipu6_isys_pfmts_packed[]; 111 110 111 + const struct ipu6_isys_pixelformat * 112 + ipu6_isys_get_isys_format(u32 pixelformat, u32 code); 112 113 int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av, 113 114 struct media_entity *source_entity, 114 115 int nr_queues); ··· 131 128 void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av, 132 129 bool state); 133 130 void ipu6_isys_update_stream_watermark(struct ipu6_isys_video *av, bool state); 131 + 132 + u32 ipu6_isys_get_format(struct ipu6_isys_video *av); 133 + u32 ipu6_isys_get_data_size(struct ipu6_isys_video *av); 134 + u32 ipu6_isys_get_bytes_per_line(struct ipu6_isys_video *av); 135 + u32 ipu6_isys_get_frame_width(struct ipu6_isys_video *av); 136 + u32 ipu6_isys_get_frame_height(struct ipu6_isys_video *av); 134 137 135 138 #endif /* IPU6_ISYS_VIDEO_H */
-1
drivers/media/pci/intel/ipu6/ipu6-isys.c
··· 249 249 av->isys = isys; 250 250 av->aq.vbq.buf_struct_size = 251 251 sizeof(struct ipu6_isys_video_buffer); 252 - av->pfmt = &ipu6_isys_pfmts[0]; 253 252 254 253 ret = ipu6_isys_video_init(av); 255 254 if (ret)