All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH/RFC v4 00/13] V4L: camera control enhancements
@ 2012-05-04 18:32 Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 01/12] V4L: Add helper function for standard integer menu controls Sylwester Nawrocki
                   ` (12 more replies)
  0 siblings, 13 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki

Here is one more update of the camera class controls change set.

Changes since v3, these are mainly corrections after comments from
Hans (thank you!):
 - V4L2_CID_IMAGE_STABILIZATION and V4L2_CID_WIDE_DYNAMIC_RANGE controls
   type reverted back to boolean, added a note in the documentation that
   these controls may be converted to menu controls in future;
 - Added description for new integer menu control helpers to
   Documentation/video4linux/v4l2-controls.txt
 - edited V4L2_CID_3A_LOCK control's description;
 - removed the vivi patch from the series;

Comments are welcome. If there is no more major corrections required
I'd like to send a pull request next week for the following:

  V4L: Add helper function for standard integer menu controls
  V4L: Add camera exposure bias control
  V4L: Add an extended camera white balance control
  V4L: Add camera wide dynamic range control
  V4L: Add camera image stabilization control
  V4L: Add camera ISO sensitivity controls
  V4L: Add camera exposure metering control
  V4L: Add camera scene mode control
  V4L: Add camera 3A lock control

and after there is an agreement on how to handle the enums in the V4L2 API,
since some of the above patches depend on the new integer menu control
type addition.


Changes since v2:
 - V4L2_CID_WHITE_BALANCE_PRESET replaced with V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
   according to suggestions from Hans de Goede;
 - added Flurescent H white balance preset;
 - V4L2_CID_IMAGE_STABILIZATION and V4L2_CID_WIDE_DYNAMIC_RANGE controls type
   changed from boolean to menu, to make any further extensions of these
   controls easier;
   I'm just not 100% sure if V4L2_WIDE_DYNAMIC_RANGE_ENABLED and
   V4L2_IMAGE_STABILIZATION_ENABLED are good names for cases where the camera
   doesn't support wide dynamic range or image stabilization technique
   selection and only allows to enable or disable those algorithms;
 - V4L2_CID_ISO_SENSITIVITY_AUTO control type changed from boolean to menu in
   order to support ISO presets; currently enum v4l2_iso_sensitivity_auto_type
   does not contain any presets though;
 - V4L2_CID_COLORFX patch removed from this series;
 - updated vivi and s5c73m3 driver patches.

Changes since v1 (implicit):
 - the V4L2_CID_AUTO_FOCUS_FACE_PRIORITY control merged with
   V4L2_CID_AUTO_FOCUS_FACE_AREA,
 - many minor documentation corrections,
 - removed "08/23 V4L: camera control class..." patch, which got
   accidentally added at v1,
 - added V4L2_CID_SCENE_MODE and V4L2_CID_3A_LOCK controls,
 - added vivi patch for testing.

The patches will be also available in few hours in git repository at:
http://git.infradead.org/users/kmpark/linux-samsung/shortlog/refs/heads/v4l-camera-controls

Regards,
Sylwester


Sylwester Nawrocki (12):
  V4L: Add helper function for standard integer menu controls
  V4L: Add camera exposure bias control
  V4L: Add an extended camera white balance control
  V4L: Add camera wide dynamic range control
  V4L: Add camera image stabilization control
  V4L: Add camera ISO sensitivity controls
  V4L: Add camera exposure metering control
  V4L: Add camera scene mode control
  V4L: Add camera 3A lock control
  V4L: Add auto focus targets to the selections API
  V4L: Add auto focus targets to the subdev selections API
  V4L: Add camera auto focus controls

 Documentation/DocBook/media/v4l/biblio.xml         |   11 +
 Documentation/DocBook/media/v4l/controls.xml       |  481 +++++++++++++++++++-
 Documentation/DocBook/media/v4l/dev-subdev.xml     |   27 +-
 Documentation/DocBook/media/v4l/selection-api.xml  |   33 +-
 .../DocBook/media/v4l/vidioc-g-selection.xml       |   11 +
 .../media/v4l/vidioc-subdev-g-selection.xml        |   14 +-
 Documentation/video4linux/v4l2-controls.txt        |   22 +
 drivers/media/video/v4l2-ctrls.c                   |  121 ++++-
 include/linux/v4l2-subdev.h                        |    4 +
 include/linux/videodev2.h                          |   86 ++++
 include/media/v4l2-ctrls.h                         |   17 +
 11 files changed, 820 insertions(+), 7 deletions(-)

-- 
1.7.10


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 01/12] V4L: Add helper function for standard integer menu controls
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-06 10:12   ` Sakari Ailus
  2012-05-04 18:32 ` [PATCH/RFC v4 02/12] V4L: Add camera exposure bias control Sylwester Nawrocki
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

This patch adds v4l2_ctrl_new_std_int_menu() helper function which can
be used in drivers for creating standard integer menu control. It is
similar to v4l2_ctrl_new_std_menu(), except it doesn't have a mask
parameter and an additional qmenu parameter allows passing an array
of signed 64-bit integers constituting the menu items.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/video4linux/v4l2-controls.txt |   22 ++++++++++++++++++++++
 drivers/media/video/v4l2-ctrls.c            |   21 +++++++++++++++++++++
 include/media/v4l2-ctrls.h                  |   17 +++++++++++++++++
 3 files changed, 60 insertions(+)

diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt
index e2492a9..c536d32 100644
--- a/Documentation/video4linux/v4l2-controls.txt
+++ b/Documentation/video4linux/v4l2-controls.txt
@@ -130,8 +130,18 @@ Menu controls are added by calling v4l2_ctrl_new_std_menu:
 			const struct v4l2_ctrl_ops *ops,
 			u32 id, s32 max, s32 skip_mask, s32 def);
 
+Or alternatively for integer menu controls, by calling v4l2_ctrl_new_std_int_menu:
+
+	struct v4l2_ctrl *v4l2_ctrl_new_std_int_menu(struct v4l2_ctrl_handler *hdl,
+			const struct v4l2_ctrl_ops *ops,
+			u32 id, s32 max, s32 def, const s64 *qmenu_int);
+
 These functions are typically called right after the v4l2_ctrl_handler_init:
 
+	static const s64 exp_bias_qmenu[] = {
+	       -2, -1, 0, 1, 2
+	};
+
 	v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);
 	v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,
 			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
@@ -141,6 +151,11 @@ These functions are typically called right after the v4l2_ctrl_handler_init:
 			V4L2_CID_POWER_LINE_FREQUENCY,
 			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
 			V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
+	v4l2_ctrl_new_std_int_menu(&foo->ctrl_handler, &foo_ctrl_ops,
+			V4L2_CID_EXPOSURE_BIAS,
+			ARRAY_SIZE(exp_bias_qmenu) - 1,
+			ARRAY_SIZE(exp_bias_qmenu) / 2 - 1,
+			exp_bias_qmenu);
 	...
 	if (foo->ctrl_handler.error) {
 		int err = foo->ctrl_handler.error;
@@ -164,6 +179,11 @@ controls. There is no min argument since that is always 0 for menu controls,
 and instead of a step there is a skip_mask argument: if bit X is 1, then menu
 item X is skipped.
 
+The v4l2_ctrl_new_std_int_menu function creates a new standard integer menu
+control. It differs from v4l2_ctrl_new_std_menu in that it doesn't have the
+mask argument and takes as the last argument an array of signed 64-bit
+integers that form an exact menu item list.
+
 Note that if something fails, the function will return NULL or an error and
 set ctrl_handler->error to the error code. If ctrl_handler->error was already
 set, then it will just return and do nothing. This is also true for
@@ -346,6 +366,8 @@ it to 0 means that all menu items are supported.
 You set this mask either through the v4l2_ctrl_config struct for a custom
 control, or by calling v4l2_ctrl_new_std_menu().
 
+For integer menu controls menu_skip_mask remains unused, it is set to 0
+within v4l2_ctrl_new_std_int_menu().
 
 Custom Controls
 ===============
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index c93a979..e0725b5 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -1517,6 +1517,27 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
 
+/* Helper function for standard integer menu controls */
+struct v4l2_ctrl *v4l2_ctrl_new_std_int_menu(struct v4l2_ctrl_handler *hdl,
+			const struct v4l2_ctrl_ops *ops,
+			u32 id, s32 max, s32 def, const s64 *qmenu_int)
+{
+	const char *name;
+	enum v4l2_ctrl_type type;
+	s32 min;
+	s32 step;
+	u32 flags;
+
+	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
+	if (type != V4L2_CTRL_TYPE_INTEGER_MENU) {
+		handler_set_err(hdl, -EINVAL);
+		return NULL;
+	}
+	return v4l2_ctrl_new(hdl, ops, id, name, type,
+			     0, max, 0, def, flags, NULL, qmenu_int, NULL);
+}
+EXPORT_SYMBOL(v4l2_ctrl_new_std_int_menu);
+
 /* Add a control from another handler to this handler */
 struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl,
 					  struct v4l2_ctrl *ctrl)
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 8920f82..15116d2 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -347,6 +347,23 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
 			u32 id, s32 max, s32 mask, s32 def);
 
+/** v4l2_ctrl_new_std_int_menu() - Create a new standard V4L2 integer menu control.
+  * @hdl:	The control handler.
+  * @ops:	The control ops.
+  * @id:	The control ID.
+  * @max:	The control's maximum value.
+  * @def:	The control's default value.
+  * @qmenu_int:	The control's menu entries.
+  *
+  * Same as v4l2_ctrl_new_std_menu(), but @mask is set to 0 and it additionaly
+  * needs an array of integers determining the menu entries.
+  *
+  * If @id refers to a non-integer-menu control, then this function will return NULL.
+  */
+struct v4l2_ctrl *v4l2_ctrl_new_std_int_menu(struct v4l2_ctrl_handler *hdl,
+			const struct v4l2_ctrl_ops *ops,
+			u32 id, s32 max, s32 def, const s64 *qmenu_int);
+
 /** v4l2_ctrl_add_ctrl() - Add a control from another handler to this handler.
   * @hdl:	The control handler.
   * @ctrl:	The control to add.
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 02/12] V4L: Add camera exposure bias control
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 01/12] V4L: Add helper function for standard integer menu controls Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 03/12] V4L: Add an extended camera white balance control Sylwester Nawrocki
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

The camera may in some conditions incorrectly determine the exposure,
and a manual automatic exposure correction may be needed. This patch
adds V4L2_CID_AUTO_EXPOSURE_BIAS control which allows to add some
offset in the automatic exposure control loop, to compensate for
frame under- or over-exposure.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/DocBook/media/v4l/controls.xml |   16 ++++++++++++++++
 drivers/media/video/v4l2-ctrls.c             |    4 ++++
 include/linux/videodev2.h                    |    2 ++
 3 files changed, 22 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 5e12257..612009f 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -2775,6 +2775,22 @@ remain constant.</entry>
 	  <row><entry></entry></row>
 
 	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_EXPOSURE_BIAS</constant>&nbsp;</entry>
+	    <entry>integer menu</entry>
+	  </row><row><entry spanname="descr"> Determines the automatic
+exposure compensation, it is effective only when <constant>V4L2_CID_EXPOSURE_AUTO</constant>
+control is set to <constant>AUTO</constant>, <constant>SHUTTER_PRIORITY </constant>
+or <constant>APERTURE_PRIORITY</constant>.
+It is expressed in terms of EV, drivers should interpret the values as 0.001 EV
+units, where the value 1000 stands for +1 EV.
+<para>Increasing the exposure compensation value is equivalent to decreasing
+the exposure value (EV) and will increase the amount of light at the image
+sensor. The camera performs the exposure compensation by adjusting absolute
+exposure time and/or aperture.</para></entry>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row>
 	    <entry spanname="id"><constant>V4L2_CID_PAN_RELATIVE</constant>&nbsp;</entry>
 	    <entry>integer</entry>
 	  </row><row><entry spanname="descr">This control turns the
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index e0725b5..1d7091f 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -597,6 +597,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_PRIVACY:			return "Privacy";
 	case V4L2_CID_IRIS_ABSOLUTE:		return "Iris, Absolute";
 	case V4L2_CID_IRIS_RELATIVE:		return "Iris, Relative";
+	case V4L2_CID_AUTO_EXPOSURE_BIAS:	return "Auto Exposure, Bias";
 
 	/* FM Radio Modulator control */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -739,6 +740,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_RDS_TX_RADIO_TEXT:
 		*type = V4L2_CTRL_TYPE_STRING;
 		break;
+	case V4L2_CID_AUTO_EXPOSURE_BIAS:
+		*type = V4L2_CTRL_TYPE_INTEGER_MENU;
+		break;
 	case V4L2_CID_USER_CLASS:
 	case V4L2_CID_CAMERA_CLASS:
 	case V4L2_CID_MPEG_CLASS:
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 5a09ac3..da60cbb 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1693,6 +1693,8 @@ enum  v4l2_exposure_auto_type {
 #define V4L2_CID_IRIS_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+17)
 #define V4L2_CID_IRIS_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+18)
 
+#define V4L2_CID_AUTO_EXPOSURE_BIAS		(V4L2_CID_CAMERA_CLASS_BASE+19)
+
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
 #define V4L2_CID_FM_TX_CLASS			(V4L2_CTRL_CLASS_FM_TX | 1)
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 03/12] V4L: Add an extended camera white balance control
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 01/12] V4L: Add helper function for standard integer menu controls Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 02/12] V4L: Add camera exposure bias control Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 04/12] V4L: Add camera wide dynamic range control Sylwester Nawrocki
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

This patch adds V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE control which is
an extended version of the V4L2_CID_AUTO_WHITE_BALANCE control,
including white balance presets. The following presets are defined:

 - V4L2_WHITE_BALANCE_INCANDESCENT,
 - V4L2_WHITE_BALANCE_FLUORESCENT,
 - V4L2_WHITE_BALANCE_FLUORESCENT_H,
 - V4L2_WHITE_BALANCE_HORIZON,
 - V4L2_WHITE_BALANCE_DAYLIGHT,
 - V4L2_WHITE_BALANCE_FLASH,
 - V4L2_WHITE_BALANCE_CLOUDY,
 - V4L2_WHITE_BALANCE_SHADE.

Signed-off-by: HeungJun Kim <riverful.kim@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
---
 Documentation/DocBook/media/v4l/controls.xml |   70 ++++++++++++++++++++++++++
 drivers/media/video/v4l2-ctrls.c             |   17 +++++++
 include/linux/videodev2.h                    |   14 ++++++
 3 files changed, 101 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 612009f..e3f9277 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -2948,6 +2948,76 @@ camera sensor on or off, or specify its strength. Such band-stop filters can
 be used, for example, to filter out the fluorescent light component.</entry>
 	  </row>
 	  <row><entry></entry></row>
+
+	  <row id="v4l2-auto-n-preset-white-balance">
+	    <entry spanname="id"><constant>V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE</constant>&nbsp;</entry>
+	    <entry>enum&nbsp;v4l2_auto_n_preset_white_balance</entry>
+	  </row><row><entry spanname="descr">Sets white balance to automatic,
+manual or a preset. The presets determine color temperature of the light as
+a hint to the camera for white balance adjustments resulting in most accurate
+color representation. The following white balance presets are listed in order
+of increasing color temperature.</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_WHITE_BALANCE_MANUAL</constant>&nbsp;</entry>
+		  <entry>Manual white balance.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_WHITE_BALANCE_AUTO</constant>&nbsp;</entry>
+		  <entry>Automatic white balance adjustments.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_WHITE_BALANCE_INCANDESCENT</constant>&nbsp;</entry>
+		  <entry>White balance setting for incandescent (tungsten) lighting.
+It generally cools down the colors and corresponds approximately to 2500...3500 K
+color temperature range.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_WHITE_BALANCE_FLUORESCENT</constant>&nbsp;</entry>
+		  <entry>White balance preset for fluorescent lighting.
+It corresponds approximately to 4000...5000 K color temperature.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_WHITE_BALANCE_FLUORESCENT_H</constant>&nbsp;</entry>
+		  <entry>With this setting the camera will compensate for
+fluorescent H lighting.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_WHITE_BALANCE_HORIZON</constant>&nbsp;</entry>
+		  <entry>White balance setting for horizon daylight.
+It corresponds approximately to 5000 K color temperature.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_WHITE_BALANCE_DAYLIGHT</constant>&nbsp;</entry>
+		  <entry>White balance preset for daylight (with clear sky).
+It corresponds approximately to 5000...6500 K color temperature.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_WHITE_BALANCE_FLASH</constant>&nbsp;</entry>
+		  <entry>With this setting the camera will compensate for the flash
+light. It slightly warms up the colors and corresponds roughly to 5000...5500 K
+color temperature.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_WHITE_BALANCE_CLOUDY</constant>&nbsp;</entry>
+		  <entry>White balance preset for moderately overcast sky.
+This option corresponds approximately to 6500...8000 K color temperature
+range.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_WHITE_BALANCE_SHADE</constant>&nbsp;</entry>
+		  <entry>White balance preset for shade or heavily overcast
+sky. It corresponds approximately to 9000...10000 K color temperature.
+</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry></entry></row>
+
 	</tbody>
       </tgroup>
     </table>
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 1d7091f..02fa9b0 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -243,6 +243,19 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		"Vivid",
 		NULL
 	};
+	static const char * const auto_n_preset_white_balance[] = {
+		"Manual",
+		"Auto",
+		"Incandescent",
+		"Fluorescent",
+		"Fluorescent H",
+		"Horizon",
+		"Daylight",
+		"Flash",
+		"Cloudy",
+		"Shade",
+		NULL,
+	};
 	static const char * const tune_preemphasis[] = {
 		"No Preemphasis",
 		"50 Microseconds",
@@ -412,6 +425,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		return camera_exposure_auto;
 	case V4L2_CID_COLORFX:
 		return colorfx;
+	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
+		return auto_n_preset_white_balance;
 	case V4L2_CID_TUNE_PREEMPHASIS:
 		return tune_preemphasis;
 	case V4L2_CID_FLASH_LED_MODE:
@@ -598,6 +613,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_IRIS_ABSOLUTE:		return "Iris, Absolute";
 	case V4L2_CID_IRIS_RELATIVE:		return "Iris, Relative";
 	case V4L2_CID_AUTO_EXPOSURE_BIAS:	return "Auto Exposure, Bias";
+	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: return "White Balance, Auto & Preset";
 
 	/* FM Radio Modulator control */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -721,6 +737,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_MPEG_STREAM_VBI_FMT:
 	case V4L2_CID_EXPOSURE_AUTO:
 	case V4L2_CID_COLORFX:
+	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
 	case V4L2_CID_TUNE_PREEMPHASIS:
 	case V4L2_CID_FLASH_LED_MODE:
 	case V4L2_CID_FLASH_STROBE_SOURCE:
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index da60cbb..1460419 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1695,6 +1695,20 @@ enum  v4l2_exposure_auto_type {
 
 #define V4L2_CID_AUTO_EXPOSURE_BIAS		(V4L2_CID_CAMERA_CLASS_BASE+19)
 
+#define V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE	(V4L2_CID_CAMERA_CLASS_BASE+20)
+enum v4l2_auto_n_preset_white_balance {
+	V4L2_WHITE_BALANCE_MANUAL		= 0,
+	V4L2_WHITE_BALANCE_AUTO			= 1,
+	V4L2_WHITE_BALANCE_INCANDESCENT		= 2,
+	V4L2_WHITE_BALANCE_FLUORESCENT		= 3,
+	V4L2_WHITE_BALANCE_FLUORESCENT_H	= 4,
+	V4L2_WHITE_BALANCE_HORIZON		= 5,
+	V4L2_WHITE_BALANCE_DAYLIGHT		= 6,
+	V4L2_WHITE_BALANCE_FLASH		= 7,
+	V4L2_WHITE_BALANCE_CLOUDY		= 8,
+	V4L2_WHITE_BALANCE_SHADE		= 9,
+};
+
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
 #define V4L2_CID_FM_TX_CLASS			(V4L2_CTRL_CLASS_FM_TX | 1)
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 04/12] V4L: Add camera wide dynamic range control
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
                   ` (2 preceding siblings ...)
  2012-05-04 18:32 ` [PATCH/RFC v4 03/12] V4L: Add an extended camera white balance control Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 05/12] V4L: Add camera image stabilization control Sylwester Nawrocki
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

Add V4L2_CID_WIDE_DYNAMIC_RANGE camera class control for the
camera wide dynamic range (WDR, HDR) feature. This control
can be used to enable/disable wide dynamic range. It might
get converted to a menu control in future if more options
are needed.

Signed-off-by: HeungJun Kim <riverful.kim@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/DocBook/media/v4l/controls.xml |   15 +++++++++++++++
 drivers/media/video/v4l2-ctrls.c             |    2 ++
 include/linux/videodev2.h                    |    2 ++
 3 files changed, 19 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index e3f9277..0256a02 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -3018,6 +3018,21 @@ sky. It corresponds approximately to 9000...10000 K color temperature.
 	  </row>
 	  <row><entry></entry></row>
 
+	  <row id="v4l2-wide-dynamic-range">
+	    <entry spanname="id"><constant>V4L2_CID_WIDE_DYNAMIC_RANGE</constant></entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Enables or disables the camera's wide dynamic
+range feature. This feature allows to obtain clear images in situations where
+intensity of the illumination varies significantly throughout the scene, i.e.
+there are simultaneously very dark and very bright areas. It is most commonly
+realized in cameras by combining two subsequent frames with different exposure
+times. <footnote id="ctypeconv"><para> This control may be changed to a menu
+control in future, if more options are required.</para></footnote></entry>
+	  </row>
+	  <row><entry></entry></row>
+
 	</tbody>
       </tgroup>
     </table>
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 02fa9b0..8b47c05 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -614,6 +614,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_IRIS_RELATIVE:		return "Iris, Relative";
 	case V4L2_CID_AUTO_EXPOSURE_BIAS:	return "Auto Exposure, Bias";
 	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: return "White Balance, Auto & Preset";
+	case V4L2_CID_WIDE_DYNAMIC_RANGE:	return "Wide Dynamic Range";
 
 	/* FM Radio Modulator control */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -705,6 +706,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
 	case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
 	case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
+	case V4L2_CID_WIDE_DYNAMIC_RANGE:
 		*type = V4L2_CTRL_TYPE_BOOLEAN;
 		*min = 0;
 		*max = *step = 1;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 1460419..8964ebc 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1709,6 +1709,8 @@ enum v4l2_auto_n_preset_white_balance {
 	V4L2_WHITE_BALANCE_SHADE		= 9,
 };
 
+#define V4L2_CID_WIDE_DYNAMIC_RANGE		(V4L2_CID_CAMERA_CLASS_BASE+21)
+
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
 #define V4L2_CID_FM_TX_CLASS			(V4L2_CTRL_CLASS_FM_TX | 1)
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 05/12] V4L: Add camera image stabilization control
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
                   ` (3 preceding siblings ...)
  2012-05-04 18:32 ` [PATCH/RFC v4 04/12] V4L: Add camera wide dynamic range control Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 06/12] V4L: Add camera ISO sensitivity controls Sylwester Nawrocki
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

Add V4L2_CID_IMAGE_STABILIZATION control for the camera image
stabilization feature. This control can be used to enable/disable
image stabilization. It might get converted to a menu control
in future if more options are needed.

Signed-off-by: HeungJun Kim <riverful.kim@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/DocBook/media/v4l/controls.xml |   10 ++++++++++
 drivers/media/video/v4l2-ctrls.c             |    2 ++
 include/linux/videodev2.h                    |    1 +
 3 files changed, 13 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 0256a02..7468267 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -3033,6 +3033,16 @@ control in future, if more options are required.</para></footnote></entry>
 	  </row>
 	  <row><entry></entry></row>
 
+	  <row id="v4l2-image-stabilization">
+	    <entry spanname="id"><constant>V4L2_CID_IMAGE_STABILIZATION</constant></entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Enables or disables image stabilization.
+	      <footnoteref linkend="ctypeconv"/></entry>
+	  </row>
+	  <row><entry></entry></row>
+
 	</tbody>
       </tgroup>
     </table>
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 8b47c05..406916a 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -615,6 +615,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_AUTO_EXPOSURE_BIAS:	return "Auto Exposure, Bias";
 	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: return "White Balance, Auto & Preset";
 	case V4L2_CID_WIDE_DYNAMIC_RANGE:	return "Wide Dynamic Range";
+	case V4L2_CID_IMAGE_STABILIZATION:	return "Image Stabilization";
 
 	/* FM Radio Modulator control */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -707,6 +708,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
 	case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
 	case V4L2_CID_WIDE_DYNAMIC_RANGE:
+	case V4L2_CID_IMAGE_STABILIZATION:
 		*type = V4L2_CTRL_TYPE_BOOLEAN;
 		*min = 0;
 		*max = *step = 1;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 8964ebc..9b5fe8a 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1710,6 +1710,7 @@ enum v4l2_auto_n_preset_white_balance {
 };
 
 #define V4L2_CID_WIDE_DYNAMIC_RANGE		(V4L2_CID_CAMERA_CLASS_BASE+21)
+#define V4L2_CID_IMAGE_STABILIZATION		(V4L2_CID_CAMERA_CLASS_BASE+22)
 
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 06/12] V4L: Add camera ISO sensitivity controls
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
                   ` (4 preceding siblings ...)
  2012-05-04 18:32 ` [PATCH/RFC v4 05/12] V4L: Add camera image stabilization control Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 07/12] V4L: Add camera exposure metering control Sylwester Nawrocki
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

Add ISO sensitivity and ISO auto/manual controls. The sensitivity
values are related to level of amplification of the analog signal
between image sensor and ADC. These controls allow to support sensors
exposing an interface to accept the ISO values directly.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/DocBook/media/v4l/biblio.xml   |   11 ++++++++
 Documentation/DocBook/media/v4l/controls.xml |   38 ++++++++++++++++++++++++++
 drivers/media/video/v4l2-ctrls.c             |   11 ++++++++
 include/linux/videodev2.h                    |    7 +++++
 4 files changed, 67 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/biblio.xml b/Documentation/DocBook/media/v4l/biblio.xml
index 7dc65c5..66a0ef2 100644
--- a/Documentation/DocBook/media/v4l/biblio.xml
+++ b/Documentation/DocBook/media/v4l/biblio.xml
@@ -197,4 +197,15 @@ in the frequency range from 87,5 to 108,0 MHz</title>
       <title>NTSC-4: United States RBDS Standard</title>
     </biblioentry>
 
+    <biblioentry id="iso12232">
+      <abbrev>ISO&nbsp;12232:2006</abbrev>
+      <authorgroup>
+	<corpauthor>International Organization for Standardization
+(<ulink url="http://www.iso.org">http://www.iso.org</ulink>)</corpauthor>
+      </authorgroup>
+      <title>Photography &mdash; Digital still cameras &mdash; Determination
+      of exposure index, ISO speed ratings, standard output sensitivity, and
+      recommended exposure index</title>
+    </biblioentry>
+
   </bibliography>
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 7468267..1300901 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -3043,6 +3043,44 @@ control in future, if more options are required.</para></footnote></entry>
 	  </row>
 	  <row><entry></entry></row>
 
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_ISO_SENSITIVITY</constant>&nbsp;</entry>
+	    <entry>integer menu</entry>
+	  </row><row><entry spanname="descr">Determines ISO equivalent of an
+image sensor indicating the sensor's sensitivity to light. The numbers are
+expressed in arithmetic scale, as per <xref linkend="iso12232" /> standard,
+where doubling the sensor sensitivity is represented by doubling the numerical
+ISO value. Applications should interpret the values as standard ISO values
+multiplied by 1000, e.g. control value 800 stands for ISO 0.8. Drivers will
+usually support only a subset of standard ISO values. The effect of setting
+this control while the <constant>V4L2_CID_ISO_SENSITIVITY_AUTO</constant>
+control is set to a value other than <constant>V4L2_CID_ISO_SENSITIVITY_MANUAL
+</constant> is undefined, drivers should ignore such requests.</entry>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row id="v4l2-iso-sensitivity-auto-type">
+	    <entry spanname="id"><constant>V4L2_CID_ISO_SENSITIVITY_AUTO</constant>&nbsp;</entry>
+	    <entry>enum&nbsp;v4l2_iso_sensitivity_type</entry>
+	  </row><row><entry spanname="descr">Enables or disables automatic ISO
+sensitivity adjustments.</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_CID_ISO_SENSITIVITY_MANUAL</constant>&nbsp;</entry>
+		  <entry>Manual ISO sensitivity.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_CID_ISO_SENSITIVITY_AUTO</constant>&nbsp;</entry>
+		  <entry>Automatic ISO sensitivity adjustments.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry></entry></row>
+
 	</tbody>
       </tgroup>
     </table>
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 406916a..b70226e 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -256,6 +256,11 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		"Shade",
 		NULL,
 	};
+	static const char * const camera_iso_sensitivity_auto[] = {
+		"Manual",
+		"Auto",
+		NULL
+	};
 	static const char * const tune_preemphasis[] = {
 		"No Preemphasis",
 		"50 Microseconds",
@@ -427,6 +432,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		return colorfx;
 	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
 		return auto_n_preset_white_balance;
+	case V4L2_CID_ISO_SENSITIVITY_AUTO:
+		return camera_iso_sensitivity_auto;
 	case V4L2_CID_TUNE_PREEMPHASIS:
 		return tune_preemphasis;
 	case V4L2_CID_FLASH_LED_MODE:
@@ -616,6 +623,8 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: return "White Balance, Auto & Preset";
 	case V4L2_CID_WIDE_DYNAMIC_RANGE:	return "Wide Dynamic Range";
 	case V4L2_CID_IMAGE_STABILIZATION:	return "Image Stabilization";
+	case V4L2_CID_ISO_SENSITIVITY:		return "ISO Sensitivity";
+	case V4L2_CID_ISO_SENSITIVITY_AUTO:	return "ISO Sensitivity, Auto";
 
 	/* FM Radio Modulator control */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -755,12 +764,14 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
 	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
 	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
+	case V4L2_CID_ISO_SENSITIVITY_AUTO:
 		*type = V4L2_CTRL_TYPE_MENU;
 		break;
 	case V4L2_CID_RDS_TX_PS_NAME:
 	case V4L2_CID_RDS_TX_RADIO_TEXT:
 		*type = V4L2_CTRL_TYPE_STRING;
 		break;
+	case V4L2_CID_ISO_SENSITIVITY:
 	case V4L2_CID_AUTO_EXPOSURE_BIAS:
 		*type = V4L2_CTRL_TYPE_INTEGER_MENU;
 		break;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 9b5fe8a..993af23 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1712,6 +1712,13 @@ enum v4l2_auto_n_preset_white_balance {
 #define V4L2_CID_WIDE_DYNAMIC_RANGE		(V4L2_CID_CAMERA_CLASS_BASE+21)
 #define V4L2_CID_IMAGE_STABILIZATION		(V4L2_CID_CAMERA_CLASS_BASE+22)
 
+#define V4L2_CID_ISO_SENSITIVITY		(V4L2_CID_CAMERA_CLASS_BASE+23)
+#define V4L2_CID_ISO_SENSITIVITY_AUTO		(V4L2_CID_CAMERA_CLASS_BASE+24)
+enum v4l2_iso_sensitivity_auto_type {
+	V4L2_ISO_SENSITIVITY_MANUAL		= 0,
+	V4L2_ISO_SENSITIVITY_AUTO		= 1,
+};
+
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
 #define V4L2_CID_FM_TX_CLASS			(V4L2_CTRL_CLASS_FM_TX | 1)
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 07/12] V4L: Add camera exposure metering control
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
                   ` (5 preceding siblings ...)
  2012-05-04 18:32 ` [PATCH/RFC v4 06/12] V4L: Add camera ISO sensitivity controls Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 08/12] V4L: Add camera scene mode control Sylwester Nawrocki
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

The V4L2_CID_EXPOSURE_METERING control allows to determine
a method used by the camera for measuring the amount of light
available for automatic exposure.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/DocBook/media/v4l/controls.xml |   29 ++++++++++++++++++++++++++
 drivers/media/video/v4l2-ctrls.c             |   10 +++++++++
 include/linux/videodev2.h                    |    7 +++++++
 3 files changed, 46 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 1300901..3cd6972 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -2790,6 +2790,35 @@ exposure time and/or aperture.</para></entry>
 	  </row>
 	  <row><entry></entry></row>
 
+	  <row id="v4l2-exposure-metering">
+	    <entry spanname="id"><constant>V4L2_CID_EXPOSURE_METERING</constant>&nbsp;</entry>
+	    <entry>enum&nbsp;v4l2_exposure_metering</entry>
+	  </row><row><entry spanname="descr">Determines how the camera measures
+the amount of light available for the frame exposure. Possible values are:</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_EXPOSURE_METERING_AVERAGE</constant>&nbsp;</entry>
+		  <entry>Use the light information coming from the entire frame
+and average giving no weighting to any particular portion of the metered area.
+		  </entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_EXPOSURE_METERING_CENTER_WEIGHTED</constant>&nbsp;</entry>
+		  <entry>Average the light information coming from the entire frame
+giving priority to the center of the metered area.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_EXPOSURE_METERING_SPOT</constant>&nbsp;</entry>
+		  <entry>Measure only very small area at the center of the frame.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry></entry></row>
+
 	  <row>
 	    <entry spanname="id"><constant>V4L2_CID_PAN_RELATIVE</constant>&nbsp;</entry>
 	    <entry>integer</entry>
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index b70226e..350c745 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -230,6 +230,12 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		"Aperture Priority Mode",
 		NULL
 	};
+	static const char * const camera_exposure_metering[] = {
+		"Average",
+		"Center Weighted",
+		"Spot",
+		NULL
+	};
 	static const char * const colorfx[] = {
 		"None",
 		"Black & White",
@@ -428,6 +434,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		return camera_power_line_frequency;
 	case V4L2_CID_EXPOSURE_AUTO:
 		return camera_exposure_auto;
+	case V4L2_CID_EXPOSURE_METERING:
+		return camera_exposure_metering;
 	case V4L2_CID_COLORFX:
 		return colorfx;
 	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
@@ -625,6 +633,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_IMAGE_STABILIZATION:	return "Image Stabilization";
 	case V4L2_CID_ISO_SENSITIVITY:		return "ISO Sensitivity";
 	case V4L2_CID_ISO_SENSITIVITY_AUTO:	return "ISO Sensitivity, Auto";
+	case V4L2_CID_EXPOSURE_METERING:	return "Exposure, Metering Mode";
 
 	/* FM Radio Modulator control */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -765,6 +774,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
 	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
 	case V4L2_CID_ISO_SENSITIVITY_AUTO:
+	case V4L2_CID_EXPOSURE_METERING:
 		*type = V4L2_CTRL_TYPE_MENU;
 		break;
 	case V4L2_CID_RDS_TX_PS_NAME:
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 993af23..4fb1d0f 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1719,6 +1719,13 @@ enum v4l2_iso_sensitivity_auto_type {
 	V4L2_ISO_SENSITIVITY_AUTO		= 1,
 };
 
+#define V4L2_CID_EXPOSURE_METERING		(V4L2_CID_CAMERA_CLASS_BASE+25)
+enum v4l2_exposure_metering {
+	V4L2_EXPOSURE_METERING_AVERAGE		= 0,
+	V4L2_EXPOSURE_METERING_CENTER_WEIGHTED	= 1,
+	V4L2_EXPOSURE_METERING_SPOT		= 2,
+};
+
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
 #define V4L2_CID_FM_TX_CLASS			(V4L2_CTRL_CLASS_FM_TX | 1)
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 08/12] V4L: Add camera scene mode control
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
                   ` (6 preceding siblings ...)
  2012-05-04 18:32 ` [PATCH/RFC v4 07/12] V4L: Add camera exposure metering control Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 09/12] V4L: Add camera 3A lock control Sylwester Nawrocki
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

Add control for the scene mode feature available in image sensor
with more advanced ISP firmware. The V4L2_CID_SCENE_MODE menu
control allows to select a set of parameters or a specific image
processing and capture control algorithm optimized for common
image capture conditions.

Signed-off-by: HeungJun Kim <riverful.kim@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/DocBook/media/v4l/controls.xml |  117 ++++++++++++++++++++++++++
 drivers/media/video/v4l2-ctrls.c             |   21 +++++
 include/linux/videodev2.h                    |   18 ++++
 3 files changed, 156 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 3cd6972..88608f6 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -3110,6 +3110,123 @@ sensitivity adjustments.</entry>
 	  </row>
 	  <row><entry></entry></row>
 
+	  <row id="v4l2-scene-mode">
+	    <entry spanname="id"><constant>V4L2_CID_SCENE_MODE</constant>&nbsp;</entry>
+	    <entry>enum&nbsp;v4l2_scene_mode</entry>
+	  </row><row><entry spanname="descr">This control allows to select
+scene programs as the camera automatic modes optimized for common shooting
+scenes. Within these modes the camera determines best exposure, aperture,
+focusing, light metering, white balance and equivalent sensitivity. The
+controls of those parameters are influenced by the scene mode control.
+An exact behavior in each mode is subject to the camera specification.
+
+<para>When the scene mode feature is not used, this control should be set to
+<constant>V4L2_SCENE_MODE_NONE</constant> to make sure the other possibly
+related controls are accessible. The following scene programs are defined:
+</para>
+</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_NONE</constant>&nbsp;</entry>
+		  <entry>The scene mode feature is disabled.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_BACKLIGHT</constant>&nbsp;</entry>
+		  <entry>Backlight. Compensates for dark shadows when light is
+		  coming from behind a subject, also by automatically turning
+		  on the flash.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_BEACH_SNOW</constant>&nbsp;</entry>
+		  <entry>Beach and snow. This mode compensates for all-white or
+bright scenes, which tend to look gray and low contrast, when camera's automatic
+exposure is based on an average scene brightness. To compensate, this mode
+automatically slightly overexposes the frames. The white balance may also be
+adjusted to compensate for the fact that reflected snow looks bluish rather
+than white.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_CANDLELIGHT</constant>&nbsp;</entry>
+		  <entry>Candle light. The camera generally raises the ISO
+sensitivity and lowers the shutter speed. This mode compensates for relatively
+close subject in the scene. The flash is disabled in order to preserve the
+ambiance of the light.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_DAWN_DUSK</constant>&nbsp;</entry>
+		  <entry>Dawn and dusk. Preserves the colors seen in low
+natural light before dusk and after down. The camera may turn off the flash,
+and automatically focus at infinity. It will usually boost saturation and
+lower the shutter speed.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_FALL_COLORS</constant>&nbsp;</entry>
+		  <entry>Fall colors. Increases saturation and adjusts white
+balance for color enhancement. Pictures of autumn leaves get saturated reds
+and yellows.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_FIREWORKS</constant>&nbsp;</entry>
+		  <entry>Fireworks. Long exposure times are used to capture
+the expanding burst of light from a firework. The camera may invoke image
+stabilization.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_LANDSCAPE</constant>&nbsp;</entry>
+		  <entry>Landscape. The camera may choose a small aperture to
+provide deep depth of field and long exposure duration to help capture detail
+in dim light conditions. The focus is fixed at infinity. Suitable for distant
+and wide scenery.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_NIGHT</constant>&nbsp;</entry>
+		  <entry>Night, also known as Night Landscape. Designed for low
+light conditions, it preserves detail in the dark areas without blowing out bright
+objects. The camera generally sets itself to a medium-to-high ISO sensitivity,
+with a relatively long exposure time, and turns flash off. As such, there will be
+increased image noise and the possibility of blurred image.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_PARTY_INDOOR</constant>&nbsp;</entry>
+		  <entry>Party and indoor. Designed to capture indoor scenes
+that are lit by indoor background lighting as well as the flash. The camera
+usually increases ISO sensitivity, and adjusts exposure for the low light
+conditions.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_PORTRAIT</constant>&nbsp;</entry>
+		  <entry>Portrait. The camera adjusts the aperture so that the
+depth of field is reduced, which helps to isolate the subject against a smooth
+background. Most cameras recognize the presence of faces in the scene and focus
+on them. The color hue is adjusted to enhance skin tones. The intensity of the
+flash is often reduced.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_SPORTS</constant>&nbsp;</entry>
+		  <entry>Sports. Significantly increases ISO and uses a fast
+shutter speed to freeze motion of rapidly-moving subjects. Increased image
+noise may be seen in this mode.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_SUNSET</constant>&nbsp;</entry>
+		  <entry>Sunset. Preserves deep hues seen in sunsets and
+sunrises. It bumps up the saturation.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_SCENE_MODE_TEXT</constant>&nbsp;</entry>
+		  <entry>Text. It applies extra contrast and sharpness, it is
+typically a black-and-white mode optimized for readability. Automatic focus
+may be switched to close-up mode and this setting may also involve some
+lens-distortion correction.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry></entry></row>
+
 	</tbody>
       </tgroup>
     </table>
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 350c745..386f20c 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -267,6 +267,23 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		"Auto",
 		NULL
 	};
+	static const char * const scene_mode[] = {
+		"None",
+		"Backlight",
+		"Beach/Snow",
+		"Candle Light",
+		"Dusk/Dawn",
+		"Fall Colors",
+		"Fireworks",
+		"Landscape",
+		"Night",
+		"Party/Indoor",
+		"Portrait",
+		"Sports",
+		"Sunset",
+		"Text",
+		NULL
+	};
 	static const char * const tune_preemphasis[] = {
 		"No Preemphasis",
 		"50 Microseconds",
@@ -442,6 +459,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		return auto_n_preset_white_balance;
 	case V4L2_CID_ISO_SENSITIVITY_AUTO:
 		return camera_iso_sensitivity_auto;
+	case V4L2_CID_SCENE_MODE:
+		return scene_mode;
 	case V4L2_CID_TUNE_PREEMPHASIS:
 		return tune_preemphasis;
 	case V4L2_CID_FLASH_LED_MODE:
@@ -634,6 +653,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_ISO_SENSITIVITY:		return "ISO Sensitivity";
 	case V4L2_CID_ISO_SENSITIVITY_AUTO:	return "ISO Sensitivity, Auto";
 	case V4L2_CID_EXPOSURE_METERING:	return "Exposure, Metering Mode";
+	case V4L2_CID_SCENE_MODE:		return "Scene Mode";
 
 	/* FM Radio Modulator control */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -775,6 +795,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
 	case V4L2_CID_ISO_SENSITIVITY_AUTO:
 	case V4L2_CID_EXPOSURE_METERING:
+	case V4L2_CID_SCENE_MODE:
 		*type = V4L2_CTRL_TYPE_MENU;
 		break;
 	case V4L2_CID_RDS_TX_PS_NAME:
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 4fb1d0f..c672c13 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1726,6 +1726,24 @@ enum v4l2_exposure_metering {
 	V4L2_EXPOSURE_METERING_SPOT		= 2,
 };
 
+#define V4L2_CID_SCENE_MODE			(V4L2_CID_CAMERA_CLASS_BASE+26)
+enum v4l2_scene_mode {
+	V4L2_SCENE_MODE_NONE			= 0,
+	V4L2_SCENE_MODE_BACKLIGHT		= 1,
+	V4L2_SCENE_MODE_BEACH_SNOW		= 2,
+	V4L2_SCENE_MODE_CANDLE_LIGHT		= 3,
+	V4L2_SCENE_MODE_DAWN_DUSK		= 4,
+	V4L2_SCENE_MODE_FALL_COLORS		= 5,
+	V4L2_SCENE_MODE_FIREWORKS		= 6,
+	V4L2_SCENE_MODE_LANDSCAPE		= 7,
+	V4L2_SCENE_MODE_NIGHT			= 8,
+	V4L2_SCENE_MODE_PARTY_INDOOR		= 9,
+	V4L2_SCENE_MODE_PORTRAIT		= 10,
+	V4L2_SCENE_MODE_SPORTS			= 11,
+	V4L2_SCENE_MODE_SUNSET			= 12,
+	V4L2_SCENE_MODE_TEXT			= 13,
+};
+
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
 #define V4L2_CID_FM_TX_CLASS			(V4L2_CTRL_CLASS_FM_TX | 1)
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 09/12] V4L: Add camera 3A lock control
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
                   ` (7 preceding siblings ...)
  2012-05-04 18:32 ` [PATCH/RFC v4 08/12] V4L: Add camera scene mode control Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 10/12] V4L: Add auto focus targets to the selections API Sylwester Nawrocki
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

The V4L2_CID_3A_LOCK bitmask control allows applications to pause
or resume the automatic exposure, focus and wite balance adjustments.
It can be used, for example, to lock the 3A adjustments right before
a still image is captured, for pre-focus, etc.
The applications can control each of the algorithms independently,
through a corresponding control bit, if driver allows that.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/DocBook/media/v4l/controls.xml |   39 ++++++++++++++++++++++++++
 drivers/media/video/v4l2-ctrls.c             |    2 ++
 include/linux/videodev2.h                    |    5 ++++
 3 files changed, 46 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 88608f6..4a463d3 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -3227,6 +3227,45 @@ lens-distortion correction.</entry>
 	  </row>
 	  <row><entry></entry></row>
 
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_3A_LOCK</constant></entry>
+	    <entry>bitmask</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">This control locks or unlocks the automatic
+focus, exposure and white balance. The automatic adjustments can be paused
+independently by setting the corresponding lock bit to 1. The camera then retains
+the settings until the lock bit is cleared. The following lock bits are defined:
+</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_LOCK_EXPOSURE</constant></entry>
+		  <entry>Automatic exposure adjustments lock.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_LOCK_WHITE_BALANCE</constant></entry>
+		  <entry>Automatic white balance adjustments lock.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_LOCK_FOCUS</constant></entry>
+		  <entry>Automatic focus lock.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry spanname="descr">
+When a given algorithm is not enabled, drivers should ignore requests
+to lock it and should return no error. An example might be an application
+setting bit <constant>V4L2_LOCK_WHITE_BALANCE</constant> when the
+<constant>V4L2_CID_AUTO_WHITE_BALANCE</constant> control is set to
+<constant>FALSE</constant>. The value of this control may be changed
+by exposure, white balance or focus controls.</entry>
+	  </row>
+	  <row><entry></entry></row>
+
 	</tbody>
       </tgroup>
     </table>
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 386f20c..6346978 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -654,6 +654,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_ISO_SENSITIVITY_AUTO:	return "ISO Sensitivity, Auto";
 	case V4L2_CID_EXPOSURE_METERING:	return "Exposure, Metering Mode";
 	case V4L2_CID_SCENE_MODE:		return "Scene Mode";
+	case V4L2_CID_3A_LOCK:			return "3A Lock";
 
 	/* FM Radio Modulator control */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -826,6 +827,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 		break;
 	case V4L2_CID_FLASH_FAULT:
 	case V4L2_CID_JPEG_ACTIVE_MARKER:
+	case V4L2_CID_3A_LOCK:
 		*type = V4L2_CTRL_TYPE_BITMASK;
 		break;
 	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index c672c13..c1fae94 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1744,6 +1744,11 @@ enum v4l2_scene_mode {
 	V4L2_SCENE_MODE_TEXT			= 13,
 };
 
+#define V4L2_CID_3A_LOCK			(V4L2_CID_CAMERA_CLASS_BASE+27)
+#define V4L2_LOCK_EXPOSURE			(1 << 0)
+#define V4L2_LOCK_WHITE_BALANCE			(1 << 1)
+#define V4L2_LOCK_FOCUS				(1 << 2)
+
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
 #define V4L2_CID_FM_TX_CLASS			(V4L2_CTRL_CLASS_FM_TX | 1)
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 10/12] V4L: Add auto focus targets to the selections API
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
                   ` (8 preceding siblings ...)
  2012-05-04 18:32 ` [PATCH/RFC v4 09/12] V4L: Add camera 3A lock control Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-06 18:22   ` Sakari Ailus
  2012-05-04 18:32 ` [PATCH/RFC v4 11/12] V4L: Add auto focus targets to the subdev " Sylwester Nawrocki
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

The camera automatic focus algorithms may require setting up
a spot or rectangle coordinates or multiple such parameters.

The automatic focus selection targets are introduced in order
to allow applications to query and set such coordinates. Those
selections are intended to be used together with the automatic
focus controls available in the camera control class.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/DocBook/media/v4l/selection-api.xml  |   33 +++++++++++++++++++-
 .../DocBook/media/v4l/vidioc-g-selection.xml       |   11 +++++++
 include/linux/videodev2.h                          |    5 +++
 3 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml
index b299e47..490d29a 100644
--- a/Documentation/DocBook/media/v4l/selection-api.xml
+++ b/Documentation/DocBook/media/v4l/selection-api.xml
@@ -1,6 +1,6 @@
 <section id="selection-api">
 
-  <title>Experimental API for cropping, composing and scaling</title>
+  <title>Experimental selections API</title>
 
       <note>
 	<title>Experimental</title>
@@ -9,6 +9,10 @@
 interface and may change in the future.</para>
       </note>
 
+ <section>
+
+ <title>Image cropping, composing and scaling</title>
+
   <section>
     <title>Introduction</title>
 
@@ -321,5 +325,32 @@ V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> for other devices</para>
       </example>
 
    </section>
+ </section>
+
+   <section>
+     <title>Automatic focus regions of interest</title>
+
+<para> The camera automatic focus algorithms may require configuration of
+regions of interest in form of rectangle or spot coordinates. The automatic
+focus selection targets allow applications to query and set such coordinates.
+Those selections are intended to be used together with the
+<constant>V4L2_CID_AUTO_FOCUS_AREA</constant> <link linkend="camera-controls">
+camera class</link> control. The <constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL
+</constant> target is used for querying or setting actual spot or rectangle
+coordinates, while <constant>V4L2_SEL_TGT_AUTO_FOCUS_BOUNDS</constant> target
+determines bounds for a single spot or rectangle.
+These selections are only effective when the <constant>V4L2_CID_AUTO_FOCUS_AREA
+</constant>control is set to <constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant> or
+<constant>V4L2_AUTO_FOCUS_AREA_RECTANGLE</constant>. The new coordinates shall
+be accepted and applied to hardware when the focus area control value is
+changed and also during a &VIDIOC-S-SELECTION; ioctl call, only when the focus
+area control is already set to required value.</para>
+
+<para> For the <constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant> case, the selection
+rectangle <structfield> width</structfield> and <structfield>height</structfield>
+are not used, i.e. shall be set to 0 by applications and ignored by drivers for
+the &VIDIOC-S-SELECTION; ioctl and shall be ignored by applications for the
+&VIDIOC-G-SELECTION; ioctl.</para>
+   </section>
 
 </section>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
index bb04eff..87df4da 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
@@ -195,6 +195,17 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
             <entry>0x0103</entry>
             <entry>The active area and all padding pixels that are inserted or modified by hardware.</entry>
 	  </row>
+	  <row>
+            <entry><constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant></entry>
+            <entry>0x1000</entry>
+	    <entry>Actual automatic focus rectangle or spot coordinates.</entry>
+	  </row>
+	  <row>
+            <entry><constant>V4L2_SEL_TGT_AUTO_FOCUS_BOUNDS</constant></entry>
+            <entry>0x1002</entry>
+            <entry>Bounds of the automatic focus region of interest.
+	    </entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index c1fae94..6bfd6c5 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -777,6 +777,11 @@ struct v4l2_crop {
 /* Current composing area plus all padding pixels */
 #define V4L2_SEL_TGT_COMPOSE_PADDED	0x0103
 
+/* Auto focus region of interest */
+#define V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL	0x1000
+/* Auto focus region (spot coordinates) bounds */
+#define V4L2_SEL_TGT_AUTO_FOCUS_BOUNDS	0x1001
+
 /**
  * struct v4l2_selection - selection info
  * @type:	buffer type (do not use *_MPLANE types)
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 11/12] V4L: Add auto focus targets to the subdev selections API
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
                   ` (9 preceding siblings ...)
  2012-05-04 18:32 ` [PATCH/RFC v4 10/12] V4L: Add auto focus targets to the selections API Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 12/12] V4L: Add camera auto focus controls Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 13/13] V4L: Add S5C73M3 sensor sub-device driver Sylwester Nawrocki
  12 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/DocBook/media/v4l/dev-subdev.xml     |   27 +++++++++++++++++++-
 .../media/v4l/vidioc-subdev-g-selection.xml        |   14 ++++++++--
 include/linux/v4l2-subdev.h                        |    4 +++
 3 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml
index 4afcbbe..8a212c4 100644
--- a/Documentation/DocBook/media/v4l/dev-subdev.xml
+++ b/Documentation/DocBook/media/v4l/dev-subdev.xml
@@ -277,7 +277,7 @@
     </section>
 
     <section>
-      <title>Selections: cropping, scaling and composition</title>
+      <title>Selections - cropping, scaling and composition</title>
 
       <para>Many sub-devices support cropping frames on their input or output
       pads (or possible even on both). Cropping is used to select the area of
@@ -330,6 +330,31 @@
     </section>
 
     <section>
+      <title>Selections - regions of interest</title>
+    <section>
+      <title>Automatic focus</title>
+
+      <para>The camera automatic focus algorithms may require configuration
+      of a region or multiple regions of interest in form of rectangle or spot
+      coordinates.</para>
+
+      <para>A single rectangle of interest is represented in &v4l2-rect;
+      by the coordinates of the top left corner and the rectangle size. Both
+      the coordinates and sizes are expressed in pixels. When the <structfield>
+      width</structfield> and <structfield>height</structfield> fields of
+      &v4l2-rect; are set to 0 the selection determines spot coordinates,
+      rather than a rectangle.</para>
+
+      <para>Auto focus rectangles are reset to their default values when the
+      output image format is modified. Drivers should use the output image size
+      as the auto focus rectangle default value, but hardware requirements may
+      prevent this.
+      </para>
+      <para>The auto focus selections on input pads are not defined.</para>
+    </section>
+    </section>
+
+    <section>
       <title>Types of selection targets</title>
 
       <section>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
index 208e9f0..c4ccae5 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
@@ -57,8 +57,8 @@
 
     <para>The selections are used to configure various image
     processing functionality performed by the subdevs which affect the
-    image size. This currently includes cropping, scaling and
-    composition.</para>
+    image size. This currently includes cropping, scaling, composition
+    and automatic focus regions of interest.</para>
 
     <para>The selection API replaces <link
     linkend="vidioc-subdev-g-crop">the old subdev crop API</link>. All
@@ -114,6 +114,16 @@
 	    <entry>0x0102</entry>
 	    <entry>Bounds of the compose rectangle.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_BOUNDS</constant></entry>
+	    <entry>0x1000</entry>
+	    <entry>Bounds of the automatic focus region of interest.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant></entry>
+	    <entry>0x1001</entry>
+	    <entry>Actual automatic focus rectangle or spot coordinates.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h
index 812019e..49b1f14 100644
--- a/include/linux/v4l2-subdev.h
+++ b/include/linux/v4l2-subdev.h
@@ -136,6 +136,10 @@ struct v4l2_subdev_frame_interval_enum {
 /* composing bounds */
 #define V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS		0x0102
 
+/* auto focus region of interest */
+#define V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL		0x1000
+/* auto focus region (spot coordinates) bounds */
+#define V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_BOUNDS		0x1001
 
 /**
  * struct v4l2_subdev_selection - selection info
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 12/12] V4L: Add camera auto focus controls
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
                   ` (10 preceding siblings ...)
  2012-05-04 18:32 ` [PATCH/RFC v4 11/12] V4L: Add auto focus targets to the subdev " Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  2012-05-06 18:46   ` Sakari Ailus
  2012-05-06 18:58   ` [PATCH v5 " Sylwester Nawrocki
  2012-05-04 18:32 ` [PATCH/RFC v4 13/13] V4L: Add S5C73M3 sensor sub-device driver Sylwester Nawrocki
  12 siblings, 2 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

