All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH/RFC v11 00/20] LED / flash API integration
@ 2015-02-18 16:20 Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 01/20] leds: flash: document sysfs interface Jacek Anaszewski
                   ` (19 more replies)
  0 siblings, 20 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

This patch set is a follow-up of the LED / flash API integration
series [1]. It is based on linux-next_20150218.

========================
Changes since version 10 :
========================

- added to the v4l2-flash sub-device driver the support for flash
  LED devices with non-linear brightness setting
- improved current setting in the max77693-led driver 
- added ABI documentation for flash LED sysfs attributes
- improved synchronized LEDs related sysfs attributes in the
  LED Flash class
- applied various fixes and cleanups

========================
Changes since version 9 :
========================

- switched to assigning sub-led related of_node to led_cdev->dev->of_node
  member which allowed for avoiding modifications around v4l-async
- reimplemented max77693 flash cell driver to avoid extensive use
  of macros
- added led-sources DT property and switched to using it
- switched to reporting flash faults in the LED subsystem in the form
  of human readable strings
- added available_sync_leds sysfs attribute to the LED Flash class
  and changed the semantics of flash_sync_strobe attribute
- made LED subsystem flash faults not depending on the V4L2 Flash ones
- applied various fixes and cleanups

========================
Changes since version 8:
========================

- added a new way of registering async sub-device
- switched to matching flash leds by DT phandles
- improved Device Tree bindings documentation
- split the drivers patches to LED Flash class
  and V4L2 Flash part
- fixed indicator leds handling in v4l2-flash
- applied various fixes an cleanups

========================
Changes since version 7:
========================

- removed explicit support for indicator leds from
  LED Flash class - indicator leds will be registered
  as a separate LED Flash class devices
- added flash_sync_strobe sysfs attribute and related
  V4L2_CID_FLASH_SYNC_STROBE control
- changed the way of matching V4L2 Flash sub-devices
  in a media device, which entailed modification in
  v4l2-async driver
- modified max77693 DT bindings documentation
- applied various fixes an cleanups

========================
Changes since version 6:
========================

- removed addition of public LED subsystem API for setting
  torch brightness in favour of internal API for
  synchronous and asynchronous led brightness level setting
- fixed possible race condition upon creating LED Flash class
  related sysfs attributes

========================
Changes since version 5:
========================

- removed flash manager framework - its implementation needs
  further thorough discussion.
- removed external strobe facilities from the LED Flash Class
  and provided external_strobe_set op in v4l2-flash. LED subsystem
  should be strobe provider agnostic.

Thanks,
Jacek Anaszewski

[1] https://lkml.org/lkml/2014/7/11/914

Jacek Anaszewski (20):
  leds: flash: document sysfs interface
  leds: flash: Improve sync strobe related sysfs attributes
  Documentation: leds: Add description of LED Flash class extension
  dt-binding: leds: Add common LED DT bindings macros
  mfd: max77693: Modify flash cell name identifiers
  mfd: max77693: Remove struct max77693_led_platform_data
  mfd: max77693: add TORCH_IOUT_MASK macro
  mfd: max77693: Adjust FLASH_EN_SHIFT and TORCH_EN_SHIFT macros
  leds: Add support for max77693 mfd flash cell
  DT: Add documentation for the mfd Maxim max77693
  leds: Add driver for AAT1290 current regulator
  of: Add Skyworks Solutions, Inc. vendor prefix
  DT: Add documentation for the Skyworks AAT1290
  exynos4-is: Add support for v4l2-flash subdevs
  v4l2-ctrls: Add V4L2_CID_FLASH_SYNC_STROBE control
  media: Add registration helpers for V4L2 flash sub-devices
  Documentation: leds: Add description of v4l2-flash sub-device
  DT: Add documentation for exynos4-is 'flashes' property
  leds: max77693: add support for V4L2 Flash sub-device
  leds: aat1290: add support for V4L2 Flash sub-device

 Documentation/ABI/testing/sysfs-class-led-flash    |  104 ++
 Documentation/DocBook/media/v4l/controls.xml       |    9 +
 .../devicetree/bindings/leds/leds-aat1290.txt      |   43 +
 .../devicetree/bindings/media/samsung-fimc.txt     |    8 +
 Documentation/devicetree/bindings/mfd/max77693.txt |   61 +
 .../devicetree/bindings/vendor-prefixes.txt        |    1 +
 Documentation/leds/leds-class-flash.txt            |   45 +
 drivers/leds/Kconfig                               |   17 +
 drivers/leds/Makefile                              |    2 +
 drivers/leds/led-class-flash.c                     |    6 +-
 drivers/leds/leds-aat1290.c                        |  570 ++++++++++
 drivers/leds/leds-max77693.c                       | 1191 ++++++++++++++++++++
 drivers/media/platform/exynos4-is/media-dev.c      |   36 +-
 drivers/media/platform/exynos4-is/media-dev.h      |   13 +-
 drivers/media/v4l2-core/Kconfig                    |   11 +
 drivers/media/v4l2-core/Makefile                   |    2 +
 drivers/media/v4l2-core/v4l2-ctrls.c               |    2 +
 drivers/media/v4l2-core/v4l2-flash.c               |  640 +++++++++++
 drivers/mfd/max77693.c                             |    4 +-
 include/dt-bindings/leds/max77693.h                |   21 +
 include/linux/mfd/max77693-private.h               |    5 +-
 include/linux/mfd/max77693.h                       |   13 -
 include/media/v4l2-flash.h                         |  146 +++
 include/uapi/linux/v4l2-controls.h                 |    1 +
 24 files changed, 2928 insertions(+), 23 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-flash
 create mode 100644 Documentation/devicetree/bindings/leds/leds-aat1290.txt
 create mode 100644 Documentation/leds/leds-class-flash.txt
 create mode 100644 drivers/leds/leds-aat1290.c
 create mode 100644 drivers/leds/leds-max77693.c
 create mode 100644 drivers/media/v4l2-core/v4l2-flash.c
 create mode 100644 include/dt-bindings/leds/max77693.h
 create mode 100644 include/media/v4l2-flash.h

-- 
1.7.9.5

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

* [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 22:47   ` 0.led_name 2.other.led.name in /sysfs " Pavel Machek
  2015-02-18 16:20 ` [PATCH/RFC v11 02/20] leds: flash: Improve sync strobe related sysfs attributes Jacek Anaszewski
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

Add a documentation of LED Flash class specific sysfs attributes.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
---
 Documentation/ABI/testing/sysfs-class-led-flash |  104 +++++++++++++++++++++++
 1 file changed, 104 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-flash

diff --git a/Documentation/ABI/testing/sysfs-class-led-flash b/Documentation/ABI/testing/sysfs-class-led-flash
new file mode 100644
index 0000000..c941d21
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-flash
@@ -0,0 +1,104 @@
+What:		/sys/class/leds/<led>/flash_brightness
+Date:		February 2015
+KernelVersion:	3.20
+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
+Description:	read/write
+		Set the brightness of this LED in the flash strobe mode, in
+		microamperes. The file is created only for the flash LED devices
+		that support setting flash brightness.
+
+		The value is between 0 and
+		/sys/class/leds/<led>/max_flash_brightness.
+
+What:		/sys/class/leds/<led>/max_flash_brightness
+Date:		February 2015
+KernelVersion:	3.20
+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
+Description:	read only
+		Maximum brightness level for this LED in the flash strobe mode,
+		in microamperes.
+
+What:		/sys/class/leds/<led>/flash_timeout
+Date:		February 2015
+KernelVersion:	3.20
+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
+Description:	read/write
+		Hardware timeout for flash, in microseconds. The flash strobe
+		is stopped after this period of time has passed from the start
+		of the strobe. The file is created only for the flash LED
+		devices that support setting flash timeout.
+
+What:		/sys/class/leds/<led>/max_flash_timeout
+Date:		February 2015
+KernelVersion:	3.20
+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
+Description:	read only
+		Maximum flash timeout for this LED, in microseconds.
+
+What:		/sys/class/leds/<led>/flash_strobe
+Date:		February 2015
+KernelVersion:	3.20
+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
+Description:	read/write
+		Flash strobe state. When written with 1 it triggers flash strobe
+		and when written with 0 it turns the flash off.
+
+		On read 1 means that flash is currently strobing and 0 means
+		that flash is off.
+
+What:		/sys/class/leds/<led>/flash_sync_strobe
+Date:		February 2015
+KernelVersion:	3.20
+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
+Description:	read/write
+		Identifier of the LED to synchronize the flash strobe with.
+		0 stands for no synchronization. Usually the LEDs available for
+		flash strobing are driven by the same flash LED device. The LEDs
+		available for flash strobe synchronization can be obtained by
+		reading the /sys/class/leds/<led>/available_sync_leds attribute.
+
+		On read the currently selected LED is displayed in the format:
+		led_id.led_name
+
+What:		/sys/class/leds/<led>/available_sync_leds
+Date:		February 2015
+KernelVersion:	3.20
+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
+Description:	read/write
+		Space separated list of LEDs available for flash strobe
+		synchronization, displayed in the format:
+
+		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
+
+What:		/sys/class/leds/<led>/flash_fault
+Date:		February 2015
+KernelVersion:	3.20
+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
+Description:	read only
+		Space separated list of flash faults that may have occurred.
+		Flash faults are re-read after strobing the flash. Possible
+		flash faults:
+
+		* led-over-voltage - flash controller voltage to the flash LED
+			has exceeded the limit specific to the flash controller
+		* flash-timeout-exceeded - the flash strobe was still on when
+			the timeout set by the user has expired; not all flash
+			controllers may set this in all such conditions
+		* controller-over-temperature - the flash controller has
+			overheated
+		* controller-short-circuit - the short circuit protection
+			of the flash controller has been triggered
+		* led-power-supply-over-current - current in the LED power
+			supply has exceeded the limit specific to the flash
+			controller
+		* indicator-led-fault - the flash controller has detected
+			a short or open circuit condition on the indicator LED
+		* led-under-voltage - flash controller voltage to the flash
+			LED has been below the minimum limit specific to
+			the flash
+		* controller-under-voltage - the input voltage of the flash
+			controller is below the limit under which strobing the
+			flash at full current will not be possible;
+			the condition persists until this flag is no longer set
+		* led-over-temperature - the temperature of the LED has exceeded
+			its allowed upper limit
-- 
1.7.9.5

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

* [PATCH/RFC v11 02/20] leds: flash: Improve sync strobe related sysfs attributes
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 01/20] leds: flash: document sysfs interface Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 03/20] Documentation: leds: Add description of LED Flash class extension Jacek Anaszewski
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

Current format of synchronized strobe related attributes introduces
problems when it comes to parsing. Avoding the usage of square brackets
and colons makes the parsing more convenient.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
---
 drivers/leds/led-class-flash.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c
index 4a19fd4..a2da52e 100644
--- a/drivers/leds/led-class-flash.c
+++ b/drivers/leds/led-class-flash.c
@@ -224,11 +224,11 @@ static ssize_t available_sync_leds_show(struct device *dev,
 	char *pbuf = buf;
 	int i, buf_len;
 
-	buf_len = sprintf(pbuf, "[0: none] ");
+	buf_len = sprintf(pbuf, "0.none ");
 	pbuf += buf_len;
 
 	for (i = 0; i < fled_cdev->num_sync_leds; ++i) {
-		buf_len = sprintf(pbuf, "[%d: %s] ", i + 1,
+		buf_len = sprintf(pbuf, "%d.%s ", i + 1,
 				  fled_cdev->sync_leds[i]->led_cdev.name);
 		pbuf += buf_len;
 	}
@@ -281,7 +281,7 @@ static ssize_t flash_sync_strobe_show(struct device *dev,
 		sync_led_name = (char *)
 			fled_cdev->sync_leds[sled_id - 1]->led_cdev.name;
 
-	return sprintf(buf, "[%d: %s]\n", sled_id, sync_led_name);
+	return sprintf(buf, "%d.%s\n", sled_id, sync_led_name);
 }
 static DEVICE_ATTR_RW(flash_sync_strobe);
 
-- 
1.7.9.5

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

* [PATCH/RFC v11 03/20] Documentation: leds: Add description of LED Flash class extension
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 01/20] leds: flash: document sysfs interface Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 02/20] leds: flash: Improve sync strobe related sysfs attributes Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 04/20] dt-binding: leds: Add common LED DT bindings macros Jacek Anaszewski
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

The documentation being added contains overall description of the
LED Flash Class and the related sysfs attributes.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
---
 Documentation/leds/leds-class-flash.txt |   32 +++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 Documentation/leds/leds-class-flash.txt

diff --git a/Documentation/leds/leds-class-flash.txt b/Documentation/leds/leds-class-flash.txt
new file mode 100644
index 0000000..ff03a66
--- /dev/null
+++ b/Documentation/leds/leds-class-flash.txt
@@ -0,0 +1,32 @@
+
+Flash LED handling under Linux
+==============================
+
+Some LED devices provide two modes - torch and flash. In the LED subsystem
+those modes are supported by LED class (see Documentation/leds/leds-class.txt)
+and LED Flash class respectively. The torch mode related features are enabled
+by default and the flash ones only if a driver declares it by setting
+LED_DEV_CAP_FLASH flag.
+
+In order to enable support for flash LEDs CONFIG_LEDS_CLASS_FLASH symbol
+must be defined in the kernel config. A flash LED driver must register
+in the LED subsystem with led_classdev_flash_register function to gain flash
+related capabilities.
+
+There are flash LED devices which can control more than one LED and allow for
+strobing the sub-LEDs synchronously. A LED will be strobed synchronously with
+the one whose identifier is written to the flash_sync_strobe sysfs attribute.
+The list of available sub-LED identifiers can be read from the available_sync_leds
+sysfs attribute. In order to enable the related settings the driver must set
+LED_DEV_CAP_SYNC_STROBE flag.
+
+Following sysfs attributes are exposed for controlling flash LED devices:
+(see Documentation/ABI/testing/sysfs-class-led-flash)
+	- flash_brightness
+	- max_flash_brightness
+	- flash_timeout
+	- max_flash_timeout
+	- flash_strobe
+	- available_sync_leds
+	- flash_sync_strobe
+	- flash_fault
-- 
1.7.9.5

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

* [PATCH/RFC v11 04/20] dt-binding: leds: Add common LED DT bindings macros
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (2 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 03/20] Documentation: leds: Add description of LED Flash class extension Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 05/20] mfd: max77693: Modify flash cell name identifiers Jacek Anaszewski
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

Add macros for defining boost mode and trigger type properties
of flash LED devices.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
---
 include/dt-bindings/leds/max77693.h |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 include/dt-bindings/leds/max77693.h

diff --git a/include/dt-bindings/leds/max77693.h b/include/dt-bindings/leds/max77693.h
new file mode 100644
index 0000000..79fcef7
--- /dev/null
+++ b/include/dt-bindings/leds/max77693.h
@@ -0,0 +1,21 @@
+/*
+ * This header provides macros for the common LEDs device tree bindings.
+ *
+ * Copyright (C) 2015, Samsung Electronics Co., Ltd.
+ *
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ */
+
+#ifndef __DT_BINDINGS_LEDS_H__
+#define __DT_BINDINGS_LEDS_H
+
+/* External trigger type */
+#define LEDS_TRIG_TYPE_EDGE	0
+#define LEDS_TRIG_TYPE_LEVEL	1
+
+/* Boost modes */
+#define LEDS_BOOST_OFF		0
+#define LEDS_BOOST_ADAPTIVE	1
+#define LEDS_BOOST_FIXED	2
+
+#endif /* __DT_BINDINGS_LEDS_H */
-- 
1.7.9.5

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

* [PATCH/RFC v11 05/20] mfd: max77693: Modify flash cell name identifiers
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (3 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 04/20] dt-binding: leds: Add common LED DT bindings macros Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-19  9:21   ` Sakari Ailus
  2015-02-18 16:20 ` [PATCH/RFC v11 06/20] mfd: max77693: Remove struct max77693_led_platform_data Jacek Anaszewski
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

Change flash cell identifiers from max77693-flash to max77693-led
to avoid confusion with NOR/NAND Flash.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/max77693.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index a159593..cb14afa 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -53,8 +53,8 @@ static const struct mfd_cell max77693_devs[] = {
 		.of_compatible = "maxim,max77693-haptic",
 	},
 	{
-		.name = "max77693-flash",
-		.of_compatible = "maxim,max77693-flash",
+		.name = "max77693-led",
+		.of_compatible = "maxim,max77693-led",
 	},
 };
 
-- 
1.7.9.5

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

* [PATCH/RFC v11 06/20] mfd: max77693: Remove struct max77693_led_platform_data
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (4 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 05/20] mfd: max77693: Modify flash cell name identifiers Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 07/20] mfd: max77693: add TORCH_IOUT_MASK macro Jacek Anaszewski
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski, Chanwoo Choi, Lee Jones

The flash part of the max77693 device will depend only on OF, and thus
will not use board files. Since there are no other users of the
struct max77693_led_platform_data its existence is unjustified.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Chanwoo Choi <cw00.choi@samsung.com>
Cc: Lee Jones <lee.jones@linaro.org>
---
 include/linux/mfd/max77693.h |   13 -------------
 1 file changed, 13 deletions(-)

diff --git a/include/linux/mfd/max77693.h b/include/linux/mfd/max77693.h
index f0b6585..ce894b6 100644
--- a/include/linux/mfd/max77693.h
+++ b/include/linux/mfd/max77693.h
@@ -87,19 +87,6 @@ enum max77693_led_boost_mode {
 	MAX77693_LED_BOOST_FIXED,
 };
 
-struct max77693_led_platform_data {
-	u32 fleds[2];
-	u32 iout_torch[2];
-	u32 iout_flash[2];
-	u32 trigger[2];
-	u32 trigger_type[2];
-	u32 num_leds;
-	u32 boost_mode;
-	u32 flash_timeout;
-	u32 boost_vout;
-	u32 low_vsys;
-};
-
 /* MAX77693 */
 
 struct max77693_platform_data {
-- 
1.7.9.5

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

* [PATCH/RFC v11 07/20] mfd: max77693: add TORCH_IOUT_MASK macro
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (5 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 06/20] mfd: max77693: Remove struct max77693_led_platform_data Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 08/20] mfd: max77693: Adjust FLASH_EN_SHIFT and TORCH_EN_SHIFT macros Jacek Anaszewski
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski, Chanwoo Choi, Lee Jones

Add a macro for obtaining the mask of ITORCH register bit fields
related either to FLED1 or FLED2 current output. The expected
arguments are TORCH_IOUT1_SHIFT or TORCH_IOUT2_SHIFT.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Chanwoo Choi <cw00.choi@samsung.com>
Cc: Lee Jones <lee.jones@linaro.org>
---
 include/linux/mfd/max77693-private.h |    1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h
index 955dd99..8770ce1 100644
--- a/include/linux/mfd/max77693-private.h
+++ b/include/linux/mfd/max77693-private.h
@@ -87,6 +87,7 @@ enum max77693_pmic_reg {
 /* MAX77693 ITORCH register */
 #define TORCH_IOUT1_SHIFT	0
 #define TORCH_IOUT2_SHIFT	4
+#define TORCH_IOUT_MASK(x)	(0xf << (x))
 #define TORCH_IOUT_MIN		15625
 #define TORCH_IOUT_MAX		250000
 #define TORCH_IOUT_STEP		15625
-- 
1.7.9.5

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

* [PATCH/RFC v11 08/20] mfd: max77693: Adjust FLASH_EN_SHIFT and TORCH_EN_SHIFT macros
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (6 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 07/20] mfd: max77693: add TORCH_IOUT_MASK macro Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 09/20] leds: Add support for max77693 mfd flash cell Jacek Anaszewski
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski, Chanwoo Choi, Lee Jones

Modify FLASH_EN_SHIFT and TORCH_EN_SHIFT macros to work properly
when passed enum max77693_fled values (0 for FLED1 and 1 for FLED2)
from leds-max77693 driver. Previous definitions were compatible with
one of the previous RFC versions of leds-max77693.c driver, which was
not merged.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Chanwoo Choi <cw00.choi@samsung.com>
Cc: Lee Jones <lee.jones@linaro.org>
---
 include/linux/mfd/max77693-private.h |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h
index 8770ce1..51633ea 100644
--- a/include/linux/mfd/max77693-private.h
+++ b/include/linux/mfd/max77693-private.h
@@ -114,8 +114,8 @@ enum max77693_pmic_reg {
 #define FLASH_EN_FLASH		0x1
 #define FLASH_EN_TORCH		0x2
 #define FLASH_EN_ON		0x3
-#define FLASH_EN_SHIFT(x)	(6 - ((x) - 1) * 2)
-#define TORCH_EN_SHIFT(x)	(2 - ((x) - 1) * 2)
+#define FLASH_EN_SHIFT(x)	(6 - (x) * 2)
+#define TORCH_EN_SHIFT(x)	(2 - (x) * 2)
 
 /* MAX77693 MAX_FLASH1 register */
 #define MAX_FLASH1_MAX_FL_EN	0x80
-- 
1.7.9.5

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

* [PATCH/RFC v11 09/20] leds: Add support for max77693 mfd flash cell
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (7 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 08/20] mfd: max77693: Adjust FLASH_EN_SHIFT and TORCH_EN_SHIFT macros Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 10/20] DT: Add documentation for the mfd Maxim max77693 Jacek Anaszewski
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski, Andrzej Hajda, Lee Jones,
	Chanwoo Choi

This patch adds led-flash support to Maxim max77693 chipset.
A device can be exposed to user space through LED subsystem
sysfs interface. Device supports up to two leds which can
work in flash and torch mode. The leds can be triggered
externally or by software.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: Lee Jones <lee.jones@linaro.org>
Cc: Chanwoo Choi <cw00.choi@samsung.com>
---
 drivers/leds/Kconfig         |   10 +
 drivers/leds/Makefile        |    1 +
 drivers/leds/leds-max77693.c | 1058 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1069 insertions(+)
 create mode 100644 drivers/leds/leds-max77693.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 95029df..ff9c21b 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -464,6 +464,16 @@ config LEDS_TCA6507
 	  LED driver chips accessed via the I2C bus.
 	  Driver support brightness control and hardware-assisted blinking.
 
+config LEDS_MAX77693
+	tristate "LED support for MAX77693 Flash"
+	depends on LEDS_CLASS_FLASH
+	depends on MFD_MAX77693
+	depends on OF
+	help
+	  This option enables support for the flash part of the MAX77693
+	  multifunction device. It has build in control for two leds in flash
+	  and torch mode.
+
 config LEDS_MAX8997
 	tristate "LED support for MAX8997 PMIC"
 	depends on LEDS_CLASS && MFD_MAX8997
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index cbba921..57ca62b 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_LEDS_MC13783)		+= leds-mc13783.o
 obj-$(CONFIG_LEDS_NS2)			+= leds-ns2.o
 obj-$(CONFIG_LEDS_NETXBIG)		+= leds-netxbig.o
 obj-$(CONFIG_LEDS_ASIC3)		+= leds-asic3.o
+obj-$(CONFIG_LEDS_MAX77693)		+= leds-max77693.o
 obj-$(CONFIG_LEDS_MAX8997)		+= leds-max8997.o
 obj-$(CONFIG_LEDS_LM355x)		+= leds-lm355x.o
 obj-$(CONFIG_LEDS_BLINKM)		+= leds-blinkm.o
diff --git a/drivers/leds/leds-max77693.c b/drivers/leds/leds-max77693.c
new file mode 100644
index 0000000..45d50d9
--- /dev/null
+++ b/drivers/leds/leds-max77693.c
@@ -0,0 +1,1058 @@
+/*
+ * LED Flash class driver for the flash cell of max77693 mfd.
+ *
+ *	Copyright (C) 2015, Samsung Electronics Co., Ltd.
+ *
+ *	Authors: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *		 Andrzej Hajda <a.hajda@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <asm/div64.h>
+#include <linux/led-class-flash.h>
+#include <linux/mfd/max77693.h>
+#include <linux/mfd/max77693-private.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#define MODE_OFF		0
+#define MODE_FLASH(a)		(1 << (a))
+#define MODE_TORCH(a)		(1 << (2 + (a)))
+#define MODE_FLASH_EXTERNAL(a)	(1 << (4 + (a)))
+
+#define MODE_FLASH_MASK		(MODE_FLASH(FLED1) | MODE_FLASH(FLED2) | \
+				 MODE_FLASH_EXTERNAL(FLED1) | \
+				 MODE_FLASH_EXTERNAL(FLED2))
+#define MODE_TORCH_MASK		(MODE_TORCH(FLED1) | MODE_TORCH(FLED2))
+
+#define FLED1_IOUT		(1 << 0)
+#define FLED2_IOUT		(1 << 1)
+
+enum max77693_fled {
+	FLED1,
+	FLED2,
+};
+
+enum max77693_led_mode {
+	FLASH,
+	TORCH,
+};
+
+struct max77693_led_config_data {
+	const char *label[2];
+	u32 iout_torch_max[2];
+	u32 iout_flash_max[2];
+	u32 flash_timeout[2];
+	u32 num_leds;
+	u32 boost_mode;
+	u32 boost_vout;
+	u32 low_vsys;
+	u32 trigger_type;
+};
+
+struct max77693_sub_led {
+	/* related FLED output identifier */
+	int fled_id;
+	/* related LED Flash class device */
+	struct led_classdev_flash fled_cdev;
+	/* assures led-triggers compatibility */
+	struct work_struct work_brightness_set;
+
+	/* brightness cache */
+	unsigned int torch_brightness;
+	/* flash timeout cache */
+	unsigned int flash_timeout;
+	/* flash faults that may have occurred */
+	u32 flash_faults;
+};
+
+struct max77693_led_device {
+	/* parent mfd regmap */
+	struct regmap *regmap;
+	/* platform device data */
+	struct platform_device *pdev;
+	/* secures access to the device */
+	struct mutex lock;
+
+	/* sub led data */
+	struct max77693_sub_led sub_leds[2];
+
+	/* maximum torch current values for FLED outputs */
+	u32 iout_torch_max[2];
+	/* maximum flash current values for FLED outputs */
+	u32 iout_flash_max[2];
+	/* flash trigger type */
+	u32 trigger_type;
+
+	/* current flash timeout cache */
+	unsigned int current_flash_timeout;
+	/* ITORCH register cache */
+	u8 torch_iout_reg;
+	/* mode of fled outputs */
+	unsigned int mode_flags;
+	/* recently strobed fled */
+	int strobing_sub_led_id;
+	/* bitmask of fled outputs use state (bit 0. - FLED1, bit 1. - FLED2) */
+	u8 fled_mask;
+	/* FLED modes that can be set */
+	u8 allowed_modes;
+
+	/* arrangement of current outputs */
+	bool iout_joint;
+};
+
+struct max77693_led_settings {
+	struct led_flash_setting torch_brightness;
+	struct led_flash_setting flash_brightness;
+	struct led_flash_setting flash_timeout;
+};
+
+static u8 max77693_led_iout_to_reg(u32 ua)
+{
+	if (ua < FLASH_IOUT_MIN)
+		ua = FLASH_IOUT_MIN;
+	return (ua - FLASH_IOUT_MIN) / FLASH_IOUT_STEP;
+}
+
+static u8 max77693_flash_timeout_to_reg(u32 us)
+{
+	return (us - FLASH_TIMEOUT_MIN) / FLASH_TIMEOUT_STEP;
+}
+
+static inline struct max77693_sub_led *flcdev_to_sub_led(
+					struct led_classdev_flash *fled_cdev)
+{
+	return container_of(fled_cdev, struct max77693_sub_led, fled_cdev);
+}
+
+static inline struct max77693_led_device *sub_led_to_led(
+					struct max77693_sub_led *sub_led)
+{
+	return container_of(sub_led, struct max77693_led_device,
+				sub_leds[sub_led->fled_id]);
+}
+
+static inline u8 max77693_led_vsys_to_reg(u32 mv)
+{
+	return ((mv - MAX_FLASH1_VSYS_MIN) / MAX_FLASH1_VSYS_STEP) << 2;
+}
+
+static inline u8 max77693_led_vout_to_reg(u32 mv)
+{
+	return (mv - FLASH_VOUT_MIN) / FLASH_VOUT_STEP + FLASH_VOUT_RMIN;
+}
+
+static inline bool max77693_fled_used(struct max77693_led_device *led,
+					 int fled_id)
+{
+	u8 fled_bit = (fled_id == FLED1) ? FLED1_IOUT : FLED2_IOUT;
+
+	return led->fled_mask & fled_bit;
+}
+
+static int max77693_set_mode_reg(struct max77693_led_device *led, u8 mode)
+{
+	struct regmap *rmap = led->regmap;
+	int ret, v = 0, i;
+
+	for (i = FLED1; i <= FLED2; ++i) {
+		if (mode & MODE_TORCH(i))
+			v |= FLASH_EN_ON << TORCH_EN_SHIFT(i);
+
+		if (mode & MODE_FLASH(i)) {
+			v |= FLASH_EN_ON << FLASH_EN_SHIFT(i);
+		} else if (mode & MODE_FLASH_EXTERNAL(i)) {
+			v |= FLASH_EN_FLASH << FLASH_EN_SHIFT(i);
+			/*
+			 * Enable hw triggering also for torch mode, as some
+			 * camera sensors use torch led to fathom ambient light
+			 * conditions before strobing the flash.
+			 */
+			v |= FLASH_EN_TORCH << TORCH_EN_SHIFT(i);
+		}
+	}
+
+	/* Reset the register only prior setting flash modes */
+	if (mode & ~(MODE_TORCH(FLED1) | MODE_TORCH(FLED2))) {
+		ret = regmap_write(rmap, MAX77693_LED_REG_FLASH_EN, 0);
+		if (ret < 0)
+			return ret;
+	}
+
+	return regmap_write(rmap, MAX77693_LED_REG_FLASH_EN, v);
+}
+
+static void max77693_set_sync_strobe(struct max77693_led_device *led,
+					u8 *mode)
+{
+	struct max77693_sub_led *sub_leds = led->sub_leds;
+	struct led_classdev_flash *fled_cdev;
+	u8 m = *mode;
+
+	if (led->iout_joint)
+		return;
+
+	/* Check if the other sub-led wants to be strobed simultaneously. */
+	if (m & (MODE_FLASH(FLED1) | MODE_FLASH_EXTERNAL(FLED1))) {
+		fled_cdev = &sub_leds[FLED2].fled_cdev;
+		if (fled_cdev->sync_led_id)
+			m |= m << 1;
+	} else if (m & (MODE_FLASH(FLED2) | MODE_FLASH_EXTERNAL(FLED2))) {
+		fled_cdev = &sub_leds[FLED1].fled_cdev;
+		if (fled_cdev->sync_led_id)
+			m |= m >> 1;
+	}
+
+	*mode = m;
+}
+
+static int max77693_add_mode(struct max77693_led_device *led, u8 mode)
+{
+	int i, ret;
+
+	mode &= led->allowed_modes;
+
+	/*
+	 * Torch mode once enabled remains active until turned off. If the FLED2
+	 * output isn't to be disabled check if the torch mode to be set isn't
+	 * already activated and avoid re-setting it.
+	 */
+	if ((!(mode ^ led->mode_flags)) & MODE_TORCH(FLED2)) {
+		for (i = FLED1; i <= FLED2; ++i)
+			if ((mode & led->mode_flags & MODE_TORCH(i)))
+				return 0;
+	}
+
+	if (led->iout_joint)
+		/* Span the mode on FLED2 for joint iouts case */
+		mode |= (mode << 1);
+	else
+		/*
+		 * Span the flash mode on the other led
+		 * if it is to be synchronized.
+		 */
+		max77693_set_sync_strobe(led, &mode);
+
+	/*
+	 * FLASH_EXTERNAL mode activates FLASHEN and TORCHEN pins in the device.
+	 * The related register bits fields interfere with SW triggerred modes,
+	 * thus clear them to ensure proper device configuration.
+	 */
+	for (i = FLED1; i <= FLED2; ++i)
+		if (mode & MODE_FLASH_EXTERNAL(i))
+			led->mode_flags &= (~MODE_TORCH(i) & ~MODE_FLASH(i));
+
+	led->mode_flags |= mode;
+	led->mode_flags &= led->allowed_modes;
+
+	ret = max77693_set_mode_reg(led, led->mode_flags);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Clear flash mode flag after setting the mode to avoid spurious flash
+	 * strobing on each subsequent torch mode setting.
+	 */
+	if (mode & MODE_FLASH_MASK)
+		led->mode_flags &= ~mode;
+
+	return ret;
+}
+
+static int max77693_clear_mode(struct max77693_led_device *led,
+				u8 mode)
+{
+	if (led->iout_joint)
+		/* Clear mode also on FLED2 for joint iouts case */
+		mode |= (mode << 1);
+	else
+		/*
+		 * Clear a flash mode on the other led
+		 * if it is to be synchronized.
+		 */
+		max77693_set_sync_strobe(led, &mode);
+
+	led->mode_flags &= ~mode;
+
+	return max77693_set_mode_reg(led, led->mode_flags);
+}
+
+static void max77693_add_allowed_modes(struct max77693_led_device *led,
+				int fled_id, enum max77693_led_mode mode)
+{
+	if (mode == FLASH)
+		led->allowed_modes |= (MODE_FLASH(fled_id) |
+				       MODE_FLASH_EXTERNAL(fled_id));
+	else
+		led->allowed_modes |= MODE_TORCH(fled_id);
+}
+
+static void max77693_distribute_currents(struct max77693_led_device *led,
+				int fled_id, enum max77693_led_mode mode,
+				u32 micro_amp, u32 iout_max[2], u32 iout[2])
+{
+	if (!led->iout_joint) {
+		iout[fled_id] = micro_amp;
+		max77693_add_allowed_modes(led, fled_id, mode);
+		return;
+	}
+
+	iout[FLED1] = min(micro_amp, iout_max[FLED1]);
+	iout[FLED2] = micro_amp - iout[FLED1];
+
+	if (mode == FLASH)
+		led->allowed_modes &= ~MODE_FLASH_MASK;
+	else
+		led->allowed_modes &= ~MODE_TORCH_MASK;
+
+	max77693_add_allowed_modes(led, FLED1, mode);
+
+	if (iout[FLED2])
+		max77693_add_allowed_modes(led, FLED2, mode);
+}
+
+static int max77693_set_torch_current(struct max77693_led_device *led,
+				int fled_id, u32 micro_amp)
+{
+	struct regmap *rmap = led->regmap;
+	u8 iout1_reg = 0, iout2_reg = 0;
+	u32 iout[2];
+
+	max77693_distribute_currents(led, fled_id, TORCH, micro_amp,
+					led->iout_torch_max, iout);
+
+	if (fled_id == FLED1 || led->iout_joint) {
+		iout1_reg = max77693_led_iout_to_reg(iout[FLED1]);
+		led->torch_iout_reg &= TORCH_IOUT_MASK(TORCH_IOUT2_SHIFT);
+	}
+	if (fled_id == FLED2 || led->iout_joint) {
+		iout2_reg = max77693_led_iout_to_reg(iout[FLED2]);
+		led->torch_iout_reg &= TORCH_IOUT_MASK(TORCH_IOUT1_SHIFT);
+	}
+
+	led->torch_iout_reg |= ((iout1_reg << TORCH_IOUT1_SHIFT) |
+				(iout2_reg << TORCH_IOUT2_SHIFT));
+
+	return regmap_write(rmap, MAX77693_LED_REG_ITORCH,
+						led->torch_iout_reg);
+}
+
+static int max77693_set_flash_current(struct max77693_led_device *led,
+					int fled_id,
+					u32 micro_amp)
+{
+	struct regmap *rmap = led->regmap;
+	u8 iout1_reg, iout2_reg;
+	u32 iout[2];
+	int ret = -EINVAL;
+
+	max77693_distribute_currents(led, fled_id, FLASH, micro_amp,
+					led->iout_flash_max, iout);
+
+	if (fled_id == FLED1 || led->iout_joint) {
+		iout1_reg = max77693_led_iout_to_reg(iout[FLED1]);
+		ret = regmap_write(rmap, MAX77693_LED_REG_IFLASH1,
+							iout1_reg);
+		if (ret < 0)
+			return ret;
+	}
+	if (fled_id == FLED2 || led->iout_joint) {
+		iout2_reg = max77693_led_iout_to_reg(iout[FLED2]);
+		ret = regmap_write(rmap, MAX77693_LED_REG_IFLASH2,
+							iout2_reg);
+	}
+
+	return ret;
+}
+
+static int max77693_set_timeout(struct max77693_led_device *led, u32 microsec)
+{
+	struct regmap *rmap = led->regmap;
+	u8 v;
+	int ret;
+
+	v = max77693_flash_timeout_to_reg(microsec);
+
+	if (led->trigger_type == MAX77693_LED_TRIG_TYPE_LEVEL)
+		v |= FLASH_TMR_LEVEL;
+
+	ret = regmap_write(rmap, MAX77693_LED_REG_FLASH_TIMER, v);
+	if (ret < 0)
+		return ret;
+
+	led->current_flash_timeout = microsec;
+
+	return 0;
+}
+
+static int max77693_get_strobe_status(struct max77693_led_device *led,
+					bool *state)
+{
+	struct regmap *rmap = led->regmap;
+	unsigned int v;
+	int ret;
+
+	ret = regmap_read(rmap, MAX77693_LED_REG_FLASH_STATUS, &v);
+	if (ret < 0)
+		return ret;
+
+	*state = v & FLASH_STATUS_FLASH_ON;
+
+	return ret;
+}
+
+static int max77693_get_flash_faults(struct max77693_sub_led *sub_led)
+{
+	struct max77693_led_device *led = sub_led_to_led(sub_led);
+	struct regmap *rmap = led->regmap;
+	unsigned int v;
+	u8 fault_open_mask, fault_short_mask;
+	int ret;
+
+	sub_led->flash_faults = 0;
+
+	if (led->iout_joint) {
+		fault_open_mask = FLASH_INT_FLED1_OPEN | FLASH_INT_FLED2_OPEN;
+		fault_short_mask = FLASH_INT_FLED1_SHORT |
+							FLASH_INT_FLED2_SHORT;
+	} else {
+		fault_open_mask = (sub_led->fled_id == FLED1) ?
+						FLASH_INT_FLED1_OPEN :
+						FLASH_INT_FLED2_OPEN;
+		fault_short_mask = (sub_led->fled_id == FLED1) ?
+						FLASH_INT_FLED1_SHORT :
+						FLASH_INT_FLED2_SHORT;
+	}
+
+	ret = regmap_read(rmap, MAX77693_LED_REG_FLASH_INT, &v);
+	if (ret < 0)
+		return ret;
+
+	if (v & fault_open_mask)
+		sub_led->flash_faults |= LED_FAULT_OVER_VOLTAGE;
+	if (v & fault_short_mask)
+		sub_led->flash_faults |= LED_FAULT_SHORT_CIRCUIT;
+	if (v & FLASH_INT_OVER_CURRENT)
+		sub_led->flash_faults |= LED_FAULT_OVER_CURRENT;
+
+	return 0;
+}
+
+static int max77693_setup(struct max77693_led_device *led,
+			 struct max77693_led_config_data *cfg)
+{
+	struct regmap *rmap = led->regmap;
+	int i, first_led, last_led, ret;
+	u32 max_flash_curr[2];
+	u8 v;
+
+	/*
+	 * Initialize only flash current. Torch current doesn't
+	 * require initialization as ITORCH register is written with
+	 * new value each time brightness_set op is called.
+	 */
+	if (led->iout_joint) {
+		first_led = FLED1;
+		last_led = FLED1;
+		max_flash_curr[FLED1] = cfg->iout_flash_max[FLED1] +
+					cfg->iout_flash_max[FLED2];
+	} else {
+		first_led = max77693_fled_used(led, FLED1) ? FLED1 : FLED2;
+		last_led = max77693_fled_used(led, FLED2) ? FLED2 : FLED1;
+		max_flash_curr[FLED1] = cfg->iout_flash_max[FLED1];
+		max_flash_curr[FLED2] = cfg->iout_flash_max[FLED2];
+	}
+
+	for (i = first_led; i <= last_led; ++i) {
+		ret = max77693_set_flash_current(led, i,
+					max_flash_curr[i]);
+		if (ret < 0)
+			return ret;
+	}
+
+	v = TORCH_TMR_NO_TIMER | MAX77693_LED_TRIG_TYPE_LEVEL;
+	ret = regmap_write(rmap, MAX77693_LED_REG_ITORCHTIMER, v);
+	if (ret < 0)
+		return ret;
+
+	/* initially set FLED1 timeout */
+	ret = max77693_set_timeout(led, cfg->flash_timeout[FLED1]);
+	if (ret < 0)
+		return ret;
+
+	if (cfg->low_vsys > 0)
+		v = max77693_led_vsys_to_reg(cfg->low_vsys) |
+						MAX_FLASH1_MAX_FL_EN;
+	else
+		v = 0;
+
+	ret = regmap_write(rmap, MAX77693_LED_REG_MAX_FLASH1, v);
+	if (ret < 0)
+		return ret;
+	ret = regmap_write(rmap, MAX77693_LED_REG_MAX_FLASH2, 0);
+	if (ret < 0)
+		return ret;
+
+	if (cfg->boost_mode == MAX77693_LED_BOOST_FIXED)
+		v = FLASH_BOOST_FIXED;
+	else
+		v = cfg->boost_mode | cfg->boost_mode << 1;
+
+	if (max77693_fled_used(led, FLED1) && max77693_fled_used(led, FLED2))
+		v |= FLASH_BOOST_LEDNUM_2;
+
+	ret = regmap_write(rmap, MAX77693_LED_REG_VOUT_CNTL, v);
+	if (ret < 0)
+		return ret;
+
+	v = max77693_led_vout_to_reg(cfg->boost_vout);
+	ret = regmap_write(rmap, MAX77693_LED_REG_VOUT_FLASH1, v);
+	if (ret < 0)
+		return ret;
+
+	return max77693_set_mode_reg(led, MODE_OFF);
+}
+
+static int __max77693_led_brightness_set(struct max77693_led_device *led,
+					int fled_id, enum led_brightness value)
+{
+	int ret;
+
+	mutex_lock(&led->lock);
+
+	if (value == 0) {
+		ret = max77693_clear_mode(led, MODE_TORCH(fled_id));
+		if (ret < 0)
+			dev_dbg(&led->pdev->dev,
+				"Failed to clear torch mode (%d)\n",
+				ret);
+		goto unlock;
+	}
+
+	ret = max77693_set_torch_current(led, fled_id, value * TORCH_IOUT_STEP);
+	if (ret < 0) {
+		dev_dbg(&led->pdev->dev,
+			"Failed to set torch current (%d)\n",
+			ret);
+		goto unlock;
+	}
+
+	ret = max77693_add_mode(led, MODE_TORCH(fled_id));
+	if (ret < 0)
+		dev_dbg(&led->pdev->dev,
+			"Failed to set torch mode (%d)\n",
+			ret);
+unlock:
+	mutex_unlock(&led->lock);
+	return ret;
+}
+
+static void max77693_led_brightness_set_work(
+					struct work_struct *work)
+{
+	struct max77693_sub_led *sub_led =
+			container_of(work, struct max77693_sub_led,
+					work_brightness_set);
+	struct max77693_led_device *led = sub_led_to_led(sub_led);
+
+	__max77693_led_brightness_set(led, sub_led->fled_id,
+				sub_led->torch_brightness);
+}
+
+/* LED subsystem callbacks */
+
+static int max77693_led_brightness_set_sync(
+				struct led_classdev *led_cdev,
+				enum led_brightness value)
+{
+	struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
+	struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
+	struct max77693_led_device *led = sub_led_to_led(sub_led);
+
+	return __max77693_led_brightness_set(led, sub_led->fled_id, value);
+}
+
+static void max77693_led_brightness_set(
+				struct led_classdev *led_cdev,
+				enum led_brightness value)
+{
+	struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
+	struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
+
+	sub_led->torch_brightness = value;
+	schedule_work(&sub_led->work_brightness_set);
+}
+
+static int max77693_led_flash_brightness_set(
+				struct led_classdev_flash *fled_cdev,
+				u32 brightness)
+{
+	struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
+	struct max77693_led_device *led = sub_led_to_led(sub_led);
+	int ret;
+
+	mutex_lock(&led->lock);
+	ret = max77693_set_flash_current(led, sub_led->fled_id, brightness);
+	mutex_unlock(&led->lock);
+
+	return ret;
+}
+
+static int max77693_led_flash_strobe_set(
+				struct led_classdev_flash *fled_cdev,
+				bool state)
+{
+	struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
+	struct max77693_led_device *led = sub_led_to_led(sub_led);
+	int fled_id = sub_led->fled_id;
+	int ret;
+
+	mutex_lock(&led->lock);
+
+	if (!state) {
+		ret = max77693_clear_mode(led, MODE_FLASH(fled_id));
+		goto unlock;
+	}
+
+	if (sub_led->flash_timeout != led->current_flash_timeout) {
+		ret = max77693_set_timeout(led, sub_led->flash_timeout);
+		if (ret < 0)
+			goto unlock;
+	}
+
+	led->strobing_sub_led_id = fled_id;
+
+	ret = max77693_add_mode(led, MODE_FLASH(fled_id));
+	if (ret < 0)
+		goto unlock;
+
+	ret = max77693_get_flash_faults(sub_led);
+
+unlock:
+	mutex_unlock(&led->lock);
+	return ret;
+}
+
+static int max77693_led_flash_fault_get(
+				struct led_classdev_flash *fled_cdev,
+				u32 *fault)
+{
+	struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
+
+	*fault = sub_led->flash_faults;
+
+	return 0;
+}
+
+static int max77693_led_flash_strobe_get(
+				struct led_classdev_flash *fled_cdev,
+				bool *state)
+{
+	struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
+	struct max77693_led_device *led = sub_led_to_led(sub_led);
+	int ret;
+
+	if (!state)
+		return -EINVAL;
+
+	mutex_lock(&led->lock);
+
+	ret = max77693_get_strobe_status(led, state);
+
+	*state = !!(*state && (led->strobing_sub_led_id == sub_led->fled_id));
+
+	mutex_unlock(&led->lock);
+
+	return ret;
+}
+
+static int max77693_led_flash_timeout_set(
+				struct led_classdev_flash *fled_cdev,
+				u32 timeout)
+{
+	struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
+	struct max77693_led_device *led = sub_led_to_led(sub_led);
+
+	mutex_lock(&led->lock);
+	sub_led->flash_timeout = timeout;
+	mutex_unlock(&led->lock);
+
+	return 0;
+}
+
+static int max77693_led_parse_dt(struct max77693_led_device *led,
+				struct max77693_led_config_data *cfg)
+{
+	struct device *dev = &led->pdev->dev;
+	struct max77693_sub_led *sub_leds = led->sub_leds;
+	struct device_node *node = dev->of_node, *child_node;
+	struct property *prop;
+	u32 led_sources[2];
+	int i, fled_id, ret;
+
+	of_property_read_u32(node, "maxim,trigger-type", &cfg->trigger_type);
+	of_property_read_u32(node, "maxim,boost-mode", &cfg->boost_mode);
+	of_property_read_u32(node, "maxim,boost-mvout", &cfg->boost_vout);
+	of_property_read_u32(node, "maxim,mvsys-min", &cfg->low_vsys);
+
+	for_each_available_child_of_node(node, child_node) {
+		prop = of_find_property(child_node, "led-sources", NULL);
+		if (prop) {
+			const __be32 *srcs = NULL;
+
+			for (i = 0; i < ARRAY_SIZE(led_sources); ++i) {
+				srcs = of_prop_next_u32(prop, srcs,
+							&led_sources[i]);
+				if (!srcs)
+					break;
+			}
+		} else {
+			dev_err(dev,
+				"\"led-sources\" DT property not found.\n");
+			return -EINVAL;
+		}
+
+		if (i == 2) {
+			fled_id = FLED1;
+			led->fled_mask = FLED1_IOUT | FLED2_IOUT;
+		} else if (led_sources[0] == FLED1) {
+			fled_id = FLED1;
+			led->fled_mask |= FLED1_IOUT;
+		} else if (led_sources[0] == FLED2) {
+			fled_id = FLED2;
+			led->fled_mask |= FLED2_IOUT;
+		} else {
+			dev_err(dev,
+				"Wrong \"led-sources\" DT property value.\n");
+			return -EINVAL;
+		}
+
+		sub_leds[fled_id].fled_id = fled_id;
+
+		ret = of_property_read_string(child_node, "label",
+					(const char **) &cfg->label[fled_id]);
+		if (ret < 0) {
+			dev_err(dev, "Error reading \"label\" DT property.\n");
+			return ret;
+		}
+
+		of_property_read_u32(child_node, "max-microamp",
+						&cfg->iout_torch_max[fled_id]);
+		of_property_read_u32(child_node, "flash-max-microamp",
+						&cfg->iout_flash_max[fled_id]);
+		of_property_read_u32(child_node, "flash-timeout-us",
+						&cfg->flash_timeout[fled_id]);
+
+		if (++cfg->num_leds == 2 ||
+		    (max77693_fled_used(led, FLED1) &&
+		     max77693_fled_used(led, FLED2)))
+			break;
+	}
+
+	if (cfg->num_leds == 0) {
+		dev_err(dev, "No DT child node found for the connected LED.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void clamp_align(u32 *v, u32 min, u32 max, u32 step)
+{
+	*v = clamp_val(*v, min, max);
+	if (step > 1)
+		*v = (*v - min) / step * step + min;
+}
+
+static void max77693_led_validate_configuration(struct max77693_led_device *led,
+					struct max77693_led_config_data *cfg)
+{
+	int i;
+
+	if (cfg->num_leds == 1 &&
+	    max77693_fled_used(led, FLED1) && max77693_fled_used(led, FLED2))
+		led->iout_joint = true;
+
+	cfg->boost_mode = clamp_val(cfg->boost_mode, MAX77693_LED_BOOST_NONE,
+			    MAX77693_LED_BOOST_FIXED);
+
+	/* Boost must be enabled if both current outputs are used */
+	if ((cfg->boost_mode == MAX77693_LED_BOOST_NONE) && led->iout_joint)
+		cfg->boost_mode = MAX77693_LED_BOOST_FIXED;
+
+	/* Split max current settings to both outputs in case of joint leds */
+	if (led->iout_joint) {
+		cfg->iout_torch_max[FLED1] /= 2;
+		cfg->iout_torch_max[FLED2] = cfg->iout_torch_max[FLED1];
+		cfg->iout_flash_max[FLED1] /= 2;
+		cfg->iout_flash_max[FLED2] = cfg->iout_flash_max[FLED1];
+	}
+
+	for (i = FLED1; i <= FLED2; ++i) {
+		if (max77693_fled_used(led, i)) {
+			clamp_align(&cfg->iout_torch_max[i], TORCH_IOUT_MIN,
+					TORCH_IOUT_MAX, TORCH_IOUT_STEP);
+			clamp_align(&cfg->iout_flash_max[i], FLASH_IOUT_MIN,
+					cfg->boost_mode ? FLASH_IOUT_MAX_2LEDS :
+							FLASH_IOUT_MAX_1LED,
+					FLASH_IOUT_STEP);
+		} else {
+			cfg->iout_torch_max[i] = cfg->iout_flash_max[i] = 0;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(cfg->flash_timeout); ++i)
+		clamp_align(&cfg->flash_timeout[i], FLASH_TIMEOUT_MIN,
+				FLASH_TIMEOUT_MAX, FLASH_TIMEOUT_STEP);
+
+	cfg->trigger_type = clamp_val(cfg->trigger_type,
+					MAX77693_LED_TRIG_TYPE_EDGE,
+					MAX77693_LED_TRIG_TYPE_LEVEL);
+
+	clamp_align(&cfg->boost_vout, FLASH_VOUT_MIN, FLASH_VOUT_MAX,
+							FLASH_VOUT_STEP);
+
+	if (cfg->low_vsys)
+		clamp_align(&cfg->low_vsys, MAX_FLASH1_VSYS_MIN,
+				MAX_FLASH1_VSYS_MAX, MAX_FLASH1_VSYS_STEP);
+}
+
+static int max77693_led_get_configuration(struct max77693_led_device *led,
+				struct max77693_led_config_data *cfg)
+{
+	int ret;
+
+	ret = max77693_led_parse_dt(led, cfg);
+	if (ret < 0)
+		return ret;
+
+	max77693_led_validate_configuration(led, cfg);
+
+	memcpy(led->iout_torch_max, cfg->iout_torch_max,
+				sizeof(led->iout_torch_max));
+	memcpy(led->iout_flash_max, cfg->iout_flash_max,
+				sizeof(led->iout_flash_max));
+	led->trigger_type = cfg->trigger_type;
+	led->allowed_modes = MODE_FLASH_MASK;
+
+	return 0;
+}
+
+static const struct led_flash_ops flash_ops = {
+	.flash_brightness_set	= max77693_led_flash_brightness_set,
+	.strobe_set		= max77693_led_flash_strobe_set,
+	.strobe_get		= max77693_led_flash_strobe_get,
+	.timeout_set		= max77693_led_flash_timeout_set,
+	.fault_get		= max77693_led_flash_fault_get,
+};
+
+static void max77693_init_flash_settings(struct max77693_led_device *led,
+					 int fled_id,
+					 struct max77693_led_config_data *cfg,
+					 struct max77693_led_settings *s)
+{
+	struct led_flash_setting *setting;
+
+	/* Init torch intensity setting */
+	setting = &s->torch_brightness;
+	setting->min = TORCH_IOUT_MIN;
+	setting->max = cfg->iout_torch_max[fled_id];
+	setting->max = led->iout_joint ?
+		cfg->iout_torch_max[FLED1] + cfg->iout_torch_max[FLED2] :
+		cfg->iout_torch_max[fled_id];
+	setting->step = TORCH_IOUT_STEP;
+	setting->val = setting->max;
+
+	/* Init flash intensity setting */
+	setting = &s->flash_brightness;
+	setting->min = FLASH_IOUT_MIN;
+	setting->max = led->iout_joint ?
+		cfg->iout_flash_max[FLED1] + cfg->iout_flash_max[FLED2] :
+		cfg->iout_flash_max[fled_id];
+	setting->step = FLASH_IOUT_STEP;
+	setting->val = setting->max;
+
+	/* Init flash timeout setting */
+	setting = &s->flash_timeout;
+	setting->min = FLASH_TIMEOUT_MIN;
+	setting->max = cfg->flash_timeout[fled_id];
+	setting->step = FLASH_TIMEOUT_STEP;
+	setting->val = setting->max;
+}
+
+static int max77693_set_available_sync_led(struct max77693_led_device *led,
+						int fled_id)
+{
+	struct max77693_sub_led *sub_led = &led->sub_leds[fled_id];
+	struct led_classdev_flash *fled_cdev = &sub_led->fled_cdev;
+
+	fled_cdev->sync_leds = devm_kzalloc(&led->pdev->dev, sizeof(fled_cdev),
+					GFP_KERNEL);
+	if (!fled_cdev->sync_leds)
+		return -ENOMEM;
+
+	fled_cdev->sync_leds[0] = &led->sub_leds[!fled_id].fled_cdev;
+	fled_cdev->num_sync_leds = 1;
+
+	return 0;
+}
+
+static void max77693_init_fled_cdev(struct max77693_led_device *led,
+				int fled_id,
+				struct max77693_led_config_data *cfg)
+{
+	struct led_classdev_flash *fled_cdev;
+	struct led_classdev *led_cdev;
+	struct max77693_sub_led *sub_led = &led->sub_leds[fled_id];
+	struct max77693_led_settings settings;
+
+	/* Initialize flash settings */
+	max77693_init_flash_settings(led, fled_id, cfg, &settings);
+
+	/* Initialize LED Flash class device */
+	fled_cdev = &sub_led->fled_cdev;
+	fled_cdev->ops = &flash_ops;
+	led_cdev = &fled_cdev->led_cdev;
+	led_cdev->name = cfg->label[fled_id];
+	led_cdev->brightness_set = max77693_led_brightness_set;
+	led_cdev->brightness_set_sync = max77693_led_brightness_set_sync;
+	INIT_WORK(&sub_led->work_brightness_set,
+			max77693_led_brightness_set_work);
+
+	led_cdev->max_brightness = settings.torch_brightness.val /
+					TORCH_IOUT_STEP;
+	led_cdev->flags |= LED_DEV_CAP_FLASH;
+	if (cfg->num_leds == 2)
+		led_cdev->flags |= LED_DEV_CAP_SYNC_STROBE;
+
+	fled_cdev->brightness = settings.flash_brightness;
+	fled_cdev->timeout = settings.flash_timeout;
+	sub_led->flash_timeout = fled_cdev->timeout.val;
+}
+
+static int max77693_led_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct max77693_dev *iodev = dev_get_drvdata(dev->parent);
+	struct max77693_led_device *led;
+	struct max77693_sub_led *sub_leds;
+	struct max77693_led_config_data cfg = {};
+	int init_fled_cdev[2], i, ret;
+
+	led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
+	if (!led)
+		return -ENOMEM;
+
+	led->pdev = pdev;
+	led->regmap = iodev->regmap;
+	sub_leds = led->sub_leds;
+
+	platform_set_drvdata(pdev, led);
+	ret = max77693_led_get_configuration(led, &cfg);
+	if (ret < 0)
+		return ret;
+
+	ret = max77693_setup(led, &cfg);
+	if (ret < 0)
+		return ret;
+
+	init_fled_cdev[FLED1] =
+			led->iout_joint || max77693_fled_used(led, FLED1);
+	init_fled_cdev[FLED2] =
+			!led->iout_joint && max77693_fled_used(led, FLED2);
+
+	/* Initialize LED Flash class device(s) */
+	for (i = FLED1; i <= FLED2; ++i)
+		if (init_fled_cdev[i])
+			max77693_init_fled_cdev(led, i, &cfg);
+
+	/* Setup sub-leds available for flash strobe synchronization */
+	if (cfg.num_leds == 2)
+		for (i = FLED1; i <= FLED2; ++i) {
+			ret = max77693_set_available_sync_led(led, i);
+			if (ret < 0)
+				return ret;
+		}
+
+	mutex_init(&led->lock);
+
+	/* Register LED Flash class device(s) */
+	for (i = FLED1; i <= FLED2; ++i) {
+		if (!init_fled_cdev[i])
+			continue;
+
+		ret = led_classdev_flash_register(dev, &sub_leds[i].fled_cdev);
+		if (ret < 0) {
+			/*
+			 * At this moment FLED1 might have been already
+			 * registered and it needs to be released.
+			 */
+			if (i == FLED2)
+				goto err_register_led2;
+			else
+				goto err_register_led1;
+		}
+	}
+
+
+	return 0;
+
+err_register_led2:
+	/* It is possible than only FLED2 was to be registered */
+	if (!init_fled_cdev[FLED1])
+		goto err_register_led1;
+	led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
+err_register_led1:
+	mutex_destroy(&led->lock);
+
+	return ret;
+}
+
+static int max77693_led_remove(struct platform_device *pdev)
+{
+	struct max77693_led_device *led = platform_get_drvdata(pdev);
+	struct max77693_sub_led *sub_leds = led->sub_leds;
+
+	if (led->iout_joint || max77693_fled_used(led, FLED1)) {
+		led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
+		cancel_work_sync(&sub_leds[FLED1].work_brightness_set);
+	}
+
+	if (!led->iout_joint && max77693_fled_used(led, FLED2)) {
+		led_classdev_flash_unregister(&sub_leds[FLED2].fled_cdev);
+		cancel_work_sync(&sub_leds[FLED2].work_brightness_set);
+	}
+
+	mutex_destroy(&led->lock);
+
+	return 0;
+}
+
+static struct of_device_id max77693_led_dt_match[] = {
+	{.compatible = "maxim,max77693-led"},
+	{},
+};
+
+static struct platform_driver max77693_led_driver = {
+	.probe		= max77693_led_probe,
+	.remove		= max77693_led_remove,
+	.driver		= {
+		.name	= "max77693-led",
+		.owner	= THIS_MODULE,
+		.of_match_table = max77693_led_dt_match,
+	},
+};
+
+module_platform_driver(max77693_led_driver);
+
+MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
+MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
+MODULE_DESCRIPTION("Maxim MAX77693 led flash driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

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

* [PATCH/RFC v11 10/20] DT: Add documentation for the mfd Maxim max77693
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (8 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 09/20] leds: Add support for max77693 mfd flash cell Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 11/20] leds: Add driver for AAT1290 current regulator Jacek Anaszewski
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski, Andrzej Hajda, Lee Jones,
	Chanwoo Choi, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala

This patch adds device tree binding documentation for
the flash cell of the Maxim max77693 multifunctional device.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Lee Jones <lee.jones@linaro.org>
Cc: Chanwoo Choi <cw00.choi@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
---
 Documentation/devicetree/bindings/mfd/max77693.txt |   61 ++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/max77693.txt b/Documentation/devicetree/bindings/mfd/max77693.txt
index 38e6440..ab8fbd5 100644
--- a/Documentation/devicetree/bindings/mfd/max77693.txt
+++ b/Documentation/devicetree/bindings/mfd/max77693.txt
@@ -76,7 +76,53 @@ Optional properties:
     Valid values: 4300000, 4700000, 4800000, 4900000
     Default: 4300000
 
+- led : the LED submodule device node
+
+There are two LED outputs available - FLED1 and FLED2. Each of them can
+control a separate LED or they can be connected together to double
+the maximum current for a single connected LED. One LED is represented
+by one child node.
+
+Required properties:
+- compatible : Must be "maxim,max77693-led".
+
+Optional properties:
+- maxim,trigger-type : Flash trigger type.
+	Possible trigger types:
+		LEDS_TRIG_TYPE_EDGE (0) - Rising edge of the signal triggers
+			the flash,
+		LEDS_TRIG_TYPE_LEVEL (1) - Strobe pulse length controls duration
+			of the flash.
+- maxim,boost-mode :
+	In boost mode the device can produce up to 1.2A of total current
+	on both outputs. The maximum current on each output is reduced
+	to 625mA then. If not enabled explicitly, boost setting defaults to
+	LEDS_BOOST_FIXED in case both current sources are used.
+	Possible values:
+		LEDS_BOOST_OFF (0) - no boost,
+		LEDS_BOOST_ADAPTIVE (1) - adaptive mode,
+		LEDS_BOOST_FIXED (2) - fixed mode.
+- maxim,boost-mvout : Output voltage of the boost module in millivolts.
+- maxim,mvsys-min : Low input voltage level in millivolts. Flash is not fired
+	if chip estimates that system voltage could drop below this level due
+	to flash power consumption.
+
+Required properties of the LED child node:
+- label : see Documentation/devicetree/bindings/leds/common.txt
+- led-sources : see Documentation/devicetree/bindings/leds/common.txt;
+		device current output identifiers: 0 - FLED1, 1 - FLED2
+
+Optional properties of the LED child node:
+- max-microamp : see Documentation/devicetree/bindings/leds/common.txt
+		Range: 15625 - 250000
+- flash-max-microamp : see Documentation/devicetree/bindings/leds/common.txt
+		Range: 15625 - 1000000
+- flash-timeout-us : see Documentation/devicetree/bindings/leds/common.txt
+		Range: 62500 - 1000000
+
 Example:
+#include <dt-bindings/leds/max77693.h>
+
 	max77693@66 {
 		compatible = "maxim,max77693";
 		reg = <0x66>;
@@ -117,5 +163,20 @@ Example:
 			maxim,thermal-regulation-celsius = <75>;
 			maxim,battery-overcurrent-microamp = <3000000>;
 			maxim,charge-input-threshold-microvolt = <4300000>;
+
+		led {
+			compatible = "maxim,max77693-led";
+			maxim,trigger-type = <LEDS_TRIG_TYPE_LEVEL>;
+			maxim,boost-mode = <LEDS_BOOST_FIXED>;
+			maxim,boost-mvout = <5000>;
+			maxim,mvsys-min = <2400>;
+
+			camera_flash: flash-led {
+				label = "max77693-flash1";
+				led-sources = <0>, <1>;
+				max-microamp = <500000>;
+				flash-max-microamp = <1250000>;
+				flash-timeout-us = <1000000>;
+			};
 		};
 	};
-- 
1.7.9.5

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

* [PATCH/RFC v11 11/20] leds: Add driver for AAT1290 current regulator
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (9 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 10/20] DT: Add documentation for the mfd Maxim max77693 Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 12/20] of: Add Skyworks Solutions, Inc. vendor prefix Jacek Anaszewski
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

This patch adds a driver for the 1.5A Step-Up Current Regulator
for Flash LEDs. The device is programmed through a Skyworks proprietary
AS2Cwire serial digital interface.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
---
 drivers/leds/Kconfig        |    7 +
 drivers/leds/Makefile       |    1 +
 drivers/leds/leds-aat1290.c |  407 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 415 insertions(+)
 create mode 100644 drivers/leds/leds-aat1290.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index ff9c21b..d70fc7b 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -39,6 +39,13 @@ config LEDS_88PM860X
 	  This option enables support for on-chip LED drivers found on Marvell
 	  Semiconductor 88PM8606 PMIC.
 
+config LEDS_AAT1290
+	tristate "LED support for the AAT1290"
+	depends on LEDS_CLASS_FLASH
+	depends on OF
+	help
+	 This option enables support for the LEDs on the AAT1290.
+
 config LEDS_LM3530
 	tristate "LCD Backlight driver for LM3530"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 57ca62b..b802251 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_LEDS_TRIGGERS)		+= led-triggers.o
 
 # LED Platform Drivers
 obj-$(CONFIG_LEDS_88PM860X)		+= leds-88pm860x.o
+obj-$(CONFIG_LEDS_AAT1290)		+= leds-aat1290.o
 obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
 obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c
new file mode 100644
index 0000000..b217f0a
--- /dev/null
+++ b/drivers/leds/leds-aat1290.c
@@ -0,0 +1,407 @@
+/*
+ *	LED Flash class driver for the AAT1290
+ *	1.5A Step-Up Current Regulator for Flash LEDs
+ *
+ *	Copyright (C) 2015, Samsung Electronics Co., Ltd.
+ *	Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/led-class-flash.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#define AAT1290_MOVIE_MODE_CURRENT_ADDR	17
+#define AAT1290_MAX_MM_CURR_PERCENT_0	16
+#define AAT1290_MAX_MM_CURR_PERCENT_100	1
+
+#define AAT1290_FLASH_SAFETY_TIMER_ADDR	18
+
+#define AAT1290_MOVIE_MODE_CONFIG_ADDR	19
+#define AAT1290_MOVIE_MODE_OFF		1
+#define AAT1290_MOVIE_MODE_ON		3
+
+#define AAT1290_MM_CURRENT_RATIO_ADDR	20
+#define AAT1290_MM_TO_FL_1_92		1
+
+#define AAT1290_MM_TO_FL_RATIO		1000 / 1920
+#define AAT1290_MAX_MM_CURRENT(fl_max)	(fl_max * AAT1290_MM_TO_FL_RATIO)
+
+#define AAT1290_LATCH_TIME_MIN_US	500
+#define AAT1290_LATCH_TIME_MAX_US	1000
+#define AAT1290_EN_SET_TICK_TIME_US	1
+#define AAT1290_FLEN_OFF_DELAY_TIME_US	10
+#define AAT1290_FLASH_TM_NUM_LEVELS	16
+#define AAT1290_MM_CURRENT_SCALE_SIZE	15
+
+struct aat1290_led_settings {
+	struct led_flash_setting flash_timeout;
+};
+
+struct aat1290_led {
+	/* platform device data */
+	struct platform_device *pdev;
+	/* secures access to the device */
+	struct mutex lock;
+
+	/* related LED Flash class device */
+	struct led_classdev_flash fled_cdev;
+
+	/* FLEN pin */
+	int flen_gpio;
+	/* EN|SET pin  */
+	int en_set_gpio;
+
+	/* maximum flash timeout */
+	u32 max_flash_tm;
+	/* maximum LED current in flash mode */
+	u32 max_flash_current;
+	/* device mode */
+	bool movie_mode;
+
+	/* brightness cache */
+	unsigned int torch_brightness;
+	/* assures led-triggers compatibility */
+	struct work_struct work_brightness_set;
+};
+
+static struct aat1290_led *fled_cdev_to_led(
+				struct led_classdev_flash *fled_cdev)
+{
+	return container_of(fled_cdev, struct aat1290_led, fled_cdev);
+}
+
+static void aat1290_as2cwire_write(struct aat1290_led *led, int addr, int value)
+{
+	int i;
+
+	gpio_set_value(led->flen_gpio, 0);
+	gpio_set_value(led->en_set_gpio, 0);
+
+	udelay(AAT1290_FLEN_OFF_DELAY_TIME_US);
+
+	/* write address */
+	for (i = 0; i < addr; ++i) {
+		udelay(AAT1290_EN_SET_TICK_TIME_US);
+		gpio_set_value(led->en_set_gpio, 0);
+		udelay(AAT1290_EN_SET_TICK_TIME_US);
+		gpio_set_value(led->en_set_gpio, 1);
+	}
+
+	usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US);
+
+	/* write data */
+	for (i = 0; i < value; ++i) {
+		udelay(AAT1290_EN_SET_TICK_TIME_US);
+		gpio_set_value(led->en_set_gpio, 0);
+		udelay(AAT1290_EN_SET_TICK_TIME_US);
+		gpio_set_value(led->en_set_gpio, 1);
+	}
+
+	usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US);
+}
+
+static void aat1290_set_flash_safety_timer(struct aat1290_led *led,
+					unsigned int micro_sec)
+{
+	struct led_classdev_flash *fled_cdev = &led->fled_cdev;
+	struct led_flash_setting *flash_tm = &fled_cdev->timeout;
+	int flash_tm_reg = AAT1290_FLASH_TM_NUM_LEVELS -
+				(micro_sec / flash_tm->step) + 1;
+
+	aat1290_as2cwire_write(led, AAT1290_FLASH_SAFETY_TIMER_ADDR,
+							flash_tm_reg);
+}
+
+static void aat1290_brightness_set(struct aat1290_led *led,
+					enum led_brightness brightness)
+{
+	mutex_lock(&led->lock);
+
+	if (brightness == 0) {
+		gpio_set_value(led->flen_gpio, 0);
+		gpio_set_value(led->en_set_gpio, 0);
+		led->movie_mode = false;
+		goto unlock;
+	}
+
+	if (!led->movie_mode) {
+		aat1290_as2cwire_write(led, AAT1290_MM_CURRENT_RATIO_ADDR,
+					AAT1290_MM_TO_FL_1_92);
+		led->movie_mode = true;
+	}
+
+	aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CURRENT_ADDR,
+				AAT1290_MAX_MM_CURR_PERCENT_0 - brightness);
+	aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CONFIG_ADDR,
+				AAT1290_MOVIE_MODE_ON);
+unlock:
+	mutex_unlock(&led->lock);
+}
+
+/* LED subsystem callbacks */
+
+static void aat1290_brightness_set_work(struct work_struct *work)
+{
+	struct aat1290_led *led =
+		container_of(work, struct aat1290_led, work_brightness_set);
+
+	aat1290_brightness_set(led, led->torch_brightness);
+}
+
+static void aat1290_led_brightness_set(struct led_classdev *led_cdev,
+					enum led_brightness brightness)
+{
+	struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
+	struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
+
+	led->torch_brightness = brightness;
+	schedule_work(&led->work_brightness_set);
+}
+
+static int aat1290_led_brightness_set_sync(struct led_classdev *led_cdev,
+					enum led_brightness brightness)
+{
+	struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
+	struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
+
+	aat1290_brightness_set(led, brightness);
+
+	return 0;
+}
+
+static int aat1290_led_flash_strobe_set(struct led_classdev_flash *fled_cdev,
+					 bool state)
+
+{
+	struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	struct led_flash_setting *timeout = &fled_cdev->timeout;
+
+	mutex_lock(&led->lock);
+
+	if (state == 0) {
+		gpio_set_value(led->flen_gpio, 0);
+		gpio_set_value(led->en_set_gpio, 0);
+		goto unlock;
+	}
+
+	aat1290_set_flash_safety_timer(led, timeout->val);
+
+	/*
+	 * To reenter movie mode after a flash event the part
+	 * must be cycled off and back on to reset the movie
+	 * mode and reprogrammed via the AS2Cwire. Therefore
+	 * the brightness value needs to be updated here to
+	 * reflect the actual state.
+	 */
+	led_cdev->brightness = 0;
+	led->movie_mode = false;
+
+	gpio_set_value(led->flen_gpio, 1);
+
+unlock:
+	mutex_unlock(&led->lock);
+
+	return 0;
+}
+
+static int aat1290_led_flash_timeout_set(struct led_classdev_flash *fled_cdev,
+						u32 timeout)
+{
+	/*
+	 * Don't do anything - flash timeout is cached in the led-class-flash
+	 * core and will be applied in the strobe_set op, as writing the
+	 * safety timer register spuriously turns the torch mode on.
+	 */
+
+	return 0;
+}
+
+static int aat1290_led_parse_dt(struct aat1290_led *led,
+				struct device *dev,
+				const char **led_label)
+{
+	struct device_node *node = dev->of_node, *child_node;
+	int cnt_leds = 0, ret;
+
+	for_each_available_child_of_node(node, child_node) {
+		ret = of_property_read_string(child_node, "label",
+					(const char **) led_label);
+		if (ret < 0) {
+			dev_err(dev,
+				"Error reading \"label\" DT property.\n");
+			return ret;
+		}
+
+		ret = of_property_read_u32(child_node, "flash-max-microamp",
+					&led->max_flash_current);
+		if (ret < 0) {
+			dev_err(dev,
+				"Error reading \"flash-max-microamp\" DT property\n");
+			return ret;
+		}
+
+		ret = of_property_read_u32(child_node, "flash-timeout-us",
+					&led->max_flash_tm);
+		if (ret < 0) {
+			dev_err(dev,
+				"Error reading \"flash-timeout-us\" DT property\n");
+			return ret;
+		}
+
+		++cnt_leds;
+	}
+
+	if (cnt_leds != 1) {
+		dev_err(dev,
+			"Expected one DT child node for the connected LED.\n");
+		return -EINVAL;
+	}
+
+
+	return ret;
+}
+
+static void aat1290_init_flash_settings(struct aat1290_led *led,
+					 struct aat1290_led_settings *s)
+{
+	struct led_flash_setting *setting;
+
+	/* Init flash timeout setting */
+	setting = &s->flash_timeout;
+	setting->min = led->max_flash_tm / AAT1290_FLASH_TM_NUM_LEVELS;
+	setting->max = setting->min * AAT1290_FLASH_TM_NUM_LEVELS;
+	setting->step = setting->min;
+	setting->val = setting->max;
+}
+
+static const struct led_flash_ops flash_ops = {
+	.strobe_set = aat1290_led_flash_strobe_set,
+	.timeout_set = aat1290_led_flash_timeout_set,
+};
+
+static int aat1290_led_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *dev_node = pdev->dev.of_node;
+	struct aat1290_led *led;
+	struct led_classdev *led_cdev;
+	struct led_classdev_flash *fled_cdev;
+	struct aat1290_led_settings settings;
+	int flen_gpio, enset_gpio, ret;
+
+	led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
+	if (!led)
+		return -ENOMEM;
+
+	led->pdev = pdev;
+	platform_set_drvdata(pdev, led);
+
+	if (!dev_node)
+		return -ENXIO;
+
+	flen_gpio = of_get_gpio(dev_node, 0);
+	if (gpio_is_valid(flen_gpio)) {
+		ret = devm_gpio_request_one(dev, flen_gpio, GPIOF_DIR_OUT,
+						"aat1290_flen");
+		if (ret < 0) {
+			dev_err(dev,
+				"failed to request GPIO %d, error %d\n",
+							flen_gpio, ret);
+			return ret;
+		}
+	} else {
+		return -EINVAL;
+	}
+	led->flen_gpio = flen_gpio;
+
+	enset_gpio = of_get_gpio(dev_node, 1);
+	if (gpio_is_valid(enset_gpio)) {
+		ret = devm_gpio_request_one(dev, enset_gpio, GPIOF_DIR_OUT,
+						"aat1290_en_set");
+		if (ret < 0) {
+			dev_err(dev,
+				"failed to request GPIO %d, error %d\n",
+							enset_gpio, ret);
+			return ret;
+		}
+	} else {
+		return -EINVAL;
+	}
+	led->en_set_gpio = enset_gpio;
+
+	fled_cdev = &led->fled_cdev;
+	led_cdev = &fled_cdev->led_cdev;
+
+	ret = aat1290_led_parse_dt(led, &pdev->dev, &led_cdev->name);
+	if (ret < 0)
+		return ret;
+
+	/* Init flash settings */
+	aat1290_init_flash_settings(led, &settings);
+
+	fled_cdev->timeout = settings.flash_timeout;
+	fled_cdev->ops = &flash_ops;
+
+	/* Init LED class */
+	led_cdev->brightness_set = aat1290_led_brightness_set;
+	led_cdev->brightness_set_sync = aat1290_led_brightness_set_sync;
+	led_cdev->max_brightness = AAT1290_MM_CURRENT_SCALE_SIZE;
+	led_cdev->flags |= LED_DEV_CAP_FLASH;
+
+	INIT_WORK(&led->work_brightness_set, aat1290_brightness_set_work);
+
+	/* Register in the LED subsystem. */
+	ret = led_classdev_flash_register(&pdev->dev, fled_cdev);
+	if (ret < 0)
+		return ret;
+
+	mutex_init(&led->lock);
+
+	return 0;
+}
+
+static int aat1290_led_remove(struct platform_device *pdev)
+{
+	struct aat1290_led *led = platform_get_drvdata(pdev);
+
+	led_classdev_flash_unregister(&led->fled_cdev);
+	cancel_work_sync(&led->work_brightness_set);
+
+	mutex_destroy(&led->lock);
+
+	return 0;
+}
+
+static struct of_device_id aat1290_led_dt_match[] = {
+	{.compatible = "skyworks,aat1290"},
+	{},
+};
+
+static struct platform_driver aat1290_led_driver = {
+	.probe		= aat1290_led_probe,
+	.remove		= aat1290_led_remove,
+	.driver		= {
+		.name	= "aat1290-led",
+		.owner	= THIS_MODULE,
+		.of_match_table = aat1290_led_dt_match,
+	},
+};
+
+module_platform_driver(aat1290_led_driver);
+
+MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
+MODULE_DESCRIPTION("Skyworks Current Regulator for Flash LEDs");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

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

* [PATCH/RFC v11 12/20] of: Add Skyworks Solutions, Inc. vendor prefix
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (10 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 11/20] leds: Add driver for AAT1290 current regulator Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 13/20] DT: Add documentation for the Skyworks AAT1290 Jacek Anaszewski
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala

Use "skyworks" as the vendor prefix for the Skyworks Solutions, Inc.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
---
 .../devicetree/bindings/vendor-prefixes.txt        |    1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 389ca13..9276e7f 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -153,6 +153,7 @@ ricoh	Ricoh Co. Ltd.
 rockchip	Fuzhou Rockchip Electronics Co., Ltd
 samsung	Samsung Semiconductor
 sandisk	Sandisk Corporation
+skyworks	Skyworks Solutions, Inc.
 sbs	Smart Battery System
 schindler	Schindler
 seagate	Seagate Technology PLC
-- 
1.7.9.5

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

* [PATCH/RFC v11 13/20] DT: Add documentation for the Skyworks AAT1290
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (11 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 12/20] of: Add Skyworks Solutions, Inc. vendor prefix Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 14/20] exynos4-is: Add support for v4l2-flash subdevs Jacek Anaszewski
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

This patch adds device tree binding documentation for
1.5A Step-Up Current Regulator for Flash LEDs.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
---
 .../devicetree/bindings/leds/leds-aat1290.txt      |   43 ++++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/leds/leds-aat1290.txt

diff --git a/Documentation/devicetree/bindings/leds/leds-aat1290.txt b/Documentation/devicetree/bindings/leds/leds-aat1290.txt
new file mode 100644
index 0000000..78aa7da
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-aat1290.txt
@@ -0,0 +1,43 @@
+* Skyworks Solutions, Inc. AAT1290 Current Regulator for Flash LEDs
+
+The device is controlled through two pins: FL_EN and EN_SET. The pins when,
+asserted high, enable flash strobe and movie mode (max 1/2 of flash current)
+respectively. In order to add a capability of selecting the strobe signal source
+(e.g. GPIO or camera sensor) there is an additional switch required, independent
+of the flash chip.
+
+Such a switch is provided on the exynos4412-trats2 board. The switch is
+configured so that it is possible to change EN_SET and FL_EN signal sources
+simultaneously with one GPIO. This gpio can be provided in the third element
+of 'gpios ' property.
+
+Required properties:
+
+- compatible : Must be "skyworks,aat1290".
+- gpios : Two gpio pins in order FLEN, EN/SET, and optional third
+	  HW_FLASH_EN gpio for controlling the HW_FLASH_SW mux.
+
+The LED connected to the device must be represented by a child node -
+see Documentation/devicetree/bindings/leds/common.txt.
+
+Required properties of the LED child node:
+- label : see Documentation/devicetree/bindings/leds/common.txt
+- flash-max-microamp : Maximum intensity in microamperes of the flash LED -
+		       it can be calculated using following formula:
+		       I = 1A * 162kohm / Rset
+- flash-timeout-us : Maximum flash timeout in microseconds -
+		     it can be calculated using following formula:
+		     T = 8.82 * 10^9 * Ct.
+
+Example (by Ct = 220nF, Rset = 160kohm)
+
+aat1290 {
+	compatible = "skyworks,aat1290";
+	gpios = <&gpj1 1 0>, <&gpj1 2 0>, <&gpj1 0 0>;
+
+	camera_flash: flash-led {
+		label = "aat1290-flash";
+		flash-max-microamp = <1012500>
+		flash-timeout-us = <1940000>;
+	};
+};
-- 
1.7.9.5

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

* [PATCH/RFC v11 14/20] exynos4-is: Add support for v4l2-flash subdevs
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (12 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 13/20] DT: Add documentation for the Skyworks AAT1290 Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 15/20] v4l2-ctrls: Add V4L2_CID_FLASH_SYNC_STROBE control Jacek Anaszewski
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

This patch adds support for external v4l2-flash devices.
The support includes parsing "flashes" DT property
and asynchronous subdevice registration.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/media/platform/exynos4-is/media-dev.c |   36 +++++++++++++++++++++++--
 drivers/media/platform/exynos4-is/media-dev.h |   13 ++++++++-
 2 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index f315ef9..8dd0e5d 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -451,6 +451,25 @@ rpm_put:
 	return ret;
 }
 
+static void fimc_md_register_flash_entities(struct fimc_md *fmd)
+{
+	struct device_node *parent = fmd->pdev->dev.of_node;
+	struct device_node *np;
+	int i = 0;
+
+	do {
+		np = of_parse_phandle(parent, "flashes", i);
+		if (np) {
+			fmd->flash[fmd->num_flashes].asd.match_type =
+							V4L2_ASYNC_MATCH_OF;
+			fmd->flash[fmd->num_flashes].asd.match.of.node = np;
+			fmd->num_flashes++;
+			fmd->async_subdevs[fmd->num_sensors + i] =
+						&fmd->flash[i].asd;
+		}
+	} while (np && (++i < FIMC_MAX_FLASHES));
+}
+
 static int __of_get_csis_id(struct device_node *np)
 {
 	u32 reg = 0;
@@ -1275,6 +1294,15 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
 	struct fimc_sensor_info *si = NULL;
 	int i;
 
+	/* Register flash subdev if detected any */
+	for (i = 0; i < ARRAY_SIZE(fmd->flash); i++) {
+		if (fmd->flash[i].asd.match.of.node == subdev->dev->of_node) {
+			fmd->flash[i].subdev = subdev;
+			fmd->num_flashes++;
+			return 0;
+		}
+	}
+
 	/* Find platform data for this sensor subdev */
 	for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++)
 		if (fmd->sensor[i].asd.match.of.node == subdev->dev->of_node)
@@ -1385,6 +1413,8 @@ static int fimc_md_probe(struct platform_device *pdev)
 		goto err_m_ent;
 	}
 
+	fimc_md_register_flash_entities(fmd);
+
 	mutex_unlock(&fmd->media_dev.graph_mutex);
 
 	ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
@@ -1401,12 +1431,14 @@ static int fimc_md_probe(struct platform_device *pdev)
 		goto err_attr;
 	}
 
-	if (fmd->num_sensors > 0) {
+	if (fmd->num_sensors > 0 || fmd->num_flashes > 0) {
 		fmd->subdev_notifier.subdevs = fmd->async_subdevs;
-		fmd->subdev_notifier.num_subdevs = fmd->num_sensors;
+		fmd->subdev_notifier.num_subdevs = fmd->num_sensors +
+							fmd->num_flashes;
 		fmd->subdev_notifier.bound = subdev_notifier_bound;
 		fmd->subdev_notifier.complete = subdev_notifier_complete;
 		fmd->num_sensors = 0;
+		fmd->num_flashes = 0;
 
 		ret = v4l2_async_notifier_register(&fmd->v4l2_dev,
 						&fmd->subdev_notifier);
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
index 0321454..feff9c8 100644
--- a/drivers/media/platform/exynos4-is/media-dev.h
+++ b/drivers/media/platform/exynos4-is/media-dev.h
@@ -34,6 +34,8 @@
 
 #define FIMC_MAX_SENSORS	4
 #define FIMC_MAX_CAMCLKS	2
+#define FIMC_MAX_FLASHES	2
+#define FIMC_MAX_ASYNC_SUBDEVS (FIMC_MAX_SENSORS + FIMC_MAX_FLASHES)
 #define DEFAULT_SENSOR_CLK_FREQ	24000000U
 
 /* LCD/ISP Writeback clocks (PIXELASYNCMx) */
@@ -93,6 +95,11 @@ struct fimc_sensor_info {
 	struct fimc_dev *host;
 };
 
+struct fimc_flash_info {
+	struct v4l2_subdev *subdev;
+	struct v4l2_async_subdev asd;
+};
+
 struct cam_clk {
 	struct clk_hw hw;
 	struct fimc_md *fmd;
@@ -104,6 +111,8 @@ struct cam_clk {
  * @csis: MIPI CSIS subdevs data
  * @sensor: array of registered sensor subdevs
  * @num_sensors: actual number of registered sensors
+ * @flash: array of registered flash subdevs
+ * @num_flashes: actual number of registered flashes
  * @camclk: external sensor clock information
  * @fimc: array of registered fimc devices
  * @fimc_is: fimc-is data structure
@@ -123,6 +132,8 @@ struct fimc_md {
 	struct fimc_csis_info csis[CSIS_MAX_ENTITIES];
 	struct fimc_sensor_info sensor[FIMC_MAX_SENSORS];
 	int num_sensors;
+	struct fimc_flash_info flash[FIMC_MAX_FLASHES];
+	int num_flashes;
 	struct fimc_camclk_info camclk[FIMC_MAX_CAMCLKS];
 	struct clk *wbclk[FIMC_MAX_WBCLKS];
 	struct fimc_lite *fimc_lite[FIMC_LITE_MAX_DEVS];
@@ -149,7 +160,7 @@ struct fimc_md {
 	} clk_provider;
 
 	struct v4l2_async_notifier subdev_notifier;
-	struct v4l2_async_subdev *async_subdevs[FIMC_MAX_SENSORS];
+	struct v4l2_async_subdev *async_subdevs[FIMC_MAX_ASYNC_SUBDEVS];
 
 	bool user_subdev_api;
 	spinlock_t slock;
-- 
1.7.9.5

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

* [PATCH/RFC v11 15/20] v4l2-ctrls: Add V4L2_CID_FLASH_SYNC_STROBE control
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (13 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 14/20] exynos4-is: Add support for v4l2-flash subdevs Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 16/20] media: Add registration helpers for V4L2 flash sub-devices Jacek Anaszewski
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

Add V4L2_CID_FLASH_SYNC_STROBE control for determining
whether a flash device strobe has to be synchronized
with other flash leds controller by the same device.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
---
 Documentation/DocBook/media/v4l/controls.xml |    9 +++++++++
 drivers/media/v4l2-core/v4l2-ctrls.c         |    2 ++
 include/uapi/linux/v4l2-controls.h           |    1 +
 3 files changed, 12 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 4e9462f..434d020 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -4562,6 +4562,15 @@ interface and may change in the future.</para>
     	    after strobe during which another strobe will not be
     	    possible. This is a read-only control.</entry>
     	  </row>
+    	  <row>
+            <entry spanname="id"><constant>V4L2_CID_FLASH_SYNC_STROBE</constant></entry>
+            <entry>menu</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="descr">Synchronized strobe: whether the flash
+	    should be strobed synchronously with the other one controlled
+	    by the same device.</entry>
+    	  </row>
     	  <row><entry></entry></row>
     	</tbody>
           </tgroup>
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 45c5b47..4bc7e00 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -846,6 +846,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_FLASH_FAULT:		return "Faults";
 	case V4L2_CID_FLASH_CHARGE:		return "Charge";
 	case V4L2_CID_FLASH_READY:		return "Ready to Strobe";
+	case V4L2_CID_FLASH_SYNC_STROBE:	return "Synchronize Strobe";
 
 	/* JPEG encoder controls */
 	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
@@ -1041,6 +1042,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_TUNE_DEEMPHASIS:
 	case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
 	case V4L2_CID_DETECT_MD_MODE:
+	case V4L2_CID_FLASH_SYNC_STROBE:
 		*type = V4L2_CTRL_TYPE_MENU;
 		break;
 	case V4L2_CID_LINK_FREQ:
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 9f6e108..7084696 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -837,6 +837,7 @@ enum v4l2_flash_strobe_source {
 
 #define V4L2_CID_FLASH_CHARGE			(V4L2_CID_FLASH_CLASS_BASE + 11)
 #define V4L2_CID_FLASH_READY			(V4L2_CID_FLASH_CLASS_BASE + 12)
+#define V4L2_CID_FLASH_SYNC_STROBE		(V4L2_CID_FLASH_CLASS_BASE + 13)
 
 
 /* JPEG-class control IDs */
-- 
1.7.9.5

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

* [PATCH/RFC v11 16/20] media: Add registration helpers for V4L2 flash sub-devices
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (14 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 15/20] v4l2-ctrls: Add V4L2_CID_FLASH_SYNC_STROBE control Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 17/20] Documentation: leds: Add description of v4l2-flash sub-device Jacek Anaszewski
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski, Hans Verkuil

This patch adds helper functions for registering/unregistering
LED Flash class devices as V4L2 sub-devices. The functions should
be called from the LED subsystem device driver. In case the
support for V4L2 Flash sub-devices is disabled in the kernel
config the functions' empty versions will be used.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Sakari Ailus <sakari.ailus@iki.fi>
Cc: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/Kconfig      |   11 +
 drivers/media/v4l2-core/Makefile     |    2 +
 drivers/media/v4l2-core/v4l2-flash.c |  640 ++++++++++++++++++++++++++++++++++
 include/media/v4l2-flash.h           |  146 ++++++++
 4 files changed, 799 insertions(+)
 create mode 100644 drivers/media/v4l2-core/v4l2-flash.c
 create mode 100644 include/media/v4l2-flash.h

diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index ba7e21a..f034f1a 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -44,6 +44,17 @@ config V4L2_MEM2MEM_DEV
         tristate
         depends on VIDEOBUF2_CORE
 
+# Used by LED subsystem flash drivers
+config V4L2_FLASH_LED_CLASS
+	tristate "Enable support for Flash sub-devices"
+	depends on VIDEO_V4L2_SUBDEV_API
+	depends on LEDS_CLASS_FLASH
+	---help---
+	  Say Y here to enable support for Flash sub-devices, which allow
+	  to control LED class devices with use of V4L2 Flash controls.
+
+	  When in doubt, say N.
+
 # Used by drivers that need Videobuf modules
 config VIDEOBUF_GEN
 	tristate
diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
index 63d29f2..44e858c 100644
--- a/drivers/media/v4l2-core/Makefile
+++ b/drivers/media/v4l2-core/Makefile
@@ -22,6 +22,8 @@ obj-$(CONFIG_VIDEO_TUNER) += tuner.o
 
 obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
 
+obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash.o
+
 obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
 obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
 obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
diff --git a/drivers/media/v4l2-core/v4l2-flash.c b/drivers/media/v4l2-core/v4l2-flash.c
new file mode 100644
index 0000000..bb38216
--- /dev/null
+++ b/drivers/media/v4l2-core/v4l2-flash.c
@@ -0,0 +1,640 @@
+/*
+ * V4L2 Flash LED sub-device registration helpers.
+ *
+ *	Copyright (C) 2015 Samsung Electronics Co., Ltd
+ *	Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/led-class-flash.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <media/v4l2-flash.h>
+
+#define has_flash_op(v4l2_flash, op)				\
+	(v4l2_flash && v4l2_flash->ops->op)
+
+#define call_flash_op(v4l2_flash, op, arg)			\
+		(has_flash_op(v4l2_flash, op) ?			\
+			v4l2_flash->ops->op(v4l2_flash, arg) :	\
+			-EINVAL)
+
+static enum led_brightness __intensity_to_led_brightness(
+					struct v4l2_ctrl *ctrl,
+					s32 intensity)
+{
+	s64 intensity64 = intensity - ctrl->minimum;
+
+	do_div(intensity64, ctrl->step);
+
+	/*
+	 * Indicator LEDs, unlike torch LEDs, are turned on/off basing on
+	 * the state of V4L2_CID_FLASH_INDICATOR_INTENSITY control only.
+	 * Therefore it must be possible to set it to 0 level which in
+	 * the LED subsystem reflects LED_OFF state.
+	 */
+	if (ctrl->id != V4L2_CID_FLASH_INDICATOR_INTENSITY)
+		++intensity64;
+
+	return intensity64;
+}
+
+static s32 __led_brightness_to_intensity(struct v4l2_ctrl *ctrl,
+					 enum led_brightness brightness)
+{
+	/*
+	 * Indicator LEDs, unlike torch LEDs, are turned on/off basing on
+	 * the state of V4L2_CID_FLASH_INDICATOR_INTENSITY control only.
+	 * Do not decrement brightness read from the LED subsystem for
+	 * indicator LED as it may equal 0. For torch LEDs this function
+	 * is called only when V4L2_FLASH_LED_MODE_TORCH is set and the
+	 * brightness read is guaranteed to be greater than 0. In the mode
+	 * V4L2_FLASH_LED_MODE_NONE the cached torch intensity value is used.
+	 */
+	if (ctrl->id != V4L2_CID_FLASH_INDICATOR_INTENSITY)
+		--brightness;
+
+	return (brightness * ctrl->step) + ctrl->minimum;
+}
+
+static void v4l2_flash_set_led_brightness(struct v4l2_flash *v4l2_flash,
+					struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
+	enum led_brightness brightness;
+
+	if (has_flash_op(v4l2_flash, intensity_to_led_brightness))
+		brightness = call_flash_op(v4l2_flash,
+					intensity_to_led_brightness,
+					ctrl->val);
+	else
+		brightness = __intensity_to_led_brightness(ctrl, ctrl->val);
+	/*
+	 * In case a LED Flash class driver provides ops for custom
+	 * brightness <-> intensity conversion, it also must have defined
+	 * related v4l2 control step == 1. In such a case a backward conversion
+	 * from led brightness to v4l2 intensity is required to find out the
+	 * the aligned intensity value.
+	 */
+	if (has_flash_op(v4l2_flash, led_brightness_to_intensity))
+		ctrl->val = call_flash_op(v4l2_flash,
+					led_brightness_to_intensity,
+					brightness);
+
+	if (ctrl == ctrls[TORCH_INTENSITY] &&
+	    ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
+		return;
+
+	led_set_brightness(&v4l2_flash->fled_cdev->led_cdev, brightness);
+}
+
+static int v4l2_flash_update_led_brightness(struct v4l2_flash *v4l2_flash,
+					struct v4l2_ctrl *ctrl)
+{
+	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
+	int ret;
+
+	/*
+	 * Update torch brightness only if in TORCH_MODE. In other modes torch
+	 * led is turned off, which would spuriously inform the user space that
+	 * V4L2_CID_FLASH_TORCH_INTENSITY control value has changed to 0.
+	 */
+	if (ctrl == ctrls[TORCH_INTENSITY] &&
+	    ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
+		return 0;
+
+	ret = led_update_brightness(led_cdev);
+	if (ret < 0)
+		return ret;
+
+	if (has_flash_op(v4l2_flash, led_brightness_to_intensity))
+		ctrl->val = call_flash_op(v4l2_flash,
+						led_brightness_to_intensity,
+						led_cdev->brightness);
+	else
+		ctrl->val = __led_brightness_to_intensity(ctrl,
+						led_cdev->brightness);
+
+	return 0;
+}
+
+static int v4l2_flash_g_volatile_ctrl(struct v4l2_ctrl *c)
+{
+	struct v4l2_flash *v4l2_flash = v4l2_ctrl_to_v4l2_flash(c);
+	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
+	bool is_strobing;
+	int ret;
+
+	switch (c->id) {
+	case V4L2_CID_FLASH_TORCH_INTENSITY:
+	case V4L2_CID_FLASH_INDICATOR_INTENSITY:
+		return v4l2_flash_update_led_brightness(v4l2_flash, c);
+	case V4L2_CID_FLASH_INTENSITY:
+		ret = led_update_flash_brightness(fled_cdev);
+		if (ret < 0)
+			return ret;
+		/* no conversion is needed */
+		c->val = fled_cdev->brightness.val;
+		return 0;
+	case V4L2_CID_FLASH_STROBE_STATUS:
+		ret = led_get_flash_strobe(fled_cdev, &is_strobing);
+		if (ret < 0)
+			return ret;
+		c->val = is_strobing;
+		return 0;
+	case V4L2_CID_FLASH_FAULT:
+		/* LED faults map directly to V4L2 flash faults */
+		return led_get_flash_fault(fled_cdev, &c->val);
+	default:
+		return -EINVAL;
+	}
+}
+
+static bool __software_strobe_mode_inactive(struct v4l2_ctrl **ctrls)
+{
+	return ((ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_FLASH) ||
+		(ctrls[STROBE_SOURCE] && (ctrls[STROBE_SOURCE]->val !=
+				V4L2_FLASH_STROBE_SOURCE_SOFTWARE)));
+}
+
+static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
+{
+	struct v4l2_flash *v4l2_flash = v4l2_ctrl_to_v4l2_flash(c);
+	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
+	bool external_strobe;
+	int ret = 0;
+
+	switch (c->id) {
+	case V4L2_CID_FLASH_LED_MODE:
+		switch (c->val) {
+		case V4L2_FLASH_LED_MODE_NONE:
+			led_set_brightness(led_cdev, LED_OFF);
+			return led_set_flash_strobe(fled_cdev, false);
+		case V4L2_FLASH_LED_MODE_FLASH:
+			/* Turn the torch LED off */
+			led_set_brightness(led_cdev, LED_OFF);
+			if (ctrls[STROBE_SOURCE]) {
+				external_strobe = (ctrls[STROBE_SOURCE]->val ==
+					V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
+
+				ret = call_flash_op(v4l2_flash,
+						external_strobe_set,
+						external_strobe);
+			}
+			return ret;
+		case V4L2_FLASH_LED_MODE_TORCH:
+			if (ctrls[STROBE_SOURCE]) {
+				ret = call_flash_op(v4l2_flash,
+						external_strobe_set,
+						false);
+				if (ret < 0)
+					return ret;
+			}
+			/* Stop flash strobing */
+			ret = led_set_flash_strobe(fled_cdev, false);
+			if (ret < 0)
+				return ret;
+
+			v4l2_flash_set_led_brightness(v4l2_flash,
+							ctrls[TORCH_INTENSITY]);
+			return 0;
+		}
+		break;
+	case V4L2_CID_FLASH_STROBE_SOURCE:
+		external_strobe = (c->val == V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
+		/*
+		 * For some hardware arrangements setting external flash strobe
+		 * may spuriously turn the torch mode off. Therefore cache only
+		 * this settting in such a case and apply it while switching to
+		 * the torch mode.
+		 */
+		if ((ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_FLASH) &&
+		    external_strobe)
+			return 0;
+
+		return call_flash_op(v4l2_flash, external_strobe_set,
+					external_strobe);
+	case V4L2_CID_FLASH_STROBE:
+		if (__software_strobe_mode_inactive(ctrls))
+			return -EBUSY;
+		return led_set_flash_strobe(fled_cdev, true);
+	case V4L2_CID_FLASH_STROBE_STOP:
+		if (__software_strobe_mode_inactive(ctrls))
+			return -EBUSY;
+		return led_set_flash_strobe(fled_cdev, false);
+	case V4L2_CID_FLASH_TIMEOUT:
+		/* no conversion is needed */
+		return led_set_flash_timeout(fled_cdev, c->val);
+	case V4L2_CID_FLASH_INTENSITY:
+		/* no conversion is needed */
+		return led_set_flash_brightness(fled_cdev, c->val);
+	case V4L2_CID_FLASH_TORCH_INTENSITY:
+	case V4L2_CID_FLASH_INDICATOR_INTENSITY:
+		v4l2_flash_set_led_brightness(v4l2_flash, c);
+		return 0;
+	case V4L2_CID_FLASH_SYNC_STROBE:
+		fled_cdev->sync_led_id = c->val;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static const struct v4l2_ctrl_ops v4l2_flash_ctrl_ops = {
+	.g_volatile_ctrl = v4l2_flash_g_volatile_ctrl,
+	.s_ctrl = v4l2_flash_s_ctrl,
+};
+
+static void fill_ctrl_init_data(struct v4l2_flash *v4l2_flash,
+			  struct v4l2_flash_ctrl_config *flash_ctrl_cfg,
+			  struct v4l2_flash_ctrl_data *ctrl_init_data)
+{
+	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
+	const struct led_flash_ops *fled_cdev_ops = fled_cdev->ops;
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	struct v4l2_ctrl_config *ctrl_cfg;
+	u32 mask;
+
+	/* Init FLASH_FAULT ctrl data */
+	if (flash_ctrl_cfg->flash_faults) {
+		ctrl_init_data[FLASH_FAULT].cid = V4L2_CID_FLASH_FAULT;
+		ctrl_cfg = &ctrl_init_data[FLASH_FAULT].config;
+		ctrl_cfg->id = V4L2_CID_FLASH_FAULT;
+		ctrl_cfg->max = flash_ctrl_cfg->flash_faults;
+		ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
+				  V4L2_CTRL_FLAG_READ_ONLY;
+	}
+
+	/* Init INDICATOR_INTENSITY ctrl data */
+	if (flash_ctrl_cfg->indicator_led) {
+		ctrl_init_data[INDICATOR_INTENSITY].cid =
+					V4L2_CID_FLASH_INDICATOR_INTENSITY;
+		ctrl_init_data[INDICATOR_INTENSITY].config =
+						flash_ctrl_cfg->intensity;
+		ctrl_cfg = &ctrl_init_data[INDICATOR_INTENSITY].config;
+		ctrl_cfg->id = V4L2_CID_FLASH_INDICATOR_INTENSITY;
+		ctrl_cfg->min = 0;
+		ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE;
+
+		/* Indicator LED can have only faults and intensity controls. */
+		return;
+	}
+
+	/* Init FLASH_LED_MODE ctrl data */
+	mask = 1 << V4L2_FLASH_LED_MODE_NONE |
+	       1 << V4L2_FLASH_LED_MODE_TORCH;
+	if (led_cdev->flags & LED_DEV_CAP_FLASH)
+		mask |= 1 << V4L2_FLASH_LED_MODE_FLASH;
+
+	ctrl_init_data[LED_MODE].cid = V4L2_CID_FLASH_LED_MODE;
+	ctrl_cfg = &ctrl_init_data[LED_MODE].config;
+	ctrl_cfg->id = V4L2_CID_FLASH_LED_MODE;
+	ctrl_cfg->max = V4L2_FLASH_LED_MODE_TORCH;
+	ctrl_cfg->menu_skip_mask = ~mask;
+	ctrl_cfg->def = V4L2_FLASH_LED_MODE_NONE;
+	ctrl_cfg->flags = 0;
+
+	/* Init TORCH_INTENSITY ctrl data */
+	ctrl_init_data[TORCH_INTENSITY].cid = V4L2_CID_FLASH_TORCH_INTENSITY;
+	ctrl_init_data[TORCH_INTENSITY].config = flash_ctrl_cfg->intensity;
+	ctrl_cfg = &ctrl_init_data[TORCH_INTENSITY].config;
+	ctrl_cfg->id = V4L2_CID_FLASH_TORCH_INTENSITY;
+	ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE;
+
+	if (!(led_cdev->flags & LED_DEV_CAP_FLASH))
+		return;
+
+	/* Init FLASH_STROBE ctrl data */
+	ctrl_init_data[FLASH_STROBE].cid = V4L2_CID_FLASH_STROBE;
+	ctrl_cfg = &ctrl_init_data[FLASH_STROBE].config;
+	ctrl_cfg->id = V4L2_CID_FLASH_STROBE;
+
+	/* Init STROBE_STOP ctrl data */
+	ctrl_init_data[STROBE_STOP].cid = V4L2_CID_FLASH_STROBE_STOP;
+	ctrl_cfg = &ctrl_init_data[STROBE_STOP].config;
+	ctrl_cfg->id = V4L2_CID_FLASH_STROBE_STOP;
+
+	/* Init FLASH_STROBE_SOURCE ctrl data */
+	if (flash_ctrl_cfg->has_external_strobe) {
+		mask = (1 << V4L2_FLASH_STROBE_SOURCE_SOFTWARE) |
+		       (1 << V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
+		ctrl_init_data[STROBE_SOURCE].cid =
+					V4L2_CID_FLASH_STROBE_SOURCE;
+		ctrl_cfg = &ctrl_init_data[STROBE_SOURCE].config;
+		ctrl_cfg->id = V4L2_CID_FLASH_STROBE_SOURCE;
+		ctrl_cfg->max = V4L2_FLASH_STROBE_SOURCE_EXTERNAL;
+		ctrl_cfg->menu_skip_mask = ~mask;
+		ctrl_cfg->def = V4L2_FLASH_STROBE_SOURCE_SOFTWARE;
+	}
+
+	/* Init STROBE_STATUS ctrl data */
+	if (fled_cdev_ops->strobe_get) {
+		ctrl_init_data[STROBE_STATUS].cid =
+					V4L2_CID_FLASH_STROBE_STATUS;
+		ctrl_cfg = &ctrl_init_data[STROBE_STATUS].config;
+		ctrl_cfg->id = V4L2_CID_FLASH_STROBE_STATUS;
+		ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
+				  V4L2_CTRL_FLAG_READ_ONLY;
+	}
+
+	/* Init FLASH_TIMEOUT ctrl data */
+	if (fled_cdev_ops->timeout_set) {
+		ctrl_init_data[FLASH_TIMEOUT].cid = V4L2_CID_FLASH_TIMEOUT;
+		ctrl_init_data[FLASH_TIMEOUT].config =
+					flash_ctrl_cfg->flash_timeout;
+		ctrl_cfg = &ctrl_init_data[FLASH_TIMEOUT].config;
+		ctrl_cfg->id = V4L2_CID_FLASH_TIMEOUT;
+		ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE;
+	}
+
+	/* Init FLASH_INTENSITY ctrl data */
+	if (fled_cdev_ops->flash_brightness_set) {
+		ctrl_init_data[FLASH_INTENSITY].cid = V4L2_CID_FLASH_INTENSITY;
+		ctrl_init_data[FLASH_INTENSITY].config =
+					flash_ctrl_cfg->flash_intensity;
+		ctrl_cfg = &ctrl_init_data[FLASH_INTENSITY].config;
+		ctrl_cfg->id = V4L2_CID_FLASH_INTENSITY;
+		ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE;
+	}
+}
+
+static int v4l2_flash_init_sync_strobe_menu(struct v4l2_flash *v4l2_flash)
+{
+	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
+	struct v4l2_ctrl *ctrl;
+	int i = 0;
+
+	v4l2_flash->sync_strobe_menu =
+			devm_kcalloc(fled_cdev->led_cdev.dev->parent,
+					fled_cdev->num_sync_leds + 1,
+					sizeof(char *),
+					GFP_KERNEL);
+
+	if (!v4l2_flash->sync_strobe_menu)
+		return -ENOMEM;
+
+	v4l2_flash->sync_strobe_menu[0] = "none";
+
+	for (i = 0; i < fled_cdev->num_sync_leds; ++i)
+		v4l2_flash->sync_strobe_menu[i + 1] =
+				(char *) fled_cdev->sync_leds[i]->led_cdev.name;
+
+	ctrl = v4l2_ctrl_new_std_menu_items(
+		&v4l2_flash->hdl, &v4l2_flash_ctrl_ops,
+		V4L2_CID_FLASH_SYNC_STROBE,
+		fled_cdev->num_sync_leds,
+		0, 0,
+		(const char * const *) v4l2_flash->sync_strobe_menu);
+
+	return 0;
+}
+
+static int v4l2_flash_init_controls(struct v4l2_flash *v4l2_flash,
+				struct v4l2_flash_ctrl_config *flash_ctrl_cfg)
+
+{
+	struct led_classdev *led_cdev = &v4l2_flash->fled_cdev->led_cdev;
+	struct v4l2_flash_ctrl_data *ctrl_init_data;
+	struct v4l2_ctrl *ctrl;
+	struct v4l2_ctrl_config *ctrl_cfg;
+	int i, ret, num_ctrls = 0;
+
+	/* allocate memory dynamically so as not to exceed stack frame size */
+	ctrl_init_data = kcalloc(NUM_FLASH_CTRLS, sizeof(*ctrl_init_data),
+					GFP_KERNEL);
+	if (!ctrl_init_data)
+		return -ENOMEM;
+
+	fill_ctrl_init_data(v4l2_flash, flash_ctrl_cfg, ctrl_init_data);
+
+	for (i = 0; i < NUM_FLASH_CTRLS; ++i)
+		if (ctrl_init_data[i].cid)
+			++num_ctrls;
+
+	v4l2_ctrl_handler_init(&v4l2_flash->hdl, num_ctrls);
+
+	for (i = 0; i < NUM_FLASH_CTRLS; ++i) {
+		ctrl_cfg = &ctrl_init_data[i].config;
+		if (!ctrl_init_data[i].cid)
+			continue;
+
+		if (ctrl_cfg->id == V4L2_CID_FLASH_LED_MODE ||
+		    ctrl_cfg->id == V4L2_CID_FLASH_STROBE_SOURCE)
+			ctrl = v4l2_ctrl_new_std_menu(&v4l2_flash->hdl,
+						&v4l2_flash_ctrl_ops,
+						ctrl_cfg->id,
+						ctrl_cfg->max,
+						ctrl_cfg->menu_skip_mask,
+						ctrl_cfg->def);
+		else
+			ctrl = v4l2_ctrl_new_std(&v4l2_flash->hdl,
+						&v4l2_flash_ctrl_ops,
+						ctrl_cfg->id,
+						ctrl_cfg->min,
+						ctrl_cfg->max,
+						ctrl_cfg->step,
+						ctrl_cfg->def);
+
+		if (ctrl)
+			ctrl->flags |= ctrl_cfg->flags;
+
+		if (i <= SYNC_STROBE)
+			v4l2_flash->ctrls[i] = ctrl;
+	}
+
+	kfree(ctrl_init_data);
+
+	if (led_cdev->flags & LED_DEV_CAP_SYNC_STROBE) {
+		ret = v4l2_flash_init_sync_strobe_menu(v4l2_flash);
+		if (ret < 0)
+			goto error_free_handler;
+	}
+
+	if (v4l2_flash->hdl.error) {
+		ret = v4l2_flash->hdl.error;
+		goto error_free_handler;
+	}
+
+	v4l2_ctrl_handler_setup(&v4l2_flash->hdl);
+
+	v4l2_flash->sd.ctrl_handler = &v4l2_flash->hdl;
+
+	return 0;
+
+error_free_handler:
+	v4l2_ctrl_handler_free(&v4l2_flash->hdl);
+	return ret;
+}
+
+static int __sync_device_with_v4l2_controls(struct v4l2_flash *v4l2_flash)
+{
+	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
+	struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
+	int ret = 0;
+
+	if (ctrls[SYNC_STROBE])
+		fled_cdev->sync_led_id = ctrls[SYNC_STROBE]->val;
+
+	if (ctrls[FLASH_TIMEOUT]) {
+		ret = led_set_flash_timeout(fled_cdev,
+					ctrls[FLASH_TIMEOUT]->val);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (ctrls[FLASH_INTENSITY]) {
+		ret = led_set_flash_brightness(fled_cdev,
+					ctrls[FLASH_INTENSITY]->val);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (ctrls[STROBE_SOURCE])
+		ret = call_flash_op(v4l2_flash, external_strobe_set, false);
+
+	if (ctrls[INDICATOR_INTENSITY])
+		v4l2_flash_set_led_brightness(v4l2_flash,
+						ctrls[INDICATOR_INTENSITY]);
+	else
+		v4l2_flash_set_led_brightness(v4l2_flash,
+						ctrls[TORCH_INTENSITY]);
+
+	return ret;
+}
+
+/*
+ * V4L2 subdev internal operations
+ */
+
+static int v4l2_flash_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_flash *v4l2_flash = v4l2_subdev_to_v4l2_flash(sd);
+	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	int ret = 0;
+
+	mutex_lock(&led_cdev->led_access);
+
+	if (!v4l2_fh_is_singular(&fh->vfh)) {
+		ret = -EBUSY;
+		goto unlock;
+	}
+
+	led_sysfs_disable(led_cdev);
+
+	ret = __sync_device_with_v4l2_controls(v4l2_flash);
+
+unlock:
+	mutex_unlock(&led_cdev->led_access);
+	return ret;
+}
+
+static int v4l2_flash_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_flash *v4l2_flash = v4l2_subdev_to_v4l2_flash(sd);
+	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	int ret = 0;
+
+	mutex_lock(&led_cdev->led_access);
+
+	if (v4l2_flash->ctrls[STROBE_SOURCE])
+		v4l2_ctrl_s_ctrl(v4l2_flash->ctrls[STROBE_SOURCE],
+				V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
+
+	led_sysfs_enable(led_cdev);
+
+	mutex_unlock(&led_cdev->led_access);
+
+	return ret;
+}
+
+static const struct v4l2_subdev_internal_ops v4l2_flash_subdev_internal_ops = {
+	.open = v4l2_flash_open,
+	.close = v4l2_flash_close,
+};
+
+static const struct v4l2_subdev_core_ops v4l2_flash_core_ops = {
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+};
+
+static const struct v4l2_subdev_ops v4l2_flash_subdev_ops = {
+	.core = &v4l2_flash_core_ops,
+};
+
+struct v4l2_flash *v4l2_flash_init(struct led_classdev_flash *fled_cdev,
+				   const struct v4l2_flash_ops *ops,
+				   struct v4l2_flash_ctrl_config *config)
+{
+	struct v4l2_flash *v4l2_flash;
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	struct v4l2_subdev *sd;
+	int ret;
+
+	if (!fled_cdev || !ops || !config)
+		return ERR_PTR(-EINVAL);
+
+	v4l2_flash = devm_kzalloc(led_cdev->dev, sizeof(*v4l2_flash),
+					GFP_KERNEL);
+	if (!v4l2_flash)
+		return ERR_PTR(-ENOMEM);
+
+	sd = &v4l2_flash->sd;
+	v4l2_flash->fled_cdev = fled_cdev;
+	v4l2_flash->ops = ops;
+	sd->dev = led_cdev->dev;
+	v4l2_subdev_init(sd, &v4l2_flash_subdev_ops);
+	sd->internal_ops = &v4l2_flash_subdev_internal_ops;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	strlcpy(sd->name, led_cdev->name, sizeof(sd->name));
+
+	ret = media_entity_init(&sd->entity, 0, NULL, 0);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
+
+	ret = v4l2_flash_init_controls(v4l2_flash, config);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	ret = v4l2_async_register_subdev(sd);
+	if (ret < 0)
+		goto err_async_register_sd;
+
+	return v4l2_flash;
+
+err_async_register_sd:
+	media_entity_cleanup(&sd->entity);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(v4l2_flash_init);
+
+void v4l2_flash_release(struct v4l2_flash *v4l2_flash)
+{
+	struct v4l2_subdev *sd = &v4l2_flash->sd;
+
+	if (!v4l2_flash)
+		return;
+
+	v4l2_async_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	media_entity_cleanup(&sd->entity);
+}
+EXPORT_SYMBOL_GPL(v4l2_flash_release);
+
+MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
+MODULE_DESCRIPTION("V4L2 Flash sub-device helpers");
+MODULE_LICENSE("GPL v2");
diff --git a/include/media/v4l2-flash.h b/include/media/v4l2-flash.h
new file mode 100644
index 0000000..e0d58cf
--- /dev/null
+++ b/include/media/v4l2-flash.h
@@ -0,0 +1,146 @@
+/*
+ * V4L2 Flash LED sub-device registration helpers.
+ *
+ *	Copyright (C) 2015 Samsung Electronics Co., Ltd
+ *	Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _V4L2_FLASH_H
+#define _V4L2_FLASH_H
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+struct led_classdev_flash;
+struct led_classdev;
+struct v4l2_flash;
+enum led_brightness;
+
+enum ctrl_init_data_id {
+	LED_MODE,
+	TORCH_INTENSITY,
+	FLASH_INTENSITY,
+	INDICATOR_INTENSITY,
+	FLASH_TIMEOUT,
+	STROBE_SOURCE,
+	SYNC_STROBE,
+	/*
+	 * Only above values are applicable to
+	 * the 'ctrls' array in the struct v4l2_flash.
+	 */
+	FLASH_STROBE,
+	STROBE_STOP,
+	STROBE_STATUS,
+	FLASH_FAULT,
+	NUM_FLASH_CTRLS,
+};
+
+/*
+ * struct v4l2_flash_ctrl_data - flash control initialization data, filled
+ *				basing on the features declared by the LED Flash
+ *				class driver in the v4l2_flash_ctrl_config
+ * @config:	initialization data for a control
+ * @cid:	contains v4l2 flash control id if the config
+ *		field was initialized, 0 otherwise
+ */
+struct v4l2_flash_ctrl_data {
+	struct v4l2_ctrl_config config;
+	u32 cid;
+};
+
+struct v4l2_flash_ops {
+	/* setup strobing the flash by hardware pin state assertion */
+	int (*external_strobe_set)(struct v4l2_flash *v4l2_flash,
+					bool enable);
+	/* convert intensity to brightness in a device specific manner */
+	enum led_brightness (*intensity_to_led_brightness)
+		(struct v4l2_flash *v4l2_flash, s32 intensity);
+	/* convert brightness to intensity in a device specific manner */
+	s32 (*led_brightness_to_intensity)
+		(struct v4l2_flash *v4l2_flash, enum led_brightness);
+};
+
+/**
+ * struct v4l2_flash_ctrl_config - V4L2 Flash controls initialization data
+ * @intensity:			constraints for the led in a non-flash mode
+ * @flash_intensity:		V4L2_CID_FLASH_INTENSITY settings constraints
+ * @flash_timeout:		V4L2_CID_FLASH_TIMEOUT constraints
+ * @flash_faults:		possible flash faults
+ * @has_external_strobe:	external strobe capability
+ * @indicator_led:		signifies that a led is of indicator type
+ */
+struct v4l2_flash_ctrl_config {
+	struct v4l2_ctrl_config intensity;
+	struct v4l2_ctrl_config flash_intensity;
+	struct v4l2_ctrl_config flash_timeout;
+	u32 flash_faults;
+	bool has_external_strobe:1;
+	bool indicator_led:1;
+};
+
+/**
+ * struct v4l2_flash - Flash sub-device context
+ * @fled_cdev:		LED Flash class device controlled by this sub-device
+ * @ops:		V4L2 specific flash ops
+ * @sd:			V4L2 sub-device
+ * @hdl:		flash controls handler
+ * @ctrls:		array of pointers to controls, whose values define
+ *			the sub-device state
+ * @sync_strobe_menu	leds available for flash strobe synchronization
+ */
+struct v4l2_flash {
+	struct led_classdev_flash *fled_cdev;
+	const struct v4l2_flash_ops *ops;
+
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *ctrls[SYNC_STROBE + 1];
+	char **sync_strobe_menu;
+};
+
+static inline struct v4l2_flash *v4l2_subdev_to_v4l2_flash(
+							struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct v4l2_flash, sd);
+}
+
+static inline struct v4l2_flash *v4l2_ctrl_to_v4l2_flash(struct v4l2_ctrl *c)
+{
+	return container_of(c->handler, struct v4l2_flash, hdl);
+}
+
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+/**
+ * v4l2_flash_init - initialize V4L2 flash led sub-device
+ * @fled_cdev:	the LED Flash class device to wrap
+ * @flash_ops:	V4L2 Flash device ops
+ * @config:	initialization data for V4L2 Flash controls
+ *
+ * Create V4L2 Flash sub-device wrapping given LED subsystem device.
+ *
+ * Returns: A valid pointer, or, when an error occurs, the return
+ * value is encoded using ERR_PTR(). Use IS_ERR() to check and
+ * PTR_ERR() to obtain the numeric return value.
+ */
+struct v4l2_flash *v4l2_flash_init(struct led_classdev_flash *fled_cdev,
+				   const struct v4l2_flash_ops *ops,
+				   struct v4l2_flash_ctrl_config *config);
+
+/**
+ * v4l2_flash_release - release V4L2 Flash sub-device
+ * @flash: the V4L2 Flash sub-device to release
+ *
+ * Release V4L2 Flash sub-device.
+ */
+void v4l2_flash_release(struct v4l2_flash *v4l2_flash);
+
+#else
+#define v4l2_flash_init(fled_cdev, ops, config) (NULL)
+#define v4l2_flash_release(v4l2_flash)
+#endif /* CONFIG_V4L2_FLASH_LED_CLASS */
+
+#endif /* _V4L2_FLASH_H */
-- 
1.7.9.5

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

* [PATCH/RFC v11 17/20] Documentation: leds: Add description of v4l2-flash sub-device
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (15 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 16/20] media: Add registration helpers for V4L2 flash sub-devices Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 18/20] DT: Add documentation for exynos4-is 'flashes' property Jacek Anaszewski
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski

This patch extends LED Flash class documention by
the description of interactions with v4l2-flash sub-device.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
---
 Documentation/leds/leds-class-flash.txt |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Documentation/leds/leds-class-flash.txt b/Documentation/leds/leds-class-flash.txt
index ff03a66..dc46ae0 100644
--- a/Documentation/leds/leds-class-flash.txt
+++ b/Documentation/leds/leds-class-flash.txt
@@ -30,3 +30,16 @@ Following sysfs attributes are exposed for controlling flash LED devices:
 	- available_sync_leds
 	- flash_sync_strobe
 	- flash_fault
+
+A LED subsystem driver can be controlled also from the level of VideoForLinux2
+subsystem. In order to enable this CONFIG_V4L2_FLASH_LED_CLASS symbol has to
+be defined in the kernel config. The driver must call the v4l2_flash_init
+function to get registered in the V4L2 subsystem. On remove the
+v4l2_flash_release function has to be called (see <media/v4l2-flash.h>).
+
+After proper initialization a V4L2 Flash sub-device is created. The sub-device
+exposes a number of V4L2 controls, which allow for controlling a LED Flash class
+device with use of its internal kernel API.
+Opening the V4L2 Flash sub-device makes the LED subsystem sysfs interface
+unavailable. The interface is re-enabled after the V4L2 Flash sub-device
+is closed.
-- 
1.7.9.5

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

* [PATCH/RFC v11 18/20] DT: Add documentation for exynos4-is 'flashes' property
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (16 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 17/20] Documentation: leds: Add description of v4l2-flash sub-device Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 19/20] leds: max77693: add support for V4L2 Flash sub-device Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 20/20] leds: aat1290: " Jacek Anaszewski
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala

This patch adds a description of 'flashes' property
to the samsung-fimc.txt.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
---
 .../devicetree/bindings/media/samsung-fimc.txt     |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/samsung-fimc.txt b/Documentation/devicetree/bindings/media/samsung-fimc.txt
index 922d6f8..cb0e263 100644
--- a/Documentation/devicetree/bindings/media/samsung-fimc.txt
+++ b/Documentation/devicetree/bindings/media/samsung-fimc.txt
@@ -40,6 +40,13 @@ should be inactive. For the "active-a" state the camera port A must be activated
 and the port B deactivated and for the state "active-b" it should be the other
 way around.
 
+Optional properties:
+
+- flashes - Array of phandles to the flash LEDs that can be controlled by the
+	    sub-devices contained in this media device. Flash LED is
+	    represented by a child node of a flash LED device
+	    (see Documentation/devicetree/bindings/leds/common.txt).
+
 The 'camera' node must include at least one 'fimc' child node.
 
 
@@ -166,6 +173,7 @@ Example:
 		clock-output-names = "cam_a_clkout", "cam_b_clkout";
 		pinctrl-names = "default";
 		pinctrl-0 = <&cam_port_a_clk_active>;
+		flashes = <&camera_flash>, <&system_torch>;
 		status = "okay";
 		#address-cells = <1>;
 		#size-cells = <1>;
-- 
1.7.9.5

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

* [PATCH/RFC v11 19/20] leds: max77693: add support for V4L2 Flash sub-device
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (17 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 18/20] DT: Add documentation for exynos4-is 'flashes' property Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  2015-02-18 16:20 ` [PATCH/RFC v11 20/20] leds: aat1290: " Jacek Anaszewski
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski, Sakari Ailus

