All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver
@ 2011-05-19 10:41 Sakari Ailus
  2011-05-19 10:41 ` [PATCH 1/3] v4l: Add a class and a set of controls for flash devices Sakari Ailus
                   ` (4 more replies)
  0 siblings, 5 replies; 22+ messages in thread
From: Sakari Ailus @ 2011-05-19 10:41 UTC (permalink / raw)
  To: linux-media
  Cc: Nayden Kanchev, Guennadi Liakhovetski, Laurent Pinchart,
	Hans Verkuil, David Cohen, Kim HeungJun, andrew.b.adams,
	Sung Hee Park

Hi,


This patchset implements RFC v4 of V4L2 API for flash devices [1], with
minor modifications, and adds the adp1653 flash controller driver.

This patchset depends on the bitmask controls patch [4].

Changes since v2 [3] of the RFC patchset:

- Improved flash control documentation in general.

- Faults may change the LED mode to none. This is now documented.

- adp1653 is returned to sane after faults are detected.

- Proper error handling for adp1653_get_fault() in adp1653_strobe().

- Remove useless function: adp1653_registered() and the corresponding
  callback. Controls are now initialised in adp1653_probe().

- Improved fault handling in adp1653_init_device().

Changes since v1 [2] of the RFC patchset:

- Faults on the flash LED are allowed to make the LED unusable before
the faults are read. This is implemented in the adp1653 driver.

- Intensities are using standard units; mA for flash / torch and uA for
the indicator.


Thanks to those who have given their feedback so far in the process!


[1] http://www.spinics.net/lists/linux-media/msg32030.html

[2] http://www.spinics.net/lists/linux-media/msg32396.html

[3] http://www.spinics.net/lists/linux-media/msg32436.html

[4] http://www.spinics.net/lists/linux-media/msg31001.html

Cheers,

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com

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

* [PATCH 1/3] v4l: Add a class and a set of controls for flash devices.
  2011-05-19 10:41 [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Sakari Ailus
@ 2011-05-19 10:41 ` Sakari Ailus
  2011-05-19 10:41 ` [PATCH 2/3] v4l: Add flash control documentation Sakari Ailus
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2011-05-19 10:41 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

From: Sakari Ailus <sakari.ailus@iki.fi>

Add a control class and a set of controls to support LED and Xenon flash
devices. An example of such a device is the adp1653.

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 drivers/media/video/v4l2-ctrls.c |   45 ++++++++++++++++++++++++++++++++++++++
 include/linux/videodev2.h        |   36 ++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 2412f08..74aae36 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -216,6 +216,17 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		"75 useconds",
 		NULL,
 	};
+	static const char * const flash_led_mode[] = {
+		"Off",
+		"Flash",
+		"Torch",
+		NULL,
+	};
+	static const char * const flash_strobe_source[] = {
+		"Software",
+		"External",
+		NULL,
+	};
 
 	switch (id) {
 	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
@@ -256,6 +267,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		return colorfx;
 	case V4L2_CID_TUNE_PREEMPHASIS:
 		return tune_preemphasis;
+	case V4L2_CID_FLASH_LED_MODE:
+		return flash_led_mode;
+	case V4L2_CID_FLASH_STROBE_SOURCE:
+		return flash_strobe_source;
 	default:
 		return NULL;
 	}
@@ -389,6 +404,21 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_TUNE_POWER_LEVEL:		return "Tune Power Level";
 	case V4L2_CID_TUNE_ANTENNA_CAPACITOR:	return "Tune Antenna Capacitor";
 
+	/* Flash controls */
+	case V4L2_CID_FLASH_CLASS:		return "Flash controls";
+	case V4L2_CID_FLASH_LED_MODE:		return "LED mode";
+	case V4L2_CID_FLASH_STROBE_SOURCE:	return "Strobe source";
+	case V4L2_CID_FLASH_STROBE:		return "Strobe";
+	case V4L2_CID_FLASH_STROBE_STOP:	return "Stop strobe";
+	case V4L2_CID_FLASH_STROBE_STATUS:	return "Strobe status";
+	case V4L2_CID_FLASH_TIMEOUT:		return "Strobe timeout";
+	case V4L2_CID_FLASH_INTENSITY:		return "Intensity, flash mode";
+	case V4L2_CID_FLASH_TORCH_INTENSITY:	return "Intensity, torch mode";
+	case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, indicator";
+	case V4L2_CID_FLASH_FAULT:		return "Faults";
+	case V4L2_CID_FLASH_CHARGE:		return "Charge";
+	case V4L2_CID_FLASH_READY:		return "Ready to strobe";
+
 	default:
 		return NULL;
 	}
@@ -423,12 +453,17 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_PILOT_TONE_ENABLED:
 	case V4L2_CID_ILLUMINATORS_1:
 	case V4L2_CID_ILLUMINATORS_2:
+	case V4L2_CID_FLASH_STROBE_STATUS:
+	case V4L2_CID_FLASH_CHARGE:
+	case V4L2_CID_FLASH_READY:
 		*type = V4L2_CTRL_TYPE_BOOLEAN;
 		*min = 0;
 		*max = *step = 1;
 		break;
 	case V4L2_CID_PAN_RESET:
 	case V4L2_CID_TILT_RESET:
+	case V4L2_CID_FLASH_STROBE:
+	case V4L2_CID_FLASH_STROBE_STOP:
 		*type = V4L2_CTRL_TYPE_BUTTON;
 		*flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
 		*min = *max = *step = *def = 0;
@@ -452,6 +487,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_EXPOSURE_AUTO:
 	case V4L2_CID_COLORFX:
 	case V4L2_CID_TUNE_PREEMPHASIS:
+	case V4L2_CID_FLASH_LED_MODE:
+	case V4L2_CID_FLASH_STROBE_SOURCE:
 		*type = V4L2_CTRL_TYPE_MENU;
 		break;
 	case V4L2_CID_RDS_TX_PS_NAME:
@@ -462,6 +499,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_CAMERA_CLASS:
 	case V4L2_CID_MPEG_CLASS:
 	case V4L2_CID_FM_TX_CLASS:
+	case V4L2_CID_FLASH_CLASS:
 		*type = V4L2_CTRL_TYPE_CTRL_CLASS;
 		/* You can neither read not write these */
 		*flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;
@@ -474,6 +512,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 		/* Max is calculated as RGB888 that is 2^24 */
 		*max = 0xFFFFFF;
 		break;
+	case V4L2_CID_FLASH_FAULT:
+		*type = V4L2_CTRL_TYPE_BITMASK;
+		break;
 	default:
 		*type = V4L2_CTRL_TYPE_INTEGER;
 		break;
@@ -519,6 +560,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_ZOOM_RELATIVE:
 		*flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
 		break;
