linux/drivers/media/platform/qcom/camss-8x16/camss-video.c
<<
>>
Prefs
   1/*
   2 * camss-video.c
   3 *
   4 * Qualcomm MSM Camera Subsystem - V4L2 device node
   5 *
   6 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
   7 * Copyright (C) 2015-2017 Linaro Ltd.
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 and
  11 * only version 2 as published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 */
  18#include <linux/slab.h>
  19#include <media/media-entity.h>
  20#include <media/v4l2-dev.h>
  21#include <media/v4l2-device.h>
  22#include <media/v4l2-ioctl.h>
  23#include <media/v4l2-mc.h>
  24#include <media/videobuf-core.h>
  25#include <media/videobuf2-dma-sg.h>
  26
  27#include "camss-video.h"
  28#include "camss.h"
  29
  30struct fract {
  31        u8 numerator;
  32        u8 denominator;
  33};
  34
  35/*
  36 * struct camss_format_info - ISP media bus format information
  37 * @code: V4L2 media bus format code
  38 * @pixelformat: V4L2 pixel format FCC identifier
  39 * @planes: Number of planes
  40 * @hsub: Horizontal subsampling (for each plane)
  41 * @vsub: Vertical subsampling (for each plane)
  42 * @bpp: Bits per pixel when stored in memory (for each plane)
  43 */
  44struct camss_format_info {
  45        u32 code;
  46        u32 pixelformat;
  47        u8 planes;
  48        struct fract hsub[3];
  49        struct fract vsub[3];
  50        unsigned int bpp[3];
  51};
  52
  53static const struct camss_format_info formats_rdi[] = {
  54        { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1,
  55          { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  56        { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1,
  57          { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  58        { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1,
  59          { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  60        { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_YVYU, 1,
  61          { { 1, 1 } }, { { 1, 1 } }, { 16 } },
  62        { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1,
  63          { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  64        { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1,
  65          { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  66        { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1,
  67          { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  68        { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1,
  69          { { 1, 1 } }, { { 1, 1 } }, { 8 } },
  70        { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10P, 1,
  71          { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  72        { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10P, 1,
  73          { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  74        { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10P, 1,
  75          { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  76        { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10P, 1,
  77          { { 1, 1 } }, { { 1, 1 } }, { 10 } },
  78        { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12P, 1,
  79          { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  80        { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12P, 1,
  81          { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  82        { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12P, 1,
  83          { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  84        { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12P, 1,
  85          { { 1, 1 } }, { { 1, 1 } }, { 12 } },
  86};
  87
  88static const struct camss_format_info formats_pix[] = {
  89        { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  90          { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  91        { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  92          { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  93        { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  94          { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  95        { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV12, 1,
  96          { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  97        { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV21, 1,
  98          { { 1, 1 } }, { { 2, 3 } }, { 8 } },
  99        { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV21, 1,
 100          { { 1, 1 } }, { { 2, 3 } }, { 8 } },
 101        { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV21, 1,
 102          { { 1, 1 } }, { { 2, 3 } }, { 8 } },
 103        { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV21, 1,
 104          { { 1, 1 } }, { { 2, 3 } }, { 8 } },
 105        { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV16, 1,
 106          { { 1, 1 } }, { { 1, 2 } }, { 8 } },
 107        { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV16, 1,
 108          { { 1, 1 } }, { { 1, 2 } }, { 8 } },
 109        { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV16, 1,
 110          { { 1, 1 } }, { { 1, 2 } }, { 8 } },
 111        { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV16, 1,
 112          { { 1, 1 } }, { { 1, 2 } }, { 8 } },
 113        { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV61, 1,
 114          { { 1, 1 } }, { { 1, 2 } }, { 8 } },
 115        { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV61, 1,
 116          { { 1, 1 } }, { { 1, 2 } }, { 8 } },
 117        { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV61, 1,
 118          { { 1, 1 } }, { { 1, 2 } }, { 8 } },
 119        { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV61, 1,
 120          { { 1, 1 } }, { { 1, 2 } }, { 8 } },
 121};
 122
 123/* -----------------------------------------------------------------------------
 124 * Helper functions
 125 */
 126
 127static int video_find_format(u32 code, u32 pixelformat,
 128                             const struct camss_format_info *formats,
 129                             unsigned int nformats)
 130{
 131        int i;
 132
 133        for (i = 0; i < nformats; i++) {
 134                if (formats[i].code == code &&
 135                    formats[i].pixelformat == pixelformat)
 136                        return i;
 137        }
 138
 139        for (i = 0; i < nformats; i++)
 140                if (formats[i].code == code)
 141                        return i;
 142
 143        WARN_ON(1);
 144
 145        return -EINVAL;
 146}
 147
 148/*
 149 * video_mbus_to_pix_mp - Convert v4l2_mbus_framefmt to v4l2_pix_format_mplane
 150 * @mbus: v4l2_mbus_framefmt format (input)
 151 * @pix: v4l2_pix_format_mplane format (output)
 152 * @f: a pointer to formats array element to be used for the conversion
 153 * @alignment: bytesperline alignment value
 154 *
 155 * Fill the output pix structure with information from the input mbus format.
 156 *
 157 * Return 0 on success or a negative error code otherwise
 158 */
 159static int video_mbus_to_pix_mp(const struct v4l2_mbus_framefmt *mbus,
 160                                struct v4l2_pix_format_mplane *pix,
 161                                const struct camss_format_info *f,
 162                                unsigned int alignment)
 163{
 164        unsigned int i;
 165        u32 bytesperline;
 166
 167        memset(pix, 0, sizeof(*pix));
 168        v4l2_fill_pix_format_mplane(pix, mbus);
 169        pix->pixelformat = f->pixelformat;
 170        pix->num_planes = f->planes;
 171        for (i = 0; i < pix->num_planes; i++) {
 172                bytesperline = pix->width / f->hsub[i].numerator *
 173                        f->hsub[i].denominator * f->bpp[i] / 8;
 174                bytesperline = ALIGN(bytesperline, alignment);
 175                pix->plane_fmt[i].bytesperline = bytesperline;
 176                pix->plane_fmt[i].sizeimage = pix->height /
 177                                f->vsub[i].numerator * f->vsub[i].denominator *
 178                                bytesperline;
 179        }
 180
 181        return 0;
 182}
 183
 184static struct v4l2_subdev *video_remote_subdev(struct camss_video *video,
 185                                               u32 *pad)
 186{
 187        struct media_pad *remote;
 188
 189        remote = media_entity_remote_pad(&video->pad);
 190
 191        if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 192                return NULL;
 193
 194        if (pad)
 195                *pad = remote->index;
 196
 197        return media_entity_to_v4l2_subdev(remote->entity);
 198}
 199
 200static int video_get_subdev_format(struct camss_video *video,
 201                                   struct v4l2_format *format)
 202{
 203        struct v4l2_subdev_format fmt;
 204        struct v4l2_subdev *subdev;
 205        u32 pad;
 206        int ret;
 207
 208        subdev = video_remote_subdev(video, &pad);
 209        if (subdev == NULL)
 210                return -EPIPE;
 211
 212        fmt.pad = pad;
 213        fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 214
 215        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
 216        if (ret)
 217                return ret;
 218
 219        ret = video_find_format(fmt.format.code,
 220                                format->fmt.pix_mp.pixelformat,
 221                                video->formats, video->nformats);
 222        if (ret < 0)
 223                return ret;
 224
 225        format->type = video->type;
 226
 227        return video_mbus_to_pix_mp(&fmt.format, &format->fmt.pix_mp,
 228                                    &video->formats[ret], video->bpl_alignment);
 229}
 230
 231/* -----------------------------------------------------------------------------
 232 * Video queue operations
 233 */
 234
 235static int video_queue_setup(struct vb2_queue *q,
 236        unsigned int *num_buffers, unsigned int *num_planes,
 237        unsigned int sizes[], struct device *alloc_devs[])
 238{
 239        struct camss_video *video = vb2_get_drv_priv(q);
 240        const struct v4l2_pix_format_mplane *format =
 241                                                &video->active_fmt.fmt.pix_mp;
 242        unsigned int i;
 243
 244        if (*num_planes) {
 245                if (*num_planes != format->num_planes)
 246                        return -EINVAL;
 247
 248                for (i = 0; i < *num_planes; i++)
 249                        if (sizes[i] < format->plane_fmt[i].sizeimage)
 250                                return -EINVAL;
 251
 252                return 0;
 253        }
 254
 255        *num_planes = format->num_planes;
 256
 257        for (i = 0; i < *num_planes; i++)
 258                sizes[i] = format->plane_fmt[i].sizeimage;
 259
 260        return 0;
 261}
 262
 263static int video_buf_init(struct vb2_buffer *vb)
 264{
 265        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 266        struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue);
 267        struct camss_buffer *buffer = container_of(vbuf, struct camss_buffer,
 268                                                   vb);
 269        const struct v4l2_pix_format_mplane *format =
 270                                                &video->active_fmt.fmt.pix_mp;
 271        struct sg_table *sgt;
 272        unsigned int i;
 273
 274        for (i = 0; i < format->num_planes; i++) {
 275                sgt = vb2_dma_sg_plane_desc(vb, i);
 276                if (!sgt)
 277                        return -EFAULT;
 278
 279                buffer->addr[i] = sg_dma_address(sgt->sgl);
 280        }
 281
 282        if (format->pixelformat == V4L2_PIX_FMT_NV12 ||
 283                        format->pixelformat == V4L2_PIX_FMT_NV21 ||
 284                        format->pixelformat == V4L2_PIX_FMT_NV16 ||
 285                        format->pixelformat == V4L2_PIX_FMT_NV61)
 286                buffer->addr[1] = buffer->addr[0] +
 287                                format->plane_fmt[0].bytesperline *
 288                                format->height;
 289
 290        return 0;
 291}
 292
 293static int video_buf_prepare(struct vb2_buffer *vb)
 294{
 295        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 296        struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue);
 297        const struct v4l2_pix_format_mplane *format =
 298                                                &video->active_fmt.fmt.pix_mp;
 299        unsigned int i;
 300
 301        for (i = 0; i < format->num_planes; i++) {
 302                if (format->plane_fmt[i].sizeimage > vb2_plane_size(vb, i))
 303                        return -EINVAL;
 304
 305                vb2_set_plane_payload(vb, i, format->plane_fmt[i].sizeimage);
 306        }
 307
 308        vbuf->field = V4L2_FIELD_NONE;
 309
 310        return 0;
 311}
 312
 313static void video_buf_queue(struct vb2_buffer *vb)
 314{
 315        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 316        struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue);
 317        struct camss_buffer *buffer = container_of(vbuf, struct camss_buffer,
 318                                                   vb);
 319
 320        video->ops->queue_buffer(video, buffer);
 321}
 322
 323static int video_check_format(struct camss_video *video)
 324{
 325        struct v4l2_pix_format_mplane *pix = &video->active_fmt.fmt.pix_mp;
 326        struct v4l2_format format;
 327        struct v4l2_pix_format_mplane *sd_pix = &format.fmt.pix_mp;
 328        int ret;
 329
 330        sd_pix->pixelformat = pix->pixelformat;
 331        ret = video_get_subdev_format(video, &format);
 332        if (ret < 0)
 333                return ret;
 334
 335        if (pix->pixelformat != sd_pix->pixelformat ||
 336            pix->height != sd_pix->height ||
 337            pix->width != sd_pix->width ||
 338            pix->num_planes != sd_pix->num_planes ||
 339            pix->field != format.fmt.pix_mp.field)
 340                return -EPIPE;
 341
 342        return 0;
 343}
 344
 345static int video_start_streaming(struct vb2_queue *q, unsigned int count)
 346{
 347        struct camss_video *video = vb2_get_drv_priv(q);
 348        struct video_device *vdev = &video->vdev;
 349        struct media_entity *entity;
 350        struct media_pad *pad;
 351        struct v4l2_subdev *subdev;
 352        int ret;
 353
 354        ret = media_pipeline_start(&vdev->entity, &video->pipe);
 355        if (ret < 0)
 356                return ret;
 357
 358        ret = video_check_format(video);
 359        if (ret < 0)
 360                goto error;
 361
 362        entity = &vdev->entity;
 363        while (1) {
 364                pad = &entity->pads[0];
 365                if (!(pad->flags & MEDIA_PAD_FL_SINK))
 366                        break;
 367
 368                pad = media_entity_remote_pad(pad);
 369                if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 370                        break;
 371
 372                entity = pad->entity;
 373                subdev = media_entity_to_v4l2_subdev(entity);
 374
 375                ret = v4l2_subdev_call(subdev, video, s_stream, 1);
 376                if (ret < 0 && ret != -ENOIOCTLCMD)
 377                        goto error;
 378        }
 379
 380        return 0;
 381
 382error:
 383        media_pipeline_stop(&vdev->entity);
 384
 385        video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED);
 386
 387        return ret;
 388}
 389
 390static void video_stop_streaming(struct vb2_queue *q)
 391{
 392        struct camss_video *video = vb2_get_drv_priv(q);
 393        struct video_device *vdev = &video->vdev;
 394        struct media_entity *entity;
 395        struct media_pad *pad;
 396        struct v4l2_subdev *subdev;
 397
 398        entity = &vdev->entity;
 399        while (1) {
 400                pad = &entity->pads[0];
 401                if (!(pad->flags & MEDIA_PAD_FL_SINK))
 402                        break;
 403
 404                pad = media_entity_remote_pad(pad);
 405                if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 406                        break;
 407
 408                entity = pad->entity;
 409                subdev = media_entity_to_v4l2_subdev(entity);
 410
 411                v4l2_subdev_call(subdev, video, s_stream, 0);
 412        }
 413
 414        media_pipeline_stop(&vdev->entity);
 415
 416        video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR);
 417}
 418
 419static const struct vb2_ops msm_video_vb2_q_ops = {
 420        .queue_setup     = video_queue_setup,
 421        .wait_prepare    = vb2_ops_wait_prepare,
 422        .wait_finish     = vb2_ops_wait_finish,
 423        .buf_init        = video_buf_init,
 424        .buf_prepare     = video_buf_prepare,
 425        .buf_queue       = video_buf_queue,
 426        .start_streaming = video_start_streaming,
 427        .stop_streaming  = video_stop_streaming,
 428};
 429
 430/* -----------------------------------------------------------------------------
 431 * V4L2 ioctls
 432 */
 433
 434static int video_querycap(struct file *file, void *fh,
 435                          struct v4l2_capability *cap)
 436{
 437        struct camss_video *video = video_drvdata(file);
 438
 439        strlcpy(cap->driver, "qcom-camss", sizeof(cap->driver));
 440        strlcpy(cap->card, "Qualcomm Camera Subsystem", sizeof(cap->card));
 441        snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
 442                 dev_name(video->camss->dev));
 443
 444        return 0;
 445}
 446
 447static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
 448{
 449        struct camss_video *video = video_drvdata(file);
 450        int i, j, k;
 451
 452        if (f->type != video->type)
 453                return -EINVAL;
 454
 455        if (f->index >= video->nformats)
 456                return -EINVAL;
 457
 458        /* find index "i" of "k"th unique pixelformat in formats array */
 459        k = -1;
 460        for (i = 0; i < video->nformats; i++) {
 461                for (j = 0; j < i; j++) {
 462                        if (video->formats[i].pixelformat ==
 463                                        video->formats[j].pixelformat)
 464                                break;
 465                }
 466
 467                if (j == i)
 468                        k++;
 469
 470                if (k == f->index)
 471                        break;
 472        }
 473
 474        if (k < f->index)
 475                return -EINVAL;
 476
 477        f->pixelformat = video->formats[i].pixelformat;
 478
 479        return 0;
 480}
 481
 482static int video_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
 483{
 484        struct camss_video *video = video_drvdata(file);
 485
 486        *f = video->active_fmt;
 487
 488        return 0;
 489}
 490
 491static int __video_try_fmt(struct camss_video *video, struct v4l2_format *f)
 492{
 493        struct v4l2_pix_format_mplane *pix_mp;
 494        const struct camss_format_info *fi;
 495        struct v4l2_plane_pix_format *p;
 496        u32 bytesperline[3] = { 0 };
 497        u32 sizeimage[3] = { 0 };
 498        u32 width, height;
 499        u32 bpl, lines;
 500        int i, j;
 501
 502        pix_mp = &f->fmt.pix_mp;
 503
 504        if (video->line_based)
 505                for (i = 0; i < pix_mp->num_planes && i < 3; i++) {
 506                        p = &pix_mp->plane_fmt[i];
 507                        bytesperline[i] = clamp_t(u32, p->bytesperline,
 508                                                  1, 65528);
 509                        sizeimage[i] = clamp_t(u32, p->sizeimage,
 510                                               bytesperline[i],
 511                                               bytesperline[i] * 4096);
 512                }
 513
 514        for (j = 0; j < video->nformats; j++)
 515                if (pix_mp->pixelformat == video->formats[j].pixelformat)
 516                        break;
 517
 518        if (j == video->nformats)
 519                j = 0; /* default format */
 520
 521        fi = &video->formats[j];
 522        width = pix_mp->width;
 523        height = pix_mp->height;
 524
 525        memset(pix_mp, 0, sizeof(*pix_mp));
 526
 527        pix_mp->pixelformat = fi->pixelformat;
 528        pix_mp->width = clamp_t(u32, width, 1, 8191);
 529        pix_mp->height = clamp_t(u32, height, 1, 8191);
 530        pix_mp->num_planes = fi->planes;
 531        for (i = 0; i < pix_mp->num_planes; i++) {
 532                bpl = pix_mp->width / fi->hsub[i].numerator *
 533                        fi->hsub[i].denominator * fi->bpp[i] / 8;
 534                bpl = ALIGN(bpl, video->bpl_alignment);
 535                pix_mp->plane_fmt[i].bytesperline = bpl;
 536                pix_mp->plane_fmt[i].sizeimage = pix_mp->height /
 537                        fi->vsub[i].numerator * fi->vsub[i].denominator * bpl;
 538        }
 539
 540        pix_mp->field = V4L2_FIELD_NONE;
 541        pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
 542        pix_mp->flags = 0;
 543        pix_mp->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix_mp->colorspace);
 544        pix_mp->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
 545                                        pix_mp->colorspace, pix_mp->ycbcr_enc);
 546        pix_mp->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix_mp->colorspace);
 547
 548        if (video->line_based)
 549                for (i = 0; i < pix_mp->num_planes; i++) {
 550                        p = &pix_mp->plane_fmt[i];
 551                        p->bytesperline = clamp_t(u32, p->bytesperline,
 552                                                  1, 65528);
 553                        p->sizeimage = clamp_t(u32, p->sizeimage,
 554                                               p->bytesperline,
 555                                               p->bytesperline * 4096);
 556                        lines = p->sizeimage / p->bytesperline;
 557
 558                        if (p->bytesperline < bytesperline[i])
 559                                p->bytesperline = ALIGN(bytesperline[i], 8);
 560
 561                        if (p->sizeimage < p->bytesperline * lines)
 562                                p->sizeimage = p->bytesperline * lines;
 563
 564                        if (p->sizeimage < sizeimage[i])
 565                                p->sizeimage = sizeimage[i];
 566                }
 567
 568        return 0;
 569}
 570
 571static int video_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
 572{
 573        struct camss_video *video = video_drvdata(file);
 574
 575        return __video_try_fmt(video, f);
 576}
 577
 578static int video_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
 579{
 580        struct camss_video *video = video_drvdata(file);
 581        int ret;
 582
 583        if (vb2_is_busy(&video->vb2_q))
 584                return -EBUSY;
 585
 586        ret = __video_try_fmt(video, f);
 587        if (ret < 0)
 588                return ret;
 589
 590        video->active_fmt = *f;
 591
 592        return 0;
 593}
 594
 595static int video_enum_input(struct file *file, void *fh,
 596                            struct v4l2_input *input)
 597{
 598        if (input->index > 0)
 599                return -EINVAL;
 600
 601        strlcpy(input->name, "camera", sizeof(input->name));
 602        input->type = V4L2_INPUT_TYPE_CAMERA;
 603
 604        return 0;
 605}
 606
 607static int video_g_input(struct file *file, void *fh, unsigned int *input)
 608{
 609        *input = 0;
 610
 611        return 0;
 612}
 613
 614static int video_s_input(struct file *file, void *fh, unsigned int input)
 615{
 616        return input == 0 ? 0 : -EINVAL;
 617}
 618
 619static const struct v4l2_ioctl_ops msm_vid_ioctl_ops = {
 620        .vidioc_querycap                = video_querycap,
 621        .vidioc_enum_fmt_vid_cap_mplane = video_enum_fmt,
 622        .vidioc_g_fmt_vid_cap_mplane    = video_g_fmt,
 623        .vidioc_s_fmt_vid_cap_mplane    = video_s_fmt,
 624        .vidioc_try_fmt_vid_cap_mplane  = video_try_fmt,
 625        .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
 626        .vidioc_querybuf                = vb2_ioctl_querybuf,
 627        .vidioc_qbuf                    = vb2_ioctl_qbuf,
 628        .vidioc_expbuf                  = vb2_ioctl_expbuf,
 629        .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
 630        .vidioc_create_bufs             = vb2_ioctl_create_bufs,
 631        .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
 632        .vidioc_streamon                = vb2_ioctl_streamon,
 633        .vidioc_streamoff               = vb2_ioctl_streamoff,
 634        .vidioc_enum_input              = video_enum_input,
 635        .vidioc_g_input                 = video_g_input,
 636        .vidioc_s_input                 = video_s_input,
 637};
 638
 639/* -----------------------------------------------------------------------------
 640 * V4L2 file operations
 641 */
 642
 643static int video_open(struct file *file)
 644{
 645        struct video_device *vdev = video_devdata(file);
 646        struct camss_video *video = video_drvdata(file);
 647        struct v4l2_fh *vfh;
 648        int ret;
 649
 650        mutex_lock(&video->lock);
 651
 652        vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
 653        if (vfh == NULL) {
 654                ret = -ENOMEM;
 655                goto error_alloc;
 656        }
 657
 658        v4l2_fh_init(vfh, vdev);
 659        v4l2_fh_add(vfh);
 660
 661        file->private_data = vfh;
 662
 663        ret = v4l2_pipeline_pm_use(&vdev->entity, 1);
 664        if (ret < 0) {
 665                dev_err(video->camss->dev, "Failed to power up pipeline: %d\n",
 666                        ret);
 667                goto error_pm_use;
 668        }
 669
 670        mutex_unlock(&video->lock);
 671
 672        return 0;
 673
 674error_pm_use:
 675        v4l2_fh_release(file);
 676
 677error_alloc:
 678        mutex_unlock(&video->lock);
 679
 680        return ret;
 681}
 682
 683static int video_release(struct file *file)
 684{
 685        struct video_device *vdev = video_devdata(file);
 686
 687        vb2_fop_release(file);
 688
 689        v4l2_pipeline_pm_use(&vdev->entity, 0);
 690
 691        file->private_data = NULL;
 692
 693        return 0;
 694}
 695
 696static const struct v4l2_file_operations msm_vid_fops = {
 697        .owner          = THIS_MODULE,
 698        .unlocked_ioctl = video_ioctl2,
 699        .open           = video_open,
 700        .release        = video_release,
 701        .poll           = vb2_fop_poll,
 702        .mmap           = vb2_fop_mmap,
 703        .read           = vb2_fop_read,
 704};
 705
 706/* -----------------------------------------------------------------------------
 707 * CAMSS video core
 708 */
 709
 710static void msm_video_release(struct video_device *vdev)
 711{
 712        struct camss_video *video = video_get_drvdata(vdev);
 713
 714        media_entity_cleanup(&vdev->entity);
 715
 716        mutex_destroy(&video->q_lock);
 717        mutex_destroy(&video->lock);
 718
 719        if (atomic_dec_and_test(&video->camss->ref_count))
 720                camss_delete(video->camss);
 721}
 722
 723/*
 724 * msm_video_init_format - Helper function to initialize format
 725 * @video: struct camss_video
 726 *
 727 * Initialize pad format with default value.
 728 *
 729 * Return 0 on success or a negative error code otherwise
 730 */
 731static int msm_video_init_format(struct camss_video *video)
 732{
 733        int ret;
 734        struct v4l2_format format = {
 735                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
 736                .fmt.pix_mp = {
 737                        .width = 1920,
 738                        .height = 1080,
 739                        .pixelformat = video->formats[0].pixelformat,
 740                },
 741        };
 742
 743        ret = __video_try_fmt(video, &format);
 744        if (ret < 0)
 745                return ret;
 746
 747        video->active_fmt = format;
 748
 749        return 0;
 750}
 751
 752/*
 753 * msm_video_register - Register a video device node
 754 * @video: struct camss_video
 755 * @v4l2_dev: V4L2 device
 756 * @name: name to be used for the video device node
 757 *
 758 * Initialize and register a video device node to a V4L2 device. Also
 759 * initialize the vb2 queue.
 760 *
 761 * Return 0 on success or a negative error code otherwise
 762 */
 763
 764int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev,
 765                       const char *name, int is_pix)
 766{
 767        struct media_pad *pad = &video->pad;
 768        struct video_device *vdev;
 769        struct vb2_queue *q;
 770        int ret;
 771
 772        vdev = &video->vdev;
 773
 774        mutex_init(&video->q_lock);
 775
 776        q = &video->vb2_q;
 777        q->drv_priv = video;
 778        q->mem_ops = &vb2_dma_sg_memops;
 779        q->ops = &msm_video_vb2_q_ops;
 780        q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 781        q->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ;
 782        q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 783        q->buf_struct_size = sizeof(struct camss_buffer);
 784        q->dev = video->camss->dev;
 785        q->lock = &video->q_lock;
 786        ret = vb2_queue_init(q);
 787        if (ret < 0) {
 788                dev_err(v4l2_dev->dev, "Failed to init vb2 queue: %d\n", ret);
 789                goto error_vb2_init;
 790        }
 791
 792        pad->flags = MEDIA_PAD_FL_SINK;
 793        ret = media_entity_pads_init(&vdev->entity, 1, pad);
 794        if (ret < 0) {
 795                dev_err(v4l2_dev->dev, "Failed to init video entity: %d\n",
 796                        ret);
 797                goto error_media_init;
 798        }
 799
 800        mutex_init(&video->lock);
 801
 802        video->formats = formats_rdi;
 803        video->nformats = ARRAY_SIZE(formats_rdi);
 804        if (is_pix) {
 805                video->formats = formats_pix;
 806                video->nformats = ARRAY_SIZE(formats_pix);
 807        }
 808
 809        ret = msm_video_init_format(video);
 810        if (ret < 0) {
 811                dev_err(v4l2_dev->dev, "Failed to init format: %d\n", ret);
 812                goto error_video_register;
 813        }
 814
 815        vdev->fops = &msm_vid_fops;
 816        vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING |
 817                                                        V4L2_CAP_READWRITE;
 818        vdev->ioctl_ops = &msm_vid_ioctl_ops;
 819        vdev->release = msm_video_release;
 820        vdev->v4l2_dev = v4l2_dev;
 821        vdev->vfl_dir = VFL_DIR_RX;
 822        vdev->queue = &video->vb2_q;
 823        vdev->lock = &video->lock;
 824        strlcpy(vdev->name, name, sizeof(vdev->name));
 825
 826        ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
 827        if (ret < 0) {
 828                dev_err(v4l2_dev->dev, "Failed to register video device: %d\n",
 829                        ret);
 830                goto error_video_register;
 831        }
 832
 833        video_set_drvdata(vdev, video);
 834        atomic_inc(&video->camss->ref_count);
 835
 836        return 0;
 837
 838error_video_register:
 839        media_entity_cleanup(&vdev->entity);
 840        mutex_destroy(&video->lock);
 841error_media_init:
 842        vb2_queue_release(&video->vb2_q);
 843error_vb2_init:
 844        mutex_destroy(&video->q_lock);
 845
 846        return ret;
 847}
 848
 849void msm_video_stop_streaming(struct camss_video *video)
 850{
 851        if (vb2_is_streaming(&video->vb2_q))
 852                vb2_queue_release(&video->vb2_q);
 853}
 854
 855void msm_video_unregister(struct camss_video *video)
 856{
 857        atomic_inc(&video->camss->ref_count);
 858        video_unregister_device(&video->vdev);
 859        atomic_dec(&video->camss->ref_count);
 860}
 861