Add support for V4L2 Flash sub-device to the max77693 LED Flash class
driver. The support allows for V4L2 Flash sub-device to take the control
of the LED Flash class device.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/leds/leds-max77693.c |  149 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 141 insertions(+), 8 deletions(-)

diff --git a/drivers/leds/leds-max77693.c b/drivers/leds/leds-max77693.c
index 45d50d9..af06ca7 100644
--- a/drivers/leds/leds-max77693.c
+++ b/drivers/leds/leds-max77693.c
@@ -21,6 +21,7 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <media/v4l2-flash.h>
 
 #define MODE_OFF		0
 #define MODE_FLASH(a)		(1 << (a))
@@ -64,6 +65,8 @@ struct max77693_sub_led {
 	struct led_classdev_flash fled_cdev;
 	/* assures led-triggers compatibility */
 	struct work_struct work_brightness_set;
+	/* V4L2 Flash device */
+	struct v4l2_flash *v4l2_flash;
 
 	/* brightness cache */
 	unsigned int torch_brightness;
@@ -640,6 +643,32 @@ unlock:
 	return ret;
 }
 
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+static int max77693_led_external_strobe_set(
+				struct v4l2_flash *v4l2_flash,
+				bool enable)
+{
+	struct max77693_sub_led *sub_led =
+				flcdev_to_sub_led(v4l2_flash->fled_cdev);
+	struct max77693_led_device *led = sub_led_to_led(sub_led);
+	int fled_id = sub_led->fled_id;
+	int ret;
+
+	mutex_lock(&led->lock);
+
+	if (enable)
+		ret = max77693_add_mode(led, MODE_FLASH_EXTERNAL(fled_id));
+	else
+		ret = max77693_clear_mode(led, MODE_FLASH_EXTERNAL(fled_id));
+
+	mutex_unlock(&led->lock);
+
+	return ret;
+}
+#else
+#define max77693_led_external_strobe_set(v4l2_flash, enable) (NULL)
+#endif
+
 static int max77693_led_flash_fault_get(
 				struct led_classdev_flash *fled_cdev,
 				u32 *fault)