+	case V4L2_CID_FLASH_STROBE_STATUS:
+	case V4L2_CID_FLASH_READY:
+		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
+		break;
 	}
 }
 EXPORT_SYMBOL(v4l2_ctrl_fill);
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index be82c8e..e364350 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1022,6 +1022,7 @@ struct v4l2_ext_controls {
 #define V4L2_CTRL_CLASS_MPEG 0x00990000	/* MPEG-compression controls */
 #define V4L2_CTRL_CLASS_CAMERA 0x009a0000	/* Camera class controls */
 #define V4L2_CTRL_CLASS_FM_TX 0x009b0000	/* FM Modulator control class */
+#define V4L2_CTRL_CLASS_FLASH 0x009c0000	/* Camera flash controls */
 
 #define V4L2_CTRL_ID_MASK      	  (0x0fffffff)
 #define V4L2_CTRL_ID2CLASS(id)    ((id) & 0x0fff0000UL)
@@ -1423,6 +1424,41 @@ enum v4l2_preemphasis {
 #define V4L2_CID_TUNE_POWER_LEVEL		(V4L2_CID_FM_TX_CLASS_BASE + 113)
 #define V4L2_CID_TUNE_ANTENNA_CAPACITOR		(V4L2_CID_FM_TX_CLASS_BASE + 114)
 
+/* Flash and privacy (indicator) light controls */
+#define V4L2_CID_FLASH_CLASS_BASE		(V4L2_CTRL_CLASS_FLASH | 0x900)
+#define V4L2_CID_FLASH_CLASS			(V4L2_CTRL_CLASS_FLASH | 1)
+
+#define V4L2_CID_FLASH_LED_MODE			(V4L2_CID_FLASH_CLASS_BASE + 1)
+enum v4l2_flash_led_mode {
+	V4L2_FLASH_LED_MODE_NONE,
+	V4L2_FLASH_LED_MODE_FLASH,
+	V4L2_FLASH_LED_MODE_TORCH,
+};
+
+#define V4L2_CID_FLASH_STROBE_SOURCE		(V4L2_CID_FLASH_CLASS_BASE + 2)
+enum v4l2_flash_strobe_source {
+	V4L2_FLASH_STROBE_SOURCE_SOFTWARE,
+	V4L2_FLASH_STROBE_SOURCE_EXTERNAL,
+};
+
+#define V4L2_CID_FLASH_STROBE			(V4L2_CID_FLASH_CLASS_BASE + 3)
+#define V4L2_CID_FLASH_STROBE_STOP		(V4L2_CID_FLASH_CLASS_BASE + 4)
+#define V4L2_CID_FLASH_STROBE_STATUS		(V4L2_CID_FLASH_CLASS_BASE + 5)
+
+#define V4L2_CID_FLASH_TIMEOUT			(V4L2_CID_FLASH_CLASS_BASE + 6)
+#define V4L2_CID_FLASH_INTENSITY		(V4L2_CID_FLASH_CLASS_BASE + 7)
+#define V4L2_CID_FLASH_TORCH_INTENSITY		(V4L2_CID_FLASH_CLASS_BASE + 8)
+#define V4L2_CID_FLASH_INDICATOR_INTENSITY	(V4L2_CID_FLASH_CLASS_BASE + 9)
+
+#define V4L2_CID_FLASH_FAULT			(V4L2_CID_FLASH_CLASS_BASE + 10)
+#define V4L2_FLASH_FAULT_OVER_VOLTAGE		(1 << 0)
+#define V4L2_FLASH_FAULT_TIMEOUT		(1 << 1)
+#define V4L2_FLASH_FAULT_OVER_TEMPERATURE	(1 << 2)
+#define V4L2_FLASH_FAULT_SHORT_CIRCUIT		(1 << 3)
+
+#define V4L2_CID_FLASH_CHARGE			(V4L2_CID_FLASH_CLASS_BASE + 11)
+#define V4L2_CID_FLASH_READY			(V4L2_CID_FLASH_CLASS_BASE + 12)
+
 /*
  *	T U N I N G
  */
-- 
1.7.2.5


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

* [PATCH 2/3] v4l: Add flash control documentation
  2011-05-19 10:41 [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Sakari Ailus
  2011-05-19 10:41 ` [PATCH 1/3] v4l: Add a class and a set of controls for flash devices Sakari Ailus
@ 2011-05-19 10:41 ` Sakari Ailus
  2011-05-19 10:41 ` [PATCH 3/3] adp1653: Add driver for LED flash controller Sakari Ailus
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2011-05-19 10:41 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

Add documentation for V4L2 flash controls.

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
---
 Documentation/DocBook/v4l/controls.xml           |  275 ++++++++++++++++++++++
 Documentation/DocBook/v4l/vidioc-g-ext-ctrls.xml |    7 +
 2 files changed, 282 insertions(+), 0 deletions(-)

diff --git a/Documentation/DocBook/v4l/controls.xml b/Documentation/DocBook/v4l/controls.xml
index a920ee8..77913b7 100644
--- a/Documentation/DocBook/v4l/controls.xml
+++ b/Documentation/DocBook/v4l/controls.xml
@@ -2092,6 +2092,281 @@ manually or automatically if set to zero. Unit, range and step are driver-specif
 <para>For more details about RDS specification, refer to
 <xref linkend="en50067" /> document, from CENELEC.</para>
     </section>
+
+    <section id="flash-controls">
+      <title>Flash Control Reference</title>
+
+      <para>
+	The V4L2 flash controls are intended to provide generic access
+	to flash controller devices. Flash controller devices are
+	typically used in digital cameras.
+      </para>
+
+      <para>
+	The interface can support both LED and xenon flash devices. As
+	of writing this, there is no xenon flash driver using this
+	interface.
+      </para>
+
+      <section id="flash-controls-use-cases">
+	<title>Supported use cases</title>
+
+	<section>
+	  <title>Unsynchronised LED flash (software strobe)</title>
+
+	  <para>
+	    Unsynchronised LED flash is controlled directly by the
+	    host as the sensor. The flash must be enabled by the host
+	    before the exposure of the image starts and disabled once
+	    it ends. The host is fully responsible for the timing of
+	    the flash.
+	  </para>
+
+	  <para>Example of such device: Nokia N900.</para>
+	</section>
+
+	<section>
+	  <title>Synchronised LED flash (hardware strobe)</title>
+
+	  <para>
+	    The synchronised LED flash is pre-programmed by the host
+	    (power and timeout) but controlled by the sensor through a
+	    strobe signal from the sensor to the flash.
+	  </para>
+
+	  <para>
+	    The sensor controls the flash duration and timing. This
+	    information typically must be made available to the
+	    sensor.
+	  </para>
+
+	</section>
+
+	<section>
+	  <title>LED flash as torch</title>
+
+	  <para>
+	    LED flash may be used as torch in conjunction with another
+	    use case involving camera or individually.
+	  </para>
+
+	</section>
+
+      </section>
+
+      <table pgwide="1" frame="none" id="flash-control-id">
+      <title>Flash Control IDs</title>
+
+      <tgroup cols="4">
+	<colspec colname="c1" colwidth="1*" />
+	<colspec colname="c2" colwidth="6*" />
+	<colspec colname="c3" colwidth="2*" />
+	<colspec colname="c4" colwidth="6*" />
+	<spanspec namest="c1" nameend="c2" spanname="id" />
+	<spanspec namest="c2" nameend="c4" spanname="descr" />
+	<thead>
+	  <row>
+	    <entry spanname="id" align="left">ID</entry>
+	    <entry align="left">Type</entry>
+	  </row><row rowsep="1"><entry spanname="descr" align="left">Description</entry>
+	  </row>
+	</thead>
+	<tbody valign="top">
+	  <row><entry></entry></row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_CLASS</constant></entry>
+	    <entry>class</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">The FLASH class descriptor.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_LED_MODE</constant></entry>
+	    <entry>menu</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Defines the mode of the flash LED,
+	    the high-power white LED attached to the flash controller.
+	    Setting this control may not be possible in presence of
+	    some faults. See V4L2_CID_FLASH_FAULT.</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_FLASH_LED_MODE_NONE</constant></entry>
+		  <entry>Off.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_FLASH_LED_MODE_FLASH</constant></entry>
+		  <entry>Flash mode.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_FLASH_LED_MODE_TORCH</constant></entry>
+		  <entry>Torch mode. See V4L2_CID_FLASH_TORCH_INTENSITY.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_SOURCE</constant></entry>
+	    <entry>menu</entry>
+	  </row>
+	  <row><entry spanname="descr">Defines the mode of the
+	  flash LED strobe.</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_FLASH_STROBE_SOURCE_SOFTWARE</constant></entry>
+		  <entry>The flash strobe is triggered by using
+		  the V4L2_CID_FLASH_STROBE control.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_FLASH_STROBE_SOURCE_EXTERNAL</constant></entry>
+		  <entry>The flash strobe is triggered by an
+		  external source. Typically this is a sensor,
+		  which makes it possible to synchronises the
+		  flash strobe start to exposure start.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE</constant></entry>
+	    <entry>button</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Strobe flash. Valid when
+	    V4L2_CID_FLASH_LED_MODE is set to
+	    V4L2_FLASH_LED_MODE_FLASH and V4L2_CID_FLASH_STROBE_SOURCE
+	    is set to V4L2_FLASH_STROBE_SOURCE_SOFTWARE. Setting this
+	    control may not be possible in presence of some faults.
+	    See V4L2_CID_FLASH_FAULT.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STOP</constant></entry>
+	    <entry>button</entry>
+	  </row>
+	  <row><entry spanname="descr">Stop flash strobe immediately.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STATUS</constant></entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Strobe status: whether the flash
+	    is strobing at the moment or not. This is a read-only
+	    control.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_TIMEOUT</constant></entry>
+	    <entry>integer</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Hardware timeout for flash. The
+	    flash strobe is stopped after this period of time has
+	    passed from the start of the strobe.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_INTENSITY</constant></entry>
+	    <entry>integer</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Intensity of the flash strobe when
+	    the flash LED is in flash mode
+	    (V4L2_FLASH_LED_MODE_FLASH). The unit should be milliamps
+	    (mA) if possible.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_TORCH_INTENSITY</constant></entry>
+	    <entry>integer</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Intensity of the flash LED in
+	    torch mode (V4L2_FLASH_LED_MODE_TORCH). The unit should be
+	    milliamps (mA) if possible. Setting this control may not
+	    be possible in presence of some faults. See
+	    V4L2_CID_FLASH_FAULT.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_INDICATOR_INTENSITY</constant></entry>
+	    <entry>integer</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Intensity of the indicator LED.
+	    The indicator LED may be fully independent of the flash
+	    LED. The unit should be microamps (uA) if possible.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_FAULT</constant></entry>
+	    <entry>bitmask</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Faults related to the flash. The
+	    faults tell about specific problems in the flash chip
+	    itself or the LEDs attached to it. Faults may prevent
+	    further use of some of the flash controls. In particular,
+	    V4L2_CID_FLASH_LED_MODE is set to V4L2_FLASH_LED_MODE_NONE
+	    if the fault affects the flash LED. Exactly which faults
+	    have such an effect is chip dependent. Reading the faults
+	    resets the control and returns the chip to a usable state
+	    if possible.</entry>
+	  </row>
+	  <row>
+	    <entrytbl spanname="descr" cols="2">
+	      <tbody valign="top">
+		<row>
+		  <entry><constant>V4L2_FLASH_FAULT_OVER_VOLTAGE</constant></entry>
+		  <entry>Flash controller voltage to the flash LED
+		  has exceeded the limit specific to the flash
+		  controller.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_FLASH_FAULT_TIMEOUT</constant></entry>
+		  <entry>The flash strobe was still on when
+		  the timeout set by the user ---
+		  V4L2_CID_FLASH_TIMEOUT control --- has expired.
+		  Not all flash controllers may set this in all
+		  such conditions.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_FLASH_FAULT_OVER_TEMPERATURE</constant></entry>
+		  <entry>The flash controller has overheated.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_FLASH_FAULT_SHORT_CIRCUIT</constant></entry>
+		  <entry>The short circuit protection of the flash
+		  controller has been triggered.</entry>
+		</row>
+	      </tbody>
+	    </entrytbl>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_CHARGE</constant></entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row><entry spanname="descr">Enable or disable charging of the xenon
+	  flash capacitor.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_FLASH_READY</constant></entry>
+	    <entry>boolean</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Is the flash ready to strobe?
+	    Xenon flashes require their capacitors charged before
+	    strobing. LED flashes often require a cooldown period
+	    after strobe during which another strobe will not be
+	    possible. This is a read-only control.</entry>
+	  </row>
+	  <row><entry></entry></row>
+	</tbody>
+      </tgroup>
+      </table>
+
+    </section>
 </section>
 
   <!--
diff --git a/Documentation/DocBook/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/v4l/vidioc-g-ext-ctrls.xml
index 3aa7f8f..c37bd86 100644
--- a/Documentation/DocBook/v4l/vidioc-g-ext-ctrls.xml
+++ b/Documentation/DocBook/v4l/vidioc-g-ext-ctrls.xml
@@ -250,6 +250,13 @@ These controls are described in <xref
 These controls are described in <xref
 		linkend="fm-tx-controls" />.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CTRL_CLASS_FLASH</constant></entry>
+	    <entry>0x9c0000</entry>
+	    <entry>The class containing flash device controls.
+These controls are described in <xref
+		linkend="flash-controls" />.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
-- 
1.7.2.5


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

* [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-05-19 10:41 [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Sakari Ailus
  2011-05-19 10:41 ` [PATCH 1/3] v4l: Add a class and a set of controls for flash devices Sakari Ailus
  2011-05-19 10:41 ` [PATCH 2/3] v4l: Add flash control documentation Sakari Ailus
@ 2011-05-19 10:41 ` Sakari Ailus
  2011-05-21 11:57   ` Mauro Carvalho Chehab
  2011-05-19 12:14 ` [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Laurent Pinchart
  2011-06-30 10:55 ` v4l2 api for flash drivers Andy Shevchenko
  4 siblings, 1 reply; 22+ messages in thread
From: Sakari Ailus @ 2011-05-19 10:41 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

This patch adds the driver for the adp1653 LED flash controller. This
controller supports a high power led in flash and torch modes and an
indicator light, sometimes also called privacy light.

The adp1653 is used on the Nokia N900.

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
Signed-off-by: Tuukka Toivonen <tuukkat76@gmail.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: David Cohen <dacohen@gmail.com>
---
 drivers/media/video/Kconfig   |    7 +
 drivers/media/video/Makefile  |    2 +
 drivers/media/video/adp1653.c |  481 +++++++++++++++++++++++++++++++++++++++++
 include/media/adp1653.h       |  126 +++++++++++
 4 files changed, 616 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/adp1653.c
 create mode 100644 include/media/adp1653.h

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 00f51dd..c004dbb 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -344,6 +344,13 @@ config VIDEO_TCM825X
 	  This is a driver for the Toshiba TCM825x VGA camera sensor.
 	  It is used for example in Nokia N800.
 
+config VIDEO_ADP1653
+	tristate "ADP1653 flash support"
+	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+	---help---
+	  This is a driver for the ADP1653 flash controller. It is used for
+	  example in Nokia N900.
+
 config VIDEO_SAA7110
 	tristate "Philips SAA7110 video decoder"
 	depends on VIDEO_V4L2 && I2C
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index ace5d8b..abdf021 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -131,6 +131,8 @@ obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
 
 obj-$(CONFIG_VIDEO_OMAP3)	+= omap3isp/
 
+obj-$(CONFIG_VIDEO_ADP1653)	+= adp1653.o
+
 obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
 obj-$(CONFIG_USB_STKWEBCAM)     += stkwebcam.o
 
diff --git a/drivers/media/video/adp1653.c b/drivers/media/video/adp1653.c
new file mode 100644
index 0000000..5bd64a2
--- /dev/null
+++ b/drivers/media/video/adp1653.c
@@ -0,0 +1,481 @@
+/*
+ * drivers/media/video/adp1653.c
+ *
+ * Copyright (C) 2008--2011 Nokia Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * Contributors:
+ *	Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *	Tuukka Toivonen <tuukkat76@gmail.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * TODO:
+ * - fault interrupt handling
+ * - faster strobe (use i/o pin instead of i2c)
+ *   - should ensure that the pin is in some sane state even if not used
+ * - power doesn't need to be ON if all lights are off
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <media/adp1653.h>
+#include <media/v4l2-device.h>
+
+#define TIMEOUT_MAX		820000
+#define TIMEOUT_STEP		54600
+#define TIMEOUT_MIN		(TIMEOUT_MAX - ADP1653_REG_CONFIG_TMR_SET_MAX \
+				 * TIMEOUT_STEP)
+#define TIMEOUT_US_TO_CODE(t)	((TIMEOUT_MAX + (TIMEOUT_STEP / 2) - (t)) \
+				 / TIMEOUT_STEP)
+#define TIMEOUT_CODE_TO_US(c)	(TIMEOUT_MAX - (c) * TIMEOUT_STEP)
+
+/* Write values into ADP1653 registers. */
+static int adp1653_update_hw(struct adp1653_flash *flash)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	u8 out_sel;
+	u8 config = 0;
+	int rval;
+
+	out_sel = ADP1653_INDICATOR_INTENSITY_uA_TO_REG(
+		flash->indicator_intensity->val)
+		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
+
+	switch (flash->led_mode->val) {
+	case V4L2_FLASH_LED_MODE_NONE:
+		break;
+	case V4L2_FLASH_LED_MODE_FLASH:
+		/* Flash mode, light on with strobe, duration from timer */
+		config = ADP1653_REG_CONFIG_TMR_CFG;
+		config |= TIMEOUT_US_TO_CODE(flash->flash_timeout->val)
+			  << ADP1653_REG_CONFIG_TMR_SET_SHIFT;
+		break;
+	case V4L2_FLASH_LED_MODE_TORCH:
+		/* Torch mode, light immediately on, duration indefinite */
+		out_sel |= ADP1653_FLASH_INTENSITY_mA_TO_REG(
+			flash->torch_intensity->val)
+			<< ADP1653_REG_OUT_SEL_HPLED_SHIFT;
+		break;
+	}
+
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
+	if (rval < 0)
+		return rval;
+
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_CONFIG, config);
+	if (rval < 0)
+		return rval;
+
+	return 0;
+}
+
+static int adp1653_get_fault(struct adp1653_flash *flash)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int fault;
+	int rval;
+
+	fault = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
+	if (IS_ERR_VALUE(fault))
+		return fault;
+
+	flash->fault |= fault;
+
+	if (!flash->fault)
+		return 0;
+
+	/* Clear faults. */
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
+	if (IS_ERR_VALUE(rval))
+		return rval;
+
+	flash->led_mode->val = V4L2_FLASH_LED_MODE_NONE;
+
+	rval = adp1653_update_hw(flash);
+	if (IS_ERR_VALUE(rval))
+		return rval;
+
+	return flash->fault;
+}
+
+static int adp1653_strobe(struct adp1653_flash *flash, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	u8 out_sel = ADP1653_INDICATOR_INTENSITY_uA_TO_REG(
+		flash->indicator_intensity->val)
+		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
+	int rval;
+
+	if (flash->led_mode->val != V4L2_FLASH_LED_MODE_FLASH)
+		return -EBUSY;
+
+	if (!enable)
+		return i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL,
+						 out_sel);
+
+	out_sel |= ADP1653_FLASH_INTENSITY_mA_TO_REG(
+		flash->flash_intensity->val)
+		<< ADP1653_REG_OUT_SEL_HPLED_SHIFT;
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
+	if (rval)
+		return rval;
+
+	/* Software strobe using i2c */
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE,
+		ADP1653_REG_SW_STROBE_SW_STROBE);
+	if (rval)
+		return rval;
+	return i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE, 0);
+}
+
+/* --------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct adp1653_flash *flash =
+		container_of(ctrl->handler, struct adp1653_flash, ctrls);
+	int rval;
+
+	rval = adp1653_get_fault(flash);
+	if (IS_ERR_VALUE(rval))
+		return rval;
+
+	ctrl->cur.val = 0;
+
+	if (flash->fault & ADP1653_REG_FAULT_FLT_SCP)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
+	if (flash->fault & ADP1653_REG_FAULT_FLT_OT)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
+	if (flash->fault & ADP1653_REG_FAULT_FLT_TMR)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
+	if (flash->fault & ADP1653_REG_FAULT_FLT_OV)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
+
+	flash->fault = 0;
+
+	return 0;
+}
+
+static int adp1653_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct adp1653_flash *flash =
+		container_of(ctrl->handler, struct adp1653_flash, ctrls);
+	int rval;
+
+	rval = adp1653_get_fault(flash);
+	if (IS_ERR_VALUE(rval))
+		return rval;
+	if ((rval & (ADP1653_REG_FAULT_FLT_SCP |
+		     ADP1653_REG_FAULT_FLT_OT |
+		     ADP1653_REG_FAULT_FLT_OV)) &&
+	    (ctrl->id == V4L2_CID_FLASH_STROBE ||
+	     ctrl->id == V4L2_CID_FLASH_TORCH_INTENSITY ||
+	     ctrl->id == V4L2_CID_FLASH_LED_MODE))
+		return -EBUSY;
+
+	switch (ctrl->id) {
+	case V4L2_CID_FLASH_STROBE:
+		return adp1653_strobe(flash, 1);
+	case V4L2_CID_FLASH_STROBE_STOP:
+		return adp1653_strobe(flash, 0);
+	}
+
+	return adp1653_update_hw(flash);
+}
+
+static const struct v4l2_ctrl_ops adp1653_ctrl_ops = {
+	.g_volatile_ctrl = adp1653_get_ctrl,
+	.s_ctrl = adp1653_set_ctrl,
+};
+
+static int adp1653_init_controls(struct adp1653_flash *flash)
+{
+	v4l2_ctrl_handler_init(&flash->ctrls, 9);
+
+	flash->led_mode =
+		v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
+				       V4L2_CID_FLASH_LED_MODE,
+				       V4L2_FLASH_LED_MODE_TORCH, ~0x7, 0);
+	v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
+			       V4L2_CID_FLASH_STROBE_SOURCE,
+			       V4L2_FLASH_STROBE_SOURCE_SOFTWARE, ~0x1, 0);
+	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+			  V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
+	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+			  V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
+	flash->flash_timeout =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_TIMEOUT, TIMEOUT_MIN,
+				  flash->platform_data->max_flash_timeout,
+				  TIMEOUT_STEP,
+				  flash->platform_data->max_flash_timeout);
+	flash->flash_intensity =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_INTENSITY,
+				  ADP1653_FLASH_INTENSITY_MIN,
+				  flash->platform_data->max_flash_intensity,
+				  1, flash->platform_data->max_flash_intensity);
+	flash->torch_intensity =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_TORCH_INTENSITY,
+				  ADP1653_TORCH_INTENSITY_MIN,
+				  flash->platform_data->max_torch_intensity,
+				  ADP1653_FLASH_INTENSITY_STEP,
+				  flash->platform_data->max_torch_intensity);
+	flash->indicator_intensity =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_INDICATOR_INTENSITY,
+				  ADP1653_INDICATOR_INTENSITY_MIN,
+				  flash->platform_data->max_indicator_intensity,
+				  ADP1653_INDICATOR_INTENSITY_STEP,
+				  ADP1653_INDICATOR_INTENSITY_MIN);
+	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+			  V4L2_CID_FLASH_FAULT, 0, V4L2_FLASH_FAULT_OVER_VOLTAGE
+			  | V4L2_FLASH_FAULT_OVER_TEMPERATURE
+			  | V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
+
+	if (flash->ctrls.error)
+		return flash->ctrls.error;
+
+	flash->subdev.ctrl_handler = &flash->ctrls;
+	return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static int
+adp1653_init_device(struct adp1653_flash *flash)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int rval;
+
+	/* Clear FAULT register by writing zero to OUT_SEL */
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
+	if (rval < 0) {
+		dev_err(&client->dev, "failed writing fault register\n");
+		return -EIO;
+	}
+
+	mutex_lock(&flash->ctrls.lock);
+	/* Reset faults before reading new ones. */
+	flash->fault = 0;
+	rval = adp1653_get_fault(flash);
+	mutex_unlock(&flash->ctrls.lock);
+	if (rval > 0) {
+		dev_err(&client->dev, "faults detected: 0x%1.1x\n", rval);
+		return -EIO;
+	}
+
+	mutex_lock(&flash->ctrls.lock);
+	rval = adp1653_update_hw(flash);
+	mutex_unlock(&flash->ctrls.lock);
+	if (rval) {
+		dev_err(&client->dev,
+			"adp1653_update_hw failed at %s\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int
+__adp1653_set_power(struct adp1653_flash *flash, int on)
+{
+	int ret;
+
+	ret = flash->platform_data->power(&flash->subdev, on);
+	if (ret < 0)
+		return ret;
+
+	if (!on)
+		return 0;
+
+	ret = adp1653_init_device(flash);
+	if (ret < 0)
+		flash->platform_data->power(&flash->subdev, 0);
+
+	return ret;
+}
+
+static int
+adp1653_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+	int ret = 0;
+
+	mutex_lock(&flash->power_lock);
+
+	/* If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (flash->power_count == !on) {
+		ret = __adp1653_set_power(flash, !!on);
+		if (ret < 0)
+			goto done;
+	}
+
+	/* Update the power count. */
+	flash->power_count += on ? 1 : -1;
+	WARN_ON(flash->power_count < 0);
+
+done:
+	mutex_unlock(&flash->power_lock);
+	return ret;
+}
+
+static int adp1653_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return adp1653_set_power(sd, 1);
+}
+
+static int adp1653_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return adp1653_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops adp1653_core_ops = {
+	.s_power = adp1653_set_power,
+};
+
+static const struct v4l2_subdev_ops adp1653_ops = {
+	.core = &adp1653_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops adp1653_internal_ops = {
+	.open = adp1653_open,
+	.close = adp1653_close,
+};
+
+/* --------------------------------------------------------------------------
+ * I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int adp1653_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+	if (!flash->power_count)
+		return 0;
+
+	return __adp1653_set_power(flash, 0);
+}
+
+static int adp1653_resume(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+	if (!flash->power_count)
+		return 0;
+
+	return __adp1653_set_power(flash, 1);
+}
+
+#else
+
+#define adp1653_suspend	NULL
+#define adp1653_resume	NULL
+
+#endif /* CONFIG_PM */
+
+static int adp1653_probe(struct i2c_client *client,
+			 const struct i2c_device_id *devid)
+{
+	struct adp1653_flash *flash;
+	int ret;
+
+	flash = kzalloc(sizeof(*flash), GFP_KERNEL);
+	if (flash == NULL)
+		return -ENOMEM;
+
+	flash->platform_data = client->dev.platform_data;
+
+	mutex_init(&flash->power_lock);
+
+	v4l2_i2c_subdev_init(&flash->subdev, client, &adp1653_ops);
+	flash->subdev.internal_ops = &adp1653_internal_ops;
+	flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	adp1653_init_controls(flash);
+
+	ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
+	if (ret < 0)
+		kfree(flash);
+
+	return ret;
+}
+
+static int __exit adp1653_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+	v4l2_device_unregister_subdev(&flash->subdev);
+	v4l2_ctrl_handler_free(&flash->ctrls);
+	media_entity_cleanup(&flash->subdev.entity);
+	kfree(flash);
+	return 0;
+}
+
+static const struct i2c_device_id adp1653_id_table[] = {
+	{ ADP1653_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adp1653_id_table);
+
+static struct i2c_driver adp1653_i2c_driver = {
+	.driver		= {
+		.name	= ADP1653_NAME,
+	},
+	.probe		= adp1653_probe,
+	.remove		= __exit_p(adp1653_remove),
+	.suspend	= adp1653_suspend,
+	.resume		= adp1653_resume,
+	.id_table	= adp1653_id_table,
+};
+
+static int __init adp1653_init(void)
+{
+	int rval;
+
+	rval = i2c_add_driver(&adp1653_i2c_driver);
+	if (rval)
+		printk(KERN_ALERT "%s: failed at i2c_add_driver\n", __func__);
+
+	return rval;
+}
+
+static void __exit adp1653_exit(void)
+{
+	i2c_del_driver(&adp1653_i2c_driver);
+}
+
+module_init(adp1653_init);
+module_exit(adp1653_exit);
+
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
+MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver");
+MODULE_LICENSE("GPL");
diff --git a/include/media/adp1653.h b/include/media/adp1653.h
new file mode 100644
index 0000000..50a1af8
--- /dev/null
+++ b/include/media/adp1653.h
@@ -0,0 +1,126 @@
+/*
+ * include/media/adp1653.h
+ *
+ * Copyright (C) 2008--2011 Nokia Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * Contributors:
+ *	Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *	Tuukka Toivonen <tuukkat76@gmail.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef ADP1653_H
+#define ADP1653_H
+
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#define ADP1653_NAME				"adp1653"
+#define ADP1653_I2C_ADDR			(0x60 >> 1)
+
+/* Register definitions */
+#define ADP1653_REG_OUT_SEL			0x00
+#define ADP1653_REG_OUT_SEL_HPLED_TORCH_MIN	0x01
+#define ADP1653_REG_OUT_SEL_HPLED_TORCH_MAX	0x0b
+#define ADP1653_REG_OUT_SEL_HPLED_FLASH_MIN	0x0c
+#define ADP1653_REG_OUT_SEL_HPLED_FLASH_MAX	0x1f
+#define ADP1653_REG_OUT_SEL_HPLED_SHIFT		3
+#define ADP1653_REG_OUT_SEL_ILED_MAX		0x07
+#define ADP1653_REG_OUT_SEL_ILED_SHIFT		0
+
+#define ADP1653_REG_CONFIG			0x01
+#define ADP1653_REG_CONFIG_TMR_CFG		(1 << 4)
+#define ADP1653_REG_CONFIG_TMR_SET_MAX		0x0f
+#define ADP1653_REG_CONFIG_TMR_SET_SHIFT	0
+
+#define ADP1653_REG_SW_STROBE			0x02
+#define ADP1653_REG_SW_STROBE_SW_STROBE		(1 << 0)
+
+#define ADP1653_REG_FAULT			0x03
+#define ADP1653_REG_FAULT_FLT_SCP		(1 << 3)
+#define ADP1653_REG_FAULT_FLT_OT		(1 << 2)
+#define ADP1653_REG_FAULT_FLT_TMR		(1 << 1)
+#define ADP1653_REG_FAULT_FLT_OV		(1 << 0)
+
+#define ADP1653_INDICATOR_INTENSITY_MIN		0
+#define ADP1653_INDICATOR_INTENSITY_STEP	2500
+#define ADP1653_INDICATOR_INTENSITY_MAX		\
+	(ADP1653_REG_OUT_SEL_ILED_MAX * ADP1653_INDICATOR_INTENSITY_STEP)
+#define ADP1653_INDICATOR_INTENSITY_uA_TO_REG(a) \
+	((a) / ADP1653_INDICATOR_INTENSITY_STEP)
+#define ADP1653_INDICATOR_INTENSITY_REG_TO_uA(a) \
+	((a) * ADP1653_INDICATOR_INTENSITY_STEP)
+
+#define ADP1653_FLASH_INTENSITY_BASE		35
+#define ADP1653_FLASH_INTENSITY_STEP		15
+#define ADP1653_FLASH_INTENSITY_MIN					\
+	(ADP1653_FLASH_INTENSITY_BASE					\
+	 + ADP1653_REG_OUT_SEL_HPLED_FLASH_MIN * ADP1653_FLASH_INTENSITY_STEP)
+#define ADP1653_FLASH_INTENSITY_MAX			\
+	(ADP1653_FLASH_INTENSITY_MIN +			\
+	 (ADP1653_REG_OUT_SEL_HPLED_FLASH_MAX -		\
+	  ADP1653_REG_OUT_SEL_HPLED_FLASH_MIN + 1) *	\
+	 ADP1653_FLASH_INTENSITY_STEP)
+
+#define ADP1653_FLASH_INTENSITY_mA_TO_REG(a)				\
+	((a) < ADP1653_FLASH_INTENSITY_BASE ? 0 :			\
+	 (((a) - ADP1653_FLASH_INTENSITY_BASE) / ADP1653_FLASH_INTENSITY_STEP))
+#define ADP1653_FLASH_INTENSITY_REG_TO_mA(a)		\
+	((a) * ADP1653_FLASH_INTENSITY_STEP + ADP1653_FLASH_INTENSITY_BASE)
+
+#define ADP1653_TORCH_INTENSITY_MIN					\
+	(ADP1653_FLASH_INTENSITY_BASE					\
+	 + ADP1653_REG_OUT_SEL_HPLED_TORCH_MIN * ADP1653_FLASH_INTENSITY_STEP)
+#define ADP1653_TORCH_INTENSITY_MAX			\
+	(ADP1653_TORCH_INTENSITY_MIN +			\
+	 (ADP1653_REG_OUT_SEL_HPLED_TORCH_MAX -		\
+	  ADP1653_REG_OUT_SEL_HPLED_TORCH_MIN + 1) *	\
+	 ADP1653_FLASH_INTENSITY_STEP)
+
+struct adp1653_platform_data {
+	int (*power)(struct v4l2_subdev *sd, int on);
+
+	u32 max_flash_timeout;		/* flash light timeout in us */
+	u32 max_flash_intensity;	/* led intensity, flash mode */
+	u32 max_torch_intensity;	/* led intensity, torch mode */
+	u32 max_indicator_intensity;	/* indicator led intensity */
+};
+
+#define to_adp1653_flash(sd)	container_of(sd, struct adp1653_flash, subdev)
+
+struct adp1653_flash {
+	struct v4l2_subdev subdev;
+	struct adp1653_platform_data *platform_data;
+
+	struct v4l2_ctrl_handler ctrls;
+	struct v4l2_ctrl *led_mode;
+	struct v4l2_ctrl *flash_timeout;
+	struct v4l2_ctrl *flash_intensity;
+	struct v4l2_ctrl *torch_intensity;
+	struct v4l2_ctrl *indicator_intensity;
+
+	struct mutex power_lock;
+	int power_count;
+	int fault;
+};
+
+#endif /* ADP1653_H */
-- 
1.7.2.5


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

* Re: [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver
  2011-05-19 10:41 [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Sakari Ailus
                   ` (2 preceding siblings ...)
  2011-05-19 10:41 ` [PATCH 3/3] adp1653: Add driver for LED flash controller Sakari Ailus
@ 2011-05-19 12:14 ` Laurent Pinchart
  2011-05-19 14:22   ` David Cohen
  2011-06-30 10:55 ` v4l2 api for flash drivers Andy Shevchenko
  4 siblings, 1 reply; 22+ messages in thread
From: Laurent Pinchart @ 2011-05-19 12:14 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Nayden Kanchev, Guennadi Liakhovetski, Hans Verkuil,
	David Cohen, Kim HeungJun, andrew.b.adams, Sung Hee Park

Hi Sakari,

On Thursday 19 May 2011 12:41:14 Sakari Ailus wrote:
> Hi,
> 
> This patchset implements RFC v4 of V4L2 API for flash devices [1], with
> minor modifications, and adds the adp1653 flash controller driver.

As already answered in private:

Acked-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
 
> This patchset depends on the bitmask controls patch [4].
>
> Changes since v2 [3] of the RFC patchset:
> 
> - Improved flash control documentation in general.
> 
> - Faults may change the LED mode to none. This is now documented.
> 
> - adp1653 is returned to sane after faults are detected.
> 
> - Proper error handling for adp1653_get_fault() in adp1653_strobe().
> 
> - Remove useless function: adp1653_registered() and the corresponding
>   callback. Controls are now initialised in adp1653_probe().
> 
> - Improved fault handling in adp1653_init_device().
> 
> Changes since v1 [2] of the RFC patchset:
> 
> - Faults on the flash LED are allowed to make the LED unusable before
> the faults are read. This is implemented in the adp1653 driver.
> 
> - Intensities are using standard units; mA for flash / torch and uA for
> the indicator.
> 
> 
> Thanks to those who have given their feedback so far in the process!
> 
> 
> [1] http://www.spinics.net/lists/linux-media/msg32030.html
> 
> [2] http://www.spinics.net/lists/linux-media/msg32396.html
> 
> [3] http://www.spinics.net/lists/linux-media/msg32436.html
> 
> [4] http://www.spinics.net/lists/linux-media/msg31001.html

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver
  2011-05-19 12:14 ` [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Laurent Pinchart
@ 2011-05-19 14:22   ` David Cohen
  2011-05-19 14:24     ` Laurent Pinchart
  0 siblings, 1 reply; 22+ messages in thread
From: David Cohen @ 2011-05-19 14:22 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Sakari Ailus, linux-media, Nayden Kanchev, Guennadi Liakhovetski,
	Hans Verkuil, Kim HeungJun, andrew.b.adams, Sung Hee Park

Hi Laurent,

On Thu, May 19, 2011 at 3:14 PM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hi Sakari,
>
> On Thursday 19 May 2011 12:41:14 Sakari Ailus wrote:
>> Hi,
>>
>> This patchset implements RFC v4 of V4L2 API for flash devices [1], with
>> minor modifications, and adds the adp1653 flash controller driver.
>
> As already answered in private:
>
> Acked-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>

Sorry if I missed something, but shouldn't be your ack here? :)
The patches are from Sakari already.

Br,

David

>
>> This patchset depends on the bitmask controls patch [4].
>>
>> Changes since v2 [3] of the RFC patchset:
>>
>> - Improved flash control documentation in general.
>>
>> - Faults may change the LED mode to none. This is now documented.
>>
>> - adp1653 is returned to sane after faults are detected.
>>
>> - Proper error handling for adp1653_get_fault() in adp1653_strobe().
>>
>> - Remove useless function: adp1653_registered() and the corresponding
>>   callback. Controls are now initialised in adp1653_probe().
>>
>> - Improved fault handling in adp1653_init_device().
>>
>> Changes since v1 [2] of the RFC patchset:
>>
>> - Faults on the flash LED are allowed to make the LED unusable before
>> the faults are read. This is implemented in the adp1653 driver.
>>
>> - Intensities are using standard units; mA for flash / torch and uA for
>> the indicator.
>>
>>
>> Thanks to those who have given their feedback so far in the process!
>>
>>
>> [1] http://www.spinics.net/lists/linux-media/msg32030.html
>>
>> [2] http://www.spinics.net/lists/linux-media/msg32396.html
>>
>> [3] http://www.spinics.net/lists/linux-media/msg32436.html
>>
>> [4] http://www.spinics.net/lists/linux-media/msg31001.html
>
> --
> Regards,
>
> Laurent Pinchart
>

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

* Re: [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver
  2011-05-19 14:22   ` David Cohen
@ 2011-05-19 14:24     ` Laurent Pinchart
  0 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2011-05-19 14:24 UTC (permalink / raw)
  To: David Cohen
  Cc: Sakari Ailus, linux-media, Nayden Kanchev, Guennadi Liakhovetski,
	Hans Verkuil, Kim HeungJun, andrew.b.adams, Sung Hee Park

Hi David,

On Thursday 19 May 2011 16:22:45 David Cohen wrote:
> On Thu, May 19, 2011 at 3:14 PM, Laurent Pinchart wrote:
> > On Thursday 19 May 2011 12:41:14 Sakari Ailus wrote:
> >> Hi,
> >> 
> >> This patchset implements RFC v4 of V4L2 API for flash devices [1], with
> >> minor modifications, and adds the adp1653 flash controller driver.
> > 
> > As already answered in private:
> > 
> > Acked-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
> 
> Sorry if I missed something, but shouldn't be your ack here? :)
> The patches are from Sakari already.

OK, I'll stop trying to impersonate Sakari :-)

Wrong copy&paste, sorry.

Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-05-19 10:41 ` [PATCH 3/3] adp1653: Add driver for LED flash controller Sakari Ailus
@ 2011-05-21 11:57   ` Mauro Carvalho Chehab
  2011-05-22 12:39     ` Sakari Ailus
  0 siblings, 1 reply; 22+ messages in thread
From: Mauro Carvalho Chehab @ 2011-05-21 11:57 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, laurent.pinchart, nkanchev, g.liakhovetski,
	hverkuil, dacohen, riverful, andrew.b.adams, shpark7

Em 19-05-2011 07:41, Sakari Ailus escreveu:
> This patch adds the driver for the adp1653 LED flash controller. This
> controller supports a high power led in flash and torch modes and an
> indicator light, sometimes also called privacy light.
> 
> The adp1653 is used on the Nokia N900.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
> Signed-off-by: Tuukka Toivonen <tuukkat76@gmail.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: David Cohen <dacohen@gmail.com>
> ---
>  drivers/media/video/Kconfig   |    7 +
>  drivers/media/video/Makefile  |    2 +
>  drivers/media/video/adp1653.c |  481 +++++++++++++++++++++++++++++++++++++++++
>  include/media/adp1653.h       |  126 +++++++++++
>  4 files changed, 616 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/adp1653.c
>  create mode 100644 include/media/adp1653.h
> 
> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> index 00f51dd..c004dbb 100644
> --- a/drivers/media/video/Kconfig
> +++ b/drivers/media/video/Kconfig
> @@ -344,6 +344,13 @@ config VIDEO_TCM825X
>  	  This is a driver for the Toshiba TCM825x VGA camera sensor.
>  	  It is used for example in Nokia N800.
>  
> +config VIDEO_ADP1653
> +	tristate "ADP1653 flash support"
> +	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
> +	---help---
> +	  This is a driver for the ADP1653 flash controller. It is used for
> +	  example in Nokia N900.
> +
>  config VIDEO_SAA7110
>  	tristate "Philips SAA7110 video decoder"
>  	depends on VIDEO_V4L2 && I2C

The patches look sane. I have just one comment: Please, create a separate
section for the LED controls. OK, some patches already messed the Kconfig stuff
by mixing sensors together with video decoders, but let's not make the things
worse.

Thanks,
Mauro.

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

* Re: [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-05-21 11:57   ` Mauro Carvalho Chehab
@ 2011-05-22 12:39     ` Sakari Ailus
  0 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2011-05-22 12:39 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: linux-media, laurent.pinchart, nkanchev, g.liakhovetski,
	hverkuil, dacohen, riverful, andrew.b.adams, shpark7

Mauro Carvalho Chehab wrote:
> Em 19-05-2011 07:41, Sakari Ailus escreveu:
>> This patch adds the driver for the adp1653 LED flash controller. This
>> controller supports a high power led in flash and torch modes and an
>> indicator light, sometimes also called privacy light.
>>
>> The adp1653 is used on the Nokia N900.
>>
>> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
>> Signed-off-by: Tuukka Toivonen <tuukkat76@gmail.com>
>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> Signed-off-by: David Cohen <dacohen@gmail.com>
>> ---
>>  drivers/media/video/Kconfig   |    7 +
>>  drivers/media/video/Makefile  |    2 +
>>  drivers/media/video/adp1653.c |  481 +++++++++++++++++++++++++++++++++++++++++
>>  include/media/adp1653.h       |  126 +++++++++++
>>  4 files changed, 616 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/media/video/adp1653.c
>>  create mode 100644 include/media/adp1653.h
>>
>> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
>> index 00f51dd..c004dbb 100644
>> --- a/drivers/media/video/Kconfig
>> +++ b/drivers/media/video/Kconfig
>> @@ -344,6 +344,13 @@ config VIDEO_TCM825X
>>  	  This is a driver for the Toshiba TCM825x VGA camera sensor.
>>  	  It is used for example in Nokia N800.
>>  
>> +config VIDEO_ADP1653
>> +	tristate "ADP1653 flash support"
>> +	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
>> +	---help---
>> +	  This is a driver for the ADP1653 flash controller. It is used for
>> +	  example in Nokia N900.
>> +
>>  config VIDEO_SAA7110
>>  	tristate "Philips SAA7110 video decoder"
>>  	depends on VIDEO_V4L2 && I2C
> 
> The patches look sane. I have just one comment: Please, create a separate
> section for the LED controls. OK, some patches already messed the Kconfig stuff
> by mixing sensors together with video decoders, but let's not make the things
> worse.

Hi Mauro,

Thanks for the comment! I'll fix this in the Kconfig for the next patchset.

Regards,

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com

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

* v4l2 api for flash drivers
  2011-05-19 10:41 [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Sakari Ailus
                   ` (3 preceding siblings ...)
  2011-05-19 12:14 ` [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Laurent Pinchart
@ 2011-06-30 10:55 ` Andy Shevchenko
  2011-06-30 11:06   ` Laurent Pinchart
  4 siblings, 1 reply; 22+ messages in thread
From: Andy Shevchenko @ 2011-06-30 10:55 UTC (permalink / raw)
  To: linux-media; +Cc: Laurent Pinchart, Mauro Carvalho Chehab

Hello.

I didn't see the patchset [1] in any public tree on git.kernel.org. Is
this patch going to be pushed?

[1] http://www.spinics.net/lists/linux-media/msg32527.html

-- 
Andy Shevchenko <andriy.shevchenko@intel.com>
Intel Finland Oy

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

* Re: v4l2 api for flash drivers
  2011-06-30 10:55 ` v4l2 api for flash drivers Andy Shevchenko
@ 2011-06-30 11:06   ` Laurent Pinchart
  2011-06-30 11:26     ` Sakari Ailus
  0 siblings, 1 reply; 22+ messages in thread
From: Laurent Pinchart @ 2011-06-30 11:06 UTC (permalink / raw)
  To: Andy Shevchenko; +Cc: linux-media, Mauro Carvalho Chehab, Sakari Ailus

Hi Andy,

On Thursday 30 June 2011 12:55:10 Andy Shevchenko wrote:
> Hello.
> 
> I didn't see the patchset [1] in any public tree on git.kernel.org. Is
> this patch going to be pushed?
> 
> [1] http://www.spinics.net/lists/linux-media/msg32527.html

Sakari Ailus sent a pull request for Linux 3.1, so the patches should get 
there soon.

-- 
Regards,

Laurent Pinchart

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

* Re: v4l2 api for flash drivers
  2011-06-30 11:06   ` Laurent Pinchart
@ 2011-06-30 11:26     ` Sakari Ailus
  2011-07-26  9:12       ` Andy Shevchenko
  0 siblings, 1 reply; 22+ messages in thread
From: Sakari Ailus @ 2011-06-30 11:26 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Andy Shevchenko, linux-media, Mauro Carvalho Chehab

Hi Andy and Laurent,

On Thu, Jun 30, 2011 at 01:06:08PM +0200, Laurent Pinchart wrote:
> Hi Andy,
> 
> On Thursday 30 June 2011 12:55:10 Andy Shevchenko wrote:
> > Hello.
> > 
> > I didn't see the patchset [1] in any public tree on git.kernel.org. Is
> > this patch going to be pushed?
> > 
> > [1] http://www.spinics.net/lists/linux-media/msg32527.html
> 
> Sakari Ailus sent a pull request for Linux 3.1, so the patches should get 
> there soon.

Yeah, that's my expectation as well unless there are further issues found
with them.

Mauro? :-)

Cheers,

-- 
Sakari Ailus
sakari.ailus@iki.fi

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

* Re: v4l2 api for flash drivers
  2011-06-30 11:26     ` Sakari Ailus
@ 2011-07-26  9:12       ` Andy Shevchenko
  2011-07-26  9:47         ` Sakari Ailus
  0 siblings, 1 reply; 22+ messages in thread
From: Andy Shevchenko @ 2011-07-26  9:12 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: Laurent Pinchart, linux-media

On Thu, 2011-06-30 at 14:26 +0300, Sakari Ailus wrote: 
> > > [1] http://www.spinics.net/lists/linux-media/msg32527.html
> Yeah, that's my expectation as well unless there are further issues found
> with them.
I had not been subscribed to ML when you discussed the topic. So, might
be I missed something. However, the question is why have you chosen
hardware units for *_INTENSITY instead of, let say, hundredth of
percents (like 0 .. 10000)?

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

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

* Re: v4l2 api for flash drivers
  2011-07-26  9:12       ` Andy Shevchenko
@ 2011-07-26  9:47         ` Sakari Ailus
  0 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2011-07-26  9:47 UTC (permalink / raw)
  To: Andy Shevchenko; +Cc: Laurent Pinchart, linux-media

Hi Andy,

On Tue, Jul 26, 2011 at 12:12:02PM +0300, Andy Shevchenko wrote:
> On Thu, 2011-06-30 at 14:26 +0300, Sakari Ailus wrote: 
> > > > [1] http://www.spinics.net/lists/linux-media/msg32527.html
> > Yeah, that's my expectation as well unless there are further issues found
> > with them.
> I had not been subscribed to ML when you discussed the topic. So, might
> be I missed something. However, the question is why have you chosen
> hardware units for *_INTENSITY instead of, let say, hundredth of
> percents (like 0 .. 10000)?

Current is not that hardware specific.

There is some value in knowing the actual current. For example, if you have
two different flash controllers with the same LED, you can achieve the same
luminous output by choosing the same current on both controllers, without
knowing which one you're actually using.

Regards,

-- 
Sakari Ailus
sakari.ailus@iki.fi

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

* Re: [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-06-09 15:10   ` Laurent Pinchart
@ 2011-06-10  8:20     ` Sakari Ailus
  0 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2011-06-10  8:20 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

Laurent Pinchart wrote:
> Hi Sakari,
> 
> On Monday 16 May 2011 15:00:39 Sakari Ailus wrote:
>> This patch adds the driver for the adp1653 LED flash controller. This
>> controller supports a high power led in flash and torch modes and an
>> indicator light, sometimes also called privacy light.
>>
>> The adp1653 is used on the Nokia N900.
>>
>> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
>> Signed-off-by: Tuukka Toivonen <tuukkat76@gmail.com>
>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> Signed-off-by: David Cohen <dacohen@gmail.com>
> 
> [snip]
> 
>> +	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
>> +			  V4L2_CID_FLASH_FAULT, 0, V4L2_FLASH_FAULT_OVER_VOLTAGE
>> +			  | V4L2_FLASH_FAULT_OVER_TEMPERATURE
>> +			  | V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
> 
> You need to mark the fault control as volatile.

Thanks for catching this!

I'll fix it for the pull req.

Cheers,

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com

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

* Re: [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-05-16 13:00 ` [PATCH 3/3] adp1653: Add driver for LED flash controller Sakari Ailus
  2011-05-16 20:31   ` Laurent Pinchart
@ 2011-06-09 15:10   ` Laurent Pinchart
  2011-06-10  8:20     ` Sakari Ailus
  1 sibling, 1 reply; 22+ messages in thread
From: Laurent Pinchart @ 2011-06-09 15:10 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

Hi Sakari,

On Monday 16 May 2011 15:00:39 Sakari Ailus wrote:
> This patch adds the driver for the adp1653 LED flash controller. This
> controller supports a high power led in flash and torch modes and an
> indicator light, sometimes also called privacy light.
> 
> The adp1653 is used on the Nokia N900.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
> Signed-off-by: Tuukka Toivonen <tuukkat76@gmail.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: David Cohen <dacohen@gmail.com>

[snip]

> +	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
> +			  V4L2_CID_FLASH_FAULT, 0, V4L2_FLASH_FAULT_OVER_VOLTAGE
> +			  | V4L2_FLASH_FAULT_OVER_TEMPERATURE
> +			  | V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);

You need to mark the fault control as volatile.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-05-17 10:47         ` Sakari Ailus
@ 2011-05-17 10:51           ` Laurent Pinchart
  0 siblings, 0 replies; 22+ messages in thread
From: Laurent Pinchart @ 2011-05-17 10:51 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

Hi Sakari,

On Tuesday 17 May 2011 12:47:25 Sakari Ailus wrote:
> Laurent Pinchart wrote:
> > On Tuesday 17 May 2011 07:38:38 Sakari Ailus wrote:
> [clip]
> 
> >>> If several applications read controls, only one of them will be
> >>> notified of faults. Shouldn't clearing the fault be handled explicitly
> >>> by writing to a control ? I know this changes the API :-)
> >> 
> >> This is true.
> >> 
> >> Although I can't imagine right now why two separate processes should be
> >> so interested in the faults but it is still entirely possible that
> >> someone does that since it's permitted by the interface.
> >> 
> >> Having to write zero to faults to clear them isn't good either since it
> >> might mean missing faults that are triggered between reading and writing
> >> this control.
> >> 
> >> Perhaps this would make sense as a file handle specific control?
> > 
> > Good question. Control events will help I guess, maybe that's the
> > solution.
> 
> They would help, yes, but in the case of N900 we don't have that luxury
> since there's no interrupt line from the adp1653 to OMAP. So if one user
> would read the control, the others would get notified. Yes, that would
> work, too.
> 
> The use case is mostly theoretical and that's actually best the hardware
> can offer, so I think this is good. No special arrangements needed then.
> 
> So reading the value will reset the faults?

OK, let's leave it that way, at least for now.

> >> The control documentation says that the faults are cleared when the
> >> register is read, but the adp1653 also clears the faults whenever
> >> writing zero to out_sel which happens also in other circumstances, for
> >> example when changing mode from flash to torch when the torch intensity
> >> is zero, or when indicator intensity is zero in other modes.
> >> 
> >>>> +	/* Restore configuration. */
> >>>> +	rval = adp1653_update_hw(flash);
> >>>> +	if (IS_ERR_VALUE(rval))
> >>>> +		return rval;
> >>> 
> >>> Will that produce expected results ? For instance, if a fault was
> >>> detected during flash strobe, won't it try to re-strobe the flash ?
> >>> Shouldn't the user
> >> 
> >> No. Flash is strobed using adp1653_strobe().
> >> 
> >>> be required to explicitly re-strobe the flash or turn the torch (or
> >>> indicator) on after a fault ? Once again this should be clarified in
> >>> the API :-)
> >> 
> >> The mode won't be changed from the flash but to strobe again, the user
> >> has to push V4L2_CID_FLASH_STROBE again.
> >> 
> >> The adp1653 doesn't have any torch (as such) or indicator faults; some
> >> other chips do have indicator faults at least. Using the torch mode
> >> might trigger faults, too, since it's the same LED; just the power isn't
> >> that high.
> > 
> > When an over-current fault is detected, shouldn't the mode be set back to
> > none ? If we just clear the fault and reprogram the registers, the torch
> > will be turned back on, and the fault will likely happen again.
> 
> That's a good point.
> 
> Over-temperature, over-voltage, and short circuit faults should change the
> LED mode to be set to none. This is likely chip independent behaviour but on
> the other hand, not all the chips implement all the faults.

If the chip doesn't implement faults handling there little we can do. For 
chips that do implement faults handling, let's switch the LED mode to none 
when a fault is detected.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-05-17  7:23       ` Laurent Pinchart
@ 2011-05-17 10:47         ` Sakari Ailus
  2011-05-17 10:51           ` Laurent Pinchart
  0 siblings, 1 reply; 22+ messages in thread
From: Sakari Ailus @ 2011-05-17 10:47 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

Laurent Pinchart wrote:
> Hi Sakari,

Hi Laurent,

> On Tuesday 17 May 2011 07:38:38 Sakari Ailus wrote:
[clip]
>>>
>>> If several applications read controls, only one of them will be notified
>>> of faults. Shouldn't clearing the fault be handled explicitly by writing
>>> to a control ? I know this changes the API :-)
>>
>> This is true.
>>
>> Although I can't imagine right now why two separate processes should be
>> so interested in the faults but it is still entirely possible that
>> someone does that since it's permitted by the interface.
>>
>> Having to write zero to faults to clear them isn't good either since it
>> might mean missing faults that are triggered between reading and writing
>> this control.
>>
>> Perhaps this would make sense as a file handle specific control?
> 
> Good question. Control events will help I guess, maybe that's the solution.

They would help, yes, but in the case of N900 we don't have that luxury
since there's no interrupt line from the adp1653 to OMAP. So if one user
would read the control, the others would get notified. Yes, that would
work, too.

The use case is mostly theoretical and that's actually best the hardware
can offer, so I think this is good. No special arrangements needed then.

So reading the value will reset the faults?

>> The control documentation says that the faults are cleared when the
>> register is read, but the adp1653 also clears the faults whenever
>> writing zero to out_sel which happens also in other circumstances, for
>> example when changing mode from flash to torch when the torch intensity
>> is zero, or when indicator intensity is zero in other modes.
>>
>>>> +	/* Restore configuration. */
>>>> +	rval = adp1653_update_hw(flash);
>>>> +	if (IS_ERR_VALUE(rval))
>>>> +		return rval;
>>>
>>> Will that produce expected results ? For instance, if a fault was
>>> detected during flash strobe, won't it try to re-strobe the flash ?
>>> Shouldn't the user
>>
>> No. Flash is strobed using adp1653_strobe().
>>
>>> be required to explicitly re-strobe the flash or turn the torch (or
>>> indicator) on after a fault ? Once again this should be clarified in the
>>> API :-)
>>
>> The mode won't be changed from the flash but to strobe again, the user
>> has to push V4L2_CID_FLASH_STROBE again.
>>
>> The adp1653 doesn't have any torch (as such) or indicator faults; some
>> other chips do have indicator faults at least. Using the torch mode
>> might trigger faults, too, since it's the same LED; just the power isn't
>> that high.
> 
> When an over-current fault is detected, shouldn't the mode be set back to none 
> ? If we just clear the fault and reprogram the registers, the torch will be 
> turned back on, and the fault will likely happen again.

That's a good point.

Over-temperature, over-voltage, and short circuit faults should change
the LED mode to be set to none. This is likely chip independent
behaviour but on the other hand, not all the chips implement all the faults.

Regards,

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com

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

* Re: [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-05-17  5:38     ` Sakari Ailus
@ 2011-05-17  7:23       ` Laurent Pinchart
  2011-05-17 10:47         ` Sakari Ailus
  0 siblings, 1 reply; 22+ messages in thread
From: Laurent Pinchart @ 2011-05-17  7:23 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

Hi Sakari,

On Tuesday 17 May 2011 07:38:38 Sakari Ailus wrote:
> Laurent Pinchart wrote:
> > On Monday 16 May 2011 15:00:39 Sakari Ailus wrote:
> >> This patch adds the driver for the adp1653 LED flash controller. This
> >> controller supports a high power led in flash and torch modes and an
> >> indicator light, sometimes also called privacy light.
> >> 
> >> The adp1653 is used on the Nokia N900.
> >> 
> >> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
> >> Signed-off-by: Tuukka Toivonen <tuukkat76@gmail.com>
> >> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >> Signed-off-by: David Cohen <dacohen@gmail.com>
> > 
> > [snip]
> > 
> >> diff --git a/drivers/media/video/adp1653.c
> >> b/drivers/media/video/adp1653.c new file mode 100644
> >> index 0000000..92ea38b
> >> --- /dev/null
> >> +++ b/drivers/media/video/adp1653.c
> > 
> > [snip]
> > 
> >> +/* Write values into ADP1653 registers. */
> >> +static int adp1653_update_hw(struct adp1653_flash *flash)
> >> +{
> >> +	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
> >> +	u8 out_sel;
> >> +	u8 config = 0;
> >> +	int rval;
> >> +
> >> +	out_sel = flash->indicator_intensity->val
> >> +		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
> >> +
> >> +	switch (flash->led_mode->val) {
> >> +	case V4L2_FLASH_LED_MODE_NONE:
> >> +		break;
> >> +	case V4L2_FLASH_LED_MODE_FLASH:
> >> +		/* Flash mode, light on with strobe, duration from timer */
> >> +		config = ADP1653_REG_CONFIG_TMR_CFG;
> >> +		config |= TIMEOUT_US_TO_CODE(flash->flash_timeout->val)
> >> +			  << ADP1653_REG_CONFIG_TMR_SET_SHIFT;
> >> +		break;
> >> +	case V4L2_FLASH_LED_MODE_TORCH:
> >> +		/* Torch mode, light immediately on, duration indefinite */
> >> +		out_sel |= flash->torch_intensity->val
> >> +			   << ADP1653_REG_OUT_SEL_HPLED_SHIFT;
> >> +		break;
> >> +	}
> >> +
> >> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL,
> >> out_sel);
> > 
> > out_sel can be used uninitialized here.
> 
> I don't think so. It's assigned a value in the beginning of the function.

My bad, I missed that. Sorry.

> >> +	if (rval < 0)
> >> +		return rval;
> >> +
> >> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_CONFIG, config);
> >> +	if (rval < 0)
> >> +		return rval;
> >> +
> >> +	return 0;
> >> +}
> > 
> > [snip]
> > 
> >> +static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
> >> +{
> >> +	struct adp1653_flash *flash =
> >> +		container_of(ctrl->handler, struct adp1653_flash, ctrls);
> >> +	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
> >> +	int fault;
> >> +	int rval;
> >> +
> >> +	fault = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
> >> +	if (IS_ERR_VALUE(fault))
> >> +		return fault;
> >> +
> >> +	/* Clear faults. */
> >> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
> >> +	if (IS_ERR_VALUE(rval))
> >> +		return rval;
> > 
> > If several applications read controls, only one of them will be notified
> > of faults. Shouldn't clearing the fault be handled explicitly by writing
> > to a control ? I know this changes the API :-)
> 
> This is true.
> 
> Although I can't imagine right now why two separate processes should be
> so interested in the faults but it is still entirely possible that
> someone does that since it's permitted by the interface.
> 
> Having to write zero to faults to clear them isn't good either since it
> might mean missing faults that are triggered between reading and writing
> this control.
> 
> Perhaps this would make sense as a file handle specific control?

Good question. Control events will help I guess, maybe that's the solution.

> The control documentation says that the faults are cleared when the
> register is read, but the adp1653 also clears the faults whenever
> writing zero to out_sel which happens also in other circumstances, for
> example when changing mode from flash to torch when the torch intensity
> is zero, or when indicator intensity is zero in other modes.
> 
> >> +	/* Restore configuration. */
> >> +	rval = adp1653_update_hw(flash);
> >> +	if (IS_ERR_VALUE(rval))
> >> +		return rval;
> > 
> > Will that produce expected results ? For instance, if a fault was
> > detected during flash strobe, won't it try to re-strobe the flash ?
> > Shouldn't the user
> 
> No. Flash is strobed using adp1653_strobe().
> 
> > be required to explicitly re-strobe the flash or turn the torch (or
> > indicator) on after a fault ? Once again this should be clarified in the
> > API :-)
> 
> The mode won't be changed from the flash but to strobe again, the user
> has to push V4L2_CID_FLASH_STROBE again.
> 
> The adp1653 doesn't have any torch (as such) or indicator faults; some
> other chips do have indicator faults at least. Using the torch mode
> might trigger faults, too, since it's the same LED; just the power isn't
> that high.

When an over-current fault is detected, shouldn't the mode be set back to none 
? If we just clear the fault and reprogram the registers, the torch will be 
turned back on, and the fault will likely happen again.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-05-16 20:31   ` Laurent Pinchart
@ 2011-05-17  5:38     ` Sakari Ailus
  2011-05-17  7:23       ` Laurent Pinchart
  0 siblings, 1 reply; 22+ messages in thread
From: Sakari Ailus @ 2011-05-17  5:38 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thanks for the patch.

Thanks for the comments! :-)

> On Monday 16 May 2011 15:00:39 Sakari Ailus wrote:
>> This patch adds the driver for the adp1653 LED flash controller. This
>> controller supports a high power led in flash and torch modes and an
>> indicator light, sometimes also called privacy light.
>>
>> The adp1653 is used on the Nokia N900.
>>
>> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
>> Signed-off-by: Tuukka Toivonen <tuukkat76@gmail.com>
>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> Signed-off-by: David Cohen <dacohen@gmail.com>
> 
> [snip]
> 
>> diff --git a/drivers/media/video/adp1653.c b/drivers/media/video/adp1653.c
>> new file mode 100644
>> index 0000000..92ea38b
>> --- /dev/null
>> +++ b/drivers/media/video/adp1653.c
> 
> [snip]
> 
>> +/* Write values into ADP1653 registers. */
>> +static int adp1653_update_hw(struct adp1653_flash *flash)
>> +{
>> +	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
>> +	u8 out_sel;
>> +	u8 config = 0;
>> +	int rval;
>> +
>> +	out_sel = flash->indicator_intensity->val
>> +		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
>> +
>> +	switch (flash->led_mode->val) {
>> +	case V4L2_FLASH_LED_MODE_NONE:
>> +		break;
>> +	case V4L2_FLASH_LED_MODE_FLASH:
>> +		/* Flash mode, light on with strobe, duration from timer */
>> +		config = ADP1653_REG_CONFIG_TMR_CFG;
>> +		config |= TIMEOUT_US_TO_CODE(flash->flash_timeout->val)
>> +			  << ADP1653_REG_CONFIG_TMR_SET_SHIFT;
>> +		break;
>> +	case V4L2_FLASH_LED_MODE_TORCH:
>> +		/* Torch mode, light immediately on, duration indefinite */
>> +		out_sel |= flash->torch_intensity->val
>> +			   << ADP1653_REG_OUT_SEL_HPLED_SHIFT;
>> +		break;
>> +	}
>> +
>> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
> 
> out_sel can be used uninitialized here.

I don't think so. It's assigned a value in the beginning of the function.

>> +	if (rval < 0)
>> +		return rval;
>> +
>> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_CONFIG, config);
>> +	if (rval < 0)
>> +		return rval;
>> +
>> +	return 0;
>> +}
> 
> [snip]
> 
>> +static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
>> +{
>> +	struct adp1653_flash *flash =
>> +		container_of(ctrl->handler, struct adp1653_flash, ctrls);
>> +	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
>> +	int fault;
>> +	int rval;
>> +
>> +	fault = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
>> +	if (IS_ERR_VALUE(fault))
>> +		return fault;
>> +
>> +	/* Clear faults. */
>> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
>> +	if (IS_ERR_VALUE(rval))
>> +		return rval;
> 
> If several applications read controls, only one of them will be notified of 
> faults. Shouldn't clearing the fault be handled explicitly by writing to a 
> control ? I know this changes the API :-)

This is true.

Although I can't imagine right now why two separate processes should be
so interested in the faults but it is still entirely possible that
someone does that since it's permitted by the interface.

Having to write zero to faults to clear them isn't good either since it
might mean missing faults that are triggered between reading and writing
this control.

Perhaps this would make sense as a file handle specific control?

The control documentation says that the faults are cleared when the
register is read, but the adp1653 also clears the faults whenever
writing zero to out_sel which happens also in other circumstances, for
example when changing mode from flash to torch when the torch intensity
is zero, or when indicator intensity is zero in other modes.

>> +	/* Restore configuration. */
>> +	rval = adp1653_update_hw(flash);
>> +	if (IS_ERR_VALUE(rval))
>> +		return rval;
> 
> Will that produce expected results ? For instance, if a fault was detected 
> during flash strobe, won't it try to re-strobe the flash ? Shouldn't the user 

No. Flash is strobed using adp1653_strobe().

> be required to explicitly re-strobe the flash or turn the torch (or indicator) 
> on after a fault ? Once again this should be clarified in the API :-)

The mode won't be changed from the flash but to strobe again, the user
has to push V4L2_CID_FLASH_STROBE again.

The adp1653 doesn't have any torch (as such) or indicator faults; some
other chips do have indicator faults at least. Using the torch mode
might trigger faults, too, since it's the same LED; just the power isn't
that high.

>> +	ctrl->cur.val = 0;
>> +
>> +	if (fault & ADP1653_REG_FAULT_FLT_SCP)
>> +		ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
>> +	if (fault & ADP1653_REG_FAULT_FLT_OT)
>> +		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
>> +	if (fault & ADP1653_REG_FAULT_FLT_TMR)
>> +		ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
>> +	if (fault & ADP1653_REG_FAULT_FLT_OV)
>> +		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
>> +
>> +	return 0;
>> +}
> 
> [snip]
> 
>> +static int
>> +adp1653_init_device(struct adp1653_flash *flash)
>> +{
>> +	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
>> +	int rval;
>> +
>> +	/* Clear FAULT register by writing zero to OUT_SEL */
>> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
>> +	if (rval < 0) {
>> +		dev_err(&client->dev, "failed writing fault register\n");
>> +		return -EIO;
>> +	}
>> +
>> +	/* Read FAULT register */
>> +	rval = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
>> +	if (rval < 0) {
>> +		dev_err(&client->dev, "failed reading fault register\n");
>> +		return -EIO;
>> +	}
>> +
>> +	if ((rval & 0x0f) != 0) {
>> +		dev_err(&client->dev, "device fault\n");
> 
> You could print the fault value, that could help debugging problems.

I'll change that.

>> +		return -EIO;
>> +	}
>> +
>> +	mutex_lock(&flash->ctrls.lock);
>> +	rval = adp1653_update_hw(flash);
>> +	mutex_unlock(&flash->ctrls.lock);
>> +	if (rval) {
>> +		dev_err(&client->dev,
>> +			"adp1653_update_hw failed at %s\n", __func__);
>> +		return -EIO;
>> +	}
>> +
>> +	return 0;
>> +}
> 
> [snip]
> 

Regards,

-- 
Sakari Ailus
sakari.ailus@maxwell.research.nokia.com

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

* Re: [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-05-16 13:00 ` [PATCH 3/3] adp1653: Add driver for LED flash controller Sakari Ailus
@ 2011-05-16 20:31   ` Laurent Pinchart
  2011-05-17  5:38     ` Sakari Ailus
  2011-06-09 15:10   ` Laurent Pinchart
  1 sibling, 1 reply; 22+ messages in thread
From: Laurent Pinchart @ 2011-05-16 20:31 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

Hi Sakari,

Thanks for the patch.

On Monday 16 May 2011 15:00:39 Sakari Ailus wrote:
> This patch adds the driver for the adp1653 LED flash controller. This
> controller supports a high power led in flash and torch modes and an
> indicator light, sometimes also called privacy light.
> 
> The adp1653 is used on the Nokia N900.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
> Signed-off-by: Tuukka Toivonen <tuukkat76@gmail.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: David Cohen <dacohen@gmail.com>

[snip]

> diff --git a/drivers/media/video/adp1653.c b/drivers/media/video/adp1653.c
> new file mode 100644
> index 0000000..92ea38b
> --- /dev/null
> +++ b/drivers/media/video/adp1653.c

[snip]

> +/* Write values into ADP1653 registers. */
> +static int adp1653_update_hw(struct adp1653_flash *flash)
> +{
> +	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
> +	u8 out_sel;
> +	u8 config = 0;
> +	int rval;
> +
> +	out_sel = flash->indicator_intensity->val
> +		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
> +
> +	switch (flash->led_mode->val) {
> +	case V4L2_FLASH_LED_MODE_NONE:
> +		break;
> +	case V4L2_FLASH_LED_MODE_FLASH:
> +		/* Flash mode, light on with strobe, duration from timer */
> +		config = ADP1653_REG_CONFIG_TMR_CFG;
> +		config |= TIMEOUT_US_TO_CODE(flash->flash_timeout->val)
> +			  << ADP1653_REG_CONFIG_TMR_SET_SHIFT;
> +		break;
> +	case V4L2_FLASH_LED_MODE_TORCH:
> +		/* Torch mode, light immediately on, duration indefinite */
> +		out_sel |= flash->torch_intensity->val
> +			   << ADP1653_REG_OUT_SEL_HPLED_SHIFT;
> +		break;
> +	}
> +
> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);

out_sel can be used uninitialized here.

> +	if (rval < 0)
> +		return rval;
> +
> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_CONFIG, config);
> +	if (rval < 0)
> +		return rval;
> +
> +	return 0;
> +}

