FILE
ipu7-isys-queue.c
File preview with syntax highlighting.
linux-6.19.14/drivers/staging/media/ipu7/ipu7-isys-queue.c
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2013 - 2025 Intel Corporation 4 */ 5 6#include <linux/atomic.h> 7#include <linux/bug.h> 8#include <linux/device.h> 9#include <linux/list.h> 10#include <linux/lockdep.h> 11#include <linux/mutex.h> 12#include <linux/spinlock.h> 13#include <linux/types.h> 14 15#include <media/media-entity.h> 16#include <media/v4l2-subdev.h> 17#include <media/videobuf2-dma-sg.h> 18#include <media/videobuf2-v4l2.h> 19 20#include "abi/ipu7_fw_isys_abi.h" 21 22#include "ipu7-bus.h" 23#include "ipu7-dma.h" 24#include "ipu7-fw-isys.h" 25#include "ipu7-isys.h" 26#include "ipu7-isys-csi2-regs.h" 27#include "ipu7-isys-video.h" 28#include "ipu7-platform-regs.h" 29 30#define IPU_MAX_FRAME_COUNTER (U8_MAX + 1) 31 32static int ipu7_isys_buf_init(struct vb2_buffer *vb) 33{ 34 struct ipu7_isys *isys = vb2_get_drv_priv(vb->vb2_queue); 35 struct sg_table *sg = vb2_dma_sg_plane_desc(vb, 0); 36 struct vb2_v4l2_buffer *vvb = to_vb2_v4l2_buffer(vb); 37 struct ipu7_isys_video_buffer *ivb = 38 vb2_buffer_to_ipu7_isys_video_buffer(vvb); 39 int ret; 40 41 ret = ipu7_dma_map_sgtable(isys->adev, sg, DMA_TO_DEVICE, 0); 42 if (ret) 43 return ret; 44 45 ivb->dma_addr = sg_dma_address(sg->sgl); 46 47 return 0; 48} 49 50static void ipu7_isys_buf_cleanup(struct vb2_buffer *vb) 51{ 52 struct ipu7_isys *isys = vb2_get_drv_priv(vb->vb2_queue); 53 struct sg_table *sg = vb2_dma_sg_plane_desc(vb, 0); 54 struct vb2_v4l2_buffer *vvb = to_vb2_v4l2_buffer(vb); 55 struct ipu7_isys_video_buffer *ivb = 56 vb2_buffer_to_ipu7_isys_video_buffer(vvb); 57 58 ivb->dma_addr = 0; 59 ipu7_dma_unmap_sgtable(isys->adev, sg, DMA_TO_DEVICE, 0); 60} 61 62static int ipu7_isys_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, 63 unsigned int *num_planes, unsigned int sizes[], 64 struct device *alloc_devs[]) 65{ 66 struct ipu7_isys_queue *aq = vb2_queue_to_isys_queue(q); 67 struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); 68 struct device *dev = &av->isys->adev->auxdev.dev; 69 u32 size = av->pix_fmt.sizeimage; 70 71 /* num_planes == 0: we're being called through VIDIOC_REQBUFS */ 72 if (!*num_planes) { 73 sizes[0] = size; 74 } else if (sizes[0] < size) { 75 dev_dbg(dev, "%s: queue setup: size %u < %u\n", 76 av->vdev.name, sizes[0], size); 77 return -EINVAL; 78 } 79 80 *num_planes = 1; 81 82 return 0; 83} 84 85static int ipu7_isys_buf_prepare(struct vb2_buffer *vb) 86{ 87 struct ipu7_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); 88 struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); 89 struct device *dev = &av->isys->adev->auxdev.dev; 90 u32 bytesperline = av->pix_fmt.bytesperline; 91 u32 height = av->pix_fmt.height; 92 93 dev_dbg(dev, "buffer: %s: configured size %u, buffer size %lu\n", 94 av->vdev.name, av->pix_fmt.sizeimage, vb2_plane_size(vb, 0)); 95 96 if (av->pix_fmt.sizeimage > vb2_plane_size(vb, 0)) 97 return -EINVAL; 98 99 dev_dbg(dev, "buffer: %s: bytesperline %u, height %u\n", 100 av->vdev.name, bytesperline, height); 101 vb2_set_plane_payload(vb, 0, bytesperline * height); 102 103 return 0; 104} 105 106/* 107 * Queue a buffer list back to incoming or active queues. The buffers 108 * are removed from the buffer list. 109 */ 110void ipu7_isys_buffer_list_queue(struct ipu7_isys_buffer_list *bl, 111 unsigned long op_flags, 112 enum vb2_buffer_state state) 113{ 114 struct ipu7_isys_buffer *ib, *ib_safe; 115 unsigned long flags; 116 bool first = true; 117 118 if (!bl) 119 return; 120 121 WARN_ON_ONCE(!bl->nbufs); 122 WARN_ON_ONCE(op_flags & IPU_ISYS_BUFFER_LIST_FL_ACTIVE && 123 op_flags & IPU_ISYS_BUFFER_LIST_FL_INCOMING); 124 125 list_for_each_entry_safe(ib, ib_safe, &bl->head, head) { 126 struct ipu7_isys_video *av; 127 128 struct vb2_buffer *vb = ipu7_isys_buffer_to_vb2_buffer(ib); 129 struct ipu7_isys_queue *aq = 130 vb2_queue_to_isys_queue(vb->vb2_queue); 131 132 av = ipu7_isys_queue_to_video(aq); 133 spin_lock_irqsave(&aq->lock, flags); 134 list_del(&ib->head); 135 if (op_flags & IPU_ISYS_BUFFER_LIST_FL_ACTIVE) 136 list_add(&ib->head, &aq->active); 137 else if (op_flags & IPU_ISYS_BUFFER_LIST_FL_INCOMING) 138 list_add_tail(&ib->head, &aq->incoming); 139 spin_unlock_irqrestore(&aq->lock, flags); 140 141 if (op_flags & IPU_ISYS_BUFFER_LIST_FL_SET_STATE) 142 vb2_buffer_done(vb, state); 143 144 if (first) { 145 dev_dbg(&av->isys->adev->auxdev.dev, 146 "queue buf list %p flags %lx, s %d, %d bufs\n", 147 bl, op_flags, state, bl->nbufs); 148 first = false; 149 } 150 151 bl->nbufs--; 152 } 153 154 WARN_ON(bl->nbufs); 155} 156 157/* 158 * flush_firmware_streamon_fail() - Flush in cases where requests may 159 * have been queued to firmware and the *firmware streamon fails for a 160 * reason or another. 161 */ 162static void flush_firmware_streamon_fail(struct ipu7_isys_stream *stream) 163{ 164 struct ipu7_isys_queue *aq; 165 unsigned long flags; 166 167 lockdep_assert_held(&stream->mutex); 168 169 list_for_each_entry(aq, &stream->queues, node) { 170 struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); 171 struct device *dev = &av->isys->adev->auxdev.dev; 172 struct ipu7_isys_buffer *ib, *ib_safe; 173 174 spin_lock_irqsave(&aq->lock, flags); 175 list_for_each_entry_safe(ib, ib_safe, &aq->active, head) { 176 struct vb2_buffer *vb = 177 ipu7_isys_buffer_to_vb2_buffer(ib); 178 179 list_del(&ib->head); 180 if (av->streaming) { 181 dev_dbg(dev, 182 "%s: queue buffer %u back to incoming\n", 183 av->vdev.name, vb->index); 184 /* Queue already streaming, return to driver. */ 185 list_add(&ib->head, &aq->incoming); 186 continue; 187 } 188 /* Queue not yet streaming, return to user. */ 189 dev_dbg(dev, "%s: return %u back to videobuf2\n", 190 av->vdev.name, vb->index); 191 vb2_buffer_done(ipu7_isys_buffer_to_vb2_buffer(ib), 192 VB2_BUF_STATE_QUEUED); 193 } 194 spin_unlock_irqrestore(&aq->lock, flags); 195 } 196} 197 198/* 199 * Attempt obtaining a buffer list from the incoming queues, a list of buffers 200 * that contains one entry from each video buffer queue. If a buffer can't be 201 * obtained from every queue, the buffers are returned back to the queue. 202 */ 203static int buffer_list_get(struct ipu7_isys_stream *stream, 204 struct ipu7_isys_buffer_list *bl) 205{ 206 unsigned long buf_flag = IPU_ISYS_BUFFER_LIST_FL_INCOMING; 207 struct device *dev = &stream->isys->adev->auxdev.dev; 208 struct ipu7_isys_queue *aq; 209 unsigned long flags; 210 211 bl->nbufs = 0; 212 INIT_LIST_HEAD(&bl->head); 213 214 list_for_each_entry(aq, &stream->queues, node) { 215 struct ipu7_isys_buffer *ib; 216 217 spin_lock_irqsave(&aq->lock, flags); 218 if (list_empty(&aq->incoming)) { 219 spin_unlock_irqrestore(&aq->lock, flags); 220 if (!list_empty(&bl->head)) 221 ipu7_isys_buffer_list_queue(bl, buf_flag, 0); 222 return -ENODATA; 223 } 224 225 ib = list_last_entry(&aq->incoming, 226 struct ipu7_isys_buffer, head); 227 228 dev_dbg(dev, "buffer: %s: buffer %u\n", 229 ipu7_isys_queue_to_video(aq)->vdev.name, 230 ipu7_isys_buffer_to_vb2_buffer(ib)->index); 231 list_del(&ib->head); 232 list_add(&ib->head, &bl->head); 233 spin_unlock_irqrestore(&aq->lock, flags); 234 235 bl->nbufs++; 236 } 237 238 dev_dbg(dev, "get buffer list %p, %u buffers\n", bl, bl->nbufs); 239 240 return 0; 241} 242 243static void ipu7_isys_buf_to_fw_frame_buf_pin(struct vb2_buffer *vb, 244 struct ipu7_insys_buffset *set) 245{ 246 struct ipu7_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); 247 struct vb2_v4l2_buffer *vvb = to_vb2_v4l2_buffer(vb); 248 struct ipu7_isys_video_buffer *ivb = 249 vb2_buffer_to_ipu7_isys_video_buffer(vvb); 250 251 set->output_pins[aq->fw_output].addr = ivb->dma_addr; 252 set->output_pins[aq->fw_output].user_token = (uintptr_t)set; 253} 254 255/* 256 * Convert a buffer list to a isys fw ABI framebuffer set. The 257 * buffer list is not modified. 258 */ 259#define IPU_ISYS_FRAME_NUM_THRESHOLD (30) 260void ipu7_isys_buffer_to_fw_frame_buff(struct ipu7_insys_buffset *set, 261 struct ipu7_isys_stream *stream, 262 struct ipu7_isys_buffer_list *bl) 263{ 264 struct ipu7_isys_buffer *ib; 265 u32 buf_id; 266 267 WARN_ON(!bl->nbufs); 268 269 set->skip_frame = 0; 270 set->capture_msg_map = IPU_INSYS_FRAME_ENABLE_MSG_SEND_RESP | 271 IPU_INSYS_FRAME_ENABLE_MSG_SEND_IRQ; 272 273 buf_id = atomic_fetch_inc(&stream->buf_id); 274 set->frame_id = buf_id % IPU_MAX_FRAME_COUNTER; 275 276 list_for_each_entry(ib, &bl->head, head) { 277 struct vb2_buffer *vb = ipu7_isys_buffer_to_vb2_buffer(ib); 278 279 ipu7_isys_buf_to_fw_frame_buf_pin(vb, set); 280 } 281} 282 283/* Start streaming for real. The buffer list must be available. */ 284static int ipu7_isys_stream_start(struct ipu7_isys_video *av, 285 struct ipu7_isys_buffer_list *bl, bool error) 286{ 287 struct ipu7_isys_stream *stream = av->stream; 288 struct device *dev = &stream->isys->adev->auxdev.dev; 289 struct ipu7_isys_buffer_list __bl; 290 int ret; 291 292 mutex_lock(&stream->isys->stream_mutex); 293 294 ret = ipu7_isys_video_set_streaming(av, 1, bl); 295 mutex_unlock(&stream->isys->stream_mutex); 296 if (ret) 297 goto out_requeue; 298 299 stream->streaming = 1; 300 301 bl = &__bl; 302 303 do { 304 struct ipu7_insys_buffset *buf = NULL; 305 struct isys_fw_msgs *msg; 306 enum ipu7_insys_send_type send_type = 307 IPU_INSYS_SEND_TYPE_STREAM_CAPTURE; 308 309 ret = buffer_list_get(stream, bl); 310 if (ret < 0) 311 break; 312 313 msg = ipu7_get_fw_msg_buf(stream); 314 if (!msg) 315 return -ENOMEM; 316 317 buf = &msg->fw_msg.frame; 318 319 ipu7_isys_buffer_to_fw_frame_buff(buf, stream, bl); 320 321 ipu7_fw_isys_dump_frame_buff_set(dev, buf, 322 stream->nr_output_pins); 323 324 ipu7_isys_buffer_list_queue(bl, IPU_ISYS_BUFFER_LIST_FL_ACTIVE, 325 0); 326 327 ret = ipu7_fw_isys_complex_cmd(stream->isys, 328 stream->stream_handle, buf, 329 msg->dma_addr, sizeof(*buf), 330 send_type); 331 } while (!WARN_ON(ret)); 332 333 return 0; 334 335out_requeue: 336 if (bl && bl->nbufs) 337 ipu7_isys_buffer_list_queue(bl, 338 IPU_ISYS_BUFFER_LIST_FL_INCOMING | 339 (error ? 340 IPU_ISYS_BUFFER_LIST_FL_SET_STATE : 341 0), error ? VB2_BUF_STATE_ERROR : 342 VB2_BUF_STATE_QUEUED); 343 flush_firmware_streamon_fail(stream); 344 345 return ret; 346} 347 348static void buf_queue(struct vb2_buffer *vb) 349{ 350 struct ipu7_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); 351 struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); 352 struct vb2_v4l2_buffer *vvb = to_vb2_v4l2_buffer(vb); 353 struct ipu7_isys_video_buffer *ivb = 354 vb2_buffer_to_ipu7_isys_video_buffer(vvb); 355 struct media_pipeline *media_pipe = 356 media_entity_pipeline(&av->vdev.entity); 357 struct device *dev = &av->isys->adev->auxdev.dev; 358 struct ipu7_isys_stream *stream = av->stream; 359 struct ipu7_isys_buffer *ib = &ivb->ib; 360 struct ipu7_insys_buffset *buf = NULL; 361 struct ipu7_isys_buffer_list bl; 362 struct isys_fw_msgs *msg; 363 unsigned long flags; 364 dma_addr_t dma; 365 int ret; 366 367 dev_dbg(dev, "queue buffer %u for %s\n", vb->index, av->vdev.name); 368 369 dma = ivb->dma_addr; 370 dev_dbg(dev, "iova: iova %pad\n", &dma); 371 372 spin_lock_irqsave(&aq->lock, flags); 373 list_add(&ib->head, &aq->incoming); 374 spin_unlock_irqrestore(&aq->lock, flags); 375 376 if (!media_pipe || !vb->vb2_queue->start_streaming_called) { 377 dev_dbg(dev, "media pipeline is not ready for %s\n", 378 av->vdev.name); 379 return; 380 } 381 382 mutex_lock(&stream->mutex); 383 384 if (stream->nr_streaming != stream->nr_queues) { 385 dev_dbg(dev, "not streaming yet, adding to incoming\n"); 386 goto out; 387 } 388 389 /* 390 * We just put one buffer to the incoming list of this queue 391 * (above). Let's see whether all queues in the pipeline would 392 * have a buffer. 393 */ 394 ret = buffer_list_get(stream, &bl); 395 if (ret < 0) { 396 dev_dbg(dev, "No buffers available\n"); 397 goto out; 398 } 399 400 msg = ipu7_get_fw_msg_buf(stream); 401 if (!msg) { 402 ret = -ENOMEM; 403 goto out; 404 } 405 406 buf = &msg->fw_msg.frame; 407 408 ipu7_isys_buffer_to_fw_frame_buff(buf, stream, &bl); 409 410 ipu7_fw_isys_dump_frame_buff_set(dev, buf, stream->nr_output_pins); 411 412 if (!stream->streaming) { 413 ret = ipu7_isys_stream_start(av, &bl, true); 414 if (ret) 415 dev_err(dev, "stream start failed.\n"); 416 goto out; 417 } 418 419 /* 420 * We must queue the buffers in the buffer list to the 421 * appropriate video buffer queues BEFORE passing them to the 422 * firmware since we could get a buffer event back before we 423 * have queued them ourselves to the active queue. 424 */ 425 ipu7_isys_buffer_list_queue(&bl, IPU_ISYS_BUFFER_LIST_FL_ACTIVE, 0); 426 427 ret = ipu7_fw_isys_complex_cmd(stream->isys, stream->stream_handle, 428 buf, msg->dma_addr, sizeof(*buf), 429 IPU_INSYS_SEND_TYPE_STREAM_CAPTURE); 430 if (ret < 0) 431 dev_err(dev, "send stream capture failed\n"); 432 433out: 434 mutex_unlock(&stream->mutex); 435} 436 437static int ipu7_isys_link_fmt_validate(struct ipu7_isys_queue *aq) 438{ 439 struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); 440 struct device *dev = &av->isys->adev->auxdev.dev; 441 struct media_pad *remote_pad = 442 media_pad_remote_pad_first(av->vdev.entity.pads); 443 struct v4l2_mbus_framefmt format; 444 struct v4l2_subdev *sd; 445 u32 r_stream = 0, code; 446 int ret; 447 448 if (!remote_pad) 449 return -ENOTCONN; 450 451 sd = media_entity_to_v4l2_subdev(remote_pad->entity); 452 453 ret = ipu7_isys_get_stream_pad_fmt(sd, remote_pad->index, r_stream, 454 &format); 455 if (ret) { 456 dev_dbg(dev, "failed to get %s: pad %d, stream:%d format\n", 457 sd->entity.name, remote_pad->index, r_stream); 458 return ret; 459 } 460 461 if (format.width != av->pix_fmt.width || 462 format.height != av->pix_fmt.height) { 463 dev_dbg(dev, "wrong width or height %ux%u (%ux%u expected)\n", 464 av->pix_fmt.width, av->pix_fmt.height, format.width, 465 format.height); 466 return -EINVAL; 467 } 468 469 code = ipu7_isys_get_isys_format(av->pix_fmt.pixelformat)->code; 470 if (format.code != code) { 471 dev_dbg(dev, "wrong mbus code 0x%8.8x (0x%8.8x expected)\n", 472 code, format.code); 473 return -EINVAL; 474 } 475 476 return 0; 477} 478 479static void return_buffers(struct ipu7_isys_queue *aq, 480 enum vb2_buffer_state state) 481{ 482 struct ipu7_isys_buffer *ib; 483 struct vb2_buffer *vb; 484 unsigned long flags; 485 486 spin_lock_irqsave(&aq->lock, flags); 487 /* 488 * Something went wrong (FW crash / HW hang / not all buffers 489 * returned from isys) if there are still buffers queued in active 490 * queue. We have to clean up places a bit. 491 */ 492 while (!list_empty(&aq->active)) { 493 ib = list_last_entry(&aq->active, struct ipu7_isys_buffer, 494 head); 495 vb = ipu7_isys_buffer_to_vb2_buffer(ib); 496 497 list_del(&ib->head); 498 spin_unlock_irqrestore(&aq->lock, flags); 499 500 vb2_buffer_done(vb, state); 501 502 spin_lock_irqsave(&aq->lock, flags); 503 } 504 505 while (!list_empty(&aq->incoming)) { 506 ib = list_last_entry(&aq->incoming, struct ipu7_isys_buffer, 507 head); 508 vb = ipu7_isys_buffer_to_vb2_buffer(ib); 509 list_del(&ib->head); 510 spin_unlock_irqrestore(&aq->lock, flags); 511 512 vb2_buffer_done(vb, state); 513 514 spin_lock_irqsave(&aq->lock, flags); 515 } 516 517 spin_unlock_irqrestore(&aq->lock, flags); 518} 519 520static void ipu7_isys_stream_cleanup(struct ipu7_isys_video *av) 521{ 522 video_device_pipeline_stop(&av->vdev); 523 ipu7_isys_put_stream(av->stream); 524 av->stream = NULL; 525} 526 527static int start_streaming(struct vb2_queue *q, unsigned int count) 528{ 529 struct ipu7_isys_queue *aq = vb2_queue_to_isys_queue(q); 530 struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); 531 struct device *dev = &av->isys->adev->auxdev.dev; 532 const struct ipu7_isys_pixelformat *pfmt = 533 ipu7_isys_get_isys_format(av->pix_fmt.pixelformat); 534 struct ipu7_isys_buffer_list __bl, *bl = NULL; 535 struct ipu7_isys_stream *stream; 536 struct media_entity *source_entity = NULL; 537 int nr_queues, ret; 538 539 dev_dbg(dev, "stream: %s: width %u, height %u, css pixelformat %u\n", 540 av->vdev.name, av->pix_fmt.width, av->pix_fmt.height, 541 pfmt->css_pixelformat); 542 543 ret = ipu7_isys_setup_video(av, &source_entity, &nr_queues); 544 if (ret < 0) { 545 dev_dbg(dev, "failed to setup video\n"); 546 goto out_return_buffers; 547 } 548 549 ret = ipu7_isys_link_fmt_validate(aq); 550 if (ret) { 551 dev_dbg(dev, 552 "%s: link format validation failed (%d)\n", 553 av->vdev.name, ret); 554 goto out_pipeline_stop; 555 } 556 557 stream = av->stream; 558 mutex_lock(&stream->mutex); 559 if (!stream->nr_streaming) { 560 ret = ipu7_isys_video_prepare_stream(av, source_entity, 561 nr_queues); 562 if (ret) { 563 mutex_unlock(&stream->mutex); 564 goto out_pipeline_stop; 565 } 566 } 567 568 stream->nr_streaming++; 569 dev_dbg(dev, "queue %u of %u\n", stream->nr_streaming, 570 stream->nr_queues); 571 572 list_add(&aq->node, &stream->queues); 573 574 if (stream->nr_streaming != stream->nr_queues) 575 goto out; 576 577 bl = &__bl; 578 ret = buffer_list_get(stream, bl); 579 if (ret < 0) { 580 dev_warn(dev, "no buffer available, DRIVER BUG?\n"); 581 goto out; 582 } 583 584 ret = ipu7_isys_fw_open(av->isys); 585 if (ret) 586 goto out_stream_start; 587 588 ipu7_isys_setup_hw(av->isys); 589 590 ret = ipu7_isys_stream_start(av, bl, false); 591 if (ret) 592 goto out_isys_fw_close; 593 594out: 595 mutex_unlock(&stream->mutex); 596 597 return 0; 598 599out_isys_fw_close: 600 ipu7_isys_fw_close(av->isys); 601 602out_stream_start: 603 list_del(&aq->node); 604 stream->nr_streaming--; 605 mutex_unlock(&stream->mutex); 606 607out_pipeline_stop: 608 ipu7_isys_stream_cleanup(av); 609 610out_return_buffers: 611 return_buffers(aq, VB2_BUF_STATE_QUEUED); 612 613 return ret; 614} 615 616static void stop_streaming(struct vb2_queue *q) 617{ 618 struct ipu7_isys_queue *aq = vb2_queue_to_isys_queue(q); 619 struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); 620 struct ipu7_isys_stream *stream = av->stream; 621 622 mutex_lock(&stream->mutex); 623 mutex_lock(&av->isys->stream_mutex); 624 if (stream->nr_streaming == stream->nr_queues && stream->streaming) 625 ipu7_isys_video_set_streaming(av, 0, NULL); 626 mutex_unlock(&av->isys->stream_mutex); 627 628 stream->nr_streaming--; 629 list_del(&aq->node); 630 stream->streaming = 0; 631 632 mutex_unlock(&stream->mutex); 633 634 ipu7_isys_stream_cleanup(av); 635 636 return_buffers(aq, VB2_BUF_STATE_ERROR); 637 638 ipu7_isys_fw_close(av->isys); 639} 640 641static unsigned int 642get_sof_sequence_by_timestamp(struct ipu7_isys_stream *stream, u64 time) 643{ 644 struct ipu7_isys *isys = stream->isys; 645 struct device *dev = &isys->adev->auxdev.dev; 646 unsigned int i; 647 648 /* 649 * The timestamp is invalid as no TSC in some FPGA platform, 650 * so get the sequence from pipeline directly in this case. 651 */ 652 if (time == 0) 653 return atomic_read(&stream->sequence) - 1; 654 655 for (i = 0; i < IPU_ISYS_MAX_PARALLEL_SOF; i++) 656 if (time == stream->seq[i].timestamp) { 657 dev_dbg(dev, "SOF: using seq nr %u for ts %llu\n", 658 stream->seq[i].sequence, time); 659 return stream->seq[i].sequence; 660 } 661 662 dev_dbg(dev, "SOF: looking for %llu\n", time); 663 for (i = 0; i < IPU_ISYS_MAX_PARALLEL_SOF; i++) 664 dev_dbg(dev, "SOF: sequence %u, timestamp value %llu\n", 665 stream->seq[i].sequence, stream->seq[i].timestamp); 666 dev_dbg(dev, "SOF sequence number not found\n"); 667 668 return atomic_read(&stream->sequence) - 1; 669} 670 671static u64 get_sof_ns_delta(struct ipu7_isys_video *av, u64 time) 672{ 673 struct ipu7_bus_device *adev = av->isys->adev; 674 struct ipu7_device *isp = adev->isp; 675 u64 delta, tsc_now; 676 677 ipu_buttress_tsc_read(isp, &tsc_now); 678 if (!tsc_now) 679 return 0; 680 681 delta = tsc_now - time; 682 683 return ipu_buttress_tsc_ticks_to_ns(delta, isp); 684} 685 686static void ipu7_isys_buf_calc_sequence_time(struct ipu7_isys_buffer *ib, 687 u64 time) 688{ 689 struct vb2_buffer *vb = ipu7_isys_buffer_to_vb2_buffer(ib); 690 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 691 struct ipu7_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); 692 struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); 693 struct device *dev = &av->isys->adev->auxdev.dev; 694 struct ipu7_isys_stream *stream = av->stream; 695 u64 ns; 696 u32 sequence; 697 698 ns = ktime_get_ns() - get_sof_ns_delta(av, time); 699 sequence = get_sof_sequence_by_timestamp(stream, time); 700 701 vbuf->vb2_buf.timestamp = ns; 702 vbuf->sequence = sequence; 703 704 dev_dbg(dev, "buf: %s: buffer done, CPU-timestamp:%lld, sequence:%d\n", 705 av->vdev.name, ktime_get_ns(), sequence); 706 dev_dbg(dev, "index:%d, vbuf timestamp:%lld\n", vb->index, 707 vbuf->vb2_buf.timestamp); 708} 709 710static void ipu7_isys_queue_buf_done(struct ipu7_isys_buffer *ib) 711{ 712 struct vb2_buffer *vb = ipu7_isys_buffer_to_vb2_buffer(ib); 713 714 if (atomic_read(&ib->str2mmio_flag)) { 715 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); 716 /* 717 * Operation on buffer is ended with error and will be reported 718 * to the userspace when it is de-queued 719 */ 720 atomic_set(&ib->str2mmio_flag, 0); 721 } else { 722 vb2_buffer_done(vb, VB2_BUF_STATE_DONE); 723 } 724} 725 726void ipu7_isys_queue_buf_ready(struct ipu7_isys_stream *stream, 727 struct ipu7_insys_resp *info) 728{ 729 struct ipu7_isys_queue *aq = stream->output_pins[info->pin_id].aq; 730 u64 time = ((u64)info->timestamp[1] << 32 | info->timestamp[0]); 731 struct ipu7_isys *isys = stream->isys; 732 struct device *dev = &isys->adev->auxdev.dev; 733 struct ipu7_isys_buffer *ib; 734 struct vb2_buffer *vb; 735 unsigned long flags; 736 bool first = true; 737 struct vb2_v4l2_buffer *buf; 738 739 dev_dbg(dev, "buffer: %s: received buffer %8.8x %d\n", 740 ipu7_isys_queue_to_video(aq)->vdev.name, info->pin.addr, 741 info->frame_id); 742 743 spin_lock_irqsave(&aq->lock, flags); 744 if (list_empty(&aq->active)) { 745 spin_unlock_irqrestore(&aq->lock, flags); 746 dev_err(dev, "active queue empty\n"); 747 return; 748 } 749 750 list_for_each_entry_reverse(ib, &aq->active, head) { 751 struct ipu7_isys_video_buffer *ivb; 752 struct vb2_v4l2_buffer *vvb; 753 dma_addr_t addr; 754 755 vb = ipu7_isys_buffer_to_vb2_buffer(ib); 756 vvb = to_vb2_v4l2_buffer(vb); 757 ivb = vb2_buffer_to_ipu7_isys_video_buffer(vvb); 758 addr = ivb->dma_addr; 759 760 if (info->pin.addr != addr) { 761 if (first) 762 dev_err(dev, "Unexpected buffer address %pad\n", 763 &addr); 764 765 first = false; 766 continue; 767 } 768 769 dev_dbg(dev, "buffer: found buffer %pad\n", &addr); 770 771 buf = to_vb2_v4l2_buffer(vb); 772 buf->field = V4L2_FIELD_NONE; 773 774 list_del(&ib->head); 775 spin_unlock_irqrestore(&aq->lock, flags); 776 777 ipu7_isys_buf_calc_sequence_time(ib, time); 778 779 ipu7_isys_queue_buf_done(ib); 780 781 return; 782 } 783 784 dev_err(dev, "Failed to find a matching video buffer\n"); 785 786 spin_unlock_irqrestore(&aq->lock, flags); 787} 788 789static const struct vb2_ops ipu7_isys_queue_ops = { 790 .queue_setup = ipu7_isys_queue_setup, 791 .buf_init = ipu7_isys_buf_init, 792 .buf_prepare = ipu7_isys_buf_prepare, 793 .buf_cleanup = ipu7_isys_buf_cleanup, 794 .start_streaming = start_streaming, 795 .stop_streaming = stop_streaming, 796 .buf_queue = buf_queue, 797}; 798 799int ipu7_isys_queue_init(struct ipu7_isys_queue *aq) 800{ 801 struct ipu7_isys *isys = ipu7_isys_queue_to_video(aq)->isys; 802 struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); 803 struct ipu7_bus_device *adev = isys->adev; 804 int ret; 805 806 if (!aq->vbq.io_modes) 807 aq->vbq.io_modes = VB2_MMAP | VB2_DMABUF; 808 809 aq->vbq.drv_priv = isys; 810 aq->vbq.ops = &ipu7_isys_queue_ops; 811 aq->vbq.lock = &av->mutex; 812 aq->vbq.mem_ops = &vb2_dma_sg_memops; 813 aq->vbq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 814 aq->vbq.min_queued_buffers = 1; 815 aq->vbq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 816 817 ret = vb2_queue_init(&aq->vbq); 818 if (ret) 819 return ret; 820 821 aq->dev = &adev->auxdev.dev; 822 aq->vbq.dev = &adev->isp->pdev->dev; 823 spin_lock_init(&aq->lock); 824 INIT_LIST_HEAD(&aq->active); 825 INIT_LIST_HEAD(&aq->incoming); 826 827 return 0; 828}
~/
Read-only file preview.