linux/drivers/media/v4l2-core/v4l2-subdev.c
<<
>>
Prefs
   1/*
   2 * V4L2 sub-device
   3 *
   4 * Copyright (C) 2010 Nokia Corporation
   5 *
   6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
   7 *          Sakari Ailus <sakari.ailus@iki.fi>
   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 as
  11 * 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 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21 */
  22
  23#include <linux/ioctl.h>
  24#include <linux/slab.h>
  25#include <linux/types.h>
  26#include <linux/videodev2.h>
  27#include <linux/export.h>
  28
  29#include <media/v4l2-ctrls.h>
  30#include <media/v4l2-device.h>
  31#include <media/v4l2-ioctl.h>
  32#include <media/v4l2-fh.h>
  33#include <media/v4l2-event.h>
  34
  35static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)
  36{
  37#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
  38        fh->pad = kzalloc(sizeof(*fh->pad) * sd->entity.num_pads, GFP_KERNEL);
  39        if (fh->pad == NULL)
  40                return -ENOMEM;
  41#endif
  42        return 0;
  43}
  44
  45static void subdev_fh_free(struct v4l2_subdev_fh *fh)
  46{
  47#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
  48        kfree(fh->pad);
  49        fh->pad = NULL;
  50#endif
  51}
  52
  53static int subdev_open(struct file *file)
  54{
  55        struct video_device *vdev = video_devdata(file);
  56        struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
  57        struct v4l2_subdev_fh *subdev_fh;
  58#if defined(CONFIG_MEDIA_CONTROLLER)
  59        struct media_entity *entity = NULL;
  60#endif
  61        int ret;
  62
  63        subdev_fh = kzalloc(sizeof(*subdev_fh), GFP_KERNEL);
  64        if (subdev_fh == NULL)
  65                return -ENOMEM;
  66
  67        ret = subdev_fh_init(subdev_fh, sd);
  68        if (ret) {
  69                kfree(subdev_fh);
  70                return ret;
  71        }
  72
  73        v4l2_fh_init(&subdev_fh->vfh, vdev);
  74        v4l2_fh_add(&subdev_fh->vfh);
  75        file->private_data = &subdev_fh->vfh;
  76#if defined(CONFIG_MEDIA_CONTROLLER)
  77        if (sd->v4l2_dev->mdev) {
  78                entity = media_entity_get(&sd->entity);
  79                if (!entity) {
  80                        ret = -EBUSY;
  81                        goto err;
  82                }
  83        }
  84#endif
  85
  86        if (sd->internal_ops && sd->internal_ops->open) {
  87                ret = sd->internal_ops->open(sd, subdev_fh);
  88                if (ret < 0)
  89                        goto err;
  90        }
  91
  92        return 0;
  93
  94err:
  95#if defined(CONFIG_MEDIA_CONTROLLER)
  96        media_entity_put(entity);
  97#endif
  98        v4l2_fh_del(&subdev_fh->vfh);
  99        v4l2_fh_exit(&subdev_fh->vfh);
 100        subdev_fh_free(subdev_fh);
 101        kfree(subdev_fh);
 102
 103        return ret;
 104}
 105
 106static int subdev_close(struct file *file)
 107{
 108        struct video_device *vdev = video_devdata(file);
 109        struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
 110        struct v4l2_fh *vfh = file->private_data;
 111        struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
 112
 113        if (sd->internal_ops && sd->internal_ops->close)
 114                sd->internal_ops->close(sd, subdev_fh);
 115#if defined(CONFIG_MEDIA_CONTROLLER)
 116        if (sd->v4l2_dev->mdev)
 117                media_entity_put(&sd->entity);
 118#endif
 119        v4l2_fh_del(vfh);
 120        v4l2_fh_exit(vfh);
 121        subdev_fh_free(subdev_fh);
 122        kfree(subdev_fh);
 123        file->private_data = NULL;
 124
 125        return 0;
 126}
 127
 128#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 129static int check_format(struct v4l2_subdev *sd,
 130                        struct v4l2_subdev_format *format)
 131{
 132        if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
 133            format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
 134                return -EINVAL;
 135
 136        if (format->pad >= sd->entity.num_pads)
 137                return -EINVAL;
 138
 139        return 0;
 140}
 141
 142static int check_crop(struct v4l2_subdev *sd, struct v4l2_subdev_crop *crop)
 143{
 144        if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
 145            crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
 146                return -EINVAL;
 147
 148        if (crop->pad >= sd->entity.num_pads)
 149                return -EINVAL;
 150
 151        return 0;
 152}
 153
 154static int check_selection(struct v4l2_subdev *sd,
 155                           struct v4l2_subdev_selection *sel)
 156{
 157        if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
 158            sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
 159                return -EINVAL;
 160
 161        if (sel->pad >= sd->entity.num_pads)
 162                return -EINVAL;
 163
 164        return 0;
 165}
 166
 167static int check_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
 168{
 169        if (edid->pad >= sd->entity.num_pads)
 170                return -EINVAL;
 171
 172        if (edid->blocks && edid->edid == NULL)
 173                return -EINVAL;
 174
 175        return 0;
 176}
 177#endif
 178
 179static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 180{
 181        struct video_device *vdev = video_devdata(file);
 182        struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
 183        struct v4l2_fh *vfh = file->private_data;
 184#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 185        struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
 186        int rval;
 187#endif
 188
 189        switch (cmd) {
 190        case VIDIOC_QUERYCTRL:
 191                return v4l2_queryctrl(vfh->ctrl_handler, arg);
 192
 193        case VIDIOC_QUERY_EXT_CTRL:
 194                return v4l2_query_ext_ctrl(vfh->ctrl_handler, arg);
 195
 196        case VIDIOC_QUERYMENU:
 197                return v4l2_querymenu(vfh->ctrl_handler, arg);
 198
 199        case VIDIOC_G_CTRL:
 200                return v4l2_g_ctrl(vfh->ctrl_handler, arg);
 201
 202        case VIDIOC_S_CTRL:
 203                return v4l2_s_ctrl(vfh, vfh->ctrl_handler, arg);
 204
 205        case VIDIOC_G_EXT_CTRLS:
 206                return v4l2_g_ext_ctrls(vfh->ctrl_handler, arg);
 207
 208        case VIDIOC_S_EXT_CTRLS:
 209                return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, arg);
 210
 211        case VIDIOC_TRY_EXT_CTRLS:
 212                return v4l2_try_ext_ctrls(vfh->ctrl_handler, arg);
 213
 214        case VIDIOC_DQEVENT:
 215                if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
 216                        return -ENOIOCTLCMD;
 217
 218                return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK);
 219
 220        case VIDIOC_SUBSCRIBE_EVENT:
 221                return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg);
 222
 223        case VIDIOC_UNSUBSCRIBE_EVENT:
 224                return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg);
 225
 226#ifdef CONFIG_VIDEO_ADV_DEBUG
 227        case VIDIOC_DBG_G_REGISTER:
 228        {
 229                struct v4l2_dbg_register *p = arg;
 230
 231                if (!capable(CAP_SYS_ADMIN))
 232                        return -EPERM;
 233                return v4l2_subdev_call(sd, core, g_register, p);
 234        }
 235        case VIDIOC_DBG_S_REGISTER:
 236        {
 237                struct v4l2_dbg_register *p = arg;
 238
 239                if (!capable(CAP_SYS_ADMIN))
 240                        return -EPERM;
 241                return v4l2_subdev_call(sd, core, s_register, p);
 242        }
 243#endif
 244
 245        case VIDIOC_LOG_STATUS: {
 246                int ret;
 247
 248                pr_info("%s: =================  START STATUS  =================\n",
 249                        sd->name);
 250                ret = v4l2_subdev_call(sd, core, log_status);
 251                pr_info("%s: ==================  END STATUS  ==================\n",
 252                        sd->name);
 253                return ret;
 254        }
 255
 256#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 257        case VIDIOC_SUBDEV_G_FMT: {
 258                struct v4l2_subdev_format *format = arg;
 259
 260                rval = check_format(sd, format);
 261                if (rval)
 262                        return rval;
 263
 264                return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh->pad, format);
 265        }
 266
 267        case VIDIOC_SUBDEV_S_FMT: {
 268                struct v4l2_subdev_format *format = arg;
 269
 270                rval = check_format(sd, format);
 271                if (rval)
 272                        return rval;
 273
 274                return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh->pad, format);
 275        }
 276
 277        case VIDIOC_SUBDEV_G_CROP: {
 278                struct v4l2_subdev_crop *crop = arg;
 279                struct v4l2_subdev_selection sel;
 280
 281                rval = check_crop(sd, crop);
 282                if (rval)
 283                        return rval;
 284
 285                memset(&sel, 0, sizeof(sel));
 286                sel.which = crop->which;
 287                sel.pad = crop->pad;
 288                sel.target = V4L2_SEL_TGT_CROP;
 289
 290                rval = v4l2_subdev_call(
 291                        sd, pad, get_selection, subdev_fh->pad, &sel);
 292
 293                crop->rect = sel.r;
 294
 295                return rval;
 296        }
 297
 298        case VIDIOC_SUBDEV_S_CROP: {
 299                struct v4l2_subdev_crop *crop = arg;
 300                struct v4l2_subdev_selection sel;
 301
 302                rval = check_crop(sd, crop);
 303                if (rval)
 304                        return rval;
 305
 306                memset(&sel, 0, sizeof(sel));
 307                sel.which = crop->which;
 308                sel.pad = crop->pad;
 309                sel.target = V4L2_SEL_TGT_CROP;
 310                sel.r = crop->rect;
 311
 312                rval = v4l2_subdev_call(
 313                        sd, pad, set_selection, subdev_fh->pad, &sel);
 314
 315                crop->rect = sel.r;
 316
 317                return rval;
 318        }
 319
 320        case VIDIOC_SUBDEV_ENUM_MBUS_CODE: {
 321                struct v4l2_subdev_mbus_code_enum *code = arg;
 322
 323                if (code->which != V4L2_SUBDEV_FORMAT_TRY &&
 324                    code->which != V4L2_SUBDEV_FORMAT_ACTIVE)
 325                        return -EINVAL;
 326
 327                if (code->pad >= sd->entity.num_pads)
 328                        return -EINVAL;
 329
 330                return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh->pad,
 331                                        code);
 332        }
 333
 334        case VIDIOC_SUBDEV_ENUM_FRAME_SIZE: {
 335                struct v4l2_subdev_frame_size_enum *fse = arg;
 336
 337                if (fse->which != V4L2_SUBDEV_FORMAT_TRY &&
 338                    fse->which != V4L2_SUBDEV_FORMAT_ACTIVE)
 339                        return -EINVAL;
 340
 341                if (fse->pad >= sd->entity.num_pads)
 342                        return -EINVAL;
 343
 344                return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh->pad,
 345                                        fse);
 346        }
 347
 348        case VIDIOC_SUBDEV_G_FRAME_INTERVAL: {
 349                struct v4l2_subdev_frame_interval *fi = arg;
 350
 351                if (fi->pad >= sd->entity.num_pads)
 352                        return -EINVAL;
 353
 354                return v4l2_subdev_call(sd, video, g_frame_interval, arg);
 355        }
 356
 357        case VIDIOC_SUBDEV_S_FRAME_INTERVAL: {
 358                struct v4l2_subdev_frame_interval *fi = arg;
 359
 360                if (fi->pad >= sd->entity.num_pads)
 361                        return -EINVAL;
 362
 363                return v4l2_subdev_call(sd, video, s_frame_interval, arg);
 364        }
 365
 366        case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: {
 367                struct v4l2_subdev_frame_interval_enum *fie = arg;
 368
 369                if (fie->which != V4L2_SUBDEV_FORMAT_TRY &&
 370                    fie->which != V4L2_SUBDEV_FORMAT_ACTIVE)
 371                        return -EINVAL;
 372
 373                if (fie->pad >= sd->entity.num_pads)
 374                        return -EINVAL;
 375
 376                return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh->pad,
 377                                        fie);
 378        }
 379
 380        case VIDIOC_SUBDEV_G_SELECTION: {
 381                struct v4l2_subdev_selection *sel = arg;
 382
 383                rval = check_selection(sd, sel);
 384                if (rval)
 385                        return rval;
 386
 387                return v4l2_subdev_call(
 388                        sd, pad, get_selection, subdev_fh->pad, sel);
 389        }
 390
 391        case VIDIOC_SUBDEV_S_SELECTION: {
 392                struct v4l2_subdev_selection *sel = arg;
 393
 394                rval = check_selection(sd, sel);
 395                if (rval)
 396                        return rval;
 397
 398                return v4l2_subdev_call(
 399                        sd, pad, set_selection, subdev_fh->pad, sel);
 400        }
 401
 402        case VIDIOC_G_EDID: {
 403                struct v4l2_subdev_edid *edid = arg;
 404
 405                rval = check_edid(sd, edid);
 406                if (rval)
 407                        return rval;
 408
 409                return v4l2_subdev_call(sd, pad, get_edid, edid);
 410        }
 411
 412        case VIDIOC_S_EDID: {
 413                struct v4l2_subdev_edid *edid = arg;
 414
 415                rval = check_edid(sd, edid);
 416                if (rval)
 417                        return rval;
 418
 419                return v4l2_subdev_call(sd, pad, set_edid, edid);
 420        }
 421
 422        case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
 423                struct v4l2_dv_timings_cap *cap = arg;
 424
 425                if (cap->pad >= sd->entity.num_pads)
 426                        return -EINVAL;
 427
 428                return v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
 429        }
 430
 431        case VIDIOC_SUBDEV_ENUM_DV_TIMINGS: {
 432                struct v4l2_enum_dv_timings *dvt = arg;
 433
 434                if (dvt->pad >= sd->entity.num_pads)
 435                        return -EINVAL;
 436
 437                return v4l2_subdev_call(sd, pad, enum_dv_timings, dvt);
 438        }
 439
 440        case VIDIOC_SUBDEV_QUERY_DV_TIMINGS:
 441                return v4l2_subdev_call(sd, video, query_dv_timings, arg);
 442
 443        case VIDIOC_SUBDEV_G_DV_TIMINGS:
 444                return v4l2_subdev_call(sd, video, g_dv_timings, arg);
 445
 446        case VIDIOC_SUBDEV_S_DV_TIMINGS:
 447                return v4l2_subdev_call(sd, video, s_dv_timings, arg);
 448#endif
 449        default:
 450                return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
 451        }
 452
 453        return 0;
 454}
 455
 456static long subdev_ioctl(struct file *file, unsigned int cmd,
 457        unsigned long arg)
 458{
 459        return video_usercopy(file, cmd, arg, subdev_do_ioctl);
 460}
 461
 462#ifdef CONFIG_COMPAT
 463static long subdev_compat_ioctl32(struct file *file, unsigned int cmd,
 464        unsigned long arg)
 465{
 466        struct video_device *vdev = video_devdata(file);
 467        struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
 468
 469        return v4l2_subdev_call(sd, core, compat_ioctl32, cmd, arg);
 470}
 471#endif
 472
 473static unsigned int subdev_poll(struct file *file, poll_table *wait)
 474{
 475        struct video_device *vdev = video_devdata(file);
 476        struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
 477        struct v4l2_fh *fh = file->private_data;
 478
 479        if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
 480                return POLLERR;
 481
 482        poll_wait(file, &fh->wait, wait);
 483
 484        if (v4l2_event_pending(fh))
 485                return POLLPRI;
 486
 487        return 0;
 488}
 489
 490const struct v4l2_file_operations v4l2_subdev_fops = {
 491        .owner = THIS_MODULE,
 492        .open = subdev_open,
 493        .unlocked_ioctl = subdev_ioctl,
 494#ifdef CONFIG_COMPAT
 495        .compat_ioctl32 = subdev_compat_ioctl32,
 496#endif
 497        .release = subdev_close,
 498        .poll = subdev_poll,
 499};
 500
 501#ifdef CONFIG_MEDIA_CONTROLLER
 502int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
 503                                      struct media_link *link,
 504                                      struct v4l2_subdev_format *source_fmt,
 505                                      struct v4l2_subdev_format *sink_fmt)
 506{
 507        /* The width, height and code must match. */
 508        if (source_fmt->format.width != sink_fmt->format.width
 509            || source_fmt->format.height != sink_fmt->format.height
 510            || source_fmt->format.code != sink_fmt->format.code)
 511                return -EINVAL;
 512
 513        /* The field order must match, or the sink field order must be NONE
 514         * to support interlaced hardware connected to bridges that support
 515         * progressive formats only.
 516         */
 517        if (source_fmt->format.field != sink_fmt->format.field &&
 518            sink_fmt->format.field != V4L2_FIELD_NONE)
 519                return -EINVAL;
 520
 521        return 0;
 522}
 523EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default);
 524
 525static int
 526v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 527                                     struct v4l2_subdev_format *fmt)
 528{
 529        if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
 530                struct v4l2_subdev *sd =
 531                        media_entity_to_v4l2_subdev(pad->entity);
 532
 533                fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
 534                fmt->pad = pad->index;
 535                return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
 536        }
 537
 538        WARN(pad->entity->type != MEDIA_ENT_T_DEVNODE_V4L,
 539             "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
 540             pad->entity->type, pad->entity->name);
 541
 542        return -EINVAL;
 543}
 544
 545int v4l2_subdev_link_validate(struct media_link *link)
 546{
 547        struct v4l2_subdev *sink;
 548        struct v4l2_subdev_format sink_fmt, source_fmt;
 549        int rval;
 550
 551        rval = v4l2_subdev_link_validate_get_format(
 552                link->source, &source_fmt);
 553        if (rval < 0)
 554                return 0;
 555
 556        rval = v4l2_subdev_link_validate_get_format(
 557                link->sink, &sink_fmt);
 558        if (rval < 0)
 559                return 0;
 560
 561        sink = media_entity_to_v4l2_subdev(link->sink->entity);
 562
 563        rval = v4l2_subdev_call(sink, pad, link_validate, link,
 564                                &source_fmt, &sink_fmt);
 565        if (rval != -ENOIOCTLCMD)
 566                return rval;
 567
 568        return v4l2_subdev_link_validate_default(
 569                sink, link, &source_fmt, &sink_fmt);
 570}
 571EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate);
 572#endif /* CONFIG_MEDIA_CONTROLLER */
 573
 574void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
 575{
 576        INIT_LIST_HEAD(&sd->list);
 577        BUG_ON(!ops);
 578        sd->ops = ops;
 579        sd->v4l2_dev = NULL;
 580        sd->flags = 0;
 581        sd->name[0] = '\0';
 582        sd->grp_id = 0;
 583        sd->dev_priv = NULL;
 584        sd->host_priv = NULL;
 585#if defined(CONFIG_MEDIA_CONTROLLER)
 586        sd->entity.name = sd->name;
 587        sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
 588#endif
 589}
 590EXPORT_SYMBOL(v4l2_subdev_init);
 591
 592/**
 593 * v4l2_subdev_notify_event() - Delivers event notification for subdevice
 594 * @sd: The subdev for which to deliver the event
 595 * @ev: The event to deliver
 596 *
 597 * Will deliver the specified event to all userspace event listeners which are
 598 * subscribed to the v42l subdev event queue as well as to the bridge driver
 599 * using the notify callback. The notification type for the notify callback
 600 * will be V4L2_DEVICE_NOTIFY_EVENT.
 601 */
 602void v4l2_subdev_notify_event(struct v4l2_subdev *sd,
 603                              const struct v4l2_event *ev)
 604{
 605        v4l2_event_queue(sd->devnode, ev);
 606        v4l2_subdev_notify(sd, V4L2_DEVICE_NOTIFY_EVENT, (void *)ev);
 607}
 608EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event);
 609