1*2ccf48afSBin Du // SPDX-License-Identifier: GPL-2.0+ 2*2ccf48afSBin Du /* 3*2ccf48afSBin Du * Copyright (C) 2025 Advanced Micro Devices, Inc. 4*2ccf48afSBin Du */ 5*2ccf48afSBin Du 6*2ccf48afSBin Du #include <media/v4l2-ioctl.h> 7*2ccf48afSBin Du #include <media/v4l2-mc.h> 8*2ccf48afSBin Du #include <media/videobuf2-vmalloc.h> 9*2ccf48afSBin Du 10*2ccf48afSBin Du #include "isp4_interface.h" 11*2ccf48afSBin Du #include "isp4_subdev.h" 12*2ccf48afSBin Du #include "isp4_video.h" 13*2ccf48afSBin Du 14*2ccf48afSBin Du #define ISP4VID_ISP_DRV_NAME "amd_isp_capture" 15*2ccf48afSBin Du #define ISP4VID_MAX_PREVIEW_FPS 30 16*2ccf48afSBin Du #define ISP4VID_DEFAULT_FMT V4L2_PIX_FMT_NV12 17*2ccf48afSBin Du 18*2ccf48afSBin Du #define ISP4VID_PAD_VIDEO_OUTPUT 0 19*2ccf48afSBin Du 20*2ccf48afSBin Du /* time perframe default */ 21*2ccf48afSBin Du #define ISP4VID_ISP_TPF_DEFAULT isp4vid_tpfs[0] 22*2ccf48afSBin Du 23*2ccf48afSBin Du static const char *const isp4vid_video_dev_name = "Preview"; 24*2ccf48afSBin Du 25*2ccf48afSBin Du /* Sizes must be in increasing order */ 26*2ccf48afSBin Du static const struct v4l2_frmsize_discrete isp4vid_frmsize[] = { 27*2ccf48afSBin Du {640, 360}, 28*2ccf48afSBin Du {640, 480}, 29*2ccf48afSBin Du {1280, 720}, 30*2ccf48afSBin Du {1280, 960}, 31*2ccf48afSBin Du {1920, 1080}, 32*2ccf48afSBin Du {1920, 1440}, 33*2ccf48afSBin Du {2560, 1440}, 34*2ccf48afSBin Du {2880, 1620}, 35*2ccf48afSBin Du {2880, 1624}, 36*2ccf48afSBin Du {2888, 1808}, 37*2ccf48afSBin Du }; 38*2ccf48afSBin Du 39*2ccf48afSBin Du static const u32 isp4vid_formats[] = { 40*2ccf48afSBin Du V4L2_PIX_FMT_NV12, 41*2ccf48afSBin Du V4L2_PIX_FMT_YUYV 42*2ccf48afSBin Du }; 43*2ccf48afSBin Du 44*2ccf48afSBin Du /* time perframe list */ 45*2ccf48afSBin Du static const struct v4l2_fract isp4vid_tpfs[] = { 46*2ccf48afSBin Du { 1, ISP4VID_MAX_PREVIEW_FPS } 47*2ccf48afSBin Du }; 48*2ccf48afSBin Du 49*2ccf48afSBin Du void isp4vid_handle_frame_done(struct isp4vid_dev *isp_vdev, 50*2ccf48afSBin Du const struct isp4if_img_buf_info *img_buf) 51*2ccf48afSBin Du { 52*2ccf48afSBin Du struct isp4vid_capture_buffer *isp4vid_buf; 53*2ccf48afSBin Du void *vbuf; 54*2ccf48afSBin Du 55*2ccf48afSBin Du scoped_guard(mutex, &isp_vdev->buf_list_lock) { 56*2ccf48afSBin Du isp4vid_buf = list_first_entry_or_null(&isp_vdev->buf_list, 57*2ccf48afSBin Du typeof(*isp4vid_buf), 58*2ccf48afSBin Du list); 59*2ccf48afSBin Du if (!isp4vid_buf) 60*2ccf48afSBin Du return; 61*2ccf48afSBin Du 62*2ccf48afSBin Du vbuf = vb2_plane_vaddr(&isp4vid_buf->vb2.vb2_buf, 0); 63*2ccf48afSBin Du 64*2ccf48afSBin Du if (vbuf != img_buf->planes[0].sys_addr) { 65*2ccf48afSBin Du dev_err(isp_vdev->dev, "Invalid vbuf\n"); 66*2ccf48afSBin Du return; 67*2ccf48afSBin Du } 68*2ccf48afSBin Du 69*2ccf48afSBin Du list_del(&isp4vid_buf->list); 70*2ccf48afSBin Du } 71*2ccf48afSBin Du 72*2ccf48afSBin Du /* Fill the buffer */ 73*2ccf48afSBin Du isp4vid_buf->vb2.vb2_buf.timestamp = ktime_get_ns(); 74*2ccf48afSBin Du isp4vid_buf->vb2.sequence = isp_vdev->sequence++; 75*2ccf48afSBin Du isp4vid_buf->vb2.field = V4L2_FIELD_ANY; 76*2ccf48afSBin Du 77*2ccf48afSBin Du vb2_set_plane_payload(&isp4vid_buf->vb2.vb2_buf, 78*2ccf48afSBin Du 0, isp_vdev->format.sizeimage); 79*2ccf48afSBin Du 80*2ccf48afSBin Du vb2_buffer_done(&isp4vid_buf->vb2.vb2_buf, VB2_BUF_STATE_DONE); 81*2ccf48afSBin Du 82*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "call vb2_buffer_done(size=%u)\n", 83*2ccf48afSBin Du isp_vdev->format.sizeimage); 84*2ccf48afSBin Du } 85*2ccf48afSBin Du 86*2ccf48afSBin Du static const struct v4l2_pix_format isp4vid_fmt_default = { 87*2ccf48afSBin Du .width = 1920, 88*2ccf48afSBin Du .height = 1080, 89*2ccf48afSBin Du .pixelformat = ISP4VID_DEFAULT_FMT, 90*2ccf48afSBin Du .field = V4L2_FIELD_NONE, 91*2ccf48afSBin Du .colorspace = V4L2_COLORSPACE_SRGB, 92*2ccf48afSBin Du }; 93*2ccf48afSBin Du 94*2ccf48afSBin Du static void isp4vid_capture_return_all_buffers(struct isp4vid_dev *isp_vdev, 95*2ccf48afSBin Du enum vb2_buffer_state state) 96*2ccf48afSBin Du { 97*2ccf48afSBin Du struct isp4vid_capture_buffer *vbuf, *node; 98*2ccf48afSBin Du 99*2ccf48afSBin Du scoped_guard(mutex, &isp_vdev->buf_list_lock) { 100*2ccf48afSBin Du list_for_each_entry_safe(vbuf, node, &isp_vdev->buf_list, list) 101*2ccf48afSBin Du vb2_buffer_done(&vbuf->vb2.vb2_buf, state); 102*2ccf48afSBin Du INIT_LIST_HEAD(&isp_vdev->buf_list); 103*2ccf48afSBin Du } 104*2ccf48afSBin Du 105*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "call vb2_buffer_done(%d)\n", state); 106*2ccf48afSBin Du } 107*2ccf48afSBin Du 108*2ccf48afSBin Du static int isp4vid_vdev_link_validate(struct media_link *link) 109*2ccf48afSBin Du { 110*2ccf48afSBin Du return 0; 111*2ccf48afSBin Du } 112*2ccf48afSBin Du 113*2ccf48afSBin Du static const struct media_entity_operations isp4vid_vdev_ent_ops = { 114*2ccf48afSBin Du .link_validate = isp4vid_vdev_link_validate, 115*2ccf48afSBin Du }; 116*2ccf48afSBin Du 117*2ccf48afSBin Du static const struct v4l2_file_operations isp4vid_vdev_fops = { 118*2ccf48afSBin Du .owner = THIS_MODULE, 119*2ccf48afSBin Du .open = v4l2_fh_open, 120*2ccf48afSBin Du .release = vb2_fop_release, 121*2ccf48afSBin Du .read = vb2_fop_read, 122*2ccf48afSBin Du .poll = vb2_fop_poll, 123*2ccf48afSBin Du .unlocked_ioctl = video_ioctl2, 124*2ccf48afSBin Du .mmap = vb2_fop_mmap, 125*2ccf48afSBin Du }; 126*2ccf48afSBin Du 127*2ccf48afSBin Du static int isp4vid_ioctl_querycap(struct file *file, void *fh, 128*2ccf48afSBin Du struct v4l2_capability *cap) 129*2ccf48afSBin Du { 130*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = video_drvdata(file); 131*2ccf48afSBin Du 132*2ccf48afSBin Du strscpy(cap->driver, ISP4VID_ISP_DRV_NAME, sizeof(cap->driver)); 133*2ccf48afSBin Du snprintf(cap->card, sizeof(cap->card), "%s", ISP4VID_ISP_DRV_NAME); 134*2ccf48afSBin Du cap->capabilities |= V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE; 135*2ccf48afSBin Du 136*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "%s|capabilities=0x%X\n", isp_vdev->vdev.name, 137*2ccf48afSBin Du cap->capabilities); 138*2ccf48afSBin Du 139*2ccf48afSBin Du return 0; 140*2ccf48afSBin Du } 141*2ccf48afSBin Du 142*2ccf48afSBin Du static int isp4vid_g_fmt_vid_cap(struct file *file, void *priv, 143*2ccf48afSBin Du struct v4l2_format *f) 144*2ccf48afSBin Du { 145*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = video_drvdata(file); 146*2ccf48afSBin Du 147*2ccf48afSBin Du f->fmt.pix = isp_vdev->format; 148*2ccf48afSBin Du 149*2ccf48afSBin Du return 0; 150*2ccf48afSBin Du } 151*2ccf48afSBin Du 152*2ccf48afSBin Du static int isp4vid_fill_buffer_size(struct v4l2_pix_format *fmt) 153*2ccf48afSBin Du { 154*2ccf48afSBin Du int ret = 0; 155*2ccf48afSBin Du 156*2ccf48afSBin Du switch (fmt->pixelformat) { 157*2ccf48afSBin Du case V4L2_PIX_FMT_NV12: 158*2ccf48afSBin Du fmt->bytesperline = fmt->width; 159*2ccf48afSBin Du fmt->sizeimage = fmt->bytesperline * fmt->height * 3 / 2; 160*2ccf48afSBin Du break; 161*2ccf48afSBin Du case V4L2_PIX_FMT_YUYV: 162*2ccf48afSBin Du fmt->bytesperline = fmt->width * 2; 163*2ccf48afSBin Du fmt->sizeimage = fmt->bytesperline * fmt->height; 164*2ccf48afSBin Du break; 165*2ccf48afSBin Du default: 166*2ccf48afSBin Du ret = -EINVAL; 167*2ccf48afSBin Du break; 168*2ccf48afSBin Du } 169*2ccf48afSBin Du 170*2ccf48afSBin Du return ret; 171*2ccf48afSBin Du } 172*2ccf48afSBin Du 173*2ccf48afSBin Du static int isp4vid_try_fmt_vid_cap(struct file *file, void *priv, 174*2ccf48afSBin Du struct v4l2_format *f) 175*2ccf48afSBin Du { 176*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = video_drvdata(file); 177*2ccf48afSBin Du struct v4l2_pix_format *format = &f->fmt.pix; 178*2ccf48afSBin Du const struct v4l2_frmsize_discrete *fsz; 179*2ccf48afSBin Du size_t i; 180*2ccf48afSBin Du 181*2ccf48afSBin Du /* 182*2ccf48afSBin Du * Check if the hardware supports the requested format, use the default 183*2ccf48afSBin Du * format otherwise. 184*2ccf48afSBin Du */ 185*2ccf48afSBin Du for (i = 0; i < ARRAY_SIZE(isp4vid_formats); i++) 186*2ccf48afSBin Du if (isp4vid_formats[i] == format->pixelformat) 187*2ccf48afSBin Du break; 188*2ccf48afSBin Du 189*2ccf48afSBin Du if (i == ARRAY_SIZE(isp4vid_formats)) 190*2ccf48afSBin Du format->pixelformat = ISP4VID_DEFAULT_FMT; 191*2ccf48afSBin Du 192*2ccf48afSBin Du switch (format->pixelformat) { 193*2ccf48afSBin Du case V4L2_PIX_FMT_NV12: 194*2ccf48afSBin Du case V4L2_PIX_FMT_YUYV: 195*2ccf48afSBin Du fsz = v4l2_find_nearest_size(isp4vid_frmsize, 196*2ccf48afSBin Du ARRAY_SIZE(isp4vid_frmsize), 197*2ccf48afSBin Du width, height, format->width, 198*2ccf48afSBin Du format->height); 199*2ccf48afSBin Du format->width = fsz->width; 200*2ccf48afSBin Du format->height = fsz->height; 201*2ccf48afSBin Du break; 202*2ccf48afSBin Du default: 203*2ccf48afSBin Du dev_err(isp_vdev->dev, "%s|unsupported fmt=%u\n", 204*2ccf48afSBin Du isp_vdev->vdev.name, 205*2ccf48afSBin Du format->pixelformat); 206*2ccf48afSBin Du return -EINVAL; 207*2ccf48afSBin Du } 208*2ccf48afSBin Du 209*2ccf48afSBin Du /* 210*2ccf48afSBin Du * There is no need to check the return value, as failure will never 211*2ccf48afSBin Du * happen here 212*2ccf48afSBin Du */ 213*2ccf48afSBin Du isp4vid_fill_buffer_size(format); 214*2ccf48afSBin Du 215*2ccf48afSBin Du if (format->field == V4L2_FIELD_ANY) 216*2ccf48afSBin Du format->field = isp4vid_fmt_default.field; 217*2ccf48afSBin Du 218*2ccf48afSBin Du if (format->colorspace == V4L2_COLORSPACE_DEFAULT) 219*2ccf48afSBin Du format->colorspace = isp4vid_fmt_default.colorspace; 220*2ccf48afSBin Du 221*2ccf48afSBin Du return 0; 222*2ccf48afSBin Du } 223*2ccf48afSBin Du 224*2ccf48afSBin Du static int isp4vid_set_fmt_2_isp(struct v4l2_subdev *sdev, 225*2ccf48afSBin Du struct v4l2_pix_format *pix_fmt) 226*2ccf48afSBin Du { 227*2ccf48afSBin Du struct v4l2_subdev_format fmt = {}; 228*2ccf48afSBin Du 229*2ccf48afSBin Du switch (pix_fmt->pixelformat) { 230*2ccf48afSBin Du case V4L2_PIX_FMT_NV12: 231*2ccf48afSBin Du fmt.format.code = MEDIA_BUS_FMT_YUYV8_1_5X8; 232*2ccf48afSBin Du break; 233*2ccf48afSBin Du case V4L2_PIX_FMT_YUYV: 234*2ccf48afSBin Du fmt.format.code = MEDIA_BUS_FMT_YUYV8_1X16; 235*2ccf48afSBin Du break; 236*2ccf48afSBin Du default: 237*2ccf48afSBin Du return -EINVAL; 238*2ccf48afSBin Du } 239*2ccf48afSBin Du fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; 240*2ccf48afSBin Du fmt.pad = ISP4VID_PAD_VIDEO_OUTPUT; 241*2ccf48afSBin Du fmt.format.width = pix_fmt->width; 242*2ccf48afSBin Du fmt.format.height = pix_fmt->height; 243*2ccf48afSBin Du return v4l2_subdev_call(sdev, pad, set_fmt, NULL, &fmt); 244*2ccf48afSBin Du } 245*2ccf48afSBin Du 246*2ccf48afSBin Du static int isp4vid_s_fmt_vid_cap(struct file *file, void *priv, 247*2ccf48afSBin Du struct v4l2_format *f) 248*2ccf48afSBin Du { 249*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = video_drvdata(file); 250*2ccf48afSBin Du int ret; 251*2ccf48afSBin Du 252*2ccf48afSBin Du /* Do not change the format while stream is on */ 253*2ccf48afSBin Du if (vb2_is_busy(&isp_vdev->vbq)) 254*2ccf48afSBin Du return -EBUSY; 255*2ccf48afSBin Du 256*2ccf48afSBin Du ret = isp4vid_try_fmt_vid_cap(file, priv, f); 257*2ccf48afSBin Du if (ret) 258*2ccf48afSBin Du return ret; 259*2ccf48afSBin Du 260*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "%s|width height:%ux%u->%ux%u\n", 261*2ccf48afSBin Du isp_vdev->vdev.name, 262*2ccf48afSBin Du isp_vdev->format.width, isp_vdev->format.height, 263*2ccf48afSBin Du f->fmt.pix.width, f->fmt.pix.height); 264*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "%s|pixelformat:0x%x-0x%x\n", 265*2ccf48afSBin Du isp_vdev->vdev.name, isp_vdev->format.pixelformat, 266*2ccf48afSBin Du f->fmt.pix.pixelformat); 267*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "%s|bytesperline:%u->%u\n", 268*2ccf48afSBin Du isp_vdev->vdev.name, isp_vdev->format.bytesperline, 269*2ccf48afSBin Du f->fmt.pix.bytesperline); 270*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "%s|sizeimage:%u->%u\n", 271*2ccf48afSBin Du isp_vdev->vdev.name, isp_vdev->format.sizeimage, 272*2ccf48afSBin Du f->fmt.pix.sizeimage); 273*2ccf48afSBin Du 274*2ccf48afSBin Du isp_vdev->format = f->fmt.pix; 275*2ccf48afSBin Du ret = isp4vid_set_fmt_2_isp(isp_vdev->isp_sdev, &isp_vdev->format); 276*2ccf48afSBin Du 277*2ccf48afSBin Du return ret; 278*2ccf48afSBin Du } 279*2ccf48afSBin Du 280*2ccf48afSBin Du static int isp4vid_enum_fmt_vid_cap(struct file *file, void *priv, 281*2ccf48afSBin Du struct v4l2_fmtdesc *f) 282*2ccf48afSBin Du { 283*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = video_drvdata(file); 284*2ccf48afSBin Du 285*2ccf48afSBin Du switch (f->index) { 286*2ccf48afSBin Du case 0: 287*2ccf48afSBin Du f->pixelformat = V4L2_PIX_FMT_NV12; 288*2ccf48afSBin Du break; 289*2ccf48afSBin Du case 1: 290*2ccf48afSBin Du f->pixelformat = V4L2_PIX_FMT_YUYV; 291*2ccf48afSBin Du break; 292*2ccf48afSBin Du default: 293*2ccf48afSBin Du return -EINVAL; 294*2ccf48afSBin Du } 295*2ccf48afSBin Du 296*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "%s|index=%d, pixelformat=0x%X\n", 297*2ccf48afSBin Du isp_vdev->vdev.name, f->index, f->pixelformat); 298*2ccf48afSBin Du 299*2ccf48afSBin Du return 0; 300*2ccf48afSBin Du } 301*2ccf48afSBin Du 302*2ccf48afSBin Du static int isp4vid_enum_framesizes(struct file *file, void *fh, 303*2ccf48afSBin Du struct v4l2_frmsizeenum *fsize) 304*2ccf48afSBin Du { 305*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = video_drvdata(file); 306*2ccf48afSBin Du unsigned int i; 307*2ccf48afSBin Du 308*2ccf48afSBin Du for (i = 0; i < ARRAY_SIZE(isp4vid_formats); i++) { 309*2ccf48afSBin Du if (isp4vid_formats[i] == fsize->pixel_format) 310*2ccf48afSBin Du break; 311*2ccf48afSBin Du } 312*2ccf48afSBin Du 313*2ccf48afSBin Du if (i == ARRAY_SIZE(isp4vid_formats)) 314*2ccf48afSBin Du return -EINVAL; 315*2ccf48afSBin Du 316*2ccf48afSBin Du if (fsize->index < ARRAY_SIZE(isp4vid_frmsize)) { 317*2ccf48afSBin Du fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; 318*2ccf48afSBin Du fsize->discrete = isp4vid_frmsize[fsize->index]; 319*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "%s|size[%d]=%dx%d\n", 320*2ccf48afSBin Du isp_vdev->vdev.name, fsize->index, 321*2ccf48afSBin Du fsize->discrete.width, fsize->discrete.height); 322*2ccf48afSBin Du } else { 323*2ccf48afSBin Du return -EINVAL; 324*2ccf48afSBin Du } 325*2ccf48afSBin Du 326*2ccf48afSBin Du return 0; 327*2ccf48afSBin Du } 328*2ccf48afSBin Du 329*2ccf48afSBin Du static int isp4vid_ioctl_enum_frameintervals(struct file *file, void *priv, 330*2ccf48afSBin Du struct v4l2_frmivalenum *fival) 331*2ccf48afSBin Du { 332*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = video_drvdata(file); 333*2ccf48afSBin Du size_t i; 334*2ccf48afSBin Du 335*2ccf48afSBin Du if (fival->index >= ARRAY_SIZE(isp4vid_tpfs)) 336*2ccf48afSBin Du return -EINVAL; 337*2ccf48afSBin Du 338*2ccf48afSBin Du for (i = 0; i < ARRAY_SIZE(isp4vid_formats); i++) 339*2ccf48afSBin Du if (isp4vid_formats[i] == fival->pixel_format) 340*2ccf48afSBin Du break; 341*2ccf48afSBin Du 342*2ccf48afSBin Du if (i == ARRAY_SIZE(isp4vid_formats)) 343*2ccf48afSBin Du return -EINVAL; 344*2ccf48afSBin Du 345*2ccf48afSBin Du for (i = 0; i < ARRAY_SIZE(isp4vid_frmsize); i++) 346*2ccf48afSBin Du if (isp4vid_frmsize[i].width == fival->width && 347*2ccf48afSBin Du isp4vid_frmsize[i].height == fival->height) 348*2ccf48afSBin Du break; 349*2ccf48afSBin Du 350*2ccf48afSBin Du if (i == ARRAY_SIZE(isp4vid_frmsize)) 351*2ccf48afSBin Du return -EINVAL; 352*2ccf48afSBin Du 353*2ccf48afSBin Du fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; 354*2ccf48afSBin Du fival->discrete = isp4vid_tpfs[fival->index]; 355*2ccf48afSBin Du v4l2_simplify_fraction(&fival->discrete.numerator, 356*2ccf48afSBin Du &fival->discrete.denominator, 8, 333); 357*2ccf48afSBin Du 358*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "%s|interval[%d]=%d/%d\n", 359*2ccf48afSBin Du isp_vdev->vdev.name, fival->index, 360*2ccf48afSBin Du fival->discrete.numerator, 361*2ccf48afSBin Du fival->discrete.denominator); 362*2ccf48afSBin Du 363*2ccf48afSBin Du return 0; 364*2ccf48afSBin Du } 365*2ccf48afSBin Du 366*2ccf48afSBin Du static int isp4vid_ioctl_g_param(struct file *file, void *priv, 367*2ccf48afSBin Du struct v4l2_streamparm *param) 368*2ccf48afSBin Du { 369*2ccf48afSBin Du struct v4l2_captureparm *capture = ¶m->parm.capture; 370*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = video_drvdata(file); 371*2ccf48afSBin Du 372*2ccf48afSBin Du if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 373*2ccf48afSBin Du return -EINVAL; 374*2ccf48afSBin Du 375*2ccf48afSBin Du capture->capability = V4L2_CAP_TIMEPERFRAME; 376*2ccf48afSBin Du capture->timeperframe = isp_vdev->timeperframe; 377*2ccf48afSBin Du capture->readbuffers = 0; 378*2ccf48afSBin Du 379*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "%s|timeperframe=%d/%d\n", isp_vdev->vdev.name, 380*2ccf48afSBin Du capture->timeperframe.numerator, 381*2ccf48afSBin Du capture->timeperframe.denominator); 382*2ccf48afSBin Du 383*2ccf48afSBin Du return 0; 384*2ccf48afSBin Du } 385*2ccf48afSBin Du 386*2ccf48afSBin Du static const struct v4l2_ioctl_ops isp4vid_vdev_ioctl_ops = { 387*2ccf48afSBin Du .vidioc_querycap = isp4vid_ioctl_querycap, 388*2ccf48afSBin Du .vidioc_enum_fmt_vid_cap = isp4vid_enum_fmt_vid_cap, 389*2ccf48afSBin Du .vidioc_g_fmt_vid_cap = isp4vid_g_fmt_vid_cap, 390*2ccf48afSBin Du .vidioc_s_fmt_vid_cap = isp4vid_s_fmt_vid_cap, 391*2ccf48afSBin Du .vidioc_try_fmt_vid_cap = isp4vid_try_fmt_vid_cap, 392*2ccf48afSBin Du .vidioc_reqbufs = vb2_ioctl_reqbufs, 393*2ccf48afSBin Du .vidioc_querybuf = vb2_ioctl_querybuf, 394*2ccf48afSBin Du .vidioc_qbuf = vb2_ioctl_qbuf, 395*2ccf48afSBin Du .vidioc_expbuf = vb2_ioctl_expbuf, 396*2ccf48afSBin Du .vidioc_dqbuf = vb2_ioctl_dqbuf, 397*2ccf48afSBin Du .vidioc_create_bufs = vb2_ioctl_create_bufs, 398*2ccf48afSBin Du .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 399*2ccf48afSBin Du .vidioc_streamon = vb2_ioctl_streamon, 400*2ccf48afSBin Du .vidioc_streamoff = vb2_ioctl_streamoff, 401*2ccf48afSBin Du .vidioc_g_parm = isp4vid_ioctl_g_param, 402*2ccf48afSBin Du .vidioc_s_parm = isp4vid_ioctl_g_param, 403*2ccf48afSBin Du .vidioc_enum_framesizes = isp4vid_enum_framesizes, 404*2ccf48afSBin Du .vidioc_enum_frameintervals = isp4vid_ioctl_enum_frameintervals, 405*2ccf48afSBin Du }; 406*2ccf48afSBin Du 407*2ccf48afSBin Du static unsigned int isp4vid_get_image_size(struct v4l2_pix_format *fmt) 408*2ccf48afSBin Du { 409*2ccf48afSBin Du switch (fmt->pixelformat) { 410*2ccf48afSBin Du case V4L2_PIX_FMT_NV12: 411*2ccf48afSBin Du return fmt->width * fmt->height * 3 / 2; 412*2ccf48afSBin Du case V4L2_PIX_FMT_YUYV: 413*2ccf48afSBin Du return fmt->width * fmt->height * 2; 414*2ccf48afSBin Du default: 415*2ccf48afSBin Du return 0; 416*2ccf48afSBin Du } 417*2ccf48afSBin Du } 418*2ccf48afSBin Du 419*2ccf48afSBin Du static int isp4vid_qops_queue_setup(struct vb2_queue *vq, 420*2ccf48afSBin Du unsigned int *nbuffers, 421*2ccf48afSBin Du unsigned int *nplanes, unsigned int sizes[], 422*2ccf48afSBin Du struct device *alloc_devs[]) 423*2ccf48afSBin Du { 424*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = vb2_get_drv_priv(vq); 425*2ccf48afSBin Du unsigned int q_num_bufs = vb2_get_num_buffers(vq); 426*2ccf48afSBin Du 427*2ccf48afSBin Du if (*nplanes > 1) { 428*2ccf48afSBin Du dev_err(isp_vdev->dev, 429*2ccf48afSBin Du "fail to setup queue, no mplane supported %u\n", 430*2ccf48afSBin Du *nplanes); 431*2ccf48afSBin Du return -EINVAL; 432*2ccf48afSBin Du } 433*2ccf48afSBin Du 434*2ccf48afSBin Du if (*nplanes == 1) { 435*2ccf48afSBin Du unsigned int size; 436*2ccf48afSBin Du 437*2ccf48afSBin Du size = isp4vid_get_image_size(&isp_vdev->format); 438*2ccf48afSBin Du if (sizes[0] < size) { 439*2ccf48afSBin Du dev_err(isp_vdev->dev, 440*2ccf48afSBin Du "fail for small plane size %u, %u expected\n", 441*2ccf48afSBin Du sizes[0], size); 442*2ccf48afSBin Du return -EINVAL; 443*2ccf48afSBin Du } 444*2ccf48afSBin Du } 445*2ccf48afSBin Du 446*2ccf48afSBin Du if (q_num_bufs + *nbuffers < ISP4IF_MAX_STREAM_BUF_COUNT) 447*2ccf48afSBin Du *nbuffers = ISP4IF_MAX_STREAM_BUF_COUNT - q_num_bufs; 448*2ccf48afSBin Du 449*2ccf48afSBin Du switch (isp_vdev->format.pixelformat) { 450*2ccf48afSBin Du case V4L2_PIX_FMT_NV12: 451*2ccf48afSBin Du case V4L2_PIX_FMT_YUYV: { 452*2ccf48afSBin Du *nplanes = 1; 453*2ccf48afSBin Du sizes[0] = max(sizes[0], isp_vdev->format.sizeimage); 454*2ccf48afSBin Du isp_vdev->format.sizeimage = sizes[0]; 455*2ccf48afSBin Du } 456*2ccf48afSBin Du break; 457*2ccf48afSBin Du default: 458*2ccf48afSBin Du dev_err(isp_vdev->dev, "%s|unsupported fmt=%u\n", 459*2ccf48afSBin Du isp_vdev->vdev.name, isp_vdev->format.pixelformat); 460*2ccf48afSBin Du return -EINVAL; 461*2ccf48afSBin Du } 462*2ccf48afSBin Du 463*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "%s|*nbuffers=%u *nplanes=%u sizes[0]=%u\n", 464*2ccf48afSBin Du isp_vdev->vdev.name, 465*2ccf48afSBin Du *nbuffers, *nplanes, sizes[0]); 466*2ccf48afSBin Du 467*2ccf48afSBin Du return 0; 468*2ccf48afSBin Du } 469*2ccf48afSBin Du 470*2ccf48afSBin Du static void isp4vid_qops_buffer_queue(struct vb2_buffer *vb) 471*2ccf48afSBin Du { 472*2ccf48afSBin Du struct isp4vid_capture_buffer *buf = 473*2ccf48afSBin Du container_of(vb, struct isp4vid_capture_buffer, vb2.vb2_buf); 474*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = vb2_get_drv_priv(vb->vb2_queue); 475*2ccf48afSBin Du struct isp4if_img_buf_info *img_buf = &buf->img_buf; 476*2ccf48afSBin Du void *vaddr = vb2_plane_vaddr(vb, 0); 477*2ccf48afSBin Du 478*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "queue buf, vaddr %p, gpuva 0x%llx, size %u\n", 479*2ccf48afSBin Du vaddr, buf->gpu_addr, vb->planes[0].length); 480*2ccf48afSBin Du 481*2ccf48afSBin Du switch (isp_vdev->format.pixelformat) { 482*2ccf48afSBin Du case V4L2_PIX_FMT_NV12: { 483*2ccf48afSBin Du u32 y_size = isp_vdev->format.sizeimage / 3 * 2; 484*2ccf48afSBin Du u32 uv_size = isp_vdev->format.sizeimage / 3; 485*2ccf48afSBin Du 486*2ccf48afSBin Du img_buf->planes[0].len = y_size; 487*2ccf48afSBin Du img_buf->planes[0].sys_addr = vaddr; 488*2ccf48afSBin Du img_buf->planes[0].mc_addr = buf->gpu_addr; 489*2ccf48afSBin Du 490*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "img_buf[0]: mc=0x%llx size=%u\n", 491*2ccf48afSBin Du img_buf->planes[0].mc_addr, 492*2ccf48afSBin Du img_buf->planes[0].len); 493*2ccf48afSBin Du 494*2ccf48afSBin Du img_buf->planes[1].len = uv_size; 495*2ccf48afSBin Du img_buf->planes[1].sys_addr = vaddr + y_size; 496*2ccf48afSBin Du img_buf->planes[1].mc_addr = buf->gpu_addr + y_size; 497*2ccf48afSBin Du 498*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "img_buf[1]: mc=0x%llx size=%u\n", 499*2ccf48afSBin Du img_buf->planes[1].mc_addr, 500*2ccf48afSBin Du img_buf->planes[1].len); 501*2ccf48afSBin Du 502*2ccf48afSBin Du img_buf->planes[2].len = 0; 503*2ccf48afSBin Du } 504*2ccf48afSBin Du break; 505*2ccf48afSBin Du case V4L2_PIX_FMT_YUYV: { 506*2ccf48afSBin Du img_buf->planes[0].len = isp_vdev->format.sizeimage; 507*2ccf48afSBin Du img_buf->planes[0].sys_addr = vaddr; 508*2ccf48afSBin Du img_buf->planes[0].mc_addr = buf->gpu_addr; 509*2ccf48afSBin Du 510*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "img_buf[0]: mc=0x%llx size=%u\n", 511*2ccf48afSBin Du img_buf->planes[0].mc_addr, 512*2ccf48afSBin Du img_buf->planes[0].len); 513*2ccf48afSBin Du 514*2ccf48afSBin Du img_buf->planes[1].len = 0; 515*2ccf48afSBin Du img_buf->planes[2].len = 0; 516*2ccf48afSBin Du } 517*2ccf48afSBin Du break; 518*2ccf48afSBin Du default: 519*2ccf48afSBin Du dev_err(isp_vdev->dev, "%s|unsupported fmt=%u\n", 520*2ccf48afSBin Du isp_vdev->vdev.name, isp_vdev->format.pixelformat); 521*2ccf48afSBin Du return; 522*2ccf48afSBin Du } 523*2ccf48afSBin Du 524*2ccf48afSBin Du if (isp_vdev->stream_started) 525*2ccf48afSBin Du isp4sd_ioc_send_img_buf(isp_vdev->isp_sdev, img_buf); 526*2ccf48afSBin Du 527*2ccf48afSBin Du scoped_guard(mutex, &isp_vdev->buf_list_lock) 528*2ccf48afSBin Du list_add_tail(&buf->list, &isp_vdev->buf_list); 529*2ccf48afSBin Du } 530*2ccf48afSBin Du 531*2ccf48afSBin Du static int isp4vid_qops_start_streaming(struct vb2_queue *vq, 532*2ccf48afSBin Du unsigned int count) 533*2ccf48afSBin Du { 534*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = vb2_get_drv_priv(vq); 535*2ccf48afSBin Du struct isp4vid_capture_buffer *isp4vid_buf; 536*2ccf48afSBin Du struct media_entity *entity; 537*2ccf48afSBin Du struct v4l2_subdev *subdev; 538*2ccf48afSBin Du struct media_pad *pad; 539*2ccf48afSBin Du int ret = 0; 540*2ccf48afSBin Du 541*2ccf48afSBin Du isp_vdev->sequence = 0; 542*2ccf48afSBin Du 543*2ccf48afSBin Du ret = isp4sd_pwron_and_init(isp_vdev->isp_sdev); 544*2ccf48afSBin Du if (ret) { 545*2ccf48afSBin Du dev_err(isp_vdev->dev, "power up isp fail %d\n", ret); 546*2ccf48afSBin Du goto release_buffers; 547*2ccf48afSBin Du } 548*2ccf48afSBin Du 549*2ccf48afSBin Du entity = &isp_vdev->vdev.entity; 550*2ccf48afSBin Du while (1) { 551*2ccf48afSBin Du pad = &entity->pads[0]; 552*2ccf48afSBin Du if (!(pad->flags & MEDIA_PAD_FL_SINK)) 553*2ccf48afSBin Du break; 554*2ccf48afSBin Du 555*2ccf48afSBin Du pad = media_pad_remote_pad_first(pad); 556*2ccf48afSBin Du if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) 557*2ccf48afSBin Du break; 558*2ccf48afSBin Du 559*2ccf48afSBin Du entity = pad->entity; 560*2ccf48afSBin Du subdev = media_entity_to_v4l2_subdev(entity); 561*2ccf48afSBin Du 562*2ccf48afSBin Du ret = v4l2_subdev_call(subdev, video, s_stream, 1); 563*2ccf48afSBin Du if (ret < 0 && ret != -ENOIOCTLCMD) { 564*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "fail start streaming: %s %d\n", 565*2ccf48afSBin Du subdev->name, ret); 566*2ccf48afSBin Du goto release_buffers; 567*2ccf48afSBin Du } 568*2ccf48afSBin Du } 569*2ccf48afSBin Du 570*2ccf48afSBin Du list_for_each_entry(isp4vid_buf, &isp_vdev->buf_list, list) 571*2ccf48afSBin Du isp4sd_ioc_send_img_buf(isp_vdev->isp_sdev, 572*2ccf48afSBin Du &isp4vid_buf->img_buf); 573*2ccf48afSBin Du 574*2ccf48afSBin Du isp_vdev->stream_started = true; 575*2ccf48afSBin Du 576*2ccf48afSBin Du return 0; 577*2ccf48afSBin Du 578*2ccf48afSBin Du release_buffers: 579*2ccf48afSBin Du isp4vid_capture_return_all_buffers(isp_vdev, VB2_BUF_STATE_QUEUED); 580*2ccf48afSBin Du return ret; 581*2ccf48afSBin Du } 582*2ccf48afSBin Du 583*2ccf48afSBin Du static void isp4vid_qops_stop_streaming(struct vb2_queue *vq) 584*2ccf48afSBin Du { 585*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = vb2_get_drv_priv(vq); 586*2ccf48afSBin Du struct media_entity *entity; 587*2ccf48afSBin Du struct v4l2_subdev *subdev; 588*2ccf48afSBin Du struct media_pad *pad; 589*2ccf48afSBin Du int ret; 590*2ccf48afSBin Du 591*2ccf48afSBin Du entity = &isp_vdev->vdev.entity; 592*2ccf48afSBin Du while (1) { 593*2ccf48afSBin Du pad = &entity->pads[0]; 594*2ccf48afSBin Du if (!(pad->flags & MEDIA_PAD_FL_SINK)) 595*2ccf48afSBin Du break; 596*2ccf48afSBin Du 597*2ccf48afSBin Du pad = media_pad_remote_pad_first(pad); 598*2ccf48afSBin Du if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) 599*2ccf48afSBin Du break; 600*2ccf48afSBin Du 601*2ccf48afSBin Du entity = pad->entity; 602*2ccf48afSBin Du subdev = media_entity_to_v4l2_subdev(entity); 603*2ccf48afSBin Du 604*2ccf48afSBin Du ret = v4l2_subdev_call(subdev, video, s_stream, 0); 605*2ccf48afSBin Du 606*2ccf48afSBin Du if (ret < 0 && ret != -ENOIOCTLCMD) 607*2ccf48afSBin Du dev_dbg(isp_vdev->dev, "fail stop streaming: %s %d\n", 608*2ccf48afSBin Du subdev->name, ret); 609*2ccf48afSBin Du } 610*2ccf48afSBin Du 611*2ccf48afSBin Du isp_vdev->stream_started = false; 612*2ccf48afSBin Du isp4sd_pwroff_and_deinit(isp_vdev->isp_sdev); 613*2ccf48afSBin Du 614*2ccf48afSBin Du /* Release all active buffers */ 615*2ccf48afSBin Du isp4vid_capture_return_all_buffers(isp_vdev, VB2_BUF_STATE_ERROR); 616*2ccf48afSBin Du } 617*2ccf48afSBin Du 618*2ccf48afSBin Du static int isp4vid_qops_buf_init(struct vb2_buffer *vb) 619*2ccf48afSBin Du { 620*2ccf48afSBin Du struct isp4vid_capture_buffer *buf = 621*2ccf48afSBin Du container_of(vb, struct isp4vid_capture_buffer, vb2.vb2_buf); 622*2ccf48afSBin Du struct isp4vid_dev *isp_vdev = vb2_get_drv_priv(vb->vb2_queue); 623*2ccf48afSBin Du void *mem_priv = vb->planes[0].mem_priv; 624*2ccf48afSBin Du struct device *dev = isp_vdev->dev; 625*2ccf48afSBin Du u64 gpu_addr; 626*2ccf48afSBin Du void *bo; 627*2ccf48afSBin Du int ret; 628*2ccf48afSBin Du 629*2ccf48afSBin Du if (vb->planes[0].dbuf) { 630*2ccf48afSBin Du buf->dbuf = vb->planes[0].dbuf; 631*2ccf48afSBin Du } else { 632*2ccf48afSBin Du /* 633*2ccf48afSBin Du * HAS_DMA is a Kconfig dependency so CONFIG_HAS_DMA is always 634*2ccf48afSBin Du * defined when this driver is compiled. The #else branch is 635*2ccf48afSBin Du * kept as a safeguard in case the dependency is ever removed. 636*2ccf48afSBin Du */ 637*2ccf48afSBin Du #ifdef CONFIG_HAS_DMA 638*2ccf48afSBin Du buf->dbuf = vb2_vmalloc_memops.get_dmabuf(vb, mem_priv, 0); 639*2ccf48afSBin Du if (IS_ERR_OR_NULL(buf->dbuf)) { 640*2ccf48afSBin Du dev_err(dev, "fail to get dma buf\n"); 641*2ccf48afSBin Du return -EINVAL; 642*2ccf48afSBin Du } 643*2ccf48afSBin Du #else 644*2ccf48afSBin Du dev_err(dev, "get dmabuf fail -- CONFIG_HAS_DMA not defined\n"); 645*2ccf48afSBin Du buf->dbuf = NULL; 646*2ccf48afSBin Du return -EINVAL; 647*2ccf48afSBin Du #endif 648*2ccf48afSBin Du } 649*2ccf48afSBin Du 650*2ccf48afSBin Du /* create isp user BO and obtain gpu_addr */ 651*2ccf48afSBin Du ret = isp_user_buffer_alloc(dev, buf->dbuf, &bo, &gpu_addr); 652*2ccf48afSBin Du if (ret) { 653*2ccf48afSBin Du dev_err(dev, "fail to create isp user BO\n"); 654*2ccf48afSBin Du if (!vb->planes[0].dbuf) { 655*2ccf48afSBin Du dma_buf_put(buf->dbuf); 656*2ccf48afSBin Du buf->dbuf = NULL; 657*2ccf48afSBin Du } 658*2ccf48afSBin Du 659*2ccf48afSBin Du return ret; 660*2ccf48afSBin Du } 661*2ccf48afSBin Du 662*2ccf48afSBin Du buf->bo = bo; 663*2ccf48afSBin Du buf->gpu_addr = gpu_addr; 664*2ccf48afSBin Du return 0; 665*2ccf48afSBin Du } 666*2ccf48afSBin Du 667*2ccf48afSBin Du static void isp4vid_qops_buf_cleanup(struct vb2_buffer *vb) 668*2ccf48afSBin Du { 669*2ccf48afSBin Du struct isp4vid_capture_buffer *buf = 670*2ccf48afSBin Du container_of(vb, struct isp4vid_capture_buffer, vb2.vb2_buf); 671*2ccf48afSBin Du 672*2ccf48afSBin Du if (buf->bo) { 673*2ccf48afSBin Du isp_user_buffer_free(buf->bo); 674*2ccf48afSBin Du buf->bo = NULL; 675*2ccf48afSBin Du } 676*2ccf48afSBin Du 677*2ccf48afSBin Du /* 678*2ccf48afSBin Du * Only put dmabufs we obtained ourselves via get_dmabuf, not ones 679*2ccf48afSBin Du * provided by the framework for DMABUF import 680*2ccf48afSBin Du */ 681*2ccf48afSBin Du if (buf->dbuf && buf->dbuf != vb->planes[0].dbuf) 682*2ccf48afSBin Du dma_buf_put(buf->dbuf); 683*2ccf48afSBin Du 684*2ccf48afSBin Du buf->dbuf = NULL; 685*2ccf48afSBin Du } 686*2ccf48afSBin Du 687*2ccf48afSBin Du static const struct vb2_ops isp4vid_qops = { 688*2ccf48afSBin Du .queue_setup = isp4vid_qops_queue_setup, 689*2ccf48afSBin Du .buf_init = isp4vid_qops_buf_init, 690*2ccf48afSBin Du .buf_cleanup = isp4vid_qops_buf_cleanup, 691*2ccf48afSBin Du .start_streaming = isp4vid_qops_start_streaming, 692*2ccf48afSBin Du .stop_streaming = isp4vid_qops_stop_streaming, 693*2ccf48afSBin Du .buf_queue = isp4vid_qops_buffer_queue, 694*2ccf48afSBin Du }; 695*2ccf48afSBin Du 696*2ccf48afSBin Du int isp4vid_dev_init(struct isp4vid_dev *isp_vdev, struct v4l2_subdev *isp_sd) 697*2ccf48afSBin Du { 698*2ccf48afSBin Du const char *vdev_name = isp4vid_video_dev_name; 699*2ccf48afSBin Du struct v4l2_device *v4l2_dev; 700*2ccf48afSBin Du struct video_device *vdev; 701*2ccf48afSBin Du struct vb2_queue *q; 702*2ccf48afSBin Du int ret; 703*2ccf48afSBin Du 704*2ccf48afSBin Du if (!isp_vdev || !isp_sd || !isp_sd->v4l2_dev) 705*2ccf48afSBin Du return -EINVAL; 706*2ccf48afSBin Du 707*2ccf48afSBin Du v4l2_dev = isp_sd->v4l2_dev; 708*2ccf48afSBin Du vdev = &isp_vdev->vdev; 709*2ccf48afSBin Du 710*2ccf48afSBin Du isp_vdev->isp_sdev = isp_sd; 711*2ccf48afSBin Du isp_vdev->dev = v4l2_dev->dev; 712*2ccf48afSBin Du 713*2ccf48afSBin Du /* Initialize the vb2_queue struct */ 714*2ccf48afSBin Du mutex_init(&isp_vdev->vbq_lock); 715*2ccf48afSBin Du q = &isp_vdev->vbq; 716*2ccf48afSBin Du q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 717*2ccf48afSBin Du q->io_modes = VB2_MMAP | VB2_DMABUF; 718*2ccf48afSBin Du q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 719*2ccf48afSBin Du q->buf_struct_size = sizeof(struct isp4vid_capture_buffer); 720*2ccf48afSBin Du q->min_queued_buffers = 2; 721*2ccf48afSBin Du q->ops = &isp4vid_qops; 722*2ccf48afSBin Du q->drv_priv = isp_vdev; 723*2ccf48afSBin Du q->mem_ops = &vb2_vmalloc_memops; 724*2ccf48afSBin Du q->lock = &isp_vdev->vbq_lock; 725*2ccf48afSBin Du q->dev = v4l2_dev->dev; 726*2ccf48afSBin Du ret = vb2_queue_init(q); 727*2ccf48afSBin Du if (ret) { 728*2ccf48afSBin Du dev_err(v4l2_dev->dev, "vb2_queue_init error:%d\n", ret); 729*2ccf48afSBin Du return ret; 730*2ccf48afSBin Du } 731*2ccf48afSBin Du 732*2ccf48afSBin Du /* Initialize buffer list and its lock */ 733*2ccf48afSBin Du mutex_init(&isp_vdev->buf_list_lock); 734*2ccf48afSBin Du INIT_LIST_HEAD(&isp_vdev->buf_list); 735*2ccf48afSBin Du 736*2ccf48afSBin Du /* Set default frame format */ 737*2ccf48afSBin Du isp_vdev->format = isp4vid_fmt_default; 738*2ccf48afSBin Du isp_vdev->timeperframe = ISP4VID_ISP_TPF_DEFAULT; 739*2ccf48afSBin Du v4l2_simplify_fraction(&isp_vdev->timeperframe.numerator, 740*2ccf48afSBin Du &isp_vdev->timeperframe.denominator, 8, 333); 741*2ccf48afSBin Du 742*2ccf48afSBin Du ret = isp4vid_fill_buffer_size(&isp_vdev->format); 743*2ccf48afSBin Du if (ret) { 744*2ccf48afSBin Du dev_err(v4l2_dev->dev, "fail to fill buffer size: %d\n", ret); 745*2ccf48afSBin Du goto err_release_vb2_queue; 746*2ccf48afSBin Du } 747*2ccf48afSBin Du 748*2ccf48afSBin Du ret = isp4vid_set_fmt_2_isp(isp_sd, &isp_vdev->format); 749*2ccf48afSBin Du if (ret) { 750*2ccf48afSBin Du dev_err(v4l2_dev->dev, "fail init format :%d\n", ret); 751*2ccf48afSBin Du goto err_release_vb2_queue; 752*2ccf48afSBin Du } 753*2ccf48afSBin Du 754*2ccf48afSBin Du /* Initialize the video_device struct */ 755*2ccf48afSBin Du isp_vdev->vdev.entity.name = vdev_name; 756*2ccf48afSBin Du isp_vdev->vdev.entity.function = MEDIA_ENT_F_IO_V4L; 757*2ccf48afSBin Du isp_vdev->vdev_pad.flags = MEDIA_PAD_FL_SINK; 758*2ccf48afSBin Du ret = media_entity_pads_init(&isp_vdev->vdev.entity, 1, 759*2ccf48afSBin Du &isp_vdev->vdev_pad); 760*2ccf48afSBin Du 761*2ccf48afSBin Du if (ret) { 762*2ccf48afSBin Du dev_err(v4l2_dev->dev, "init media entity pad fail:%d\n", ret); 763*2ccf48afSBin Du goto err_release_vb2_queue; 764*2ccf48afSBin Du } 765*2ccf48afSBin Du 766*2ccf48afSBin Du vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | 767*2ccf48afSBin Du V4L2_CAP_STREAMING | V4L2_CAP_IO_MC; 768*2ccf48afSBin Du vdev->entity.ops = &isp4vid_vdev_ent_ops; 769*2ccf48afSBin Du vdev->release = video_device_release_empty; 770*2ccf48afSBin Du vdev->fops = &isp4vid_vdev_fops; 771*2ccf48afSBin Du vdev->ioctl_ops = &isp4vid_vdev_ioctl_ops; 772*2ccf48afSBin Du vdev->lock = NULL; 773*2ccf48afSBin Du vdev->queue = q; 774*2ccf48afSBin Du vdev->v4l2_dev = v4l2_dev; 775*2ccf48afSBin Du vdev->vfl_dir = VFL_DIR_RX; 776*2ccf48afSBin Du strscpy(vdev->name, vdev_name, sizeof(vdev->name)); 777*2ccf48afSBin Du video_set_drvdata(vdev, isp_vdev); 778*2ccf48afSBin Du 779*2ccf48afSBin Du ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 780*2ccf48afSBin Du if (ret) { 781*2ccf48afSBin Du dev_err(v4l2_dev->dev, "register video device fail:%d\n", ret); 782*2ccf48afSBin Du goto err_entity_cleanup; 783*2ccf48afSBin Du } 784*2ccf48afSBin Du 785*2ccf48afSBin Du return 0; 786*2ccf48afSBin Du 787*2ccf48afSBin Du err_entity_cleanup: 788*2ccf48afSBin Du media_entity_cleanup(&isp_vdev->vdev.entity); 789*2ccf48afSBin Du err_release_vb2_queue: 790*2ccf48afSBin Du vb2_queue_release(q); 791*2ccf48afSBin Du return ret; 792*2ccf48afSBin Du } 793*2ccf48afSBin Du 794*2ccf48afSBin Du void isp4vid_dev_deinit(struct isp4vid_dev *isp_vdev) 795*2ccf48afSBin Du { 796*2ccf48afSBin Du vb2_video_unregister_device(&isp_vdev->vdev); 797*2ccf48afSBin Du } 798