Add following auto focus controls:

 - V4L2_CID_AUTO_FOCUS_START - single-shot auto focus start
 - V4L2_CID_AUTO_FOCUS_STOP -  single-shot auto focus stop
 - V4L2_CID_AUTO_FOCUS_STATUS - automatic focus status
 - V4L2_CID_AUTO_FOCUS_AREA - automatic focus area selection
 - V4L2_CID_AUTO_FOCUS_DISTANCE - automatic focus scan range selection

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/DocBook/media/v4l/controls.xml |  147 +++++++++++++++++++++++++-
 drivers/media/video/v4l2-ctrls.c             |   31 +++++-
 include/linux/videodev2.h                    |   25 +++++
 3 files changed, 200 insertions(+), 3 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 4a463d3..d8ef71e 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -2902,13 +2902,156 @@ negative values towards infinity. This is a write-only control.</entry>
 	  <row>
 	    <entry spanname="id"><constant>V4L2_CID_FOCUS_AUTO</constant>&nbsp;</entry>
 	    <entry>boolean</entry>
-	  </row><row><entry spanname="descr">Enables automatic focus
-adjustments. The effect of manual focus adjustments while this feature
+	  </row><row><entry spanname="descr">Enables continuous automatic
+focus adjustments. The effect of manual focus adjustments while this feature
 is enabled is undefined, drivers should ignore such requests.</entry>
 	  </row>
 	  <row><entry></entry></row>
 
 	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_START</constant>&nbsp;</entry>
+	    <entry>button</entry>
+	  </row><row><entry spanname="descr">Starts single auto focus process.
+The effect of setting this control when <constant>V4L2_CID_FOCUS_AUTO</constant>
+is set to <constant>TRUE</constant> (1) is undefined, drivers should ignore
+such requests.</entry>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_STOP</constant>&nbsp;</entry>
+	    <entry>button</entry>
+	  </row><row><entry spanname="descr">Aborts automatic focusing
+started with <constant>V4L2_CID_AUTO_FOCUS_START</constant> control. It is
+effective only when the continuous autofocus is disabled, that is when
+<constant>V4L2_CID_FOCUS_AUTO</constant> control is set to <constant>FALSE
+</constant> (0).</entry>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row id="v4l2-auto-focus-status">
+	    <entry spanname="id">
+	      <constant>V4L2_CID_AUTO_FOCUS_STATUS</constant>&nbsp;</entry>
+	    <entry>bitmask</entry>
+	  </row>
+	  <row><entry spanname="descr">The automatic focus status. This is a read-only
+	  control.</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_IDLE</constant>&nbsp;</entry>
+		  <entry>Automatic focus is not active.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_BUSY</constant>&nbsp;</entry>
+		  <entry>Automatic focusing is in progress.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_REACHED</constant>&nbsp;</entry>
+		  <entry>Focus has been reached.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_LOST</constant>&nbsp;</entry>
+		  <entry>Focus has been lost.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_FAILED</constant>&nbsp;</entry>
+		  <entry>Automatic focus has failed, the driver will not
+		  transition from this state until another action is
+		  performed by an  application.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row id="v4l2-auto-focus-range">
+	    <entry spanname="id">
+	      <constant>V4L2_CID_AUTO_FOCUS_RANGE</constant>&nbsp;</entry>
+	    <entry>enum&nbsp;v4l2_auto_focus_range</entry>
+	  </row>
+	  <row><entry spanname="descr">Determines auto focus distance range
+for which lens may be adjusted. </entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_AUTO</constant>&nbsp;</entry>
+		  <entry>The camera automatically selects the focus range.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_NORMAL</constant>&nbsp;</entry>
+		  <entry>The auto focus normal distance range. It is limited
+for best auto focus algorithm performance.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_MACRO</constant>&nbsp;</entry>
+		  <entry>Macro (close-up) auto focus. The camera will
+use minimum possible distance that it is capable of for auto focus.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_INFINITY</constant>&nbsp;</entry>
+		  <entry>The focus at an object at infinite distance.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row id="v4l2-auto-focus-area">
+	    <entry spanname="id">
+	      <constant>V4L2_CID_AUTO_FOCUS_AREA</constant>&nbsp;</entry>
+	    <entry>enum&nbsp;v4l2_auto_focus_area</entry>
+	  </row>
+	  <row><entry spanname="descr">Determines the area of the frame that
+the camera uses for automatic focus. The corresponding coordinates of the
+focusing spot or rectangle can be specified and queried using the selection API.
+To change the auto focus region of interest applications first select required
+mode of this control and then set the rectangle or spot coordinates by means
+of the &VIDIOC-SUBDEV-S-SELECTION; or &VIDIOC-S-SELECTION; ioctl. In order to
+trigger again an auto focus process with same coordinates applications should
+use the <constant>V4L2_CID_AUTO_FOCUS_START </constant> control. Or alternatively
+invoke a &VIDIOC-SUBDEV-S-SELECTION; or a &VIDIOC-S-SELECTION; ioctl again.
+In the latter case the new pixel coordinates are applied to hardware only when
+the focus area control is set to a value other than
+<constant>V4L2_AUTO_FOCUS_AREA_ALL</constant>.</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_AREA_ALL</constant>&nbsp;</entry>
+		  <entry>Normal auto focus, the focusing area extends over the
+entire frame.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant>&nbsp;</entry>
+		  <entry>Automatic focus on a spot within the frame at position
+specified by the <constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> or
+<constant>V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> selection. When these
+selections are not supported by driver the default spot's position is center of
+the frame.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_AREA_RECTANGLE</constant>&nbsp;</entry>
+		  <entry>The auto focus area is determined by the <constant>
+V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> or <constant>
+V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> selection rectangle.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_AREA_FACE_DETECTION</constant>&nbsp;</entry>
+		  <entry>The camera automatically focuses on a detected face
+area.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row>
 	    <entry spanname="id"><constant>V4L2_CID_ZOOM_ABSOLUTE</constant>&nbsp;</entry>
 	    <entry>integer</entry>
 	  </row><row><entry spanname="descr">Specify the objective lens
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 6346978..ea86a10 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -236,6 +236,20 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		"Spot",
 		NULL
 	};