@@ -688,7 +717,8 @@ static int max77693_led_flash_timeout_set(
 }
 
 static int max77693_led_parse_dt(struct max77693_led_device *led,
-				struct max77693_led_config_data *cfg)
+				struct max77693_led_config_data *cfg,
+				struct device_node **sub_nodes)
 {
 	struct device *dev = &led->pdev->dev;
 	struct max77693_sub_led *sub_leds = led->sub_leds;
@@ -734,6 +764,13 @@ static int max77693_led_parse_dt(struct max77693_led_device *led,
 			return -EINVAL;
 		}
 
+		if (sub_nodes[fled_id]) {
+			dev_err(dev,
+				"Conflicting \"led-sources\" DT properties\n");
+			return -EINVAL;
+		}
+
+		sub_nodes[fled_id] = child_node;
 		sub_leds[fled_id].fled_id = fled_id;
 
 		ret = of_property_read_string(child_node, "label",
@@ -825,11 +862,12 @@ static void max77693_led_validate_configuration(struct max77693_led_device *led,
 }
 
 static int max77693_led_get_configuration(struct max77693_led_device *led,
-				struct max77693_led_config_data *cfg)
+				struct max77693_led_config_data *cfg,
+				struct device_node **sub_nodes)
 {
 	int ret;
 
-	ret = max77693_led_parse_dt(led, cfg);
+	ret = max77693_led_parse_dt(led, cfg, sub_nodes);
 	if (ret < 0)
 		return ret;
 
@@ -853,6 +891,12 @@ static const struct led_flash_ops flash_ops = {
 	.fault_get		= max77693_led_flash_fault_get,
 };
 
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+static const struct v4l2_flash_ops v4l2_flash_ops = {
+	.external_strobe_set = max77693_led_external_strobe_set,
+};
+#endif
+
 static void max77693_init_flash_settings(struct max77693_led_device *led,
 					 int fled_id,
 					 struct max77693_led_config_data *cfg,
@@ -887,6 +931,46 @@ static void max77693_init_flash_settings(struct max77693_led_device *led,
 	setting->val = setting->max;
 }
 
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+static void max77693_init_v4l2_ctrl_config(int fled_id,
+					struct max77693_led_settings *s,
+					struct v4l2_flash_ctrl_config *config)
+{
+	struct led_flash_setting *setting;
+	struct v4l2_ctrl_config *c;
+
+	c = &config->intensity;
+	setting = &s->torch_brightness;
+	c->min = setting->min;
+	c->max = setting->max;
+	c->step = setting->step;
+	c->def = setting->val;
+
+	c = &config->flash_intensity;
+	setting = &s->flash_brightness;
+	c->min = setting->min;
+	c->max = setting->max;
+	c->step = setting->step;
+	c->def = setting->val;
+
+	c = &config->flash_timeout;
+	setting = &s->flash_timeout;
+	c->min = setting->min;
+	c->max = setting->max;
+	c->step = setting->step;
+	c->def = setting->val;
+
+	/* Init flash faults config */
+	config->flash_faults =	V4L2_FLASH_FAULT_OVER_VOLTAGE |
+				V4L2_FLASH_FAULT_SHORT_CIRCUIT |
+				V4L2_FLASH_FAULT_OVER_CURRENT;
+
+	config->has_external_strobe = true;
+}
+#else
+#define max77693_init_v4l2_ctrl_config(fled_id, s, config)
+#endif
+
 static int max77693_set_available_sync_led(struct max77693_led_device *led,
 						int fled_id)
 {
@@ -906,7 +990,8 @@ static int max77693_set_available_sync_led(struct max77693_led_device *led,
 
 static void max77693_init_fled_cdev(struct max77693_led_device *led,
 				int fled_id,
-				struct max77693_led_config_data *cfg)
+				struct max77693_led_config_data *cfg,
+				struct v4l2_flash_ctrl_config *v4l2_flash_cfg)
 {
 	struct led_classdev_flash *fled_cdev;
 	struct led_classdev *led_cdev;
@@ -915,6 +1000,8 @@ static void max77693_init_fled_cdev(struct max77693_led_device *led,
 
 	/* Initialize flash settings */
 	max77693_init_flash_settings(led, fled_id, cfg, &settings);
+	/* Initialize V4L2 Flash config basing on initialized settings */
+	max77693_init_v4l2_ctrl_config(fled_id, &settings, v4l2_flash_cfg);
 
 	/* Initialize LED Flash class device */
 	fled_cdev = &sub_led->fled_cdev;
@@ -937,15 +1024,52 @@ static void max77693_init_fled_cdev(struct max77693_led_device *led,
 	sub_led->flash_timeout = fled_cdev->timeout.val;
 }
 
+static int max77693_register_led(struct max77693_sub_led *sub_led,
+				 struct v4l2_flash_ctrl_config *v4l2_flash_cfg,
+				 struct device_node *sub_node)
+{
+	struct max77693_led_device *led = sub_led_to_led(sub_led);
+	struct led_classdev_flash *fled_cdev = &sub_led->fled_cdev;
+	struct device *dev = &led->pdev->dev;
+	int ret;
+
+	/* Register in the LED subsystem */
+	ret = led_classdev_flash_register(dev, fled_cdev);
+	if (ret < 0)
+		return ret;
+
+	of_node_get(sub_node);
+	fled_cdev->led_cdev.dev->of_node = sub_node;
+
+	/* Register in the V4L2 subsystem. */
+	sub_led->v4l2_flash = v4l2_flash_init(fled_cdev, &v4l2_flash_ops,
+						v4l2_flash_cfg);
+	if (IS_ERR(sub_led->v4l2_flash)) {
+		ret = PTR_ERR(sub_led->v4l2_flash);
+		goto err_v4l2_flash_init;
+	}
+
+	return 0;
+
+err_v4l2_flash_init:
+	of_node_put(sub_node);
+	led_classdev_flash_unregister(fled_cdev);
+	return ret;
+}
+
 static int max77693_led_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct max77693_dev *iodev = dev_get_drvdata(dev->parent);
 	struct max77693_led_device *led;
 	struct max77693_sub_led *sub_leds;
+	struct device_node *sub_nodes[2] = { NULL, NULL };
 	struct max77693_led_config_data cfg = {};
+	struct v4l2_flash_ctrl_config v4l2_flash_config[2];
 	int init_fled_cdev[2], i, ret;
 
+	memset(v4l2_flash_config, 0, sizeof(v4l2_flash_config));
+
 	led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
 	if (!led)
 		return -ENOMEM;
@@ -955,7 +1079,7 @@ static int max77693_led_probe(struct platform_device *pdev)
 	sub_leds = led->sub_leds;
 
 	platform_set_drvdata(pdev, led);
-	ret = max77693_led_get_configuration(led, &cfg);
+	ret = max77693_led_get_configuration(led, &cfg, sub_nodes);
 	if (ret < 0)
 		return ret;
 
@@ -971,7 +1095,8 @@ static int max77693_led_probe(struct platform_device *pdev)
 	/* Initialize LED Flash class device(s) */
 	for (i = FLED1; i <= FLED2; ++i)
 		if (init_fled_cdev[i])
-			max77693_init_fled_cdev(led, i, &cfg);
+			max77693_init_fled_cdev(led, i, &cfg,
+						&v4l2_flash_config[i]);
 
 	/* Setup sub-leds available for flash strobe synchronization */
 	if (cfg.num_leds == 2)
@@ -983,12 +1108,14 @@ static int max77693_led_probe(struct platform_device *pdev)
 
 	mutex_init(&led->lock);
 
-	/* Register LED Flash class device(s) */
+	/* Register LED Flash class and related V4L2 Flash device(s) */
 	for (i = FLED1; i <= FLED2; ++i) {
 		if (!init_fled_cdev[i])
 			continue;
 
-		ret = led_classdev_flash_register(dev, &sub_leds[i].fled_cdev);
+		ret = max77693_register_led(&sub_leds[i],
+					    &v4l2_flash_config[i],
+					    sub_nodes[i]);
 		if (ret < 0) {
 			/*
 			 * At this moment FLED1 might have been already
@@ -1008,6 +1135,8 @@ err_register_led2:
 	/* It is possible than only FLED2 was to be registered */
 	if (!init_fled_cdev[FLED1])
 		goto err_register_led1;
+	v4l2_flash_release(sub_leds[FLED1].v4l2_flash);
+	of_node_put(sub_leds[FLED1].fled_cdev.led_cdev.dev->of_node);
 	led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
 err_register_led1:
 	mutex_destroy(&led->lock);
@@ -1021,11 +1150,15 @@ static int max77693_led_remove(struct platform_device *pdev)
 	struct max77693_sub_led *sub_leds = led->sub_leds;
 
 	if (led->iout_joint || max77693_fled_used(led, FLED1)) {
+		v4l2_flash_release(sub_leds[FLED1].v4l2_flash);
+		of_node_put(sub_leds[FLED1].fled_cdev.led_cdev.dev->of_node);
 		led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
 		cancel_work_sync(&sub_leds[FLED1].work_brightness_set);
 	}
 
 	if (!led->iout_joint && max77693_fled_used(led, FLED2)) {
+		v4l2_flash_release(sub_leds[FLED2].v4l2_flash);
+		of_node_put(sub_leds[FLED2].fled_cdev.led_cdev.dev->of_node);
 		led_classdev_flash_unregister(&sub_leds[FLED2].fled_cdev);
 		cancel_work_sync(&sub_leds[FLED2].work_brightness_set);
 	}
-- 
1.7.9.5

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

* [PATCH/RFC v11 20/20] leds: aat1290: add support for V4L2 Flash sub-device
  2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
                   ` (18 preceding siblings ...)
  2015-02-18 16:20 ` [PATCH/RFC v11 19/20] leds: max77693: add support for V4L2 Flash sub-device Jacek Anaszewski
@ 2015-02-18 16:20 ` Jacek Anaszewski
  19 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-18 16:20 UTC (permalink / raw)
  To: linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, sakari.ailus,
	s.nawrocki, Jacek Anaszewski, Sakari Ailus

Add support for V4L2 Flash sub-device to the aat1290 LED Flash class
driver. The support allows for V4L2 Flash sub-device to take the control
of the LED Flash class device.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Bryan Wu <cooloney@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/leds/leds-aat1290.c |  163 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)

diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c
index b217f0a..0e32be7 100644
--- a/drivers/leds/leds-aat1290.c
+++ b/drivers/leds/leds-aat1290.c
@@ -20,6 +20,7 @@
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <media/v4l2-flash.h>
 #include <linux/workqueue.h>
 
 #define AAT1290_MOVIE_MODE_CURRENT_ADDR	17
@@ -46,6 +47,9 @@
 #define AAT1290_MM_CURRENT_SCALE_SIZE	15
 
 struct aat1290_led_settings {
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+	struct led_flash_setting torch_brightness;
+#endif
 	struct led_flash_setting flash_timeout;
 };
 
@@ -57,11 +61,19 @@ struct aat1290_led {
 
 	/* related LED Flash class device */
 	struct led_classdev_flash fled_cdev;
+	/* V4L2 Flash device */
+	struct v4l2_flash *v4l2_flash;
 
 	/* FLEN pin */
 	int flen_gpio;
 	/* EN|SET pin  */
 	int en_set_gpio;
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+	/* chooses flash strobe source - external or SoC gpio */
+	int ext_strobe_gpio;
+	/* movie mode current scale */
+	int *mm_current_scale;
+#endif
 
 	/* maximum flash timeout */
 	u32 max_flash_tm;
@@ -279,6 +291,15 @@ static void aat1290_init_flash_settings(struct aat1290_led *led,
 {
 	struct led_flash_setting *setting;
 
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+	/* Init flash intensity setting */
+	setting = &s->torch_brightness;
+	setting->min = led->mm_current_scale[0];
+	setting->max = led->mm_current_scale[AAT1290_MM_CURRENT_SCALE_SIZE - 1];
+	setting->step = 1;
+	setting->val = setting->max;
+#endif
+
 	/* Init flash timeout setting */
 	setting = &s->flash_timeout;
 	setting->min = led->max_flash_tm / AAT1290_FLASH_TM_NUM_LEVELS;
@@ -287,6 +308,97 @@ static void aat1290_init_flash_settings(struct aat1290_led *led,
 	setting->val = setting->max;
 }
 
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+enum led_brightness aat1290_intensity_to_brightness(
+					struct v4l2_flash *v4l2_flash,
+					s32 intensity)
+{
+	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
+	struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
+	int i;
+
+	for (i = AAT1290_MM_CURRENT_SCALE_SIZE - 1; i >= 0; --i)
+		if (intensity >= led->mm_current_scale[i])
+			return i + 1;
+
+	return 1;
+}
+
+s32 aat1290_brightness_to_intensity(struct v4l2_flash *v4l2_flash,
+					enum led_brightness brightness)
+{
+	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
+	struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
+
+	return led->mm_current_scale[brightness - 1];
+}
+
+static int aat1290_led_external_strobe_set(struct v4l2_flash *v4l2_flash,
+						bool enable)
+{
+	struct aat1290_led *led = fled_cdev_to_led(v4l2_flash->fled_cdev);
+
+	led->movie_mode = false;
+	gpio_set_value(led->flen_gpio, 0);
+	gpio_set_value(led->en_set_gpio, 0);
+	gpio_set_value(led->ext_strobe_gpio, enable);
+
+	return 0;
+}
+
+int init_mm_current_scale(struct aat1290_led *led)
+{
+	int max_mm_current_percent[] = { 20, 22, 25, 28, 32, 36, 40, 45, 50, 56,
+						63, 71, 79, 89, 100 };
+	int i, max_mm_current = AAT1290_MAX_MM_CURRENT(led->max_flash_current);
+
+	led->mm_current_scale = devm_kzalloc(&led->pdev->dev,
+						sizeof(max_mm_current_percent),
+						GFP_KERNEL);
+	if (!led->mm_current_scale)
+		return -ENOMEM;
+
+	for (i = 0; i < AAT1290_MM_CURRENT_SCALE_SIZE; ++i)
+		led->mm_current_scale[i] = max_mm_current *
+					  max_mm_current_percent[i] / 100;
+
+	return 0;
+}
+
+static void aat1290_init_v4l2_ctrl_config(struct aat1290_led *led,
+					struct aat1290_led_settings *s,
+					struct v4l2_flash_ctrl_config *config)
+{
+	struct led_flash_setting *setting;
+	struct v4l2_ctrl_config *c;
+
+	c = &config->intensity;
+	setting = &s->torch_brightness;
+	c->min = setting->min;
+	c->max = setting->max;
+	c->step = setting->step;
+	c->def = setting->val;
+
+	c = &config->flash_timeout;
+	setting = &s->flash_timeout;
+	c->min = setting->min;
+	c->max = setting->max;
+	c->step = setting->step;
+	c->def = setting->val;
+
+	config->has_external_strobe = gpio_is_valid(led->ext_strobe_gpio);
+}
+
+static const struct v4l2_flash_ops v4l2_flash_ops = {
+	.external_strobe_set = aat1290_led_external_strobe_set,
+	.intensity_to_led_brightness = aat1290_intensity_to_brightness,
+	.led_brightness_to_intensity = aat1290_brightness_to_intensity,
+};
+#else
+#define aat1290_init_v4l2_ctrl_config(led, s, config)
+#define init_mm_current_scale(led) (0)
+#endif
+
 static const struct led_flash_ops flash_ops = {
 	.strobe_set = aat1290_led_flash_strobe_set,
 	.timeout_set = aat1290_led_flash_timeout_set,
@@ -299,6 +411,10 @@ static int aat1290_led_probe(struct platform_device *pdev)
 	struct aat1290_led *led;
 	struct led_classdev *led_cdev;
 	struct led_classdev_flash *fled_cdev;
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+	struct v4l2_flash_ctrl_config v4l2_flash_config;
+	int ext_strobe_gpio;
+#endif
 	struct aat1290_led_settings settings;
 	int flen_gpio, enset_gpio, ret;
 
@@ -342,6 +458,21 @@ static int aat1290_led_probe(struct platform_device *pdev)
 	}
 	led->en_set_gpio = enset_gpio;
 
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+	ext_strobe_gpio = of_get_gpio(dev_node, 2);
+	if (gpio_is_valid(ext_strobe_gpio)) {
+		ret = devm_gpio_request_one(dev, ext_strobe_gpio, GPIOF_DIR_OUT,
+						"aat1290_en_hw_strobe");
+		if (ret < 0) {
+			dev_err(dev,
+				"failed to request GPIO %d, error %d\n",
+							ext_strobe_gpio, ret);
+			return ret;
+		}
+	}
+	led->ext_strobe_gpio = ext_strobe_gpio;
+#endif
+
 	fled_cdev = &led->fled_cdev;
 	led_cdev = &fled_cdev->led_cdev;
 
@@ -349,9 +480,20 @@ static int aat1290_led_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;
 
+	/*
+	 * Initialize non-linear movie mode current scale basing
+	 * on the max flash current from Device Tree binding.
+	 */
+	ret = init_mm_current_scale(led);
+	if (ret < 0)
+		return ret;
+
 	/* Init flash settings */
 	aat1290_init_flash_settings(led, &settings);
 
+	/* Init V4L2 Flash controls basing on initialized settings */
+	aat1290_init_v4l2_ctrl_config(led, &settings, &v4l2_flash_config);
+
 	fled_cdev->timeout = settings.flash_timeout;
 	fled_cdev->ops = &flash_ops;
 
@@ -370,13 +512,34 @@ static int aat1290_led_probe(struct platform_device *pdev)
 
 	mutex_init(&led->lock);
 
+	of_node_get(dev_node);
+	led_cdev->dev->of_node = dev_node;
+
+	/* Create V4L2 Flash subdev. */
+	led->v4l2_flash = v4l2_flash_init(fled_cdev,
+					  &v4l2_flash_ops,
+					  &v4l2_flash_config);
+	if (IS_ERR(led->v4l2_flash)) {
+		ret = PTR_ERR(led->v4l2_flash);
+		goto error_v4l2_flash_init;
+	}
+
 	return 0;
+
+error_v4l2_flash_init:
+	of_node_put(dev_node);
+	led_classdev_flash_unregister(fled_cdev);
+	mutex_destroy(&led->lock);
+
+	return ret;
 }
 
 static int aat1290_led_remove(struct platform_device *pdev)
 {
 	struct aat1290_led *led = platform_get_drvdata(pdev);
 
+	v4l2_flash_release(led->v4l2_flash);
+	of_node_put(led->fled_cdev.led_cdev.dev->of_node);
 	led_classdev_flash_unregister(&led->fled_cdev);
 	cancel_work_sync(&led->work_brightness_set);
 
-- 
1.7.9.5

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

* 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-18 16:20 ` [PATCH/RFC v11 01/20] leds: flash: document sysfs interface Jacek Anaszewski
@ 2015-02-18 22:47   ` Pavel Machek
  2015-02-19  8:26     ` Jacek Anaszewski
  2015-02-19  9:02       ` Sakari Ailus
  0 siblings, 2 replies; 40+ messages in thread
From: Pavel Machek @ 2015-02-18 22:47 UTC (permalink / raw)
  To: Jacek Anaszewski, Greg KH
  Cc: linux-leds, linux-media, devicetree, kyungmin.park, cooloney,
	rpurdie, sakari.ailus, s.nawrocki


On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
> Add a documentation of LED Flash class specific sysfs attributes.
> 
> Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Bryan Wu <cooloney@gmail.com>
> Cc: Richard Purdie <rpurdie@rpsys.net>

NAK-ed-by: Pavel Machek

> +What:		/sys/class/leds/<led>/available_sync_leds
> +Date:		February 2015
> +KernelVersion:	3.20
> +Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
> +Description:	read/write
> +		Space separated list of LEDs available for flash strobe
> +		synchronization, displayed in the format:
> +
> +		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.

Multiple values per file, with all the problems we had in /proc. I
assume led_id is an integer? What prevents space or dot in led name?

       	      	    	     	  	   	    	       Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-18 22:47   ` 0.led_name 2.other.led.name in /sysfs " Pavel Machek
@ 2015-02-19  8:26     ` Jacek Anaszewski
  2015-02-19  9:02       ` Sakari Ailus
  1 sibling, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-19  8:26 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Greg KH, linux-leds, linux-media, devicetree, kyungmin.park,
	cooloney, rpurdie, sakari.ailus, s.nawrocki

On 02/18/2015 11:47 PM, Pavel Machek wrote:
>
> On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
>> Add a documentation of LED Flash class specific sysfs attributes.
>>
>> Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
>> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
>> Cc: Bryan Wu <cooloney@gmail.com>
>> Cc: Richard Purdie <rpurdie@rpsys.net>
>
> NAK-ed-by: Pavel Machek
>
>> +What:		/sys/class/leds/<led>/available_sync_leds
>> +Date:		February 2015
>> +KernelVersion:	3.20
>> +Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
>> +Description:	read/write

Here it should be 'read only', to be fixed.

>> +		Space separated list of LEDs available for flash strobe
>> +		synchronization, displayed in the format:
>> +
>> +		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
>
> Multiple values per file, with all the problems we had in /proc. I
> assume led_id is an integer?

Yes.

> What prevents space or dot in led name?

Space can be forbidden by defining naming convention. The name comes
from the DT binding 'label' property and I don't see any problem in
forbidding space in it.

A dot in the name does not introduce parsing problems - simply the first
dot after digits separates led id from led name.

-- 
Best Regards,
Jacek Anaszewski

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-18 22:47   ` 0.led_name 2.other.led.name in /sysfs " Pavel Machek
@ 2015-02-19  9:02       ` Sakari Ailus
  2015-02-19  9:02       ` Sakari Ailus
  1 sibling, 0 replies; 40+ messages in thread
From: Sakari Ailus @ 2015-02-19  9:02 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Jacek Anaszewski, Greg KH, linux-leds-u79uwXL29TY76Z2rM5mHXA,
	linux-media-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	cooloney-Re5JQEeQqe8AvxtiuMwx3w, rpurdie-Fm38FmjxZ/leoWH0uzbU5w,
	s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ

On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
> 
> On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
> > Add a documentation of LED Flash class specific sysfs attributes.
> > 
> > Signed-off-by: Jacek Anaszewski <j.anaszewski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> > Acked-by: Kyungmin Park <kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> > Cc: Bryan Wu <cooloney-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > Cc: Richard Purdie <rpurdie-Fm38FmjxZ/leoWH0uzbU5w@public.gmane.org>
> 
> NAK-ed-by: Pavel Machek
> 
> > +What:		/sys/class/leds/<led>/available_sync_leds
> > +Date:		February 2015
> > +KernelVersion:	3.20
> > +Contact:	Jacek Anaszewski <j.anaszewski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> > +Description:	read/write
> > +		Space separated list of LEDs available for flash strobe
> > +		synchronization, displayed in the format:
> > +
> > +		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
> 
> Multiple values per file, with all the problems we had in /proc. I
> assume led_id is an integer? What prevents space or dot in led name?

Very good point. How about using a newline instead? That'd be a little bit
easier to parse, too.

-- 
Sakari Ailus
e-mail: sakari.ailus-X3B1VOXEql0@public.gmane.org	XMPP: sailus-PCDdDYkjdNMDXYZnReoRVg@public.gmane.org
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
@ 2015-02-19  9:02       ` Sakari Ailus
  0 siblings, 0 replies; 40+ messages in thread
From: Sakari Ailus @ 2015-02-19  9:02 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Jacek Anaszewski, Greg KH, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki

On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
> 
> On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
> > Add a documentation of LED Flash class specific sysfs attributes.
> > 
> > Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> > Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Bryan Wu <cooloney@gmail.com>
> > Cc: Richard Purdie <rpurdie@rpsys.net>
> 
> NAK-ed-by: Pavel Machek
> 
> > +What:		/sys/class/leds/<led>/available_sync_leds
> > +Date:		February 2015
> > +KernelVersion:	3.20
> > +Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
> > +Description:	read/write
> > +		Space separated list of LEDs available for flash strobe
> > +		synchronization, displayed in the format:
> > +
> > +		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
> 
> Multiple values per file, with all the problems we had in /proc. I
> assume led_id is an integer? What prevents space or dot in led name?

Very good point. How about using a newline instead? That'd be a little bit
easier to parse, too.

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

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

* Re: [PATCH/RFC v11 05/20] mfd: max77693: Modify flash cell name identifiers
  2015-02-18 16:20 ` [PATCH/RFC v11 05/20] mfd: max77693: Modify flash cell name identifiers Jacek Anaszewski
@ 2015-02-19  9:21   ` Sakari Ailus
  0 siblings, 0 replies; 40+ messages in thread
From: Sakari Ailus @ 2015-02-19  9:21 UTC (permalink / raw)
  To: Jacek Anaszewski, linux-leds, linux-media, devicetree
  Cc: kyungmin.park, pavel, cooloney, rpurdie, s.nawrocki

Jacek Anaszewski wrote:
> Change flash cell identifiers from max77693-flash to max77693-led
> to avoid confusion with NOR/NAND Flash.
> 
> Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> Acked-by: Lee Jones <lee.jones@linaro.org>

Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>

-- 
Sakari Ailus
sakari.ailus@iki.fi

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-19  9:02       ` Sakari Ailus
  (?)
@ 2015-02-19 21:40       ` Greg KH
  2015-02-20  7:56         ` Jacek Anaszewski
  -1 siblings, 1 reply; 40+ messages in thread
From: Greg KH @ 2015-02-19 21:40 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Pavel Machek, Jacek Anaszewski, linux-leds, linux-media,
	devicetree, kyungmin.park, cooloney, rpurdie, s.nawrocki

On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
> On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
> > 
> > On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
> > > Add a documentation of LED Flash class specific sysfs attributes.
> > > 
> > > Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> > > Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > Cc: Bryan Wu <cooloney@gmail.com>
> > > Cc: Richard Purdie <rpurdie@rpsys.net>
> > 
> > NAK-ed-by: Pavel Machek
> > 
> > > +What:		/sys/class/leds/<led>/available_sync_leds
> > > +Date:		February 2015
> > > +KernelVersion:	3.20
> > > +Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
> > > +Description:	read/write
> > > +		Space separated list of LEDs available for flash strobe
> > > +		synchronization, displayed in the format:
> > > +
> > > +		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
> > 
> > Multiple values per file, with all the problems we had in /proc. I
> > assume led_id is an integer? What prevents space or dot in led name?
> 
> Very good point. How about using a newline instead? That'd be a little bit
> easier to parse, too.

No, please make it one value per-file, which is what sysfs requires.

thanks,

greg k-h

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-19 21:40       ` Greg KH
@ 2015-02-20  7:56         ` Jacek Anaszewski
  2015-02-20  8:16           ` Pavel Machek
  2015-02-20 15:36           ` Greg KH
  0 siblings, 2 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-20  7:56 UTC (permalink / raw)
  To: Greg KH
  Cc: Sakari Ailus, Pavel Machek, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki

On 02/19/2015 10:40 PM, Greg KH wrote:
> On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
>> On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
>>>
>>> On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
>>>> Add a documentation of LED Flash class specific sysfs attributes.
>>>>
>>>> Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
>>>> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
>>>> Cc: Bryan Wu <cooloney@gmail.com>
>>>> Cc: Richard Purdie <rpurdie@rpsys.net>
>>>
>>> NAK-ed-by: Pavel Machek
>>>
>>>> +What:		/sys/class/leds/<led>/available_sync_leds
>>>> +Date:		February 2015
>>>> +KernelVersion:	3.20
>>>> +Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
>>>> +Description:	read/write
>>>> +		Space separated list of LEDs available for flash strobe
>>>> +		synchronization, displayed in the format:
>>>> +
>>>> +		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
>>>
>>> Multiple values per file, with all the problems we had in /proc. I
>>> assume led_id is an integer? What prevents space or dot in led name?
>>
>> Very good point. How about using a newline instead? That'd be a little bit
>> easier to parse, too.
>
> No, please make it one value per-file, which is what sysfs requires.

The purpose of this attribute is only to provide an information about
the range of valid identifiers that can be written to the
flash_sync_strobe attribute. Wouldn't splitting this to many attributes
be an unnecessary inflation of sysfs files?

Apart from it, we have also flash_faults attribute, that currently
provides a space separated list of flash faults that have occurred.
If we are to stick tightly to the one-value-per-file rule, then how
we should approach flash_faults case? Should the separate file be
dynamically created for each reported fault?

-- 
Best Regards,
Jacek Anaszewski

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-20  7:56         ` Jacek Anaszewski
@ 2015-02-20  8:16           ` Pavel Machek
  2015-02-20  8:55             ` Jacek Anaszewski
  2015-02-20 15:36           ` Greg KH
  1 sibling, 1 reply; 40+ messages in thread
From: Pavel Machek @ 2015-02-20  8:16 UTC (permalink / raw)
  To: Jacek Anaszewski
  Cc: Greg KH, Sakari Ailus, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki

Hi!

> >>>>+What:		/sys/class/leds/<led>/available_sync_leds
> >>>>+Date:		February 2015
> >>>>+KernelVersion:	3.20
> >>>>+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
> >>>>+Description:	read/write
> >>>>+		Space separated list of LEDs available for flash strobe
> >>>>+		synchronization, displayed in the format:
> >>>>+
> >>>>+		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
> >>>
> >>>Multiple values per file, with all the problems we had in /proc. I
> >>>assume led_id is an integer? What prevents space or dot in led name?
> >>
> >>Very good point. How about using a newline instead? That'd be a little bit
> >>easier to parse, too.
> >
> >No, please make it one value per-file, which is what sysfs requires.
> 
> The purpose of this attribute is only to provide an information about
> the range of valid identifiers that can be written to the
> flash_sync_strobe attribute. Wouldn't splitting this to many attributes
> be an unnecessary inflation of sysfs files?

No, it would not. It is required so that we don't end up with broken
parsers.
 
> Apart from it, we have also flash_faults attribute, that currently
> provides a space separated list of flash faults that have occurred.
> If we are to stick tightly to the one-value-per-file rule, then how
> we should approach flash_faults case? Should the separate file be
> dynamically created for each reported fault?

I think you can get away with flash_faults attribute (since the
strings are hardcoded).

Dynamically created files would be extremely ugly interface, but you
could also have files such as "overvoltage_fault" containing either 0
or 1 ...
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-20  8:16           ` Pavel Machek
@ 2015-02-20  8:55             ` Jacek Anaszewski
  0 siblings, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-20  8:55 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Greg KH, Sakari Ailus, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki

Hi Pavel,

On 02/20/2015 09:16 AM, Pavel Machek wrote:
> Hi!
>
>>>>>> +What:		/sys/class/leds/<led>/available_sync_leds
>>>>>> +Date:		February 2015
>>>>>> +KernelVersion:	3.20
>>>>>> +Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
>>>>>> +Description:	read/write
>>>>>> +		Space separated list of LEDs available for flash strobe
>>>>>> +		synchronization, displayed in the format:
>>>>>> +
>>>>>> +		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
>>>>>
>>>>> Multiple values per file, with all the problems we had in /proc. I
>>>>> assume led_id is an integer? What prevents space or dot in led name?
>>>>
>>>> Very good point. How about using a newline instead? That'd be a little bit
>>>> easier to parse, too.
>>>
>>> No, please make it one value per-file, which is what sysfs requires.
>>
>> The purpose of this attribute is only to provide an information about
>> the range of valid identifiers that can be written to the
>> flash_sync_strobe attribute. Wouldn't splitting this to many attributes
>> be an unnecessary inflation of sysfs files?
>
> No, it would not. It is required so that we don't end up with broken
> parsers.

Let's discuss the acceptable approach then. I propose a directory
named synchronized_strobe and containing the files as you proposed
in one of the previous messages: led_id.active and led_id.name.
The attribute flash_sync_strobe would be redundant then and should
be removed.

Use cases for two LEDs:

- max77693-led1
- max77693-led2

#cd synchronized_strobe
#ls
#0.active 0.name 1.active 1.name
#cat 0.name
#max77693-led1
#cat 0.active
#0
#cat 1.name
#max77693-led2
#cat 1.active
#0
#echo 1 > 0.active
#cat 0.active
#1
#echo 1 > 1.active
#cat 0.active
#0
#cat 1.active
#1


>> Apart from it, we have also flash_faults attribute, that currently
>> provides a space separated list of flash faults that have occurred.
>> If we are to stick tightly to the one-value-per-file rule, then how
>> we should approach flash_faults case? Should the separate file be
>> dynamically created for each reported fault?
>
> I think you can get away with flash_faults attribute (since the
> strings are hardcoded).

If so, the attribute will be left as is.

> Dynamically created files would be extremely ugly interface, but you
> could also have files such as "overvoltage_fault" containing either 0
> or 1 ...

-- 
Best Regards,
Jacek Anaszewski

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-20  7:56         ` Jacek Anaszewski
  2015-02-20  8:16           ` Pavel Machek
@ 2015-02-20 15:36           ` Greg KH
  2015-02-20 16:15             ` Jacek Anaszewski
  2015-02-20 20:57             ` Pavel Machek
  1 sibling, 2 replies; 40+ messages in thread
From: Greg KH @ 2015-02-20 15:36 UTC (permalink / raw)
  To: Jacek Anaszewski
  Cc: Sakari Ailus, Pavel Machek, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki

On Fri, Feb 20, 2015 at 08:56:11AM +0100, Jacek Anaszewski wrote:
> On 02/19/2015 10:40 PM, Greg KH wrote:
> >On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
> >>On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
> >>>
> >>>On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
> >>>>Add a documentation of LED Flash class specific sysfs attributes.
> >>>>
> >>>>Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> >>>>Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> >>>>Cc: Bryan Wu <cooloney@gmail.com>
> >>>>Cc: Richard Purdie <rpurdie@rpsys.net>
> >>>
> >>>NAK-ed-by: Pavel Machek
> >>>
> >>>>+What:		/sys/class/leds/<led>/available_sync_leds
> >>>>+Date:		February 2015
> >>>>+KernelVersion:	3.20
> >>>>+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
> >>>>+Description:	read/write
> >>>>+		Space separated list of LEDs available for flash strobe
> >>>>+		synchronization, displayed in the format:
> >>>>+
> >>>>+		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
> >>>
> >>>Multiple values per file, with all the problems we had in /proc. I
> >>>assume led_id is an integer? What prevents space or dot in led name?
> >>
> >>Very good point. How about using a newline instead? That'd be a little bit
> >>easier to parse, too.
> >
> >No, please make it one value per-file, which is what sysfs requires.
> 
> The purpose of this attribute is only to provide an information about
> the range of valid identifiers that can be written to the
> flash_sync_strobe attribute. Wouldn't splitting this to many attributes
> be an unnecessary inflation of sysfs files?

Ok a list of allowed values to write is acceptable, as long as it is not
hard to parse and always is space separated.

> Apart from it, we have also flash_faults attribute, that currently
> provides a space separated list of flash faults that have occurred.

That's crazy, what's to keep it from growing and growing to be larger
than is allowed to be read?

> If we are to stick tightly to the one-value-per-file rule, then how
> we should approach flash_faults case? Should the separate file be
> dynamically created for each reported fault?

I think you need to use something other than sysfs here, sorry.

uevents for your faults?

thanks,

greg k-h

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-20 15:36           ` Greg KH
@ 2015-02-20 16:15             ` Jacek Anaszewski
  2015-02-21 19:42               ` Greg KH
  2015-02-20 20:57             ` Pavel Machek
  1 sibling, 1 reply; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-20 16:15 UTC (permalink / raw)
  To: Greg KH
  Cc: Sakari Ailus, Pavel Machek, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki

On 02/20/2015 04:36 PM, Greg KH wrote:
> On Fri, Feb 20, 2015 at 08:56:11AM +0100, Jacek Anaszewski wrote:
>> On 02/19/2015 10:40 PM, Greg KH wrote:
>>> On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
>>>> On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
>>>>>
>>>>> On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
>>>>>> Add a documentation of LED Flash class specific sysfs attributes.
>>>>>>
>>>>>> Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
>>>>>> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
>>>>>> Cc: Bryan Wu <cooloney@gmail.com>
>>>>>> Cc: Richard Purdie <rpurdie@rpsys.net>
>>>>>
>>>>> NAK-ed-by: Pavel Machek
>>>>>
>>>>>> +What:		/sys/class/leds/<led>/available_sync_leds
>>>>>> +Date:		February 2015
>>>>>> +KernelVersion:	3.20
>>>>>> +Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
>>>>>> +Description:	read/write
>>>>>> +		Space separated list of LEDs available for flash strobe
>>>>>> +		synchronization, displayed in the format:
>>>>>> +
>>>>>> +		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
>>>>>
>>>>> Multiple values per file, with all the problems we had in /proc. I
>>>>> assume led_id is an integer? What prevents space or dot in led name?
>>>>
>>>> Very good point. How about using a newline instead? That'd be a little bit
>>>> easier to parse, too.
>>>
>>> No, please make it one value per-file, which is what sysfs requires.
>>
>> The purpose of this attribute is only to provide an information about
>> the range of valid identifiers that can be written to the
>> flash_sync_strobe attribute. Wouldn't splitting this to many attributes
>> be an unnecessary inflation of sysfs files?
>
> Ok a list of allowed values to write is acceptable, as long as it is not
> hard to parse and always is space separated.

Is a new line character also acceptable as a delimiter?

>> Apart from it, we have also flash_faults attribute, that currently
>> provides a space separated list of flash faults that have occurred.
>
> That's crazy, what's to keep it from growing and growing to be larger
> than is allowed to be read?

The number of possible faults is fixed to 9 currently. They are 
presented in the form of strings no longer currently than 40 characters.
There can be maximum 9 faults reported at a time, this is not a kind of
a log. This will allow to define roughly 100 types of faults, having
that PAGE_SIZE is 4096. I think this is far more than it is conceivable
for the simple LED flash device.

>> If we are to stick tightly to the one-value-per-file rule, then how
>> we should approach flash_faults case? Should the separate file be
>> dynamically created for each reported fault?
>
> I think you need to use something other than sysfs here, sorry.
>
> uevents for your faults?
>
> thanks,
>
> greg k-h
>

-- 
Best Regards,
Jacek Anaszewski

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-20 15:36           ` Greg KH
  2015-02-20 16:15             ` Jacek Anaszewski
@ 2015-02-20 20:57             ` Pavel Machek
  2015-02-21 10:57               ` Sakari Ailus
  1 sibling, 1 reply; 40+ messages in thread
From: Pavel Machek @ 2015-02-20 20:57 UTC (permalink / raw)
  To: Greg KH
  Cc: Jacek Anaszewski, Sakari Ailus, linux-leds, linux-media,
	devicetree, kyungmin.park, cooloney, rpurdie, s.nawrocki

On Fri 2015-02-20 07:36:16, Greg KH wrote:
> On Fri, Feb 20, 2015 at 08:56:11AM +0100, Jacek Anaszewski wrote:
> > On 02/19/2015 10:40 PM, Greg KH wrote:
> > >On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
> > >>On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
> > >>>
> > >>>On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
> > >>>>Add a documentation of LED Flash class specific sysfs attributes.
> > >>>>
> > >>>>Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> > >>>>Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> > >>>>Cc: Bryan Wu <cooloney@gmail.com>
> > >>>>Cc: Richard Purdie <rpurdie@rpsys.net>
> > >>>
> > >>>NAK-ed-by: Pavel Machek
> > >>>
> > >>>>+What:		/sys/class/leds/<led>/available_sync_leds
> > >>>>+Date:		February 2015
> > >>>>+KernelVersion:	3.20
> > >>>>+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
> > >>>>+Description:	read/write
> > >>>>+		Space separated list of LEDs available for flash strobe
> > >>>>+		synchronization, displayed in the format:
> > >>>>+
> > >>>>+		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
> > >>>
> > >>>Multiple values per file, with all the problems we had in /proc. I
> > >>>assume led_id is an integer? What prevents space or dot in led name?
> > >>
> > >>Very good point. How about using a newline instead? That'd be a little bit
> > >>easier to parse, too.
> > >
> > >No, please make it one value per-file, which is what sysfs requires.
> > 
> > The purpose of this attribute is only to provide an information about
> > the range of valid identifiers that can be written to the
> > flash_sync_strobe attribute. Wouldn't splitting this to many attributes
> > be an unnecessary inflation of sysfs files?
> 
> Ok a list of allowed values to write is acceptable, as long as it is not
> hard to parse and always is space separated.

Well, this one is list of LED numbers and LED names.

> > Apart from it, we have also flash_faults attribute, that currently
> > provides a space separated list of flash faults that have occurred.
> 
> That's crazy, what's to keep it from growing and growing to be larger
> than is allowed to be read?

Umm. Actually, this one is less crazy, I'd say. List of faults is
fixed, and you can have them all-at-once, at most, which is way below
4K limit.
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-20 20:57             ` Pavel Machek
@ 2015-02-21 10:57               ` Sakari Ailus
  2015-02-21 19:42                 ` Greg KH
  2015-02-27 14:34                 ` Jacek Anaszewski
  0 siblings, 2 replies; 40+ messages in thread
From: Sakari Ailus @ 2015-02-21 10:57 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Greg KH, Jacek Anaszewski, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki

Hi Pavel and Greg,

On Fri, Feb 20, 2015 at 09:57:38PM +0100, Pavel Machek wrote:
> On Fri 2015-02-20 07:36:16, Greg KH wrote:
> > On Fri, Feb 20, 2015 at 08:56:11AM +0100, Jacek Anaszewski wrote:
> > > On 02/19/2015 10:40 PM, Greg KH wrote:
> > > >On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
> > > >>On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
> > > >>>
> > > >>>On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
> > > >>>>Add a documentation of LED Flash class specific sysfs attributes.
> > > >>>>
> > > >>>>Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> > > >>>>Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > >>>>Cc: Bryan Wu <cooloney@gmail.com>
> > > >>>>Cc: Richard Purdie <rpurdie@rpsys.net>
> > > >>>
> > > >>>NAK-ed-by: Pavel Machek
> > > >>>
> > > >>>>+What:		/sys/class/leds/<led>/available_sync_leds
> > > >>>>+Date:		February 2015
> > > >>>>+KernelVersion:	3.20
> > > >>>>+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
> > > >>>>+Description:	read/write
> > > >>>>+		Space separated list of LEDs available for flash strobe
> > > >>>>+		synchronization, displayed in the format:
> > > >>>>+
> > > >>>>+		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
> > > >>>
> > > >>>Multiple values per file, with all the problems we had in /proc. I
> > > >>>assume led_id is an integer? What prevents space or dot in led name?
> > > >>
> > > >>Very good point. How about using a newline instead? That'd be a little bit
> > > >>easier to parse, too.
> > > >
> > > >No, please make it one value per-file, which is what sysfs requires.
> > > 
> > > The purpose of this attribute is only to provide an information about
> > > the range of valid identifiers that can be written to the
> > > flash_sync_strobe attribute. Wouldn't splitting this to many attributes
> > > be an unnecessary inflation of sysfs files?
> > 
> > Ok a list of allowed values to write is acceptable, as long as it is not
> > hard to parse and always is space separated.
> 
> Well, this one is list of LED numbers and LED names.

It'd be nice if these names would match the V4L2 sub-device names. We don't
have any rules for them other than they must be unique, and there's the
established practice that an I2C address follows the component name. We're
about to discuss the matter on Monday on #v4l (11:00 Finnish time), but I
don't think we can generally guarantee any of the names won't have spaces.

Separate files, then?

> > > Apart from it, we have also flash_faults attribute, that currently
> > > provides a space separated list of flash faults that have occurred.
> > 
> > That's crazy, what's to keep it from growing and growing to be larger
> > than is allowed to be read?
> 
> Umm. Actually, this one is less crazy, I'd say. List of faults is
> fixed, and you can have them all-at-once, at most, which is way below
> 4K limit.

We'd first run out of V4L2 bitmask control bits --- there are 32 of them.
I'm frankly not really worried about that either.

-- 
Kind regards,

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

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-21 10:57               ` Sakari Ailus
@ 2015-02-21 19:42                 ` Greg KH
  2015-02-27 14:34                 ` Jacek Anaszewski
  1 sibling, 0 replies; 40+ messages in thread
From: Greg KH @ 2015-02-21 19:42 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Pavel Machek, Jacek Anaszewski, linux-leds, linux-media,
	devicetree, kyungmin.park, cooloney, rpurdie, s.nawrocki

On Sat, Feb 21, 2015 at 12:57:33PM +0200, Sakari Ailus wrote:
> Hi Pavel and Greg,
> 
> On Fri, Feb 20, 2015 at 09:57:38PM +0100, Pavel Machek wrote:
> > On Fri 2015-02-20 07:36:16, Greg KH wrote:
> > > On Fri, Feb 20, 2015 at 08:56:11AM +0100, Jacek Anaszewski wrote:
> > > > On 02/19/2015 10:40 PM, Greg KH wrote:
> > > > >On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
> > > > >>On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
> > > > >>>
> > > > >>>On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
> > > > >>>>Add a documentation of LED Flash class specific sysfs attributes.
> > > > >>>>
> > > > >>>>Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> > > > >>>>Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > > >>>>Cc: Bryan Wu <cooloney@gmail.com>
> > > > >>>>Cc: Richard Purdie <rpurdie@rpsys.net>
> > > > >>>
> > > > >>>NAK-ed-by: Pavel Machek
> > > > >>>
> > > > >>>>+What:		/sys/class/leds/<led>/available_sync_leds
> > > > >>>>+Date:		February 2015
> > > > >>>>+KernelVersion:	3.20
> > > > >>>>+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
> > > > >>>>+Description:	read/write
> > > > >>>>+		Space separated list of LEDs available for flash strobe
> > > > >>>>+		synchronization, displayed in the format:
> > > > >>>>+
> > > > >>>>+		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
> > > > >>>
> > > > >>>Multiple values per file, with all the problems we had in /proc. I
> > > > >>>assume led_id is an integer? What prevents space or dot in led name?
> > > > >>
> > > > >>Very good point. How about using a newline instead? That'd be a little bit
> > > > >>easier to parse, too.
> > > > >
> > > > >No, please make it one value per-file, which is what sysfs requires.
> > > > 
> > > > The purpose of this attribute is only to provide an information about
> > > > the range of valid identifiers that can be written to the
> > > > flash_sync_strobe attribute. Wouldn't splitting this to many attributes
> > > > be an unnecessary inflation of sysfs files?
> > > 
> > > Ok a list of allowed values to write is acceptable, as long as it is not
> > > hard to parse and always is space separated.
> > 
> > Well, this one is list of LED numbers and LED names.
> 
> It'd be nice if these names would match the V4L2 sub-device names. We don't
> have any rules for them other than they must be unique, and there's the
> established practice that an I2C address follows the component name. We're
> about to discuss the matter on Monday on #v4l (11:00 Finnish time), but I
> don't think we can generally guarantee any of the names won't have spaces.
> 
> Separate files, then?

Yes please.

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-20 16:15             ` Jacek Anaszewski
@ 2015-02-21 19:42               ` Greg KH
  0 siblings, 0 replies; 40+ messages in thread
From: Greg KH @ 2015-02-21 19:42 UTC (permalink / raw)
  To: Jacek Anaszewski
  Cc: Sakari Ailus, Pavel Machek, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki

On Fri, Feb 20, 2015 at 05:15:10PM +0100, Jacek Anaszewski wrote:
> On 02/20/2015 04:36 PM, Greg KH wrote:
> >On Fri, Feb 20, 2015 at 08:56:11AM +0100, Jacek Anaszewski wrote:
> >>On 02/19/2015 10:40 PM, Greg KH wrote:
> >>>On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
> >>>>On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
> >>>>>
> >>>>>On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
> >>>>>>Add a documentation of LED Flash class specific sysfs attributes.
> >>>>>>
> >>>>>>Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> >>>>>>Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> >>>>>>Cc: Bryan Wu <cooloney@gmail.com>
> >>>>>>Cc: Richard Purdie <rpurdie@rpsys.net>
> >>>>>
> >>>>>NAK-ed-by: Pavel Machek
> >>>>>
> >>>>>>+What:		/sys/class/leds/<led>/available_sync_leds
> >>>>>>+Date:		February 2015
> >>>>>>+KernelVersion:	3.20
> >>>>>>+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
> >>>>>>+Description:	read/write
> >>>>>>+		Space separated list of LEDs available for flash strobe
> >>>>>>+		synchronization, displayed in the format:
> >>>>>>+
> >>>>>>+		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
> >>>>>
> >>>>>Multiple values per file, with all the problems we had in /proc. I
> >>>>>assume led_id is an integer? What prevents space or dot in led name?
> >>>>
> >>>>Very good point. How about using a newline instead? That'd be a little bit
> >>>>easier to parse, too.
> >>>
> >>>No, please make it one value per-file, which is what sysfs requires.
> >>
> >>The purpose of this attribute is only to provide an information about
> >>the range of valid identifiers that can be written to the
> >>flash_sync_strobe attribute. Wouldn't splitting this to many attributes
> >>be an unnecessary inflation of sysfs files?
> >
> >Ok a list of allowed values to write is acceptable, as long as it is not
> >hard to parse and always is space separated.
> 
> Is a new line character also acceptable as a delimiter?

No.

Again, sysfs files should not need to be "parsed", they are
one-value-per-file for a good reason.

If you want to do something else, wonderful, but don't use sysfs.  It's
looking like this whole interface should not be using sysfs as it
doesn't fit there at all.

sorry,

greg k-h

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-21 10:57               ` Sakari Ailus
  2015-02-21 19:42                 ` Greg KH
@ 2015-02-27 14:34                 ` Jacek Anaszewski
  2015-03-02 12:54                   ` Sakari Ailus
  1 sibling, 1 reply; 40+ messages in thread
From: Jacek Anaszewski @ 2015-02-27 14:34 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Pavel Machek, Greg KH, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki

Hi Sakari,

On 02/21/2015 11:57 AM, Sakari Ailus wrote:
> Hi Pavel and Greg,
>
> On Fri, Feb 20, 2015 at 09:57:38PM +0100, Pavel Machek wrote:
>> On Fri 2015-02-20 07:36:16, Greg KH wrote:
>>> On Fri, Feb 20, 2015 at 08:56:11AM +0100, Jacek Anaszewski wrote:
>>>> On 02/19/2015 10:40 PM, Greg KH wrote:
>>>>> On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
>>>>>> On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
>>>>>>>
>>>>>>> On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
>>>>>>>> Add a documentation of LED Flash class specific sysfs attributes.
>>>>>>>>
>>>>>>>> Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
>>>>>>>> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
>>>>>>>> Cc: Bryan Wu <cooloney@gmail.com>
>>>>>>>> Cc: Richard Purdie <rpurdie@rpsys.net>
>>>>>>>
>>>>>>> NAK-ed-by: Pavel Machek
>>>>>>>
>>>>>>>> +What:		/sys/class/leds/<led>/available_sync_leds
>>>>>>>> +Date:		February 2015
>>>>>>>> +KernelVersion:	3.20
>>>>>>>> +Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
>>>>>>>> +Description:	read/write
>>>>>>>> +		Space separated list of LEDs available for flash strobe
>>>>>>>> +		synchronization, displayed in the format:
>>>>>>>> +
>>>>>>>> +		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
>>>>>>>
>>>>>>> Multiple values per file, with all the problems we had in /proc. I
>>>>>>> assume led_id is an integer? What prevents space or dot in led name?
>>>>>>
>>>>>> Very good point. How about using a newline instead? That'd be a little bit
>>>>>> easier to parse, too.
>>>>>
>>>>> No, please make it one value per-file, which is what sysfs requires.
>>>>
>>>> The purpose of this attribute is only to provide an information about
>>>> the range of valid identifiers that can be written to the
>>>> flash_sync_strobe attribute. Wouldn't splitting this to many attributes
>>>> be an unnecessary inflation of sysfs files?
>>>
>>> Ok a list of allowed values to write is acceptable, as long as it is not
>>> hard to parse and always is space separated.
>>
>> Well, this one is list of LED numbers and LED names.
>
> It'd be nice if these names would match the V4L2 sub-device names. We don't

 From the discussion on IRC it turned out that one of components of the
V4L2 sub-device name will be a media controller identifier.

This implies that if support for V4L2 Flash devices will be turned off
in the kernel config the LED name will have to differ from the case
when the support is on. I think that this is undesired.

> have any rules for them other than they must be unique, and there's the
> established practice that an I2C address follows the component name. We're
> about to discuss the matter on Monday on #v4l (11:00 Finnish time), but I
> don't think we can generally guarantee any of the names won't have spaces.

> Separate files, then?

I tried to split this to separate files but it turned out to be awkward.
Since the number of LEDs to synchronize can vary from device to device,
the number of the related sysfs attributes cannot be fixed.

As far as I know allocating the sysfs attributes dynamically is unsafe,
and thus the maximum allowed number of synchronized LEDs would have to
be agreed on for the whole led-class-flash and the relevant number of
similar struct attribute instances and related callbacks would have to
be created statically for every LED Flash class device, no matter if
a device would need them.

Of course the relevant sysfs group could be initialized only with
the needed number of sync leds attributes, but still this is less
than optimal design.

It looks like this interface indeed doesn't fit for sysfs.

I am leaning towards removing the support for synchronized flash LEDs
from the LED subsystem entirely and leave it only to V4L2.

-- 
Best Regards,
Jacek Anaszewski

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-02-27 14:34                 ` Jacek Anaszewski
@ 2015-03-02 12:54                   ` Sakari Ailus
  2015-03-02 13:56                     ` Jacek Anaszewski
  2015-03-02 15:12                     ` Pavel Machek
  0 siblings, 2 replies; 40+ messages in thread
From: Sakari Ailus @ 2015-03-02 12:54 UTC (permalink / raw)
  To: Jacek Anaszewski
  Cc: Pavel Machek, Greg KH, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki, laurent.pinchart,
	hverkuil

Hi Jacek,

On Fri, Feb 27, 2015 at 03:34:22PM +0100, Jacek Anaszewski wrote:
> Hi Sakari,
> 
> On 02/21/2015 11:57 AM, Sakari Ailus wrote:
> >Hi Pavel and Greg,
> >
> >On Fri, Feb 20, 2015 at 09:57:38PM +0100, Pavel Machek wrote:
> >>On Fri 2015-02-20 07:36:16, Greg KH wrote:
> >>>On Fri, Feb 20, 2015 at 08:56:11AM +0100, Jacek Anaszewski wrote:
> >>>>On 02/19/2015 10:40 PM, Greg KH wrote:
> >>>>>On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
> >>>>>>On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
> >>>>>>>
> >>>>>>>On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
> >>>>>>>>Add a documentation of LED Flash class specific sysfs attributes.
> >>>>>>>>
> >>>>>>>>Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> >>>>>>>>Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> >>>>>>>>Cc: Bryan Wu <cooloney@gmail.com>
> >>>>>>>>Cc: Richard Purdie <rpurdie@rpsys.net>
> >>>>>>>
> >>>>>>>NAK-ed-by: Pavel Machek
> >>>>>>>
> >>>>>>>>+What:		/sys/class/leds/<led>/available_sync_leds
> >>>>>>>>+Date:		February 2015
> >>>>>>>>+KernelVersion:	3.20
> >>>>>>>>+Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
> >>>>>>>>+Description:	read/write
> >>>>>>>>+		Space separated list of LEDs available for flash strobe
> >>>>>>>>+		synchronization, displayed in the format:
> >>>>>>>>+
> >>>>>>>>+		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
> >>>>>>>
> >>>>>>>Multiple values per file, with all the problems we had in /proc. I
> >>>>>>>assume led_id is an integer? What prevents space or dot in led name?
> >>>>>>
> >>>>>>Very good point. How about using a newline instead? That'd be a little bit
> >>>>>>easier to parse, too.
> >>>>>
> >>>>>No, please make it one value per-file, which is what sysfs requires.
> >>>>
> >>>>The purpose of this attribute is only to provide an information about
> >>>>the range of valid identifiers that can be written to the
> >>>>flash_sync_strobe attribute. Wouldn't splitting this to many attributes
> >>>>be an unnecessary inflation of sysfs files?
> >>>
> >>>Ok a list of allowed values to write is acceptable, as long as it is not
> >>>hard to parse and always is space separated.
> >>
> >>Well, this one is list of LED numbers and LED names.
> >
> >It'd be nice if these names would match the V4L2 sub-device names. We don't
> 
> From the discussion on IRC it turned out that one of components of the
> V4L2 sub-device name will be a media controller identifier.
> 
> This implies that if support for V4L2 Flash devices will be turned off
> in the kernel config the LED name will have to differ from the case
> when the support is on. I think that this is undesired.

Well... the media entity names need to be unique in the Media controller
device. In the future we may have just a single Media controller device in
the system, possibly depending on the driver so that some drivers can make
use of that while some will have one on their own, mostly older drivers that
is.

I think what Laurent proposed to refer to an ID was the hardware device, so
that in the future the hardware device / media entity name would be unique.
That'd be a much more manageable and easier to verify for correctness than a
global name that is defined by a driver.

Older drivers wouldn't be affected. Old user space might not work with new
drivers without taking the hwdev field into account.

So the hwdev (name or ID) would be part of the struct media_entity_desc, but
*not* a part of the name field in the struct.

Cc Laurent and Hans.

> >have any rules for them other than they must be unique, and there's the
> >established practice that an I2C address follows the component name. We're
> >about to discuss the matter on Monday on #v4l (11:00 Finnish time), but I
> >don't think we can generally guarantee any of the names won't have spaces.
> 
> >Separate files, then?
> 
> I tried to split this to separate files but it turned out to be awkward.
> Since the number of LEDs to synchronize can vary from device to device,
> the number of the related sysfs attributes cannot be fixed.
> 
> As far as I know allocating the sysfs attributes dynamically is unsafe,

How so? I think most implementations use static variables because that's all
they need.

> and thus the maximum allowed number of synchronized LEDs would have to
> be agreed on for the whole led-class-flash and the relevant number of
> similar struct attribute instances and related callbacks would have to
> be created statically for every LED Flash class device, no matter if
> a device would need them.

This could be handled in the framework instead.

> Of course the relevant sysfs group could be initialized only with
> the needed number of sync leds attributes, but still this is less
> than optimal design.
> 
> It looks like this interface indeed doesn't fit for sysfs.
> 
> I am leaning towards removing the support for synchronized flash LEDs
> from the LED subsystem entirely and leave it only to V4L2.

Perfectly fine for me as well, I guess the synchronised strobe has mostly
use on V4L2. It could always be added later on if needed.

-- 
Kind regards,

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

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-03-02 12:54                   ` Sakari Ailus
@ 2015-03-02 13:56                     ` Jacek Anaszewski
  2015-03-02 15:12                     ` Pavel Machek
  1 sibling, 0 replies; 40+ messages in thread
From: Jacek Anaszewski @ 2015-03-02 13:56 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Pavel Machek, Greg KH, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki, laurent.pinchart,
	hverkuil

On 03/02/2015 01:54 PM, Sakari Ailus wrote:
> Hi Jacek,
>
> On Fri, Feb 27, 2015 at 03:34:22PM +0100, Jacek Anaszewski wrote:
>> Hi Sakari,
>>
>> On 02/21/2015 11:57 AM, Sakari Ailus wrote:
>>> Hi Pavel and Greg,
>>>
>>> On Fri, Feb 20, 2015 at 09:57:38PM +0100, Pavel Machek wrote:
>>>> On Fri 2015-02-20 07:36:16, Greg KH wrote:
>>>>> On Fri, Feb 20, 2015 at 08:56:11AM +0100, Jacek Anaszewski wrote:
>>>>>> On 02/19/2015 10:40 PM, Greg KH wrote:
>>>>>>> On Thu, Feb 19, 2015 at 11:02:04AM +0200, Sakari Ailus wrote:
>>>>>>>> On Wed, Feb 18, 2015 at 11:47:47PM +0100, Pavel Machek wrote:
>>>>>>>>>
>>>>>>>>> On Wed 2015-02-18 17:20:22, Jacek Anaszewski wrote:
>>>>>>>>>> Add a documentation of LED Flash class specific sysfs attributes.
>>>>>>>>>>
>>>>>>>>>> Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
>>>>>>>>>> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
>>>>>>>>>> Cc: Bryan Wu <cooloney@gmail.com>
>>>>>>>>>> Cc: Richard Purdie <rpurdie@rpsys.net>
>>>>>>>>>
>>>>>>>>> NAK-ed-by: Pavel Machek
>>>>>>>>>
>>>>>>>>>> +What:		/sys/class/leds/<led>/available_sync_leds
>>>>>>>>>> +Date:		February 2015
>>>>>>>>>> +KernelVersion:	3.20
>>>>>>>>>> +Contact:	Jacek Anaszewski <j.anaszewski@samsung.com>
>>>>>>>>>> +Description:	read/write
>>>>>>>>>> +		Space separated list of LEDs available for flash strobe
>>>>>>>>>> +		synchronization, displayed in the format:
>>>>>>>>>> +
>>>>>>>>>> +		led1_id.led1_name led2_id.led2_name led3_id.led3_name etc.
>>>>>>>>>
>>>>>>>>> Multiple values per file, with all the problems we had in /proc. I
>>>>>>>>> assume led_id is an integer? What prevents space or dot in led name?
>>>>>>>>
>>>>>>>> Very good point. How about using a newline instead? That'd be a little bit
>>>>>>>> easier to parse, too.
>>>>>>>
>>>>>>> No, please make it one value per-file, which is what sysfs requires.
>>>>>>
>>>>>> The purpose of this attribute is only to provide an information about
>>>>>> the range of valid identifiers that can be written to the
>>>>>> flash_sync_strobe attribute. Wouldn't splitting this to many attributes
>>>>>> be an unnecessary inflation of sysfs files?
>>>>>
>>>>> Ok a list of allowed values to write is acceptable, as long as it is not
>>>>> hard to parse and always is space separated.
>>>>
>>>> Well, this one is list of LED numbers and LED names.
>>>
>>> It'd be nice if these names would match the V4L2 sub-device names. We don't
>>
>>  From the discussion on IRC it turned out that one of components of the
>> V4L2 sub-device name will be a media controller identifier.
>>
>> This implies that if support for V4L2 Flash devices will be turned off
>> in the kernel config the LED name will have to differ from the case
>> when the support is on. I think that this is undesired.
>
> Well... the media entity names need to be unique in the Media controller
> device. In the future we may have just a single Media controller device in
> the system, possibly depending on the driver so that some drivers can make
> use of that while some will have one on their own, mostly older drivers that
> is.
>
> I think what Laurent proposed to refer to an ID was the hardware device, so
> that in the future the hardware device / media entity name would be unique.
> That'd be a much more manageable and easier to verify for correctness than a
> global name that is defined by a driver.
>
> Older drivers wouldn't be affected. Old user space might not work with new
> drivers without taking the hwdev field into account.
>
> So the hwdev (name or ID) would be part of the struct media_entity_desc, but
> *not* a part of the name field in the struct.

The origin of this discussion was your statement:

 >>> It'd be nice if these names would match the V4L2 sub-device names.
 >>> We don't have any rules for them other than they must be unique,
 >>> and there's the established practice that an I2C address follows
 >>> the component name.

Has the naming scheme been already agreed?


> Cc Laurent and Hans.
>
>>> have any rules for them other than they must be unique, and there's the
>>> established practice that an I2C address follows the component name. We're
>>> about to discuss the matter on Monday on #v4l (11:00 Finnish time), but I
>>> don't think we can generally guarantee any of the names won't have spaces.
>>
>>> Separate files, then?
>>
>> I tried to split this to separate files but it turned out to be awkward.
>> Since the number of LEDs to synchronize can vary from device to device,
>> the number of the related sysfs attributes cannot be fixed.
>>
>> As far as I know allocating the sysfs attributes dynamically is unsafe,
>
> How so? I think most implementations use static variables because that's all
> they need.

I was thinking about the need for freeing the memory allocated for
attributes on remove and races with udev.

>> and thus the maximum allowed number of synchronized LEDs would have to
>> be agreed on for the whole led-class-flash and the relevant number of
>> similar struct attribute instances and related callbacks would have to
>> be created statically for every LED Flash class device, no matter if
>> a device would need them.
>
> This could be handled in the framework instead.
>
>> Of course the relevant sysfs group could be initialized only with
>> the needed number of sync leds attributes, but still this is less
>> than optimal design.
>>
>> It looks like this interface indeed doesn't fit for sysfs.
>>
>> I am leaning towards removing the support for synchronized flash LEDs
>> from the LED subsystem entirely and leave it only to V4L2.
>
> Perfectly fine for me as well, I guess the synchronised strobe has mostly
> use on V4L2. It could always be added later on if needed.

I think that as I have it implemented and tested for LED subsystem
it will cost not too much to just move it to v4l2-flash sub-device.

-- 
Best Regards,
Jacek Anaszewski

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

* Re: 0.led_name 2.other.led.name in /sysfs Re: [PATCH/RFC v11 01/20] leds: flash: document sysfs interface
  2015-03-02 12:54                   ` Sakari Ailus
  2015-03-02 13:56                     ` Jacek Anaszewski
@ 2015-03-02 15:12                     ` Pavel Machek
  1 sibling, 0 replies; 40+ messages in thread
From: Pavel Machek @ 2015-03-02 15:12 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Jacek Anaszewski, Greg KH, linux-leds, linux-media, devicetree,
	kyungmin.park, cooloney, rpurdie, s.nawrocki, laurent.pinchart,
	hverkuil

Hi!

> > Of course the relevant sysfs group could be initialized only with
> > the needed number of sync leds attributes, but still this is less
> > than optimal design.
> > 
> > It looks like this interface indeed doesn't fit for sysfs.
> > 
> > I am leaning towards removing the support for synchronized flash LEDs
> > from the LED subsystem entirely and leave it only to V4L2.
> 
> Perfectly fine for me as well, I guess the synchronised strobe has mostly
> use on V4L2. It could always be added later on if needed.

Makes sense...
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

end of thread, other threads:[~2015-03-02 15:12 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-18 16:20 [PATCH/RFC v11 00/20] LED / flash API integration Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 01/20] leds: flash: document sysfs interface Jacek Anaszewski
2015-02-18 22:47   ` 0.led_name 2.other.led.name in /sysfs " Pavel Machek
2015-02-19  8:26     ` Jacek Anaszewski
2015-02-19  9:02     ` Sakari Ailus
2015-02-19  9:02       ` Sakari Ailus
2015-02-19 21:40       ` Greg KH
2015-02-20  7:56         ` Jacek Anaszewski
2015-02-20  8:16           ` Pavel Machek
2015-02-20  8:55             ` Jacek Anaszewski
2015-02-20 15:36           ` Greg KH
2015-02-20 16:15             ` Jacek Anaszewski
2015-02-21 19:42               ` Greg KH
2015-02-20 20:57             ` Pavel Machek
2015-02-21 10:57               ` Sakari Ailus
2015-02-21 19:42                 ` Greg KH
2015-02-27 14:34                 ` Jacek Anaszewski
2015-03-02 12:54                   ` Sakari Ailus
2015-03-02 13:56                     ` Jacek Anaszewski
2015-03-02 15:12                     ` Pavel Machek
2015-02-18 16:20 ` [PATCH/RFC v11 02/20] leds: flash: Improve sync strobe related sysfs attributes Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 03/20] Documentation: leds: Add description of LED Flash class extension Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 04/20] dt-binding: leds: Add common LED DT bindings macros Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 05/20] mfd: max77693: Modify flash cell name identifiers Jacek Anaszewski
2015-02-19  9:21   ` Sakari Ailus
2015-02-18 16:20 ` [PATCH/RFC v11 06/20] mfd: max77693: Remove struct max77693_led_platform_data Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 07/20] mfd: max77693: add TORCH_IOUT_MASK macro Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 08/20] mfd: max77693: Adjust FLASH_EN_SHIFT and TORCH_EN_SHIFT macros Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 09/20] leds: Add support for max77693 mfd flash cell Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 10/20] DT: Add documentation for the mfd Maxim max77693 Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 11/20] leds: Add driver for AAT1290 current regulator Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 12/20] of: Add Skyworks Solutions, Inc. vendor prefix Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 13/20] DT: Add documentation for the Skyworks AAT1290 Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 14/20] exynos4-is: Add support for v4l2-flash subdevs Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 15/20] v4l2-ctrls: Add V4L2_CID_FLASH_SYNC_STROBE control Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 16/20] media: Add registration helpers for V4L2 flash sub-devices Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 17/20] Documentation: leds: Add description of v4l2-flash sub-device Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 18/20] DT: Add documentation for exynos4-is 'flashes' property Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 19/20] leds: max77693: add support for V4L2 Flash sub-device Jacek Anaszewski
2015-02-18 16:20 ` [PATCH/RFC v11 20/20] leds: aat1290: " Jacek Anaszewski

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.