Merge branch 'rmobile-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal...
[pandora-kernel.git] / include / media / v4l2-subdev.h
index daf1e57..1562c4f 100644 (file)
 #ifndef _V4L2_SUBDEV_H
 #define _V4L2_SUBDEV_H
 
+#include <linux/v4l2-subdev.h>
+#include <media/media-entity.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
 #include <media/v4l2-mediabus.h>
 
 /* generic v4l2_device notify callback notification values */
 
 struct v4l2_device;
 struct v4l2_ctrl_handler;
+struct v4l2_event_subscription;
+struct v4l2_fh;
 struct v4l2_subdev;
+struct v4l2_subdev_fh;
 struct tuner_setup;
 
 /* decode_vbi_line */
@@ -160,6 +167,10 @@ struct v4l2_subdev_core_ops {
        int (*s_power)(struct v4l2_subdev *sd, int on);
        int (*interrupt_service_routine)(struct v4l2_subdev *sd,
                                                u32 status, bool *handled);
+       int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+                              struct v4l2_event_subscription *sub);
+       int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+                                struct v4l2_event_subscription *sub);
 };
 
 /* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio.
@@ -257,6 +268,10 @@ struct v4l2_subdev_video_ops {
        int (*s_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop);
        int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
        int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
+       int (*g_frame_interval)(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_frame_interval *interval);
+       int (*s_frame_interval)(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_frame_interval *interval);
        int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);
        int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival);
        int (*enum_dv_presets) (struct v4l2_subdev *sd,
@@ -271,6 +286,8 @@ struct v4l2_subdev_video_ops {
                        struct v4l2_dv_timings *timings);
        int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
                             enum v4l2_mbus_pixelcode *code);
+       int (*enum_mbus_fsizes)(struct v4l2_subdev *sd,
+                            struct v4l2_frmsizeenum *fsize);
        int (*g_mbus_fmt)(struct v4l2_subdev *sd,
                          struct v4l2_mbus_framefmt *fmt);
        int (*try_mbus_fmt)(struct v4l2_subdev *sd,
@@ -324,9 +341,13 @@ struct v4l2_subdev_vbi_ops {
  *                   This is needed for some sensors, which always corrupt
  *                   several top lines of the output image, or which send their
  *                   metadata in them.
+ * @g_skip_frames: number of frames to skip at stream start. This is needed for
+ *                buggy sensors that generate faulty frames when they are
+ *                turned on.
  */
 struct v4l2_subdev_sensor_ops {
        int (*g_skip_top_lines)(struct v4l2_subdev *sd, u32 *lines);
+       int (*g_skip_frames)(struct v4l2_subdev *sd, u32 *frames);
 };
 
 /*
@@ -401,6 +422,25 @@ struct v4l2_subdev_ir_ops {
                                struct v4l2_subdev_ir_parameters *params);
 };
 
+struct v4l2_subdev_pad_ops {
+       int (*enum_mbus_code)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_mbus_code_enum *code);
+       int (*enum_frame_size)(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_frame_size_enum *fse);
+       int (*enum_frame_interval)(struct v4l2_subdev *sd,
+                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_frame_interval_enum *fie);
+       int (*get_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                      struct v4l2_subdev_format *format);
+       int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                      struct v4l2_subdev_format *format);
+       int (*set_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                      struct v4l2_subdev_crop *crop);
+       int (*get_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                      struct v4l2_subdev_crop *crop);
+};
+
 struct v4l2_subdev_ops {
        const struct v4l2_subdev_core_ops       *core;
        const struct v4l2_subdev_tuner_ops      *tuner;
@@ -409,6 +449,7 @@ struct v4l2_subdev_ops {
        const struct v4l2_subdev_vbi_ops        *vbi;
        const struct v4l2_subdev_ir_ops         *ir;
        const struct v4l2_subdev_sensor_ops     *sensor;
+       const struct v4l2_subdev_pad_ops        *pad;
 };
 
 /*
@@ -420,23 +461,36 @@ struct v4l2_subdev_ops {
  *
  * unregistered: called when this subdev is unregistered. When called the
  *     v4l2_dev field is still set to the correct v4l2_device.
+ *
+ * open: called when the subdev device node is opened by an application.
+ *
+ * close: called when the subdev device node is closed.
  */
 struct v4l2_subdev_internal_ops {
        int (*registered)(struct v4l2_subdev *sd);
        void (*unregistered)(struct v4l2_subdev *sd);
+       int (*open)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
+       int (*close)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
 };
 
 #define V4L2_SUBDEV_NAME_SIZE 32
 
 /* Set this flag if this subdev is a i2c device. */