+	static const char * const camera_auto_focus_area[] = {
+		"All",
+		"Spot",
+		"Rectangle",
+		"Face Detection",
+		NULL
+	};
+	static const char * const camera_auto_focus_range[] = {
+		"Auto",
+		"Normal",
+		"Macro",
+		"Infinity",
+		NULL
+	};
 	static const char * const colorfx[] = {
 		"None",
 		"Black & White",
@@ -453,6 +467,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		return camera_exposure_auto;
 	case V4L2_CID_EXPOSURE_METERING:
 		return camera_exposure_metering;
+	case V4L2_CID_AUTO_FOCUS_AREA:
+		return camera_auto_focus_area;
+	case V4L2_CID_AUTO_FOCUS_RANGE:
+		return camera_auto_focus_range;
 	case V4L2_CID_COLORFX:
 		return colorfx;
 	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
@@ -639,7 +657,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_TILT_ABSOLUTE:		return "Tilt, Absolute";
 	case V4L2_CID_FOCUS_ABSOLUTE:		return "Focus, Absolute";
 	case V4L2_CID_FOCUS_RELATIVE:		return "Focus, Relative";
-	case V4L2_CID_FOCUS_AUTO:		return "Focus, Automatic";
+	case V4L2_CID_FOCUS_AUTO:		return "Focus, Automatic Continuous";
 	case V4L2_CID_ZOOM_ABSOLUTE:		return "Zoom, Absolute";
 	case V4L2_CID_ZOOM_RELATIVE:		return "Zoom, Relative";
 	case V4L2_CID_ZOOM_CONTINUOUS:		return "Zoom, Continuous";
@@ -655,6 +673,11 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_EXPOSURE_METERING:	return "Exposure, Metering Mode";
 	case V4L2_CID_SCENE_MODE:		return "Scene Mode";
 	case V4L2_CID_3A_LOCK:			return "3A Lock";
+	case V4L2_CID_AUTO_FOCUS_START:		return "Auto Focus, Start";
+	case V4L2_CID_AUTO_FOCUS_STOP:		return "Auto Focus, Stop";
+	case V4L2_CID_AUTO_FOCUS_STATUS:	return "Auto Focus, Status";
+	case V4L2_CID_AUTO_FOCUS_RANGE:		return "Auto Focus, Range";
+	case V4L2_CID_AUTO_FOCUS_AREA:		return "Auto Focus, Area";
 
 	/* FM Radio Modulator control */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -756,6 +779,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_TILT_RESET:
 	case V4L2_CID_FLASH_STROBE:
 	case V4L2_CID_FLASH_STROBE_STOP:
+	case V4L2_CID_AUTO_FOCUS_START:
+	case V4L2_CID_AUTO_FOCUS_STOP:
 		*type = V4L2_CTRL_TYPE_BUTTON;
 		*flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
 		*min = *max = *step = *def = 0;
@@ -779,6 +804,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_MPEG_STREAM_TYPE:
 	case V4L2_CID_MPEG_STREAM_VBI_FMT:
 	case V4L2_CID_EXPOSURE_AUTO:
+	case V4L2_CID_AUTO_FOCUS_AREA:
+	case V4L2_CID_AUTO_FOCUS_RANGE:
 	case V4L2_CID_COLORFX:
 	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
 	case V4L2_CID_TUNE_PREEMPHASIS:
@@ -828,6 +855,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_FLASH_FAULT:
 	case V4L2_CID_JPEG_ACTIVE_MARKER:
 	case V4L2_CID_3A_LOCK:
+	case V4L2_CID_AUTO_FOCUS_STATUS:
 		*type = V4L2_CTRL_TYPE_BITMASK;
 		break;
 	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
@@ -887,6 +915,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 		*flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
 		break;
 	case V4L2_CID_FLASH_STROBE_STATUS:
+	case V4L2_CID_AUTO_FOCUS_STATUS:
 	case V4L2_CID_FLASH_READY:
 		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
 		break;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 6bfd6c5..1d5b839 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1754,6 +1754,31 @@ enum v4l2_scene_mode {
 #define V4L2_LOCK_WHITE_BALANCE			(1 << 1)
 #define V4L2_LOCK_FOCUS				(1 << 2)
 
+#define V4L2_CID_AUTO_FOCUS_START		(V4L2_CID_CAMERA_CLASS_BASE+28)
+#define V4L2_CID_AUTO_FOCUS_STOP		(V4L2_CID_CAMERA_CLASS_BASE+29)
+#define V4L2_CID_AUTO_FOCUS_STATUS		(V4L2_CID_CAMERA_CLASS_BASE+30)
+#define V4L2_AUTO_FOCUS_STATUS_IDLE		(0 << 0)
+#define V4L2_AUTO_FOCUS_STATUS_BUSY		(1 << 0)
+#define V4L2_AUTO_FOCUS_STATUS_REACHED		(1 << 1)
+#define V4L2_AUTO_FOCUS_STATUS_LOST		(1 << 2)
+#define V4L2_AUTO_FOCUS_STATUS_FAILED		(1 << 3)
+
+#define V4L2_CID_AUTO_FOCUS_RANGE		(V4L2_CID_CAMERA_CLASS_BASE+31)
+enum v4l2_auto_focus_range {
+	V4L2_AUTO_FOCUS_RANGE_AUTO		= 0,
+	V4L2_AUTO_FOCUS_RANGE_NORMAL		= 1,
+	V4L2_AUTO_FOCUS_RANGE_MACRO		= 2,
+	V4L2_AUTO_FOCUS_RANGE_INFINITY		= 3,
+};
+
+#define V4L2_CID_AUTO_FOCUS_AREA		(V4L2_CID_CAMERA_CLASS_BASE+32)
+enum v4l2_auto_focus_area {
+	V4L2_AUTO_FOCUS_AREA_ALL		= 0,
+	V4L2_AUTO_FOCUS_AREA_SPOT		= 1,
+	V4L2_AUTO_FOCUS_AREA_RECTANGLE		= 2,
+	V4L2_AUTO_FOCUS_AREA_FACE_DETECTION	= 3,
+};
+
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
 #define V4L2_CID_FM_TX_CLASS			(V4L2_CTRL_CLASS_FM_TX | 1)
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH/RFC v4 13/13] V4L: Add S5C73M3 sensor sub-device driver
  2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
                   ` (11 preceding siblings ...)
  2012-05-04 18:32 ` [PATCH/RFC v4 12/12] V4L: Add camera auto focus controls Sylwester Nawrocki
@ 2012-05-04 18:32 ` Sylwester Nawrocki
  12 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-04 18:32 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, sakari.ailus, g.liakhovetski, hdegoede,
	moinejf, hverkuil, m.szyprowski, riverful.kim, sw0312.kim,
	s.nawrocki, Kyungmin Park

 - initial working version
 - public header cleanup
 - add SPI slave driver and FW upload support
 - firmware load cleanup
 - change SPI driver initialization method
 - move SPI driver to separate file
 - capture context control
 - frame size enumeration
 - update to changed controls

This driver is a work in progress, it is included in this series
only to demonstrate how the new controls are used.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/Kconfig                 |    8 +
 drivers/media/video/Makefile                |    1 +
 drivers/media/video/s5c73m3/Makefile        |    3 +
 drivers/media/video/s5c73m3/s5c73m3-ctrls.c |  687 +++++++++++++++
 drivers/media/video/s5c73m3/s5c73m3-spi.c   |  126 +++
 drivers/media/video/s5c73m3/s5c73m3.c       | 1243 +++++++++++++++++++++++++++
 drivers/media/video/s5c73m3/s5c73m3.h       |  442 ++++++++++
 include/media/s5c73m3.h                     |   62 ++
 8 files changed, 2572 insertions(+)
 create mode 100644 drivers/media/video/s5c73m3/Makefile
 create mode 100644 drivers/media/video/s5c73m3/s5c73m3-ctrls.c
 create mode 100644 drivers/media/video/s5c73m3/s5c73m3-spi.c
 create mode 100644 drivers/media/video/s5c73m3/s5c73m3.c
 create mode 100644 drivers/media/video/s5c73m3/s5c73m3.h
 create mode 100644 include/media/s5c73m3.h

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index f2479c5..4dd2aeb 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -556,6 +556,14 @@ config VIDEO_S5K6AA
 	  This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
 	  camera sensor with an embedded SoC image signal processor.
 
+config VIDEO_S5C73M3
+	tristate "Samsung S5C73M3 sensor support (experimental)"
+	depends on I2C && SPI && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	depends on EXPERIMENTAL
+	---help---
+	  This is a V4L2 sensor-level driver for Samsung S5C73M3
+	  8 Mpixel camera.
+
 comment "Flash devices"
 
 config VIDEO_ADP1653
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index a6282a3..ef3d954 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_VIDEO_SR030PC30)	+= sr030pc30.o
 obj-$(CONFIG_VIDEO_NOON010PC30)	+= noon010pc30.o
 obj-$(CONFIG_VIDEO_M5MOLS)	+= m5mols/
 obj-$(CONFIG_VIDEO_S5K6AA)	+= s5k6aa.o
+obj-$(CONFIG_VIDEO_S5C73M3)	+= s5c73m3/
 obj-$(CONFIG_VIDEO_ADP1653)	+= adp1653.o
 obj-$(CONFIG_VIDEO_AS3645A)	+= as3645a.o
 
diff --git a/drivers/media/video/s5c73m3/Makefile b/drivers/media/video/s5c73m3/Makefile
new file mode 100644
index 0000000..c8a0a40
--- /dev/null
+++ b/drivers/media/video/s5c73m3/Makefile
@@ -0,0 +1,3 @@
+# Makefile for S5C73M3 camera driver
+
+obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3.o s5c73m3-spi.o s5c73m3-ctrls.o
diff --git a/drivers/media/video/s5c73m3/s5c73m3-ctrls.c b/drivers/media/video/s5c73m3/s5c73m3-ctrls.c
new file mode 100644
index 0000000..aa93889
--- /dev/null
+++ b/drivers/media/video/s5c73m3/s5c73m3-ctrls.c
@@ -0,0 +1,687 @@
+/*
+ * Samsung LSI S5C73M3 8M pixel camera driver
+ *
+ * Copyright (C) 2012, Samsung Electronics, Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+
+#include <asm/sizes.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/media.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/videodev2.h>
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-mediabus.h>
+#include <media/s5c73m3.h>
+
+#include "s5c73m3.h"
+
+static int s5c73m3_get_af_status(struct s5c73m3 *state, struct v4l2_ctrl *ctrl)
+{
+	u16 reg = REG_AF_STATUS_UNFOCUSED;
+
+	int err = s5c73m3_read(state->i2c_client, REG_AF_STATUS, &reg);
+	/*err = s5c73m3_read(sd, 0x0009, 0x5840, &temp_status);*/
+
+	switch (reg) {
+	case REG_CAF_STATUS_FIND_SEARCH_DIR:
+	case REG_AF_STATUS_FOCUSING:
+	case REG_CAF_STATUS_FOCUSING:
+		ctrl->val = V4L2_AUTO_FOCUS_STATUS_BUSY;
+		break;
+	case REG_CAF_STATUS_FOCUSED:
+	case REG_AF_STATUS_FOCUSED:
+		ctrl->val = V4L2_AUTO_FOCUS_STATUS_REACHED;
+		break;
+	case REG_CAF_STATUS_UNFOCUSED:
+	case REG_AF_STATUS_UNFOCUSED:
+		ctrl->val = V4L2_AUTO_FOCUS_STATUS_LOST;
+		break;
+	default:
+		v4l2_info(&state->subdev, "Unknown AF status\n");
+		/* Fall through */
+	case REG_AF_STATUS_INVALID:
+		ctrl->val = V4L2_AUTO_FOCUS_STATUS_FAILED;
+		break;
+	}
+
+	return err;
+}
+
+static int s5c73m3_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	int err;
+
+	v4l2_dbg(1, s5c73m3_dbg, sd, "%s: ctrl: %s\n", __func__, ctrl->name);
+
+	if (state->power == 0)
+		return -EBUSY;
+
+	switch (ctrl->id) {
+	case V4L2_CID_FIRMWARE_VERSION:
+		/* FIXME: */
+		/* strlcpy(ctrl->string, state->exif.unique_id, ctrl->maximum); */
+		break;
+
+	case V4L2_CID_FOCUS_AUTO:
+		err = s5c73m3_get_af_status(state, state->ctrls.af_status);
+		if (err)
+			return err;
+		v4l2_dbg(1, s5c73m3_dbg, sd, "AF status: %#x\n",
+			 state->ctrls.af_status->val);
+		break;
+	}
+
+	return 0;
+}
+
+static int s5c73m3_set_colorfx(struct s5c73m3 *state, int val)
+{
+	static const unsigned short colorfx[][2] = {
+		{ V4L2_COLORFX_NONE,	 REG_IMAGE_EFFECT_NONE },
+		{ V4L2_COLORFX_BW,	 REG_IMAGE_EFFECT_MONO },
+		{ V4L2_COLORFX_SEPIA,	 REG_IMAGE_EFFECT_SEPIA },
+		{ V4L2_COLORFX_NEGATIVE, REG_IMAGE_EFFECT_NEGATIVE },
+		{ V4L2_COLORFX_AQUA,	 REG_IMAGE_EFFECT_AQUA },
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(colorfx); i++) {
+		if (colorfx[i][0] != val)
+			continue;
+
+		v4l2_dbg(1, s5c73m3_dbg, &state->subdev,
+			 "Setting %s color effect\n",
+			 v4l2_ctrl_get_menu(state->ctrls.colorfx->id)[i]);
+
+		return s5c73m3_write_cmd(state, REG_IMAGE_EFFECT,
+					 colorfx[i][1]);
+	}
+	return -EINVAL;
+}
+
+/* Set exposure metering/exposure bias */
+static int s5c73m3_set_exposure(struct s5c73m3 *state, int auto_exp)
+{
+	struct v4l2_subdev *sd = &state->subdev;
+	struct s5c73m3_ctrls *ctrls = &state->ctrls;
+	int err = 0;
+
+	if (ctrls->exposure_metering->is_new) {
+		u16 metering;
+
+		switch (ctrls->exposure_metering->val) {
+		case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
+			metering = REG_METERING_CENTER;
+			break;
+		case V4L2_EXPOSURE_METERING_SPOT:
+			metering = REG_METERING_SPOT;
+			break;
+		default:
+			metering = REG_METERING_AVERAGE;
+			break;
+		}
+
+		err = s5c73m3_write_cmd(state, REG_METERING, metering);
+	}
+
+	if (!err && ctrls->exposure_bias->is_new) {
+		u16 exp_bias = ctrls->exposure_bias->val;
+		err = s5c73m3_write_cmd(state, REG_EV, exp_bias);
+	}
+
+	v4l2_dbg(1, s5c73m3_dbg, sd,
+		 "%s: exposure bias: %#x, metering: %#x (%d)\n",  __func__,
+		 ctrls->exposure_bias->val, ctrls->exposure_metering->val, err);
+
+	return err;
+}
+
+static int s5c73m3_set_white_balance(struct s5c73m3 *state, int val)
+{
+	static const unsigned short wb[][2] = {
+		{ V4L2_WHITE_BALANCE_INCANDESCENT,  REG_AWB_MODE_INCANDESCENT },
+		{ V4L2_WHITE_BALANCE_FLUORESCENT,   REG_AWB_MODE_FLUORESCENT1 },
+		{ V4L2_WHITE_BALANCE_FLUORESCENT_H, REG_AWB_MODE_FLUORESCENT2 },
+		{ V4L2_WHITE_BALANCE_CLOUDY,        REG_AWB_MODE_CLOUDY },
+		{ V4L2_WHITE_BALANCE_DAYLIGHT,      REG_AWB_MODE_DAYLIGHT },
+		{ V4L2_WHITE_BALANCE_AUTO,          REG_AWB_MODE_AUTO },
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wb); i++) {
+		if (wb[i][0] != val)
+			continue;
+
+		v4l2_dbg(1, s5c73m3_dbg, &state->subdev,
+			 "Setting white balance to: %s\n",
+			 v4l2_ctrl_get_menu(state->ctrls.auto_wb->id)[i]);
+
+		return s5c73m3_write_cmd(state, REG_AWB_MODE, wb[i][1]);
+	}
+
+	return -EINVAL;
+}
+
+static int s5c73m3_3a_lock(struct s5c73m3 *state, struct v4l2_ctrl *ctrl)
+{
+	bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE;
+	bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE;
+	int err = 0;
+
+	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
+		err = s5c73m3_write_cmd(state, REG_AE_CON,
+				ae_lock ? REG_AE_STOP : REG_AE_START);
+		if (err)
+			return err;
+	}
+
+	if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
+	    && state->ctrls.auto_wb->val) {
+		err = s5c73m3_write_cmd(state, REG_AWB_CON,
+			awb_lock ? REG_AWB_STOP : REG_AWB_START);
+	}
+
+	return err;
+}
+
+/* TODO: focus untested */
+
+static int s5c73m3_set_touch_auto_focus(struct s5c73m3 *state)
+{
+	struct v4l2_mbus_framefmt *mf = &state->format[PREVIEW_IDX];
+	struct i2c_client *client = state->i2c_client;
+	int err;
+
+	err = s5c73m3_i2c_write(client, 0xfcfc, 0x3310);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0050, 0x0009);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0054, REG_AF_TOUCH_POSITION);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0f14, state->focus.pos_x);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0f14, state->focus.pos_y);
+	/* FIXME: Find out what this width/height is really for */
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0f14, mf->width);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0f14, mf->height);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0050, 0x0009);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0054, 0x5000);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0f14, 0x0e0a);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0f14, 0x0000);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0054, 0x5080);
+	if (!err)
+		err = s5c73m3_i2c_write(client, 0x0f14, 0x0001);
+
+	return err;
+}
+
+static int s5c73m3_set_auto_focus(struct s5c73m3 *state, int caf)
+{
+	struct v4l2_subdev *sd = &state->subdev;
+	struct s5c73m3_ctrls *ctrls = &state->ctrls;
+	u8 af_mode = 0;
+	int err = 0;
+
+	if (ctrls->af_distance->is_new) {
+		switch (ctrls->af_distance->val) {
+		case V4L2_AUTO_FOCUS_RANGE_MACRO:
+			af_mode = 0;
+			break;
+		case V4L2_AUTO_FOCUS_RANGE_INFINITY:
+			af_mode = 0;
+			break;
+		case V4L2_AUTO_FOCUS_RANGE_NORMAL:
+			af_mode = 0;
+			break;
+		}
+	}
+
+	if (ctrls->af_area->is_new) {
+		if (ctrls->af_area->val == V4L2_AUTO_FOCUS_AREA_SPOT) {
+			v4l2_ctrl_activate(ctrls->af_distance, 0);
+			af_mode = 0;
+		} else {
+			/*
+			 * Activate the auto focus distance control only if
+			 * auto focus area is set to V4L2_AUTO_FOCUS_AREA_ALL
+			 */
+			v4l2_ctrl_activate(ctrls->af_distance, 1);
+		}
+	}
+
+	v4l2_dbg(1, s5c73m3_dbg, sd, "af_mode: %#x\n", af_mode);
+
+	if (ctrls->af_area->val == V4L2_AUTO_FOCUS_AREA_SPOT) {
+		err = s5c73m3_set_touch_auto_focus(state);
+		if (err < 0)
+			return err;
+
+		v4l2_dbg(1, s5c73m3_dbg, sd, "Focus position: x: %u, y: %u\n",
+			 state->focus.pos_x, state->focus.pos_y);
+	}
+
+	if (ctrls->af_stop->is_new) {
+		err = 0;
+		if (err < 0)
+			return err;
+		v4l2_dbg(1, s5c73m3_dbg, sd, "Auto focus stopped\n");
+	}
+
+	if (ctrls->af_start->is_new || ctrls->focus_auto->is_new) {
+		/* Start continuous or one-shot auto focusing */
+		err = 0;
+		v4l2_dbg(1, s5c73m3_dbg, sd, "%s auto focus started\n",
+			 caf ? "Continuous" : "One-shot");
+	}
+
+	v4l2_dbg(1, s5c73m3_dbg, sd, "af_mode: %#x (%d)\n", af_mode, err);
+
+	return err;
+}
+
+static int s5c73m3_set_contrast(struct s5c73m3 *state, int val)
+{
+	u16 reg = (val < 0) ? -val + 2 : val;
+	return s5c73m3_write_cmd(state, REG_CONTRAST, reg);
+}
+
+static int s5c73m3_set_saturation(struct s5c73m3 *state, int val)
+{
+	u16 reg = (val < 0) ? -val + 2 : val;
+	return s5c73m3_write_cmd(state, REG_SATURATION, reg);
+}
+
+static int s5c73m3_set_sharpness(struct s5c73m3 *state, int val)
+{
+	u16 reg = (val < 0) ? -val + 2 : val;
+	return s5c73m3_write_cmd(state, REG_SHARPNESS, reg);
+}
+
+static int s5c73m3_set_iso(struct s5c73m3 *state, int val)
+{
+	u32 iso;
+
+	if (val == V4L2_ISO_SENSITIVITY_MANUAL)
+		iso = state->ctrls.iso->val + 1;
+	else
+		iso = 0;
+
+	return s5c73m3_write_cmd(state, REG_ISO, iso);
+}
+
+static int s5c73m3_set_stabilization(struct s5c73m3 *state, int val)
+{
+	struct v4l2_subdev *sd = &state->subdev;
+
+	v4l2_dbg(1, s5c73m3_dbg, sd, "Image stabilization: %d\n", val);
+
+	return s5c73m3_write_cmd(state, REG_AE_MODE, val  ?
+				 REG_AE_MODE_ANTI_SHAKE : REG_AE_MODE_AUTO_SET);
+}
+
+static int s5c73m3_set_still_capture(struct s5c73m3 *state, int on)
+{
+	return 0;
+}
+
+static int s5c73m3_set_jpeg_quality(struct s5c73m3 *state, int quality)
+{
+	int reg;
+
+	if (quality <= 65)
+		reg = REG_IMAGE_QUALITY_NORMAL;
+	else if (quality <= 75)
+		reg = REG_IMAGE_QUALITY_FINE;
+	else
+		reg = REG_IMAGE_QUALITY_SUPERFINE;
+
+	return s5c73m3_write_cmd(state, REG_IMAGE_QUALITY, reg);
+}
+
+static int s5c73m3_set_flash(struct s5c73m3 *state, int val)
+{
+	int err, flash;
+
+	switch (val) {
+	case FLASH_MODE_AUTO:
+		flash = REG_FLASH_MODE_AUTO;
+		break;
+	case FLASH_MODE_ON:
+		flash = REG_FLASH_MODE_ON;
+		break;
+	default:
+		flash = REG_FLASH_MODE_OFF;
+		break;
+	}
+
+	err = s5c73m3_write_cmd(state, REG_FLASH_MODE, flash);
+	if (err)
+		return err;
+	return s5c73m3_write_cmd(state, REG_FLASH_TORCH,
+				 val == FLASH_MODE_TORCH);
+}
+
+static int s5c73m3_set_scene_program(struct s5c73m3 *state, int val)
+{
+	static const unsigned short scene_lookup[] = {
+		REG_SCENE_MODE_NONE,	     /* V4L2_SCENE_MODE_NONE */
+		REG_SCENE_MODE_AGAINST_LIGHT,/* V4L2_SCENE_MODE_BACKLIGHT */
+		REG_SCENE_MODE_BEACH,	     /* V4L2_SCENE_MODE_BEACH_SNOW */
+		REG_SCENE_MODE_CANDLE,	     /* V4L2_SCENE_MODE_CANDLE_LIGHT */
+		REG_SCENE_MODE_DAWN,	     /* V4L2_SCENE_MODE_DAWN_DUSK */
+		REG_SCENE_MODE_FALL,	     /* V4L2_SCENE_MODE_FALL_COLORS */
+		REG_SCENE_MODE_FIRE,	     /* V4L2_SCENE_MODE_FIREWORKS */
+		REG_SCENE_MODE_LANDSCAPE,    /* V4L2_SCENE_MODE_LANDSCAPE */
+		REG_SCENE_MODE_NIGHT,	     /* V4L2_SCENE_MODE_NIGHT */
+		REG_SCENE_MODE_INDOOR,	     /* V4L2_SCENE_MODE_PARTY_INDOOR */
+		REG_SCENE_MODE_PORTRAIT,     /* V4L2_SCENE_MODE_PORTRAIT */
+		REG_SCENE_MODE_SPORTS,	     /* V4L2_SCENE_MODE_SPORTS */
+		REG_SCENE_MODE_SUNSET,	     /* V4L2_SCENE_MODE_SUNSET */
+		REG_SCENE_MODE_TEXT,	     /* V4L2_SCENE_MODE_TEXT */
+	};
+
+	v4l2_dbg(1, s5c73m3_dbg, &state->subdev, "Setting %s scene mode\n",
+		 v4l2_ctrl_get_menu(state->ctrls.scene_mode->id)[val]);
+
+	return s5c73m3_write_cmd(state, REG_SCENE_MODE, scene_lookup[val]);
+}
+
+static int s5c73m3_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
+	/* struct i2c_client *client = v4l2_get_subdevdata(sd); */
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	int err = 0;
+
+	v4l2_dbg(1, s5c73m3_dbg, sd, "ctrl: 0x%x, value: %d\n",
+		 ctrl->id, ctrl->val);
+
+	mutex_lock(&state->lock);
+	/*
+	 * If the device is not powered up by the host driver do
+	 * not apply any controls to H/W at this time. Instead
+	 * the controls will be restored right after power-up.
+	 */
+	if (state->power == 0)
+		goto unlock;
+
+	if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
+		return -EINVAL;
+
+	switch (ctrl->id) {
+	case V4L2_CID_3A_LOCK:
+		err = s5c73m3_3a_lock(state, ctrl);
+		break;
+
+	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
+		err = s5c73m3_set_white_balance(state, ctrl->val);
+		break;
+
+	case V4L2_CID_CONTRAST:
+		err = s5c73m3_set_contrast(state, ctrl->val);
+		break;
+
+	case V4L2_CID_COLORFX:
+		err = s5c73m3_set_colorfx(state, ctrl->val);
+		break;
+
+	case V4L2_CID_EXPOSURE_AUTO:
+		err = s5c73m3_set_exposure(state, ctrl->val);
+		break;
+
+	case V4L2_CID_FLASH_MODE:
+		err = s5c73m3_set_flash(state, ctrl->val);
+		break;
+
+	case V4L2_CID_FOCUS_AUTO:
+		err = s5c73m3_set_auto_focus(state, ctrl->val);
+		break;
+
+	case V4L2_CID_IMAGE_STABILIZATION:
+		err = s5c73m3_set_stabilization(state, ctrl->val);
+		break;
+
+	case V4L2_CID_ISO_SENSITIVITY:
+		err = s5c73m3_set_iso(state, ctrl->val);
+		break;
+
+	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+		err = s5c73m3_set_jpeg_quality(state, ctrl->val);
+		break;
+
+	case V4L2_CID_SATURATION:
+		err = s5c73m3_set_saturation(state, ctrl->val);
+		break;
+
+	case V4L2_CID_SCENE_MODE:
+		err = s5c73m3_set_scene_program(state, ctrl->val);
+		break;
+
+	case V4L2_CID_SHARPNESS:
+		err = s5c73m3_set_sharpness(state, ctrl->val);
+		break;
+
+	case V4L2_CID_SNAPSHOT:
+		err = s5c73m3_set_still_capture(state, ctrl->val);
+		break;
+
+	case V4L2_CID_WIDE_DYNAMIC_RANGE:
+		err = s5c73m3_write_cmd(state, REG_WDR, !!ctrl->val);
+		break;
+
+	case V4L2_CID_ZOOM_ABSOLUTE:
+		err = s5c73m3_write_cmd(state, REG_ZOOM_STEP, ctrl->val);
+		break;
+	}
+unlock:
+	mutex_unlock(&state->lock);
+	return err;
+}
+
+static const struct v4l2_ctrl_ops s5c73m3_ctrl_ops = {
+	.g_volatile_ctrl	= s5c73m3_g_volatile_ctrl,
+	.s_ctrl			= s5c73m3_s_ctrl,
+};
+
+static const char * const s5c73m3_flash_mode_menu[] = {
+	"Off", "Auto", "On", "Torch",
+};
+
+static const char * const s5c73m3_capture_ctx_menu[] = {
+	"Preview", "Still", "Camcorder",
+};
+
+static const struct v4l2_ctrl_config s5c73m3_ctrls[] = {
+	[0] = {
+		.ops = &s5c73m3_ctrl_ops,
+		.id = V4L2_CID_FIRMWARE_VERSION,
+		.type = V4L2_CTRL_TYPE_STRING,
+		.name = "Firmware version",
+		.min = 2,
+		.max = 128,
+		.step = 1,
+	},
+	[1] = {
+		.ops = &s5c73m3_ctrl_ops,
+		.id = V4L2_CID_CAPTURE_CTX,
+		.type = V4L2_CTRL_TYPE_MENU,
+		.name = "Capture Context",
+		.max = ARRAY_SIZE(s5c73m3_capture_ctx_menu) - 1,
+		.qmenu = s5c73m3_capture_ctx_menu,
+		.def = V4L2_CAPTURE_CTX_PREVIEW,
+	},
+	[2] = {
+		.ops = &s5c73m3_ctrl_ops,
+		.id = V4L2_CID_SNAPSHOT,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Snapshot",
+		.max = 1,
+		.step = 1,
+	},
+	[3] = {
+		.ops = &s5c73m3_ctrl_ops,
+		.id = V4L2_CID_FLASH_MODE,
+		.type = V4L2_CTRL_TYPE_MENU,
+		.name = "Flash Mode",
+		.max = ARRAY_SIZE(s5c73m3_flash_mode_menu) - 1,
+		.qmenu = s5c73m3_flash_mode_menu,
+	},
+};
+
+/* Supported manual ISO values */
+static const s64 iso_qmenu[] = {
+	/* REG_ISO: 0x0001...0x0004 */
+	100, 200, 400, 800,
+};
+
+/* Supported exposure bias values (-2.0EV...+2.0EV) */
+static const s64 ev_bias_qmenu[] = {
+	/* REG_EV: 0x0000...0x0008 */
+	-2000, -1500, -1000, -500, 0, 500, 1000, 1500, 2000
+};
+
+int s5c73m3_init_controls(struct s5c73m3 *state)
+{
+	const struct v4l2_ctrl_ops *ops = &s5c73m3_ctrl_ops;
+	struct s5c73m3_ctrls *ctrls = &state->ctrls;
+	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
+
+	int err = v4l2_ctrl_handler_init(hdl, 26);
+	if (err)
+		return err;
+
+	/* White balance */
+	ctrls->auto_wb = v4l2_ctrl_new_std_menu(hdl, ops,
+			V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
+			9, ~0x15e, V4L2_WHITE_BALANCE_AUTO);
+
+	/* Exposure (only automatic exposure) */
+	ctrls->auto_exposure = v4l2_ctrl_new_std_menu(hdl, ops,
+			V4L2_CID_EXPOSURE_AUTO, 0, ~0x01, V4L2_EXPOSURE_AUTO);
+
+	ctrls->exposure_bias = v4l2_ctrl_new_std_int_menu(hdl, ops,
+			V4L2_CID_AUTO_EXPOSURE_BIAS,
+			ARRAY_SIZE(ev_bias_qmenu) - 1,
+			ARRAY_SIZE(ev_bias_qmenu)/2 - 1,
+			ev_bias_qmenu);
+
+	ctrls->exposure_metering = v4l2_ctrl_new_std_menu(hdl, ops,
+			V4L2_CID_EXPOSURE_METERING,
+			2, ~0x7, V4L2_EXPOSURE_METERING_AVERAGE);
+
+	/* Auto focus */
+	ctrls->focus_auto = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_FOCUS_AUTO, 0, 1, 1, 0);
+
+	ctrls->af_start = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_AUTO_FOCUS_START, 0, 1, 1, 0);
+
+	ctrls->af_stop = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_AUTO_FOCUS_STOP, 0, 1, 1, 0);
+
+	ctrls->af_status = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_AUTO_FOCUS_STATUS, 0, 0x07, 0, 0);
+
+	ctrls->af_distance = v4l2_ctrl_new_std_menu(hdl, ops,
+			V4L2_CID_AUTO_FOCUS_RANGE, 2, ~0x1,
+			V4L2_AUTO_FOCUS_RANGE_NORMAL);
+
+	/* whole frame and spot */
+	ctrls->af_area = v4l2_ctrl_new_std_menu(hdl, ops,
+			V4L2_CID_AUTO_FOCUS_AREA, 1, ~0x03,
+			V4L2_AUTO_FOCUS_AREA_ALL);
+
+	/* ISO sensitivity */
+	ctrls->auto_iso = v4l2_ctrl_new_std_menu(hdl, ops,
+			V4L2_CID_ISO_SENSITIVITY_AUTO, 1, 0,
+			V4L2_ISO_SENSITIVITY_AUTO);
+
+	ctrls->iso = v4l2_ctrl_new_std_int_menu(hdl, ops,
+			V4L2_CID_ISO_SENSITIVITY, ARRAY_SIZE(iso_qmenu) - 1,
+			ARRAY_SIZE(iso_qmenu)/2 - 1, iso_qmenu);
+
+	ctrls->contrast = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_CONTRAST, -2, 2, 1, 0);
+
+	ctrls->saturation = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_SATURATION, -2, 2, 1, 0);
+
+	ctrls->sharpness = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_SHARPNESS, -2, 2, 1, 0);
+
+	ctrls->zoom = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_ZOOM_ABSOLUTE, 0, 30, 1, 0);
+
+	ctrls->colorfx = v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_COLORFX,
+			V4L2_COLORFX_AQUA, ~0x40f, V4L2_COLORFX_NONE);
+
+	ctrls->wdr = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_WIDE_DYNAMIC_RANGE, 0, 1, 1, 0);
+
+	ctrls->stabilization = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_IMAGE_STABILIZATION, 0, 1, 1, 0);
+
+	ctrls->jpeg_quality = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 80);
+
+	ctrls->scene_mode = v4l2_ctrl_new_std_menu(hdl, ops,
+			V4L2_CID_SCENE_MODE, V4L2_SCENE_MODE_TEXT, ~0x3fff,
+			V4L2_SCENE_MODE_NONE);
+
+	ctrls->ae_awb_lock = v4l2_ctrl_new_std(hdl, ops,
+			V4L2_CID_3A_LOCK, 0, 0x7, 0, 0);
+
+	v4l2_ctrl_new_custom(hdl, &s5c73m3_ctrls[0], NULL);
+	ctrls->capture_ctx = v4l2_ctrl_new_custom(hdl, &s5c73m3_ctrls[1], NULL);
+	ctrls->snapshot = v4l2_ctrl_new_custom(hdl, &s5c73m3_ctrls[2], NULL);
+	ctrls->flash_mode = v4l2_ctrl_new_custom(hdl, &s5c73m3_ctrls[3], NULL);
+
+	if (hdl->error) {
+		err = hdl->error;
+		v4l2_ctrl_handler_free(hdl);
+		return err;
+	}
+
+	v4l2_ctrl_auto_cluster(3, &ctrls->auto_exposure, 0, false);
+	ctrls->auto_iso->flags |= V4L2_CTRL_FLAG_VOLATILE |
+				V4L2_CTRL_FLAG_UPDATE;
+	v4l2_ctrl_auto_cluster(2, &ctrls->auto_iso, 0, false);
+	v4l2_ctrl_auto_cluster(2, &ctrls->auto_wb, 0, false);
+	ctrls->af_status->flags |= V4L2_CTRL_FLAG_VOLATILE;
+	v4l2_ctrl_cluster(6, &ctrls->focus_auto);
+
+	state->subdev.ctrl_handler = hdl;
+
+	return 0;
+}
diff --git a/drivers/media/video/s5c73m3/s5c73m3-spi.c b/drivers/media/video/s5c73m3/s5c73m3-spi.c
new file mode 100644
index 0000000..50c915e
--- /dev/null
+++ b/drivers/media/video/s5c73m3/s5c73m3-spi.c
@@ -0,0 +1,126 @@
+/*
+ * Samsung LSI S5C73M3 8M pixel camera driver
+ *
+ * Copyright (C) 2012, Samsung Electronics, Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/sizes.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/media.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+#include "s5c73m3.h"
+
+#define S5C73M3_SPI_DRV_NAME "S5C73M3-SPI"
+
+/*
+ * SPI driver
+ */
+static int spi_xmit(struct spi_device *spi_dev, const void *addr, const int len)
+{
+	struct spi_message msg;
+	int r;
+	struct spi_transfer xfer = {
+		.tx_buf	= addr,
+		.len	= len,
+	};
+
+	if (spi_dev == NULL) {
+		dev_err(&spi_dev->dev, "SPI device is uninitialized\n");
+		return -ENODEV;
+	}
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	r = spi_sync(spi_dev, &msg);
+	if (r < 0)
+		dev_err(&spi_dev->dev, "%s spi_sync failed %d\n", __func__, r);
+
+	return r;
+}
+
+int s5c73m3_spi_write(struct s5c73m3 *state, const void *addr,
+		      const unsigned int len, const unsigned int tx_size)
+{
+	struct spi_device *spi_dev = state->spi_dev;
+	u32 count = len / tx_size;
+	u32 extra = len % tx_size;
+	unsigned int i, j = 0;
+	u8 padding[32];
+	int r = 0;
+
+	memset(padding, 0, sizeof(padding));
+
+	for (i = 0; i < count ; i++) {
+		r = spi_xmit(spi_dev, addr + j, tx_size);
+		if (r < 0)
+			return r;
+		j += tx_size;
+	}
+
+	if (extra > 0) {
+		r = spi_xmit(spi_dev, addr + j, extra);
+		if (r < 0)
+			return r;
+	}
+
+	return spi_xmit(spi_dev, padding, sizeof(padding));
+}
+
+static int __devinit s5c73m3_spi_probe(struct spi_device *spi)
+{
+	int r;
+	struct s5c73m3 *state = container_of(spi->dev.driver, struct s5c73m3,
+					     spidrv.driver);
+	spi->bits_per_word = 32;
+
+	r = spi_setup(spi);
+	if (r < 0) {
+		dev_err(&spi->dev, "spi_setup() failed\n");
+		return r;
+	}
+
+	mutex_lock(&state->lock);
+	state->spi_dev = spi;
+	mutex_unlock(&state->lock);
+
+	v4l2_info(&state->subdev, "S5C73M3 SPI probed successfully\n");
+	return 0;
+}
+
+static int __devexit s5c73m3_spi_remove(struct spi_device *spi)
+{
+	return 0;
+}
+
+int s5c73m3_register_spi_driver(struct s5c73m3 *state)
+{
+	struct spi_driver *spidrv = &state->spidrv;
+
+	spidrv->remove = __devexit_p(s5c73m3_spi_remove);
+	spidrv->probe = s5c73m3_spi_probe;
+	spidrv->driver.name = S5C73M3_SPI_DRV_NAME;
+	spidrv->driver.bus = &spi_bus_type;
+	spidrv->driver.owner = THIS_MODULE;
+
+	return spi_register_driver(spidrv);
+}
+
+void s5c73m3_unregister_spi_driver(struct s5c73m3 *state)
+{
+	spi_unregister_driver(&state->spidrv);
+}
diff --git a/drivers/media/video/s5c73m3/s5c73m3.c b/drivers/media/video/s5c73m3/s5c73m3.c
new file mode 100644
index 0000000..d7ce0d7
--- /dev/null
+++ b/drivers/media/video/s5c73m3/s5c73m3.c
@@ -0,0 +1,1243 @@
+/*
+ * Samsung LSI S5C73M3 8M pixel camera driver
+ *
+ * Copyright (C) 2012, Samsung Electronics, Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+
+#include <asm/sizes.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/media.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/videodev2.h>
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-mediabus.h>
+#include <media/s5c73m3.h>
+
+#include "s5c73m3.h"
+
+int s5c73m3_dbg = 3;
+module_param_named(debug, s5c73m3_dbg, int, 0644);
+
+static int inc_fw_index;
+module_param(inc_fw_index, int, 0644);
+
+static const char * const s5c73m3_supply_names[S5C73M3_MAX_SUPPLIES] = {
+	"VDD_INT",	/* Digital Core supply (1.2V), CAM_ISP_CORE_1.2V */
+	"VDDA",		/* Analog Core supply (1.2V), CAM_SENSOR_CORE_1.2V */
+	"VDD_REG",	/* Regulator input supply (2.8V), CAM_SENSOR_A2.8V */
+	"VDDIO_HOST",	/* Digital Host I/O power supply (1.8V...2.8V),
+			   CAM_ISP_SENSOR_1.8V */
+	"VDDIO_CIS",	/* Digital CIS I/O power (1.2V...1.8V),
+			   CAM_ISP_MIPI_1.2V */
+	"VDD_AF",	/* Lens, CAM_AF_2.8V */
+};
+
+static const char *firmware_files[] = {
+	"SlimISP.bin",
+	"SlimISP_OA.bin",
+/*	"SlimISP_OB.bin",
+	"SlimISP_OD.bin",
+	"SlimISP_SC.bin",
+	"SlimISP_SD.bin",
+	"SlimISP_GC.bin",
+	"SlimISP_GD.bin",
+	"SlimISP_GE.bin",
+	"SlimISP_GF.bin",
+	"SlimISP_ZC.bin",
+	"SlimISP_ZD.bin",
+	"SlimISP_ZE.bin",
+	"SlimISP_ZF.bin",
+*/
+};
+
+static const struct s5c73m3_frame_size s5c73m3_video_resolutions[] = {
+	{ 320,	240,	0x01, 0 },
+	{ 400,	300,	0x02, 0 },
+	{ 640,	480,	0x03, 0 },
+	{ 800,	600,	0x04, 0 },
+	{ 960,	720,	0x05, 0 },
+	{ 1280,	720,	0x06, 1 },
+	{ 1280,	960,	0x07, 1 },
+	{ 1600,	1200,	0x08, 1 },
+	{ 1632,	1224,	0x09, 1 },
+	{ 1920,	1080,	0x0a, 1 },
+	{ 1920,	1440,	0x0b, 1 },
+	{ 2304,	1296,	0x0c, 1 },
+	{ 2304,	1728,	0x0d, 1 },
+};
+
+static const struct s5c73m3_frame_size s5c73m3_snapshot_resolutions[] = {
+	{ 640,	480,	0x10, 0 },
+	{ 1280,	720,	0x40, 0 },
+	{ 1600,	1200,	0x70, 1 },
+	{ 2048,	1152,	0x80, 0 },
+	{ 2048,	1536,	0x90, 0 },
+	{ 3264,	2304,	0xe0, 0 },
+	{ 3264,	2448,	0xf0, 0 },
+};
+
+struct s5c73m3_regval {
+	u16 addr;
+	u16 val;
+};
+
+static const struct s5c73m3_pixfmt s5c73m3_formats[] = {
+	{
+		.code		= V4L2_MBUS_FMT_VYUY8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+	}, {
+		.code		= V4L2_MBUS_FMT_JPEG_1X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.mipi_data_type	= 1,
+	},
+};
+
+static const struct s5c73m3_interval s5c73m3_intervals[] = {
+	/* TODO: update pixel resolutions corresponding to the frame rates */
+	{ REG_AE_MODE_FIXED_7FPS, {142857, 1000000}, {1280, 1024} }, /* 7 fps */
+	{ REG_AE_MODE_FIXED_15FPS, {66667, 1000000}, {1280, 1024} }, /* 15 fps */
+	{ REG_AE_MODE_FIXED_20FPS, {50000, 1000000}, {1280, 720} },  /* 20 fps */
+	{ REG_AE_MODE_FIXED_30FPS, {33333, 1000000}, {640, 480} },   /* 30 fps */
+	{ REG_AE_MODE_FIXED_120FPS, {8333, 1000000}, {640, 480} },   /* 120 fps */
+};
+
+#define S5C73M3_DEFAULT_FRAME_INTERVAL 3 /* 30 fps */
+
+static inline bool is_user_defined_dt(enum v4l2_mbus_pixelcode code)
+{
+	return code == V4L2_MBUS_FMT_JPEG_1X8;
+}
+
+static void s5c73m3_fill_mbus_fmt(struct v4l2_mbus_framefmt *mf,
+				  const struct s5c73m3_frame_size *fs,
+				  u32 code)
+{
+	mf->width = fs->width;
+	mf->height = fs->height;
+	mf->code = code;
+	mf->colorspace = V4L2_COLORSPACE_JPEG;
+	mf->field = V4L2_FIELD_NONE;
+}
+
+int s5c73m3_i2c_write(struct i2c_client *client, u16 addr, u16 data)
+{
+	u8 buf[4] = { addr >> 8, addr & 0xff, data >> 8, data & 0xff };
+
+	int ret = i2c_master_send(client, buf, sizeof(buf));
+
+	v4l_dbg(4, s5c73m3_dbg, client, "%s: addr 0x%04x, data 0x%04x\n",
+		 __func__, addr, data);
+
+	if (ret == 4)
+		return 0;
+
+	return ret < 0 ? ret : -EREMOTEIO;
+}
+
+static int s5c73m3_i2c_bulk_write(struct i2c_client *client, const u32 *regs)
+{
+	int i, ret = 0;
+
+	for (i = 0; regs[i] != S5C73M3_ARRAY_END && !ret; i++)
+		ret = s5c73m3_i2c_write(client, regs[i] >> 16, regs[i]);
+
+	return ret;
+}
+
+static int s5c73m3_i2c_read(struct i2c_client *client, u16 addr, u16 *data)
+{
+	int ret;
+	u8 rbuf[2], wbuf[2] = { addr >> 8, addr & 0xff };
+	struct i2c_msg msg[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = sizeof(wbuf),
+			.buf = wbuf
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = sizeof(rbuf),
+			.buf = rbuf
+		}
+	};
+	/*
+	 * Issue repeated START after writing 2 address bytes and
+	 * just one STOP only after reading the data bytes.
+	 */
+	ret = i2c_transfer(client->adapter, msg, 2);
+	if (ret == 2) {
+		*data = be16_to_cpup((u16 *)rbuf);
+		v4l2_dbg(4, s5c73m3_dbg, client,
+			 "%s: addr: 0x%04x, data: 0x%04x\n",
+			 __func__, addr, *data);
+		return 0;
+	}
+
+	v4l2_err(client, "I2C read failed: addr: %04x, (%d)\n", addr, ret);
+
+	return ret >= 0 ? -EREMOTEIO : ret;
+}
+
+static int s5c73m3_write(struct i2c_client *client, u32 addr, u16 data)
+{
+	int ret;
+
+	ret = s5c73m3_i2c_write(client, REG_CMDWR_ADDRH, addr >> 16);
+	if (ret < 0)
+		return ret;
+
+	ret = s5c73m3_i2c_write(client, REG_CMDWR_ADDRL, addr & 0xffff);
+	if (ret < 0)
+		return ret;
+
+	return s5c73m3_i2c_write(client, REG_CMDBUF_ADDR, data);
+}
+
+int s5c73m3_read(struct i2c_client *client, u32 addr, u16 *data)
+{
+	int ret;
+
+	ret = s5c73m3_i2c_write(client, AHB_MSB_ADDR_PTR, 0x3310);
+	if (ret < 0)
+		return ret;
+
+	ret = s5c73m3_i2c_write(client, REG_CMDRD_ADDRH, addr >> 16);
+	if (ret < 0)
+		return ret;
+
+	ret = s5c73m3_i2c_write(client, REG_CMDRD_ADDRL, addr & 0xffff);
+	if (ret < 0)
+		return ret;
+
+	return s5c73m3_i2c_read(client, REG_CMDBUF_ADDR, data);
+}
+
+static int s5c73m3_check_status(struct s5c73m3 *state, unsigned int value)
+{
+	unsigned long end = jiffies + msecs_to_jiffies(500);
+	int ret = 0;
+	u16 status;
+
+	while (time_is_after_jiffies(end)) {
+		ret = s5c73m3_read(state->i2c_client, 0x00095080, &status);
+		if (ret < 0)
+			return ret;
+		if (status == value)
+			return 0;
+		usleep_range(5000, 10000);
+
+		v4l2_dbg(1, s5c73m3_dbg, &state->subdev, "status: %#x\n",
+			 status);
+	}
+
+	return ret < 0 ? ret : -ETIMEDOUT;
+}
+
+int s5c73m3_write_cmd(struct s5c73m3 *state, u32 addr, u16 data)
+{
+	struct i2c_client *client = state->i2c_client;
+	int r;
+
+	r = s5c73m3_check_status(state, 0xffff);
+	if (r < 0)
+		return r;
+
+	r = s5c73m3_i2c_write(client, AHB_MSB_ADDR_PTR, 0x3310);
+	if (r < 0)
+		return r;
+
+	r = s5c73m3_i2c_write(client, REG_CMDWR_ADDRH, 0x0009);
+	if (r < 0)
+		return r;
+
+	r = s5c73m3_i2c_write(client, REG_CMDWR_ADDRL, 0x5000);
+	if (r < 0)
+		return r;
+
+	r = s5c73m3_i2c_write(client, REG_CMDBUF_ADDR, addr & 0xffff);
+	if (r < 0)
+		return r;
+
+	r = s5c73m3_i2c_write(client, REG_CMDBUF_ADDR, data);
+	if (r < 0)
+		return r;
+
+	r = s5c73m3_i2c_write(client, REG_CMDWR_ADDRL, 0x5080);
+	if (r < 0)
+		return r;
+
+	return s5c73m3_i2c_write(client, REG_CMDBUF_ADDR, 0x0001);
+}
+
+static int s5c73m3_set_af_softlanding(struct v4l2_subdev *sd)
+{
+	return 0;
+}
+
+static int s5c73m3_load_fw(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	const struct firmware *fw;
+	int r;
+
+	r = request_firmware(&fw, firmware_files[state->fw_index],
+			     &client->dev);
+	if (r < 0) {
+		v4l2_err(sd, "Firmware request failed (%s)\n",
+			 firmware_files[state->fw_index]);
+		return -EINVAL;
+	}
+	/* TODO: Sanity check on firmware size */
+
+	printk(KERN_CONT "Loading firmware (%s, %d B)...",
+	       firmware_files[state->fw_index], fw->size);
+
+	/* FIXME: Passing tx_size more than 64 leads to an oops */
+	r = s5c73m3_spi_write(state, fw->data, fw->size, 64 /*60 * SZ_1K*/);
+	if (r < 0)
+		v4l2_err(sd, "SPI write failed\n");
+	else
+		printk(KERN_CONT "done.\n");
+
+	release_firmware(fw);
+
+	if (inc_fw_index) {
+		if (++state->fw_index >= ARRAY_SIZE(firmware_files))
+			state->fw_index = 0;
+	}
+
+	return r;
+}
+
+/*
+ * v4l2_subdev video operations
+ */
+
+static int s5c73m3_set_frame_size(struct s5c73m3 *state)
+{
+	const struct s5c73m3_frame_size *prev_size = state->prev_pix_size;
+	unsigned int chg_mode;
+	int r = 0;
+
+	v4l2_dbg(1, s5c73m3_dbg, &state->subdev,
+		 "Preview size: %dx%d, reg_val: 0x%x\n",
+		 prev_size->width, prev_size->height, prev_size->reg_val);
+
+	/* FIXME: */
+	if (state->format[PREVIEW_IDX].code == V4L2_MBUS_FMT_JPEG_1X8)
+		chg_mode = CHG_MODE_INTERLEAVED;
+	else
+		chg_mode = CHG_MODE_YUV;
+
+	chg_mode |= prev_size->reg_val;
+
+	r = s5c73m3_write_cmd(state, REG_CHG_MODE, chg_mode);
+	if (r < 0)
+		return r;
+
+	/* s5c73m3_set_zoom(sd, 0); */
+	return r;
+}
+
+static int s5c73m3_set_frame_rate(struct s5c73m3 *state)
+{
+	int ret;
+
+	/*
+	 *  Image stabilization and frame rate are configured in same register.
+	 *  TODO: handle REG_AE_MODE_AUTO_SET
+	 */
+	if (state->ctrls.stabilization->val)
+		return 0;
+
+	if (WARN_ON(state->fiv == NULL))
+		return -EINVAL;
+
+	ret = s5c73m3_write_cmd(state, REG_AE_MODE, state->fiv->fps_reg);
+	if (!ret)
+		state->apply_fiv = 0;
+
+	return ret;
+}
+
+static int __s5c73m3_s_stream(struct s5c73m3 *state,
+			      struct v4l2_subdev *sd, int on)
+{
+	u16 mode;
+	int ret;
+
+	if (state->apply_fmt) {
+		/* FIXME: */
+		if (state->format[PREVIEW_IDX].code == V4L2_MBUS_FMT_JPEG_1X8)
+			mode = REG_IMG_OUTPUT_INTERLEAVED;
+		else
+			mode = REG_IMG_OUTPUT_YUV;
+
+		ret = s5c73m3_write_cmd(state, REG_IMG_OUTPUT, mode);
+		if (!ret)
+			ret = s5c73m3_set_frame_size(state);
+		if (ret)
+			return ret;
+		state->apply_fmt = 0;
+	}
+
+	switch (state->ctrls.capture_ctx->val) {
+	case V4L2_CAPTURE_CTX_PREVIEW:
+		v4l2_info(sd, "preview %s\n", on ? "on" : "off");
+		/* TODO: */
+		break;
+	case V4L2_CAPTURE_CTX_STILL:
+		v4l2_info(sd, "still capture %s\n", on ? "on" : "off");
+		/* TODO: */
+		break;
+	case V4L2_CAPTURE_CTX_CAMCORDER:
+		/* TODO: */
+		break;
+	}
+
+	ret = s5c73m3_write_cmd(state, REG_SENSOR_STREAMING, !!on);
+	if (ret || !on)
+		return ret;
+
+	ret = s5c73m3_check_status(state, 0xffff);
+	if (ret)
+		return ret;
+	/* if (state->apply_fiv) */
+		/* ret = s5c73m3_set_frame_rate(state); */
+
+	return ret;
+}
+
+static int s5c73m3_s_stream(struct v4l2_subdev *sd, int on)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	int ret;
+
+	mutex_lock(&state->lock);
+	ret = __s5c73m3_s_stream(state, sd, on);
+	mutex_unlock(&state->lock);
+
+	return ret;
+}
+
+static int s5c73m3_system_status_wait(struct s5c73m3 *state, u32 value,
+				      unsigned int delay, unsigned int steps)
+{
+	u16 reg = 0;
+
+	while (steps-- > 0) {
+		int ret = s5c73m3_read(state->i2c_client, 0x30100010, &reg);
+		if (ret < 0)
+			return ret;
+		if (reg == value)
+			return 0;
+		usleep_range(delay, delay + 25);
+	}
+	return -ETIMEDOUT;
+}
+
+static int s5c73m3_spi_boot(struct s5c73m3 *state, bool load_fw)
+{
+	struct i2c_client *client = state->i2c_client;
+	struct v4l2_subdev *sd = &state->subdev;
+	u16 sensor_fw;
+	int i, r;
+
+	/* Run ARM MCU */
+	r = s5c73m3_write(client, 0x30000004, 0xffff);
+	if (r < 0)
+		return r;
+
+	usleep_range(400, 500);
+
+	/* Check booting status */
+	r = s5c73m3_system_status_wait(state, 0x0c, 4, 150);
+	if (r < 0) {
+		v4l2_err(sd, "Booting failed: %d\n", r);
+		return r;
+	}
+
+	/* P,M,S and Boot Mode */
+	r = s5c73m3_write(client, 0x30100014, 0x2146);
+	if (r < 0)
+		return r;
+
+	r = s5c73m3_write(client, 0x30100010, 0x210c);
+	if (r < 0)
+		return r;
+
+	usleep_range(200, 250);
+
+	/* Check SPI status */
+	r = s5c73m3_system_status_wait(state, 0x210d, 60, 5000);
+	if (r < 0) {
+		v4l2_err(sd, "SPI not ready: %d\n", r);
+		return r;
+	}
+
+	/* Firmware download over SPI */
+	if (load_fw)
+		s5c73m3_load_fw(sd);
+
+	/* MCU reset */
+	r = s5c73m3_write(client, 0x30000004, 0xfffd);
+	if (r < 0)
+		return r;
+
+	/* Remap */
+	r = s5c73m3_write(client, 0x301000a4, 0x0183);
+	if (r < 0)
+		return r;
+
+	/* MCU restart */
+	r = s5c73m3_write(client, 0x30000004, 0xffff);
+
+	if (r < 0 || !load_fw)
+		return r;
+
+	for (i = 0; i < 3; i++) {
+		r = s5c73m3_read(client, 0x00000060 + i * 2, &sensor_fw);
+		if (r < 0)
+			return r;
+		state->sensor_fw[i * 2] = sensor_fw & 0xff;
+		state->sensor_fw[i * 2 + 1] = (sensor_fw >> 8) & 0xff;
+	}
+	state->sensor_fw[i * 2 + 2] = '\0';
+
+	v4l2_info(sd, "Sensor version: %s\n", state->sensor_fw);
+	return r;
+}
+
+static int s5c73m3_isp_init(struct s5c73m3 *state)
+{
+	struct i2c_client *client = state->i2c_client;
+	int ret;
+	static const u32 init_regs[] = {
+		0x00500009,
+		0x00545000,
+		0x0f140B08,
+		0x0f140000,
+		0x0f140900,
+		0x0f140403, /*640MHz*/
+		0x00545080,
+		0x0f140002,
+		S5C73M3_ARRAY_END
+	};
+
+	ret = s5c73m3_spi_boot(state, true);
+	if (ret < 0)
+		return ret;
+
+	return s5c73m3_i2c_bulk_write(client, init_regs);
+}
+
+static const struct s5c73m3_pixfmt *s5c73m3_get_pixfmt(
+				struct v4l2_mbus_framefmt *mf)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(s5c73m3_formats); i++) {
+		if (mf->colorspace == s5c73m3_formats[i].colorspace &&
+		    mf->code == s5c73m3_formats[i].code)
+			return &s5c73m3_formats[i];
+	}
+
+	return &s5c73m3_formats[0];
+}
+
+static int s5c73m3_try_format(struct s5c73m3 *state,
+			      struct v4l2_mbus_framefmt *mf,
+			      const struct s5c73m3_frame_size **fs,
+			      int op_mode)
+{
+	unsigned int i, min_err = UINT_MAX;
+	const struct s5c73m3_frame_size
+		*fsize = state->pix_sizes[op_mode],
+		*match = NULL;
+	const struct s5c73m3_pixfmt *pixfmt;
+
+	for (i = 0; i < state->pix_sizes_len[op_mode]; i++) {
+		int err;
+		err = abs(fsize->width - mf->width)
+			  + abs(fsize->height - mf->height);
+
+		if (err < min_err) {
+			min_err = err;
+			match = fsize;
+		}
+		fsize++;
+	}
+
+	if (match == NULL)
+		return -EINVAL;
+	if (fs)
+		*fs = match;
+
+	pixfmt = s5c73m3_get_pixfmt(mf);
+
+	s5c73m3_fill_mbus_fmt(mf, match, pixfmt->code);
+
+	v4l2_dbg(1, s5c73m3_dbg, &state->subdev, "%dx%d, code: %#x\n",
+		 match->width, match->height, pixfmt->code);
+
+	return 0;
+}
+
+/*
+ * V4L2 subdev pad level and video operations
+ */
+
+static int s5c73m3_g_frame_interval(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_frame_interval *fi)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+
+	mutex_lock(&state->lock);
+	fi->interval = state->fiv->interval;
+	mutex_unlock(&state->lock);
+
+	return 0;
+}
+
+static int __s5c73m3_set_frame_interval(struct s5c73m3 *state,
+					struct v4l2_subdev_frame_interval *fi)
+{
+	const struct s5c73m3_frame_size *prev_size = state->prev_pix_size;
+	const struct s5c73m3_interval *fiv = &s5c73m3_intervals[0];
+	unsigned int err, min_err = UINT_MAX;
+	unsigned int i, fr_time;
+
+	if (fi->interval.denominator == 0)
+		return -EINVAL;
+
+	/* Frame interval in ms */
+	fr_time = fi->interval.numerator * 1000 / fi->interval.denominator;
+
+	for (i = 0; i < ARRAY_SIZE(s5c73m3_intervals); i++) {
+		const struct s5c73m3_interval *iv = &s5c73m3_intervals[i];
+
+		if (prev_size->width > iv->size.width ||
+		    prev_size->height > iv->size.height)
+			continue;
+
+		err = abs(iv->interval.numerator / 10000 - fr_time);
+		if (err < min_err) {
+			fiv = iv;
+			min_err = err;
+		}
+	}
+	state->fiv = fiv;
+
+	v4l2_dbg(1, s5c73m3_dbg, &state->subdev,
+		 "Changed frame interval to %u us\n", fiv->interval.numerator);
+	return 0;
+}
+
+static int s5c73m3_s_frame_interval(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_frame_interval *fi)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	int ret;
+
+	v4l2_dbg(1, s5c73m3_dbg, sd, "Setting %d/%d frame interval\n",
+		 fi->interval.numerator, fi->interval.denominator);
+
+	mutex_lock(&state->lock);
+
+	ret = __s5c73m3_set_frame_interval(state, fi);
+	if (!ret) {
+		if (state->streaming)
+			ret = s5c73m3_set_frame_rate(state);
+		else
+			state->apply_fiv = 1;
+	}
+	mutex_unlock(&state->lock);
+	return ret;
+}
+
+static int s5c73m3_enum_frame_interval(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_frame_interval_enum *fie)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	const struct s5c73m3_interval *fi;
+	int ret = 0;
+
+	if (fie->index > ARRAY_SIZE(s5c73m3_intervals))
+		return -EINVAL;
+
+	v4l_bound_align_image(&fie->width, S5C73M3_WIN_WIDTH_MIN,
+			      S5C73M3_WIN_WIDTH_MAX, 1,
+			      &fie->height, S5C73M3_WIN_HEIGHT_MIN,
+			      S5C73M3_WIN_HEIGHT_MAX, 1, 0);
+
+	mutex_lock(&state->lock);
+	fi = &s5c73m3_intervals[fie->index];
+	if (fie->width > fi->size.width || fie->height > fi->size.height)
+		ret = -EINVAL;
+	else
+		fie->interval = fi->interval;
+	mutex_unlock(&state->lock);
+
+	return ret;
+}
+
+static int s5c73m3_get_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	struct v4l2_mbus_framefmt *mf;
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mf = v4l2_subdev_get_try_format(fh, 0);
+		fmt->format = *mf;
+		return 0;
+	}
+	mutex_lock(&state->lock);
+
+	if (fmt->pad == S5C73M3_OUTIF_SOURCE_PAD)
+		fmt->format = state->format[PREVIEW_IDX];
+	else
+		fmt->format = state->format[CAPTURE_IDX];
+
+	mutex_unlock(&state->lock);
+	return 0;
+}
+
+static int s5c73m3_set_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
+{
+	const struct s5c73m3_frame_size *frame_size = NULL;
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	struct v4l2_mbus_framefmt *mf;
+	int idx, ret = 0;
+
+	mutex_lock(&state->lock);
+
+	if (fmt->pad == S5C73M3_OUTIF_SOURCE_PAD)
+		idx = PREVIEW_IDX;
+	else
+		idx = CAPTURE_IDX;
+	s5c73m3_try_format(state, &fmt->format, &frame_size, idx);
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+	} else {
+		if (state->streaming && idx != PREVIEW_IDX) {
+			ret = -EBUSY;
+		} else {
+			mf = &state->format[idx];
+			/* if (!state->power) */
+				state->apply_fmt = 1;
+		}
+	}
+	if (!ret && mf) {
+		*mf = fmt->format;
+		if (frame_size) {
+			state->prev_pix_size = frame_size;
+			/* if (state->power) */
+			/*	ret = s5c73m3_set_frame_size(state); */
+		}
+
+		v4l2_dbg(1, s5c73m3_dbg, sd, "%s: %dx%d, code: 0x%x\n",
+			 __func__, mf->width, mf->height, mf->code);
+	}
+
+	pr_info("reg_val: 0x%x\n", state->prev_pix_size->reg_val);
+
+	mutex_unlock(&state->lock);
+
+	return ret;
+}
+
+static int s5c73m3_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index >= ARRAY_SIZE(s5c73m3_formats))
+		return -EINVAL;
+
+	code->code = s5c73m3_formats[code->index].code;
+	return 0;
+}
+
+static int s5c73m3_enum_frame_size(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	int i = ARRAY_SIZE(s5c73m3_formats);
+	int idx;
+
+	while (--i)
+		if (fse->code == s5c73m3_formats[i].code)
+			break;
+
+	fse->code = s5c73m3_formats[i].code;
+
+	/* FIXME: need to select pixel resolution list differently */
+	if (fse->code == V4L2_MBUS_FMT_JPEG_1X8)
+		idx = CAPTURE_IDX;
+	else
+		idx = PREVIEW_IDX;
+
+	if (fse->index >= state->pix_sizes_len[idx])
+		return -EINVAL;
+
+	fse->min_width  = state->pix_sizes[idx][fse->index].width;
+	fse->max_width  = fse->min_width;
+	fse->max_height = state->pix_sizes[idx][fse->index].height;
+	fse->min_height = fse->max_height;
+
+	return 0;
+}
+
+static int s5c73m3_set_selection(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_selection *sel)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	struct v4l2_mbus_framefmt *mf = &state->format[PREVIEW_IDX];
+	struct v4l2_rect *r = &sel->r;
+
+	v4l2_dbg(1, s5c73m3_dbg, sd, "%s: (%d,%d) %dx%d, %#x\n", __func__,
+		 r->left, r->top, r->width, r->height, sel->target);
+
+	if (sel->target != V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL) {
+		v4l2_err(sd, "Unsupported selection target: %#x", sel->target);
+		return -EINVAL;
+	}
+
+	r->left = clamp_t(s32, r->left, 0, mf->width);
+	r->top = clamp_t(s32, r->top, 0, mf->height);
+	r->width = 0;
+	r->height = 0;
+
+	state->focus.pos_x = r->left;
+	state->focus.pos_y = r->top;
+
+	return 0;
+}
+
+static int s5c73m3_get_selection(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_selection *sel)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	struct v4l2_mbus_framefmt *mf = &state->format[PREVIEW_IDX];
+
+	switch (sel->target) {
+	case V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL:
+		sel->r.left = state->focus.pos_x;
+		sel->r.top = state->focus.pos_y;
+		break;
+	case V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_BOUNDS:
+		sel->r.width = mf->width;
+		sel->r.height = mf->height;
+		sel->r.left = 0;
+		sel->r.top = 0;
+		break;
+	default:
+		v4l2_err(sd, "Unsupported selection target: %#x", sel->target);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int s5c73m3_log_status(struct v4l2_subdev *sd)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+
+	v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
+
+	v4l2_info(sd, "power: %d, apply_fmt: %d, apply_ctrls: %d\n",
+		  state->power, state->apply_fmt, state->apply_ctrls);
+
+	return 0;
+}
+
+/*
+ * V4L2 subdev internal operations
+ */
+static int s5c73m3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0);
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+
+	if (state->fw_error) {
+		v4l2_err(sd, "Wrong firmware state\n");
+		return -ENXIO;
+	}
+
+	s5c73m3_fill_mbus_fmt(mf, &s5c73m3_video_resolutions[0],
+			      s5c73m3_formats[0].code);
+	return 0;
+}
+
+static int s5c73m3_gpio_set_value(struct s5c73m3 *priv, int id, u32 val)
+{
+	if (!gpio_is_valid(priv->gpio[id].gpio))
+		return 0;
+	gpio_set_value(priv->gpio[id].gpio, !!val);
+	return 1;
+}
+
+static int s5c73m3_gpio_assert(struct s5c73m3 *priv, int id)
+{
+	return s5c73m3_gpio_set_value(priv, id, priv->gpio[id].level);
+}
+
+static int s5c73m3_gpio_deassert(struct s5c73m3 *priv, int id)
+{
+	return s5c73m3_gpio_set_value(priv, id, !priv->gpio[id].level);
+}
+
+static int __s5c73m3_power_on(struct s5c73m3 *state)
+{
+	int i, ret;
+
+	for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) {
+		ret = regulator_enable(state->supplies[i].consumer);
+		if (ret)
+			goto err;
+	}
+
+	s5c73m3_gpio_deassert(state, STBY);
+	usleep_range(100, 200);
+
+	s5c73m3_gpio_deassert(state, RST);
+	usleep_range(50, 100);
+
+	return 0;
+err:
+	for (--i; i >= 0; i--)
+		regulator_disable(state->supplies[i].consumer);
+	return ret;
+}
+
+static int __s5c73m3_power_off(struct s5c73m3 *state)
+{
+	int i, ret;
+
+	if (s5c73m3_gpio_assert(state, RST))
+		usleep_range(10, 50);
+
+	if (s5c73m3_gpio_assert(state, STBY))
+		usleep_range(100, 200);
+	state->streaming = 0;
+
+	for (i = S5C73M3_MAX_SUPPLIES - 1; i >= 0; i--) {
+		ret = regulator_disable(state->supplies[i].consumer);
+		if (ret)
+			goto err;
+	}
+	return 0;
+err:
+	for (++i; i < S5C73M3_MAX_SUPPLIES; i++)
+		regulator_enable(state->supplies[i].consumer);
+
+	return ret;
+}
+
+/*
+ * V4L2 subdev core and video operations
+ */
+static int s5c73m3_set_power(struct v4l2_subdev *sd, int on)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	int ret = 0;
+
+	mutex_lock(&state->lock);
+
+	if (on && !on == state->power) {
+		ret = __s5c73m3_power_on(state);
+		if (!ret)
+			ret = s5c73m3_isp_init(state);
+		if (!ret) {
+			state->apply_ctrls = 1;
+			state->apply_fiv = 1;
+			state->apply_fmt = 1;
+		}
+	} else if (!on && !on == state->power) {
+		ret = s5c73m3_set_af_softlanding(sd);
+		if (!ret)
+			ret = __s5c73m3_power_off(state);
+		else
+			v4l2_err(sd, "Soft landing lens failed\n");
+	}
+	if (!ret)
+		state->power += on ? 1 : -1;
+
+	v4l2_dbg(1, s5c73m3_dbg, sd, "%s: power: %d\n",
+		 __func__, state->power);
+
+	mutex_unlock(&state->lock);
+	return ret;
+}
+
+static int s5c73m3_registered(struct v4l2_subdev *sd)
+{
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+	int ret;
+
+	v4l2_dbg(1, s5c73m3_dbg, sd, "%s:\n", __func__);
+
+	mutex_lock(&state->lock);
+
+	ret = __s5c73m3_power_on(state);
+	if (ret == 0)
+		ret = s5c73m3_spi_boot(state, false);
+	__s5c73m3_power_off(state);
+
+	mutex_unlock(&state->lock);
+	return ret;
+}
+
+static const struct v4l2_subdev_internal_ops s5c73m3_internal_ops = {
+	.registered	= s5c73m3_registered,
+	.open		= s5c73m3_open,
+};
+
+static const struct v4l2_subdev_core_ops s5c73m3_core_ops = {
+	.load_fw	= s5c73m3_load_fw,
+	.s_power	= s5c73m3_set_power,
+	.log_status	= s5c73m3_log_status,
+};
+
+static const struct v4l2_subdev_pad_ops s5c73m3_pad_ops = {
+	.enum_mbus_code		= s5c73m3_enum_mbus_code,
+	.enum_frame_size	= s5c73m3_enum_frame_size,
+	.enum_frame_interval	= s5c73m3_enum_frame_interval,
+	.set_selection		= s5c73m3_set_selection,
+	.get_selection		= s5c73m3_get_selection,
+	.get_fmt		= s5c73m3_get_fmt,
+	.set_fmt		= s5c73m3_set_fmt,
+};
+
+static const struct v4l2_subdev_video_ops s5c73m3_video_ops = {
+	.g_frame_interval	= s5c73m3_g_frame_interval,
+	.s_frame_interval	= s5c73m3_s_frame_interval,
+	.s_stream		= s5c73m3_s_stream,
+};
+
+static const struct v4l2_subdev_ops s5c73m3_subdev_ops = {
+	.core	= &s5c73m3_core_ops,
+	.pad	= &s5c73m3_pad_ops,
+	.video	= &s5c73m3_video_ops,
+};
+
+/*
+ * GPIO control helpers
+ */
+static int s5c73m3_configure_gpio(int nr, int val, const char *name)
+{
+	unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+	int ret;
+
+	if (!gpio_is_valid(nr))
+		return 0;
+	ret = gpio_request_one(nr, flags, name);
+	if (!ret)
+		gpio_export(nr, 0);
+	return ret;
+}
+
+static int s5c73m3_free_gpios(struct s5c73m3 *state)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(state->gpio); i++) {
+		if (!gpio_is_valid(state->gpio[i].gpio))
+			continue;
+		gpio_free(state->gpio[i].gpio);
+		state->gpio[i].gpio = -EINVAL;
+	}
+	return 0;
+}
+
+static int s5c73m3_configure_gpios(struct s5c73m3 *state,
+				   const struct s5c73m3_platform_data *pdata)
+{
+	const struct s5c73m3_gpio *gpio = &pdata->gpio_stby;
+	int ret;
+
+	state->gpio[STBY].gpio = -EINVAL;
+	state->gpio[RST].gpio  = -EINVAL;
+
+	ret = s5c73m3_configure_gpio(gpio->gpio, gpio->level, "S5C73M3_STBY");
+	if (ret) {
+		s5c73m3_free_gpios(state);
+		return ret;
+	}
+	state->gpio[STBY] = *gpio;
+	if (gpio_is_valid(gpio->gpio))
+		gpio_set_value(gpio->gpio, 0);
+
+	gpio = &pdata->gpio_reset;
+	ret = s5c73m3_configure_gpio(gpio->gpio, gpio->level, "S5C73M3_RST");
+	if (ret) {
+		s5c73m3_free_gpios(state);
+		return ret;
+	}
+	state->gpio[RST] = *gpio;
+	if (gpio_is_valid(gpio->gpio))
+		gpio_set_value(gpio->gpio, 0);
+
+	return 0;
+}
+
+static int __devinit s5c73m3_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	const struct s5c73m3_platform_data *pdata = client->dev.platform_data;
+	struct v4l2_subdev *sd;
+	struct s5c73m3 *state;
+	int ret, i;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "Platform data not specified\n");
+		return -EINVAL;
+	}
+
+	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	mutex_init(&state->lock);
+	sd = &state->subdev;
+
+	v4l2_i2c_subdev_init(sd, client, &s5c73m3_subdev_ops);
+	strlcpy(sd->name, "S5C73M3", sizeof(sd->name));
+
+	sd->internal_ops = &s5c73m3_internal_ops;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	state->pads[S5C73M3_OUTIF_SOURCE_PAD].flags = MEDIA_PAD_FL_SOURCE;
+	state->pads[S5C73M3_JPEG_SINK_PAD].flags = MEDIA_PAD_FL_SINK;
+	state->pads[S5C73M3_ISP_SINK_PAD].flags = MEDIA_PAD_FL_SINK;
+	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+
+	ret = media_entity_init(&sd->entity, S5C73M3_NUM_PADS, state->pads, 0);
+	if (ret < 0)
+		return ret;
+
+	state->mclk_frequency = pdata->mclk_frequency;
+	state->bus_type = pdata->bus_type;
+
+	ret = s5c73m3_configure_gpios(state, pdata);
+	if (ret)
+		goto out_err1;
+
+	for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++)
+		state->supplies[i].supply = s5c73m3_supply_names[i];
+
+	ret = regulator_bulk_get(&client->dev, S5C73M3_MAX_SUPPLIES,
+			       state->supplies);
+	if (ret) {
+		dev_err(&client->dev, "failed to get regulators\n");
+		goto out_err2;
+	}
+
+	ret = s5c73m3_init_controls(state);
+	if (ret)
+		goto out_err3;
+
+	state->pix_sizes[PREVIEW_IDX]	  = s5c73m3_video_resolutions;
+	state->pix_sizes_len[PREVIEW_IDX] = ARRAY_SIZE(s5c73m3_video_resolutions);
+	state->prev_pix_size		  = &s5c73m3_video_resolutions[1];
+
+	s5c73m3_fill_mbus_fmt(&state->format[PREVIEW_IDX], state->prev_pix_size,
+			      s5c73m3_formats[0].code /* FIXME */);
+
+	state->pix_sizes[CAPTURE_IDX]	  = s5c73m3_snapshot_resolutions;
+	state->pix_sizes_len[CAPTURE_IDX] = ARRAY_SIZE(s5c73m3_snapshot_resolutions);
+	state->cap_pix_size		  = &s5c73m3_snapshot_resolutions[1];
+
+	s5c73m3_fill_mbus_fmt(&state->format[CAPTURE_IDX], state->cap_pix_size,
+			      s5c73m3_formats[2].code /* FIXME */);
+
+	state->fiv = &s5c73m3_intervals[S5C73M3_DEFAULT_FRAME_INTERVAL];
+
+	ret = s5c73m3_register_spi_driver(state);
+	if (ret < 0)
+		goto out_err3;
+
+	state->i2c_client = client;
+
+	state->fw_index = 0;
+
+	v4l2_info(sd, "%s: completed succesfully\n", __func__);
+	return 0;
+
+out_err3:
+	regulator_bulk_free(S5C73M3_MAX_SUPPLIES, state->supplies);
+out_err2:
+	s5c73m3_free_gpios(state);
+out_err1:
+	media_entity_cleanup(&sd->entity);
+	return ret;
+}
+
+static int __devexit s5c73m3_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct s5c73m3 *state = subdev_to_s5c73m3(sd);
+
+	v4l2_device_unregister_subdev(sd);
+
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	media_entity_cleanup(&sd->entity);
+
+	s5c73m3_unregister_spi_driver(state);
+	regulator_bulk_free(S5C73M3_MAX_SUPPLIES, state->supplies);
+	s5c73m3_free_gpios(state);
+
+	return 0;
+}
+
+static const struct i2c_device_id s5c73m3_id[] = {
+	{ DRIVER_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, s5c73m3_id);
+
+static struct i2c_driver s5c73m3_i2c_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+	},
+	.probe		= s5c73m3_probe,
+	.remove		= __devexit_p(s5c73m3_remove),
+	.id_table	= s5c73m3_id,
+};
+
+module_i2c_driver(s5c73m3_i2c_driver);
+
+MODULE_DESCRIPTION("Samsung S5C73M3 camera driver");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/s5c73m3/s5c73m3.h b/drivers/media/video/s5c73m3/s5c73m3.h
new file mode 100644
index 0000000..f37370f
--- /dev/null
+++ b/drivers/media/video/s5c73m3/s5c73m3.h
@@ -0,0 +1,442 @@
+/*
+ * Samsung LSI S5C73M3 8M pixel camera driver
+ *
+ * Copyright (C) 2012, Samsung Electronics, Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef S5C73M3_H_
+#define S5C73M3_H_
+
+#include <linux/kernel.h>
+#include <linux/regulator/consumer.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+#include <media/s5c73m3.h>
+
+/*
+ * Subdev private controls
+ */
+
+#define V4L2_CID_FIRMWARE_VERSION	(V4L2_CTRL_CLASS_CAMERA | 0x1001)
+/* Capture context */
+#define V4L2_CID_CAPTURE_CTX		(V4L2_CTRL_CLASS_CAMERA | 0x1002)
+enum s5c73m3_capture_ctx {
+	V4L2_CAPTURE_CTX_PREVIEW,
+	V4L2_CAPTURE_CTX_STILL,
+	V4L2_CAPTURE_CTX_CAMCORDER,
+};
+/* Snapshot trigger */
+#define V4L2_CID_SNAPSHOT		(V4L2_CTRL_CLASS_CAMERA | 0x1003)
+/* Flash mode */
+#define V4L2_CID_FLASH_MODE		(V4L2_CTRL_CLASS_CAMERA | 0x1004)
+enum s5c73m3_flash_mode {
+	FLASH_MODE_AUTO,
+	FLASH_MODE_ON,
+	FLASH_MODE_OFF,
+	FLASH_MODE_TORCH,
+};
+
+#define DRIVER_NAME			"S5C73M3"
+#define S5C73M3_FW_FILENAME		"SlimISP.bin"
+
+#define S5C73M3_FW_VER_LEN		22
+#define S5C73M3_FW_VER_FILE_CUR		0x16FF00
+#define S5C73M3_FLASH_BASE_ADDR		0x10000000
+#define S5C73M3_INT_RAM_BASE_ADDR	0x68000000
+
+#define S5C73M3_INTERLEAVED_SIZE_MAX	(8 * SZ_1M)
+#define S5C73M3_JPEG_MAXSIZE		0x800000
+#define S5C73M3_YUV_MAXSIZE		0x3F4800 /*FHD*/
+#define S5C73M3_POINTER_MAXSIZE		0x10E0 /*FHD*/
+
+#define S5C73M3_WIN_WIDTH_MAX		1280
+#define S5C73M3_WIN_HEIGHT_MAX		1024
+#define S5C73M3_WIN_WIDTH_MIN		8
+#define S5C73M3_WIN_HEIGHT_MIN		8
+#define S5C73M3_EMBEDDED_DATA_SIZE	SZ_4K
+
+/* Subdev pad index definitions */
+#define S5C73M3_OUTIF_SOURCE_PAD	0
+#define S5C73M3_JPEG_SINK_PAD		1
+#define S5C73M3_ISP_SINK_PAD		2
+#define S5C73M3_NUM_PADS		3
+
+/*
+ * Register definitions
+ */
+#define S5C73M3_REG(_addrh, _addrl) (((_addrh) << 16) | _addrl)
+
+/*
+ * FIXME: The CMD* register address names are a guess only. They are
+ * analogous to the S5K6AA sensor convention and are by no means
+ * correllated with the (non-existent?) S5C73M3 registers documentation.
+ */
+#define AHB_MSB_ADDR_PTR		0xfcfc
+#define REG_CMDWR_ADDRH			0x0050
+#define REG_CMDWR_ADDRL			0x0054
+#define REG_CMDRD_ADDRH			0x0058
+#define REG_CMDRD_ADDRL			0x005c
+#define REG_CMDBUF_ADDR			0x0f14
+
+#define REG_IMG_OUTPUT			S5C73M3_REG(0, 0x0902)
+#define  REG_IMG_OUTPUT_HDR		0x0008
+#define  REG_IMG_OUTPUT_YUV		0x0009
+#define  REG_IMG_OUTPUT_INTERLEAVED	0x000d
+
+#define REG_STILL_PRE_FLASH		S5C73M3_REG(0, 0x0a00)
+#define  REG_STILL_PRE_FLASH_FIRE	0x0000
+#define  REG_STILL_PRE_FLASH_NON_FIRED	0x0000
+#define  REG_STILL_PRE_FLASH_FIRED	0x0001
+
+#define REG_STILL_MAIN_FLASH		S5C73M3_REG(0, 0x0a02)
+#define  REG_STILL_MAIN_FLASH_CANCEL	0x0001
+#define  REG_STILL_MAIN_FLASH_FIRE	0x0002
+
+#define REG_ZOOM_STEP			S5C73M3_REG(0, 0x0b00)
+
+#define REG_IMAGE_EFFECT		S5C73M3_REG(0, 0x0b0a)
+#define  REG_IMAGE_EFFECT_NONE		0x0001
+#define  REG_IMAGE_EFFECT_NEGATIVE	0x0002
+#define  REG_IMAGE_EFFECT_AQUA		0x0003
+#define  REG_IMAGE_EFFECT_SEPIA		0x0004
+#define  REG_IMAGE_EFFECT_MONO		0x0005
+
+#define REG_IMAGE_QUALITY		S5C73M3_REG(0, 0x0b0c)
+#define  REG_IMAGE_QUALITY_SUPERFINE	0x0000
+#define  REG_IMAGE_QUALITY_FINE		0x0001
+#define  REG_IMAGE_QUALITY_NORMAL	0x0002
+
+#define REG_FLASH_MODE			S5C73M3_REG(0, 0x0b0e)
+#define  REG_FLASH_MODE_OFF		0x0000
+#define  REG_FLASH_MODE_ON		0x0001
+#define  REG_FLASH_MODE_AUTO		0x0002
+
+#define REG_FLASH_STATUS		S5C73M3_REG(0, 0x0b80)
+#define  REG_FLASH_STATUS_OFF		0x0001
+#define  REG_FLASH_STATUS_ON		0x0002
+#define  REG_FLASH_STATUS_AUTO		0x0003
+
+#define REG_FLASH_TORCH			S5C73M3_REG(0, 0x0b12)
+#define  REG_FLASH_TORCH_OFF		0x0000
+#define  REG_FLASH_TORCH_ON		0x0001
+
+#define REG_AE_NEEDS_FLASH		S5C73M3_REG(0, 0x0cba)
+#define  REG_AE_NEEDS_FLASH_OFF		0x0000
+#define  REG_AE_NEEDS_FLASH_ON		0x0001
+
+#define REG_CHG_MODE			S5C73M3_REG(0, 0x0b10)
+#define  CHG_MODE_YUV			0x8000
+#define  CHG_MODE_INTERLEAVED		0x8010
+
+#define  CHG_MODE_YUV_320_240		0x8001
+#define  CHG_MODE_YUV_400_300		0x8002
+#define  CHG_MODE_YUV_640_480		0x8003
+#define  CHG_MODE_YUV_800_600		0x8004
+#define  CHG_MODE_YUV_960_720		0x8005
+#define  CHG_MODE_YUV_1280_720		0x8006
+#define  CHG_MODE_YUV_1280_960		0x8007
+#define  CHG_MODE_YUV_1600_1200		0x8008
+#define  CHG_MODE_YUV_1632_1224		0x8009
+#define  CHG_MODE_YUV_1920_1080		0x800a
+#define  CHG_MODE_YUV_1920_1440		0x800b
+#define  CHG_MODE_YUV_2304_1296		0x800c
+#define  CHG_MODE_YUV_2304_1728		0x800d
+
+#define  CHG_MODE_JPEG_640_480		0x0010
+#define  CHG_MODE_JPEG_800_450		0x0020
+#define  CHG_MODE_JPEG_800_600		0x0030
+#define  CHG_MODE_JPEG_1600_960		0x0040
+#define  CHG_MODE_JPEG_1600_1200	0x0050
+#define  CHG_MODE_JPEG_2048_1152	0x0060
+#define  CHG_MODE_JPEG_2048_1536	0x0070
+#define  CHG_MODE_JPEG_2560_1440	0x0080
+#define  CHG_MODE_JPEG_2560_1920	0x0090
+#define  CHG_MODE_JPEG_3072_1728	0x00a0
+#define  CHG_MODE_JPEG_3264_2304	0x00b0
+#define  CHG_MODE_JPEG_3264_1836	0x00c0
+#define  CHG_MODE_JPEG_3264_2448	0x00d0
+
+#define REG_AF_CON			S5C73M3_REG(0, 0x0e00)
+#define  REG_AF_CON_STOP		0x0000
+#define  REG_AF_CON_SCAN		0x0001 /* AF_SCAN: Full Search */
+#define  REG_AF_CON_START		0x0002 /* AF_START: Fast Search */
+
+#define REG_AF_CAL			S5C73M3_REG(0, 0x0e06)
+#define REG_AF_TOUCH_AF			S5C73M3_REG(0, 0x0e0a)
+
+#define REG_AF_STATUS			S5C73M3_REG(0x0009, 0x5e80)
+#define  REG_CAF_STATUS_FIND_SEARCH_DIR 0x0001
+#define  REG_CAF_STATUS_FOCUSING	0x0002
+#define  REG_CAF_STATUS_FOCUSED		0x0003
+#define  REG_CAF_STATUS_UNFOCUSED	0x0004
+#define  REG_AF_STATUS_INVALID		0x0010
+#define  REG_AF_STATUS_FOCUSING		0x0020
+#define  REG_AF_STATUS_FOCUSED		0x0030
+#define  REG_AF_STATUS_UNFOCUSED	0x0040
+
+#define REG_AF_TOUCH_POSITION		S5C73M3_REG(0, 0x5e8e)
+#define REG_AF_FACE_ZOOM		S5C73M3_REG(0, 0x0e10)
+
+#define REG_AF_MODE			S5C73M3_REG(0, 0x0e02)
+#define  REG_AF_MODE_NORMAL		0x0000
+#define  REG_AF_MODE_MACRO		0x0001
+#define  REG_AF_MODE_MOVIE_CAF_START	0x0002
+#define  REG_AF_MODE_MOVIE_CAF_STOP	0x0003
+#define  REG_AF_MODE_PREVIEW_CAF_START	0x0004
+#define  REG_AF_MODE_PREVIEW_CAF_STOP	0x0005
+
+#define REG_AF_SOFTLANDING		S5C73M3_REG(0, 0x0e16)
+#define  REG_AF_SOFTLANDING_ON		0x0000
+
+#define REG_FACE_DET			S5C73M3_REG(0, 0x0e0c)
+#define  REG_FACE_DET_OFF		0x0000
+#define  REG_FACE_DET_ON		0x0001
+
+#define REG_FACE_DET_OSD		S5C73M3_REG(0, 0x0e0e)
+#define  REG_FACE_DET_OSD_OFF		0x0000
+#define  REG_FACE_DET_OSD_ON		0x0001
+
+#define REG_AE_CON			S5C73M3_REG(0, 0x0c00)
+#define  REG_AE_STOP			0x0000 /* lock */
+#define  REG_AE_START			0x0001 /* unlock */
+
+#define REG_ISO				S5C73M3_REG(0, 0x0c02)
+#define  REG_ISO_AUTO			0x0000
+#define  REG_ISO_100			0x0001
+#define  REG_ISO_200			0x0002
+#define  REG_ISO_400			0x0003
+#define  REG_ISO_800			0x0004
+#define  REG_ISO_SPORTS			0x0005
+#define  REG_ISO_NIGHT			0x0006
+#define  REG_ISO_INDOOR			0x0007
+
+/* 0x00000 (-2.0 EV)...0x0008 (2.0 EV), 0.5EV step */
+#define REG_EV				S5C73M3_REG(0, 0x0c04)
+
+#define REG_METERING			S5C73M3_REG(0, 0x0c06)
+#define  REG_METERING_CENTER		0x0000
+#define  REG_METERING_SPOT		0x0001
+#define  REG_METERING_AVERAGE		0x0002
+#define  REG_METERING_SMART		0x0003
+
+#define REG_WDR				S5C73M3_REG(0, 0x0c08)
+#define  REG_WDR_OFF			0x0000
+#define  REG_WDR_ON			0x0001
+
+#define REG_AE_MODE			S5C73M3_REG(0, 0x0c1e)
+#define  REG_AE_MODE_AUTO_SET		0x0000
+#define  REG_AE_MODE_FIXED_30FPS	0x0002
+#define  REG_AE_MODE_FIXED_20FPS	0x0003
+#define  REG_AE_MODE_FIXED_15FPS	0x0004
+#define  REG_AE_MODE_FIXED_120FPS	0x0008
+#define  REG_AE_MODE_FIXED_7FPS		0x0009
+#define  REG_AE_MODE_ANTI_SHAKE		0x0013
+
+/* 0x0000...0x0004 -> sharpness: 0, 1, 2, -1, -2 */
+#define REG_SHARPNESS			S5C73M3_REG(0, 0x0c14)
+
+/* 0x0000...0x0004 -> saturation: 0, 1, 2, -1, -2 */
+#define REG_SATURATION			S5C73M3_REG(0, 0x0c16)
+
+/* 0x0000...0x0004 -> contrast: 0, 1, 2, -1, -2 */
+#define REG_CONTRAST			S5C73M3_REG(0, 0x0c18)
+
+#define REG_SCENE_MODE			S5C73M3_REG(0, 0x0c1a)
+#define  REG_SCENE_MODE_NONE		0x0000
+#define  REG_SCENE_MODE_PORTRAIT	0x0001
+#define  REG_SCENE_MODE_LANDSCAPE	0x0002
+#define  REG_SCENE_MODE_SPORTS		0x0003
+#define  REG_SCENE_MODE_INDOOR		0x0004
+#define  REG_SCENE_MODE_BEACH		0x0005
+#define  REG_SCENE_MODE_SUNSET		0x0006
+#define  REG_SCENE_MODE_DAWN		0x0007
+#define  REG_SCENE_MODE_FALL		0x0008
+#define  REG_SCENE_MODE_NIGHT		0x0009
+#define  REG_SCENE_MODE_AGAINST_LIGHT	0x000a
+#define  REG_SCENE_MODE_FIRE		0x000b
+#define  REG_SCENE_MODE_TEXT		0x000c
+#define  REG_SCENE_MODE_CANDLE		0x000d
+
+#define REG_AE_AUTO_BRACKET		S5C73M3_REG(0, 0x0b14)
+#define  REG_AE_AUTO_BRAKET_EV05	0x0080
+#define  REG_AE_AUTO_BRAKET_EV10	0x0100
+#define  REG_AE_AUTO_BRAKET_EV15	0x0180
+#define  REG_AE_AUTO_BRAKET_EV20	0x0200
+
+#define REG_SENSOR_STREAMING		S5C73M3_REG(0, 0x090a)
+#define  REG_SENSOR_STREAMING_OFF	0x0000
+#define  REG_SENSOR_STREAMING_ON	0x0001
+
+#define REG_AWB_MODE			S5C73M3_REG(0, 0x0d02)
+#define  REG_AWB_MODE_INCANDESCENT	0x0000
+#define  REG_AWB_MODE_FLUORESCENT1	0x0001
+#define  REG_AWB_MODE_FLUORESCENT2	0x0002
+#define  REG_AWB_MODE_DAYLIGHT		0x0003
+#define  REG_AWB_MODE_CLOUDY		0x0004
+#define  REG_AWB_MODE_AUTO		0x0005
+
+#define REG_AWB_CON			S5C73M3_REG(0, 0x0d00)
+#define  REG_AWB_STOP			0x0000 /* lock */
+#define  REG_AWB_START			0x0001 /* unlock */
+
+#define S5C73M3_ARRAY_END		0xffffffff
+
+#define S5C73M3_MAX_SUPPLIES		6
+
+struct s5c73m3_ctrls {
+	struct v4l2_ctrl_handler handler;
+	struct {
+		/* exposure/exposure bias cluster */
+		struct v4l2_ctrl *auto_exposure;
+		struct v4l2_ctrl *exposure_bias;
+		struct v4l2_ctrl *exposure_metering;
+	};
+	struct {
+		/* iso/auto iso cluster */
+		struct v4l2_ctrl *auto_iso;
+		struct v4l2_ctrl *iso;
+	};
+	struct v4l2_ctrl *auto_wb;
+	struct {
+		/* continuous auto focus/auto focus cluster */
+		struct v4l2_ctrl *focus_auto;
+		struct v4l2_ctrl *af_start;
+		struct v4l2_ctrl *af_stop;
+		struct v4l2_ctrl *af_status;
+		struct v4l2_ctrl *af_distance;
+		struct v4l2_ctrl *af_area;
+	};
+
+	struct v4l2_ctrl *ae_awb_lock;
+	struct v4l2_ctrl *colorfx;
+	struct v4l2_ctrl *contrast;
+	struct v4l2_ctrl *saturation;
+	struct v4l2_ctrl *sharpness;
+	struct v4l2_ctrl *zoom;
+	struct v4l2_ctrl *wdr;
+	struct v4l2_ctrl *stabilization;
+	struct v4l2_ctrl *jpeg_quality;
+	struct v4l2_ctrl *flash_mode;
+	struct v4l2_ctrl *scene_mode;
+	struct v4l2_ctrl *capture_ctx;
+	struct v4l2_ctrl *snapshot;
+};
+
+enum s5c73m3_gpio_id {
+	STBY,
+	RST,
+	GPIO_NUM,
+};
+
+struct s5c73m3_focus {
+	unsigned short pos_x;
+	unsigned short pos_y;
+};
+
+struct s5c73m3_pixfmt {
+	enum v4l2_mbus_pixelcode code;
+	u32 colorspace;
+	u8  mipi_data_type;
+};
+
+struct s5c73m3_interval {
+	u16 fps_reg;
+	struct v4l2_fract interval;
+	/* Maximum rectangle for the interval */
+	struct v4l2_frmsize_discrete size;
+};
+
+struct s5c73m3 {
+	struct v4l2_subdev subdev;
+	struct media_pad pads[S5C73M3_NUM_PADS];
+
+	struct spi_driver spidrv;
+	struct spi_device *spi_dev;
+	struct i2c_client *i2c_client;
+
+	struct regulator_bulk_data supplies[S5C73M3_MAX_SUPPLIES];
+	struct s5c73m3_gpio gpio[GPIO_NUM];
+
+	/* External master clock frequency */
+	unsigned long mclk_frequency;
+	/* Video bus type - MIPI-CSI2/paralell */
+	enum v4l2_mbus_type bus_type;
+
+	const struct s5c73m3_frame_size *pix_sizes[2];
+#define PREVIEW_IDX 0
+#define CAPTURE_IDX 1
+	unsigned int pix_sizes_len[2];
+
+	const struct s5c73m3_frame_size *prev_pix_size;
+	const struct s5c73m3_frame_size *cap_pix_size;
+	u8 wide_res;
+
+	const struct s5c73m3_interval *fiv;
+
+	/* protects the struct members below */
+	struct mutex lock;
+
+	int fw_index;
+
+	struct s5c73m3_ctrls ctrls;
+	struct v4l2_mbus_framefmt format[2];
+
+	u8 streaming;
+	u8 apply_fmt;
+	u8 apply_crop;
+	u8 apply_ctrls;
+	u8 apply_fiv;
+	u8 isp_ready;
+
+	struct s5c73m3_focus focus;
+
+	unsigned short fw_error;
+	unsigned short power;
+
+	char sensor_fw[10];
+};
+
+struct s5c73m3_frame_size {
+	u32 width;
+	u32 height;
+	u8 reg_val;
+	/* Wide resolution is set to 1 : height / width < 0.65 */
+	u8 wide_res; /* for POSTVIEW only */
+};
+
+extern int s5c73m3_dbg;
+
+/*
+ * Function prototypes
+ */
+int s5c73m3_register_spi_driver(struct s5c73m3 *state);
+void s5c73m3_unregister_spi_driver(struct s5c73m3 *state);
+int s5c73m3_spi_write(struct s5c73m3 *state, const void *addr,
+		      const unsigned int len, const unsigned int tx_size);
+
+int s5c73m3_i2c_write(struct i2c_client *client, u16 addr, u16 data);
+int s5c73m3_read(struct i2c_client *client, u32 addr, u16 *data);
+int s5c73m3_write_cmd(struct s5c73m3 *state, u32 addr, u16 data);
+int s5c73m3_init_controls(struct s5c73m3 *state);
+
+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct s5c73m3,
+			     ctrls.handler)->subdev;
+}
+
+static inline struct s5c73m3 *subdev_to_s5c73m3(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct s5c73m3, subdev);
+}
+#endif	/* S5C73M3_H_ */
diff --git a/include/media/s5c73m3.h b/include/media/s5c73m3.h
new file mode 100644
index 0000000..9110861
--- /dev/null
+++ b/include/media/s5c73m3.h
@@ -0,0 +1,62 @@
+/*
+ * Driver for S5C73M3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef MEDIA_S5C73M3__
+#define MEDIA_S5C73M3__
+
+#include <linux/videodev2.h>
+#include <media/v4l2-mediabus.h>
+
+/**
+ * struct s5c73m3_gpio - data structure describing a GPIO
+ * @gpio:  GPIO number
+ * @level: indicates active state of the @gpio
+ */
+struct s5c73m3_gpio {
+	int gpio;
+	int level;
+};
+
+/**
+ * struct s5c73m3_platform_data - s5c73m3 driver platform data
+ * @mclk_frequency: sensor's master clock frequency in Hz
+ * @gpio_reset:  GPIO driving RESET pin
+ * @gpio_stby:   GPIO driving STBY pin
+ * @nlanes:      maximum number of MIPI-CSI lanes used
+ * @horiz_flip:  default horizontal image flip value, non zero to enable
+ * @vert_flip:   default vertical image flip value, non zero to enable
+ */
+
+struct s5c73m3_platform_data {
+	unsigned long mclk_frequency;
+
+	struct s5c73m3_gpio gpio_reset;
+	struct s5c73m3_gpio gpio_stby;
+
+	enum v4l2_mbus_type bus_type;
+	u8 nlanes;
+	u8 horiz_flip;
+	u8 vert_flip;
+};
+
+#define V4L2_CID_CAM_SENSOR_FW_VER (V4L2_CID_CAMERA_CLASS_BASE + 28)
+#define V4L2_CID_CAM_PHONE_FW_VER (V4L2_CID_CAMERA_CLASS_BASE + 29)
+
+enum stream_mode_t {
+	STREAM_MODE_CAM_OFF,
+	STREAM_MODE_CAM_ON,
+	STREAM_MODE_MOVIE_OFF,
+	STREAM_MODE_MOVIE_ON,
+};
+
+#define V4L2_CID_FOCUS_AUTO_RECTANGLE_LEFT	(V4L2_CID_CAMERA_CLASS_BASE+37)
+#define V4L2_CID_FOCUS_AUTO_RECTANGLE_TOP	(V4L2_CID_CAMERA_CLASS_BASE+38)
+#define V4L2_CID_FOCUS_AUTO_RECTANGLE_WIDTH	(V4L2_CID_CAMERA_CLASS_BASE+39)
+#define V4L2_CID_FOCUS_AUTO_RECTANGLE_HEIGHT	(V4L2_CID_CAMERA_CLASS_BASE+40)
+
+#endif /* MEDIA_S5C73M3__ */
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH/RFC v4 01/12] V4L: Add helper function for standard integer menu controls
  2012-05-04 18:32 ` [PATCH/RFC v4 01/12] V4L: Add helper function for standard integer menu controls Sylwester Nawrocki
@ 2012-05-06 10:12   ` Sakari Ailus
  2012-05-06 17:00     ` Sylwester Nawrocki
  2012-05-06 18:51     ` [PATCH v5 " Sylwester Nawrocki
  0 siblings, 2 replies; 25+ messages in thread
From: Sakari Ailus @ 2012-05-06 10:12 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-media, laurent.pinchart, g.liakhovetski, hdegoede, moinejf,
	hverkuil, m.szyprowski, riverful.kim, sw0312.kim, Kyungmin Park

Hi Sylwester,

Sylwester Nawrocki wrote:
> This patch adds v4l2_ctrl_new_std_int_menu() helper function which can
> be used in drivers for creating standard integer menu control. It is
> similar to v4l2_ctrl_new_std_menu(), except it doesn't have a mask
> parameter and an additional qmenu parameter allows passing an array
> of signed 64-bit integers constituting the menu items.

It would make sense to have the mask and no pointer to the menu items if
the menu items are universally the same. This could come into question
on some standards, for example. For example, we currently have bit rates
in controls but they are strings, not integers. I could imagine we will
have such menus in the future.

I'd suggest to rename v4l2_ctrl_new_std_int_menu() as
v4l2_ctrl_new_int_menu(), as opposed to the former which would use
standardised items in the menu --- to be implemented when needed.

Kind regards,

-- 
Sakari Ailus
sakari.ailus@iki.fi

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH/RFC v4 01/12] V4L: Add helper function for standard integer menu controls
  2012-05-06 10:12   ` Sakari Ailus
@ 2012-05-06 17:00     ` Sylwester Nawrocki
  2012-05-06 18:51     ` [PATCH v5 " Sylwester Nawrocki
  1 sibling, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-06 17:00 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Sylwester Nawrocki, linux-media, laurent.pinchart,
	g.liakhovetski, hdegoede, moinejf, hverkuil, m.szyprowski,
	riverful.kim, sw0312.kim, Kyungmin Park

Hi Sakari,

On 05/06/2012 12:12 PM, Sakari Ailus wrote:
> Hi Sylwester,
>
> Sylwester Nawrocki wrote:
>> This patch adds v4l2_ctrl_new_std_int_menu() helper function which can
>> be used in drivers for creating standard integer menu control. It is
>> similar to v4l2_ctrl_new_std_menu(), except it doesn't have a mask
>> parameter and an additional qmenu parameter allows passing an array
>> of signed 64-bit integers constituting the menu items.
>
> It would make sense to have the mask and no pointer to the menu items if
> the menu items are universally the same. This could come into question
> on some standards, for example. For example, we currently have bit rates
> in controls but they are strings, not integers. I could imagine we will
> have such menus in the future.
>
> I'd suggest to rename v4l2_ctrl_new_std_int_menu() as
> v4l2_ctrl_new_int_menu(), as opposed to the former which would use
> standardised items in the menu --- to be implemented when needed.

Thank you for pointing it out. Let me just correct this and resend
the patch.

Best regards,
Sylwester

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH/RFC v4 10/12] V4L: Add auto focus targets to the selections API
  2012-05-04 18:32 ` [PATCH/RFC v4 10/12] V4L: Add auto focus targets to the selections API Sylwester Nawrocki
@ 2012-05-06 18:22   ` Sakari Ailus
  2012-05-08 10:46     ` Sylwester Nawrocki
  0 siblings, 1 reply; 25+ messages in thread
From: Sakari Ailus @ 2012-05-06 18:22 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-media, laurent.pinchart, g.liakhovetski, hdegoede, moinejf,
	hverkuil, m.szyprowski, riverful.kim, sw0312.kim, Kyungmin Park

Hi Sylwester,

Thanks for the patch.

Sylwester Nawrocki wrote:
> The camera automatic focus algorithms may require setting up
> a spot or rectangle coordinates or multiple such parameters.
> 
> The automatic focus selection targets are introduced in order
> to allow applications to query and set such coordinates. Those
> selections are intended to be used together with the automatic
> focus controls available in the camera control class.

Have you thought about multiple autofocus windows, and how could they be
implemented on top of this patch?

I'm not saying that we should implement them now, but at least we should
think how we _would_ implement them when needed. They aren't that exotic
functionality these days after all.

I'd guess this would involve an additional bitmask control and defining
a set of new targets. A comment in the source might help here ---
perhaps a good rule is to start new ranges at 0x1000 as you're doing
already.

> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  Documentation/DocBook/media/v4l/selection-api.xml  |   33 +++++++++++++++++++-
>  .../DocBook/media/v4l/vidioc-g-selection.xml       |   11 +++++++
>  include/linux/videodev2.h                          |    5 +++
>  3 files changed, 48 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml
> index b299e47..490d29a 100644
> --- a/Documentation/DocBook/media/v4l/selection-api.xml
> +++ b/Documentation/DocBook/media/v4l/selection-api.xml
> @@ -1,6 +1,6 @@
>  <section id="selection-api">
>  
> -  <title>Experimental API for cropping, composing and scaling</title>
> +  <title>Experimental selections API</title>
>  
>        <note>
>  	<title>Experimental</title>
> @@ -9,6 +9,10 @@
>  interface and may change in the future.</para>
>        </note>
>  
> + <section>
> +
> + <title>Image cropping, composing and scaling</title>
> +
>    <section>
>      <title>Introduction</title>
>  
> @@ -321,5 +325,32 @@ V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> for other devices</para>
>        </example>
>  
>     </section>
> + </section>
> +
> +   <section>
> +     <title>Automatic focus regions of interest</title>
> +
> +<para> The camera automatic focus algorithms may require configuration of
> +regions of interest in form of rectangle or spot coordinates. The automatic
> +focus selection targets allow applications to query and set such coordinates.
> +Those selections are intended to be used together with the
> +<constant>V4L2_CID_AUTO_FOCUS_AREA</constant> <link linkend="camera-controls">
> +camera class</link> control. The <constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL
> +</constant> target is used for querying or setting actual spot or rectangle
> +coordinates, while <constant>V4L2_SEL_TGT_AUTO_FOCUS_BOUNDS</constant> target
> +determines bounds for a single spot or rectangle.
> +These selections are only effective when the <constant>V4L2_CID_AUTO_FOCUS_AREA
> +</constant>control is set to <constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant> or
> +<constant>V4L2_AUTO_FOCUS_AREA_RECTANGLE</constant>. The new coordinates shall
> +be accepted and applied to hardware when the focus area control value is
> +changed and also during a &VIDIOC-S-SELECTION; ioctl call, only when the focus
> +area control is already set to required value.</para>
> +
> +<para> For the <constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant> case, the selection
> +rectangle <structfield> width</structfield> and <structfield>height</structfield>
> +are not used, i.e. shall be set to 0 by applications and ignored by drivers for
> +the &VIDIOC-S-SELECTION; ioctl and shall be ignored by applications for the
> +&VIDIOC-G-SELECTION; ioctl.</para>
> +   </section>
>  
>  </section>
> diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
> index bb04eff..87df4da 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
> @@ -195,6 +195,17 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
>              <entry>0x0103</entry>
>              <entry>The active area and all padding pixels that are inserted or modified by hardware.</entry>
>  	  </row>
> +	  <row>
> +            <entry><constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant></entry>
> +            <entry>0x1000</entry>
> +	    <entry>Actual automatic focus rectangle or spot coordinates.</entry>
> +	  </row>
> +	  <row>
> +            <entry><constant>V4L2_SEL_TGT_AUTO_FOCUS_BOUNDS</constant></entry>
> +            <entry>0x1002</entry>

This should be 0x1001, I believe.

> +            <entry>Bounds of the automatic focus region of interest.
> +	    </entry>
> +	  </row>
>  	</tbody>
>        </tgroup>
>      </table>
> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index c1fae94..6bfd6c5 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -777,6 +777,11 @@ struct v4l2_crop {
>  /* Current composing area plus all padding pixels */
>  #define V4L2_SEL_TGT_COMPOSE_PADDED	0x0103
>  
> +/* Auto focus region of interest */
> +#define V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL	0x1000
> +/* Auto focus region (spot coordinates) bounds */
> +#define V4L2_SEL_TGT_AUTO_FOCUS_BOUNDS	0x1001
> +
>  /**
>   * struct v4l2_selection - selection info
>   * @type:	buffer type (do not use *_MPLANE types)

Cheers,

-- 
Sakari Ailus
sakari.ailus@iki.fi

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH/RFC v4 12/12] V4L: Add camera auto focus controls
  2012-05-04 18:32 ` [PATCH/RFC v4 12/12] V4L: Add camera auto focus controls Sylwester Nawrocki
@ 2012-05-06 18:46   ` Sakari Ailus
  2012-05-09 10:11     ` Sylwester Nawrocki
  2012-05-06 18:58   ` [PATCH v5 " Sylwester Nawrocki
  1 sibling, 1 reply; 25+ messages in thread
From: Sakari Ailus @ 2012-05-06 18:46 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-media, laurent.pinchart, g.liakhovetski, hdegoede, moinejf,
	hverkuil, m.szyprowski, riverful.kim, sw0312.kim, Kyungmin Park

Hi Sylwester,

Thanks for the patch,

Sylwester Nawrocki wrote:
> Add following auto focus controls:
> 
>  - V4L2_CID_AUTO_FOCUS_START - single-shot auto focus start
>  - V4L2_CID_AUTO_FOCUS_STOP -  single-shot auto focus stop
>  - V4L2_CID_AUTO_FOCUS_STATUS - automatic focus status
>  - V4L2_CID_AUTO_FOCUS_AREA - automatic focus area selection
>  - V4L2_CID_AUTO_FOCUS_DISTANCE - automatic focus scan range selection
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  Documentation/DocBook/media/v4l/controls.xml |  147 +++++++++++++++++++++++++-
>  drivers/media/video/v4l2-ctrls.c             |   31 +++++-
>  include/linux/videodev2.h                    |   25 +++++
>  3 files changed, 200 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
> index 4a463d3..d8ef71e 100644
> --- a/Documentation/DocBook/media/v4l/controls.xml
> +++ b/Documentation/DocBook/media/v4l/controls.xml
> @@ -2902,13 +2902,156 @@ negative values towards infinity. This is a write-only control.</entry>
>  	  <row>
>  	    <entry spanname="id"><constant>V4L2_CID_FOCUS_AUTO</constant>&nbsp;</entry>
>  	    <entry>boolean</entry>
> -	  </row><row><entry spanname="descr">Enables automatic focus
> -adjustments. The effect of manual focus adjustments while this feature
> +	  </row><row><entry spanname="descr">Enables continuous automatic
> +focus adjustments. The effect of manual focus adjustments while this feature
>  is enabled is undefined, drivers should ignore such requests.</entry>
>  	  </row>
>  	  <row><entry></entry></row>
>  
>  	  <row>
> +	    <entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_START</constant>&nbsp;</entry>
> +	    <entry>button</entry>
> +	  </row><row><entry spanname="descr">Starts single auto focus process.
> +The effect of setting this control when <constant>V4L2_CID_FOCUS_AUTO</constant>
> +is set to <constant>TRUE</constant> (1) is undefined, drivers should ignore
> +such requests.</entry>
> +	  </row>
> +	  <row><entry></entry></row>
> +
> +	  <row>
> +	    <entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_STOP</constant>&nbsp;</entry>
> +	    <entry>button</entry>
> +	  </row><row><entry spanname="descr">Aborts automatic focusing
> +started with <constant>V4L2_CID_AUTO_FOCUS_START</constant> control. It is
> +effective only when the continuous autofocus is disabled, that is when
> +<constant>V4L2_CID_FOCUS_AUTO</constant> control is set to <constant>FALSE
> +</constant> (0).</entry>
> +	  </row>
> +	  <row><entry></entry></row>
> +
> +	  <row id="v4l2-auto-focus-status">
> +	    <entry spanname="id">
> +	      <constant>V4L2_CID_AUTO_FOCUS_STATUS</constant>&nbsp;</entry>
> +	    <entry>bitmask</entry>
> +	  </row>
> +	  <row><entry spanname="descr">The automatic focus status. This is a read-only
> +	  control.</entry>
> +	  </row>
> +	  <row>
> +	    <entrytbl spanname="descr" cols="2">
> +	      <tbody valign="top">
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_IDLE</constant>&nbsp;</entry>
> +		  <entry>Automatic focus is not active.</entry>
> +		</row>
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_BUSY</constant>&nbsp;</entry>
> +		  <entry>Automatic focusing is in progress.</entry>
> +		</row>
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_REACHED</constant>&nbsp;</entry>
> +		  <entry>Focus has been reached.</entry>
> +		</row>
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_LOST</constant>&nbsp;</entry>
> +		  <entry>Focus has been lost.</entry>

When does this happen?

> +		</row>
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_FAILED</constant>&nbsp;</entry>
> +		  <entry>Automatic focus has failed, the driver will not
> +		  transition from this state until another action is
> +		  performed by an  application.</entry>

Which of these are valid for regular autofocus and which ones for
continuous autofocus? I'm a little bit confused with the above descriptions.

I might as well say that temporary conditions such as failed and reached
would return to idle after being read from user space. This is how the
flash faults behave, too.

How does this interact with the 3A lock control?

> +		</row>
> +	      </tbody>
> +	    </entrytbl>
> +	  </row>
> +	  <row><entry></entry></row>
> +
> +	  <row id="v4l2-auto-focus-range">
> +	    <entry spanname="id">
> +	      <constant>V4L2_CID_AUTO_FOCUS_RANGE</constant>&nbsp;</entry>
> +	    <entry>enum&nbsp;v4l2_auto_focus_range</entry>
> +	  </row>
> +	  <row><entry spanname="descr">Determines auto focus distance range
> +for which lens may be adjusted. </entry>
> +	  </row>
> +	  <row>
> +	    <entrytbl spanname="descr" cols="2">
> +	      <tbody valign="top">
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_AUTO</constant>&nbsp;</entry>
> +		  <entry>The camera automatically selects the focus range.</entry>
> +		</row>
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_NORMAL</constant>&nbsp;</entry>
> +		  <entry>The auto focus normal distance range. It is limited
> +for best auto focus algorithm performance.</entry>
> +		</row>
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_MACRO</constant>&nbsp;</entry>
> +		  <entry>Macro (close-up) auto focus. The camera will
> +use minimum possible distance that it is capable of for auto focus.</entry>
> +		</row>
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_INFINITY</constant>&nbsp;</entry>
> +		  <entry>The focus at an object at infinite distance.</entry>
> +		</row>
> +	      </tbody>
> +	    </entrytbl>
> +	  </row>
> +	  <row><entry></entry></row>
> +
> +	  <row id="v4l2-auto-focus-area">
> +	    <entry spanname="id">
> +	      <constant>V4L2_CID_AUTO_FOCUS_AREA</constant>&nbsp;</entry>
> +	    <entry>enum&nbsp;v4l2_auto_focus_area</entry>
> +	  </row>
> +	  <row><entry spanname="descr">Determines the area of the frame that
> +the camera uses for automatic focus. The corresponding coordinates of the
> +focusing spot or rectangle can be specified and queried using the selection API.
> +To change the auto focus region of interest applications first select required
> +mode of this control and then set the rectangle or spot coordinates by means
> +of the &VIDIOC-SUBDEV-S-SELECTION; or &VIDIOC-S-SELECTION; ioctl. In order to
> +trigger again an auto focus process with same coordinates applications should
> +use the <constant>V4L2_CID_AUTO_FOCUS_START </constant> control. Or alternatively
> +invoke a &VIDIOC-SUBDEV-S-SELECTION; or a &VIDIOC-S-SELECTION; ioctl again.
> +In the latter case the new pixel coordinates are applied to hardware only when
> +the focus area control is set to a value other than
> +<constant>V4L2_AUTO_FOCUS_AREA_ALL</constant>.</entry>
> +	  </row>
> +	  <row>
> +	    <entrytbl spanname="descr" cols="2">
> +	      <tbody valign="top">
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_AREA_ALL</constant>&nbsp;</entry>
> +		  <entry>Normal auto focus, the focusing area extends over the
> +entire frame.</entry>
> +		</row>
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant>&nbsp;</entry>
> +		  <entry>Automatic focus on a spot within the frame at position
> +specified by the <constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> or
> +<constant>V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> selection. When these
> +selections are not supported by driver the default spot's position is center of
> +the frame.</entry>
> +		</row>
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_AREA_RECTANGLE</constant>&nbsp;</entry>
> +		  <entry>The auto focus area is determined by the <constant>
> +V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> or <constant>
> +V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> selection rectangle.</entry>
> +		</row>
> +		<row>
> +		  <entry><constant>V4L2_AUTO_FOCUS_AREA_FACE_DETECTION</constant>&nbsp;</entry>
> +		  <entry>The camera automatically focuses on a detected face
> +area.</entry>

I assume there could be one or more faces to focus to, right?

> +		</row>
> +	      </tbody>
> +	    </entrytbl>
> +	  </row>
> +	  <row><entry></entry></row>
> +
> +	  <row>
>  	    <entry spanname="id"><constant>V4L2_CID_ZOOM_ABSOLUTE</constant>&nbsp;</entry>
>  	    <entry>integer</entry>
>  	  </row><row><entry spanname="descr">Specify the objective lens
> diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
> index 6346978..ea86a10 100644
> --- a/drivers/media/video/v4l2-ctrls.c
> +++ b/drivers/media/video/v4l2-ctrls.c
> @@ -236,6 +236,20 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
>  		"Spot",
>  		NULL
>  	};
> +	static const char * const camera_auto_focus_area[] = {
> +		"All",
> +		"Spot",
> +		"Rectangle",
> +		"Face Detection",
> +		NULL
> +	};
> +	static const char * const camera_auto_focus_range[] = {
> +		"Auto",
> +		"Normal",
> +		"Macro",
> +		"Infinity",
> +		NULL
> +	};
>  	static const char * const colorfx[] = {
>  		"None",
>  		"Black & White",
> @@ -453,6 +467,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
>  		return camera_exposure_auto;
>  	case V4L2_CID_EXPOSURE_METERING:
>  		return camera_exposure_metering;
> +	case V4L2_CID_AUTO_FOCUS_AREA:
> +		return camera_auto_focus_area;
> +	case V4L2_CID_AUTO_FOCUS_RANGE:
> +		return camera_auto_focus_range;
>  	case V4L2_CID_COLORFX:
>  		return colorfx;
>  	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
> @@ -639,7 +657,7 @@ const char *v4l2_ctrl_get_name(u32 id)
>  	case V4L2_CID_TILT_ABSOLUTE:		return "Tilt, Absolute";
>  	case V4L2_CID_FOCUS_ABSOLUTE:		return "Focus, Absolute";
>  	case V4L2_CID_FOCUS_RELATIVE:		return "Focus, Relative";
> -	case V4L2_CID_FOCUS_AUTO:		return "Focus, Automatic";
> +	case V4L2_CID_FOCUS_AUTO:		return "Focus, Automatic Continuous";
>  	case V4L2_CID_ZOOM_ABSOLUTE:		return "Zoom, Absolute";
>  	case V4L2_CID_ZOOM_RELATIVE:		return "Zoom, Relative";
>  	case V4L2_CID_ZOOM_CONTINUOUS:		return "Zoom, Continuous";
> @@ -655,6 +673,11 @@ const char *v4l2_ctrl_get_name(u32 id)
>  	case V4L2_CID_EXPOSURE_METERING:	return "Exposure, Metering Mode";
>  	case V4L2_CID_SCENE_MODE:		return "Scene Mode";
>  	case V4L2_CID_3A_LOCK:			return "3A Lock";
> +	case V4L2_CID_AUTO_FOCUS_START:		return "Auto Focus, Start";
> +	case V4L2_CID_AUTO_FOCUS_STOP:		return "Auto Focus, Stop";
> +	case V4L2_CID_AUTO_FOCUS_STATUS:	return "Auto Focus, Status";
> +	case V4L2_CID_AUTO_FOCUS_RANGE:		return "Auto Focus, Range";
> +	case V4L2_CID_AUTO_FOCUS_AREA:		return "Auto Focus, Area";
>  
>  	/* FM Radio Modulator control */
>  	/* Keep the order of the 'case's the same as in videodev2.h! */
> @@ -756,6 +779,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
>  	case V4L2_CID_TILT_RESET:
>  	case V4L2_CID_FLASH_STROBE:
>  	case V4L2_CID_FLASH_STROBE_STOP:
> +	case V4L2_CID_AUTO_FOCUS_START:
> +	case V4L2_CID_AUTO_FOCUS_STOP:
>  		*type = V4L2_CTRL_TYPE_BUTTON;
>  		*flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
>  		*min = *max = *step = *def = 0;
> @@ -779,6 +804,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
>  	case V4L2_CID_MPEG_STREAM_TYPE:
>  	case V4L2_CID_MPEG_STREAM_VBI_FMT:
>  	case V4L2_CID_EXPOSURE_AUTO:
> +	case V4L2_CID_AUTO_FOCUS_AREA:
> +	case V4L2_CID_AUTO_FOCUS_RANGE:
>  	case V4L2_CID_COLORFX:
>  	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
>  	case V4L2_CID_TUNE_PREEMPHASIS:
> @@ -828,6 +855,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
>  	case V4L2_CID_FLASH_FAULT:
>  	case V4L2_CID_JPEG_ACTIVE_MARKER:
>  	case V4L2_CID_3A_LOCK:
> +	case V4L2_CID_AUTO_FOCUS_STATUS:
>  		*type = V4L2_CTRL_TYPE_BITMASK;
>  		break;
>  	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
> @@ -887,6 +915,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
>  		*flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
>  		break;
>  	case V4L2_CID_FLASH_STROBE_STATUS:
> +	case V4L2_CID_AUTO_FOCUS_STATUS:
>  	case V4L2_CID_FLASH_READY:
>  		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
>  		break;
> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index 6bfd6c5..1d5b839 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -1754,6 +1754,31 @@ enum v4l2_scene_mode {
>  #define V4L2_LOCK_WHITE_BALANCE			(1 << 1)
>  #define V4L2_LOCK_FOCUS				(1 << 2)
>  
> +#define V4L2_CID_AUTO_FOCUS_START		(V4L2_CID_CAMERA_CLASS_BASE+28)
> +#define V4L2_CID_AUTO_FOCUS_STOP		(V4L2_CID_CAMERA_CLASS_BASE+29)
> +#define V4L2_CID_AUTO_FOCUS_STATUS		(V4L2_CID_CAMERA_CLASS_BASE+30)
> +#define V4L2_AUTO_FOCUS_STATUS_IDLE		(0 << 0)
> +#define V4L2_AUTO_FOCUS_STATUS_BUSY		(1 << 0)
> +#define V4L2_AUTO_FOCUS_STATUS_REACHED		(1 << 1)
> +#define V4L2_AUTO_FOCUS_STATUS_LOST		(1 << 2)
> +#define V4L2_AUTO_FOCUS_STATUS_FAILED		(1 << 3)
> +
> +#define V4L2_CID_AUTO_FOCUS_RANGE		(V4L2_CID_CAMERA_CLASS_BASE+31)
> +enum v4l2_auto_focus_range {
> +	V4L2_AUTO_FOCUS_RANGE_AUTO		= 0,
> +	V4L2_AUTO_FOCUS_RANGE_NORMAL		= 1,
> +	V4L2_AUTO_FOCUS_RANGE_MACRO		= 2,
> +	V4L2_AUTO_FOCUS_RANGE_INFINITY		= 3,
> +};
> +
> +#define V4L2_CID_AUTO_FOCUS_AREA		(V4L2_CID_CAMERA_CLASS_BASE+32)
> +enum v4l2_auto_focus_area {
> +	V4L2_AUTO_FOCUS_AREA_ALL		= 0,
> +	V4L2_AUTO_FOCUS_AREA_SPOT		= 1,
> +	V4L2_AUTO_FOCUS_AREA_RECTANGLE		= 2,
> +	V4L2_AUTO_FOCUS_AREA_FACE_DETECTION	= 3,
> +};
> +
>  /* FM Modulator class control IDs */
>  #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
>  #define V4L2_CID_FM_TX_CLASS			(V4L2_CTRL_CLASS_FM_TX | 1)

Cheers,

-- 
Sakari Ailus
sakari.ailus@iki.fi

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v5 01/12] V4L: Add helper function for standard integer menu controls
  2012-05-06 10:12   ` Sakari Ailus
  2012-05-06 17:00     ` Sylwester Nawrocki
@ 2012-05-06 18:51     ` Sylwester Nawrocki
  2012-05-07 15:05       ` Sakari Ailus
  1 sibling, 1 reply; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-06 18:51 UTC (permalink / raw)
  To: linux-media; +Cc: sakari.ailus, Sylwester Nawrocki, Kyungmin Park

This patch adds v4l2_ctrl_new_int_menu() helper function which can be used
in drivers for creating standard integer menu control with driver-specific
menu item list. It is similar to v4l2_ctrl_new_std_menu(), except it doesn't
have a mask parameter and an additional qmenu parameter allows passing
an array of signed 64-bit integers as the menu item list.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Changes since v4:
 - v4l2_ctrl_new_std_int_menu() renamed to v4l2_ctrl_new_int_menu()
   so that v4l2_ctrl_new_std_int_menu can be later used for controls
   with standar menu items, as suggested by Sakari.

Regards,
Sylwester

 Documentation/video4linux/v4l2-controls.txt |   21 +++++++++++++++++++++
 drivers/media/video/v4l2-ctrls.c            |   21 +++++++++++++++++++++
 include/media/v4l2-ctrls.h                  |   17 +++++++++++++++++
 3 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt
index e2492a9..43da22b 100644
--- a/Documentation/video4linux/v4l2-controls.txt
+++ b/Documentation/video4linux/v4l2-controls.txt
@@ -130,8 +130,18 @@ Menu controls are added by calling v4l2_ctrl_new_std_menu:
 			const struct v4l2_ctrl_ops *ops,
 			u32 id, s32 max, s32 skip_mask, s32 def);

+Or alternatively for integer menu controls, by calling v4l2_ctrl_new_int_menu:
+
+	struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
+			const struct v4l2_ctrl_ops *ops,
+			u32 id, s32 max, s32 def, const s64 *qmenu_int);
+
 These functions are typically called right after the v4l2_ctrl_handler_init:

+	static const s64 exp_bias_qmenu[] = {
+	       -2, -1, 0, 1, 2
+	};
+
 	v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);
 	v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,
 			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
@@ -141,6 +151,11 @@ These functions are typically called right after the v4l2_ctrl_handler_init:
 			V4L2_CID_POWER_LINE_FREQUENCY,
 			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
 			V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
+	v4l2_ctrl_new_int_menu(&foo->ctrl_handler, &foo_ctrl_ops,
+			V4L2_CID_EXPOSURE_BIAS,
+			ARRAY_SIZE(exp_bias_qmenu) - 1,
+			ARRAY_SIZE(exp_bias_qmenu) / 2 - 1,
+			exp_bias_qmenu);
 	...
 	if (foo->ctrl_handler.error) {
 		int err = foo->ctrl_handler.error;
@@ -164,6 +179,12 @@ controls. There is no min argument since that is always 0 for menu controls,
 and instead of a step there is a skip_mask argument: if bit X is 1, then menu
 item X is skipped.

+The v4l2_ctrl_new_int_menu function creates a new standard integer menu
+control with driver-specific items in the menu. It differs from
+v4l2_ctrl_new_std_menu in that it doesn't have the mask argument and takes
+as the last argument an array of signed 64-bit integers that form an exact
+menu item list.
+
 Note that if something fails, the function will return NULL or an error and
 set ctrl_handler->error to the error code. If ctrl_handler->error was already
 set, then it will just return and do nothing. This is also true for
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index c93a979..e586798c 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -1517,6 +1517,27 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);

+/* Helper function for standard integer menu controls */
+struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
+			const struct v4l2_ctrl_ops *ops,
+			u32 id, s32 max, s32 def, const s64 *qmenu_int)
+{
+	const char *name;
+	enum v4l2_ctrl_type type;
+	s32 min;
+	s32 step;
+	u32 flags;
+
+	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
+	if (type != V4L2_CTRL_TYPE_INTEGER_MENU) {
+		handler_set_err(hdl, -EINVAL);
+		return NULL;
+	}
+	return v4l2_ctrl_new(hdl, ops, id, name, type,
+			     0, max, 0, def, flags, NULL, qmenu_int, NULL);
+}
+EXPORT_SYMBOL(v4l2_ctrl_new_int_menu);
+
 /* Add a control from another handler to this handler */
 struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl,
 					  struct v4l2_ctrl *ctrl)
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 8920f82..48b6b90 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -347,6 +347,23 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 			const struct v4l2_ctrl_ops *ops,
 			u32 id, s32 max, s32 mask, s32 def);

+/** v4l2_ctrl_new_int_menu() - Create a new standard V4L2 integer menu control.
+  * @hdl:	The control handler.
+  * @ops:	The control ops.
+  * @id:	The control ID.
+  * @max:	The control's maximum value.
+  * @def:	The control's default value.
+  * @qmenu_int:	The control's menu entries.
+  *
+  * Same as v4l2_ctrl_new_std_menu(), but @mask is set to 0 and it additionaly
+  * takes as an argument an array of integers determining the menu items.
+  *
+  * If @id refers to a non-integer-menu control, then this function will return NULL.
+  */
+struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
+			const struct v4l2_ctrl_ops *ops,
+			u32 id, s32 max, s32 def, const s64 *qmenu_int);
+
 /** v4l2_ctrl_add_ctrl() - Add a control from another handler to this handler.
   * @hdl:	The control handler.
   * @ctrl:	The control to add.
--
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v5 12/12] V4L: Add camera auto focus controls
  2012-05-04 18:32 ` [PATCH/RFC v4 12/12] V4L: Add camera auto focus controls Sylwester Nawrocki
  2012-05-06 18:46   ` Sakari Ailus
@ 2012-05-06 18:58   ` Sylwester Nawrocki
  1 sibling, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-06 18:58 UTC (permalink / raw)
  To: linux-media; +Cc: Sylwester Nawrocki, Kyungmin Park

Add following auto focus controls:

 - V4L2_CID_AUTO_FOCUS_START - single-shot auto focus start
 - V4L2_CID_AUTO_FOCUS_STOP -  single-shot auto focus stop
 - V4L2_CID_AUTO_FOCUS_STATUS - automatic focus status
 - V4L2_CID_AUTO_FOCUS_AREA - automatic focus area selection
 - V4L2_CID_AUTO_FOCUS_RANGE - automatic focus scan range selection

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Chnages since v4:
 - V4L2_CID_AUTO_FOCUS_RANGE marked as experimental and done minor
   changes at the description of this control;

 Documentation/DocBook/media/v4l/compat.xml   |   20 ++++
 Documentation/DocBook/media/v4l/controls.xml |  151 +++++++++++++++++++++++++-
 Documentation/DocBook/media/v4l/v4l2.xml     |    9 ++-
 drivers/media/video/v4l2-ctrls.c             |   31 +++++-
 include/linux/videodev2.h                    |   25 +++++
 5 files changed, 232 insertions(+), 4 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
index d9bd3b1..be4a8c2 100644
--- a/Documentation/DocBook/media/v4l/compat.xml
+++ b/Documentation/DocBook/media/v4l/compat.xml
@@ -2435,6 +2435,22 @@ details.</para>
         <listitem>
 	  <para> Added <constant>V4L2_CID_COLORFX_CBCR</constant> control.</para>
         </listitem>
+        <listitem>
+	  <para> Added camera controls <constant>V4L2_CID_AUTO_EXPOSURE_BIAS</constant>,
+	  <constant>V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE</constant>,
+	  <constant>V4L2_CID_IMAGE_STABILIZATION</constant>,
+	  <constant>V4L2_CID_ISO_SENSITIVITY</constant>,
+	  <constant>V4L2_CID_ISO_SENSITIVITY_AUTO</constant>,
+	  <constant>V4L2_CID_EXPOSURE_METERING</constant>,
+	  <constant>V4L2_CID_SCENE_MODE</constant>,
+	  <constant>V4L2_CID_3A_LOCK</constant>,
+	  <constant>V4L2_CID_AUTO_FOCUS_START</constant>,
+	  <constant>V4L2_CID_AUTO_FOCUS_STOP</constant>,
+	  <constant>V4L2_CID_AUTO_FOCUS_STATUS</constant>,
+	  <constant>V4L2_CID_AUTO_FOCUS_RANGE</constant> and
+	  <constant>V4L2_CID_AUTO_FOCUS_AREA</constant>.
+	  </para>
+        </listitem>
       </orderedlist>
     </section>

@@ -2559,6 +2575,10 @@ ioctls.</para>
 	  <para>Importing DMABUF file descriptors as a new IO method described
 	  in <xref linkend="dmabuf" />.</para>
         </listitem>
+        <listitem>
+	  <para><link linkend="v4l2-auto-focus-area"><constant>
+	  V4L2_CID_AUTO_FOCUS_AREA</constant></link> control.</para>
+        </listitem>
       </itemizedlist>
     </section>

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 054cdba..b7b5c0c 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -2976,13 +2976,160 @@ negative values towards infinity. This is a write-only control.</entry>
 	  <row>
 	    <entry spanname="id"><constant>V4L2_CID_FOCUS_AUTO</constant>&nbsp;</entry>
 	    <entry>boolean</entry>
-	  </row><row><entry spanname="descr">Enables automatic focus
-adjustments. The effect of manual focus adjustments while this feature
+	  </row><row><entry spanname="descr">Enables continuous automatic
+focus adjustments. The effect of manual focus adjustments while this feature
 is enabled is undefined, drivers should ignore such requests.</entry>
 	  </row>
 	  <row><entry></entry></row>

 	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_START</constant>&nbsp;</entry>
+	    <entry>button</entry>
+	  </row><row><entry spanname="descr">Starts single auto focus process.
+The effect of setting this control when <constant>V4L2_CID_FOCUS_AUTO</constant>
+is set to <constant>TRUE</constant> (1) is undefined, drivers should ignore
+such requests.</entry>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_STOP</constant>&nbsp;</entry>
+	    <entry>button</entry>
+	  </row><row><entry spanname="descr">Aborts automatic focusing
+started with <constant>V4L2_CID_AUTO_FOCUS_START</constant> control. It is
+effective only when the continuous autofocus is disabled, that is when
+<constant>V4L2_CID_FOCUS_AUTO</constant> control is set to <constant>FALSE
+</constant> (0).</entry>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row id="v4l2-auto-focus-status">
+	    <entry spanname="id">
+	      <constant>V4L2_CID_AUTO_FOCUS_STATUS</constant>&nbsp;</entry>
+	    <entry>bitmask</entry>
+	  </row>
+	  <row><entry spanname="descr">The automatic focus status. This is a read-only
+	  control.</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_IDLE</constant>&nbsp;</entry>
+		  <entry>Automatic focus is not active.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_BUSY</constant>&nbsp;</entry>
+		  <entry>Automatic focusing is in progress.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_REACHED</constant>&nbsp;</entry>
+		  <entry>Focus has been reached.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_LOST</constant>&nbsp;</entry>
+		  <entry>Focus has been lost.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_FAILED</constant>&nbsp;</entry>
+		  <entry>Automatic focus has failed, the driver will not
+		  transition from this state until another action is
+		  performed by an  application.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row id="v4l2-auto-focus-range">
+	    <entry spanname="id">
+	      <constant>V4L2_CID_AUTO_FOCUS_RANGE</constant>&nbsp;</entry>
+	    <entry>enum&nbsp;v4l2_auto_focus_range</entry>
+	  </row>
+	  <row><entry spanname="descr">Determines auto focus distance range
+for which lens may be adjusted. </entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_AUTO</constant>&nbsp;</entry>
+		  <entry>The camera automatically selects the focus range.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_NORMAL</constant>&nbsp;</entry>
+		  <entry>Normal distance range, limited for best automatic focus
+performance.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_MACRO</constant>&nbsp;</entry>
+		  <entry>Macro (close-up) auto focus. The camera will
+use its minimum possible distance for auto focus.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_INFINITY</constant>&nbsp;</entry>
+		  <entry>The lens is set to focus on an object at infinite distance.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row id="v4l2-auto-focus-area">
+	    <entry spanname="id">
+	      <constant>V4L2_CID_AUTO_FOCUS_AREA</constant>&nbsp;</entry>
+	    <entry>enum&nbsp;v4l2_auto_focus_area</entry>
+	  </row>
+	  <row><entry spanname="descr">Determines the area of the frame that
+the camera uses for automatic focus. The corresponding coordinates of the
+focusing spot or rectangle can be specified and queried using the selection API.
+To change the auto focus region of interest applications first select required
+mode of this control and then set the rectangle or spot coordinates by means
+of the &VIDIOC-SUBDEV-S-SELECTION; or &VIDIOC-S-SELECTION; ioctl. In order to
+trigger again a one shot auto focus with same coordinates applications should
+use the <constant>V4L2_CID_AUTO_FOCUS_START </constant> control. Or alternatively
+invoke a &VIDIOC-SUBDEV-S-SELECTION; or a &VIDIOC-S-SELECTION; ioctl again.
+In the latter case the new pixel coordinates are applied to hardware only when
+the focus area control was set to <constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant>
+or <constant>V4L2_AUTO_FOCUS_AREA_RECTANGLE</constant>.</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_AREA_ALL</constant>&nbsp;</entry>
+		  <entry>Normal auto focus, the focusing area extends over the
+entire frame.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant>&nbsp;</entry>
+		  <entry>Automatic focus on a spot within the frame at position
+specified by the <constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> or
+<constant>V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> selection. When these
+selections are not supported by driver the default spot's position is center of
+the frame.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_AREA_RECTANGLE</constant>&nbsp;</entry>
+		  <entry>The auto focus area is determined by the <constant>
+V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> or <constant>
+V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> selection rectangle.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_AUTO_FOCUS_AREA_FACE_DETECTION</constant>&nbsp;</entry>
+		  <entry>The camera automatically focuses on a detected face
+area.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row><entry spanname="descr">
+	    This is an <link linkend="experimental">experimental</link>
+control and may change in the future.</entry>
+	  </row>
+	  <row><entry></entry></row>
+
+	  <row>
 	    <entry spanname="id"><constant>V4L2_CID_ZOOM_ABSOLUTE</constant>&nbsp;</entry>
 	    <entry>integer</entry>
 	  </row><row><entry spanname="descr">Specify the objective lens
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index 63242e2..e24ac68 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -140,11 +140,18 @@ applications. -->

       <revision>
 	<revnumber>3.5</revnumber>
-	<date>2012-04-02</date>
+	<date>2012-05-07</date>
 	<authorinitials>sa, sn</authorinitials>
 	<revremark>Added V4L2_CTRL_TYPE_INTEGER_MENU and V4L2 subdev
 	    selections API. Improved the description of V4L2_CID_COLORFX
 	    control, added V4L2_CID_COLORFX_CBCR control.
+	    Added camera controls V4L2_CID_AUTO_EXPOSURE_BIAS,
+	    V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, V4L2_CID_IMAGE_STABILIZATION,
+	    V4L2_CID_ISO_SENSITIVITY, V4L2_CID_ISO_SENSITIVITY_AUTO,
+	    V4L2_CID_EXPOSURE_METERING, V4L2_CID_SCENE_MODE,
+	    V4L2_CID_3A_LOCK, V4L2_CID_AUTO_FOCUS_START,
+	    V4L2_CID_AUTO_FOCUS_STOP, V4L2_CID_AUTO_FOCUS_STATUS,
+	    V4L2_CID_AUTO_FOCUS_RANGE and V4L2_CID_AUTO_FOCUS_AREA.
 	</revremark>
       </revision>

diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 8f14aba..d306dae 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -236,6 +236,20 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		"Spot",
 		NULL
 	};
