Replace g/s_mbus_fmt ops with the pad level get/set_fmt operations.
Add media entity initalization and set subdev flags so the host driver
creates a v4l-subdev device node for the driver. A mutex is added for
serializing operations on subdevice node. When setting format
is attempted during streaming EBUSY error code will be returned.

Signed-off-by: Sylwester Nawrocki <s.nawro...@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
---
 drivers/media/video/Kconfig       |    2 +-
 drivers/media/video/noon010pc30.c |  130 +++++++++++++++++++++++++------------
 2 files changed, 90 insertions(+), 42 deletions(-)

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 8de3476..b505120 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -746,7 +746,7 @@ config VIDEO_VIA_CAMERA
 
 config VIDEO_NOON010PC30
        tristate "NOON010PC30 CIF camera sensor support"
-       depends on I2C && VIDEO_V4L2
+       depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API
        ---help---
          This driver supports NOON010PC30 CIF camera from Siliconfile
 
diff --git a/drivers/media/video/noon010pc30.c 
b/drivers/media/video/noon010pc30.c
index 50ca097..6920cc4 100644
--- a/drivers/media/video/noon010pc30.c
+++ b/drivers/media/video/noon010pc30.c
@@ -1,7 +1,7 @@
 /*
  * Driver for SiliconFile NOON010PC30 CIF (1/11") Image Sensor with ISP
  *
- * Copyright (C) 2010 Samsung Electronics
+ * Copyright (C) 2010 - 2011 Samsung Electronics
  * Contact: Sylwester Nawrocki, <s.nawro...@samsung.com>
  *
  * Initial register configuration based on a driver authored by
@@ -130,14 +130,19 @@ static const char * const noon010_supply_name[] = {
 #define NOON010_NUM_SUPPLIES ARRAY_SIZE(noon010_supply_name)
 
 struct noon010_info {
+       /* Mutex protecting this data structure and subdev operations */
+       struct mutex lock;
        struct v4l2_subdev sd;
+       struct media_pad pad;
        struct v4l2_ctrl_handler hdl;
        const struct noon010pc30_platform_data *pdata;
        const struct noon010_format *curr_fmt;
        const struct noon010_frmsize *curr_win;
+       struct v4l2_mbus_framefmt format;
        unsigned int hflip:1;
        unsigned int vflip:1;
        unsigned int power:1;
+       unsigned int streaming:1;
        u8 i2c_reg_page;
        struct regulator_bulk_data supply[NOON010_NUM_SUPPLIES];
        u32 gpio_nreset;
@@ -342,7 +347,7 @@ static int noon010_set_params(struct v4l2_subdev *sd)
        struct noon010_info *info = to_noon010(sd);
        int ret;
 
-       if (!info->curr_win)
+       if (!info->curr_win || !info->power)
                return -EINVAL;
 
        ret = cam_i2c_write(sd, VDO_CTL_REG(0), info->curr_win->vid_ctl1);
@@ -354,7 +359,8 @@ static int noon010_set_params(struct v4l2_subdev *sd)
 }
 
 /* Find nearest matching image pixel size. */
-static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf)
+static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf,
+                                 const struct noon010_frmsize **size)
 {
        unsigned int min_err = ~0;
        int i = ARRAY_SIZE(noon010_sizes);
@@ -374,6 +380,8 @@ static int noon010_try_frame_size(struct v4l2_mbus_framefmt 
*mf)
        if (match) {
                mf->width  = match->width;
                mf->height = match->height;
+               if (size)
+                       *size = match;
                return 0;
        }
        return -EINVAL;
@@ -464,36 +472,45 @@ static int noon010_s_ctrl(struct v4l2_ctrl *ctrl)
        }
 }
 
-static int noon010_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-                           enum v4l2_mbus_pixelcode *code)
+static int noon010_enum_mbus_code(struct v4l2_subdev *sd,
+                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_mbus_code_enum *code)
 {
-       if (!code || index >= ARRAY_SIZE(noon010_formats))
+       if (!code || code->index >= ARRAY_SIZE(noon010_formats))
                return -EINVAL;
 
-       *code = noon010_formats[index].code;
+       code->code = noon010_formats[code->index].code;
        return 0;
 }
 
-static int noon010_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+static int noon010_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
 {
        struct noon010_info *info = to_noon010(sd);
-       int ret;
+       struct v4l2_mbus_framefmt *mf;
 
-       if (!mf)
+       if (fmt->pad != 0)
                return -EINVAL;
 
-       if (!info->curr_win || !info->curr_fmt) {
-               ret = noon010_set_params(sd);
-               if (ret)
-                       return ret;
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               if (fh) {
+                       mf = v4l2_subdev_get_try_format(fh, 0);
+                       fmt->format = *mf;
+               }
+               return 0;
        }
+       /* Active format */
+       mf = &fmt->format;
 
+       mutex_lock(&info->lock);
        mf->width       = info->curr_win->width;
        mf->height      = info->curr_win->height;
        mf->code        = info->curr_fmt->code;
        mf->colorspace  = info->curr_fmt->colorspace;
-       mf->field       = V4L2_FIELD_NONE;
+       mutex_unlock(&info->lock);
 
+       mf->field       = V4L2_FIELD_NONE;
+       mf->colorspace  = V4L2_COLORSPACE_JPEG;
        return 0;
 }
 