-#define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
+#define V4L2_SUBDEV_FL_IS_I2C                  (1U << 0)
 /* Set this flag if this subdev is a spi device. */
-#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
+#define V4L2_SUBDEV_FL_IS_SPI                  (1U << 1)
+/* Set this flag if this subdev needs a device node. */
+#define V4L2_SUBDEV_FL_HAS_DEVNODE             (1U << 2)
+/* Set this flag if this subdev generates events. */
+#define V4L2_SUBDEV_FL_HAS_EVENTS              (1U << 3)
 
 /* Each instance of a subdev driver should create this struct, either
    stand-alone or embedded in a larger struct.
  */
 struct v4l2_subdev {
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       struct media_entity entity;
+#endif
        struct list_head list;
        struct module *owner;
        u32 flags;
@@ -453,8 +507,47 @@ struct v4l2_subdev {
        /* pointer to private data */
        void *dev_priv;
        void *host_priv;
+       /* subdev device node */
+       struct video_device devnode;
+       /* number of events to be allocated on open */
+       unsigned int nevents;
+};
+
+#define media_entity_to_v4l2_subdev(ent) \
+       container_of(ent, struct v4l2_subdev, entity)
+#define vdev_to_v4l2_subdev(vdev) \
+       container_of(vdev, struct v4l2_subdev, devnode)
+
+/*
+ * Used for storing subdev information per file handle
+ */
+struct v4l2_subdev_fh {
+       struct v4l2_fh vfh;
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+       struct v4l2_mbus_framefmt *try_fmt;
+       struct v4l2_rect *try_crop;
+#endif
 };
 
+#define to_v4l2_subdev_fh(fh)  \
+       container_of(fh, struct v4l2_subdev_fh, vfh)
+
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+static inline struct v4l2_mbus_framefmt *
+v4l2_subdev_get_try_format(struct v4l2_subdev_fh *fh, unsigned int pad)
+{
+       return &fh->try_fmt[pad];
+}
+
+static inline struct v4l2_rect *
+v4l2_subdev_get_try_crop(struct v4l2_subdev_fh *fh, unsigned int pad)
+{
+       return &fh->try_crop[pad];
+}
+#endif
+
+extern const struct v4l2_file_operations v4l2_subdev_fops;
+
 static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)
 {
        sd->dev_priv = p;
@@ -475,20 +568,8 @@ static inline void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)
        return sd->host_priv;
 }
 
-static inline void v4l2_subdev_init(struct v4l2_subdev *sd,
-                                       const struct v4l2_subdev_ops *ops)
-{
-       INIT_LIST_HEAD(&sd->list);
-       /* ops->core MUST be set */
-       BUG_ON(!ops || !ops->core);
-       sd->ops = ops;
-       sd->v4l2_dev = NULL;
-       sd->flags = 0;
-       sd->name[0] = '\0';
-       sd->grp_id = 0;
-       sd->dev_priv = NULL;
-       sd->host_priv = NULL;
-}
+void v4l2_subdev_init(struct v4l2_subdev *sd,
+                     const struct v4l2_subdev_ops *ops);
 
 /* Call an ops of a v4l2_subdev, doing the right checks against
    NULL pointers.