+	static const char * const camera_auto_focus_area[] = {
+		"All",
+		"Spot",
+		"Rectangle",
+		"Face Detection",
+		NULL
+	};
+	static const char * const camera_auto_focus_range[] = {
+		"Auto",
+		"Normal",
+		"Macro",
+		"Infinity",
+		NULL
+	};
 	static const char * const colorfx[] = {
 		"None",
 		"Black & White",
@@ -459,6 +473,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		return camera_exposure_auto;
 	case V4L2_CID_EXPOSURE_METERING:
 		return camera_exposure_metering;
+	case V4L2_CID_AUTO_FOCUS_AREA:
+		return camera_auto_focus_area;
+	case V4L2_CID_AUTO_FOCUS_RANGE:
+		return camera_auto_focus_range;
 	case V4L2_CID_COLORFX:
 		return colorfx;
 	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
@@ -646,7 +664,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_TILT_ABSOLUTE:		return "Tilt, Absolute";
 	case V4L2_CID_FOCUS_ABSOLUTE:		return "Focus, Absolute";
 	case V4L2_CID_FOCUS_RELATIVE:		return "Focus, Relative";
-	case V4L2_CID_FOCUS_AUTO:		return "Focus, Automatic";
+	case V4L2_CID_FOCUS_AUTO:		return "Focus, Automatic Continuous";
 	case V4L2_CID_ZOOM_ABSOLUTE:		return "Zoom, Absolute";
 	case V4L2_CID_ZOOM_RELATIVE:		return "Zoom, Relative";
 	case V4L2_CID_ZOOM_CONTINUOUS:		return "Zoom, Continuous";
@@ -662,6 +680,11 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_EXPOSURE_METERING:	return "Exposure, Metering Mode";
 	case V4L2_CID_SCENE_MODE:		return "Scene Mode";
 	case V4L2_CID_3A_LOCK:			return "3A Lock";
+	case V4L2_CID_AUTO_FOCUS_START:		return "Auto Focus, Start";
+	case V4L2_CID_AUTO_FOCUS_STOP:		return "Auto Focus, Stop";
+	case V4L2_CID_AUTO_FOCUS_STATUS:	return "Auto Focus, Status";
+	case V4L2_CID_AUTO_FOCUS_RANGE:		return "Auto Focus, Range";
+	case V4L2_CID_AUTO_FOCUS_AREA:		return "Auto Focus, Area";

 	/* FM Radio Modulator control */
 	/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -763,6 +786,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_TILT_RESET:
 	case V4L2_CID_FLASH_STROBE:
 	case V4L2_CID_FLASH_STROBE_STOP:
+	case V4L2_CID_AUTO_FOCUS_START:
+	case V4L2_CID_AUTO_FOCUS_STOP:
 		*type = V4L2_CTRL_TYPE_BUTTON;
 		*flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
 		*min = *max = *step = *def = 0;
@@ -786,6 +811,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_MPEG_STREAM_TYPE:
 	case V4L2_CID_MPEG_STREAM_VBI_FMT:
 	case V4L2_CID_EXPOSURE_AUTO:
+	case V4L2_CID_AUTO_FOCUS_AREA:
+	case V4L2_CID_AUTO_FOCUS_RANGE:
 	case V4L2_CID_COLORFX:
 	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
 	case V4L2_CID_TUNE_PREEMPHASIS:
@@ -835,6 +862,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_FLASH_FAULT:
 	case V4L2_CID_JPEG_ACTIVE_MARKER:
 	case V4L2_CID_3A_LOCK:
+	case V4L2_CID_AUTO_FOCUS_STATUS:
 		*type = V4L2_CTRL_TYPE_BITMASK;
 		break;
 	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
@@ -893,6 +921,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 		*flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
 		break;
 	case V4L2_CID_FLASH_STROBE_STATUS:
+	case V4L2_CID_AUTO_FOCUS_STATUS:
 	case V4L2_CID_FLASH_READY:
 		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
 		break;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 793345d..dcc5243 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1768,6 +1768,31 @@ enum v4l2_scene_mode {
 #define V4L2_LOCK_WHITE_BALANCE			(1 << 1)
 #define V4L2_LOCK_FOCUS				(1 << 2)

+#define V4L2_CID_AUTO_FOCUS_START		(V4L2_CID_CAMERA_CLASS_BASE+28)
+#define V4L2_CID_AUTO_FOCUS_STOP		(V4L2_CID_CAMERA_CLASS_BASE+29)
+#define V4L2_CID_AUTO_FOCUS_STATUS		(V4L2_CID_CAMERA_CLASS_BASE+30)
+#define V4L2_AUTO_FOCUS_STATUS_IDLE		(0 << 0)
+#define V4L2_AUTO_FOCUS_STATUS_BUSY		(1 << 0)
+#define V4L2_AUTO_FOCUS_STATUS_REACHED		(1 << 1)
+#define V4L2_AUTO_FOCUS_STATUS_LOST		(1 << 2)
+#define V4L2_AUTO_FOCUS_STATUS_FAILED		(1 << 3)
+
+#define V4L2_CID_AUTO_FOCUS_RANGE		(V4L2_CID_CAMERA_CLASS_BASE+31)
+enum v4l2_auto_focus_range {
+	V4L2_AUTO_FOCUS_RANGE_AUTO		= 0,
+	V4L2_AUTO_FOCUS_RANGE_NORMAL		= 1,
+	V4L2_AUTO_FOCUS_RANGE_MACRO		= 2,
+	V4L2_AUTO_FOCUS_RANGE_INFINITY		= 3,
+};
+
+#define V4L2_CID_AUTO_FOCUS_AREA		(V4L2_CID_CAMERA_CLASS_BASE+32)
+enum v4l2_auto_focus_area {
+	V4L2_AUTO_FOCUS_AREA_ALL		= 0,
+	V4L2_AUTO_FOCUS_AREA_SPOT		= 1,
+	V4L2_AUTO_FOCUS_AREA_RECTANGLE		= 2,
+	V4L2_AUTO_FOCUS_AREA_FACE_DETECTION	= 3,
+};
+
 /* FM Modulator class control IDs */
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)
 #define V4L2_CID_FM_TX_CLASS			(V4L2_CTRL_CLASS_FM_TX | 1)
--
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v5 01/12] V4L: Add helper function for standard integer menu controls
  2012-05-06 18:51     ` [PATCH v5 " Sylwester Nawrocki
@ 2012-05-07 15:05       ` Sakari Ailus
  0 siblings, 0 replies; 25+ messages in thread