[snip]

> +static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct adp1653_flash *flash =
> +		container_of(ctrl->handler, struct adp1653_flash, ctrls);
> +	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
> +	int fault;
> +	int rval;
> +
> +	fault = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
> +	if (IS_ERR_VALUE(fault))
> +		return fault;
> +
> +	/* Clear faults. */
> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
> +	if (IS_ERR_VALUE(rval))
> +		return rval;

If several applications read controls, only one of them will be notified of 
faults. Shouldn't clearing the fault be handled explicitly by writing to a 
control ? I know this changes the API :-)

> +	/* Restore configuration. */
> +	rval = adp1653_update_hw(flash);
> +	if (IS_ERR_VALUE(rval))
> +		return rval;

Will that produce expected results ? For instance, if a fault was detected 
during flash strobe, won't it try to re-strobe the flash ? Shouldn't the user 
be required to explicitly re-strobe the flash or turn the torch (or indicator) 
on after a fault ? Once again this should be clarified in the API :-)

> +	ctrl->cur.val = 0;
> +
> +	if (fault & ADP1653_REG_FAULT_FLT_SCP)
> +		ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
> +	if (fault & ADP1653_REG_FAULT_FLT_OT)
> +		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
> +	if (fault & ADP1653_REG_FAULT_FLT_TMR)
> +		ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
> +	if (fault & ADP1653_REG_FAULT_FLT_OV)
> +		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
> +
> +	return 0;
> +}

