Lines Matching +full:min +full:- +full:pix +full:- +full:alignment
1 // SPDX-License-Identifier: GPL-2.0+
3 * Renesas R-Car Fine Display Processor
11 * m2m-deinterlace, and vsp1 drivers.
16 #include <linux/dma-mapping.h>
26 #include <media/rcar-fcp.h>
27 #include <media/v4l2-ctrls.h>
28 #include <media/v4l2-device.h>
29 #include <media/v4l2-event.h>
30 #include <media/v4l2-ioctl.h>
31 #include <media/v4l2-mem2mem.h>
32 #include <media/videobuf2-dma-contig.h>
58 v4l2_dbg(1, debug, &fdp1->v4l2_dev, "%s: " fmt, __func__, ## arg)
64 /* FDP1 start register - Imm */
68 /* Sync generator register - Imm */
72 /* Register set end register - Imm */
76 /* Channel activation register - Vupdt */
85 /* Operation Mode Register - Vupdt */
100 /* Control status register (V-update-status) */
256 /* R-Car Gen2 HW manual says zero, but actual value matches R-Car H3 ES1.x */
271 * struct fdp1_fmt - The FDP1 internal format data
277 * @fmt: 7-bit format code for the fdp1 hardware
408 return fmt->fmt <= 0x1b; /* Last RGB code */ in fdp1_fmt_is_rgb()
472 /* Per-queue, driver-specific private data */
489 if (fmt->fourcc == pixelformat) in fdp1_find_format()
608 * for supported formats. 0-255 only
627 * For de-interlacing we need to track our previous buffer
642 return &ctx->out_q; in get_q_data()
644 return &ctx->cap_q; in get_q_data()
658 spin_lock_irqsave(&fdp1->irqlock, flags); in list_remove_job()
661 list_del(&job->list); in list_remove_job()
662 spin_unlock_irqrestore(&fdp1->irqlock, flags); in list_remove_job()
670 * Returns: void - always succeeds
678 spin_lock_irqsave(&fdp1->irqlock, flags); in list_add_job()
679 list_add_tail(&job->list, list); in list_add_job()
680 spin_unlock_irqrestore(&fdp1->irqlock, flags); in list_add_job()
685 return list_remove_job(fdp1, &fdp1->free_job_list); in fdp1_job_alloc()
693 list_add_job(fdp1, &fdp1->free_job_list, job); in fdp1_job_free()
698 list_add_job(fdp1, &fdp1->queued_job_list, job); in queue_job()
703 return list_remove_job(fdp1, &fdp1->queued_job_list); in get_queued_job()
708 list_add_job(fdp1, &fdp1->hw_job_list, job); in queue_hw_job()
713 return list_remove_job(fdp1, &fdp1->hw_job_list); in get_hw_queued_job()
722 /* job->previous may be on the first field */ in fdp1_field_complete()
726 if (fbuf->last_field) in fdp1_field_complete()
727 v4l2_m2m_buf_done(fbuf->vb, VB2_BUF_STATE_DONE); in fdp1_field_complete()
735 spin_lock_irqsave(&ctx->fdp1->irqlock, flags); in fdp1_queue_field()
736 list_add_tail(&fbuf->list, &ctx->fields_queue); in fdp1_queue_field()
737 spin_unlock_irqrestore(&ctx->fdp1->irqlock, flags); in fdp1_queue_field()
739 ctx->buffers_queued++; in fdp1_queue_field()
747 ctx->buffers_queued--; in fdp1_dequeue_field()
749 spin_lock_irqsave(&ctx->fdp1->irqlock, flags); in fdp1_dequeue_field()
750 fbuf = list_first_entry_or_null(&ctx->fields_queue, in fdp1_dequeue_field()
753 list_del(&fbuf->list); in fdp1_dequeue_field()
754 spin_unlock_irqrestore(&ctx->fdp1->irqlock, flags); in fdp1_dequeue_field()
760 * Return the next field in the queue - or NULL,
768 spin_lock_irqsave(&ctx->fdp1->irqlock, flags); in fdp1_peek_queued_field()
769 fbuf = list_first_entry_or_null(&ctx->fields_queue, in fdp1_peek_queued_field()
771 spin_unlock_irqrestore(&ctx->fdp1->irqlock, flags); in fdp1_peek_queued_field()
778 u32 value = ioread32(fdp1->regs + reg); in fdp1_read()
791 iowrite32(val, fdp1->regs + reg); in fdp1_write()
797 struct fdp1_dev *fdp1 = ctx->fdp1; in fdp1_set_ipc_dli()
814 struct fdp1_dev *fdp1 = ctx->fdp1; in fdp1_set_ipc_sensor()
815 struct fdp1_q_data *src_q_data = &ctx->out_q; in fdp1_set_ipc_sensor()
817 unsigned int hsize = src_q_data->format.width; in fdp1_set_ipc_sensor()
818 unsigned int vsize = src_q_data->format.height; in fdp1_set_ipc_sensor()
828 fdp1_write(fdp1, ((hsize - 1) << FD1_IPC_SENSOR_CTL2_X_SHIFT) | in fdp1_set_ipc_sensor()
829 ((vsize - 1) << FD1_IPC_SENSOR_CTL2_Y_SHIFT), in fdp1_set_ipc_sensor()
840 * FDP1 uses constant data for de-interlacing processing,
853 len = min(len, 256u); in fdp1_write_lut()
859 pad = lut[i-1]; in fdp1_write_lut()
882 struct fdp1_dev *fdp1 = ctx->fdp1; in fdp1_configure_rpf()
888 struct fdp1_q_data *q_data = &ctx->out_q; in fdp1_configure_rpf()
891 picture_size = (q_data->format.width << FD1_RPF_SIZE_H_SHIFT) in fdp1_configure_rpf()
892 | (q_data->vsize << FD1_RPF_SIZE_V_SHIFT); in fdp1_configure_rpf()
895 pstride = q_data->stride_y << FD1_RPF_PSTRIDE_Y_SHIFT; in fdp1_configure_rpf()
896 if (q_data->format.num_planes > 1) in fdp1_configure_rpf()
897 pstride |= q_data->stride_c << FD1_RPF_PSTRIDE_C_SHIFT; in fdp1_configure_rpf()
900 format = q_data->fmt->fmt; in fdp1_configure_rpf()
901 if (q_data->fmt->swap_yc) in fdp1_configure_rpf()
904 if (q_data->fmt->swap_uv) in fdp1_configure_rpf()
907 if (job->active->field == V4L2_FIELD_BOTTOM) { in fdp1_configure_rpf()
909 smsk_addr = ctx->smsk_addr[0]; in fdp1_configure_rpf()
911 smsk_addr = ctx->smsk_addr[1]; in fdp1_configure_rpf()
914 /* Deint mode is non-zero when deinterlacing */ in fdp1_configure_rpf()
915 if (ctx->deint_mode) in fdp1_configure_rpf()
919 fdp1_write(fdp1, q_data->fmt->swap, FD1_RPF_SWAP); in fdp1_configure_rpf()
925 if (job->previous) in fdp1_configure_rpf()
926 fdp1_write(fdp1, job->previous->addrs[0], FD1_RPF0_ADDR_Y); in fdp1_configure_rpf()
929 fdp1_write(fdp1, job->active->addrs[0], FD1_RPF1_ADDR_Y); in fdp1_configure_rpf()
930 fdp1_write(fdp1, job->active->addrs[1], FD1_RPF1_ADDR_C0); in fdp1_configure_rpf()
931 fdp1_write(fdp1, job->active->addrs[2], FD1_RPF1_ADDR_C1); in fdp1_configure_rpf()
934 if (job->next) in fdp1_configure_rpf()
935 fdp1_write(fdp1, job->next->addrs[0], FD1_RPF2_ADDR_Y); in fdp1_configure_rpf()
941 struct fdp1_dev *fdp1 = ctx->fdp1; in fdp1_configure_wpf()
942 struct fdp1_q_data *src_q_data = &ctx->out_q; in fdp1_configure_wpf()
943 struct fdp1_q_data *q_data = &ctx->cap_q; in fdp1_configure_wpf()
949 pstride = q_data->format.plane_fmt[0].bytesperline in fdp1_configure_wpf()
952 if (q_data->format.num_planes > 1) in fdp1_configure_wpf()
953 pstride |= q_data->format.plane_fmt[1].bytesperline in fdp1_configure_wpf()
956 format = q_data->fmt->fmt; /* Output Format Code */ in fdp1_configure_wpf()
958 if (q_data->fmt->swap_yc) in fdp1_configure_wpf()
961 if (q_data->fmt->swap_uv) in fdp1_configure_wpf()
964 if (fdp1_fmt_is_rgb(q_data->fmt)) { in fdp1_configure_wpf()
969 if (src_q_data->format.ycbcr_enc == V4L2_YCBCR_ENC_709) in fdp1_configure_wpf()
971 else if (src_q_data->format.quantization == in fdp1_configure_wpf()
979 format |= ctx->alpha << FD1_WPF_FORMAT_PDV_SHIFT; in fdp1_configure_wpf()
986 swap = q_data->fmt->swap << FD1_WPF_SWAP_OSWAP_SHIFT; in fdp1_configure_wpf()
987 swap |= src_q_data->fmt->swap << FD1_WPF_SWAP_SSWAP_SHIFT; in fdp1_configure_wpf()
994 fdp1_write(fdp1, job->dst->addrs[0], FD1_WPF_ADDR_Y); in fdp1_configure_wpf()
995 fdp1_write(fdp1, job->dst->addrs[1], FD1_WPF_ADDR_C0); in fdp1_configure_wpf()
996 fdp1_write(fdp1, job->dst->addrs[2], FD1_WPF_ADDR_C1); in fdp1_configure_wpf()
1002 struct fdp1_dev *fdp1 = ctx->fdp1; in fdp1_configure_deint_mode()
1007 /* De-interlacing Mode */ in fdp1_configure_deint_mode()
1008 switch (ctx->deint_mode) { in fdp1_configure_deint_mode()
1017 if (ctx->sequence == 0 || ctx->aborting) in fdp1_configure_deint_mode()
1022 if (ctx->sequence > 1) { in fdp1_configure_deint_mode()
1027 if (ctx->sequence > 2) in fdp1_configure_deint_mode()
1035 if (!(ctx->sequence == 0 || ctx->aborting)) in fdp1_configure_deint_mode()
1061 * fdp1_device_process() - Run the hardware
1069 struct fdp1_dev *fdp1 = ctx->fdp1; in fdp1_device_process()
1073 spin_lock_irqsave(&fdp1->device_process_lock, flags); in fdp1_device_process()
1082 spin_unlock_irqrestore(&fdp1->device_process_lock, flags); in fdp1_device_process()
1124 spin_unlock_irqrestore(&fdp1->device_process_lock, flags); in fdp1_device_process()
1134 * job_ready() - check whether an instance is ready to be scheduled to run
1139 struct fdp1_q_data *src_q_data = &ctx->out_q; in fdp1_m2m_job_ready()
1143 dprintk(ctx->fdp1, "+ Src: %d : Dst: %d\n", in fdp1_m2m_job_ready()
1144 v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx), in fdp1_m2m_job_ready()
1145 v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)); in fdp1_m2m_job_ready()
1148 if (V4L2_FIELD_HAS_BOTH(src_q_data->format.field)) in fdp1_m2m_job_ready()
1151 if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < srcbufs in fdp1_m2m_job_ready()
1152 || v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < dstbufs) { in fdp1_m2m_job_ready()
1153 dprintk(ctx->fdp1, "Not enough buffers available\n"); in fdp1_m2m_job_ready()
1164 dprintk(ctx->fdp1, "+\n"); in fdp1_m2m_job_abort()
1167 ctx->aborting = 1; in fdp1_m2m_job_abort()
1170 fdp1_write(ctx->fdp1, 0, FD1_CTL_SGCMD); in fdp1_m2m_job_abort()
1171 fdp1_write(ctx->fdp1, FD1_CTL_SRESET_SRST, FD1_CTL_SRESET); in fdp1_m2m_job_abort()
1184 struct fdp1_dev *fdp1 = ctx->fdp1; in fdp1_prepare_job()
1190 if (FDP1_DEINT_MODE_USES_NEXT(ctx->deint_mode)) in fdp1_prepare_job()
1193 if (ctx->buffers_queued < buffers_required) in fdp1_prepare_job()
1202 job->active = fdp1_dequeue_field(ctx); in fdp1_prepare_job()
1203 if (!job->active) { in fdp1_prepare_job()
1211 dprintk(fdp1, "+ Buffer en-route...\n"); in fdp1_prepare_job()
1216 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); in fdp1_prepare_job()
1218 job->dst = &fbuf->fields[0]; in fdp1_prepare_job()
1220 job->active->vb->sequence = ctx->sequence; in fdp1_prepare_job()
1221 job->dst->vb->sequence = ctx->sequence; in fdp1_prepare_job()
1222 ctx->sequence++; in fdp1_prepare_job()
1224 if (FDP1_DEINT_MODE_USES_PREV(ctx->deint_mode)) { in fdp1_prepare_job()
1225 job->previous = ctx->previous; in fdp1_prepare_job()
1228 ctx->previous = job->active; in fdp1_prepare_job()
1231 if (FDP1_DEINT_MODE_USES_NEXT(ctx->deint_mode)) { in fdp1_prepare_job()
1233 job->next = fdp1_peek_queued_field(ctx); in fdp1_prepare_job()
1236 /* Transfer timestamps and flags from src->dst */ in fdp1_prepare_job()
1238 job->dst->vb->vb2_buf.timestamp = job->active->vb->vb2_buf.timestamp; in fdp1_prepare_job()
1240 job->dst->vb->flags = job->active->vb->flags & in fdp1_prepare_job()
1243 /* Ideally, the frame-end function will just 'check' to see in fdp1_prepare_job()
1246 ctx->translen++; in fdp1_prepare_job()
1251 dprintk(fdp1, "Job Queued translen = %d\n", ctx->translen); in fdp1_prepare_job()
1256 /* fdp1_m2m_device_run() - prepares and starts the device for an M2M task
1265 struct fdp1_dev *fdp1 = ctx->fdp1; in fdp1_m2m_device_run()
1272 ctx->translen = 0; in fdp1_m2m_device_run()
1275 src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); in fdp1_m2m_device_run()
1278 for (i = 0; i < buf->num_fields; i++) { in fdp1_m2m_device_run()
1279 struct fdp1_field_buffer *fbuf = &buf->fields[i]; in fdp1_m2m_device_run()
1283 i, fbuf->last_field); in fdp1_m2m_device_run()
1290 if (ctx->translen == 0) { in fdp1_m2m_device_run()
1292 v4l2_m2m_job_finish(fdp1->m2m_dev, ctx->fh.m2m_ctx); in fdp1_m2m_device_run()
1314 ctx = v4l2_m2m_get_curr_priv(fdp1->m2m_dev); in device_frame_end()
1317 v4l2_err(&fdp1->v4l2_dev, in device_frame_end()
1322 ctx->num_processed++; in device_frame_end()
1328 if (FDP1_DEINT_MODE_USES_PREV(ctx->deint_mode)) in device_frame_end()
1329 fdp1_field_complete(ctx, job->previous); in device_frame_end()
1331 fdp1_field_complete(ctx, job->active); in device_frame_end()
1333 spin_lock_irqsave(&fdp1->irqlock, flags); in device_frame_end()
1334 v4l2_m2m_buf_done(job->dst->vb, state); in device_frame_end()
1335 job->dst = NULL; in device_frame_end()
1336 spin_unlock_irqrestore(&fdp1->irqlock, flags); in device_frame_end()
1341 dprintk(fdp1, "curr_ctx->num_processed %d curr_ctx->translen %d\n", in device_frame_end()
1342 ctx->num_processed, ctx->translen); in device_frame_end()
1344 if (ctx->num_processed == ctx->translen || in device_frame_end()
1345 ctx->aborting) { in device_frame_end()
1346 dprintk(ctx->fdp1, "Finishing transaction\n"); in device_frame_end()
1347 ctx->num_processed = 0; in device_frame_end()
1348 v4l2_m2m_job_finish(fdp1->m2m_dev, ctx->fh.m2m_ctx); in device_frame_end()
1364 strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)); in fdp1_vidioc_querycap()
1365 strscpy(cap->card, DRIVER_NAME, sizeof(cap->card)); in fdp1_vidioc_querycap()
1366 snprintf(cap->bus_info, sizeof(cap->bus_info), in fdp1_vidioc_querycap()
1379 if (num == f->index) in fdp1_enum_fmt()
1387 return -EINVAL; in fdp1_enum_fmt()
1390 f->pixelformat = fdp1_formats[i].fourcc; in fdp1_enum_fmt()
1412 if (!v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type)) in fdp1_g_fmt()
1413 return -EINVAL; in fdp1_g_fmt()
1415 q_data = get_q_data(ctx, f->type); in fdp1_g_fmt()
1416 f->fmt.pix_mp = q_data->format; in fdp1_g_fmt()
1421 static void fdp1_compute_stride(struct v4l2_pix_format_mplane *pix, in fdp1_compute_stride() argument
1427 for (i = 0; i < min_t(unsigned int, fmt->num_planes, 2U); ++i) { in fdp1_compute_stride()
1428 unsigned int hsub = i > 0 ? fmt->hsub : 1; in fdp1_compute_stride()
1429 unsigned int vsub = i > 0 ? fmt->vsub : 1; in fdp1_compute_stride()
1430 /* From VSP : TODO: Confirm alignment limits for FDP1 */ in fdp1_compute_stride()
1434 bpl = clamp_t(unsigned int, pix->plane_fmt[i].bytesperline, in fdp1_compute_stride()
1435 pix->width / hsub * fmt->bpp[i] / 8, in fdp1_compute_stride()
1438 pix->plane_fmt[i].bytesperline = round_up(bpl, align); in fdp1_compute_stride()
1439 pix->plane_fmt[i].sizeimage = pix->plane_fmt[i].bytesperline in fdp1_compute_stride()
1440 * pix->height / vsub; in fdp1_compute_stride()
1444 if (fmt->num_planes == 3) { in fdp1_compute_stride()
1446 pix->plane_fmt[2].bytesperline = pix->plane_fmt[1].bytesperline; in fdp1_compute_stride()
1447 pix->plane_fmt[2].sizeimage = pix->plane_fmt[1].sizeimage; in fdp1_compute_stride()
1454 struct v4l2_pix_format_mplane *pix) in fdp1_try_fmt_output() argument
1461 fmt = fdp1_find_format(pix->pixelformat); in fdp1_try_fmt_output()
1462 if (!fmt || !(fmt->types & FDP1_OUTPUT)) in fdp1_try_fmt_output()
1468 pix->pixelformat = fmt->fourcc; in fdp1_try_fmt_output()
1469 pix->num_planes = fmt->num_planes; in fdp1_try_fmt_output()
1475 if (pix->field != V4L2_FIELD_NONE && in fdp1_try_fmt_output()
1476 pix->field != V4L2_FIELD_ALTERNATE && in fdp1_try_fmt_output()
1477 !V4L2_FIELD_HAS_BOTH(pix->field)) in fdp1_try_fmt_output()
1478 pix->field = V4L2_FIELD_INTERLACED; in fdp1_try_fmt_output()
1487 if (pix->colorspace == V4L2_COLORSPACE_DEFAULT) in fdp1_try_fmt_output()
1488 pix->colorspace = V4L2_COLORSPACE_SMPTE170M; in fdp1_try_fmt_output()
1496 width = round_down(pix->width, fmt->hsub); in fdp1_try_fmt_output()
1497 pix->width = clamp(width, FDP1_MIN_W, FDP1_MAX_W); in fdp1_try_fmt_output()
1499 height = round_down(pix->height, fmt->vsub); in fdp1_try_fmt_output()
1500 if (pix->field == V4L2_FIELD_ALTERNATE) in fdp1_try_fmt_output()
1501 pix->height = clamp(height, FDP1_MIN_H / 2, FDP1_MAX_H / 2); in fdp1_try_fmt_output()
1503 pix->height = clamp(height, FDP1_MIN_H, FDP1_MAX_H); in fdp1_try_fmt_output()
1505 fdp1_compute_stride(pix, fmt); in fdp1_try_fmt_output()
1510 struct v4l2_pix_format_mplane *pix) in fdp1_try_fmt_capture() argument
1512 struct fdp1_q_data *src_data = &ctx->out_q; in fdp1_try_fmt_capture()
1528 colorspace = src_data->format.colorspace; in fdp1_try_fmt_capture()
1530 ycbcr_enc = src_data->format.ycbcr_enc; in fdp1_try_fmt_capture()
1534 quantization = src_data->format.quantization; in fdp1_try_fmt_capture()
1543 fmt = fdp1_find_format(pix->pixelformat); in fdp1_try_fmt_capture()
1550 pix->pixelformat = fmt->fourcc; in fdp1_try_fmt_capture()
1551 pix->num_planes = fmt->num_planes; in fdp1_try_fmt_capture()
1552 pix->field = V4L2_FIELD_NONE; in fdp1_try_fmt_capture()
1560 pix->colorspace = src_data->format.colorspace; in fdp1_try_fmt_capture()
1561 pix->xfer_func = src_data->format.xfer_func; in fdp1_try_fmt_capture()
1564 pix->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in fdp1_try_fmt_capture()
1565 pix->quantization = V4L2_QUANTIZATION_DEFAULT; in fdp1_try_fmt_capture()
1567 pix->ycbcr_enc = src_data->format.ycbcr_enc; in fdp1_try_fmt_capture()
1568 pix->quantization = src_data->format.quantization; in fdp1_try_fmt_capture()
1576 pix->width = src_data->format.width; in fdp1_try_fmt_capture()
1577 if (src_data->format.field == V4L2_FIELD_ALTERNATE) in fdp1_try_fmt_capture()
1578 pix->height = 2 * src_data->format.height; in fdp1_try_fmt_capture()
1580 pix->height = src_data->format.height; in fdp1_try_fmt_capture()
1582 fdp1_compute_stride(pix, fmt); in fdp1_try_fmt_capture()
1589 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) in fdp1_try_fmt()
1590 fdp1_try_fmt_output(ctx, NULL, &f->fmt.pix_mp); in fdp1_try_fmt()
1592 fdp1_try_fmt_capture(ctx, NULL, &f->fmt.pix_mp); in fdp1_try_fmt()
1594 dprintk(ctx->fdp1, "Try %s format: %4.4s (0x%08x) %ux%u field %u\n", in fdp1_try_fmt()
1595 V4L2_TYPE_IS_OUTPUT(f->type) ? "output" : "capture", in fdp1_try_fmt()
1596 (char *)&f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.pixelformat, in fdp1_try_fmt()
1597 f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.field); in fdp1_try_fmt()
1603 struct v4l2_pix_format_mplane *pix, in fdp1_set_format() argument
1610 fdp1_try_fmt_output(ctx, &fmtinfo, pix); in fdp1_set_format()
1612 fdp1_try_fmt_capture(ctx, &fmtinfo, pix); in fdp1_set_format()
1614 q_data->fmt = fmtinfo; in fdp1_set_format()
1615 q_data->format = *pix; in fdp1_set_format()
1617 q_data->vsize = pix->height; in fdp1_set_format()
1618 if (pix->field != V4L2_FIELD_NONE) in fdp1_set_format()
1619 q_data->vsize /= 2; in fdp1_set_format()
1621 q_data->stride_y = pix->plane_fmt[0].bytesperline; in fdp1_set_format()
1622 q_data->stride_c = pix->plane_fmt[1].bytesperline; in fdp1_set_format()
1625 if (pix->field == V4L2_FIELD_INTERLACED || in fdp1_set_format()
1626 pix->field == V4L2_FIELD_INTERLACED_TB || in fdp1_set_format()
1627 pix->field == V4L2_FIELD_INTERLACED_BT) { in fdp1_set_format()
1628 q_data->stride_y *= 2; in fdp1_set_format()
1629 q_data->stride_c *= 2; in fdp1_set_format()
1634 struct fdp1_q_data *dst_data = &ctx->cap_q; in fdp1_set_format()
1637 * Copy the format, clear the per-plane bytes per line and image in fdp1_set_format()
1640 dst_data->format = q_data->format; in fdp1_set_format()
1641 memset(dst_data->format.plane_fmt, 0, in fdp1_set_format()
1642 sizeof(dst_data->format.plane_fmt)); in fdp1_set_format()
1644 dst_data->format.field = V4L2_FIELD_NONE; in fdp1_set_format()
1645 if (pix->field == V4L2_FIELD_ALTERNATE) in fdp1_set_format()
1646 dst_data->format.height *= 2; in fdp1_set_format()
1648 fdp1_try_fmt_capture(ctx, &dst_data->fmt, &dst_data->format); in fdp1_set_format()
1650 dst_data->vsize = dst_data->format.height; in fdp1_set_format()
1651 dst_data->stride_y = dst_data->format.plane_fmt[0].bytesperline; in fdp1_set_format()
1652 dst_data->stride_c = dst_data->format.plane_fmt[1].bytesperline; in fdp1_set_format()
1659 struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; in fdp1_s_fmt()
1660 struct vb2_queue *vq = v4l2_m2m_get_vq(m2m_ctx, f->type); in fdp1_s_fmt()
1663 v4l2_err(&ctx->fdp1->v4l2_dev, "%s queue busy\n", __func__); in fdp1_s_fmt()
1664 return -EBUSY; in fdp1_s_fmt()
1667 fdp1_set_format(ctx, &f->fmt.pix_mp, f->type); in fdp1_s_fmt()
1669 dprintk(ctx->fdp1, "Set %s format: %4.4s (0x%08x) %ux%u field %u\n", in fdp1_s_fmt()
1670 V4L2_TYPE_IS_OUTPUT(f->type) ? "output" : "capture", in fdp1_s_fmt()
1671 (char *)&f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.pixelformat, in fdp1_s_fmt()
1672 f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.field); in fdp1_s_fmt()
1680 container_of(ctrl->handler, struct fdp1_ctx, hdl); in fdp1_g_ctrl()
1681 struct fdp1_q_data *src_q_data = &ctx->out_q; in fdp1_g_ctrl()
1683 switch (ctrl->id) { in fdp1_g_ctrl()
1685 if (V4L2_FIELD_HAS_BOTH(src_q_data->format.field)) in fdp1_g_ctrl()
1686 ctrl->val = 2; in fdp1_g_ctrl()
1688 ctrl->val = 1; in fdp1_g_ctrl()
1698 container_of(ctrl->handler, struct fdp1_ctx, hdl); in fdp1_s_ctrl()
1700 switch (ctrl->id) { in fdp1_s_ctrl()
1702 ctx->alpha = ctrl->val; in fdp1_s_ctrl()
1706 ctx->deint_mode = ctrl->val; in fdp1_s_ctrl()
1768 q_data = get_q_data(ctx, vq->type); in fdp1_queue_setup()
1772 return -EINVAL; in fdp1_queue_setup()
1777 *nplanes = q_data->format.num_planes; in fdp1_queue_setup()
1780 sizes[i] = q_data->format.plane_fmt[i].sizeimage; in fdp1_queue_setup()
1790 struct fdp1_field_buffer *fbuf = &buf->fields[field_num]; in fdp1_buf_prepare_field()
1794 num_fields = V4L2_FIELD_HAS_BOTH(vbuf->field) ? 2 : 1; in fdp1_buf_prepare_field()
1796 fbuf->vb = vbuf; in fdp1_buf_prepare_field()
1797 fbuf->last_field = (field_num + 1) == num_fields; in fdp1_buf_prepare_field()
1799 for (i = 0; i < vbuf->vb2_buf.num_planes; ++i) in fdp1_buf_prepare_field()
1800 fbuf->addrs[i] = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, i); in fdp1_buf_prepare_field()
1802 switch (vbuf->field) { in fdp1_buf_prepare_field()
1805 * Interlaced means bottom-top for 60Hz TV standards (NTSC) and in fdp1_buf_prepare_field()
1806 * top-bottom for 50Hz. As TV standards are not applicable to in fdp1_buf_prepare_field()
1807 * the mem-to-mem API, use the height as a heuristic. in fdp1_buf_prepare_field()
1809 fbuf->field = (q_data->format.height < 576) == field_num in fdp1_buf_prepare_field()
1814 fbuf->field = field_num ? V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP; in fdp1_buf_prepare_field()
1818 fbuf->field = field_num ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM; in fdp1_buf_prepare_field()
1821 fbuf->field = vbuf->field; in fdp1_buf_prepare_field()
1830 switch (vbuf->field) { in fdp1_buf_prepare_field()
1834 for (i = 0; i < vbuf->vb2_buf.num_planes; i++) in fdp1_buf_prepare_field()
1835 fbuf->addrs[i] += in fdp1_buf_prepare_field()
1836 (i == 0 ? q_data->stride_y : q_data->stride_c); in fdp1_buf_prepare_field()
1840 for (i = 0; i < vbuf->vb2_buf.num_planes; i++) in fdp1_buf_prepare_field()
1841 fbuf->addrs[i] += q_data->vsize * in fdp1_buf_prepare_field()
1842 (i == 0 ? q_data->stride_y : q_data->stride_c); in fdp1_buf_prepare_field()
1849 struct fdp1_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); in fdp1_buf_prepare()
1850 struct fdp1_q_data *q_data = get_q_data(ctx, vb->vb2_queue->type); in fdp1_buf_prepare()
1855 if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { in fdp1_buf_prepare()
1859 switch (q_data->format.field) { in fdp1_buf_prepare()
1861 if (vbuf->field != V4L2_FIELD_NONE) in fdp1_buf_prepare()
1866 if (vbuf->field != V4L2_FIELD_TOP && in fdp1_buf_prepare()
1867 vbuf->field != V4L2_FIELD_BOTTOM) in fdp1_buf_prepare()
1876 if (vbuf->field != q_data->format.field) in fdp1_buf_prepare()
1882 dprintk(ctx->fdp1, in fdp1_buf_prepare()
1884 vbuf->field, q_data->format.field); in fdp1_buf_prepare()
1885 return -EINVAL; in fdp1_buf_prepare()
1888 vbuf->field = V4L2_FIELD_NONE; in fdp1_buf_prepare()
1892 for (i = 0; i < q_data->format.num_planes; i++) { in fdp1_buf_prepare()
1893 unsigned long size = q_data->format.plane_fmt[i].sizeimage; in fdp1_buf_prepare()
1896 dprintk(ctx->fdp1, in fdp1_buf_prepare()
1898 i, q_data->format.num_planes, in fdp1_buf_prepare()
1900 return -EINVAL; in fdp1_buf_prepare()
1907 buf->num_fields = V4L2_FIELD_HAS_BOTH(vbuf->field) ? 2 : 1; in fdp1_buf_prepare()
1908 for (i = 0; i < buf->num_fields; ++i) in fdp1_buf_prepare()
1917 struct fdp1_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); in fdp1_buf_queue()
1919 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); in fdp1_buf_queue()
1925 struct fdp1_q_data *q_data = get_q_data(ctx, q->type); in fdp1_start_streaming()
1927 if (V4L2_TYPE_IS_OUTPUT(q->type)) { in fdp1_start_streaming()
1931 * Otherwise, lock in the requested de-interlace mode. in fdp1_start_streaming()
1933 if (q_data->format.field == V4L2_FIELD_NONE) in fdp1_start_streaming()
1934 ctx->deint_mode = FDP1_PROGRESSIVE; in fdp1_start_streaming()
1936 if (ctx->deint_mode == FDP1_ADAPT2D3D) { in fdp1_start_streaming()
1941 stride = round_up(q_data->format.width, 8); in fdp1_start_streaming()
1943 ctx->smsk_size = bpp * stride * q_data->vsize; in fdp1_start_streaming()
1945 ctx->smsk_cpu = dma_alloc_coherent(ctx->fdp1->dev, in fdp1_start_streaming()
1946 ctx->smsk_size, &smsk_base, GFP_KERNEL); in fdp1_start_streaming()
1948 if (ctx->smsk_cpu == NULL) { in fdp1_start_streaming()
1949 dprintk(ctx->fdp1, "Failed to alloc smsk\n"); in fdp1_start_streaming()
1950 return -ENOMEM; in fdp1_start_streaming()
1953 ctx->smsk_addr[0] = smsk_base; in fdp1_start_streaming()
1954 ctx->smsk_addr[1] = smsk_base + (ctx->smsk_size/2); in fdp1_start_streaming()
1968 if (V4L2_TYPE_IS_OUTPUT(q->type)) in fdp1_stop_streaming()
1969 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); in fdp1_stop_streaming()
1971 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); in fdp1_stop_streaming()
1974 spin_lock_irqsave(&ctx->fdp1->irqlock, flags); in fdp1_stop_streaming()
1976 spin_unlock_irqrestore(&ctx->fdp1->irqlock, flags); in fdp1_stop_streaming()
1980 if (V4L2_TYPE_IS_OUTPUT(q->type)) { in fdp1_stop_streaming()
1992 if (ctx->smsk_cpu) { in fdp1_stop_streaming()
1993 dma_free_coherent(ctx->fdp1->dev, ctx->smsk_size, in fdp1_stop_streaming()
1994 ctx->smsk_cpu, ctx->smsk_addr[0]); in fdp1_stop_streaming()
1995 ctx->smsk_addr[0] = ctx->smsk_addr[1] = 0; in fdp1_stop_streaming()
1996 ctx->smsk_cpu = NULL; in fdp1_stop_streaming()
1999 WARN(!list_empty(&ctx->fields_queue), in fdp1_stop_streaming()
2005 job = get_queued_job(ctx->fdp1); in fdp1_stop_streaming()
2007 if (FDP1_DEINT_MODE_USES_PREV(ctx->deint_mode)) in fdp1_stop_streaming()
2008 fdp1_field_complete(ctx, job->previous); in fdp1_stop_streaming()
2010 fdp1_field_complete(ctx, job->active); in fdp1_stop_streaming()
2012 v4l2_m2m_buf_done(job->dst->vb, VB2_BUF_STATE_ERROR); in fdp1_stop_streaming()
2013 job->dst = NULL; in fdp1_stop_streaming()
2015 job = get_queued_job(ctx->fdp1); in fdp1_stop_streaming()
2019 fdp1_field_complete(ctx, ctx->previous); in fdp1_stop_streaming()
2021 WARN(!list_empty(&ctx->fdp1->queued_job_list), in fdp1_stop_streaming()
2024 WARN(!list_empty(&ctx->fdp1->hw_job_list), in fdp1_stop_streaming()
2045 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; in queue_init()
2046 src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; in queue_init()
2047 src_vq->drv_priv = ctx; in queue_init()
2048 src_vq->buf_struct_size = sizeof(struct fdp1_buffer); in queue_init()
2049 src_vq->ops = &fdp1_qops; in queue_init()
2050 src_vq->mem_ops = &vb2_dma_contig_memops; in queue_init()
2051 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in queue_init()
2052 src_vq->lock = &ctx->fdp1->dev_mutex; in queue_init()
2053 src_vq->dev = ctx->fdp1->dev; in queue_init()
2059 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; in queue_init()
2060 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; in queue_init()
2061 dst_vq->drv_priv = ctx; in queue_init()
2062 dst_vq->buf_struct_size = sizeof(struct fdp1_buffer); in queue_init()
2063 dst_vq->ops = &fdp1_qops; in queue_init()
2064 dst_vq->mem_ops = &vb2_dma_contig_memops; in queue_init()
2065 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in queue_init()
2066 dst_vq->lock = &ctx->fdp1->dev_mutex; in queue_init()
2067 dst_vq->dev = ctx->fdp1->dev; in queue_init()
2083 if (mutex_lock_interruptible(&fdp1->dev_mutex)) in fdp1_open()
2084 return -ERESTARTSYS; in fdp1_open()
2088 ret = -ENOMEM; in fdp1_open()
2092 v4l2_fh_init(&ctx->fh, video_devdata(file)); in fdp1_open()
2093 file->private_data = &ctx->fh; in fdp1_open()
2094 ctx->fdp1 = fdp1; in fdp1_open()
2097 INIT_LIST_HEAD(&ctx->fields_queue); in fdp1_open()
2099 ctx->translen = 1; in fdp1_open()
2100 ctx->sequence = 0; in fdp1_open()
2104 v4l2_ctrl_handler_init(&ctx->hdl, 3); in fdp1_open()
2105 v4l2_ctrl_new_std_menu_items(&ctx->hdl, &fdp1_ctrl_ops, in fdp1_open()
2110 ctrl = v4l2_ctrl_new_std(&ctx->hdl, &fdp1_ctrl_ops, in fdp1_open()
2113 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; in fdp1_open()
2115 v4l2_ctrl_new_std(&ctx->hdl, &fdp1_ctrl_ops, in fdp1_open()
2118 if (ctx->hdl.error) { in fdp1_open()
2119 ret = ctx->hdl.error; in fdp1_open()
2123 ctx->fh.ctrl_handler = &ctx->hdl; in fdp1_open()
2124 v4l2_ctrl_handler_setup(&ctx->hdl); in fdp1_open()
2130 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(fdp1->m2m_dev, ctx, &queue_init); in fdp1_open()
2132 if (IS_ERR(ctx->fh.m2m_ctx)) { in fdp1_open()
2133 ret = PTR_ERR(ctx->fh.m2m_ctx); in fdp1_open()
2138 ret = pm_runtime_resume_and_get(fdp1->dev); in fdp1_open()
2142 v4l2_fh_add(&ctx->fh); in fdp1_open()
2145 ctx, ctx->fh.m2m_ctx); in fdp1_open()
2147 mutex_unlock(&fdp1->dev_mutex); in fdp1_open()
2151 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); in fdp1_open()
2153 v4l2_ctrl_handler_free(&ctx->hdl); in fdp1_open()
2156 mutex_unlock(&fdp1->dev_mutex); in fdp1_open()
2163 struct fdp1_ctx *ctx = fh_to_ctx(file->private_data); in fdp1_release()
2167 v4l2_fh_del(&ctx->fh); in fdp1_release()
2168 v4l2_fh_exit(&ctx->fh); in fdp1_release()
2169 v4l2_ctrl_handler_free(&ctx->hdl); in fdp1_release()
2170 mutex_lock(&fdp1->dev_mutex); in fdp1_release()
2171 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); in fdp1_release()
2172 mutex_unlock(&fdp1->dev_mutex); in fdp1_release()
2175 pm_runtime_put(fdp1->dev); in fdp1_release()
2195 .minor = -1,
2229 cycles, cycles/(fdp1->clk_rate/1000)); in fdp1_irq_handler()
2265 fdp1 = devm_kzalloc(&pdev->dev, sizeof(*fdp1), GFP_KERNEL); in fdp1_probe()
2267 return -ENOMEM; in fdp1_probe()
2269 INIT_LIST_HEAD(&fdp1->free_job_list); in fdp1_probe()
2270 INIT_LIST_HEAD(&fdp1->queued_job_list); in fdp1_probe()
2271 INIT_LIST_HEAD(&fdp1->hw_job_list); in fdp1_probe()
2274 for (i = 0; i < ARRAY_SIZE(fdp1->jobs); i++) in fdp1_probe()
2275 list_add(&fdp1->jobs[i].list, &fdp1->free_job_list); in fdp1_probe()
2277 mutex_init(&fdp1->dev_mutex); in fdp1_probe()
2279 spin_lock_init(&fdp1->irqlock); in fdp1_probe()
2280 spin_lock_init(&fdp1->device_process_lock); in fdp1_probe()
2281 fdp1->dev = &pdev->dev; in fdp1_probe()
2284 /* Memory-mapped registers */ in fdp1_probe()
2285 fdp1->regs = devm_platform_ioremap_resource(pdev, 0); in fdp1_probe()
2286 if (IS_ERR(fdp1->regs)) in fdp1_probe()
2287 return PTR_ERR(fdp1->regs); in fdp1_probe()
2293 fdp1->irq = ret; in fdp1_probe()
2295 ret = devm_request_irq(&pdev->dev, fdp1->irq, fdp1_irq_handler, 0, in fdp1_probe()
2296 dev_name(&pdev->dev), fdp1); in fdp1_probe()
2298 dev_err(&pdev->dev, "cannot claim IRQ %d\n", fdp1->irq); in fdp1_probe()
2303 fcp_node = of_parse_phandle(pdev->dev.of_node, "renesas,fcp", 0); in fdp1_probe()
2305 fdp1->fcp = rcar_fcp_get(fcp_node); in fdp1_probe()
2307 if (IS_ERR(fdp1->fcp)) { in fdp1_probe()
2308 dev_dbg(&pdev->dev, "FCP not found (%ld)\n", in fdp1_probe()
2309 PTR_ERR(fdp1->fcp)); in fdp1_probe()
2310 return PTR_ERR(fdp1->fcp); in fdp1_probe()
2315 clk = clk_get(&pdev->dev, NULL); in fdp1_probe()
2321 fdp1->clk_rate = clk_get_rate(clk); in fdp1_probe()
2325 ret = v4l2_device_register(&pdev->dev, &fdp1->v4l2_dev); in fdp1_probe()
2327 v4l2_err(&fdp1->v4l2_dev, "Failed to register video device\n"); in fdp1_probe()
2332 fdp1->m2m_dev = v4l2_m2m_init(&m2m_ops); in fdp1_probe()
2333 if (IS_ERR(fdp1->m2m_dev)) { in fdp1_probe()
2334 v4l2_err(&fdp1->v4l2_dev, "Failed to init mem2mem device\n"); in fdp1_probe()
2335 ret = PTR_ERR(fdp1->m2m_dev); in fdp1_probe()
2340 fdp1->vfd = fdp1_videodev; in fdp1_probe()
2341 vfd = &fdp1->vfd; in fdp1_probe()
2342 vfd->lock = &fdp1->dev_mutex; in fdp1_probe()
2343 vfd->v4l2_dev = &fdp1->v4l2_dev; in fdp1_probe()
2345 strscpy(vfd->name, fdp1_videodev.name, sizeof(vfd->name)); in fdp1_probe()
2349 v4l2_err(&fdp1->v4l2_dev, "Failed to register video device\n"); in fdp1_probe()
2353 v4l2_info(&fdp1->v4l2_dev, "Device registered as /dev/video%d\n", in fdp1_probe()
2354 vfd->num); in fdp1_probe()
2357 pm_runtime_enable(&pdev->dev); in fdp1_probe()
2358 ret = pm_runtime_resume_and_get(fdp1->dev); in fdp1_probe()
2365 dprintk(fdp1, "FDP1 Version R-Car Gen2\n"); in fdp1_probe()
2368 dprintk(fdp1, "FDP1 Version R-Car M3-W\n"); in fdp1_probe()
2371 dprintk(fdp1, "FDP1 Version R-Car H3\n"); in fdp1_probe()
2374 dprintk(fdp1, "FDP1 Version R-Car M3-N\n"); in fdp1_probe()
2377 dprintk(fdp1, "FDP1 Version R-Car E3\n"); in fdp1_probe()
2380 dev_err(fdp1->dev, "FDP1 Unidentifiable (0x%08x)\n", in fdp1_probe()
2385 pm_runtime_put(fdp1->dev); in fdp1_probe()
2390 pm_runtime_disable(fdp1->dev); in fdp1_probe()
2393 v4l2_m2m_release(fdp1->m2m_dev); in fdp1_probe()
2396 v4l2_device_unregister(&fdp1->v4l2_dev); in fdp1_probe()
2399 rcar_fcp_put(fdp1->fcp); in fdp1_probe()
2407 v4l2_m2m_release(fdp1->m2m_dev); in fdp1_remove()
2408 video_unregister_device(&fdp1->vfd); in fdp1_remove()
2409 v4l2_device_unregister(&fdp1->v4l2_dev); in fdp1_remove()
2410 pm_runtime_disable(&pdev->dev); in fdp1_remove()
2411 rcar_fcp_put(fdp1->fcp); in fdp1_remove()
2418 rcar_fcp_disable(fdp1->fcp); in fdp1_pm_runtime_suspend()
2430 return rcar_fcp_enable(fdp1->fcp); in fdp1_pm_runtime_resume()
2457 MODULE_DESCRIPTION("Renesas R-Car Fine Display Processor Driver");