From: Sakari Ailus @ 2012-05-07 15:05 UTC (permalink / raw)
  To: Sylwester Nawrocki; +Cc: linux-media, Sylwester Nawrocki, Kyungmin Park

Hi Sylwester,

On Sun, May 06, 2012 at 08:51:03PM +0200, Sylwester Nawrocki wrote:
> This patch adds v4l2_ctrl_new_int_menu() helper function which can be used
> in drivers for creating standard integer menu control with driver-specific
> menu item list. It is similar to v4l2_ctrl_new_std_menu(), except it doesn't
> have a mask parameter and an additional qmenu parameter allows passing
> an array of signed 64-bit integers as the menu item list.
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>

Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
Tested-by: Sakari Ailus <sakari.ailus@iki.fi>

-- 
Sakari Ailus
e-mail: sakari.ailus@iki.fi	jabber/XMPP/Gmail: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH/RFC v4 10/12] V4L: Add auto focus targets to the selections API
  2012-05-06 18:22   ` Sakari Ailus
@ 2012-05-08 10:46     ` Sylwester Nawrocki
  2012-05-13  0:06       ` Sakari Ailus
  0 siblings, 1 reply; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-08 10:46 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, laurent.pinchart, g.liakhovetski, hdegoede, moinejf,
	hverkuil, m.szyprowski, riverful.kim, sw0312.kim, Kyungmin Park

Hi Sakari!

On 05/06/2012 08:22 PM, Sakari Ailus wrote:
> Hi Sylwester,
> 
> Thanks for the patch.
> 
> Sylwester Nawrocki wrote:
>> The camera automatic focus algorithms may require setting up
>> a spot or rectangle coordinates or multiple such parameters.
>>
>> The automatic focus selection targets are introduced in order
>> to allow applications to query and set such coordinates. Those
>> selections are intended to be used together with the automatic
>> focus controls available in the camera control class.
> 
> Have you thought about multiple autofocus windows, and how could they be
> implemented on top of this patch?
> 
> I'm not saying that we should implement them now, but at least we should
> think how we _would_ implement them when needed. They aren't that exotic
> functionality these days after all.
> 
> I'd guess this would involve an additional bitmask control and defining
> a set of new targets. A comment in the source might help here ---
> perhaps a good rule is to start new ranges at 0x1000 as you're doing
> already.

There was also an idea to convert part of the reserved[] field to a window
index IIRC. Not sure which approach is better. I didn't want to make any
assumptions about features I don't have exact knowledge about, neither that
I currently need. The large offset in the auto focus target is to better
indicate they are really different than current selection targets we have,
I also had in mind reserving a target pool for AF targets as you are
pointing out.
That said I'm not really sure right now what additional exact comments
would need to be added.
Hopefully there isn't anything blocking further expansion in this patches.

I didn't decided yet if I want to send this selection/auto focus patches
out for v3.5. I'm also considering dropping just the V4L2_AUTO_FOCUS_AREA
control from "12/12 V4L: Add camera auto focus controls" patch this time.

The bitmask control for multiple windows selection makes a lot of sense
to me. I suppose it would be better to use an additional 'index' field
in the selection data structures for AF window selection.

>> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>> ---
>>  Documentation/DocBook/media/v4l/selection-api.xml  |   33 +++++++++++++++++++-
>>  .../DocBook/media/v4l/vidioc-g-selection.xml       |   11 +++++++
>>  include/linux/videodev2.h                          |    5 +++
>>  3 files changed, 48 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml
>> index b299e47..490d29a 100644
>> --- a/Documentation/DocBook/media/v4l/selection-api.xml
>> +++ b/Documentation/DocBook/media/v4l/selection-api.xml
>> @@ -1,6 +1,6 @@
>>  <section id="selection-api">
>>  
>> -  <title>Experimental API for cropping, composing and scaling</title>
>> +  <title>Experimental selections API</title>
>>  
>>        <note>
>>  	<title>Experimental</title>
>> @@ -9,6 +9,10 @@
>>  interface and may change in the future.</para>
>>        </note>
>>  
>> + <section>
>> +
>> + <title>Image cropping, composing and scaling</title>
>> +
>>    <section>
>>      <title>Introduction</title>
>>  
>> @@ -321,5 +325,32 @@ V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> for other devices</para>
>>        </example>
>>  
>>     </section>
>> + </section>
>> +
>> +   <section>
>> +     <title>Automatic focus regions of interest</title>
>> +
>> +<para> The camera automatic focus algorithms may require configuration of
>> +regions of interest in form of rectangle or spot coordinates. The automatic
>> +focus selection targets allow applications to query and set such coordinates.
>> +Those selections are intended to be used together with the
>> +<constant>V4L2_CID_AUTO_FOCUS_AREA</constant> <link linkend="camera-controls">
>> +camera class</link> control. The <constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL
>> +</constant> target is used for querying or setting actual spot or rectangle
>> +coordinates, while <constant>V4L2_SEL_TGT_AUTO_FOCUS_BOUNDS</constant> target
>> +determines bounds for a single spot or rectangle.
>> +These selections are only effective when the <constant>V4L2_CID_AUTO_FOCUS_AREA
>> +</constant>control is set to <constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant> or
>> +<constant>V4L2_AUTO_FOCUS_AREA_RECTANGLE</constant>. The new coordinates shall
>> +be accepted and applied to hardware when the focus area control value is
>> +changed and also during a &VIDIOC-S-SELECTION; ioctl call, only when the focus
>> +area control is already set to required value.</para>
>> +
>> +<para> For the <constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant> case, the selection
>> +rectangle <structfield> width</structfield> and <structfield>height</structfield>
>> +are not used, i.e. shall be set to 0 by applications and ignored by drivers for
>> +the &VIDIOC-S-SELECTION; ioctl and shall be ignored by applications for the
>> +&VIDIOC-G-SELECTION; ioctl.</para>
>> +   </section>
>>  
>>  </section>
>> diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
>> index bb04eff..87df4da 100644
>> --- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
>> +++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
>> @@ -195,6 +195,17 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
>>              <entry>0x0103</entry>
>>              <entry>The active area and all padding pixels that are inserted or modified by hardware.</entry>
>>  	  </row>
>> +	  <row>
>> +            <entry><constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant></entry>
>> +            <entry>0x1000</entry>
>> +	    <entry>Actual automatic focus rectangle or spot coordinates.</entry>
>> +	  </row>
>> +	  <row>
>> +            <entry><constant>V4L2_SEL_TGT_AUTO_FOCUS_BOUNDS</constant></entry>
>> +            <entry>0x1002</entry>
> 
> This should be 0x1001, I believe.

Yeah, thanks for spotting it, I'll fix this.

--

Regards,
Sylwester

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH/RFC v4 12/12] V4L: Add camera auto focus controls
  2012-05-06 18:46   ` Sakari Ailus
