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