@@ -503,38 +520,47 @@ static const struct noon010_format *try_fmt(struct 
v4l2_subdev *sd,
 {
        int i = ARRAY_SIZE(noon010_formats);
 
-       noon010_try_frame_size(mf);
-
-       while (i--)
+       while (--i)
                if (mf->code == noon010_formats[i].code)
                        break;
-
        mf->code = noon010_formats[i].code;
 
        return &noon010_formats[i];
 }
 
-static int noon010_try_fmt(struct v4l2_subdev *sd,
-                          struct v4l2_mbus_framefmt *mf)
-{
-       if (!sd || !mf)
-               return -EINVAL;
-
-       try_fmt(sd, mf);
-       return 0;
-}
-
-static int noon010_s_fmt(struct v4l2_subdev *sd,
-                        struct v4l2_mbus_framefmt *mf)
+static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
 {
        struct noon010_info *info = to_noon010(sd);
+       const struct noon010_frmsize *size = NULL;
+       const struct noon010_format *nf;
+       struct v4l2_mbus_framefmt *mf;
+       int ret;
 
-       if (!sd || !mf)
+       if (fmt->pad != 0)
                return -EINVAL;
 
-       info->curr_fmt = try_fmt(sd, mf);
+       nf = try_fmt(sd, &fmt->format);
+       noon010_try_frame_size(&fmt->format, &size);
+       fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
 
-       return noon010_set_params(sd);
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               if (fh) {
+                       mf = v4l2_subdev_get_try_format(fh, 0);
+                       *mf = fmt->format;
+               }
+               return 0;
+       }
+       mutex_lock(&info->lock);
+       if (info->streaming) {
+               ret = -EBUSY;
+       } else {
+               info->curr_fmt = nf;
+               info->curr_win = size;
+               ret = noon010_set_params(sd);
+       }
+       mutex_unlock(&info->lock);
+       return ret;
 }
 
 static int noon010_base_config(struct v4l2_subdev *sd)
@@ -583,6 +609,17 @@ static int noon010_s_power(struct v4l2_subdev *sd, int on)
        return ret;
 }
 
+static int noon010_s_stream(struct v4l2_subdev *sd, int on)
+{
+       struct noon010_info *info = to_noon010(sd);
+
+       mutex_lock(&info->lock);
+       info->streaming = on;
+       mutex_unlock(&info->lock);
+
+       return 0;
+}
+
 static int noon010_g_chip_ident(struct v4l2_subdev *sd,
                                struct v4l2_dbg_chip_ident *chip)
 {
@@ -617,15 +654,19 @@ static const struct v4l2_subdev_core_ops noon010_core_ops 
= {
        .log_status     = noon010_log_status,
 };
 
-static const struct v4l2_subdev_video_ops noon010_video_ops = {
-       .g_mbus_fmt     = noon010_g_fmt,
-       .s_mbus_fmt     = noon010_s_fmt,
-       .try_mbus_fmt   = noon010_try_fmt,
-       .enum_mbus_fmt  = noon010_enum_fmt,
+static struct v4l2_subdev_pad_ops noon010_pad_ops = {
+       .enum_mbus_code = noon010_enum_mbus_code,
+       .get_fmt        = noon010_get_fmt,
+       .set_fmt        = noon010_set_fmt,
+};
+
+static struct v4l2_subdev_video_ops noon010_video_ops = {
+       .s_stream       = noon010_s_stream,
 };
 
 static const struct v4l2_subdev_ops noon010_ops = {
        .core   = &noon010_core_ops,
+       .pad    = &noon010_pad_ops,
        .video  = &noon010_video_ops,
 };
 
@@ -666,9 +707,11 @@ static int noon010_probe(struct i2c_client *client,
        if (!info)
                return -ENOMEM;
 
+       mutex_init(&info->lock);
        sd = &info->sd;
        strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
        v4l2_i2c_subdev_init(sd, client, &noon010_ops);
+       sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
 
        v4l2_ctrl_handler_init(&info->hdl, 3);
 
@@ -720,11 +763,16 @@ static int noon010_probe(struct i2c_client *client,
        if (ret)
                goto np_reg_err;
 
+       info->pad.flags = MEDIA_PAD_FL_SOURCE;
+       ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
+       if (ret < 0)
+               goto np_me_err;
+
        ret = noon010_detect(client, info);
        if (!ret)
                return 0;
 
-       /* the sensor detection failed */
+np_me_err:
        regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply);
 np_reg_err:
        if (gpio_is_valid(info->gpio_nstby))
@@ -751,10 +799,10 @@ static int noon010_remove(struct i2c_client *client)
 
        if (gpio_is_valid(info->gpio_nreset))
                gpio_free(info->gpio_nreset);
-
        if (gpio_is_valid(info->gpio_nstby))
                gpio_free(info->gpio_nstby);
 
+       media_entity_cleanup(&sd->entity);
        kfree(info);
        return 0;
 }
-- 
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to