@ 2012-05-09 10:11     ` Sylwester Nawrocki
  2012-05-09 17:39       ` Sylwester Nawrocki
  0 siblings, 1 reply; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-09 10:11 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, laurent.pinchart, g.liakhovetski, hdegoede, moinejf,
	hverkuil, m.szyprowski, riverful.kim, sw0312.kim, Kyungmin Park

Hi Sakari,

thank you for the comments.

On 05/06/2012 08:46 PM, Sakari Ailus wrote:
> Hi Sylwester,
> 
> Thanks for the patch,
> 
> Sylwester Nawrocki wrote:
>> Add following auto focus controls:
>>
>>  - V4L2_CID_AUTO_FOCUS_START - single-shot auto focus start
>>  - V4L2_CID_AUTO_FOCUS_STOP -  single-shot auto focus stop
>>  - V4L2_CID_AUTO_FOCUS_STATUS - automatic focus status
>>  - V4L2_CID_AUTO_FOCUS_AREA - automatic focus area selection
>>  - V4L2_CID_AUTO_FOCUS_DISTANCE - automatic focus scan range selection
>>
>> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>> ---
>>  Documentation/DocBook/media/v4l/controls.xml |  147 +++++++++++++++++++++++++-
>>  drivers/media/video/v4l2-ctrls.c             |   31 +++++-
>>  include/linux/videodev2.h                    |   25 +++++
>>  3 files changed, 200 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
>> index 4a463d3..d8ef71e 100644
>> --- a/Documentation/DocBook/media/v4l/controls.xml
>> +++ b/Documentation/DocBook/media/v4l/controls.xml
>> @@ -2902,13 +2902,156 @@ negative values towards infinity. This is a write-only control.</entry>
>>  	  <row>
>>  	    <entry spanname="id"><constant>V4L2_CID_FOCUS_AUTO</constant>&nbsp;</entry>
>>  	    <entry>boolean</entry>
>> -	  </row><row><entry spanname="descr">Enables automatic focus
>> -adjustments. The effect of manual focus adjustments while this feature
>> +	  </row><row><entry spanname="descr">Enables continuous automatic
>> +focus adjustments. The effect of manual focus adjustments while this feature
>>  is enabled is undefined, drivers should ignore such requests.</entry>
>>  	  </row>
>>  	  <row><entry></entry></row>
>>  
>>  	  <row>
>> +	    <entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_START</constant>&nbsp;</entry>
>> +	    <entry>button</entry>
>> +	  </row><row><entry spanname="descr">Starts single auto focus process.
>> +The effect of setting this control when <constant>V4L2_CID_FOCUS_AUTO</constant>
>> +is set to <constant>TRUE</constant> (1) is undefined, drivers should ignore
>> +such requests.</entry>
>> +	  </row>
>> +	  <row><entry></entry></row>
>> +
>> +	  <row>
>> +	    <entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_STOP</constant>&nbsp;</entry>
>> +	    <entry>button</entry>
>> +	  </row><row><entry spanname="descr">Aborts automatic focusing
>> +started with <constant>V4L2_CID_AUTO_FOCUS_START</constant> control. It is
>> +effective only when the continuous autofocus is disabled, that is when
>> +<constant>V4L2_CID_FOCUS_AUTO</constant> control is set to <constant>FALSE
>> +</constant> (0).</entry>
>> +	  </row>
>> +	  <row><entry></entry></row>
>> +
>> +	  <row id="v4l2-auto-focus-status">
>> +	    <entry spanname="id">
>> +	      <constant>V4L2_CID_AUTO_FOCUS_STATUS</constant>&nbsp;</entry>
>> +	    <entry>bitmask</entry>
>> +	  </row>
>> +	  <row><entry spanname="descr">The automatic focus status. This is a read-only
>> +	  control.</entry>
>> +	  </row>
>> +	  <row>
>> +	    <entrytbl spanname="descr" cols="2">
>> +	      <tbody valign="top">
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_IDLE</constant>&nbsp;</entry>
>> +		  <entry>Automatic focus is not active.</entry>
>> +		</row>
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_BUSY</constant>&nbsp;</entry>
>> +		  <entry>Automatic focusing is in progress.</entry>
>> +		</row>
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_REACHED</constant>&nbsp;</entry>
>> +		  <entry>Focus has been reached.</entry>
>> +		</row>
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_LOST</constant>&nbsp;</entry>
>> +		  <entry>Focus has been lost.</entry>
> 
> When does this happen?