[snip]

> +static int
> +adp1653_init_device(struct adp1653_flash *flash)
> +{
> +	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
> +	int rval;
> +
> +	/* Clear FAULT register by writing zero to OUT_SEL */
> +	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
> +	if (rval < 0) {
> +		dev_err(&client->dev, "failed writing fault register\n");
> +		return -EIO;
> +	}
> +
> +	/* Read FAULT register */
> +	rval = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
> +	if (rval < 0) {
> +		dev_err(&client->dev, "failed reading fault register\n");
> +		return -EIO;
> +	}
> +
> +	if ((rval & 0x0f) != 0) {
> +		dev_err(&client->dev, "device fault\n");

You could print the fault value, that could help debugging problems.

> +		return -EIO;
> +	}
> +
> +	mutex_lock(&flash->ctrls.lock);
> +	rval = adp1653_update_hw(flash);
> +	mutex_unlock(&flash->ctrls.lock);
> +	if (rval) {
> +		dev_err(&client->dev,
> +			"adp1653_update_hw failed at %s\n", __func__);
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}

[snip]

-- 
Regards,

Laurent Pinchart

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

* [PATCH 3/3] adp1653: Add driver for LED flash controller
  2011-05-16 13:00 [RFC 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Sakari Ailus
@ 2011-05-16 13:00 ` Sakari Ailus
  2011-05-16 20:31   ` Laurent Pinchart
  2011-06-09 15:10   ` Laurent Pinchart
  0 siblings, 2 replies; 22+ messages in thread
From: Sakari Ailus @ 2011-05-16 13:00 UTC (permalink / raw)
  To: linux-media
  Cc: laurent.pinchart, nkanchev, g.liakhovetski, hverkuil, dacohen,
	riverful, andrew.b.adams, shpark7

This patch adds the driver for the adp1653 LED flash controller. This
controller supports a high power led in flash and torch modes and an
indicator light, sometimes also called privacy light.

The adp1653 is used on the Nokia N900.

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
Signed-off-by: Tuukka Toivonen <tuukkat76@gmail.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: David Cohen <dacohen@gmail.com>
---
 drivers/media/video/Kconfig   |    7 +
 drivers/media/video/Makefile  |    2 +
 drivers/media/video/adp1653.c |  453 +++++++++++++++++++++++++++++++++++++++++
 include/media/adp1653.h       |   94 +++++++++
 4 files changed, 556 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/adp1653.c
 create mode 100644 include/media/adp1653.h

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 00f51dd..c004dbb 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -344,6 +344,13 @@ config VIDEO_TCM825X
 	  This is a driver for the Toshiba TCM825x VGA camera sensor.
 	  It is used for example in Nokia N800.
 
+config VIDEO_ADP1653
+	tristate "ADP1653 flash support"
+	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+	---help---
+	  This is a driver for the ADP1653 flash controller. It is used for
+	  example in Nokia N900.
+
 config VIDEO_SAA7110
 	tristate "Philips SAA7110 video decoder"
 	depends on VIDEO_V4L2 && I2C
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index ace5d8b..abdf021 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -131,6 +131,8 @@ obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
 
 obj-$(CONFIG_VIDEO_OMAP3)	+= omap3isp/
 
+obj-$(CONFIG_VIDEO_ADP1653)	+= adp1653.o
+
 obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
 obj-$(CONFIG_USB_STKWEBCAM)     += stkwebcam.o
 
diff --git a/drivers/media/video/adp1653.c b/drivers/media/video/adp1653.c
new file mode 100644
index 0000000..92ea38b
--- /dev/null
+++ b/drivers/media/video/adp1653.c
@@ -0,0 +1,453 @@
+/*
+ * drivers/media/video/adp1653.c
+ *
+ * Copyright (C) 2008--2011 Nokia Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * Contributors:
+ *	Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *	Tuukka Toivonen <tuukkat76@gmail.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * TODO:
+ * - fault interrupt handling
+ * - faster strobe (use i/o pin instead of i2c)
+ *   - should ensure that the pin is in some sane state even if not used
+ * - power doesn't need to be ON if all lights are off
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <media/adp1653.h>
+#include <media/v4l2-device.h>
+
+#define TIMEOUT_MAX		820000
+#define TIMEOUT_STEP		54600
+#define TIMEOUT_MIN		(TIMEOUT_MAX - ADP1653_REG_CONFIG_TMR_SET_MAX \
+				 * TIMEOUT_STEP)
+#define TIMEOUT_US_TO_CODE(t)	((TIMEOUT_MAX + (TIMEOUT_STEP / 2) - (t)) \
+				 / TIMEOUT_STEP)
+#define TIMEOUT_CODE_TO_US(c)	(TIMEOUT_MAX - (c) * TIMEOUT_STEP)
+
+/* Write values into ADP1653 registers. */
+static int adp1653_update_hw(struct adp1653_flash *flash)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	u8 out_sel;
+	u8 config = 0;
+	int rval;
+
+	out_sel = flash->indicator_intensity->val
+		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
+
+	switch (flash->led_mode->val) {
+	case V4L2_FLASH_LED_MODE_NONE:
+		break;
+	case V4L2_FLASH_LED_MODE_FLASH:
+		/* Flash mode, light on with strobe, duration from timer */
+		config = ADP1653_REG_CONFIG_TMR_CFG;
+		config |= TIMEOUT_US_TO_CODE(flash->flash_timeout->val)
+			  << ADP1653_REG_CONFIG_TMR_SET_SHIFT;
+		break;
+	case V4L2_FLASH_LED_MODE_TORCH:
+		/* Torch mode, light immediately on, duration indefinite */
+		out_sel |= flash->torch_intensity->val
+			   << ADP1653_REG_OUT_SEL_HPLED_SHIFT;
+		break;
+	}
+
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
+	if (rval < 0)
+		return rval;
+
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_CONFIG, config);
+	if (rval < 0)
+		return rval;
+
+	return 0;
+}
+
+static int adp1653_strobe(struct adp1653_flash *flash, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	u8 out_sel = flash->indicator_intensity->val
+		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
+	int rval;
+
+	if (flash->led_mode->val != V4L2_FLASH_LED_MODE_FLASH)
+		return -EBUSY;
+
+	if (!enable)
+		return i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL,
+						 out_sel);
+
+	out_sel |= flash->flash_intensity->val
+		<< ADP1653_REG_OUT_SEL_HPLED_SHIFT;
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
+	if (rval)
+		return rval;
+
+	/* Software strobe using i2c */
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE,
+		ADP1653_REG_SW_STROBE_SW_STROBE);
+	if (rval)
+		return rval;
+	return i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE, 0);
+}
+
+/* --------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct adp1653_flash *flash =
+		container_of(ctrl->handler, struct adp1653_flash, ctrls);
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int fault;
+	int rval;
+
+	fault = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
+	if (IS_ERR_VALUE(fault))
+		return fault;
+
+	/* Clear faults. */
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
+	if (IS_ERR_VALUE(rval))
+		return rval;
+
+	/* Restore configuration. */
+	rval = adp1653_update_hw(flash);
+	if (IS_ERR_VALUE(rval))
+		return rval;
+
+	ctrl->cur.val = 0;
+
+	if (fault & ADP1653_REG_FAULT_FLT_SCP)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
+	if (fault & ADP1653_REG_FAULT_FLT_OT)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
+	if (fault & ADP1653_REG_FAULT_FLT_TMR)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
+	if (fault & ADP1653_REG_FAULT_FLT_OV)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
+
+	return 0;
+}
+
+static int adp1653_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct adp1653_flash *flash =
+		container_of(ctrl->handler, struct adp1653_flash, ctrls);
+
+	switch (ctrl->id) {
+	case V4L2_CID_FLASH_STROBE:
+		return adp1653_strobe(flash, 1);
+	case V4L2_CID_FLASH_STROBE_STOP:
+		return adp1653_strobe(flash, 0);
+	}
+
+	return adp1653_update_hw(flash);
+}
+
+static const struct v4l2_ctrl_ops adp1653_ctrl_ops = {
+	.g_volatile_ctrl = adp1653_get_ctrl,
+	.s_ctrl = adp1653_set_ctrl,
+};
+
+static int adp1653_init_controls(struct adp1653_flash *flash)
+{
+	v4l2_ctrl_handler_init(&flash->ctrls, 9);
+
+	flash->led_mode =
+		v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
+				       V4L2_CID_FLASH_LED_MODE,
+				       V4L2_FLASH_LED_MODE_TORCH, ~0x7, 0);
+	v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
+			       V4L2_CID_FLASH_STROBE_SOURCE,
+			       V4L2_FLASH_STROBE_SOURCE_SOFTWARE, ~0x1, 0);
+	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+			  V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
+	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+			  V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
+	flash->flash_timeout =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_TIMEOUT, TIMEOUT_MIN,
+				  flash->platform_data->max_flash_timeout,
+				  TIMEOUT_STEP,
+				  flash->platform_data->max_flash_timeout);
+	flash->flash_intensity =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_INTENSITY,
+				  ADP1653_FLASH_INTENSITY_MIN,
+				  flash->platform_data->max_flash_intensity,
+				  1, flash->platform_data->max_flash_intensity);
+	flash->torch_intensity =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_TORCH_INTENSITY,
+				  ADP1653_TORCH_INTENSITY_MIN,
+				  flash->platform_data->max_torch_intensity,
+				  1, flash->platform_data->max_torch_intensity);
+	flash->indicator_intensity =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_INDICATOR_INTENSITY,
+				  ADP1653_INDICATOR_INTENSITY_MIN,
+				  flash->platform_data->max_indicator_intensity,
+				  1, ADP1653_INDICATOR_INTENSITY_MIN);
+	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+			  V4L2_CID_FLASH_FAULT, 0, V4L2_FLASH_FAULT_OVER_VOLTAGE
+			  | V4L2_FLASH_FAULT_OVER_TEMPERATURE
+			  | V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
+
+	if (flash->ctrls.error)
+		return flash->ctrls.error;
+
+	flash->subdev.ctrl_handler = &flash->ctrls;
+	return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static int
+adp1653_registered(struct v4l2_subdev *subdev)
+{
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+	return adp1653_init_controls(flash);
+}
+
+static int
+adp1653_init_device(struct adp1653_flash *flash)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int rval;
+
+	/* Clear FAULT register by writing zero to OUT_SEL */
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
+	if (rval < 0) {
+		dev_err(&client->dev, "failed writing fault register\n");
+		return -EIO;
+	}
+
+	/* Read FAULT register */
+	rval = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
+	if (rval < 0) {
+		dev_err(&client->dev, "failed reading fault register\n");
+		return -EIO;
+	}
+
+	if ((rval & 0x0f) != 0) {
+		dev_err(&client->dev, "device fault\n");
+		return -EIO;
+	}
+
+	mutex_lock(&flash->ctrls.lock);
+	rval = adp1653_update_hw(flash);
+	mutex_unlock(&flash->ctrls.lock);
+	if (rval) {
+		dev_err(&client->dev,
+			"adp1653_update_hw failed at %s\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int
+__adp1653_set_power(struct adp1653_flash *flash, int on)
+{
+	int ret;
+
+	ret = flash->platform_data->power(&flash->subdev, on);
+	if (ret < 0)
+		return ret;
+
+	if (!on)
+		return 0;
+
+	ret = adp1653_init_device(flash);
+	if (ret < 0)
+		flash->platform_data->power(&flash->subdev, 0);
+
+	return ret;
+}
+
+static int
+adp1653_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+	int ret = 0;
+
+	mutex_lock(&flash->power_lock);
+
+	/* If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (flash->power_count == !on) {
+		ret = __adp1653_set_power(flash, !!on);
+		if (ret < 0)
+			goto done;
+	}
+
+	/* Update the power count. */
+	flash->power_count += on ? 1 : -1;
+	WARN_ON(flash->power_count < 0);
+
+done:
+	mutex_unlock(&flash->power_lock);
+	return ret;
+}
+
+static int adp1653_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return adp1653_set_power(sd, 1);
+}
+
+static int adp1653_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return adp1653_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops adp1653_core_ops = {
+	.s_power = adp1653_set_power,
+};
+
+static const struct v4l2_subdev_ops adp1653_ops = {
+	.core = &adp1653_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops adp1653_internal_ops = {
+	.registered = adp1653_registered,
+	.open = adp1653_open,
+	.close = adp1653_close,
+};
+
+/* --------------------------------------------------------------------------
+ * I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int adp1653_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+	if (!flash->power_count)
+		return 0;
+
+	return __adp1653_set_power(flash, 0);
+}
+
+static int adp1653_resume(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+	if (!flash->power_count)
+		return 0;
+
+	return __adp1653_set_power(flash, 1);
+}
+
+#else
+
+#define adp1653_suspend	NULL
+#define adp1653_resume	NULL
+
+#endif /* CONFIG_PM */
+
+static int adp1653_probe(struct i2c_client *client,
+			 const struct i2c_device_id *devid)
+{
+	struct adp1653_flash *flash;
+	int ret;
+
+	flash = kzalloc(sizeof(*flash), GFP_KERNEL);
+	if (flash == NULL)
+		return -ENOMEM;
+
+	flash->platform_data = client->dev.platform_data;
+
+	mutex_init(&flash->power_lock);
+
+	v4l2_i2c_subdev_init(&flash->subdev, client, &adp1653_ops);
+	flash->subdev.internal_ops = &adp1653_internal_ops;
+	flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
+	if (ret < 0)
+		kfree(flash);
+
+	return ret;
+}
+
+static int __exit adp1653_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+	v4l2_device_unregister_subdev(&flash->subdev);
+	v4l2_ctrl_handler_free(&flash->ctrls);
+	media_entity_cleanup(&flash->subdev.entity);
+	kfree(flash);
+	return 0;
+}
+
+static const struct i2c_device_id adp1653_id_table[] = {
+	{ ADP1653_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adp1653_id_table);
+
+static struct i2c_driver adp1653_i2c_driver = {
+	.driver		= {
+		.name	= ADP1653_NAME,
+	},
+	.probe		= adp1653_probe,
+	.remove		= __exit_p(adp1653_remove),
+	.suspend	= adp1653_suspend,
+	.resume		= adp1653_resume,
+	.id_table	= adp1653_id_table,
+};
+
+static int __init adp1653_init(void)
+{
+	int rval;
+
+	rval = i2c_add_driver(&adp1653_i2c_driver);
+	if (rval)
+		printk(KERN_ALERT "%s: failed at i2c_add_driver\n", __func__);
+
+	return rval;
+}
+
+static void __exit adp1653_exit(void)
+{
+	i2c_del_driver(&adp1653_i2c_driver);
+}
+
+module_init(adp1653_init);
+module_exit(adp1653_exit);
+
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
+MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver");
+MODULE_LICENSE("GPL");
diff --git a/include/media/adp1653.h b/include/media/adp1653.h
new file mode 100644
index 0000000..1da9964
--- /dev/null
+++ b/include/media/adp1653.h
@@ -0,0 +1,94 @@
+/*
+ * include/media/adp1653.h
+ *
+ * Copyright (C) 2008--2011 Nokia Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * Contributors:
+ *	Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *	Tuukka Toivonen <tuukkat76@gmail.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef ADP1653_H
+#define ADP1653_H
+
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#define ADP1653_NAME				"adp1653"
+#define ADP1653_I2C_ADDR			(0x60 >> 1)
+
+/* Register definitions */
+#define ADP1653_REG_OUT_SEL			0x00
+#define ADP1653_REG_OUT_SEL_HPLED_MAX		0x1f
+#define ADP1653_REG_OUT_SEL_HPLED_SHIFT		3
+#define ADP1653_REG_OUT_SEL_ILED_MAX		0x07
+#define ADP1653_REG_OUT_SEL_ILED_SHIFT		0
+
+#define ADP1653_REG_CONFIG			0x01
+#define ADP1653_REG_CONFIG_TMR_CFG		(1 << 4)
+#define ADP1653_REG_CONFIG_TMR_SET_MAX		0x0f
+#define ADP1653_REG_CONFIG_TMR_SET_SHIFT	0
+
+#define ADP1653_REG_SW_STROBE			0x02
+#define ADP1653_REG_SW_STROBE_SW_STROBE		(1 << 0)
+
+#define ADP1653_REG_FAULT			0x03
+#define ADP1653_REG_FAULT_FLT_SCP		(1 << 3)
+#define ADP1653_REG_FAULT_FLT_OT		(1 << 2)
+#define ADP1653_REG_FAULT_FLT_TMR		(1 << 1)
+#define ADP1653_REG_FAULT_FLT_OV		(1 << 0)
+
+#define ADP1653_INDICATOR_INTENSITY_MIN		0
+#define ADP1653_INDICATOR_INTENSITY_MAX		ADP1653_REG_OUT_SEL_ILED_MAX
+#define ADP1653_TORCH_INTENSITY_MIN		0
+#define ADP1653_TORCH_INTENSITY_MAX		11
+#define ADP1653_FLASH_INTENSITY_MIN		12
+#define ADP1653_FLASH_INTENSITY_MAX		ADP1653_REG_OUT_SEL_HPLED_MAX
+
+struct adp1653_platform_data {
+	int (*power)(struct v4l2_subdev *sd, int on);
+
+	u32 max_flash_timeout;		/* flash light timeout in us */
+	u32 max_flash_intensity;	/* led intensity, flash mode */
+	u32 max_torch_intensity;	/* led intensity, torch mode */
+	u32 max_indicator_intensity;	/* indicator led intensity */
+};
+
+#define to_adp1653_flash(sd)	container_of(sd, struct adp1653_flash, subdev)
+
+struct adp1653_flash {
+	struct v4l2_subdev subdev;
+	struct adp1653_platform_data *platform_data;
+
+	struct v4l2_ctrl_handler ctrls;
+	struct v4l2_ctrl *led_mode;
+	struct v4l2_ctrl *flash_timeout;
+	struct v4l2_ctrl *flash_intensity;
+	struct v4l2_ctrl *torch_intensity;
+	struct v4l2_ctrl *indicator_intensity;
+
+	struct mutex power_lock;
+	int power_count;
+};
+
+#endif /* ADP1653_H */
-- 
1.7.2.5


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

end of thread, other threads:[~2011-07-26  9:47 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-19 10:41 [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Sakari Ailus
2011-05-19 10:41 ` [PATCH 1/3] v4l: Add a class and a set of controls for flash devices Sakari Ailus
2011-05-19 10:41 ` [PATCH 2/3] v4l: Add flash control documentation Sakari Ailus
2011-05-19 10:41 ` [PATCH 3/3] adp1653: Add driver for LED flash controller Sakari Ailus
2011-05-21 11:57   ` Mauro Carvalho Chehab
2011-05-22 12:39     ` Sakari Ailus
2011-05-19 12:14 ` [PATCH 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Laurent Pinchart
2011-05-19 14:22   ` David Cohen
2011-05-19 14:24     ` Laurent Pinchart
2011-06-30 10:55 ` v4l2 api for flash drivers Andy Shevchenko
2011-06-30 11:06   ` Laurent Pinchart
2011-06-30 11:26     ` Sakari Ailus
2011-07-26  9:12       ` Andy Shevchenko
2011-07-26  9:47         ` Sakari Ailus
  -- strict thread matches above, loose matches on Subject: below --
2011-05-16 13:00 [RFC 0/3] V4L2 API for flash devices and the adp1653 flash controller driver Sakari Ailus
2011-05-16 13:00 ` [PATCH 3/3] adp1653: Add driver for LED flash controller Sakari Ailus
2011-05-16 20:31   ` Laurent Pinchart
2011-05-17  5:38     ` Sakari Ailus
2011-05-17  7:23       ` Laurent Pinchart
2011-05-17 10:47         ` Sakari Ailus
2011-05-17 10:51           ` Laurent Pinchart
2011-06-09 15:10   ` Laurent Pinchart
2011-06-10  8:20     ` Sakari Ailus

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.