Hmm, good question. I intended this one for continuous auto focus, for the moments
when the focus  is lost. I felt the control is incomplete without such status bit.

Thinking about it a bit more, it is just a negation of V4L2_AUTO_FOCUS_STATUS_FOCUSED.
The focus lost notifications could be well provided to user space be clearing this bit.

So I would just get rid of V4L2_AUTO_FOCUS_STATUS_LOST, I don't really use it in any 
driver, it was supposed to be just for completeness. 

What do you think ? 

>> +		</row>
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_STATUS_FAILED</constant>&nbsp;</entry>
>> +		  <entry>Automatic focus has failed, the driver will not
>> +		  transition from this state until another action is
>> +		  performed by an  application.</entry>
> 
> Which of these are valid for regular autofocus and which ones for
> continuous autofocus? I'm a little bit confused with the above descriptions.

All, except V4L2_AUTO_FOCUS_STATUS_LOST are valid for both auto focus modes.
But I'm going to remove V4L2_AUTO_FOCUS_STATUS_LOST bit, as indicated above.

> I might as well say that temporary conditions such as failed and reached
> would return to idle after being read from user space. This is how the
> flash faults behave, too.

I'm not sure if it would be possible to fulfil such assumption in drivers
in all cases. The status often comes from hardware and the driver might
not be able to change it at will. I'm not sure if it is safe to change 
state just by reading it from user-space. This probably wouldn't work well
with multiple processes accessing the camera. 

For instance, from state V4L2_AUTO_FOCUS_STATUS_FAILED a driver would have 
transitioned to something else after user-space sets V4L2_CID_AUTO_FOCUS_START
control. Also I would prefer having V4L2_AUTO_FOCUS_STATUS_REACHED bit set
as long as the camera stays in this state, regardless of how many status 
readers there are. 

> 
> How does this interact with the 3A lock control?

Setting V4L2_LOCK_FOCUS lock would just stop updates to the status control
value. The 3A lock control is just another one that influences the auto 
focus status, among V4L2_CID_AUTO_FOCUS_START and V4L2_CID_AUTO_FOCUS_STOP.

Nevertheless, I see your point, that it's not clear from the Spec.
How about adding something like this to the AF status control description:

"Setting V4L2_LOCK_FOCUS lock may stop updates of the V4L2_CID_AUTO_FOCUS_STOP
control value."

?

I'm not sure how much detailed the documentation should be, I wouldn't like
to add something that would be hard to implement in drivers, for sake of
the applications' simplicity... :)

>> +		</row>
>> +	      </tbody>
>> +	    </entrytbl>
>> +	  </row>
>> +	  <row><entry></entry></row>
>> +
>> +	  <row id="v4l2-auto-focus-range">
>> +	    <entry spanname="id">
>> +	      <constant>V4L2_CID_AUTO_FOCUS_RANGE</constant>&nbsp;</entry>
>> +	    <entry>enum&nbsp;v4l2_auto_focus_range</entry>
>> +	  </row>
>> +	  <row><entry spanname="descr">Determines auto focus distance range
>> +for which lens may be adjusted. </entry>
>> +	  </row>
>> +	  <row>
>> +	    <entrytbl spanname="descr" cols="2">
>> +	      <tbody valign="top">
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_AUTO</constant>&nbsp;</entry>
>> +		  <entry>The camera automatically selects the focus range.</entry>
>> +		</row>
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_NORMAL</constant>&nbsp;</entry>
>> +		  <entry>The auto focus normal distance range. It is limited
>> +for best auto focus algorithm performance.</entry>
>> +		</row>
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_MACRO</constant>&nbsp;</entry>
>> +		  <entry>Macro (close-up) auto focus. The camera will
>> +use minimum possible distance that it is capable of for auto focus.</entry>
>> +		</row>
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_RANGE_INFINITY</constant>&nbsp;</entry>
>> +		  <entry>The focus at an object at infinite distance.</entry>
>> +		</row>
>> +	      </tbody>
>> +	    </entrytbl>
>> +	  </row>
>> +	  <row><entry></entry></row>
>> +
>> +	  <row id="v4l2-auto-focus-area">
>> +	    <entry spanname="id">
>> +	      <constant>V4L2_CID_AUTO_FOCUS_AREA</constant>&nbsp;</entry>
>> +	    <entry>enum&nbsp;v4l2_auto_focus_area</entry>
>> +	  </row>
>> +	  <row><entry spanname="descr">Determines the area of the frame that
>> +the camera uses for automatic focus. The corresponding coordinates of the
>> +focusing spot or rectangle can be specified and queried using the selection API.
>> +To change the auto focus region of interest applications first select required
>> +mode of this control and then set the rectangle or spot coordinates by means
>> +of the &VIDIOC-SUBDEV-S-SELECTION; or &VIDIOC-S-SELECTION; ioctl. In order to
>> +trigger again an auto focus process with same coordinates applications should
>> +use the <constant>V4L2_CID_AUTO_FOCUS_START </constant> control. Or alternatively
>> +invoke a &VIDIOC-SUBDEV-S-SELECTION; or a &VIDIOC-S-SELECTION; ioctl again.
>> +In the latter case the new pixel coordinates are applied to hardware only when
>> +the focus area control is set to a value other than
>> +<constant>V4L2_AUTO_FOCUS_AREA_ALL</constant>.</entry>
>> +	  </row>
>> +	  <row>
>> +	    <entrytbl spanname="descr" cols="2">
>> +	      <tbody valign="top">
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_AREA_ALL</constant>&nbsp;</entry>
>> +		  <entry>Normal auto focus, the focusing area extends over the
>> +entire frame.</entry>
>> +		</row>
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant>&nbsp;</entry>
>> +		  <entry>Automatic focus on a spot within the frame at position
>> +specified by the <constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> or
>> +<constant>V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> selection. When these
>> +selections are not supported by driver the default spot's position is center of
>> +the frame.</entry>
>> +		</row>
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_AREA_RECTANGLE</constant>&nbsp;</entry>
>> +		  <entry>The auto focus area is determined by the <constant>
>> +V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> or <constant>
>> +V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant> selection rectangle.</entry>
>> +		</row>
>> +		<row>
>> +		  <entry><constant>V4L2_AUTO_FOCUS_AREA_FACE_DETECTION</constant>&nbsp;</entry>
>> +		  <entry>The camera automatically focuses on a detected face
>> +area.</entry>
> 
> I assume there could be one or more faces to focus to, right?

Indeed, I presume we're going to need another set of controls for Face Detection 
features.
 
That's true, there can be more faces. I wasn't good enough at expressing this
here :(

Maybe something like:

"The camera automatically focuses on the face detection regions."

would be better ?


-- 
Regards,
Sylwester Nawrocki

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH/RFC v4 12/12] V4L: Add camera auto focus controls
  2012-05-09 10:11     ` Sylwester Nawrocki
@ 2012-05-09 17:39       ` Sylwester Nawrocki
  0 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2012-05-09 17:39 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: Sakari Ailus, linux-media, laurent.pinchart, g.liakhovetski,
	hdegoede, moinejf, hverkuil, m.szyprowski, riverful.kim,
	sw0312.kim, Kyungmin Park

On 05/09/2012 12:11 PM, Sylwester Nawrocki wrote:
> On 05/06/2012 08:46 PM, Sakari Ailus wrote:
>> Sylwester Nawrocki wrote:
>>> Add following auto focus controls:
>>>
>>>   - V4L2_CID_AUTO_FOCUS_START - single-shot auto focus start
>>>   - V4L2_CID_AUTO_FOCUS_STOP -  single-shot auto focus stop
>>>   - V4L2_CID_AUTO_FOCUS_STATUS - automatic focus status
>>>   - V4L2_CID_AUTO_FOCUS_AREA - automatic focus area selection
>>>   - V4L2_CID_AUTO_FOCUS_DISTANCE - automatic focus scan range selection
>>>
>>> Signed-off-by: Sylwester Nawrocki<s.nawrocki@samsung.com>
>>> Signed-off-by: Kyungmin Park<kyungmin.park@samsung.com>
>>> ---
>>>   Documentation/DocBook/media/v4l/controls.xml |  147 +++++++++++++++++++++++++-
>>>   drivers/media/video/v4l2-ctrls.c             |   31 +++++-
>>>   include/linux/videodev2.h                    |   25 +++++
>>>   3 files changed, 200 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
>>> index 4a463d3..d8ef71e 100644
>>> --- a/Documentation/DocBook/media/v4l/controls.xml
>>> +++ b/Documentation/DocBook/media/v4l/controls.xml
>>> @@ -2902,13 +2902,156 @@ negative values towards infinity. This is a write-only control.</entry>
>>>   	<row>
>>>   	<entry spanname="id"><constant>V4L2_CID_FOCUS_AUTO</constant>&nbsp;</entry>
>>>   	<entry>boolean</entry>
>>> -	</row><row><entry spanname="descr">Enables automatic focus
>>> -adjustments. The effect of manual focus adjustments while this feature
>>> +	</row><row><entry spanname="descr">Enables continuous automatic
>>> +focus adjustments. The effect of manual focus adjustments while this feature
>>>   is enabled is undefined, drivers should ignore such requests.</entry>
>>>   	</row>
>>>   	<row><entry></entry></row>
>>>
>>>   	<row>
>>> +	<entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_START</constant>&nbsp;</entry>
>>> +	<entry>button</entry>
>>> +	</row><row><entry spanname="descr">Starts single auto focus process.
>>> +The effect of setting this control when<constant>V4L2_CID_FOCUS_AUTO</constant>
>>> +is set to<constant>TRUE</constant>  (1) is undefined, drivers should ignore
>>> +such requests.</entry>
>>> +	</row>
>>> +	<row><entry></entry></row>
>>> +
>>> +	<row>
>>> +	<entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_STOP</constant>&nbsp;</entry>
>>> +	<entry>button</entry>
>>> +	</row><row><entry spanname="descr">Aborts automatic focusing
>>> +started with<constant>V4L2_CID_AUTO_FOCUS_START</constant>  control. It is
>>> +effective only when the continuous autofocus is disabled, that is when
>>> +<constant>V4L2_CID_FOCUS_AUTO</constant>  control is set to<constant>FALSE
>>> +</constant>  (0).</entry>
>>> +	</row>
>>> +	<row><entry></entry></row>
>>> +
>>> +	<row id="v4l2-auto-focus-status">
>>> +	<entry spanname="id">
>>> +	<constant>V4L2_CID_AUTO_FOCUS_STATUS</constant>&nbsp;</entry>
>>> +	<entry>bitmask</entry>
>>> +	</row>
>>> +	<row><entry spanname="descr">The automatic focus status. This is a read-only
>>> +	  control.</entry>
>>> +	</row>
>>> +	<row>
>>> +	<entrytbl spanname="descr" cols="2">
>>> +	<tbody valign="top">
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_STATUS_IDLE</constant>&nbsp;</entry>
>>> +		<entry>Automatic focus is not active.</entry>
>>> +		</row>
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_STATUS_BUSY</constant>&nbsp;</entry>
>>> +		<entry>Automatic focusing is in progress.</entry>
>>> +		</row>
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_STATUS_REACHED</constant>&nbsp;</entry>
>>> +		<entry>Focus has been reached.</entry>
>>> +		</row>
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_STATUS_LOST</constant>&nbsp;</entry>
>>> +		<entry>Focus has been lost.</entry>
>>
>> When does this happen?
> 
> Hmm, good question. I intended this one for continuous auto focus, for the moments
> when the focus  is lost. I felt the control is incomplete without such status bit.
> 
> Thinking about it a bit more, it is just a negation of V4L2_AUTO_FOCUS_STATUS_FOCUSED.
                                                                               ^^^^^^^^^                        
Sorry, that should be V4L2_AUTO_FOCUS_STATUS_REACHED. 

> The focus lost notifications could be well provided to user space be clearing this bit.
> 
> So I would just get rid of V4L2_AUTO_FOCUS_STATUS_LOST, I don't really use it in any
> driver, it was supposed to be just for completeness.
> 
> What do you think ?
> 
>>> +		</row>
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_STATUS_FAILED</constant>&nbsp;</entry>
>>> +		<entry>Automatic focus has failed, the driver will not
>>> +		  transition from this state until another action is
>>> +		  performed by an  application.</entry>
>>
>> Which of these are valid for regular autofocus and which ones for
>> continuous autofocus? I'm a little bit confused with the above descriptions.
> 
> All, except V4L2_AUTO_FOCUS_STATUS_LOST are valid for both auto focus modes.
> But I'm going to remove V4L2_AUTO_FOCUS_STATUS_LOST bit, as indicated above.
> 
>> I might as well say that temporary conditions such as failed and reached
>> would return to idle after being read from user space. This is how the
>> flash faults behave, too.
> 
> I'm not sure if it would be possible to fulfil such assumption in drivers
> in all cases. The status often comes from hardware and the driver might
> not be able to change it at will. I'm not sure if it is safe to change
> state just by reading it from user-space. This probably wouldn't work well
> with multiple processes accessing the camera.
> 
> For instance, from state V4L2_AUTO_FOCUS_STATUS_FAILED a driver would have
> transitioned to something else after user-space sets V4L2_CID_AUTO_FOCUS_START
> control. Also I would prefer having V4L2_AUTO_FOCUS_STATUS_REACHED bit set
> as long as the camera stays in this state, regardless of how many status
> readers there are.
> 
>>
>> How does this interact with the 3A lock control?
> 
> Setting V4L2_LOCK_FOCUS lock would just stop updates to the status control
> value. The 3A lock control is just another one that influences the auto
> focus status, among V4L2_CID_AUTO_FOCUS_START and V4L2_CID_AUTO_FOCUS_STOP.
> 
> Nevertheless, I see your point, that it's not clear from the Spec.
> How about adding something like this to the AF status control description:
> 
> "Setting V4L2_LOCK_FOCUS lock may stop updates of the V4L2_CID_AUTO_FOCUS_STOP
                                                                           ^^^^^
And this - V4L2_CID_AUTO_FOCUS_STATUS. I guess I need more sleeping, and not on
the computer keyboard... :-)

The updated patch series is also available here:
http://git.infradead.org/users/kmpark/linux-samsung/shortlog/refs/heads/v4l-camera-controls

> control value."
> 
> ?
> 
> I'm not sure how much detailed the documentation should be, I wouldn't like
> to add something that would be hard to implement in drivers, for sake of
> the applications' simplicity... :)
> 
>>> +		</row>
>>> +	</tbody>
>>> +	</entrytbl>
>>> +	</row>
>>> +	<row><entry></entry></row>
>>> +
>>> +	<row id="v4l2-auto-focus-range">
>>> +	<entry spanname="id">
>>> +	<constant>V4L2_CID_AUTO_FOCUS_RANGE</constant>&nbsp;</entry>
>>> +	<entry>enum&nbsp;v4l2_auto_focus_range</entry>
>>> +	</row>
>>> +	<row><entry spanname="descr">Determines auto focus distance range
>>> +for which lens may be adjusted.</entry>
>>> +	</row>
>>> +	<row>
>>> +	<entrytbl spanname="descr" cols="2">
>>> +	<tbody valign="top">
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_RANGE_AUTO</constant>&nbsp;</entry>
>>> +		<entry>The camera automatically selects the focus range.</entry>
>>> +		</row>
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_RANGE_NORMAL</constant>&nbsp;</entry>
>>> +		<entry>The auto focus normal distance range. It is limited
>>> +for best auto focus algorithm performance.</entry>
>>> +		</row>
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_RANGE_MACRO</constant>&nbsp;</entry>
>>> +		<entry>Macro (close-up) auto focus. The camera will
>>> +use minimum possible distance that it is capable of for auto focus.</entry>
>>> +		</row>
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_RANGE_INFINITY</constant>&nbsp;</entry>
>>> +		<entry>The focus at an object at infinite distance.</entry>
>>> +		</row>
>>> +	</tbody>
>>> +	</entrytbl>
>>> +	</row>
>>> +	<row><entry></entry></row>
>>> +
>>> +	<row id="v4l2-auto-focus-area">
>>> +	<entry spanname="id">
>>> +	<constant>V4L2_CID_AUTO_FOCUS_AREA</constant>&nbsp;</entry>
>>> +	<entry>enum&nbsp;v4l2_auto_focus_area</entry>
>>> +	</row>
>>> +	<row><entry spanname="descr">Determines the area of the frame that
>>> +the camera uses for automatic focus. The corresponding coordinates of the
>>> +focusing spot or rectangle can be specified and queried using the selection API.
>>> +To change the auto focus region of interest applications first select required
>>> +mode of this control and then set the rectangle or spot coordinates by means
>>> +of the&VIDIOC-SUBDEV-S-SELECTION; or&VIDIOC-S-SELECTION; ioctl. In order to
>>> +trigger again an auto focus process with same coordinates applications should
>>> +use the<constant>V4L2_CID_AUTO_FOCUS_START</constant>  control. Or alternatively
>>> +invoke a&VIDIOC-SUBDEV-S-SELECTION; or a&VIDIOC-S-SELECTION; ioctl again.
>>> +In the latter case the new pixel coordinates are applied to hardware only when
>>> +the focus area control is set to a value other than
>>> +<constant>V4L2_AUTO_FOCUS_AREA_ALL</constant>.</entry>
>>> +	</row>
>>> +	<row>
>>> +	<entrytbl spanname="descr" cols="2">
>>> +	<tbody valign="top">
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_AREA_ALL</constant>&nbsp;</entry>
>>> +		<entry>Normal auto focus, the focusing area extends over the
>>> +entire frame.</entry>
>>> +		</row>
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_AREA_SPOT</constant>&nbsp;</entry>
>>> +		<entry>Automatic focus on a spot within the frame at position
>>> +specified by the<constant>V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant>  or
>>> +<constant>V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant>  selection. When these
>>> +selections are not supported by driver the default spot's position is center of
>>> +the frame.</entry>
>>> +		</row>
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_AREA_RECTANGLE</constant>&nbsp;</entry>
>>> +		<entry>The auto focus area is determined by the<constant>
>>> +V4L2_SEL_TGT_AUTO_FOCUS_ACTUAL</constant>  or<constant>
>>> +V4L2_SUBDEV_SEL_TGT_AUTO_FOCUS_ACTUAL</constant>  selection rectangle.</entry>
>>> +		</row>
>>> +		<row>
>>> +		<entry><constant>V4L2_AUTO_FOCUS_AREA_FACE_DETECTION</constant>&nbsp;</entry>
>>> +		<entry>The camera automatically focuses on a detected face
>>> +area.</entry>
>>
>> I assume there could be one or more faces to focus to, right?
> 
> Indeed, I presume we're going to need another set of controls for Face Detection
> features.
> 
> That's true, there can be more faces. I wasn't good enough at expressing this
> here :(
> 
> Maybe something like:
> 
> "The camera automatically focuses on the face detection regions."
> 
> would be better ?

--

Regards,
Sylwester

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH/RFC v4 10/12] V4L: Add auto focus targets to the selections API
  2012-05-08 10:46     ` Sylwester Nawrocki
@ 2012-05-13  0:06       ` Sakari Ailus
  0 siblings, 0 replies; 25+ messages in thread
From: Sakari Ailus @ 2012-05-13  0:06 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-media, laurent.pinchart, g.liakhovetski, hdegoede, moinejf,
	hverkuil, m.szyprowski, riverful.kim, sw0312.kim, Kyungmin Park

Hi Sylwester,

On Tue, May 08, 2012 at 12:46:15PM +0200, Sylwester Nawrocki wrote:
> Hi Sakari!
> 
> On 05/06/2012 08:22 PM, Sakari Ailus wrote:
> > Hi Sylwester,
> > 
> > Thanks for the patch.
> > 
> > Sylwester Nawrocki wrote:
> >> The camera automatic focus algorithms may require setting up
> >> a spot or rectangle coordinates or multiple such parameters.
> >>
> >> The automatic focus selection targets are introduced in order
> >> to allow applications to query and set such coordinates. Those
> >> selections are intended to be used together with the automatic
> >> focus controls available in the camera control class.
> > 
> > Have you thought about multiple autofocus windows, and how could they be
> > implemented on top of this patch?
> > 
> > I'm not saying that we should implement them now, but at least we should
> > think how we _would_ implement them when needed. They aren't that exotic
> > functionality these days after all.
> > 
> > I'd guess this would involve an additional bitmask control and defining
> > a set of new targets. A comment in the source might help here ---
> > perhaps a good rule is to start new ranges at 0x1000 as you're doing
> > already.
> 
> There was also an idea to convert part of the reserved[] field to a window
> index IIRC. Not sure which approach is better. I didn't want to make any
> assumptions about features I don't have exact knowledge about, neither that
> I currently need. The large offset in the auto focus target is to better
> indicate they are really different than current selection targets we have,
> I also had in mind reserving a target pool for AF targets as you are
> pointing out.
> That said I'm not really sure right now what additional exact comments
> would need to be added.

I was thinking about reserving a bunch of targets for just AF windows, but
the idea of adding a window ID is interesting. Then there's only need for a
single target which does sound a lot cleaner.

This would be a quite nice way to implement passing the face detection info
to user space, too: face detection target and object identifier. The target
field would map nicely to id in events, too.

It might make sense to implement a new IOCTL for passing multiple events but
that's fine optimisation.

> Hopefully there isn't anything blocking further expansion in this patches.
> 
> I didn't decided yet if I want to send this selection/auto focus patches
> out for v3.5. I'm also considering dropping just the V4L2_AUTO_FOCUS_AREA
> control from "12/12 V4L: Add camera auto focus controls" patch this time.
> 
> The bitmask control for multiple windows selection makes a lot of sense
> to me. I suppose it would be better to use an additional 'index' field
> in the selection data structures for AF window selection.

I agree.

I'd like to get a conclusion to whether or not to drop ACTUAL / ACTIVE
before I give my ack to this patch.

Kind regards,

-- 
Sakari Ailus
e-mail: sakari.ailus@iki.fi	jabber/XMPP/Gmail: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2012-05-13  0:06 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-04 18:32 [PATCH/RFC v4 00/13] V4L: camera control enhancements Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 01/12] V4L: Add helper function for standard integer menu controls Sylwester Nawrocki
2012-05-06 10:12   ` Sakari Ailus
2012-05-06 17:00     ` Sylwester Nawrocki
2012-05-06 18:51     ` [PATCH v5 " Sylwester Nawrocki
2012-05-07 15:05       ` Sakari Ailus
2012-05-04 18:32 ` [PATCH/RFC v4 02/12] V4L: Add camera exposure bias control Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 03/12] V4L: Add an extended camera white balance control Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 04/12] V4L: Add camera wide dynamic range control Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 05/12] V4L: Add camera image stabilization control Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 06/12] V4L: Add camera ISO sensitivity controls Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 07/12] V4L: Add camera exposure metering control Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 08/12] V4L: Add camera scene mode control Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 09/12] V4L: Add camera 3A lock control Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 10/12] V4L: Add auto focus targets to the selections API Sylwester Nawrocki
2012-05-06 18:22   ` Sakari Ailus
2012-05-08 10:46     ` Sylwester Nawrocki
2012-05-13  0:06       ` Sakari Ailus
2012-05-04 18:32 ` [PATCH/RFC v4 11/12] V4L: Add auto focus targets to the subdev " Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 12/12] V4L: Add camera auto focus controls Sylwester Nawrocki
2012-05-06 18:46   ` Sakari Ailus
2012-05-09 10:11     ` Sylwester Nawrocki
2012-05-09 17:39       ` Sylwester Nawrocki
2012-05-06 18:58   ` [PATCH v5 " Sylwester Nawrocki
2012-05-04 18:32 ` [PATCH/RFC v4 13/13] V4L: Add S5C73M3 sensor sub-device driver Sylwester Nawrocki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.