aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-07-01 22:09:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-07-01 22:09:11 -0400
commit13d45f79a2af84de9083310db58b309a61065208 (patch)
tree06968d83ed6e5e23e1f729cf6f096f9a79f14f72
parent05fde26a943a9c55d8b498d97bb49d3d207e5069 (diff)
parentb67893206fc0a0e8af87130e67f3d8ae553fc87c (diff)
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds
Pull LED subsystem updates from Bryan Wu: "In this cycle, we finished to merge patches for LED Flash class driver. Other than that we have some bug fixes and new drivers for LED controllers" * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds: (33 commits) leds:lp55xx: fix firmware loading error leds: fix max77693-led build errors leds: fix aat1290 build errors leds: aat1290: pass flags parameter to devm_gpiod_get leds: ktd2692: pass flags parameter to devm_gpiod_get drivers/leds: don't use module_init in non-modular leds-cobalt-raq.c leds: aat1290: add support for V4L2 Flash sub-device DT: aat1290: Document handling external strobe sources leds: max77693: add support for V4L2 Flash sub-device media: Add registration helpers for V4L2 flash sub-devices v4l: async: Add a pointer to of_node to struct v4l2_subdev, match it Documentation: leds: Add description of v4l2-flash sub-device leds: add BCM6358 LED driver leds: add DT binding for BCM6358 LED controller leds: fix brightness changing when software blinking is active Documentation: leds-lp5523: describe master fader attributes leds: lp5523: add master_fader support leds: leds-gpio: Allow compile test if !GPIOLIB leds: leds-gpio: Add missing #include <linux/of.h> gpiolib: Add missing dummies for the unified device properties interface ...
-rw-r--r--Documentation/devicetree/bindings/leds/leds-aat1290.txt73
-rw-r--r--Documentation/devicetree/bindings/leds/leds-bcm6328.txt309
-rw-r--r--Documentation/devicetree/bindings/leds/leds-bcm6358.txt145
-rw-r--r--Documentation/devicetree/bindings/leds/leds-ktd2692.txt50
-rw-r--r--Documentation/devicetree/bindings/leds/leds-tlc591xx.txt40
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--Documentation/leds/leds-class-flash.txt51
-rw-r--r--Documentation/leds/leds-lp5523.txt30
-rw-r--r--drivers/leds/Kconfig57
-rw-r--r--drivers/leds/Makefile6
-rw-r--r--drivers/leds/led-class.c5
-rw-r--r--drivers/leds/led-core.c5
-rw-r--r--drivers/leds/leds-aat1290.c576
-rw-r--r--drivers/leds/leds-bcm6328.c413
-rw-r--r--drivers/leds/leds-bcm6358.c243
-rw-r--r--drivers/leds/leds-cobalt-raq.c15
-rw-r--r--drivers/leds/leds-gpio.c12
-rw-r--r--drivers/leds/leds-ktd2692.c443
-rw-r--r--drivers/leds/leds-lp5523.c148
-rw-r--r--drivers/leds/leds-lp55xx-common.c2
-rw-r--r--drivers/leds/leds-max77693.c1097
-rw-r--r--drivers/leds/leds-tlc591xx.c300
-rw-r--r--drivers/leds/leds.h24
-rw-r--r--drivers/media/v4l2-core/Kconfig11
-rw-r--r--drivers/media/v4l2-core/Makefile2
-rw-r--r--drivers/media/v4l2-core/v4l2-async.c39
-rw-r--r--drivers/media/v4l2-core/v4l2-flash-led-class.c710
-rw-r--r--include/linux/gpio/consumer.h15
-rw-r--r--include/linux/leds.h25
-rw-r--r--include/media/v4l2-flash-led-class.h148
-rw-r--r--include/media/v4l2-subdev.h2
31 files changed, 4939 insertions, 58 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-aat1290.txt b/Documentation/devicetree/bindings/leds/leds-aat1290.txt
new file mode 100644
index 000000000000..c05ed91a4e42
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-aat1290.txt
@@ -0,0 +1,73 @@
1* Skyworks Solutions, Inc. AAT1290 Current Regulator for Flash LEDs
2
3The device is controlled through two pins: FL_EN and EN_SET. The pins when,
4asserted high, enable flash strobe and movie mode (max 1/2 of flash current)
5respectively. In order to add a capability of selecting the strobe signal source
6(e.g. CPU or camera sensor) there is an additional switch required, independent
7of the flash chip. The switch is controlled with pin control.
8
9Required properties:
10
11- compatible : Must be "skyworks,aat1290".
12- flen-gpios : Must be device tree identifier of the flash device FL_EN pin.
13- enset-gpios : Must be device tree identifier of the flash device EN_SET pin.
14
15Optional properties:
16- pinctrl-names : Must contain entries: "default", "host", "isp". Entries
17 "default" and "host" must refer to the same pin configuration
18 node, which sets the host as a strobe signal provider. Entry
19 "isp" must refer to the pin configuration node, which sets the
20 ISP as a strobe signal provider.
21
22A discrete LED element connected to the device must be represented by a child
23node - see Documentation/devicetree/bindings/leds/common.txt.
24
25Required properties of the LED child node:
26- led-max-microamp : see Documentation/devicetree/bindings/leds/common.txt
27- flash-max-microamp : see Documentation/devicetree/bindings/leds/common.txt
28 Maximum flash LED supply current can be calculated using
29 following formula: I = 1A * 162kohm / Rset.
30- flash-timeout-us : see Documentation/devicetree/bindings/leds/common.txt
31 Maximum flash timeout can be calculated using following
32 formula: T = 8.82 * 10^9 * Ct.
33
34Optional properties of the LED child node:
35- label : see Documentation/devicetree/bindings/leds/common.txt
36
37Example (by Ct = 220nF, Rset = 160kohm and exynos4412-trats2 board with
38a switch that allows for routing strobe signal either from the host or from
39the camera sensor):
40
41#include "exynos4412.dtsi"
42
43aat1290 {
44 compatible = "skyworks,aat1290";
45 flen-gpios = <&gpj1 1 GPIO_ACTIVE_HIGH>;
46 enset-gpios = <&gpj1 2 GPIO_ACTIVE_HIGH>;
47
48 pinctrl-names = "default", "host", "isp";
49 pinctrl-0 = <&camera_flash_host>;
50 pinctrl-1 = <&camera_flash_host>;
51 pinctrl-2 = <&camera_flash_isp>;
52
53 camera_flash: flash-led {
54 label = "aat1290-flash";
55 led-max-microamp = <520833>;
56 flash-max-microamp = <1012500>;
57 flash-timeout-us = <1940000>;
58 };
59};
60
61&pinctrl_0 {
62 camera_flash_host: camera-flash-host {
63 samsung,pins = "gpj1-0";
64 samsung,pin-function = <1>;
65 samsung,pin-val = <0>;
66 };
67
68 camera_flash_isp: camera-flash-isp {
69 samsung,pins = "gpj1-0";
70 samsung,pin-function = <1>;
71 samsung,pin-val = <1>;
72 };
73};
diff --git a/Documentation/devicetree/bindings/leds/leds-bcm6328.txt b/Documentation/devicetree/bindings/leds/leds-bcm6328.txt
new file mode 100644
index 000000000000..f9e36adc0ebf
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-bcm6328.txt
@@ -0,0 +1,309 @@
1LEDs connected to Broadcom BCM6328 controller
2
3This controller is present on BCM6318, BCM6328, BCM6362 and BCM63268.
4In these SoCs it's possible to control LEDs both as GPIOs or by hardware.
5However, on some devices there are Serial LEDs (LEDs connected to a 74x164
6controller), which can either be controlled by software (exporting the 74x164
7as spi-gpio. See Documentation/devicetree/bindings/gpio/gpio-74x164.txt), or
8by hardware using this driver.
9Some of these Serial LEDs are hardware controlled (e.g. ethernet LEDs) and
10exporting the 74x164 as spi-gpio prevents those LEDs to be hardware
11controlled, so the only chance to keep them working is by using this driver.
12
13BCM6328 LED controller has a HWDIS register, which controls whether a LED
14should be controlled by a hardware signal instead of the MODE register value,
15with 0 meaning hardware control enabled and 1 hardware control disabled. This
16is usually 1:1 for hardware to LED signals, but through the activity/link
17registers you have some limited control over rerouting the LEDs (as
18explained later in brcm,link-signal-sources). Even if a LED is hardware
19controlled you are still able to make it blink or light it up if it isn't,
20but you can't turn it off if the hardware decides to light it up. For this
21reason, hardware controlled LEDs aren't registered as LED class devices.
22
23Required properties:
24 - compatible : should be "brcm,bcm6328-leds".
25 - #address-cells : must be 1.
26 - #size-cells : must be 0.
27 - reg : BCM6328 LED controller address and size.
28
29Optional properties:
30 - brcm,serial-leds : Boolean, enables Serial LEDs.
31 Default : false
32
33Each LED is represented as a sub-node of the brcm,bcm6328-leds device.
34
35LED sub-node required properties:
36 - reg : LED pin number (only LEDs 0 to 23 are valid).
37
38LED sub-node optional properties:
39 a) Optional properties for sub-nodes related to software controlled LEDs:
40 - label : see Documentation/devicetree/bindings/leds/common.txt
41 - active-low : Boolean, makes LED active low.
42 Default : false
43 - default-state : see
44 Documentation/devicetree/bindings/leds/leds-gpio.txt
45 - linux,default-trigger : see
46 Documentation/devicetree/bindings/leds/common.txt
47
48 b) Optional properties for sub-nodes related to hardware controlled LEDs:
49 - brcm,hardware-controlled : Boolean, makes this LED hardware controlled.
50 Default : false
51 - brcm,link-signal-sources : An array of hardware link
52 signal sources. Up to four link hardware signals can get muxed into
53 these LEDs. Only valid for LEDs 0 to 7, where LED signals 0 to 3 may
54 be muxed to LEDs 0 to 3, and signals 4 to 7 may be muxed to LEDs
55 4 to 7. A signal can be muxed to more than one LED, and one LED can
56 have more than one source signal.
57 - brcm,activity-signal-sources : An array of hardware activity
58 signal sources. Up to four activity hardware signals can get muxed into
59 these LEDs. Only valid for LEDs 0 to 7, where LED signals 0 to 3 may
60 be muxed to LEDs 0 to 3, and signals 4 to 7 may be muxed to LEDs
61 4 to 7. A signal can be muxed to more than one LED, and one LED can
62 have more than one source signal.
63
64Examples:
65Scenario 1 : BCM6328 with 4 EPHY LEDs
66 leds0: led-controller@10000800 {
67 compatible = "brcm,bcm6328-leds";
68 #address-cells = <1>;
69 #size-cells = <0>;
70 reg = <0x10000800 0x24>;
71
72 alarm_red@2 {
73 reg = <2>;
74 active-low;
75 label = "red:alarm";
76 };
77 inet_green@3 {
78 reg = <3>;
79 active-low;
80 label = "green:inet";
81 };
82 power_green@4 {
83 reg = <4>;
84 active-low;
85 label = "green:power";
86 default-state = "on";
87 };
88 ephy0_spd@17 {
89 reg = <17>;
90 brcm,hardware-controlled;
91 };
92 ephy1_spd@18 {
93 reg = <18>;
94 brcm,hardware-controlled;
95 };
96 ephy2_spd@19 {
97 reg = <19>;
98 brcm,hardware-controlled;
99 };
100 ephy3_spd@20 {
101 reg = <20>;
102 brcm,hardware-controlled;
103 };
104 };
105
106Scenario 2 : BCM63268 with Serial/GPHY0 LEDs
107 leds0: led-controller@10001900 {
108 compatible = "brcm,bcm6328-leds";
109 #address-cells = <1>;
110 #size-cells = <0>;
111 reg = <0x10001900 0x24>;
112 brcm,serial-leds;
113
114 gphy0_spd0@0 {
115 reg = <0>;
116 brcm,hardware-controlled;
117 brcm,link-signal-sources = <0>;
118 };
119 gphy0_spd1@1 {
120 reg = <1>;
121 brcm,hardware-controlled;
122 brcm,link-signal-sources = <1>;
123 };
124 inet_red@2 {
125 reg = <2>;
126 active-low;
127 label = "red:inet";
128 };
129 dsl_green@3 {
130 reg = <3>;
131 active-low;
132 label = "green:dsl";
133 };
134 usb_green@4 {
135 reg = <4>;
136 active-low;
137 label = "green:usb";
138 };
139 wps_green@7 {
140 reg = <7>;
141 active-low;
142 label = "green:wps";
143 };
144 inet_green@8 {
145 reg = <8>;
146 active-low;
147 label = "green:inet";
148 };
149 ephy0_act@9 {
150 reg = <9>;
151 brcm,hardware-controlled;
152 };
153 ephy1_act@10 {
154 reg = <10>;
155 brcm,hardware-controlled;
156 };
157 ephy2_act@11 {
158 reg = <11>;
159 brcm,hardware-controlled;
160 };
161 gphy0_act@12 {
162 reg = <12>;
163 brcm,hardware-controlled;
164 };
165 ephy0_spd@13 {
166 reg = <13>;
167 brcm,hardware-controlled;
168 };
169 ephy1_spd@14 {
170 reg = <14>;
171 brcm,hardware-controlled;
172 };
173 ephy2_spd@15 {
174 reg = <15>;
175 brcm,hardware-controlled;
176 };
177 power_green@20 {
178 reg = <20>;
179 active-low;
180 label = "green:power";
181 default-state = "on";
182 };
183 };
184
185Scenario 3 : BCM6362 with 1 LED for each EPHY
186 leds0: led-controller@10001900 {
187 compatible = "brcm,bcm6328-leds";
188 #address-cells = <1>;
189 #size-cells = <0>;
190 reg = <0x10001900 0x24>;
191
192 usb@0 {
193 reg = <0>;
194 brcm,hardware-controlled;
195 brcm,link-signal-sources = <0>;
196 brcm,activity-signal-sources = <0>;
197 /* USB link/activity routed to USB LED */
198 };
199 inet@1 {
200 reg = <1>;
201 brcm,hardware-controlled;
202 brcm,activity-signal-sources = <1>;
203 /* INET activity routed to INET LED */
204 };
205 ephy0@4 {
206 reg = <4>;
207 brcm,hardware-controlled;
208 brcm,link-signal-sources = <4>;
209 /* EPHY0 link routed to EPHY0 LED */
210 };
211 ephy1@5 {
212 reg = <5>;
213 brcm,hardware-controlled;
214 brcm,link-signal-sources = <5>;
215 /* EPHY1 link routed to EPHY1 LED */
216 };
217 ephy2@6 {
218 reg = <6>;
219 brcm,hardware-controlled;
220 brcm,link-signal-sources = <6>;
221 /* EPHY2 link routed to EPHY2 LED */
222 };
223 ephy3@7 {
224 reg = <7>;
225 brcm,hardware-controlled;
226 brcm,link-signal-sources = <7>;
227 /* EPHY3 link routed to EPHY3 LED */
228 };
229 power_green@20 {
230 reg = <20>;
231 active-low;
232 label = "green:power";
233 default-state = "on";
234 };
235 };
236
237Scenario 4 : BCM6362 with 1 LED for all EPHYs
238 leds0: led-controller@10001900 {
239 compatible = "brcm,bcm6328-leds";
240 #address-cells = <1>;
241 #size-cells = <0>;
242 reg = <0x10001900 0x24>;
243
244 usb@0 {
245 reg = <0>;
246 brcm,hardware-controlled;
247 brcm,link-signal-sources = <0 1>;
248 brcm,activity-signal-sources = <0 1>;
249 /* USB/INET link/activity routed to USB LED */
250 };
251 ephy@4 {
252 reg = <4>;
253 brcm,hardware-controlled;
254 brcm,link-signal-sources = <4 5 6 7>;
255 /* EPHY0/1/2/3 link routed to EPHY0 LED */
256 };
257 power_green@20 {
258 reg = <20>;
259 active-low;
260 label = "green:power";
261 default-state = "on";
262 };
263 };
264
265Scenario 5 : BCM6362 with EPHY LEDs swapped
266 leds0: led-controller@10001900 {
267 compatible = "brcm,bcm6328-leds";
268 #address-cells = <1>;
269 #size-cells = <0>;
270 reg = <0x10001900 0x24>;
271
272 usb@0 {
273 reg = <0>;
274 brcm,hardware-controlled;
275 brcm,link-signal-sources = <0>;
276 brcm,activity-signal-sources = <0 1>;
277 /* USB link/act and INET act routed to USB LED */
278 };
279 ephy0@4 {
280 reg = <4>;
281 brcm,hardware-controlled;
282 brcm,link-signal-sources = <7>;
283 /* EPHY3 link routed to EPHY0 LED */
284 };
285 ephy1@5 {
286 reg = <5>;
287 brcm,hardware-controlled;
288 brcm,link-signal-sources = <6>;
289 /* EPHY2 link routed to EPHY1 LED */
290 };
291 ephy2@6 {
292 reg = <6>;
293 brcm,hardware-controlled;
294 brcm,link-signal-sources = <5>;
295 /* EPHY1 link routed to EPHY2 LED */
296 };
297 ephy3@7 {
298 reg = <7>;
299 brcm,hardware-controlled;
300 brcm,link-signal-sources = <4>;
301 /* EPHY0 link routed to EPHY3 LED */
302 };
303 power_green@20 {
304 reg = <20>;
305 active-low;
306 label = "green:power";
307 default-state = "on";
308 };
309 };
diff --git a/Documentation/devicetree/bindings/leds/leds-bcm6358.txt b/Documentation/devicetree/bindings/leds/leds-bcm6358.txt
new file mode 100644
index 000000000000..b22a55bcc65d
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-bcm6358.txt
@@ -0,0 +1,145 @@
1LEDs connected to Broadcom BCM6358 controller
2
3This controller is present on BCM6358 and BCM6368.
4In these SoCs there are Serial LEDs (LEDs connected to a 74x164 controller),
5which can either be controlled by software (exporting the 74x164 as spi-gpio.
6See Documentation/devicetree/bindings/gpio/gpio-74x164.txt), or
7by hardware using this driver.
8
9Required properties:
10 - compatible : should be "brcm,bcm6358-leds".
11 - #address-cells : must be 1.
12 - #size-cells : must be 0.
13 - reg : BCM6358 LED controller address and size.
14
15Optional properties:
16 - brcm,clk-div : SCK signal divider. Possible values are 1, 2, 4 and 8.
17 Default : 1
18 - brcm,clk-dat-low : Boolean, makes clock and data signals active low.
19 Default : false
20
21Each LED is represented as a sub-node of the brcm,bcm6358-leds device.
22
23LED sub-node required properties:
24 - reg : LED pin number (only LEDs 0 to 31 are valid).
25
26LED sub-node optional properties:
27 - label : see Documentation/devicetree/bindings/leds/common.txt
28 - active-low : Boolean, makes LED active low.
29 Default : false
30 - default-state : see
31 Documentation/devicetree/bindings/leds/leds-gpio.txt
32 - linux,default-trigger : see
33 Documentation/devicetree/bindings/leds/common.txt
34
35Examples:
36Scenario 1 : BCM6358
37 leds0: led-controller@fffe00d0 {
38 compatible = "brcm,bcm6358-leds";
39 #address-cells = <1>;
40 #size-cells = <0>;
41 reg = <0xfffe00d0 0x8>;
42
43 alarm_white {
44 reg = <0>;
45 active-low;
46 label = "white:alarm";
47 };
48 tv_white {
49 reg = <2>;
50 active-low;
51 label = "white:tv";
52 };
53 tel_white {
54 reg = <3>;
55 active-low;
56 label = "white:tel";
57 };
58 adsl_white {
59 reg = <4>;
60 active-low;
61 label = "white:adsl";
62 };
63 };
64
65Scenario 2 : BCM6368
66 leds0: led-controller@100000d0 {
67 compatible = "brcm,bcm6358-leds";
68 #address-cells = <1>;
69 #size-cells = <0>;
70 reg = <0x100000d0 0x8>;
71 brcm,pol-low;
72 brcm,clk-div = <4>;
73
74 power_red {
75 reg = <0>;
76 active-low;
77 label = "red:power";
78 };
79 power_green {
80 reg = <1>;
81 active-low;
82 label = "green:power";
83 default-state = "on";
84 };
85 power_blue {
86 reg = <2>;
87 label = "blue:power";
88 };
89 broadband_red {
90 reg = <3>;
91 active-low;
92 label = "red:broadband";
93 };
94 broadband_green {
95 reg = <4>;
96 label = "green:broadband";
97 };
98 broadband_blue {
99 reg = <5>;
100 active-low;
101 label = "blue:broadband";
102 };
103 wireless_red {
104 reg = <6>;
105 active-low;
106 label = "red:wireless";
107 };
108 wireless_green {
109 reg = <7>;
110 active-low;
111 label = "green:wireless";
112 };
113 wireless_blue {
114 reg = <8>;
115 label = "blue:wireless";
116 };
117 phone_red {
118 reg = <9>;
119 active-low;
120 label = "red:phone";
121 };
122 phone_green {
123 reg = <10>;
124 active-low;
125 label = "green:phone";
126 };
127 phone_blue {
128 reg = <11>;
129 label = "blue:phone";
130 };
131 upgrading_red {
132 reg = <12>;
133 active-low;
134 label = "red:upgrading";
135 };
136 upgrading_green {
137 reg = <13>;
138 active-low;
139 label = "green:upgrading";
140 };
141 upgrading_blue {
142 reg = <14>;
143 label = "blue:upgrading";
144 };
145 };
diff --git a/Documentation/devicetree/bindings/leds/leds-ktd2692.txt b/Documentation/devicetree/bindings/leds/leds-ktd2692.txt
new file mode 100644
index 000000000000..853737452580
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-ktd2692.txt
@@ -0,0 +1,50 @@
1* Kinetic Technologies - KTD2692 Flash LED Driver
2
3KTD2692 is the ideal power solution for high-power flash LEDs.
4It uses ExpressWire single-wire programming for maximum flexibility.
5
6The ExpressWire interface through CTRL pin can control LED on/off and
7enable/disable the IC, Movie(max 1/3 of Flash current) / Flash mode current,
8Flash timeout, LVP(low voltage protection).
9
10Also, When the AUX pin is pulled high while CTRL pin is high,
11LED current will be ramped up to the flash-mode current level.
12
13Required properties:
14- compatible : Should be "kinetic,ktd2692".
15- ctrl-gpios : Specifier of the GPIO connected to CTRL pin.
16- aux-gpios : Specifier of the GPIO connected to AUX pin.
17
18Optional properties:
19- vin-supply : "vin" LED supply (2.7V to 5.5V).
20 See Documentation/devicetree/bindings/regulator/regulator.txt
21
22A discrete LED element connected to the device must be represented by a child
23node - See Documentation/devicetree/bindings/leds/common.txt
24
25Required properties for flash LED child nodes:
26 See Documentation/devicetree/bindings/leds/common.txt
27- led-max-microamp : Minimum Threshold for Timer protection
28 is defined internally (Maximum 300mA).
29- flash-max-microamp : Flash LED maximum current
30 Formula : I(mA) = 15000 / Rset.
31- flash-max-timeout-us : Flash LED maximum timeout.
32
33Optional properties for flash LED child nodes:
34- label : See Documentation/devicetree/bindings/leds/common.txt
35
36Example:
37
38ktd2692 {
39 compatible = "kinetic,ktd2692";
40 ctrl-gpios = <&gpc0 1 0>;
41 aux-gpios = <&gpc0 2 0>;
42 vin-supply = <&vbat>;
43
44 flash-led {
45 label = "ktd2692-flash";
46 led-max-microamp = <300000>;
47 flash-max-microamp = <1500000>;
48 flash-max-timeout-us = <1835000>;
49 };
50};
diff --git a/Documentation/devicetree/bindings/leds/leds-tlc591xx.txt b/Documentation/devicetree/bindings/leds/leds-tlc591xx.txt
new file mode 100644
index 000000000000..3bbbf7024411
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-tlc591xx.txt
@@ -0,0 +1,40 @@
1LEDs connected to tlc59116 or tlc59108
2
3Required properties
4- compatible: should be "ti,tlc59116" or "ti,tlc59108"
5- #address-cells: must be 1
6- #size-cells: must be 0
7- reg: typically 0x68
8
9Each led is represented as a sub-node of the ti,tlc59116.
10See Documentation/devicetree/bindings/leds/common.txt
11
12LED sub-node properties:
13- reg: number of LED line, 0 to 15 or 0 to 7
14- label: (optional) name of LED
15- linux,default-trigger : (optional)
16
17Examples:
18
19tlc59116@68 {
20 #address-cells = <1>;
21 #size-cells = <0>;
22 compatible = "ti,tlc59116";
23 reg = <0x68>;
24
25 wan@0 {
26 label = "wrt1900ac:amber:wan";
27 reg = <0x0>;
28 };
29
30 2g@2 {
31 label = "wrt1900ac:white:2g";
32 reg = <0x2>;
33 };
34
35 alive@9 {
36 label = "wrt1900ac:green:alive";
37 reg = <0x9>;
38 linux,default_trigger = "heartbeat";
39 };
40};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 7b607761b774..347c8fdcf250 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -114,6 +114,7 @@ isee ISEE 2007 S.L.
114isil Intersil 114isil Intersil
115karo Ka-Ro electronics GmbH 115karo Ka-Ro electronics GmbH
116keymile Keymile GmbH 116keymile Keymile GmbH
117kinetic Kinetic Technologies
117lacie LaCie 118lacie LaCie
118lantiq Lantiq Semiconductor 119lantiq Lantiq Semiconductor
119lenovo Lenovo Group Ltd. 120lenovo Lenovo Group Ltd.
diff --git a/Documentation/leds/leds-class-flash.txt b/Documentation/leds/leds-class-flash.txt
index 19bb67355424..8da3c6f4b60b 100644
--- a/Documentation/leds/leds-class-flash.txt
+++ b/Documentation/leds/leds-class-flash.txt
@@ -20,3 +20,54 @@ Following sysfs attributes are exposed for controlling flash LED devices:
20 - max_flash_timeout 20 - max_flash_timeout
21 - flash_strobe 21 - flash_strobe
22 - flash_fault 22 - flash_fault
23
24
25V4L2 flash wrapper for flash LEDs
26=================================
27
28A LED subsystem driver can be controlled also from the level of VideoForLinux2
29subsystem. In order to enable this CONFIG_V4L2_FLASH_LED_CLASS symbol has to
30be defined in the kernel config.
31
32The driver must call the v4l2_flash_init function to get registered in the
33V4L2 subsystem. The function takes six arguments:
34- dev : flash device, e.g. an I2C device
35- of_node : of_node of the LED, may be NULL if the same as device's
36- fled_cdev : LED flash class device to wrap
37- iled_cdev : LED flash class device representing indicator LED associated with
38 fled_cdev, may be NULL
39- ops : V4L2 specific ops
40 * external_strobe_set - defines the source of the flash LED strobe -
41 V4L2_CID_FLASH_STROBE control or external source, typically
42 a sensor, which makes it possible to synchronise the flash
43 strobe start with exposure start,
44 * intensity_to_led_brightness and led_brightness_to_intensity - perform
45 enum led_brightness <-> V4L2 intensity conversion in a device
46 specific manner - they can be used for devices with non-linear
47 LED current scale.
48- config : configuration for V4L2 Flash sub-device
49 * dev_name - the name of the media entity, unique in the system,
50 * flash_faults - bitmask of flash faults that the LED flash class
51 device can report; corresponding LED_FAULT* bit definitions are
52 available in <linux/led-class-flash.h>,
53 * torch_intensity - constraints for the LED in TORCH mode
54 in microamperes,
55 * indicator_intensity - constraints for the indicator LED
56 in microamperes,
57 * has_external_strobe - determines whether the flash strobe source
58 can be switched to external,
59
60On remove the v4l2_flash_release function has to be called, which takes one
61argument - struct v4l2_flash pointer returned previously by v4l2_flash_init.
62This function can be safely called with NULL or error pointer argument.
63
64Please refer to drivers/leds/leds-max77693.c for an exemplary usage of the
65v4l2 flash wrapper.
66
67Once the V4L2 sub-device is registered by the driver which created the Media
68controller device, the sub-device node acts just as a node of a native V4L2
69flash API device would. The calls are simply routed to the LED flash API.
70
71Opening the V4L2 flash sub-device makes the LED subsystem sysfs interface
72unavailable. The interface is re-enabled after the V4L2 flash sub-device
73is closed.
diff --git a/Documentation/leds/leds-lp5523.txt b/Documentation/leds/leds-lp5523.txt
index 5b3e91d4ac59..0dbbd279c9b9 100644
--- a/Documentation/leds/leds-lp5523.txt
+++ b/Documentation/leds/leds-lp5523.txt
@@ -49,6 +49,36 @@ There are two ways to run LED patterns.
492) Firmware interface - LP55xx common interface 492) Firmware interface - LP55xx common interface
50 For the details, please refer to 'firmware' section in leds-lp55xx.txt 50 For the details, please refer to 'firmware' section in leds-lp55xx.txt
51 51
52LP5523 has three master faders. If a channel is mapped to one of
53the master faders, its output is dimmed based on the value of the master
54fader.
55
56For example,
57
58 echo "123000123" > master_fader_leds
59
60creates the following channel-fader mappings:
61
62 channel 0,6 to master_fader1
63 channel 1,7 to master_fader2
64 channel 2,8 to master_fader3
65
66Then, to have 25% of the original output on channel 0,6:
67
68 echo 64 > master_fader1
69
70To have 0% of the original output (i.e. no output) channel 1,7:
71
72 echo 0 > master_fader2
73
74To have 100% of the original output (i.e. no dimming) on channel 2,8:
75
76 echo 255 > master_fader3
77
78To clear all master fader controls:
79
80 echo "000000000" > master_fader_leds
81
52Selftest uses always the current from the platform data. 82Selftest uses always the current from the platform data.
53 83
54Each channel contains led current settings. 84Each channel contains led current settings.
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 4191614c4651..9ad35f72ab4c 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -39,6 +39,32 @@ config LEDS_88PM860X
39 This option enables support for on-chip LED drivers found on Marvell 39 This option enables support for on-chip LED drivers found on Marvell
40 Semiconductor 88PM8606 PMIC. 40 Semiconductor 88PM8606 PMIC.
41 41
42config LEDS_AAT1290
43 tristate "LED support for the AAT1290"
44 depends on LEDS_CLASS_FLASH
45 depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS
46 depends on GPIOLIB
47 depends on OF
48 depends on PINCTRL
49 help
50 This option enables support for the LEDs on the AAT1290.
51
52config LEDS_BCM6328
53 tristate "LED Support for Broadcom BCM6328"
54 depends on LEDS_CLASS
55 depends on OF
56 help
57 This option enables support for LEDs connected to the BCM6328
58 LED HW controller accessed via MMIO registers.
59
60config LEDS_BCM6358
61 tristate "LED Support for Broadcom BCM6358"
62 depends on LEDS_CLASS
63 depends on OF
64 help
65 This option enables support for LEDs connected to the BCM6358
66 LED HW controller accessed via MMIO registers.
67
42config LEDS_LM3530 68config LEDS_LM3530
43 tristate "LCD Backlight driver for LM3530" 69 tristate "LCD Backlight driver for LM3530"
44 depends on LEDS_CLASS 70 depends on LEDS_CLASS
@@ -179,7 +205,7 @@ config LEDS_PCA9532_GPIO
179config LEDS_GPIO 205config LEDS_GPIO
180 tristate "LED Support for GPIO connected LEDs" 206 tristate "LED Support for GPIO connected LEDs"
181 depends on LEDS_CLASS 207 depends on LEDS_CLASS
182 depends on GPIOLIB 208 depends on GPIOLIB || COMPILE_TEST
183 help 209 help
184 This option enables support for the LEDs connected to GPIO 210 This option enables support for the LEDs connected to GPIO
185 outputs. To be useful the particular board must have LEDs 211 outputs. To be useful the particular board must have LEDs
@@ -203,6 +229,7 @@ config LEDS_LP55XX_COMMON
203 tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501" 229 tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
204 depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501 230 depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
205 select FW_LOADER 231 select FW_LOADER
232 select FW_LOADER_USER_HELPER_FALLBACK
206 help 233 help
207 This option supports common operations for LP5521/5523/55231/5562/8501 234 This option supports common operations for LP5521/5523/55231/5562/8501
208 devices. 235 devices.
@@ -464,6 +491,25 @@ config LEDS_TCA6507
464 LED driver chips accessed via the I2C bus. 491 LED driver chips accessed via the I2C bus.
465 Driver support brightness control and hardware-assisted blinking. 492 Driver support brightness control and hardware-assisted blinking.
466 493
494config LEDS_TLC591XX
495 tristate "LED driver for TLC59108 and TLC59116 controllers"
496 depends on LEDS_CLASS && I2C
497 select REGMAP_I2C
498 help
499 This option enables support for Texas Instruments TLC59108
500 and TLC59116 LED controllers.
501
502config LEDS_MAX77693
503 tristate "LED support for MAX77693 Flash"
504 depends on LEDS_CLASS_FLASH
505 depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS
506 depends on MFD_MAX77693
507 depends on OF
508 help
509 This option enables support for the flash part of the MAX77693
510 multifunction device. It has build in control for two leds in flash
511 and torch mode.
512
467config LEDS_MAX8997 513config LEDS_MAX8997
468 tristate "LED support for MAX8997 PMIC" 514 tristate "LED support for MAX8997 PMIC"
469 depends on LEDS_CLASS && MFD_MAX8997 515 depends on LEDS_CLASS && MFD_MAX8997
@@ -495,6 +541,15 @@ config LEDS_MENF21BMC
495 This driver can also be built as a module. If so the module 541 This driver can also be built as a module. If so the module
496 will be called leds-menf21bmc. 542 will be called leds-menf21bmc.
497 543
544config LEDS_KTD2692
545 tristate "LED support for KTD2692 flash LED controller"
546 depends on LEDS_CLASS_FLASH && GPIOLIB && OF
547 help
548 This option enables support for KTD2692 LED flash connected
549 through ExpressWire interface.
550
551 Say Y to enable this driver.
552
498comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)" 553comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)"
499 554
500config LEDS_BLINKM 555config LEDS_BLINKM
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index bf4609338e10..8d6a24a2f513 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -7,6 +7,9 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
7 7
8# LED Platform Drivers 8# LED Platform Drivers
9obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o 9obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o
10obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o
11obj-$(CONFIG_LEDS_BCM6328) += leds-bcm6328.o
12obj-$(CONFIG_LEDS_BCM6358) += leds-bcm6358.o
10obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o 13obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
11obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o 14obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
12obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o 15obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o
@@ -31,6 +34,7 @@ obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o
31obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o 34obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o
32obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o 35obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o
33obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o 36obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o
37obj-$(CONFIG_LEDS_TLC591XX) += leds-tlc591xx.o
34obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 38obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
35obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o 39obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o
36obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 40obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
@@ -52,6 +56,7 @@ obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
52obj-$(CONFIG_LEDS_NS2) += leds-ns2.o 56obj-$(CONFIG_LEDS_NS2) += leds-ns2.o
53obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o 57obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
54obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o 58obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o
59obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o
55obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o 60obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o
56obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o 61obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o
57obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o 62obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o
@@ -59,6 +64,7 @@ obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o
59obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o 64obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o
60obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o 65obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o
61obj-$(CONFIG_LEDS_PM8941_WLED) += leds-pm8941-wled.o 66obj-$(CONFIG_LEDS_PM8941_WLED) += leds-pm8941-wled.o
67obj-$(CONFIG_LEDS_KTD2692) += leds-ktd2692.o
62 68
63# LED SPI Drivers 69# LED SPI Drivers
64obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o 70obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 7fb2a19ac649..beabfbc6f7cd 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -121,6 +121,11 @@ static void led_timer_function(unsigned long data)
121 brightness = led_get_brightness(led_cdev); 121 brightness = led_get_brightness(led_cdev);
122 if (!brightness) { 122 if (!brightness) {
123 /* Time to switch the LED on. */ 123 /* Time to switch the LED on. */
124 if (led_cdev->delayed_set_value) {
125 led_cdev->blink_brightness =
126 led_cdev->delayed_set_value;
127 led_cdev->delayed_set_value = 0;
128 }
124 brightness = led_cdev->blink_brightness; 129 brightness = led_cdev->blink_brightness;
125 delay = led_cdev->blink_delay_on; 130 delay = led_cdev->blink_delay_on;
126 } else { 131 } else {
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 9886dace5ad2..549de7e24cfd 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -119,10 +119,11 @@ void led_set_brightness(struct led_classdev *led_cdev,
119{ 119{
120 int ret = 0; 120 int ret = 0;
121 121
122 /* delay brightness setting if need to stop soft-blink timer */ 122 /* delay brightness if soft-blink is active */
123 if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) { 123 if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
124 led_cdev->delayed_set_value = brightness; 124 led_cdev->delayed_set_value = brightness;
125 schedule_work(&led_cdev->set_brightness_work); 125 if (brightness == LED_OFF)
126 schedule_work(&led_cdev->set_brightness_work);
126 return; 127 return;
127 } 128 }
128 129
diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c
new file mode 100644
index 000000000000..fd7c25fd29c1
--- /dev/null
+++ b/drivers/leds/leds-aat1290.c
@@ -0,0 +1,576 @@
1/*
2 * LED Flash class driver for the AAT1290
3 * 1.5A Step-Up Current Regulator for Flash LEDs
4 *
5 * Copyright (C) 2015, Samsung Electronics Co., Ltd.
6 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 */
12
13#include <linux/delay.h>
14#include <linux/gpio/consumer.h>
15#include <linux/led-class-flash.h>
16#include <linux/leds.h>
17#include <linux/module.h>
18#include <linux/mutex.h>
19#include <linux/of.h>
20#include <linux/pinctrl/consumer.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/workqueue.h>
24#include <media/v4l2-flash-led-class.h>
25
26#define AAT1290_MOVIE_MODE_CURRENT_ADDR 17
27#define AAT1290_MAX_MM_CURR_PERCENT_0 16
28#define AAT1290_MAX_MM_CURR_PERCENT_100 1
29
30#define AAT1290_FLASH_SAFETY_TIMER_ADDR 18
31
32#define AAT1290_MOVIE_MODE_CONFIG_ADDR 19
33#define AAT1290_MOVIE_MODE_OFF 1
34#define AAT1290_MOVIE_MODE_ON 3
35
36#define AAT1290_MM_CURRENT_RATIO_ADDR 20
37#define AAT1290_MM_TO_FL_1_92 1
38
39#define AAT1290_MM_TO_FL_RATIO 1000 / 1920
40#define AAT1290_MAX_MM_CURRENT(fl_max) (fl_max * AAT1290_MM_TO_FL_RATIO)
41
42#define AAT1290_LATCH_TIME_MIN_US 500
43#define AAT1290_LATCH_TIME_MAX_US 1000
44#define AAT1290_EN_SET_TICK_TIME_US 1
45#define AAT1290_FLEN_OFF_DELAY_TIME_US 10
46#define AAT1290_FLASH_TM_NUM_LEVELS 16
47#define AAT1290_MM_CURRENT_SCALE_SIZE 15
48
49
50struct aat1290_led_config_data {
51 /* maximum LED current in movie mode */
52 u32 max_mm_current;
53 /* maximum LED current in flash mode */
54 u32 max_flash_current;
55 /* maximum flash timeout */
56 u32 max_flash_tm;
57 /* external strobe capability */
58 bool has_external_strobe;
59 /* max LED brightness level */
60 enum led_brightness max_brightness;
61};
62
63struct aat1290_led {
64 /* platform device data */
65 struct platform_device *pdev;
66 /* secures access to the device */
67 struct mutex lock;
68
69 /* corresponding LED Flash class device */
70 struct led_classdev_flash fled_cdev;
71 /* V4L2 Flash device */
72 struct v4l2_flash *v4l2_flash;
73
74 /* FLEN pin */
75 struct gpio_desc *gpio_fl_en;
76 /* EN|SET pin */
77 struct gpio_desc *gpio_en_set;
78 /* movie mode current scale */
79 int *mm_current_scale;
80 /* device mode */
81 bool movie_mode;
82
83 /* brightness cache */
84 unsigned int torch_brightness;
85 /* assures led-triggers compatibility */
86 struct work_struct work_brightness_set;
87};
88
89static struct aat1290_led *fled_cdev_to_led(
90 struct led_classdev_flash *fled_cdev)
91{
92 return container_of(fled_cdev, struct aat1290_led, fled_cdev);
93}
94
95static void aat1290_as2cwire_write(struct aat1290_led *led, int addr, int value)
96{
97 int i;
98
99 gpiod_direction_output(led->gpio_fl_en, 0);
100 gpiod_direction_output(led->gpio_en_set, 0);
101
102 udelay(AAT1290_FLEN_OFF_DELAY_TIME_US);
103
104 /* write address */
105 for (i = 0; i < addr; ++i) {
106 udelay(AAT1290_EN_SET_TICK_TIME_US);
107 gpiod_direction_output(led->gpio_en_set, 0);
108 udelay(AAT1290_EN_SET_TICK_TIME_US);
109 gpiod_direction_output(led->gpio_en_set, 1);
110 }
111
112 usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US);
113
114 /* write data */
115 for (i = 0; i < value; ++i) {
116 udelay(AAT1290_EN_SET_TICK_TIME_US);
117 gpiod_direction_output(led->gpio_en_set, 0);
118 udelay(AAT1290_EN_SET_TICK_TIME_US);
119 gpiod_direction_output(led->gpio_en_set, 1);
120 }
121
122 usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US);
123}
124
125static void aat1290_set_flash_safety_timer(struct aat1290_led *led,
126 unsigned int micro_sec)
127{
128 struct led_classdev_flash *fled_cdev = &led->fled_cdev;
129 struct led_flash_setting *flash_tm = &fled_cdev->timeout;
130 int flash_tm_reg = AAT1290_FLASH_TM_NUM_LEVELS -
131 (micro_sec / flash_tm->step) + 1;
132
133 aat1290_as2cwire_write(led, AAT1290_FLASH_SAFETY_TIMER_ADDR,
134 flash_tm_reg);
135}
136
137static void aat1290_brightness_set(struct aat1290_led *led,
138 enum led_brightness brightness)
139{
140 mutex_lock(&led->lock);
141
142 if (brightness == 0) {
143 gpiod_direction_output(led->gpio_fl_en, 0);
144 gpiod_direction_output(led->gpio_en_set, 0);
145 led->movie_mode = false;
146 } else {
147 if (!led->movie_mode) {
148 aat1290_as2cwire_write(led,
149 AAT1290_MM_CURRENT_RATIO_ADDR,
150 AAT1290_MM_TO_FL_1_92);
151 led->movie_mode = true;
152 }
153
154 aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CURRENT_ADDR,
155 AAT1290_MAX_MM_CURR_PERCENT_0 - brightness);
156 aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CONFIG_ADDR,
157 AAT1290_MOVIE_MODE_ON);
158 }
159
160 mutex_unlock(&led->lock);
161}
162
163/* LED subsystem callbacks */
164
165static void aat1290_brightness_set_work(struct work_struct *work)
166{
167 struct aat1290_led *led =
168 container_of(work, struct aat1290_led, work_brightness_set);
169
170 aat1290_brightness_set(led, led->torch_brightness);
171}
172
173static void aat1290_led_brightness_set(struct led_classdev *led_cdev,
174 enum led_brightness brightness)
175{
176 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
177 struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
178
179 led->torch_brightness = brightness;
180 schedule_work(&led->work_brightness_set);
181}
182
183static int aat1290_led_brightness_set_sync(struct led_classdev *led_cdev,
184 enum led_brightness brightness)
185{
186 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
187 struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
188
189 aat1290_brightness_set(led, brightness);
190
191 return 0;
192}
193
194static int aat1290_led_flash_strobe_set(struct led_classdev_flash *fled_cdev,
195 bool state)
196
197{
198 struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
199 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
200 struct led_flash_setting *timeout = &fled_cdev->timeout;
201
202 mutex_lock(&led->lock);
203
204 if (state) {
205 aat1290_set_flash_safety_timer(led, timeout->val);
206 gpiod_direction_output(led->gpio_fl_en, 1);
207 } else {
208 gpiod_direction_output(led->gpio_fl_en, 0);
209 gpiod_direction_output(led->gpio_en_set, 0);
210 }
211
212 /*
213 * To reenter movie mode after a flash event the part must be cycled
214 * off and back on to reset the movie mode and reprogrammed via the
215 * AS2Cwire. Therefore the brightness and movie_mode properties needs
216 * to be updated here to reflect the actual state.
217 */
218 led_cdev->brightness = 0;
219 led->movie_mode = false;
220
221 mutex_unlock(&led->lock);
222
223 return 0;
224}
225
226static int aat1290_led_flash_timeout_set(struct led_classdev_flash *fled_cdev,
227 u32 timeout)
228{
229 /*
230 * Don't do anything - flash timeout is cached in the led-class-flash
231 * core and will be applied in the strobe_set op, as writing the
232 * safety timer register spuriously turns the torch mode on.
233 */
234
235 return 0;
236}
237
238static int aat1290_led_parse_dt(struct aat1290_led *led,
239 struct aat1290_led_config_data *cfg,
240 struct device_node **sub_node)
241{
242 struct led_classdev *led_cdev = &led->fled_cdev.led_cdev;
243 struct device *dev = &led->pdev->dev;
244 struct device_node *child_node;
245#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
246 struct pinctrl *pinctrl;
247#endif
248 int ret = 0;
249
250 led->gpio_fl_en = devm_gpiod_get(dev, "flen", GPIOD_ASIS);
251 if (IS_ERR(led->gpio_fl_en)) {
252 ret = PTR_ERR(led->gpio_fl_en);
253 dev_err(dev, "Unable to claim gpio \"flen\".\n");
254 return ret;
255 }
256
257 led->gpio_en_set = devm_gpiod_get(dev, "enset", GPIOD_ASIS);
258 if (IS_ERR(led->gpio_en_set)) {
259 ret = PTR_ERR(led->gpio_en_set);
260 dev_err(dev, "Unable to claim gpio \"enset\".\n");
261 return ret;
262 }
263
264#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
265 pinctrl = devm_pinctrl_get_select_default(&led->pdev->dev);
266 if (IS_ERR(pinctrl)) {
267 cfg->has_external_strobe = false;
268 dev_info(dev,
269 "No support for external strobe detected.\n");
270 } else {
271 cfg->has_external_strobe = true;
272 }
273#endif
274
275 child_node = of_get_next_available_child(dev->of_node, NULL);
276 if (!child_node) {
277 dev_err(dev, "No DT child node found for connected LED.\n");
278 return -EINVAL;
279 }
280
281 led_cdev->name = of_get_property(child_node, "label", NULL) ? :
282 child_node->name;
283
284 ret = of_property_read_u32(child_node, "led-max-microamp",
285 &cfg->max_mm_current);
286 /*
287 * led-max-microamp will default to 1/20 of flash-max-microamp
288 * in case it is missing.
289 */
290 if (ret < 0)
291 dev_warn(dev,
292 "led-max-microamp DT property missing\n");
293
294 ret = of_property_read_u32(child_node, "flash-max-microamp",
295 &cfg->max_flash_current);
296 if (ret < 0) {
297 dev_err(dev,
298 "flash-max-microamp DT property missing\n");
299 return ret;
300 }
301
302 ret = of_property_read_u32(child_node, "flash-max-timeout-us",
303 &cfg->max_flash_tm);
304 if (ret < 0) {
305 dev_err(dev,
306 "flash-max-timeout-us DT property missing\n");
307 return ret;
308 }
309
310 of_node_put(child_node);
311
312 *sub_node = child_node;
313
314 return ret;
315}
316
317static void aat1290_led_validate_mm_current(struct aat1290_led *led,
318 struct aat1290_led_config_data *cfg)
319{
320 int i, b = 0, e = AAT1290_MM_CURRENT_SCALE_SIZE;
321
322 while (e - b > 1) {
323 i = b + (e - b) / 2;
324 if (cfg->max_mm_current < led->mm_current_scale[i])
325 e = i;
326 else
327 b = i;
328 }
329
330 cfg->max_mm_current = led->mm_current_scale[b];
331 cfg->max_brightness = b + 1;
332}
333
334int init_mm_current_scale(struct aat1290_led *led,
335 struct aat1290_led_config_data *cfg)
336{
337 int max_mm_current_percent[] = { 20, 22, 25, 28, 32, 36, 40, 45, 50, 56,
338 63, 71, 79, 89, 100 };
339 int i, max_mm_current =
340 AAT1290_MAX_MM_CURRENT(cfg->max_flash_current);
341
342 led->mm_current_scale = devm_kzalloc(&led->pdev->dev,
343 sizeof(max_mm_current_percent),
344 GFP_KERNEL);
345 if (!led->mm_current_scale)
346 return -ENOMEM;
347
348 for (i = 0; i < AAT1290_MM_CURRENT_SCALE_SIZE; ++i)
349 led->mm_current_scale[i] = max_mm_current *
350 max_mm_current_percent[i] / 100;
351
352 return 0;
353}
354
355static int aat1290_led_get_configuration(struct aat1290_led *led,
356 struct aat1290_led_config_data *cfg,
357 struct device_node **sub_node)
358{
359 int ret;
360
361 ret = aat1290_led_parse_dt(led, cfg, sub_node);
362 if (ret < 0)
363 return ret;
364 /*
365 * Init non-linear movie mode current scale basing
366 * on the max flash current from led configuration.
367 */
368 ret = init_mm_current_scale(led, cfg);
369 if (ret < 0)
370 return ret;
371
372 aat1290_led_validate_mm_current(led, cfg);
373
374#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
375#else
376 devm_kfree(&led->pdev->dev, led->mm_current_scale);
377#endif
378
379 return 0;
380}
381
382static void aat1290_init_flash_timeout(struct aat1290_led *led,
383 struct aat1290_led_config_data *cfg)
384{
385 struct led_classdev_flash *fled_cdev = &led->fled_cdev;
386 struct led_flash_setting *setting;
387
388 /* Init flash timeout setting */
389 setting = &fled_cdev->timeout;
390 setting->min = cfg->max_flash_tm / AAT1290_FLASH_TM_NUM_LEVELS;
391 setting->max = cfg->max_flash_tm;
392 setting->step = setting->min;
393 setting->val = setting->max;
394}
395
396#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
397static enum led_brightness aat1290_intensity_to_brightness(
398 struct v4l2_flash *v4l2_flash,
399 s32 intensity)
400{
401 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
402 struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
403 int i;
404
405 for (i = AAT1290_MM_CURRENT_SCALE_SIZE - 1; i >= 0; --i)
406 if (intensity >= led->mm_current_scale[i])
407 return i + 1;
408
409 return 1;
410}
411
412static s32 aat1290_brightness_to_intensity(struct v4l2_flash *v4l2_flash,
413 enum led_brightness brightness)
414{
415 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
416 struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
417
418 return led->mm_current_scale[brightness - 1];
419}
420
421static int aat1290_led_external_strobe_set(struct v4l2_flash *v4l2_flash,
422 bool enable)
423{
424 struct aat1290_led *led = fled_cdev_to_led(v4l2_flash->fled_cdev);
425 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
426 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
427 struct pinctrl *pinctrl;
428
429 gpiod_direction_output(led->gpio_fl_en, 0);
430 gpiod_direction_output(led->gpio_en_set, 0);
431
432 led->movie_mode = false;
433 led_cdev->brightness = 0;
434
435 pinctrl = devm_pinctrl_get_select(&led->pdev->dev,
436 enable ? "isp" : "host");
437 if (IS_ERR(pinctrl)) {
438 dev_warn(&led->pdev->dev, "Unable to switch strobe source.\n");
439 return PTR_ERR(pinctrl);
440 }
441
442 return 0;
443}
444
445static void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
446 struct aat1290_led_config_data *led_cfg,
447 struct v4l2_flash_config *v4l2_sd_cfg)
448{
449 struct led_classdev *led_cdev = &led->fled_cdev.led_cdev;
450 struct led_flash_setting *s;
451
452 strlcpy(v4l2_sd_cfg->dev_name, led_cdev->name,
453 sizeof(v4l2_sd_cfg->dev_name));
454
455 s = &v4l2_sd_cfg->torch_intensity;
456 s->min = led->mm_current_scale[0];
457 s->max = led_cfg->max_mm_current;
458 s->step = 1;
459 s->val = s->max;
460
461 v4l2_sd_cfg->has_external_strobe = led_cfg->has_external_strobe;
462}
463
464static const struct v4l2_flash_ops v4l2_flash_ops = {
465 .external_strobe_set = aat1290_led_external_strobe_set,
466 .intensity_to_led_brightness = aat1290_intensity_to_brightness,
467 .led_brightness_to_intensity = aat1290_brightness_to_intensity,
468};
469#else
470static inline void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
471 struct aat1290_led_config_data *led_cfg,
472 struct v4l2_flash_config *v4l2_sd_cfg)
473{
474}
475static const struct v4l2_flash_ops v4l2_flash_ops;
476#endif
477
478static const struct led_flash_ops flash_ops = {
479 .strobe_set = aat1290_led_flash_strobe_set,
480 .timeout_set = aat1290_led_flash_timeout_set,
481};
482
483static int aat1290_led_probe(struct platform_device *pdev)
484{
485 struct device *dev = &pdev->dev;
486 struct device_node *sub_node = NULL;
487 struct aat1290_led *led;
488 struct led_classdev *led_cdev;
489 struct led_classdev_flash *fled_cdev;
490 struct aat1290_led_config_data led_cfg = {};
491 struct v4l2_flash_config v4l2_sd_cfg = {};
492 int ret;
493
494 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
495 if (!led)
496 return -ENOMEM;
497
498 led->pdev = pdev;
499 platform_set_drvdata(pdev, led);
500
501 fled_cdev = &led->fled_cdev;
502 fled_cdev->ops = &flash_ops;
503 led_cdev = &fled_cdev->led_cdev;
504
505 ret = aat1290_led_get_configuration(led, &led_cfg, &sub_node);
506 if (ret < 0)
507 return ret;
508
509 mutex_init(&led->lock);
510
511 /* Initialize LED Flash class device */
512 led_cdev->brightness_set = aat1290_led_brightness_set;
513 led_cdev->brightness_set_sync = aat1290_led_brightness_set_sync;
514 led_cdev->max_brightness = led_cfg.max_brightness;
515 led_cdev->flags |= LED_DEV_CAP_FLASH;
516 INIT_WORK(&led->work_brightness_set, aat1290_brightness_set_work);
517
518 aat1290_init_flash_timeout(led, &led_cfg);
519
520 /* Register LED Flash class device */
521 ret = led_classdev_flash_register(&pdev->dev, fled_cdev);
522 if (ret < 0)
523 goto err_flash_register;
524
525 aat1290_init_v4l2_flash_config(led, &led_cfg, &v4l2_sd_cfg);
526
527 /* Create V4L2 Flash subdev. */
528 led->v4l2_flash = v4l2_flash_init(dev, sub_node, fled_cdev, NULL,
529 &v4l2_flash_ops, &v4l2_sd_cfg);
530 if (IS_ERR(led->v4l2_flash)) {
531 ret = PTR_ERR(led->v4l2_flash);
532 goto error_v4l2_flash_init;
533 }
534
535 return 0;
536
537error_v4l2_flash_init:
538 led_classdev_flash_unregister(fled_cdev);
539err_flash_register:
540 mutex_destroy(&led->lock);
541
542 return ret;
543}
544
545static int aat1290_led_remove(struct platform_device *pdev)
546{
547 struct aat1290_led *led = platform_get_drvdata(pdev);
548
549 v4l2_flash_release(led->v4l2_flash);
550 led_classdev_flash_unregister(&led->fled_cdev);
551 cancel_work_sync(&led->work_brightness_set);
552
553 mutex_destroy(&led->lock);
554
555 return 0;
556}
557
558static const struct of_device_id aat1290_led_dt_match[] = {
559 { .compatible = "skyworks,aat1290" },
560 {},
561};
562
563static struct platform_driver aat1290_led_driver = {
564 .probe = aat1290_led_probe,
565 .remove = aat1290_led_remove,
566 .driver = {
567 .name = "aat1290",
568 .of_match_table = aat1290_led_dt_match,
569 },
570};
571
572module_platform_driver(aat1290_led_driver);
573
574MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
575MODULE_DESCRIPTION("Skyworks Current Regulator for Flash LEDs");
576MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c
new file mode 100644
index 000000000000..986fe1e28f84
--- /dev/null
+++ b/drivers/leds/leds-bcm6328.c
@@ -0,0 +1,413 @@
1/*
2 * Driver for BCM6328 memory-mapped LEDs, based on leds-syscon.c
3 *
4 * Copyright 2015 Álvaro Fernández Rojas <noltari@gmail.com>
5 * Copyright 2015 Jonas Gorski <jogo@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12#include <linux/io.h>
13#include <linux/leds.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/platform_device.h>
17#include <linux/spinlock.h>
18
19#define BCM6328_REG_INIT 0x00
20#define BCM6328_REG_MODE_HI 0x04
21#define BCM6328_REG_MODE_LO 0x08
22#define BCM6328_REG_HWDIS 0x0c
23#define BCM6328_REG_STROBE 0x10
24#define BCM6328_REG_LNKACTSEL_HI 0x14
25#define BCM6328_REG_LNKACTSEL_LO 0x18
26#define BCM6328_REG_RBACK 0x1c
27#define BCM6328_REG_SERMUX 0x20
28
29#define BCM6328_LED_MAX_COUNT 24
30#define BCM6328_LED_DEF_DELAY 500
31#define BCM6328_LED_INTERVAL_MS 20
32
33#define BCM6328_LED_INTV_MASK 0x3f
34#define BCM6328_LED_FAST_INTV_SHIFT 6
35#define BCM6328_LED_FAST_INTV_MASK (BCM6328_LED_INTV_MASK << \
36 BCM6328_LED_FAST_INTV_SHIFT)
37#define BCM6328_SERIAL_LED_EN BIT(12)
38#define BCM6328_SERIAL_LED_MUX BIT(13)
39#define BCM6328_SERIAL_LED_CLK_NPOL BIT(14)
40#define BCM6328_SERIAL_LED_DATA_PPOL BIT(15)
41#define BCM6328_SERIAL_LED_SHIFT_DIR BIT(16)
42#define BCM6328_LED_SHIFT_TEST BIT(30)
43#define BCM6328_LED_TEST BIT(31)
44
45#define BCM6328_LED_MODE_MASK 3
46#define BCM6328_LED_MODE_OFF 0
47#define BCM6328_LED_MODE_FAST 1
48#define BCM6328_LED_MODE_BLINK 2
49#define BCM6328_LED_MODE_ON 3
50#define BCM6328_LED_SHIFT(X) ((X) << 1)
51
52/**
53 * struct bcm6328_led - state container for bcm6328 based LEDs
54 * @cdev: LED class device for this LED
55 * @mem: memory resource
56 * @lock: memory lock
57 * @pin: LED pin number
58 * @blink_leds: blinking LEDs
59 * @blink_delay: blinking delay
60 * @active_low: LED is active low
61 */
62struct bcm6328_led {
63 struct led_classdev cdev;
64 void __iomem *mem;
65 spinlock_t *lock;
66 unsigned long pin;
67 unsigned long *blink_leds;
68 unsigned long *blink_delay;
69 bool active_low;
70};
71
72static void bcm6328_led_write(void __iomem *reg, unsigned long data)
73{
74 iowrite32be(data, reg);
75}
76
77static unsigned long bcm6328_led_read(void __iomem *reg)
78{
79 return ioread32be(reg);
80}
81
82/**
83 * LEDMode 64 bits / 24 LEDs
84 * bits [31:0] -> LEDs 8-23
85 * bits [47:32] -> LEDs 0-7
86 * bits [63:48] -> unused
87 */
88static unsigned long bcm6328_pin2shift(unsigned long pin)
89{
90 if (pin < 8)
91 return pin + 16; /* LEDs 0-7 (bits 47:32) */
92 else
93 return pin - 8; /* LEDs 8-23 (bits 31:0) */
94}
95
96static void bcm6328_led_mode(struct bcm6328_led *led, unsigned long value)
97{
98 void __iomem *mode;
99 unsigned long val, shift;
100
101 shift = bcm6328_pin2shift(led->pin);
102 if (shift / 16)
103 mode = led->mem + BCM6328_REG_MODE_HI;
104 else
105 mode = led->mem + BCM6328_REG_MODE_LO;
106
107 val = bcm6328_led_read(mode);
108 val &= ~(BCM6328_LED_MODE_MASK << BCM6328_LED_SHIFT(shift % 16));
109 val |= (value << BCM6328_LED_SHIFT(shift % 16));
110 bcm6328_led_write(mode, val);
111}
112
113static void bcm6328_led_set(struct led_classdev *led_cdev,
114 enum led_brightness value)
115{
116 struct bcm6328_led *led =
117 container_of(led_cdev, struct bcm6328_led, cdev);
118 unsigned long flags;
119
120 spin_lock_irqsave(led->lock, flags);
121 *(led->blink_leds) &= ~BIT(led->pin);
122 if ((led->active_low && value == LED_OFF) ||
123 (!led->active_low && value != LED_OFF))
124 bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
125 else
126 bcm6328_led_mode(led, BCM6328_LED_MODE_ON);
127 spin_unlock_irqrestore(led->lock, flags);
128}
129
130static int bcm6328_blink_set(struct led_classdev *led_cdev,
131 unsigned long *delay_on, unsigned long *delay_off)
132{
133 struct bcm6328_led *led =
134 container_of(led_cdev, struct bcm6328_led, cdev);
135 unsigned long delay, flags;
136
137 if (!*delay_on)
138 *delay_on = BCM6328_LED_DEF_DELAY;
139 if (!*delay_off)
140 *delay_off = BCM6328_LED_DEF_DELAY;
141
142 if (*delay_on != *delay_off) {
143 dev_dbg(led_cdev->dev,
144 "fallback to soft blinking (delay_on != delay_off)\n");
145 return -EINVAL;
146 }
147
148 delay = *delay_on / BCM6328_LED_INTERVAL_MS;
149 if (delay == 0)
150 delay = 1;
151 else if (delay > BCM6328_LED_INTV_MASK) {
152 dev_dbg(led_cdev->dev,
153 "fallback to soft blinking (delay > %ums)\n",
154 BCM6328_LED_INTV_MASK * BCM6328_LED_INTERVAL_MS);
155 return -EINVAL;
156 }
157
158 spin_lock_irqsave(led->lock, flags);
159 if (*(led->blink_leds) == 0 ||
160 *(led->blink_leds) == BIT(led->pin) ||
161 *(led->blink_delay) == delay) {
162 unsigned long val;
163
164 *(led->blink_leds) |= BIT(led->pin);
165 *(led->blink_delay) = delay;
166
167 val = bcm6328_led_read(led->mem + BCM6328_REG_INIT);
168 val &= ~BCM6328_LED_FAST_INTV_MASK;
169 val |= (delay << BCM6328_LED_FAST_INTV_SHIFT);
170 bcm6328_led_write(led->mem + BCM6328_REG_INIT, val);
171
172 bcm6328_led_mode(led, BCM6328_LED_MODE_BLINK);
173
174 spin_unlock_irqrestore(led->lock, flags);
175 } else {
176 spin_unlock_irqrestore(led->lock, flags);
177 dev_dbg(led_cdev->dev,
178 "fallback to soft blinking (delay already set)\n");
179 return -EINVAL;
180 }
181
182 return 0;
183}
184
185static int bcm6328_hwled(struct device *dev, struct device_node *nc, u32 reg,
186 void __iomem *mem, spinlock_t *lock)
187{
188 int i, cnt;
189 unsigned long flags, val;
190
191 spin_lock_irqsave(lock, flags);
192 val = bcm6328_led_read(mem + BCM6328_REG_HWDIS);
193 val &= ~BIT(reg);
194 bcm6328_led_write(mem + BCM6328_REG_HWDIS, val);
195 spin_unlock_irqrestore(lock, flags);
196
197 /* Only LEDs 0-7 can be activity/link controlled */
198 if (reg >= 8)
199 return 0;
200
201 cnt = of_property_count_elems_of_size(nc, "brcm,link-signal-sources",
202 sizeof(u32));
203 for (i = 0; i < cnt; i++) {
204 u32 sel;
205 void __iomem *addr;
206
207 if (reg < 4)
208 addr = mem + BCM6328_REG_LNKACTSEL_LO;
209 else
210 addr = mem + BCM6328_REG_LNKACTSEL_HI;
211
212 of_property_read_u32_index(nc, "brcm,link-signal-sources", i,
213 &sel);
214
215 if (reg / 4 != sel / 4) {
216 dev_warn(dev, "invalid link signal source\n");
217 continue;
218 }
219
220 spin_lock_irqsave(lock, flags);
221 val = bcm6328_led_read(addr);
222 val |= (BIT(reg) << (((sel % 4) * 4) + 16));
223 bcm6328_led_write(addr, val);
224 spin_unlock_irqrestore(lock, flags);
225 }
226
227 cnt = of_property_count_elems_of_size(nc,
228 "brcm,activity-signal-sources",
229 sizeof(u32));
230 for (i = 0; i < cnt; i++) {
231 u32 sel;
232 void __iomem *addr;
233
234 if (reg < 4)
235 addr = mem + BCM6328_REG_LNKACTSEL_LO;
236 else
237 addr = mem + BCM6328_REG_LNKACTSEL_HI;
238
239 of_property_read_u32_index(nc, "brcm,activity-signal-sources",
240 i, &sel);
241
242 if (reg / 4 != sel / 4) {
243 dev_warn(dev, "invalid activity signal source\n");
244 continue;
245 }
246
247 spin_lock_irqsave(lock, flags);
248 val = bcm6328_led_read(addr);
249 val |= (BIT(reg) << ((sel % 4) * 4));
250 bcm6328_led_write(addr, val);
251 spin_unlock_irqrestore(lock, flags);
252 }
253
254 return 0;
255}
256
257static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
258 void __iomem *mem, spinlock_t *lock,
259 unsigned long *blink_leds, unsigned long *blink_delay)
260{
261 struct bcm6328_led *led;
262 unsigned long flags;
263 const char *state;
264 int rc;
265
266 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
267 if (!led)
268 return -ENOMEM;
269
270 led->pin = reg;
271 led->mem = mem;
272 led->lock = lock;
273 led->blink_leds = blink_leds;
274 led->blink_delay = blink_delay;
275
276 if (of_property_read_bool(nc, "active-low"))
277 led->active_low = true;
278
279 led->cdev.name = of_get_property(nc, "label", NULL) ? : nc->name;
280 led->cdev.default_trigger = of_get_property(nc,
281 "linux,default-trigger",
282 NULL);
283
284 if (!of_property_read_string(nc, "default-state", &state)) {
285 spin_lock_irqsave(lock, flags);
286 if (!strcmp(state, "on")) {
287 led->cdev.brightness = LED_FULL;
288 bcm6328_led_mode(led, BCM6328_LED_MODE_ON);
289 } else if (!strcmp(state, "keep")) {
290 void __iomem *mode;
291 unsigned long val, shift;
292
293 shift = bcm6328_pin2shift(led->pin);
294 if (shift / 16)
295 mode = mem + BCM6328_REG_MODE_HI;
296 else
297 mode = mem + BCM6328_REG_MODE_LO;
298
299 val = bcm6328_led_read(mode) >> (shift % 16);
300 val &= BCM6328_LED_MODE_MASK;
301 if (val == BCM6328_LED_MODE_ON)
302 led->cdev.brightness = LED_FULL;
303 else {
304 led->cdev.brightness = LED_OFF;
305 bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
306 }
307 } else {
308 led->cdev.brightness = LED_OFF;
309 bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
310 }
311 spin_unlock_irqrestore(lock, flags);
312 }
313
314 led->cdev.brightness_set = bcm6328_led_set;
315 led->cdev.blink_set = bcm6328_blink_set;
316
317 rc = led_classdev_register(dev, &led->cdev);
318 if (rc < 0)
319 return rc;
320
321 dev_dbg(dev, "registered LED %s\n", led->cdev.name);
322
323 return 0;
324}
325
326static int bcm6328_leds_probe(struct platform_device *pdev)
327{
328 struct device *dev = &pdev->dev;
329 struct device_node *np = pdev->dev.of_node;
330 struct device_node *child;
331 struct resource *mem_r;
332 void __iomem *mem;
333 spinlock_t *lock;
334 unsigned long val, *blink_leds, *blink_delay;
335
336 mem_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
337 if (!mem_r)
338 return -EINVAL;
339
340 mem = devm_ioremap_resource(dev, mem_r);
341 if (IS_ERR(mem))
342 return PTR_ERR(mem);
343
344 lock = devm_kzalloc(dev, sizeof(*lock), GFP_KERNEL);
345 if (!lock)
346 return -ENOMEM;
347
348 blink_leds = devm_kzalloc(dev, sizeof(*blink_leds), GFP_KERNEL);
349 if (!blink_leds)
350 return -ENOMEM;
351
352 blink_delay = devm_kzalloc(dev, sizeof(*blink_delay), GFP_KERNEL);
353 if (!blink_delay)
354 return -ENOMEM;
355
356 spin_lock_init(lock);
357
358 bcm6328_led_write(mem + BCM6328_REG_HWDIS, ~0);
359 bcm6328_led_write(mem + BCM6328_REG_LNKACTSEL_HI, 0);
360 bcm6328_led_write(mem + BCM6328_REG_LNKACTSEL_LO, 0);
361
362 val = bcm6328_led_read(mem + BCM6328_REG_INIT);
363 val &= ~BCM6328_SERIAL_LED_EN;
364 if (of_property_read_bool(np, "brcm,serial-leds"))
365 val |= BCM6328_SERIAL_LED_EN;
366 bcm6328_led_write(mem + BCM6328_REG_INIT, val);
367
368 for_each_available_child_of_node(np, child) {
369 int rc;
370 u32 reg;
371
372 if (of_property_read_u32(child, "reg", &reg))
373 continue;
374
375 if (reg >= BCM6328_LED_MAX_COUNT) {
376 dev_err(dev, "invalid LED (>= %d)\n",
377 BCM6328_LED_MAX_COUNT);
378 continue;
379 }
380
381 if (of_property_read_bool(child, "brcm,hardware-controlled"))
382 rc = bcm6328_hwled(dev, child, reg, mem, lock);
383 else
384 rc = bcm6328_led(dev, child, reg, mem, lock,
385 blink_leds, blink_delay);
386
387 if (rc < 0)
388 return rc;
389 }
390
391 return 0;
392}
393
394static const struct of_device_id bcm6328_leds_of_match[] = {
395 { .compatible = "brcm,bcm6328-leds", },
396 { },
397};
398
399static struct platform_driver bcm6328_leds_driver = {
400 .probe = bcm6328_leds_probe,
401 .driver = {
402 .name = "leds-bcm6328",
403 .of_match_table = bcm6328_leds_of_match,
404 },
405};
406
407module_platform_driver(bcm6328_leds_driver);
408
409MODULE_AUTHOR("Álvaro Fernández Rojas <noltari@gmail.com>");
410MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
411MODULE_DESCRIPTION("LED driver for BCM6328 controllers");
412MODULE_LICENSE("GPL v2");
413MODULE_ALIAS("platform:leds-bcm6328");
diff --git a/drivers/leds/leds-bcm6358.c b/drivers/leds/leds-bcm6358.c
new file mode 100644
index 000000000000..21f96930b3be
--- /dev/null
+++ b/drivers/leds/leds-bcm6358.c
@@ -0,0 +1,243 @@
1/*
2 * Driver for BCM6358 memory-mapped LEDs, based on leds-syscon.c
3 *
4 * Copyright 2015 Álvaro Fernández Rojas <noltari@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11#include <linux/delay.h>
12#include <linux/io.h>
13#include <linux/leds.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/platform_device.h>
17#include <linux/spinlock.h>
18
19#define BCM6358_REG_MODE 0x0
20#define BCM6358_REG_CTRL 0x4
21
22#define BCM6358_SLED_CLKDIV_MASK 3
23#define BCM6358_SLED_CLKDIV_1 0
24#define BCM6358_SLED_CLKDIV_2 1
25#define BCM6358_SLED_CLKDIV_4 2
26#define BCM6358_SLED_CLKDIV_8 3
27
28#define BCM6358_SLED_POLARITY BIT(2)
29#define BCM6358_SLED_BUSY BIT(3)
30
31#define BCM6358_SLED_MAX_COUNT 32
32#define BCM6358_SLED_WAIT 100
33
34/**
35 * struct bcm6358_led - state container for bcm6358 based LEDs
36 * @cdev: LED class device for this LED
37 * @mem: memory resource
38 * @lock: memory lock
39 * @pin: LED pin number
40 * @active_low: LED is active low
41 */
42struct bcm6358_led {
43 struct led_classdev cdev;
44 void __iomem *mem;
45 spinlock_t *lock;
46 unsigned long pin;
47 bool active_low;
48};
49
50static void bcm6358_led_write(void __iomem *reg, unsigned long data)
51{
52 iowrite32be(data, reg);
53}
54
55static unsigned long bcm6358_led_read(void __iomem *reg)
56{
57 return ioread32be(reg);
58}
59
60static unsigned long bcm6358_led_busy(void __iomem *mem)
61{
62 unsigned long val;
63
64 while ((val = bcm6358_led_read(mem + BCM6358_REG_CTRL)) &
65 BCM6358_SLED_BUSY)
66 udelay(BCM6358_SLED_WAIT);
67
68 return val;
69}
70
71static void bcm6358_led_mode(struct bcm6358_led *led, unsigned long value)
72{
73 unsigned long val;
74
75 bcm6358_led_busy(led->mem);
76
77 val = bcm6358_led_read(led->mem + BCM6358_REG_MODE);
78 if ((led->active_low && value == LED_OFF) ||
79 (!led->active_low && value != LED_OFF))
80 val |= BIT(led->pin);
81 else
82 val &= ~(BIT(led->pin));
83 bcm6358_led_write(led->mem + BCM6358_REG_MODE, val);
84}
85
86static void bcm6358_led_set(struct led_classdev *led_cdev,
87 enum led_brightness value)
88{
89 struct bcm6358_led *led =
90 container_of(led_cdev, struct bcm6358_led, cdev);
91 unsigned long flags;
92
93 spin_lock_irqsave(led->lock, flags);
94 bcm6358_led_mode(led, value);
95 spin_unlock_irqrestore(led->lock, flags);
96}
97
98static int bcm6358_led(struct device *dev, struct device_node *nc, u32 reg,
99 void __iomem *mem, spinlock_t *lock)
100{
101 struct bcm6358_led *led;
102 unsigned long flags;
103 const char *state;
104 int rc;
105
106 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
107 if (!led)
108 return -ENOMEM;
109
110 led->pin = reg;
111 led->mem = mem;
112 led->lock = lock;
113
114 if (of_property_read_bool(nc, "active-low"))
115 led->active_low = true;
116
117 led->cdev.name = of_get_property(nc, "label", NULL) ? : nc->name;
118 led->cdev.default_trigger = of_get_property(nc,
119 "linux,default-trigger",
120 NULL);
121
122 spin_lock_irqsave(lock, flags);
123 if (!of_property_read_string(nc, "default-state", &state)) {
124 if (!strcmp(state, "on")) {
125 led->cdev.brightness = LED_FULL;
126 } else if (!strcmp(state, "keep")) {
127 unsigned long val;
128
129 bcm6358_led_busy(led->mem);
130
131 val = bcm6358_led_read(led->mem + BCM6358_REG_MODE);
132 val &= BIT(led->pin);
133 if ((led->active_low && !val) ||
134 (!led->active_low && val))
135 led->cdev.brightness = LED_FULL;
136 else
137 led->cdev.brightness = LED_OFF;
138 } else {
139 led->cdev.brightness = LED_OFF;
140 }
141 } else {
142 led->cdev.brightness = LED_OFF;
143 }
144 bcm6358_led_mode(led, led->cdev.brightness);
145 spin_unlock_irqrestore(lock, flags);
146
147 led->cdev.brightness_set = bcm6358_led_set;
148
149 rc = led_classdev_register(dev, &led->cdev);
150 if (rc < 0)
151 return rc;
152
153 dev_dbg(dev, "registered LED %s\n", led->cdev.name);
154
155 return 0;
156}
157
158static int bcm6358_leds_probe(struct platform_device *pdev)
159{
160 struct device *dev = &pdev->dev;
161 struct device_node *np = pdev->dev.of_node;
162 struct device_node *child;
163 struct resource *mem_r;
164 void __iomem *mem;
165 spinlock_t *lock; /* memory lock */
166 unsigned long val;
167 u32 clk_div;
168
169 mem_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
170 if (!mem_r)
171 return -EINVAL;
172
173 mem = devm_ioremap_resource(dev, mem_r);
174 if (IS_ERR(mem))
175 return PTR_ERR(mem);
176
177 lock = devm_kzalloc(dev, sizeof(*lock), GFP_KERNEL);
178 if (!lock)
179 return -ENOMEM;
180
181 spin_lock_init(lock);
182
183 val = bcm6358_led_busy(mem);
184 val &= ~(BCM6358_SLED_POLARITY | BCM6358_SLED_CLKDIV_MASK);
185 if (of_property_read_bool(np, "brcm,clk-dat-low"))
186 val |= BCM6358_SLED_POLARITY;
187 of_property_read_u32(np, "brcm,clk-div", &clk_div);
188 switch (clk_div) {
189 case 8:
190 val |= BCM6358_SLED_CLKDIV_8;
191 break;
192 case 4:
193 val |= BCM6358_SLED_CLKDIV_4;
194 break;
195 case 2:
196 val |= BCM6358_SLED_CLKDIV_2;
197 break;
198 default:
199 val |= BCM6358_SLED_CLKDIV_1;
200 break;
201 }
202 bcm6358_led_write(mem + BCM6358_REG_CTRL, val);
203
204 for_each_available_child_of_node(np, child) {
205 int rc;
206 u32 reg;
207
208 if (of_property_read_u32(child, "reg", &reg))
209 continue;
210
211 if (reg >= BCM6358_SLED_MAX_COUNT) {
212 dev_err(dev, "invalid LED (%u >= %d)\n", reg,
213 BCM6358_SLED_MAX_COUNT);
214 continue;
215 }
216
217 rc = bcm6358_led(dev, child, reg, mem, lock);
218 if (rc < 0)
219 return rc;
220 }
221
222 return 0;
223}
224
225static const struct of_device_id bcm6358_leds_of_match[] = {
226 { .compatible = "brcm,bcm6358-leds", },
227 { },
228};
229
230static struct platform_driver bcm6358_leds_driver = {
231 .probe = bcm6358_leds_probe,
232 .driver = {
233 .name = "leds-bcm6358",
234 .of_match_table = bcm6358_leds_of_match,
235 },
236};
237
238module_platform_driver(bcm6358_leds_driver);
239
240MODULE_AUTHOR("Álvaro Fernández Rojas <noltari@gmail.com>");
241MODULE_DESCRIPTION("LED driver for BCM6358 controllers");
242MODULE_LICENSE("GPL v2");
243MODULE_ALIAS("platform:leds-bcm6358");
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
index 06dbe18a2065..b316df4a8c1e 100644
--- a/drivers/leds/leds-cobalt-raq.c
+++ b/drivers/leds/leds-cobalt-raq.c
@@ -108,20 +108,8 @@ err_null:
108 return retval; 108 return retval;
109} 109}
110 110
111static int cobalt_raq_led_remove(struct platform_device *pdev)
112{
113 led_classdev_unregister(&raq_power_off_led);
114 led_classdev_unregister(&raq_web_led);
115
116 if (led_port)
117 led_port = NULL;
118
119 return 0;
120}
121
122static struct platform_driver cobalt_raq_led_driver = { 111static struct platform_driver cobalt_raq_led_driver = {
123 .probe = cobalt_raq_led_probe, 112 .probe = cobalt_raq_led_probe,
124 .remove = cobalt_raq_led_remove,
125 .driver = { 113 .driver = {
126 .name = "cobalt-raq-leds", 114 .name = "cobalt-raq-leds",
127 }, 115 },
@@ -131,5 +119,4 @@ static int __init cobalt_raq_led_init(void)
131{ 119{
132 return platform_driver_register(&cobalt_raq_led_driver); 120 return platform_driver_register(&cobalt_raq_led_driver);
133} 121}
134 122device_initcall(cobalt_raq_led_init);
135module_init(cobalt_raq_led_init);
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index d2d54d62afee..af1876a3a77c 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -16,6 +16,7 @@
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/leds.h> 17#include <linux/leds.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/of.h>
19#include <linux/platform_device.h> 20#include <linux/platform_device.h>
20#include <linux/property.h> 21#include <linux/property.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
@@ -198,8 +199,10 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
198 } else { 199 } else {
199 if (IS_ENABLED(CONFIG_OF) && !led.name && np) 200 if (IS_ENABLED(CONFIG_OF) && !led.name && np)
200 led.name = np->name; 201 led.name = np->name;
201 if (!led.name) 202 if (!led.name) {
202 return ERR_PTR(-EINVAL); 203 ret = -EINVAL;
204 goto err;
205 }
203 } 206 }
204 fwnode_property_read_string(child, "linux,default-trigger", 207 fwnode_property_read_string(child, "linux,default-trigger",
205 &led.default_trigger); 208 &led.default_trigger);
@@ -217,18 +220,19 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
217 if (fwnode_property_present(child, "retain-state-suspended")) 220 if (fwnode_property_present(child, "retain-state-suspended"))
218 led.retain_state_suspended = 1; 221 led.retain_state_suspended = 1;
219 222
220 ret = create_gpio_led(&led, &priv->leds[priv->num_leds++], 223 ret = create_gpio_led(&led, &priv->leds[priv->num_leds],
221 dev, NULL); 224 dev, NULL);
222 if (ret < 0) { 225 if (ret < 0) {
223 fwnode_handle_put(child); 226 fwnode_handle_put(child);
224 goto err; 227 goto err;
225 } 228 }
229 priv->num_leds++;
226 } 230 }
227 231
228 return priv; 232 return priv;
229 233
230err: 234err:
231 for (count = priv->num_leds - 2; count >= 0; count--) 235 for (count = priv->num_leds - 1; count >= 0; count--)
232 delete_gpio_led(&priv->leds[count]); 236 delete_gpio_led(&priv->leds[count]);
233 return ERR_PTR(ret); 237 return ERR_PTR(ret);
234} 238}
diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/leds-ktd2692.c
new file mode 100644
index 000000000000..2ae8c4d17ff8
--- /dev/null
+++ b/drivers/leds/leds-ktd2692.c
@@ -0,0 +1,443 @@
1/*
2 * LED driver : leds-ktd2692.c
3 *
4 * Copyright (C) 2015 Samsung Electronics
5 * Ingi Kim <ingi2.kim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/delay.h>
13#include <linux/err.h>
14#include <linux/gpio/consumer.h>
15#include <linux/led-class-flash.h>
16#include <linux/module.h>
17#include <linux/mutex.h>
18#include <linux/of.h>
19#include <linux/platform_device.h>
20#include <linux/regulator/consumer.h>
21#include <linux/workqueue.h>
22
23/* Value related the movie mode */
24#define KTD2692_MOVIE_MODE_CURRENT_LEVELS 16
25#define KTD2692_MM_TO_FL_RATIO(x) ((x) / 3)
26#define KTD2962_MM_MIN_CURR_THRESHOLD_SCALE 8
27
28/* Value related the flash mode */
29#define KTD2692_FLASH_MODE_TIMEOUT_LEVELS 8
30#define KTD2692_FLASH_MODE_TIMEOUT_DISABLE 0
31#define KTD2692_FLASH_MODE_CURR_PERCENT(x) (((x) * 16) / 100)
32
33/* Macro for getting offset of flash timeout */
34#define GET_TIMEOUT_OFFSET(timeout, step) ((timeout) / (step))
35
36/* Base register address */
37#define KTD2692_REG_LVP_BASE 0x00
38#define KTD2692_REG_FLASH_TIMEOUT_BASE 0x20
39#define KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE 0x40
40#define KTD2692_REG_MOVIE_CURRENT_BASE 0x60
41#define KTD2692_REG_FLASH_CURRENT_BASE 0x80
42#define KTD2692_REG_MODE_BASE 0xA0
43
44/* Set bit coding time for expresswire interface */
45#define KTD2692_TIME_RESET_US 700
46#define KTD2692_TIME_DATA_START_TIME_US 10
47#define KTD2692_TIME_HIGH_END_OF_DATA_US 350
48#define KTD2692_TIME_LOW_END_OF_DATA_US 10
49#define KTD2692_TIME_SHORT_BITSET_US 4
50#define KTD2692_TIME_LONG_BITSET_US 12
51
52/* KTD2692 default length of name */
53#define KTD2692_NAME_LENGTH 20
54
55enum ktd2692_bitset {
56 KTD2692_LOW = 0,
57 KTD2692_HIGH,
58};
59
60/* Movie / Flash Mode Control */
61enum ktd2692_led_mode {
62 KTD2692_MODE_DISABLE = 0, /* default */
63 KTD2692_MODE_MOVIE,
64 KTD2692_MODE_FLASH,
65};
66
67struct ktd2692_led_config_data {
68 /* maximum LED current in movie mode */
69 u32 movie_max_microamp;
70 /* maximum LED current in flash mode */
71 u32 flash_max_microamp;
72 /* maximum flash timeout */
73 u32 flash_max_timeout;
74 /* max LED brightness level */
75 enum led_brightness max_brightness;
76};
77
78struct ktd2692_context {
79 /* Related LED Flash class device */
80 struct led_classdev_flash fled_cdev;
81
82 /* secures access to the device */
83 struct mutex lock;
84 struct regulator *regulator;
85 struct work_struct work_brightness_set;
86
87 struct gpio_desc *aux_gpio;
88 struct gpio_desc *ctrl_gpio;
89
90 enum ktd2692_led_mode mode;
91 enum led_brightness torch_brightness;
92};
93
94static struct ktd2692_context *fled_cdev_to_led(
95 struct led_classdev_flash *fled_cdev)
96{
97 return container_of(fled_cdev, struct ktd2692_context, fled_cdev);
98}
99
100static void ktd2692_expresswire_start(struct ktd2692_context *led)
101{
102 gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
103 udelay(KTD2692_TIME_DATA_START_TIME_US);
104}
105
106static void ktd2692_expresswire_reset(struct ktd2692_context *led)
107{
108 gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
109 udelay(KTD2692_TIME_RESET_US);
110}
111
112static void ktd2692_expresswire_end(struct ktd2692_context *led)
113{
114 gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
115 udelay(KTD2692_TIME_LOW_END_OF_DATA_US);
116 gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
117 udelay(KTD2692_TIME_HIGH_END_OF_DATA_US);
118}
119
120static void ktd2692_expresswire_set_bit(struct ktd2692_context *led, bool bit)
121{
122 /*
123 * The Low Bit(0) and High Bit(1) is based on a time detection
124 * algorithm between time low and time high
125 * Time_(L_LB) : Low time of the Low Bit(0)
126 * Time_(H_LB) : High time of the LOW Bit(0)
127 * Time_(L_HB) : Low time of the High Bit(1)
128 * Time_(H_HB) : High time of the High Bit(1)
129 *
130 * It can be simplified to:
131 * Low Bit(0) : 2 * Time_(H_LB) < Time_(L_LB)
132 * High Bit(1) : 2 * Time_(L_HB) < Time_(H_HB)
133 * HIGH ___ ____ _.. _________ ___
134 * |_________| |_.. |____| |__|
135 * LOW <L_LB> <H_LB> <L_HB> <H_HB>
136 * [ Low Bit (0) ] [ High Bit(1) ]
137 */
138 if (bit) {
139 gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
140 udelay(KTD2692_TIME_SHORT_BITSET_US);
141 gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
142 udelay(KTD2692_TIME_LONG_BITSET_US);
143 } else {
144 gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
145 udelay(KTD2692_TIME_LONG_BITSET_US);
146 gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
147 udelay(KTD2692_TIME_SHORT_BITSET_US);
148 }
149}
150
151static void ktd2692_expresswire_write(struct ktd2692_context *led, u8 value)
152{
153 int i;
154
155 ktd2692_expresswire_start(led);
156 for (i = 7; i >= 0; i--)
157 ktd2692_expresswire_set_bit(led, value & BIT(i));
158 ktd2692_expresswire_end(led);
159}
160
161static void ktd2692_brightness_set(struct ktd2692_context *led,
162 enum led_brightness brightness)
163{
164 mutex_lock(&led->lock);
165
166 if (brightness == LED_OFF) {
167 led->mode = KTD2692_MODE_DISABLE;
168 gpiod_direction_output(led->aux_gpio, KTD2692_LOW);
169 } else {
170 ktd2692_expresswire_write(led, brightness |
171 KTD2692_REG_MOVIE_CURRENT_BASE);
172 led->mode = KTD2692_MODE_MOVIE;
173 }
174
175 ktd2692_expresswire_write(led, led->mode | KTD2692_REG_MODE_BASE);
176 mutex_unlock(&led->lock);
177}
178
179static void ktd2692_brightness_set_work(struct work_struct *work)
180{
181 struct ktd2692_context *led =
182 container_of(work, struct ktd2692_context, work_brightness_set);
183
184 ktd2692_brightness_set(led, led->torch_brightness);
185}
186
187static void ktd2692_led_brightness_set(struct led_classdev *led_cdev,
188 enum led_brightness brightness)
189{
190 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
191 struct ktd2692_context *led = fled_cdev_to_led(fled_cdev);
192
193 led->torch_brightness = brightness;
194 schedule_work(&led->work_brightness_set);
195}
196
197static int ktd2692_led_brightness_set_sync(struct led_classdev *led_cdev,
198 enum led_brightness brightness)
199{
200 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
201 struct ktd2692_context *led = fled_cdev_to_led(fled_cdev);
202
203 ktd2692_brightness_set(led, brightness);
204
205 return 0;
206}
207
208static int ktd2692_led_flash_strobe_set(struct led_classdev_flash *fled_cdev,
209 bool state)
210{
211 struct ktd2692_context *led = fled_cdev_to_led(fled_cdev);
212 struct led_flash_setting *timeout = &fled_cdev->timeout;
213 u32 flash_tm_reg;
214
215 mutex_lock(&led->lock);
216
217 if (state) {
218 flash_tm_reg = GET_TIMEOUT_OFFSET(timeout->val, timeout->step);
219 ktd2692_expresswire_write(led, flash_tm_reg
220 | KTD2692_REG_FLASH_TIMEOUT_BASE);
221
222 led->mode = KTD2692_MODE_FLASH;
223 gpiod_direction_output(led->aux_gpio, KTD2692_HIGH);
224 } else {
225 led->mode = KTD2692_MODE_DISABLE;
226 gpiod_direction_output(led->aux_gpio, KTD2692_LOW);
227 }
228
229 ktd2692_expresswire_write(led, led->mode | KTD2692_REG_MODE_BASE);
230
231 fled_cdev->led_cdev.brightness = LED_OFF;
232 led->mode = KTD2692_MODE_DISABLE;
233
234 mutex_unlock(&led->lock);
235
236 return 0;
237}
238
239static int ktd2692_led_flash_timeout_set(struct led_classdev_flash *fled_cdev,
240 u32 timeout)
241{
242 return 0;
243}
244
245static void ktd2692_init_movie_current_max(struct ktd2692_led_config_data *cfg)
246{
247 u32 offset, step;
248 u32 movie_current_microamp;
249
250 offset = KTD2692_MOVIE_MODE_CURRENT_LEVELS;
251 step = KTD2692_MM_TO_FL_RATIO(cfg->flash_max_microamp)
252 / KTD2692_MOVIE_MODE_CURRENT_LEVELS;
253
254 do {
255 movie_current_microamp = step * offset;
256 offset--;
257 } while ((movie_current_microamp > cfg->movie_max_microamp) &&
258 (offset > 0));
259
260 cfg->max_brightness = offset;
261}
262
263static void ktd2692_init_flash_timeout(struct led_classdev_flash *fled_cdev,
264 struct ktd2692_led_config_data *cfg)
265{
266 struct led_flash_setting *setting;
267
268 setting = &fled_cdev->timeout;
269 setting->min = KTD2692_FLASH_MODE_TIMEOUT_DISABLE;
270 setting->max = cfg->flash_max_timeout;
271 setting->step = cfg->flash_max_timeout
272 / (KTD2692_FLASH_MODE_TIMEOUT_LEVELS - 1);
273 setting->val = cfg->flash_max_timeout;
274}
275
276static void ktd2692_setup(struct ktd2692_context *led)
277{
278 led->mode = KTD2692_MODE_DISABLE;
279 ktd2692_expresswire_reset(led);
280 gpiod_direction_output(led->aux_gpio, KTD2692_LOW);
281
282 ktd2692_expresswire_write(led, (KTD2962_MM_MIN_CURR_THRESHOLD_SCALE - 1)
283 | KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE);
284 ktd2692_expresswire_write(led, KTD2692_FLASH_MODE_CURR_PERCENT(45)
285 | KTD2692_REG_FLASH_CURRENT_BASE);
286}
287
288static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev,
289 struct ktd2692_led_config_data *cfg)
290{
291 struct device_node *np = dev->of_node;
292 struct device_node *child_node;
293 int ret;
294
295 if (!dev->of_node)
296 return -ENXIO;
297
298 led->ctrl_gpio = devm_gpiod_get(dev, "ctrl", GPIOD_ASIS);
299 if (IS_ERR(led->ctrl_gpio)) {
300 ret = PTR_ERR(led->ctrl_gpio);
301 dev_err(dev, "cannot get ctrl-gpios %d\n", ret);
302 return ret;
303 }
304
305 led->aux_gpio = devm_gpiod_get(dev, "aux", GPIOD_ASIS);
306 if (IS_ERR(led->aux_gpio)) {
307 ret = PTR_ERR(led->aux_gpio);
308 dev_err(dev, "cannot get aux-gpios %d\n", ret);
309 return ret;
310 }
311
312 led->regulator = devm_regulator_get(dev, "vin");
313 if (IS_ERR(led->regulator))
314 led->regulator = NULL;
315
316 if (led->regulator) {
317 ret = regulator_enable(led->regulator);
318 if (ret)
319 dev_err(dev, "Failed to enable supply: %d\n", ret);
320 }
321
322 child_node = of_get_next_available_child(np, NULL);
323 if (!child_node) {
324 dev_err(dev, "No DT child node found for connected LED.\n");
325 return -EINVAL;
326 }
327
328 led->fled_cdev.led_cdev.name =
329 of_get_property(child_node, "label", NULL) ? : child_node->name;
330
331 ret = of_property_read_u32(child_node, "led-max-microamp",
332 &cfg->movie_max_microamp);
333 if (ret) {
334 dev_err(dev, "failed to parse led-max-microamp\n");
335 return ret;
336 }
337
338 ret = of_property_read_u32(child_node, "flash-max-microamp",
339 &cfg->flash_max_microamp);
340 if (ret) {
341 dev_err(dev, "failed to parse flash-max-microamp\n");
342 return ret;
343 }
344
345 ret = of_property_read_u32(child_node, "flash-max-timeout-us",
346 &cfg->flash_max_timeout);
347 if (ret)
348 dev_err(dev, "failed to parse flash-max-timeout-us\n");
349
350 of_node_put(child_node);
351 return ret;
352}
353
354static const struct led_flash_ops flash_ops = {
355 .strobe_set = ktd2692_led_flash_strobe_set,
356 .timeout_set = ktd2692_led_flash_timeout_set,
357};
358
359static int ktd2692_probe(struct platform_device *pdev)
360{
361 struct ktd2692_context *led;
362 struct led_classdev *led_cdev;
363 struct led_classdev_flash *fled_cdev;
364 struct ktd2692_led_config_data led_cfg;
365 int ret;
366
367 led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
368 if (!led)
369 return -ENOMEM;
370
371 fled_cdev = &led->fled_cdev;
372 led_cdev = &fled_cdev->led_cdev;
373
374 ret = ktd2692_parse_dt(led, &pdev->dev, &led_cfg);
375 if (ret)
376 return ret;
377
378 ktd2692_init_flash_timeout(fled_cdev, &led_cfg);
379 ktd2692_init_movie_current_max(&led_cfg);
380
381 fled_cdev->ops = &flash_ops;
382
383 led_cdev->max_brightness = led_cfg.max_brightness;
384 led_cdev->brightness_set = ktd2692_led_brightness_set;
385 led_cdev->brightness_set_sync = ktd2692_led_brightness_set_sync;
386 led_cdev->flags |= LED_CORE_SUSPENDRESUME | LED_DEV_CAP_FLASH;
387
388 mutex_init(&led->lock);
389 INIT_WORK(&led->work_brightness_set, ktd2692_brightness_set_work);
390
391 platform_set_drvdata(pdev, led);
392
393 ret = led_classdev_flash_register(&pdev->dev, fled_cdev);
394 if (ret) {
395 dev_err(&pdev->dev, "can't register LED %s\n", led_cdev->name);
396 mutex_destroy(&led->lock);
397 return ret;
398 }
399
400 ktd2692_setup(led);
401
402 return 0;
403}
404
405static int ktd2692_remove(struct platform_device *pdev)
406{
407 struct ktd2692_context *led = platform_get_drvdata(pdev);
408 int ret;
409
410 led_classdev_flash_unregister(&led->fled_cdev);
411 cancel_work_sync(&led->work_brightness_set);
412
413 if (led->regulator) {
414 ret = regulator_disable(led->regulator);
415 if (ret)
416 dev_err(&pdev->dev,
417 "Failed to disable supply: %d\n", ret);
418 }
419
420 mutex_destroy(&led->lock);
421
422 return 0;
423}
424
425static const struct of_device_id ktd2692_match[] = {
426 { .compatible = "kinetic,ktd2692", },
427 { /* sentinel */ },
428};
429
430static struct platform_driver ktd2692_driver = {
431 .driver = {
432 .name = "ktd2692",
433 .of_match_table = ktd2692_match,
434 },
435 .probe = ktd2692_probe,
436 .remove = ktd2692_remove,
437};
438
439module_platform_driver(ktd2692_driver);
440
441MODULE_AUTHOR("Ingi Kim <ingi2.kim@samsung.com>");
442MODULE_DESCRIPTION("Kinetic KTD2692 LED driver");
443MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 9e1716f8098c..584dbbcec659 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -50,6 +50,7 @@
50#define LP5523_REG_OP_MODE 0x01 50#define LP5523_REG_OP_MODE 0x01
51#define LP5523_REG_ENABLE_LEDS_MSB 0x04 51#define LP5523_REG_ENABLE_LEDS_MSB 0x04
52#define LP5523_REG_ENABLE_LEDS_LSB 0x05 52#define LP5523_REG_ENABLE_LEDS_LSB 0x05
53#define LP5523_REG_LED_CTRL_BASE 0x06
53#define LP5523_REG_LED_PWM_BASE 0x16 54#define LP5523_REG_LED_PWM_BASE 0x16
54#define LP5523_REG_LED_CURRENT_BASE 0x26 55#define LP5523_REG_LED_CURRENT_BASE 0x26
55#define LP5523_REG_CONFIG 0x36 56#define LP5523_REG_CONFIG 0x36
@@ -57,6 +58,7 @@
57#define LP5523_REG_RESET 0x3D 58#define LP5523_REG_RESET 0x3D
58#define LP5523_REG_LED_TEST_CTRL 0x41 59#define LP5523_REG_LED_TEST_CTRL 0x41
59#define LP5523_REG_LED_TEST_ADC 0x42 60#define LP5523_REG_LED_TEST_ADC 0x42
61#define LP5523_REG_MASTER_FADER_BASE 0x48
60#define LP5523_REG_CH1_PROG_START 0x4C 62#define LP5523_REG_CH1_PROG_START 0x4C
61#define LP5523_REG_CH2_PROG_START 0x4D 63#define LP5523_REG_CH2_PROG_START 0x4D
62#define LP5523_REG_CH3_PROG_START 0x4E 64#define LP5523_REG_CH3_PROG_START 0x4E
@@ -78,6 +80,9 @@
78#define LP5523_EXT_CLK_USED 0x08 80#define LP5523_EXT_CLK_USED 0x08
79#define LP5523_ENG_STATUS_MASK 0x07 81#define LP5523_ENG_STATUS_MASK 0x07
80 82
83#define LP5523_FADER_MAPPING_MASK 0xC0
84#define LP5523_FADER_MAPPING_SHIFT 6
85
81/* Memory Page Selection */ 86/* Memory Page Selection */
82#define LP5523_PAGE_ENG1 0 87#define LP5523_PAGE_ENG1 0
83#define LP5523_PAGE_ENG2 1 88#define LP5523_PAGE_ENG2 1
@@ -666,6 +671,137 @@ release_lock:
666 return pos; 671 return pos;
667} 672}
668 673
674#define show_fader(nr) \
675static ssize_t show_master_fader##nr(struct device *dev, \
676 struct device_attribute *attr, \
677 char *buf) \
678{ \
679 return show_master_fader(dev, attr, buf, nr); \
680}
681
682#define store_fader(nr) \
683static ssize_t store_master_fader##nr(struct device *dev, \
684 struct device_attribute *attr, \
685 const char *buf, size_t len) \
686{ \
687 return store_master_fader(dev, attr, buf, len, nr); \
688}
689
690static ssize_t show_master_fader(struct device *dev,
691 struct device_attribute *attr,
692 char *buf, int nr)
693{
694 struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
695 struct lp55xx_chip *chip = led->chip;
696 int ret;
697 u8 val;
698
699 mutex_lock(&chip->lock);
700 ret = lp55xx_read(chip, LP5523_REG_MASTER_FADER_BASE + nr - 1, &val);
701 mutex_unlock(&chip->lock);
702
703 if (ret == 0)
704 ret = sprintf(buf, "%u\n", val);
705
706 return ret;
707}
708show_fader(1)
709show_fader(2)
710show_fader(3)
711
712static ssize_t store_master_fader(struct device *dev,
713 struct device_attribute *attr,
714 const char *buf, size_t len, int nr)
715{
716 struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
717 struct lp55xx_chip *chip = led->chip;
718 int ret;
719 unsigned long val;
720
721 if (kstrtoul(buf, 0, &val))
722 return -EINVAL;
723
724 if (val > 0xff)
725 return -EINVAL;
726
727 mutex_lock(&chip->lock);
728 ret = lp55xx_write(chip, LP5523_REG_MASTER_FADER_BASE + nr - 1,
729 (u8)val);
730 mutex_unlock(&chip->lock);
731
732 if (ret == 0)
733 ret = len;
734
735 return ret;
736}
737store_fader(1)
738store_fader(2)
739store_fader(3)
740
741static ssize_t show_master_fader_leds(struct device *dev,
742 struct device_attribute *attr,
743 char *buf)
744{
745 struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
746 struct lp55xx_chip *chip = led->chip;
747 int i, ret, pos = 0;
748 u8 val;
749
750 mutex_lock(&chip->lock);
751
752 for (i = 0; i < LP5523_MAX_LEDS; i++) {
753 ret = lp55xx_read(chip, LP5523_REG_LED_CTRL_BASE + i, &val);
754 if (ret)
755 goto leave;
756
757 val = (val & LP5523_FADER_MAPPING_MASK)
758 >> LP5523_FADER_MAPPING_SHIFT;
759 if (val > 3) {
760 ret = -EINVAL;
761 goto leave;
762 }
763 buf[pos++] = val + '0';
764 }
765 buf[pos++] = '\n';
766 ret = pos;
767leave:
768 mutex_unlock(&chip->lock);
769 return ret;
770}
771
772static ssize_t store_master_fader_leds(struct device *dev,
773 struct device_attribute *attr,
774 const char *buf, size_t len)
775{
776 struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
777 struct lp55xx_chip *chip = led->chip;
778 int i, n, ret;
779 u8 val;
780
781 n = min_t(int, len, LP5523_MAX_LEDS);
782
783 mutex_lock(&chip->lock);
784
785 for (i = 0; i < n; i++) {
786 if (buf[i] >= '0' && buf[i] <= '3') {
787 val = (buf[i] - '0') << LP5523_FADER_MAPPING_SHIFT;
788 ret = lp55xx_update_bits(chip,
789 LP5523_REG_LED_CTRL_BASE + i,
790 LP5523_FADER_MAPPING_MASK,
791 val);
792 if (ret)
793 goto leave;
794 } else {
795 ret = -EINVAL;
796 goto leave;
797 }
798 }
799 ret = len;
800leave:
801 mutex_unlock(&chip->lock);
802 return ret;
803}
804
669static void lp5523_led_brightness_work(struct work_struct *work) 805static void lp5523_led_brightness_work(struct work_struct *work)
670{ 806{
671 struct lp55xx_led *led = container_of(work, struct lp55xx_led, 807 struct lp55xx_led *led = container_of(work, struct lp55xx_led,
@@ -688,6 +824,14 @@ static LP55XX_DEV_ATTR_WO(engine1_load, store_engine1_load);
688static LP55XX_DEV_ATTR_WO(engine2_load, store_engine2_load); 824static LP55XX_DEV_ATTR_WO(engine2_load, store_engine2_load);
689static LP55XX_DEV_ATTR_WO(engine3_load, store_engine3_load); 825static LP55XX_DEV_ATTR_WO(engine3_load, store_engine3_load);
690static LP55XX_DEV_ATTR_RO(selftest, lp5523_selftest); 826static LP55XX_DEV_ATTR_RO(selftest, lp5523_selftest);
827static LP55XX_DEV_ATTR_RW(master_fader1, show_master_fader1,
828 store_master_fader1);
829static LP55XX_DEV_ATTR_RW(master_fader2, show_master_fader2,
830 store_master_fader2);
831static LP55XX_DEV_ATTR_RW(master_fader3, show_master_fader3,
832 store_master_fader3);
833static LP55XX_DEV_ATTR_RW(master_fader_leds, show_master_fader_leds,
834 store_master_fader_leds);
691 835
692static struct attribute *lp5523_attributes[] = { 836static struct attribute *lp5523_attributes[] = {
693 &dev_attr_engine1_mode.attr, 837 &dev_attr_engine1_mode.attr,
@@ -700,6 +844,10 @@ static struct attribute *lp5523_attributes[] = {
700 &dev_attr_engine2_leds.attr, 844 &dev_attr_engine2_leds.attr,
701 &dev_attr_engine3_leds.attr, 845 &dev_attr_engine3_leds.attr,
702 &dev_attr_selftest.attr, 846 &dev_attr_selftest.attr,
847 &dev_attr_master_fader1.attr,
848 &dev_attr_master_fader2.attr,
849 &dev_attr_master_fader3.attr,
850 &dev_attr_master_fader_leds.attr,
703 NULL, 851 NULL,
704}; 852};
705 853
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index 77c26bc32eed..96d51e9879c9 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -223,7 +223,7 @@ static int lp55xx_request_firmware(struct lp55xx_chip *chip)
223 const char *name = chip->cl->name; 223 const char *name = chip->cl->name;
224 struct device *dev = &chip->cl->dev; 224 struct device *dev = &chip->cl->dev;
225 225
226 return request_firmware_nowait(THIS_MODULE, true, name, dev, 226 return request_firmware_nowait(THIS_MODULE, false, name, dev,
227 GFP_KERNEL, chip, lp55xx_firmware_loaded); 227 GFP_KERNEL, chip, lp55xx_firmware_loaded);
228} 228}
229 229
diff --git a/drivers/leds/leds-max77693.c b/drivers/leds/leds-max77693.c
new file mode 100644
index 000000000000..b8b0eec7b540
--- /dev/null
+++ b/drivers/leds/leds-max77693.c
@@ -0,0 +1,1097 @@
1/*
2 * LED Flash class driver for the flash cell of max77693 mfd.
3 *
4 * Copyright (C) 2015, Samsung Electronics Co., Ltd.
5 *
6 * Authors: Jacek Anaszewski <j.anaszewski@samsung.com>
7 * Andrzej Hajda <a.hajda@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 */
13
14#include <linux/led-class-flash.h>
15#include <linux/mfd/max77693.h>
16#include <linux/mfd/max77693-private.h>
17#include <linux/module.h>
18#include <linux/mutex.h>
19#include <linux/platform_device.h>
20#include <linux/regmap.h>
21#include <linux/slab.h>
22#include <linux/workqueue.h>
23#include <media/v4l2-flash-led-class.h>
24
25#define MODE_OFF 0
26#define MODE_FLASH(a) (1 << (a))
27#define MODE_TORCH(a) (1 << (2 + (a)))
28#define MODE_FLASH_EXTERNAL(a) (1 << (4 + (a)))
29
30#define MODE_FLASH_MASK (MODE_FLASH(FLED1) | MODE_FLASH(FLED2) | \
31 MODE_FLASH_EXTERNAL(FLED1) | \
32 MODE_FLASH_EXTERNAL(FLED2))
33#define MODE_TORCH_MASK (MODE_TORCH(FLED1) | MODE_TORCH(FLED2))
34
35#define FLED1_IOUT (1 << 0)
36#define FLED2_IOUT (1 << 1)
37
38enum max77693_fled {
39 FLED1,
40 FLED2,
41};
42
43enum max77693_led_mode {
44 FLASH,
45 TORCH,
46};
47
48struct max77693_led_config_data {
49 const char *label[2];
50 u32 iout_torch_max[2];
51 u32 iout_flash_max[2];
52 u32 flash_timeout_max[2];
53 u32 num_leds;
54 u32 boost_mode;
55 u32 boost_vout;
56 u32 low_vsys;
57};
58
59struct max77693_sub_led {
60 /* corresponding FLED output identifier */
61 int fled_id;
62 /* corresponding LED Flash class device */
63 struct led_classdev_flash fled_cdev;
64 /* assures led-triggers compatibility */
65 struct work_struct work_brightness_set;
66 /* V4L2 Flash device */
67 struct v4l2_flash *v4l2_flash;
68
69 /* brightness cache */
70 unsigned int torch_brightness;
71 /* flash timeout cache */
72 unsigned int flash_timeout;
73 /* flash faults that may have occurred */
74 u32 flash_faults;
75};
76
77struct max77693_led_device {
78 /* parent mfd regmap */
79 struct regmap *regmap;
80 /* platform device data */
81 struct platform_device *pdev;
82 /* secures access to the device */
83 struct mutex lock;
84
85 /* sub led data */
86 struct max77693_sub_led sub_leds[2];
87
88 /* maximum torch current values for FLED outputs */
89 u32 iout_torch_max[2];
90 /* maximum flash current values for FLED outputs */
91 u32 iout_flash_max[2];
92
93 /* current flash timeout cache */
94 unsigned int current_flash_timeout;
95 /* ITORCH register cache */
96 u8 torch_iout_reg;
97 /* mode of fled outputs */
98 unsigned int mode_flags;
99 /* recently strobed fled */
100 int strobing_sub_led_id;
101 /* bitmask of FLED outputs use state (bit 0. - FLED1, bit 1. - FLED2) */
102 u8 fled_mask;
103 /* FLED modes that can be set */
104 u8 allowed_modes;
105
106 /* arrangement of current outputs */
107 bool iout_joint;
108};
109
110static u8 max77693_led_iout_to_reg(u32 ua)
111{
112 if (ua < FLASH_IOUT_MIN)
113 ua = FLASH_IOUT_MIN;
114 return (ua - FLASH_IOUT_MIN) / FLASH_IOUT_STEP;
115}
116
117static u8 max77693_flash_timeout_to_reg(u32 us)
118{
119 return (us - FLASH_TIMEOUT_MIN) / FLASH_TIMEOUT_STEP;
120}
121
122static inline struct max77693_sub_led *flcdev_to_sub_led(
123 struct led_classdev_flash *fled_cdev)
124{
125 return container_of(fled_cdev, struct max77693_sub_led, fled_cdev);
126}
127
128static inline struct max77693_led_device *sub_led_to_led(
129 struct max77693_sub_led *sub_led)
130{
131 return container_of(sub_led, struct max77693_led_device,
132 sub_leds[sub_led->fled_id]);
133}
134
135static inline u8 max77693_led_vsys_to_reg(u32 mv)
136{
137 return ((mv - MAX_FLASH1_VSYS_MIN) / MAX_FLASH1_VSYS_STEP) << 2;
138}
139
140static inline u8 max77693_led_vout_to_reg(u32 mv)
141{
142 return (mv - FLASH_VOUT_MIN) / FLASH_VOUT_STEP + FLASH_VOUT_RMIN;
143}
144
145static inline bool max77693_fled_used(struct max77693_led_device *led,
146 int fled_id)
147{
148 u8 fled_bit = (fled_id == FLED1) ? FLED1_IOUT : FLED2_IOUT;
149
150 return led->fled_mask & fled_bit;
151}
152
153static int max77693_set_mode_reg(struct max77693_led_device *led, u8 mode)
154{
155 struct regmap *rmap = led->regmap;
156 int ret, v = 0, i;
157
158 for (i = FLED1; i <= FLED2; ++i) {
159 if (mode & MODE_TORCH(i))
160 v |= FLASH_EN_ON << TORCH_EN_SHIFT(i);
161
162 if (mode & MODE_FLASH(i)) {
163 v |= FLASH_EN_ON << FLASH_EN_SHIFT(i);
164 } else if (mode & MODE_FLASH_EXTERNAL(i)) {
165 v |= FLASH_EN_FLASH << FLASH_EN_SHIFT(i);
166 /*
167 * Enable hw triggering also for torch mode, as some
168 * camera sensors use torch led to fathom ambient light
169 * conditions before strobing the flash.
170 */
171 v |= FLASH_EN_TORCH << TORCH_EN_SHIFT(i);
172 }
173 }
174
175 /* Reset the register only prior setting flash modes */
176 if (mode & ~(MODE_TORCH(FLED1) | MODE_TORCH(FLED2))) {
177 ret = regmap_write(rmap, MAX77693_LED_REG_FLASH_EN, 0);
178 if (ret < 0)
179 return ret;
180 }
181
182 return regmap_write(rmap, MAX77693_LED_REG_FLASH_EN, v);
183}
184
185static int max77693_add_mode(struct max77693_led_device *led, u8 mode)
186{
187 u8 new_mode_flags;
188 int i, ret;
189
190 if (led->iout_joint)
191 /* Span the mode on FLED2 for joint iouts case */
192 mode |= (mode << 1);
193
194 /*
195 * FLASH_EXTERNAL mode activates FLASHEN and TORCHEN pins in the device.
196 * Corresponding register bit fields interfere with SW triggered modes,
197 * thus clear them to ensure proper device configuration.
198 */
199 for (i = FLED1; i <= FLED2; ++i)
200 if (mode & MODE_FLASH_EXTERNAL(i))
201 led->mode_flags &= (~MODE_TORCH(i) & ~MODE_FLASH(i));
202
203 new_mode_flags = mode | led->mode_flags;
204 new_mode_flags &= led->allowed_modes;
205
206 if (new_mode_flags ^ led->mode_flags)
207 led->mode_flags = new_mode_flags;
208 else
209 return 0;
210
211 ret = max77693_set_mode_reg(led, led->mode_flags);
212 if (ret < 0)
213 return ret;
214
215 /*
216 * Clear flash mode flag after setting the mode to avoid spurious flash
217 * strobing on each subsequent torch mode setting.
218 */
219 if (mode & MODE_FLASH_MASK)
220 led->mode_flags &= ~mode;
221
222 return ret;
223}
224
225static int max77693_clear_mode(struct max77693_led_device *led,
226 u8 mode)
227{
228 if (led->iout_joint)
229 /* Clear mode also on FLED2 for joint iouts case */
230 mode |= (mode << 1);
231
232 led->mode_flags &= ~mode;
233
234 return max77693_set_mode_reg(led, led->mode_flags);
235}
236
237static void max77693_add_allowed_modes(struct max77693_led_device *led,
238 int fled_id, enum max77693_led_mode mode)
239{
240 if (mode == FLASH)
241 led->allowed_modes |= (MODE_FLASH(fled_id) |
242 MODE_FLASH_EXTERNAL(fled_id));
243 else
244 led->allowed_modes |= MODE_TORCH(fled_id);
245}
246
247static void max77693_distribute_currents(struct max77693_led_device *led,
248 int fled_id, enum max77693_led_mode mode,
249 u32 micro_amp, u32 iout_max[2], u32 iout[2])
250{
251 if (!led->iout_joint) {
252 iout[fled_id] = micro_amp;
253 max77693_add_allowed_modes(led, fled_id, mode);
254 return;
255 }
256
257 iout[FLED1] = min(micro_amp, iout_max[FLED1]);
258 iout[FLED2] = micro_amp - iout[FLED1];
259
260 if (mode == FLASH)
261 led->allowed_modes &= ~MODE_FLASH_MASK;
262 else
263 led->allowed_modes &= ~MODE_TORCH_MASK;
264
265 max77693_add_allowed_modes(led, FLED1, mode);
266
267 if (iout[FLED2])
268 max77693_add_allowed_modes(led, FLED2, mode);
269}
270
271static int max77693_set_torch_current(struct max77693_led_device *led,
272 int fled_id, u32 micro_amp)
273{
274 struct regmap *rmap = led->regmap;
275 u8 iout1_reg = 0, iout2_reg = 0;
276 u32 iout[2];
277
278 max77693_distribute_currents(led, fled_id, TORCH, micro_amp,
279 led->iout_torch_max, iout);
280
281 if (fled_id == FLED1 || led->iout_joint) {
282 iout1_reg = max77693_led_iout_to_reg(iout[FLED1]);
283 led->torch_iout_reg &= TORCH_IOUT_MASK(TORCH_IOUT2_SHIFT);
284 }
285 if (fled_id == FLED2 || led->iout_joint) {
286 iout2_reg = max77693_led_iout_to_reg(iout[FLED2]);
287 led->torch_iout_reg &= TORCH_IOUT_MASK(TORCH_IOUT1_SHIFT);
288 }
289
290 led->torch_iout_reg |= ((iout1_reg << TORCH_IOUT1_SHIFT) |
291 (iout2_reg << TORCH_IOUT2_SHIFT));
292
293 return regmap_write(rmap, MAX77693_LED_REG_ITORCH,
294 led->torch_iout_reg);
295}
296
297static int max77693_set_flash_current(struct max77693_led_device *led,
298 int fled_id,
299 u32 micro_amp)
300{
301 struct regmap *rmap = led->regmap;
302 u8 iout1_reg, iout2_reg;
303 u32 iout[2];
304 int ret = -EINVAL;
305
306 max77693_distribute_currents(led, fled_id, FLASH, micro_amp,
307 led->iout_flash_max, iout);
308
309 if (fled_id == FLED1 || led->iout_joint) {
310 iout1_reg = max77693_led_iout_to_reg(iout[FLED1]);
311 ret = regmap_write(rmap, MAX77693_LED_REG_IFLASH1,
312 iout1_reg);
313 if (ret < 0)
314 return ret;
315 }
316 if (fled_id == FLED2 || led->iout_joint) {
317 iout2_reg = max77693_led_iout_to_reg(iout[FLED2]);
318 ret = regmap_write(rmap, MAX77693_LED_REG_IFLASH2,
319 iout2_reg);
320 }
321
322 return ret;
323}
324
325static int max77693_set_timeout(struct max77693_led_device *led, u32 microsec)
326{
327 struct regmap *rmap = led->regmap;
328 u8 v;
329 int ret;
330
331 v = max77693_flash_timeout_to_reg(microsec) | FLASH_TMR_LEVEL;
332
333 ret = regmap_write(rmap, MAX77693_LED_REG_FLASH_TIMER, v);
334 if (ret < 0)
335 return ret;
336
337 led->current_flash_timeout = microsec;
338
339 return 0;
340}
341
342static int max77693_get_strobe_status(struct max77693_led_device *led,
343 bool *state)
344{
345 struct regmap *rmap = led->regmap;
346 unsigned int v;
347 int ret;
348
349 ret = regmap_read(rmap, MAX77693_LED_REG_FLASH_STATUS, &v);
350 if (ret < 0)
351 return ret;
352
353 *state = v & FLASH_STATUS_FLASH_ON;
354
355 return ret;
356}
357
358static int max77693_get_flash_faults(struct max77693_sub_led *sub_led)
359{
360 struct max77693_led_device *led = sub_led_to_led(sub_led);
361 struct regmap *rmap = led->regmap;
362 unsigned int v;
363 u8 fault_open_mask, fault_short_mask;
364 int ret;
365
366 sub_led->flash_faults = 0;
367
368 if (led->iout_joint) {
369 fault_open_mask = FLASH_INT_FLED1_OPEN | FLASH_INT_FLED2_OPEN;
370 fault_short_mask = FLASH_INT_FLED1_SHORT |
371 FLASH_INT_FLED2_SHORT;
372 } else {
373 fault_open_mask = (sub_led->fled_id == FLED1) ?
374 FLASH_INT_FLED1_OPEN :
375 FLASH_INT_FLED2_OPEN;
376 fault_short_mask = (sub_led->fled_id == FLED1) ?
377 FLASH_INT_FLED1_SHORT :
378 FLASH_INT_FLED2_SHORT;
379 }
380
381 ret = regmap_read(rmap, MAX77693_LED_REG_FLASH_INT, &v);
382 if (ret < 0)
383 return ret;
384
385 if (v & fault_open_mask)
386 sub_led->flash_faults |= LED_FAULT_OVER_VOLTAGE;
387 if (v & fault_short_mask)
388 sub_led->flash_faults |= LED_FAULT_SHORT_CIRCUIT;
389 if (v & FLASH_INT_OVER_CURRENT)
390 sub_led->flash_faults |= LED_FAULT_OVER_CURRENT;
391
392 return 0;
393}
394
395static int max77693_setup(struct max77693_led_device *led,
396 struct max77693_led_config_data *led_cfg)
397{
398 struct regmap *rmap = led->regmap;
399 int i, first_led, last_led, ret;
400 u32 max_flash_curr[2];
401 u8 v;
402
403 /*
404 * Initialize only flash current. Torch current doesn't
405 * require initialization as ITORCH register is written with
406 * new value each time brightness_set op is called.
407 */
408 if (led->iout_joint) {
409 first_led = FLED1;
410 last_led = FLED1;
411 max_flash_curr[FLED1] = led_cfg->iout_flash_max[FLED1] +
412 led_cfg->iout_flash_max[FLED2];
413 } else {
414 first_led = max77693_fled_used(led, FLED1) ? FLED1 : FLED2;
415 last_led = max77693_fled_used(led, FLED2) ? FLED2 : FLED1;
416 max_flash_curr[FLED1] = led_cfg->iout_flash_max[FLED1];
417 max_flash_curr[FLED2] = led_cfg->iout_flash_max[FLED2];
418 }
419
420 for (i = first_led; i <= last_led; ++i) {
421 ret = max77693_set_flash_current(led, i,
422 max_flash_curr[i]);
423 if (ret < 0)
424 return ret;
425 }
426
427 v = TORCH_TMR_NO_TIMER | MAX77693_LED_TRIG_TYPE_LEVEL;
428 ret = regmap_write(rmap, MAX77693_LED_REG_ITORCHTIMER, v);
429 if (ret < 0)
430 return ret;
431
432 if (led_cfg->low_vsys > 0)
433 v = max77693_led_vsys_to_reg(led_cfg->low_vsys) |
434 MAX_FLASH1_MAX_FL_EN;
435 else
436 v = 0;
437
438 ret = regmap_write(rmap, MAX77693_LED_REG_MAX_FLASH1, v);
439 if (ret < 0)
440 return ret;
441 ret = regmap_write(rmap, MAX77693_LED_REG_MAX_FLASH2, 0);
442 if (ret < 0)
443 return ret;
444
445 if (led_cfg->boost_mode == MAX77693_LED_BOOST_FIXED)
446 v = FLASH_BOOST_FIXED;
447 else
448 v = led_cfg->boost_mode | led_cfg->boost_mode << 1;
449
450 if (max77693_fled_used(led, FLED1) && max77693_fled_used(led, FLED2))
451 v |= FLASH_BOOST_LEDNUM_2;
452
453 ret = regmap_write(rmap, MAX77693_LED_REG_VOUT_CNTL, v);
454 if (ret < 0)
455 return ret;
456
457 v = max77693_led_vout_to_reg(led_cfg->boost_vout);
458 ret = regmap_write(rmap, MAX77693_LED_REG_VOUT_FLASH1, v);
459 if (ret < 0)
460 return ret;
461
462 return max77693_set_mode_reg(led, MODE_OFF);
463}
464
465static int __max77693_led_brightness_set(struct max77693_led_device *led,
466 int fled_id, enum led_brightness value)
467{
468 int ret;
469
470 mutex_lock(&led->lock);
471
472 if (value == 0) {
473 ret = max77693_clear_mode(led, MODE_TORCH(fled_id));
474 if (ret < 0)
475 dev_dbg(&led->pdev->dev,
476 "Failed to clear torch mode (%d)\n",
477 ret);
478 goto unlock;
479 }
480
481 ret = max77693_set_torch_current(led, fled_id, value * TORCH_IOUT_STEP);
482 if (ret < 0) {
483 dev_dbg(&led->pdev->dev,
484 "Failed to set torch current (%d)\n",
485 ret);
486 goto unlock;
487 }
488
489 ret = max77693_add_mode(led, MODE_TORCH(fled_id));
490 if (ret < 0)
491 dev_dbg(&led->pdev->dev,
492 "Failed to set torch mode (%d)\n",
493 ret);
494unlock:
495 mutex_unlock(&led->lock);
496 return ret;
497}
498
499static void max77693_led_brightness_set_work(
500 struct work_struct *work)
501{
502 struct max77693_sub_led *sub_led =
503 container_of(work, struct max77693_sub_led,
504 work_brightness_set);
505 struct max77693_led_device *led = sub_led_to_led(sub_led);
506
507 __max77693_led_brightness_set(led, sub_led->fled_id,
508 sub_led->torch_brightness);
509}
510
511/* LED subsystem callbacks */
512
513static int max77693_led_brightness_set_sync(
514 struct led_classdev *led_cdev,
515 enum led_brightness value)
516{
517 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
518 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
519 struct max77693_led_device *led = sub_led_to_led(sub_led);
520
521 return __max77693_led_brightness_set(led, sub_led->fled_id, value);
522}
523
524static void max77693_led_brightness_set(
525 struct led_classdev *led_cdev,
526 enum led_brightness value)
527{
528 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
529 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
530
531 sub_led->torch_brightness = value;
532 schedule_work(&sub_led->work_brightness_set);
533}
534
535static int max77693_led_flash_brightness_set(
536 struct led_classdev_flash *fled_cdev,
537 u32 brightness)
538{
539 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
540 struct max77693_led_device *led = sub_led_to_led(sub_led);
541 int ret;
542
543 mutex_lock(&led->lock);
544 ret = max77693_set_flash_current(led, sub_led->fled_id, brightness);
545 mutex_unlock(&led->lock);
546
547 return ret;
548}
549
550static int max77693_led_flash_strobe_set(
551 struct led_classdev_flash *fled_cdev,
552 bool state)
553{
554 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
555 struct max77693_led_device *led = sub_led_to_led(sub_led);
556 int fled_id = sub_led->fled_id;
557 int ret;
558
559 mutex_lock(&led->lock);
560
561 if (!state) {
562 ret = max77693_clear_mode(led, MODE_FLASH(fled_id));
563 goto unlock;
564 }
565
566 if (sub_led->flash_timeout != led->current_flash_timeout) {
567 ret = max77693_set_timeout(led, sub_led->flash_timeout);
568 if (ret < 0)
569 goto unlock;
570 }
571
572 led->strobing_sub_led_id = fled_id;
573
574 ret = max77693_add_mode(led, MODE_FLASH(fled_id));
575 if (ret < 0)
576 goto unlock;
577
578 ret = max77693_get_flash_faults(sub_led);
579
580unlock:
581 mutex_unlock(&led->lock);
582 return ret;
583}
584
585static int max77693_led_flash_fault_get(
586 struct led_classdev_flash *fled_cdev,
587 u32 *fault)
588{
589 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
590
591 *fault = sub_led->flash_faults;
592
593 return 0;
594}
595
596static int max77693_led_flash_strobe_get(
597 struct led_classdev_flash *fled_cdev,
598 bool *state)
599{
600 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
601 struct max77693_led_device *led = sub_led_to_led(sub_led);
602 int ret;
603
604 if (!state)
605 return -EINVAL;
606
607 mutex_lock(&led->lock);
608
609 ret = max77693_get_strobe_status(led, state);
610
611 *state = !!(*state && (led->strobing_sub_led_id == sub_led->fled_id));
612
613 mutex_unlock(&led->lock);
614
615 return ret;
616}
617
618static int max77693_led_flash_timeout_set(
619 struct led_classdev_flash *fled_cdev,
620 u32 timeout)
621{
622 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
623 struct max77693_led_device *led = sub_led_to_led(sub_led);
624
625 mutex_lock(&led->lock);
626 sub_led->flash_timeout = timeout;
627 mutex_unlock(&led->lock);
628
629 return 0;
630}
631
632static int max77693_led_parse_dt(struct max77693_led_device *led,
633 struct max77693_led_config_data *cfg,
634 struct device_node **sub_nodes)
635{
636 struct device *dev = &led->pdev->dev;
637 struct max77693_sub_led *sub_leds = led->sub_leds;
638 struct device_node *node = dev->of_node, *child_node;
639 struct property *prop;
640 u32 led_sources[2];
641 int i, ret, fled_id;
642
643 of_property_read_u32(node, "maxim,boost-mode", &cfg->boost_mode);
644 of_property_read_u32(node, "maxim,boost-mvout", &cfg->boost_vout);
645 of_property_read_u32(node, "maxim,mvsys-min", &cfg->low_vsys);
646
647 for_each_available_child_of_node(node, child_node) {
648 prop = of_find_property(child_node, "led-sources", NULL);
649 if (prop) {
650 const __be32 *srcs = NULL;
651
652 for (i = 0; i < ARRAY_SIZE(led_sources); ++i) {
653 srcs = of_prop_next_u32(prop, srcs,
654 &led_sources[i]);
655 if (!srcs)
656 break;
657 }
658 } else {
659 dev_err(dev,
660 "led-sources DT property missing\n");
661 of_node_put(child_node);
662 return -EINVAL;
663 }
664
665 if (i == 2) {
666 fled_id = FLED1;
667 led->fled_mask = FLED1_IOUT | FLED2_IOUT;
668 } else if (led_sources[0] == FLED1) {
669 fled_id = FLED1;
670 led->fled_mask |= FLED1_IOUT;
671 } else if (led_sources[0] == FLED2) {
672 fled_id = FLED2;
673 led->fled_mask |= FLED2_IOUT;
674 } else {
675 dev_err(dev,
676 "Wrong led-sources DT property value.\n");
677 of_node_put(child_node);
678 return -EINVAL;
679 }
680
681 if (sub_nodes[fled_id]) {
682 dev_err(dev,
683 "Conflicting \"led-sources\" DT properties\n");
684 return -EINVAL;
685 }
686
687 sub_nodes[fled_id] = child_node;
688 sub_leds[fled_id].fled_id = fled_id;
689
690 cfg->label[fled_id] =
691 of_get_property(child_node, "label", NULL) ? :
692 child_node->name;
693
694 ret = of_property_read_u32(child_node, "led-max-microamp",
695 &cfg->iout_torch_max[fled_id]);
696 if (ret < 0) {
697 cfg->iout_torch_max[fled_id] = TORCH_IOUT_MIN;
698 dev_warn(dev, "led-max-microamp DT property missing\n");
699 }
700
701 ret = of_property_read_u32(child_node, "flash-max-microamp",
702 &cfg->iout_flash_max[fled_id]);
703 if (ret < 0) {
704 cfg->iout_flash_max[fled_id] = FLASH_IOUT_MIN;
705 dev_warn(dev,
706 "flash-max-microamp DT property missing\n");
707 }
708
709 ret = of_property_read_u32(child_node, "flash-max-timeout-us",
710 &cfg->flash_timeout_max[fled_id]);
711 if (ret < 0) {
712 cfg->flash_timeout_max[fled_id] = FLASH_TIMEOUT_MIN;
713 dev_warn(dev,
714 "flash-max-timeout-us DT property missing\n");
715 }
716
717 if (++cfg->num_leds == 2 ||
718 (max77693_fled_used(led, FLED1) &&
719 max77693_fled_used(led, FLED2))) {
720 of_node_put(child_node);
721 break;
722 }
723 }
724
725 if (cfg->num_leds == 0) {
726 dev_err(dev, "No DT child node found for connected LED(s).\n");
727 return -EINVAL;
728 }
729
730 return 0;
731}
732
733static void clamp_align(u32 *v, u32 min, u32 max, u32 step)
734{
735 *v = clamp_val(*v, min, max);
736 if (step > 1)
737 *v = (*v - min) / step * step + min;
738}
739
740static void max77693_align_iout_current(struct max77693_led_device *led,
741 u32 *iout, u32 min, u32 max, u32 step)
742{
743 int i;
744
745 if (led->iout_joint) {
746 if (iout[FLED1] > min) {
747 iout[FLED1] /= 2;
748 iout[FLED2] = iout[FLED1];
749 } else {
750 iout[FLED1] = min;
751 iout[FLED2] = 0;
752 return;
753 }
754 }
755
756 for (i = FLED1; i <= FLED2; ++i)
757 if (max77693_fled_used(led, i))
758 clamp_align(&iout[i], min, max, step);
759 else
760 iout[i] = 0;
761}
762
763static void max77693_led_validate_configuration(struct max77693_led_device *led,
764 struct max77693_led_config_data *cfg)
765{
766 u32 flash_iout_max = cfg->boost_mode ? FLASH_IOUT_MAX_2LEDS :
767 FLASH_IOUT_MAX_1LED;
768 int i;
769
770 if (cfg->num_leds == 1 &&
771 max77693_fled_used(led, FLED1) && max77693_fled_used(led, FLED2))
772 led->iout_joint = true;
773
774 cfg->boost_mode = clamp_val(cfg->boost_mode, MAX77693_LED_BOOST_NONE,
775 MAX77693_LED_BOOST_FIXED);
776
777 /* Boost must be enabled if both current outputs are used */
778 if ((cfg->boost_mode == MAX77693_LED_BOOST_NONE) && led->iout_joint)
779 cfg->boost_mode = MAX77693_LED_BOOST_FIXED;
780
781 max77693_align_iout_current(led, cfg->iout_torch_max,
782 TORCH_IOUT_MIN, TORCH_IOUT_MAX, TORCH_IOUT_STEP);
783
784 max77693_align_iout_current(led, cfg->iout_flash_max,
785 FLASH_IOUT_MIN, flash_iout_max, FLASH_IOUT_STEP);
786
787 for (i = 0; i < ARRAY_SIZE(cfg->flash_timeout_max); ++i)
788 clamp_align(&cfg->flash_timeout_max[i], FLASH_TIMEOUT_MIN,
789 FLASH_TIMEOUT_MAX, FLASH_TIMEOUT_STEP);
790
791 clamp_align(&cfg->boost_vout, FLASH_VOUT_MIN, FLASH_VOUT_MAX,
792 FLASH_VOUT_STEP);
793
794 if (cfg->low_vsys)
795 clamp_align(&cfg->low_vsys, MAX_FLASH1_VSYS_MIN,
796 MAX_FLASH1_VSYS_MAX, MAX_FLASH1_VSYS_STEP);
797}
798
799static int max77693_led_get_configuration(struct max77693_led_device *led,
800 struct max77693_led_config_data *cfg,
801 struct device_node **sub_nodes)
802{
803 int ret;
804
805 ret = max77693_led_parse_dt(led, cfg, sub_nodes);
806 if (ret < 0)
807 return ret;
808
809 max77693_led_validate_configuration(led, cfg);
810
811 memcpy(led->iout_torch_max, cfg->iout_torch_max,
812 sizeof(led->iout_torch_max));
813 memcpy(led->iout_flash_max, cfg->iout_flash_max,
814 sizeof(led->iout_flash_max));
815
816 return 0;
817}
818
819static const struct led_flash_ops flash_ops = {
820 .flash_brightness_set = max77693_led_flash_brightness_set,
821 .strobe_set = max77693_led_flash_strobe_set,
822 .strobe_get = max77693_led_flash_strobe_get,
823 .timeout_set = max77693_led_flash_timeout_set,
824 .fault_get = max77693_led_flash_fault_get,
825};
826
827static void max77693_init_flash_settings(struct max77693_sub_led *sub_led,
828 struct max77693_led_config_data *led_cfg)
829{
830 struct led_classdev_flash *fled_cdev = &sub_led->fled_cdev;
831 struct max77693_led_device *led = sub_led_to_led(sub_led);
832 int fled_id = sub_led->fled_id;
833 struct led_flash_setting *setting;
834
835 /* Init flash intensity setting */
836 setting = &fled_cdev->brightness;
837 setting->min = FLASH_IOUT_MIN;
838 setting->max = led->iout_joint ?
839 led_cfg->iout_flash_max[FLED1] +
840 led_cfg->iout_flash_max[FLED2] :
841 led_cfg->iout_flash_max[fled_id];
842 setting->step = FLASH_IOUT_STEP;
843 setting->val = setting->max;
844
845 /* Init flash timeout setting */
846 setting = &fled_cdev->timeout;
847 setting->min = FLASH_TIMEOUT_MIN;
848 setting->max = led_cfg->flash_timeout_max[fled_id];
849 setting->step = FLASH_TIMEOUT_STEP;
850 setting->val = setting->max;
851}
852
853#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
854
855static int max77693_led_external_strobe_set(
856 struct v4l2_flash *v4l2_flash,
857 bool enable)
858{
859 struct max77693_sub_led *sub_led =
860 flcdev_to_sub_led(v4l2_flash->fled_cdev);
861 struct max77693_led_device *led = sub_led_to_led(sub_led);
862 int fled_id = sub_led->fled_id;
863 int ret;
864
865 mutex_lock(&led->lock);
866
867 if (enable)
868 ret = max77693_add_mode(led, MODE_FLASH_EXTERNAL(fled_id));
869 else
870 ret = max77693_clear_mode(led, MODE_FLASH_EXTERNAL(fled_id));
871
872 mutex_unlock(&led->lock);
873
874 return ret;
875}
876
877static void max77693_init_v4l2_flash_config(struct max77693_sub_led *sub_led,
878 struct max77693_led_config_data *led_cfg,
879 struct v4l2_flash_config *v4l2_sd_cfg)
880{
881 struct max77693_led_device *led = sub_led_to_led(sub_led);
882 struct device *dev = &led->pdev->dev;
883 struct max77693_dev *iodev = dev_get_drvdata(dev->parent);
884 struct i2c_client *i2c = iodev->i2c;
885 struct led_flash_setting *s;
886
887 snprintf(v4l2_sd_cfg->dev_name, sizeof(v4l2_sd_cfg->dev_name),
888 "%s %d-%04x", sub_led->fled_cdev.led_cdev.name,
889 i2c_adapter_id(i2c->adapter), i2c->addr);
890
891 s = &v4l2_sd_cfg->torch_intensity;
892 s->min = TORCH_IOUT_MIN;
893 s->max = sub_led->fled_cdev.led_cdev.max_brightness * TORCH_IOUT_STEP;
894 s->step = TORCH_IOUT_STEP;
895 s->val = s->max;
896
897 /* Init flash faults config */
898 v4l2_sd_cfg->flash_faults = LED_FAULT_OVER_VOLTAGE |
899 LED_FAULT_SHORT_CIRCUIT |
900 LED_FAULT_OVER_CURRENT;
901
902 v4l2_sd_cfg->has_external_strobe = true;
903}
904
905static const struct v4l2_flash_ops v4l2_flash_ops = {
906 .external_strobe_set = max77693_led_external_strobe_set,
907};
908#else
909static inline void max77693_init_v4l2_flash_config(
910 struct max77693_sub_led *sub_led,
911 struct max77693_led_config_data *led_cfg,
912 struct v4l2_flash_config *v4l2_sd_cfg)
913{
914}
915static const struct v4l2_flash_ops v4l2_flash_ops;
916#endif
917
918static void max77693_init_fled_cdev(struct max77693_sub_led *sub_led,
919 struct max77693_led_config_data *led_cfg)
920{
921 struct max77693_led_device *led = sub_led_to_led(sub_led);
922 int fled_id = sub_led->fled_id;
923 struct led_classdev_flash *fled_cdev;
924 struct led_classdev *led_cdev;
925
926 /* Initialize LED Flash class device */
927 fled_cdev = &sub_led->fled_cdev;
928 fled_cdev->ops = &flash_ops;
929 led_cdev = &fled_cdev->led_cdev;
930
931 led_cdev->name = led_cfg->label[fled_id];
932
933 led_cdev->brightness_set = max77693_led_brightness_set;
934 led_cdev->brightness_set_sync = max77693_led_brightness_set_sync;
935 led_cdev->max_brightness = (led->iout_joint ?
936 led_cfg->iout_torch_max[FLED1] +
937 led_cfg->iout_torch_max[FLED2] :
938 led_cfg->iout_torch_max[fled_id]) /
939 TORCH_IOUT_STEP;
940 led_cdev->flags |= LED_DEV_CAP_FLASH;
941 INIT_WORK(&sub_led->work_brightness_set,
942 max77693_led_brightness_set_work);
943
944 max77693_init_flash_settings(sub_led, led_cfg);
945
946 /* Init flash timeout cache */
947 sub_led->flash_timeout = fled_cdev->timeout.val;
948}
949
950static int max77693_register_led(struct max77693_sub_led *sub_led,
951 struct max77693_led_config_data *led_cfg,
952 struct device_node *sub_node)
953{
954 struct max77693_led_device *led = sub_led_to_led(sub_led);
955 struct led_classdev_flash *fled_cdev = &sub_led->fled_cdev;
956 struct device *dev = &led->pdev->dev;
957 struct v4l2_flash_config v4l2_sd_cfg = {};
958 int ret;
959
960 /* Register in the LED subsystem */
961 ret = led_classdev_flash_register(dev, fled_cdev);
962 if (ret < 0)
963 return ret;
964
965 max77693_init_v4l2_flash_config(sub_led, led_cfg, &v4l2_sd_cfg);
966
967 /* Register in the V4L2 subsystem. */
968 sub_led->v4l2_flash = v4l2_flash_init(dev, sub_node, fled_cdev, NULL,
969 &v4l2_flash_ops, &v4l2_sd_cfg);
970 if (IS_ERR(sub_led->v4l2_flash)) {
971 ret = PTR_ERR(sub_led->v4l2_flash);
972 goto err_v4l2_flash_init;
973 }
974
975 return 0;
976
977err_v4l2_flash_init:
978 led_classdev_flash_unregister(fled_cdev);
979 return ret;
980}
981
982static int max77693_led_probe(struct platform_device *pdev)
983{
984 struct device *dev = &pdev->dev;
985 struct max77693_dev *iodev = dev_get_drvdata(dev->parent);
986 struct max77693_led_device *led;
987 struct max77693_sub_led *sub_leds;
988 struct device_node *sub_nodes[2] = {};
989 struct max77693_led_config_data led_cfg = {};
990 int init_fled_cdev[2], i, ret;
991
992 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
993 if (!led)
994 return -ENOMEM;
995
996 led->pdev = pdev;
997 led->regmap = iodev->regmap;
998 led->allowed_modes = MODE_FLASH_MASK;
999 sub_leds = led->sub_leds;
1000
1001 platform_set_drvdata(pdev, led);
1002 ret = max77693_led_get_configuration(led, &led_cfg, sub_nodes);
1003 if (ret < 0)
1004 return ret;
1005
1006 ret = max77693_setup(led, &led_cfg);
1007 if (ret < 0)
1008 return ret;
1009
1010 mutex_init(&led->lock);
1011
1012 init_fled_cdev[FLED1] =
1013 led->iout_joint || max77693_fled_used(led, FLED1);
1014 init_fled_cdev[FLED2] =
1015 !led->iout_joint && max77693_fled_used(led, FLED2);
1016
1017 for (i = FLED1; i <= FLED2; ++i) {
1018 if (!init_fled_cdev[i])
1019 continue;
1020
1021 /* Initialize LED Flash class device */
1022 max77693_init_fled_cdev(&sub_leds[i], &led_cfg);
1023
1024 /*
1025 * Register LED Flash class device and corresponding
1026 * V4L2 Flash device.
1027 */
1028 ret = max77693_register_led(&sub_leds[i], &led_cfg,
1029 sub_nodes[i]);
1030 if (ret < 0) {
1031 /*
1032 * At this moment FLED1 might have been already
1033 * registered and it needs to be released.
1034 */
1035 if (i == FLED2)
1036 goto err_register_led2;
1037 else
1038 goto err_register_led1;
1039 }
1040 }
1041
1042 return 0;
1043
1044err_register_led2:
1045 /* It is possible than only FLED2 was to be registered */
1046 if (!init_fled_cdev[FLED1])
1047 goto err_register_led1;
1048 v4l2_flash_release(sub_leds[FLED1].v4l2_flash);
1049 led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
1050err_register_led1:
1051 mutex_destroy(&led->lock);
1052
1053 return ret;
1054}
1055
1056static int max77693_led_remove(struct platform_device *pdev)
1057{
1058 struct max77693_led_device *led = platform_get_drvdata(pdev);
1059 struct max77693_sub_led *sub_leds = led->sub_leds;
1060
1061 if (led->iout_joint || max77693_fled_used(led, FLED1)) {
1062 v4l2_flash_release(sub_leds[FLED1].v4l2_flash);
1063 led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
1064 cancel_work_sync(&sub_leds[FLED1].work_brightness_set);
1065 }
1066
1067 if (!led->iout_joint && max77693_fled_used(led, FLED2)) {
1068 v4l2_flash_release(sub_leds[FLED2].v4l2_flash);
1069 led_classdev_flash_unregister(&sub_leds[FLED2].fled_cdev);
1070 cancel_work_sync(&sub_leds[FLED2].work_brightness_set);
1071 }
1072
1073 mutex_destroy(&led->lock);
1074
1075 return 0;
1076}
1077
1078static const struct of_device_id max77693_led_dt_match[] = {
1079 { .compatible = "maxim,max77693-led" },
1080 {},
1081};
1082
1083static struct platform_driver max77693_led_driver = {
1084 .probe = max77693_led_probe,
1085 .remove = max77693_led_remove,
1086 .driver = {
1087 .name = "max77693-led",
1088 .of_match_table = max77693_led_dt_match,
1089 },
1090};
1091
1092module_platform_driver(max77693_led_driver);
1093
1094MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
1095MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1096MODULE_DESCRIPTION("Maxim MAX77693 led flash driver");
1097MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-tlc591xx.c b/drivers/leds/leds-tlc591xx.c
new file mode 100644
index 000000000000..de16c29d7895
--- /dev/null
+++ b/drivers/leds/leds-tlc591xx.c
@@ -0,0 +1,300 @@
1/*
2 * Copyright 2014 Belkin Inc.
3 * Copyright 2015 Andrew Lunn <andrew@lunn.ch>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
8 */
9
10#include <linux/i2c.h>
11#include <linux/leds.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/of_device.h>
15#include <linux/regmap.h>
16#include <linux/slab.h>
17#include <linux/workqueue.h>
18
19#define TLC591XX_MAX_LEDS 16
20
21#define TLC591XX_REG_MODE1 0x00
22#define MODE1_RESPON_ADDR_MASK 0xF0
23#define MODE1_NORMAL_MODE (0 << 4)
24#define MODE1_SPEED_MODE (1 << 4)
25
26#define TLC591XX_REG_MODE2 0x01
27#define MODE2_DIM (0 << 5)
28#define MODE2_BLINK (1 << 5)
29#define MODE2_OCH_STOP (0 << 3)
30#define MODE2_OCH_ACK (1 << 3)
31
32#define TLC591XX_REG_PWM(x) (0x02 + (x))
33
34#define TLC591XX_REG_GRPPWM 0x12
35#define TLC591XX_REG_GRPFREQ 0x13
36
37/* LED Driver Output State, determine the source that drives LED outputs */
38#define LEDOUT_OFF 0x0 /* Output LOW */
39#define LEDOUT_ON 0x1 /* Output HI-Z */
40#define LEDOUT_DIM 0x2 /* Dimming */
41#define LEDOUT_BLINK 0x3 /* Blinking */
42#define LEDOUT_MASK 0x3
43
44#define ldev_to_led(c) container_of(c, struct tlc591xx_led, ldev)
45#define work_to_led(work) container_of(work, struct tlc591xx_led, work)
46
47struct tlc591xx_led {
48 bool active;
49 unsigned int led_no;
50 struct led_classdev ldev;
51 struct work_struct work;
52 struct tlc591xx_priv *priv;
53};
54
55struct tlc591xx_priv {
56 struct tlc591xx_led leds[TLC591XX_MAX_LEDS];
57 struct regmap *regmap;
58 unsigned int reg_ledout_offset;
59};
60
61struct tlc591xx {
62 unsigned int max_leds;
63 unsigned int reg_ledout_offset;
64};
65
66static const struct tlc591xx tlc59116 = {
67 .max_leds = 16,
68 .reg_ledout_offset = 0x14,
69};
70
71static const struct tlc591xx tlc59108 = {
72 .max_leds = 8,
73 .reg_ledout_offset = 0x0c,
74};
75
76static int
77tlc591xx_set_mode(struct regmap *regmap, u8 mode)
78{
79 int err;
80 u8 val;
81
82 err = regmap_write(regmap, TLC591XX_REG_MODE1, MODE1_NORMAL_MODE);
83 if (err)
84 return err;
85
86 val = MODE2_OCH_STOP | mode;
87
88 return regmap_write(regmap, TLC591XX_REG_MODE2, val);
89}
90
91static int
92tlc591xx_set_ledout(struct tlc591xx_priv *priv, struct tlc591xx_led *led,
93 u8 val)
94{
95 unsigned int i = (led->led_no % 4) * 2;
96 unsigned int mask = LEDOUT_MASK << i;
97 unsigned int addr = priv->reg_ledout_offset + (led->led_no >> 2);
98
99 val = val << i;
100
101 return regmap_update_bits(priv->regmap, addr, mask, val);
102}
103
104static int
105tlc591xx_set_pwm(struct tlc591xx_priv *priv, struct tlc591xx_led *led,
106 u8 brightness)
107{
108 u8 pwm = TLC591XX_REG_PWM(led->led_no);
109
110 return regmap_write(priv->regmap, pwm, brightness);
111}
112
113static void
114tlc591xx_led_work(struct work_struct *work)
115{
116 struct tlc591xx_led *led = work_to_led(work);
117 struct tlc591xx_priv *priv = led->priv;
118 enum led_brightness brightness = led->ldev.brightness;
119 int err;
120
121 switch (brightness) {
122 case 0:
123 err = tlc591xx_set_ledout(priv, led, LEDOUT_OFF);
124 break;
125 case LED_FULL:
126 err = tlc591xx_set_ledout(priv, led, LEDOUT_ON);
127 break;
128 default:
129 err = tlc591xx_set_ledout(priv, led, LEDOUT_DIM);
130 if (!err)
131 err = tlc591xx_set_pwm(priv, led, brightness);
132 }
133
134 if (err)
135 dev_err(led->ldev.dev, "Failed setting brightness\n");
136}
137
138static void
139tlc591xx_brightness_set(struct led_classdev *led_cdev,
140 enum led_brightness brightness)
141{
142 struct tlc591xx_led *led = ldev_to_led(led_cdev);
143
144 led->ldev.brightness = brightness;
145 schedule_work(&led->work);
146}
147
148static void
149tlc591xx_destroy_devices(struct tlc591xx_priv *priv, unsigned int j)
150{
151 int i = j;
152
153 while (--i >= 0) {
154 if (priv->leds[i].active) {
155 led_classdev_unregister(&priv->leds[i].ldev);
156 cancel_work_sync(&priv->leds[i].work);
157 }
158 }
159}
160
161static int
162tlc591xx_configure(struct device *dev,
163 struct tlc591xx_priv *priv,
164 const struct tlc591xx *tlc591xx)
165{
166 unsigned int i;
167 int err = 0;
168
169 tlc591xx_set_mode(priv->regmap, MODE2_DIM);
170 for (i = 0; i < TLC591XX_MAX_LEDS; i++) {
171 struct tlc591xx_led *led = &priv->leds[i];
172
173 if (!led->active)
174 continue;
175
176 led->priv = priv;
177 led->led_no = i;
178 led->ldev.brightness_set = tlc591xx_brightness_set;
179 led->ldev.max_brightness = LED_FULL;
180 INIT_WORK(&led->work, tlc591xx_led_work);
181 err = led_classdev_register(dev, &led->ldev);
182 if (err < 0) {
183 dev_err(dev, "couldn't register LED %s\n",
184 led->ldev.name);
185 goto exit;
186 }
187 }
188
189 return 0;
190
191exit:
192 tlc591xx_destroy_devices(priv, i);
193 return err;
194}
195
196static const struct regmap_config tlc591xx_regmap = {
197 .reg_bits = 8,
198 .val_bits = 8,
199 .max_register = 0x1e,
200};
201
202static const struct of_device_id of_tlc591xx_leds_match[] = {
203 { .compatible = "ti,tlc59116",
204 .data = &tlc59116 },
205 { .compatible = "ti,tlc59108",
206 .data = &tlc59108 },
207 {},
208};
209MODULE_DEVICE_TABLE(of, of_tlc591xx_leds_match);
210
211static int
212tlc591xx_probe(struct i2c_client *client,
213 const struct i2c_device_id *id)
214{
215 struct device_node *np = client->dev.of_node, *child;
216 struct device *dev = &client->dev;
217 const struct of_device_id *match;
218 const struct tlc591xx *tlc591xx;
219 struct tlc591xx_priv *priv;
220 int err, count, reg;
221
222 match = of_match_device(of_tlc591xx_leds_match, dev);
223 if (!match)
224 return -ENODEV;
225
226 tlc591xx = match->data;
227 if (!np)
228 return -ENODEV;
229
230 count = of_get_child_count(np);
231 if (!count || count > tlc591xx->max_leds)
232 return -EINVAL;
233
234 if (!i2c_check_functionality(client->adapter,
235 I2C_FUNC_SMBUS_BYTE_DATA))
236 return -EIO;
237
238 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
239 if (!priv)
240 return -ENOMEM;
241
242 priv->regmap = devm_regmap_init_i2c(client, &tlc591xx_regmap);
243 if (IS_ERR(priv->regmap)) {
244 err = PTR_ERR(priv->regmap);
245 dev_err(dev, "Failed to allocate register map: %d\n", err);
246 return err;
247 }
248 priv->reg_ledout_offset = tlc591xx->reg_ledout_offset;
249
250 i2c_set_clientdata(client, priv);
251
252 for_each_child_of_node(np, child) {
253 err = of_property_read_u32(child, "reg", &reg);
254 if (err)
255 return err;
256 if (reg < 0 || reg >= tlc591xx->max_leds)
257 return -EINVAL;
258 if (priv->leds[reg].active)
259 return -EINVAL;
260 priv->leds[reg].active = true;
261 priv->leds[reg].ldev.name =
262 of_get_property(child, "label", NULL) ? : child->name;
263 priv->leds[reg].ldev.default_trigger =
264 of_get_property(child, "linux,default-trigger", NULL);
265 }
266 return tlc591xx_configure(dev, priv, tlc591xx);
267}
268
269static int
270tlc591xx_remove(struct i2c_client *client)
271{
272 struct tlc591xx_priv *priv = i2c_get_clientdata(client);
273
274 tlc591xx_destroy_devices(priv, TLC591XX_MAX_LEDS);
275
276 return 0;
277}
278
279static const struct i2c_device_id tlc591xx_id[] = {
280 { "tlc59116" },
281 { "tlc59108" },
282 {},
283};
284MODULE_DEVICE_TABLE(i2c, tlc591xx_id);
285
286static struct i2c_driver tlc591xx_driver = {
287 .driver = {
288 .name = "tlc591xx",
289 .of_match_table = of_match_ptr(of_tlc591xx_leds_match),
290 },
291 .probe = tlc591xx_probe,
292 .remove = tlc591xx_remove,
293 .id_table = tlc591xx_id,
294};
295
296module_i2c_driver(tlc591xx_driver);
297
298MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
299MODULE_LICENSE("GPL");
300MODULE_DESCRIPTION("TLC591XX LED driver");
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index 79efe57c7405..bc89d7ace2c4 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -13,7 +13,6 @@
13#ifndef __LEDS_H_INCLUDED 13#ifndef __LEDS_H_INCLUDED
14#define __LEDS_H_INCLUDED 14#define __LEDS_H_INCLUDED
15 15
16#include <linux/device.h>
17#include <linux/rwsem.h> 16#include <linux/rwsem.h>
18#include <linux/leds.h> 17#include <linux/leds.h>
19 18
@@ -50,27 +49,4 @@ void led_stop_software_blink(struct led_classdev *led_cdev);
50extern struct rw_semaphore leds_list_lock; 49extern struct rw_semaphore leds_list_lock;
51extern struct list_head leds_list; 50extern struct list_head leds_list;
52 51
53#ifdef CONFIG_LEDS_TRIGGERS
54void led_trigger_set_default(struct led_classdev *led_cdev);
55void led_trigger_set(struct led_classdev *led_cdev,
56 struct led_trigger *trigger);
57void led_trigger_remove(struct led_classdev *led_cdev);
58
59static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
60{
61 return led_cdev->trigger_data;
62}
63
64#else
65#define led_trigger_set_default(x) do {} while (0)
66#define led_trigger_set(x, y) do {} while (0)
67#define led_trigger_remove(x) do {} while (0)
68#define led_get_trigger_data(x) (NULL)
69#endif
70
71ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
72 const char *buf, size_t count);
73ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
74 char *buf);
75
76#endif /* __LEDS_H_INCLUDED */ 52#endif /* __LEDS_H_INCLUDED */
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index f7a01a72eb9e..b4b022933e29 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -44,6 +44,17 @@ config V4L2_MEM2MEM_DEV
44 tristate 44 tristate
45 depends on VIDEOBUF2_CORE 45 depends on VIDEOBUF2_CORE
46 46
47# Used by LED subsystem flash drivers
48config V4L2_FLASH_LED_CLASS
49 tristate "V4L2 flash API for LED flash class devices"
50 depends on VIDEO_V4L2_SUBDEV_API
51 depends on LEDS_CLASS_FLASH
52 ---help---
53 Say Y here to enable V4L2 flash API support for LED flash
54 class drivers.
55
56 When in doubt, say N.
57
47# Used by drivers that need Videobuf modules 58# Used by drivers that need Videobuf modules
48config VIDEOBUF_GEN 59config VIDEOBUF_GEN
49 tristate 60 tristate
diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
index 63d29f27538c..dc3de00d68b5 100644
--- a/drivers/media/v4l2-core/Makefile
+++ b/drivers/media/v4l2-core/Makefile
@@ -22,6 +22,8 @@ obj-$(CONFIG_VIDEO_TUNER) += tuner.o
22 22
23obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o 23obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
24 24
25obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o
26
25obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o 27obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
26obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o 28obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
27obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o 29obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 85a6a34128a8..5bada202b2d3 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -22,10 +22,10 @@
22#include <media/v4l2-device.h> 22#include <media/v4l2-device.h>
23#include <media/v4l2-subdev.h> 23#include <media/v4l2-subdev.h>
24 24
25static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd) 25static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
26{ 26{
27#if IS_ENABLED(CONFIG_I2C) 27#if IS_ENABLED(CONFIG_I2C)
28 struct i2c_client *client = i2c_verify_client(dev); 28 struct i2c_client *client = i2c_verify_client(sd->dev);
29 return client && 29 return client &&
30 asd->match.i2c.adapter_id == client->adapter->nr && 30 asd->match.i2c.adapter_id == client->adapter->nr &&
31 asd->match.i2c.address == client->addr; 31 asd->match.i2c.address == client->addr;
@@ -34,14 +34,24 @@ static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd)
34#endif 34#endif
35} 35}
36 36
37static bool match_devname(struct device *dev, struct v4l2_async_subdev *asd) 37static bool match_devname(struct v4l2_subdev *sd,
38 struct v4l2_async_subdev *asd)
38{ 39{
39 return !strcmp(asd->match.device_name.name, dev_name(dev)); 40 return !strcmp(asd->match.device_name.name, dev_name(sd->dev));
40} 41}
41 42
42static bool match_of(struct device *dev, struct v4l2_async_subdev *asd) 43static bool match_of(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
43{ 44{
44 return dev->of_node == asd->match.of.node; 45 return sd->of_node == asd->match.of.node;
46}
47
48static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
49{
50 if (!asd->match.custom.match)
51 /* Match always */
52 return true;
53
54 return asd->match.custom.match(sd->dev, asd);
45} 55}
46 56
47static LIST_HEAD(subdev_list); 57static LIST_HEAD(subdev_list);
@@ -51,17 +61,14 @@ static DEFINE_MUTEX(list_lock);
51static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, 61static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier,
52 struct v4l2_subdev *sd) 62 struct v4l2_subdev *sd)
53{ 63{
64 bool (*match)(struct v4l2_subdev *, struct v4l2_async_subdev *);
54 struct v4l2_async_subdev *asd; 65 struct v4l2_async_subdev *asd;
55 bool (*match)(struct device *, struct v4l2_async_subdev *);
56 66
57 list_for_each_entry(asd, &notifier->waiting, list) { 67 list_for_each_entry(asd, &notifier->waiting, list) {
58 /* bus_type has been verified valid before */ 68 /* bus_type has been verified valid before */
59 switch (asd->match_type) { 69 switch (asd->match_type) {
60 case V4L2_ASYNC_MATCH_CUSTOM: 70 case V4L2_ASYNC_MATCH_CUSTOM:
61 match = asd->match.custom.match; 71 match = match_custom;
62 if (!match)
63 /* Match always */
64 return asd;
65 break; 72 break;
66 case V4L2_ASYNC_MATCH_DEVNAME: 73 case V4L2_ASYNC_MATCH_DEVNAME:
67 match = match_devname; 74 match = match_devname;
@@ -79,7 +86,7 @@ static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *
79 } 86 }
80 87
81 /* match cannot be NULL here */ 88 /* match cannot be NULL here */
82 if (match(sd->dev, asd)) 89 if (match(sd, asd))
83 return asd; 90 return asd;
84 } 91 }
85 92
@@ -266,6 +273,14 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
266{ 273{
267 struct v4l2_async_notifier *notifier; 274 struct v4l2_async_notifier *notifier;
268 275
276 /*
277 * No reference taken. The reference is held by the device
278 * (struct v4l2_subdev.dev), and async sub-device does not
279 * exist independently of the device at any point of time.
280 */
281 if (!sd->of_node && sd->dev)
282 sd->of_node = sd->dev->of_node;
283
269 mutex_lock(&list_lock); 284 mutex_lock(&list_lock);
270 285
271 INIT_LIST_HEAD(&sd->async_list); 286 INIT_LIST_HEAD(&sd->async_list);
diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c
new file mode 100644
index 000000000000..5bdfb8d5263a
--- /dev/null
+++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c
@@ -0,0 +1,710 @@
1/*
2 * V4L2 flash LED sub-device registration helpers.
3 *
4 * Copyright (C) 2015 Samsung Electronics Co., Ltd
5 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/led-class-flash.h>
13#include <linux/module.h>
14#include <linux/mutex.h>
15#include <linux/of.h>
16#include <linux/slab.h>
17#include <linux/types.h>
18#include <media/v4l2-flash-led-class.h>
19
20#define has_flash_op(v4l2_flash, op) \
21 (v4l2_flash && v4l2_flash->ops->op)
22
23#define call_flash_op(v4l2_flash, op, arg) \
24 (has_flash_op(v4l2_flash, op) ? \
25 v4l2_flash->ops->op(v4l2_flash, arg) : \
26 -EINVAL)
27
28enum ctrl_init_data_id {
29 LED_MODE,
30 TORCH_INTENSITY,
31 FLASH_INTENSITY,
32 INDICATOR_INTENSITY,
33 FLASH_TIMEOUT,
34 STROBE_SOURCE,
35 /*
36 * Only above values are applicable to
37 * the 'ctrls' array in the struct v4l2_flash.
38 */
39 FLASH_STROBE,
40 STROBE_STOP,
41 STROBE_STATUS,
42 FLASH_FAULT,
43 NUM_FLASH_CTRLS,
44};
45
46static enum led_brightness __intensity_to_led_brightness(
47 struct v4l2_ctrl *ctrl, s32 intensity)
48{
49 intensity -= ctrl->minimum;
50 intensity /= (u32) ctrl->step;
51
52 /*
53 * Indicator LEDs, unlike torch LEDs, are turned on/off basing on
54 * the state of V4L2_CID_FLASH_INDICATOR_INTENSITY control only.
55 * Therefore it must be possible to set it to 0 level which in
56 * the LED subsystem reflects LED_OFF state.
57 */
58 if (ctrl->minimum)
59 ++intensity;
60
61 return intensity;
62}
63
64static s32 __led_brightness_to_intensity(struct v4l2_ctrl *ctrl,
65 enum led_brightness brightness)
66{
67 /*
68 * Indicator LEDs, unlike torch LEDs, are turned on/off basing on
69 * the state of V4L2_CID_FLASH_INDICATOR_INTENSITY control only.
70 * Do not decrement brightness read from the LED subsystem for
71 * indicator LED as it may equal 0. For torch LEDs this function
72 * is called only when V4L2_FLASH_LED_MODE_TORCH is set and the
73 * brightness read is guaranteed to be greater than 0. In the mode
74 * V4L2_FLASH_LED_MODE_NONE the cached torch intensity value is used.
75 */
76 if (ctrl->id != V4L2_CID_FLASH_INDICATOR_INTENSITY)
77 --brightness;
78
79 return (brightness * ctrl->step) + ctrl->minimum;
80}
81
82static void v4l2_flash_set_led_brightness(struct v4l2_flash *v4l2_flash,
83 struct v4l2_ctrl *ctrl)
84{
85 struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
86 enum led_brightness brightness;
87
88 if (has_flash_op(v4l2_flash, intensity_to_led_brightness))
89 brightness = call_flash_op(v4l2_flash,
90 intensity_to_led_brightness,
91 ctrl->val);
92 else
93 brightness = __intensity_to_led_brightness(ctrl, ctrl->val);
94 /*
95 * In case a LED Flash class driver provides ops for custom
96 * brightness <-> intensity conversion, it also must have defined
97 * related v4l2 control step == 1. In such a case a backward conversion
98 * from led brightness to v4l2 intensity is required to find out the
99 * the aligned intensity value.
100 */
101 if (has_flash_op(v4l2_flash, led_brightness_to_intensity))
102 ctrl->val = call_flash_op(v4l2_flash,
103 led_brightness_to_intensity,
104 brightness);
105
106 if (ctrl == ctrls[TORCH_INTENSITY]) {
107 if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
108 return;
109
110 led_set_brightness(&v4l2_flash->fled_cdev->led_cdev,
111 brightness);
112 } else {
113 led_set_brightness(&v4l2_flash->iled_cdev->led_cdev,
114 brightness);
115 }
116}
117
118static int v4l2_flash_update_led_brightness(struct v4l2_flash *v4l2_flash,
119 struct v4l2_ctrl *ctrl)
120{
121 struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
122 struct led_classdev *led_cdev;
123 int ret;
124
125 if (ctrl == ctrls[TORCH_INTENSITY]) {
126 /*
127 * Update torch brightness only if in TORCH_MODE. In other modes
128 * torch led is turned off, which would spuriously inform the
129 * user space that V4L2_CID_FLASH_TORCH_INTENSITY control value
130 * has changed to 0.
131 */
132 if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
133 return 0;
134 led_cdev = &v4l2_flash->fled_cdev->led_cdev;
135 } else {
136 led_cdev = &v4l2_flash->iled_cdev->led_cdev;
137 }
138
139 ret = led_update_brightness(led_cdev);
140 if (ret < 0)
141 return ret;
142
143 if (has_flash_op(v4l2_flash, led_brightness_to_intensity))
144 ctrl->val = call_flash_op(v4l2_flash,
145 led_brightness_to_intensity,
146 led_cdev->brightness);
147 else
148 ctrl->val = __led_brightness_to_intensity(ctrl,
149 led_cdev->brightness);
150
151 return 0;
152}
153
154static int v4l2_flash_g_volatile_ctrl(struct v4l2_ctrl *c)
155{
156 struct v4l2_flash *v4l2_flash = v4l2_ctrl_to_v4l2_flash(c);
157 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
158 bool is_strobing;
159 int ret;
160
161 switch (c->id) {
162 case V4L2_CID_FLASH_TORCH_INTENSITY:
163 case V4L2_CID_FLASH_INDICATOR_INTENSITY:
164 return v4l2_flash_update_led_brightness(v4l2_flash, c);
165 case V4L2_CID_FLASH_INTENSITY:
166 ret = led_update_flash_brightness(fled_cdev);
167 if (ret < 0)
168 return ret;
169 /*
170 * No conversion is needed as LED Flash class also uses
171 * microamperes for flash intensity units.
172 */
173 c->val = fled_cdev->brightness.val;
174 return 0;
175 case V4L2_CID_FLASH_STROBE_STATUS:
176 ret = led_get_flash_strobe(fled_cdev, &is_strobing);
177 if (ret < 0)
178 return ret;
179 c->val = is_strobing;
180 return 0;
181 case V4L2_CID_FLASH_FAULT:
182 /* LED faults map directly to V4L2 flash faults */
183 return led_get_flash_fault(fled_cdev, &c->val);
184 default:
185 return -EINVAL;
186 }
187}
188
189static bool __software_strobe_mode_inactive(struct v4l2_ctrl **ctrls)
190{
191 return ((ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_FLASH) ||
192 (ctrls[STROBE_SOURCE] && (ctrls[STROBE_SOURCE]->val !=
193 V4L2_FLASH_STROBE_SOURCE_SOFTWARE)));
194}
195
196static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
197{
198 struct v4l2_flash *v4l2_flash = v4l2_ctrl_to_v4l2_flash(c);
199 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
200 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
201 struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
202 bool external_strobe;
203 int ret = 0;
204
205 switch (c->id) {
206 case V4L2_CID_FLASH_LED_MODE:
207 switch (c->val) {
208 case V4L2_FLASH_LED_MODE_NONE:
209 led_set_brightness(led_cdev, LED_OFF);
210 return led_set_flash_strobe(fled_cdev, false);
211 case V4L2_FLASH_LED_MODE_FLASH:
212 /* Turn the torch LED off */
213 led_set_brightness(led_cdev, LED_OFF);
214 if (ctrls[STROBE_SOURCE]) {
215 external_strobe = (ctrls[STROBE_SOURCE]->val ==
216 V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
217
218 ret = call_flash_op(v4l2_flash,
219 external_strobe_set,
220 external_strobe);
221 }
222 return ret;
223 case V4L2_FLASH_LED_MODE_TORCH:
224 if (ctrls[STROBE_SOURCE]) {
225 ret = call_flash_op(v4l2_flash,
226 external_strobe_set,
227 false);
228 if (ret < 0)
229 return ret;
230 }
231 /* Stop flash strobing */
232 ret = led_set_flash_strobe(fled_cdev, false);
233 if (ret < 0)
234 return ret;
235
236 v4l2_flash_set_led_brightness(v4l2_flash,
237 ctrls[TORCH_INTENSITY]);
238 return 0;
239 }
240 break;
241 case V4L2_CID_FLASH_STROBE_SOURCE:
242 external_strobe = (c->val == V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
243 /*
244 * For some hardware arrangements setting strobe source may
245 * affect torch mode. Therefore, if not in the flash mode,
246 * cache only this setting. It will be applied upon switching
247 * to flash mode.
248 */
249 if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_FLASH)
250 return 0;
251
252 return call_flash_op(v4l2_flash, external_strobe_set,
253 external_strobe);
254 case V4L2_CID_FLASH_STROBE:
255 if (__software_strobe_mode_inactive(ctrls))
256 return -EBUSY;
257 return led_set_flash_strobe(fled_cdev, true);
258 case V4L2_CID_FLASH_STROBE_STOP:
259 if (__software_strobe_mode_inactive(ctrls))
260 return -EBUSY;
261 return led_set_flash_strobe(fled_cdev, false);
262 case V4L2_CID_FLASH_TIMEOUT:
263 /*
264 * No conversion is needed as LED Flash class also uses
265 * microseconds for flash timeout units.
266 */
267 return led_set_flash_timeout(fled_cdev, c->val);
268 case V4L2_CID_FLASH_INTENSITY:
269 /*
270 * No conversion is needed as LED Flash class also uses
271 * microamperes for flash intensity units.
272 */
273 return led_set_flash_brightness(fled_cdev, c->val);
274 case V4L2_CID_FLASH_TORCH_INTENSITY:
275 case V4L2_CID_FLASH_INDICATOR_INTENSITY:
276 v4l2_flash_set_led_brightness(v4l2_flash, c);
277 return 0;
278 }
279
280 return -EINVAL;
281}
282
283static const struct v4l2_ctrl_ops v4l2_flash_ctrl_ops = {
284 .g_volatile_ctrl = v4l2_flash_g_volatile_ctrl,
285 .s_ctrl = v4l2_flash_s_ctrl,
286};
287
288static void __lfs_to_v4l2_ctrl_config(struct led_flash_setting *s,
289 struct v4l2_ctrl_config *c)
290{
291 c->min = s->min;
292 c->max = s->max;
293 c->step = s->step;
294 c->def = s->val;
295}
296
297static void __fill_ctrl_init_data(struct v4l2_flash *v4l2_flash,
298 struct v4l2_flash_config *flash_cfg,
299 struct v4l2_flash_ctrl_data *ctrl_init_data)
300{
301 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
302 const struct led_flash_ops *fled_cdev_ops = fled_cdev->ops;
303 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
304 struct v4l2_ctrl_config *ctrl_cfg;
305 u32 mask;
306
307 /* Init FLASH_FAULT ctrl data */
308 if (flash_cfg->flash_faults) {
309 ctrl_init_data[FLASH_FAULT].cid = V4L2_CID_FLASH_FAULT;
310 ctrl_cfg = &ctrl_init_data[FLASH_FAULT].config;
311 ctrl_cfg->id = V4L2_CID_FLASH_FAULT;
312 ctrl_cfg->max = flash_cfg->flash_faults;
313 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
314 V4L2_CTRL_FLAG_READ_ONLY;
315 }
316
317 /* Init FLASH_LED_MODE ctrl data */
318 mask = 1 << V4L2_FLASH_LED_MODE_NONE |
319 1 << V4L2_FLASH_LED_MODE_TORCH;
320 if (led_cdev->flags & LED_DEV_CAP_FLASH)
321 mask |= 1 << V4L2_FLASH_LED_MODE_FLASH;
322
323 ctrl_init_data[LED_MODE].cid = V4L2_CID_FLASH_LED_MODE;
324 ctrl_cfg = &ctrl_init_data[LED_MODE].config;
325 ctrl_cfg->id = V4L2_CID_FLASH_LED_MODE;
326 ctrl_cfg->max = V4L2_FLASH_LED_MODE_TORCH;
327 ctrl_cfg->menu_skip_mask = ~mask;
328 ctrl_cfg->def = V4L2_FLASH_LED_MODE_NONE;
329 ctrl_cfg->flags = 0;
330
331 /* Init TORCH_INTENSITY ctrl data */
332 ctrl_init_data[TORCH_INTENSITY].cid = V4L2_CID_FLASH_TORCH_INTENSITY;
333 ctrl_cfg = &ctrl_init_data[TORCH_INTENSITY].config;
334 __lfs_to_v4l2_ctrl_config(&flash_cfg->torch_intensity, ctrl_cfg);
335 ctrl_cfg->id = V4L2_CID_FLASH_TORCH_INTENSITY;
336 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
337 V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
338
339 /* Init INDICATOR_INTENSITY ctrl data */
340 if (v4l2_flash->iled_cdev) {
341 ctrl_init_data[INDICATOR_INTENSITY].cid =
342 V4L2_CID_FLASH_INDICATOR_INTENSITY;
343 ctrl_cfg = &ctrl_init_data[INDICATOR_INTENSITY].config;
344 __lfs_to_v4l2_ctrl_config(&flash_cfg->indicator_intensity,
345 ctrl_cfg);
346 ctrl_cfg->id = V4L2_CID_FLASH_INDICATOR_INTENSITY;
347 ctrl_cfg->min = 0;
348 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
349 V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
350 }
351
352 if (!(led_cdev->flags & LED_DEV_CAP_FLASH))
353 return;
354
355 /* Init FLASH_STROBE ctrl data */
356 ctrl_init_data[FLASH_STROBE].cid = V4L2_CID_FLASH_STROBE;
357 ctrl_cfg = &ctrl_init_data[FLASH_STROBE].config;
358 ctrl_cfg->id = V4L2_CID_FLASH_STROBE;
359
360 /* Init STROBE_STOP ctrl data */
361 ctrl_init_data[STROBE_STOP].cid = V4L2_CID_FLASH_STROBE_STOP;
362 ctrl_cfg = &ctrl_init_data[STROBE_STOP].config;
363 ctrl_cfg->id = V4L2_CID_FLASH_STROBE_STOP;
364
365 /* Init FLASH_STROBE_SOURCE ctrl data */
366 if (flash_cfg->has_external_strobe) {
367 mask = (1 << V4L2_FLASH_STROBE_SOURCE_SOFTWARE) |
368 (1 << V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
369 ctrl_init_data[STROBE_SOURCE].cid =
370 V4L2_CID_FLASH_STROBE_SOURCE;
371 ctrl_cfg = &ctrl_init_data[STROBE_SOURCE].config;
372 ctrl_cfg->id = V4L2_CID_FLASH_STROBE_SOURCE;
373 ctrl_cfg->max = V4L2_FLASH_STROBE_SOURCE_EXTERNAL;
374 ctrl_cfg->menu_skip_mask = ~mask;
375 ctrl_cfg->def = V4L2_FLASH_STROBE_SOURCE_SOFTWARE;
376 }
377
378 /* Init STROBE_STATUS ctrl data */
379 if (fled_cdev_ops->strobe_get) {
380 ctrl_init_data[STROBE_STATUS].cid =
381 V4L2_CID_FLASH_STROBE_STATUS;
382 ctrl_cfg = &ctrl_init_data[STROBE_STATUS].config;
383 ctrl_cfg->id = V4L2_CID_FLASH_STROBE_STATUS;
384 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
385 V4L2_CTRL_FLAG_READ_ONLY;
386 }
387
388 /* Init FLASH_TIMEOUT ctrl data */
389 if (fled_cdev_ops->timeout_set) {
390 ctrl_init_data[FLASH_TIMEOUT].cid = V4L2_CID_FLASH_TIMEOUT;
391 ctrl_cfg = &ctrl_init_data[FLASH_TIMEOUT].config;
392 __lfs_to_v4l2_ctrl_config(&fled_cdev->timeout, ctrl_cfg);
393 ctrl_cfg->id = V4L2_CID_FLASH_TIMEOUT;
394 }
395
396 /* Init FLASH_INTENSITY ctrl data */
397 if (fled_cdev_ops->flash_brightness_set) {
398 ctrl_init_data[FLASH_INTENSITY].cid = V4L2_CID_FLASH_INTENSITY;
399 ctrl_cfg = &ctrl_init_data[FLASH_INTENSITY].config;
400 __lfs_to_v4l2_ctrl_config(&fled_cdev->brightness, ctrl_cfg);
401 ctrl_cfg->id = V4L2_CID_FLASH_INTENSITY;
402 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
403 V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
404 }
405}
406
407static int v4l2_flash_init_controls(struct v4l2_flash *v4l2_flash,
408 struct v4l2_flash_config *flash_cfg)
409
410{
411 struct v4l2_flash_ctrl_data *ctrl_init_data;
412 struct v4l2_ctrl *ctrl;
413 struct v4l2_ctrl_config *ctrl_cfg;
414 int i, ret, num_ctrls = 0;
415
416 v4l2_flash->ctrls = devm_kzalloc(v4l2_flash->sd.dev,
417 sizeof(*v4l2_flash->ctrls) *
418 (STROBE_SOURCE + 1), GFP_KERNEL);
419 if (!v4l2_flash->ctrls)
420 return -ENOMEM;
421
422 /* allocate memory dynamically so as not to exceed stack frame size */
423 ctrl_init_data = kcalloc(NUM_FLASH_CTRLS, sizeof(*ctrl_init_data),
424 GFP_KERNEL);
425 if (!ctrl_init_data)
426 return -ENOMEM;
427
428 __fill_ctrl_init_data(v4l2_flash, flash_cfg, ctrl_init_data);
429
430 for (i = 0; i < NUM_FLASH_CTRLS; ++i)
431 if (ctrl_init_data[i].cid)
432 ++num_ctrls;
433
434 v4l2_ctrl_handler_init(&v4l2_flash->hdl, num_ctrls);
435
436 for (i = 0; i < NUM_FLASH_CTRLS; ++i) {
437 ctrl_cfg = &ctrl_init_data[i].config;
438 if (!ctrl_init_data[i].cid)
439 continue;
440
441 if (ctrl_cfg->id == V4L2_CID_FLASH_LED_MODE ||
442 ctrl_cfg->id == V4L2_CID_FLASH_STROBE_SOURCE)
443 ctrl = v4l2_ctrl_new_std_menu(&v4l2_flash->hdl,
444 &v4l2_flash_ctrl_ops,
445 ctrl_cfg->id,
446 ctrl_cfg->max,
447 ctrl_cfg->menu_skip_mask,
448 ctrl_cfg->def);
449 else
450 ctrl = v4l2_ctrl_new_std(&v4l2_flash->hdl,
451 &v4l2_flash_ctrl_ops,
452 ctrl_cfg->id,
453 ctrl_cfg->min,
454 ctrl_cfg->max,
455 ctrl_cfg->step,
456 ctrl_cfg->def);
457
458 if (ctrl)
459 ctrl->flags |= ctrl_cfg->flags;
460
461 if (i <= STROBE_SOURCE)
462 v4l2_flash->ctrls[i] = ctrl;
463 }
464
465 kfree(ctrl_init_data);
466
467 if (v4l2_flash->hdl.error) {
468 ret = v4l2_flash->hdl.error;
469 goto error_free_handler;
470 }
471
472 v4l2_ctrl_handler_setup(&v4l2_flash->hdl);
473
474 v4l2_flash->sd.ctrl_handler = &v4l2_flash->hdl;
475
476 return 0;
477
478error_free_handler:
479 v4l2_ctrl_handler_free(&v4l2_flash->hdl);
480 return ret;
481}
482
483static int __sync_device_with_v4l2_controls(struct v4l2_flash *v4l2_flash)
484{
485 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
486 struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
487 int ret = 0;
488
489 v4l2_flash_set_led_brightness(v4l2_flash, ctrls[TORCH_INTENSITY]);
490
491 if (ctrls[INDICATOR_INTENSITY])
492 v4l2_flash_set_led_brightness(v4l2_flash,
493 ctrls[INDICATOR_INTENSITY]);
494
495 if (ctrls[FLASH_TIMEOUT]) {
496 ret = led_set_flash_timeout(fled_cdev,
497 ctrls[FLASH_TIMEOUT]->val);
498 if (ret < 0)
499 return ret;
500 }
501
502 if (ctrls[FLASH_INTENSITY]) {
503 ret = led_set_flash_brightness(fled_cdev,
504 ctrls[FLASH_INTENSITY]->val);
505 if (ret < 0)
506 return ret;
507 }
508
509 /*
510 * For some hardware arrangements setting strobe source may affect
511 * torch mode. Synchronize strobe source setting only if not in torch
512 * mode. For torch mode case it will get synchronized upon switching
513 * to flash mode.
514 */
515 if (ctrls[STROBE_SOURCE] &&
516 ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
517 ret = call_flash_op(v4l2_flash, external_strobe_set,
518 ctrls[STROBE_SOURCE]->val);
519
520 return ret;
521}
522
523/*
524 * V4L2 subdev internal operations
525 */
526
527static int v4l2_flash_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
528{
529 struct v4l2_flash *v4l2_flash = v4l2_subdev_to_v4l2_flash(sd);
530 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
531 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
532 struct led_classdev_flash *iled_cdev = v4l2_flash->iled_cdev;
533 struct led_classdev *led_cdev_ind = NULL;
534 int ret = 0;
535
536 if (!v4l2_fh_is_singular(&fh->vfh))
537 return 0;
538
539 mutex_lock(&led_cdev->led_access);
540
541 led_sysfs_disable(led_cdev);
542 led_trigger_remove(led_cdev);
543
544 mutex_unlock(&led_cdev->led_access);
545
546 if (iled_cdev) {
547 led_cdev_ind = &iled_cdev->led_cdev;
548
549 mutex_lock(&led_cdev_ind->led_access);
550
551 led_sysfs_disable(led_cdev_ind);
552 led_trigger_remove(led_cdev_ind);
553
554 mutex_unlock(&led_cdev_ind->led_access);
555 }
556
557 ret = __sync_device_with_v4l2_controls(v4l2_flash);
558 if (ret < 0)
559 goto out_sync_device;
560
561 return 0;
562out_sync_device:
563 mutex_lock(&led_cdev->led_access);
564 led_sysfs_enable(led_cdev);
565 mutex_unlock(&led_cdev->led_access);
566
567 if (led_cdev_ind) {
568 mutex_lock(&led_cdev_ind->led_access);
569 led_sysfs_enable(led_cdev_ind);
570 mutex_unlock(&led_cdev_ind->led_access);
571 }
572
573 return ret;
574}
575
576static int v4l2_flash_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
577{
578 struct v4l2_flash *v4l2_flash = v4l2_subdev_to_v4l2_flash(sd);
579 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
580 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
581 struct led_classdev_flash *iled_cdev = v4l2_flash->iled_cdev;
582 int ret = 0;
583
584 if (!v4l2_fh_is_singular(&fh->vfh))
585 return 0;
586
587 mutex_lock(&led_cdev->led_access);
588
589 if (v4l2_flash->ctrls[STROBE_SOURCE])
590 ret = v4l2_ctrl_s_ctrl(v4l2_flash->ctrls[STROBE_SOURCE],
591 V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
592 led_sysfs_enable(led_cdev);
593
594 mutex_unlock(&led_cdev->led_access);
595
596 if (iled_cdev) {
597 struct led_classdev *led_cdev_ind = &iled_cdev->led_cdev;
598
599 mutex_lock(&led_cdev_ind->led_access);
600 led_sysfs_enable(led_cdev_ind);
601 mutex_unlock(&led_cdev_ind->led_access);
602 }
603
604 return ret;
605}
606
607static const struct v4l2_subdev_internal_ops v4l2_flash_subdev_internal_ops = {
608 .open = v4l2_flash_open,
609 .close = v4l2_flash_close,
610};
611
612static const struct v4l2_subdev_core_ops v4l2_flash_core_ops = {
613 .queryctrl = v4l2_subdev_queryctrl,
614 .querymenu = v4l2_subdev_querymenu,
615};
616
617static const struct v4l2_subdev_ops v4l2_flash_subdev_ops = {
618 .core = &v4l2_flash_core_ops,
619};
620
621struct v4l2_flash *v4l2_flash_init(
622 struct device *dev, struct device_node *of_node,
623 struct led_classdev_flash *fled_cdev,
624 struct led_classdev_flash *iled_cdev,
625 const struct v4l2_flash_ops *ops,
626 struct v4l2_flash_config *config)
627{
628 struct v4l2_flash *v4l2_flash;
629 struct led_classdev *led_cdev;
630 struct v4l2_subdev *sd;
631 int ret;
632
633 if (!fled_cdev || !ops || !config)
634 return ERR_PTR(-EINVAL);
635
636 led_cdev = &fled_cdev->led_cdev;
637
638 v4l2_flash = devm_kzalloc(led_cdev->dev, sizeof(*v4l2_flash),
639 GFP_KERNEL);
640 if (!v4l2_flash)
641 return ERR_PTR(-ENOMEM);
642
643 sd = &v4l2_flash->sd;
644 v4l2_flash->fled_cdev = fled_cdev;
645 v4l2_flash->iled_cdev = iled_cdev;
646 v4l2_flash->ops = ops;
647 sd->dev = dev;
648 sd->of_node = of_node;
649 v4l2_subdev_init(sd, &v4l2_flash_subdev_ops);
650 sd->internal_ops = &v4l2_flash_subdev_internal_ops;
651 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
652 strlcpy(sd->name, config->dev_name, sizeof(sd->name));
653
654 ret = media_entity_init(&sd->entity, 0, NULL, 0);
655 if (ret < 0)
656 return ERR_PTR(ret);
657
658 sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
659
660 ret = v4l2_flash_init_controls(v4l2_flash, config);
661 if (ret < 0)
662 goto err_init_controls;
663
664 if (sd->of_node)
665 of_node_get(sd->of_node);
666 else
667 of_node_get(led_cdev->dev->of_node);
668
669 ret = v4l2_async_register_subdev(sd);
670 if (ret < 0)
671 goto err_async_register_sd;
672
673 return v4l2_flash;
674
675err_async_register_sd:
676 of_node_put(led_cdev->dev->of_node);
677 v4l2_ctrl_handler_free(sd->ctrl_handler);
678err_init_controls:
679 media_entity_cleanup(&sd->entity);
680
681 return ERR_PTR(ret);
682}
683EXPORT_SYMBOL_GPL(v4l2_flash_init);
684
685void v4l2_flash_release(struct v4l2_flash *v4l2_flash)
686{
687 struct v4l2_subdev *sd;
688 struct led_classdev *led_cdev;
689
690 if (IS_ERR_OR_NULL(v4l2_flash))
691 return;
692
693 sd = &v4l2_flash->sd;
694 led_cdev = &v4l2_flash->fled_cdev->led_cdev;
695
696 v4l2_async_unregister_subdev(sd);
697
698 if (sd->of_node)
699 of_node_put(sd->of_node);
700 else
701 of_node_put(led_cdev->dev->of_node);
702
703 v4l2_ctrl_handler_free(sd->ctrl_handler);
704 media_entity_cleanup(&sd->entity);
705}
706EXPORT_SYMBOL_GPL(v4l2_flash_release);
707
708MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
709MODULE_DESCRIPTION("V4L2 Flash sub-device helpers");
710MODULE_LICENSE("GPL v2");
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index fd098169fe87..adac255aee86 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -407,6 +407,21 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
407 return -EINVAL; 407 return -EINVAL;
408} 408}
409 409
410/* Child properties interface */
411struct fwnode_handle;
412
413static inline struct gpio_desc *fwnode_get_named_gpiod(
414 struct fwnode_handle *fwnode, const char *propname)
415{
416 return ERR_PTR(-ENOSYS);
417}
418
419static inline struct gpio_desc *devm_get_gpiod_from_child(
420 struct device *dev, const char *con_id, struct fwnode_handle *child)
421{
422 return ERR_PTR(-ENOSYS);
423}
424
410#endif /* CONFIG_GPIOLIB */ 425#endif /* CONFIG_GPIOLIB */
411 426
412/* 427/*
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 9a2b000094cf..b122eeafb5dc 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -12,6 +12,7 @@
12#ifndef __LINUX_LEDS_H_INCLUDED 12#ifndef __LINUX_LEDS_H_INCLUDED
13#define __LINUX_LEDS_H_INCLUDED 13#define __LINUX_LEDS_H_INCLUDED
14 14
15#include <linux/device.h>
15#include <linux/list.h> 16#include <linux/list.h>
16#include <linux/mutex.h> 17#include <linux/mutex.h>
17#include <linux/rwsem.h> 18#include <linux/rwsem.h>
@@ -222,6 +223,11 @@ struct led_trigger {
222 struct list_head next_trig; 223 struct list_head next_trig;
223}; 224};
224 225
226ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
227 const char *buf, size_t count);
228ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
229 char *buf);
230
225/* Registration functions for complex triggers */ 231/* Registration functions for complex triggers */
226extern int led_trigger_register(struct led_trigger *trigger); 232extern int led_trigger_register(struct led_trigger *trigger);
227extern void led_trigger_unregister(struct led_trigger *trigger); 233extern void led_trigger_unregister(struct led_trigger *trigger);
@@ -238,6 +244,16 @@ extern void led_trigger_blink_oneshot(struct led_trigger *trigger,
238 unsigned long *delay_on, 244 unsigned long *delay_on,
239 unsigned long *delay_off, 245 unsigned long *delay_off,
240 int invert); 246 int invert);
247extern void led_trigger_set_default(struct led_classdev *led_cdev);
248extern void led_trigger_set(struct led_classdev *led_cdev,
249 struct led_trigger *trigger);
250extern void led_trigger_remove(struct led_classdev *led_cdev);
251
252static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
253{
254 return led_cdev->trigger_data;
255}
256
241/** 257/**
242 * led_trigger_rename_static - rename a trigger 258 * led_trigger_rename_static - rename a trigger
243 * @name: the new trigger name 259 * @name: the new trigger name
@@ -267,6 +283,15 @@ static inline void led_trigger_register_simple(const char *name,
267static inline void led_trigger_unregister_simple(struct led_trigger *trigger) {} 283static inline void led_trigger_unregister_simple(struct led_trigger *trigger) {}
268static inline void led_trigger_event(struct led_trigger *trigger, 284static inline void led_trigger_event(struct led_trigger *trigger,
269 enum led_brightness event) {} 285 enum led_brightness event) {}
286static inline void led_trigger_set_default(struct led_classdev *led_cdev) {}
287static inline void led_trigger_set(struct led_classdev *led_cdev,
288 struct led_trigger *trigger) {}
289static inline void led_trigger_remove(struct led_classdev *led_cdev) {}
290static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
291{
292 return NULL;
293}
294
270#endif /* CONFIG_LEDS_TRIGGERS */ 295#endif /* CONFIG_LEDS_TRIGGERS */
271 296
272/* Trigger specific functions */ 297/* Trigger specific functions */
diff --git a/include/media/v4l2-flash-led-class.h b/include/media/v4l2-flash-led-class.h
new file mode 100644
index 000000000000..098236c083b8
--- /dev/null
+++ b/include/media/v4l2-flash-led-class.h
@@ -0,0 +1,148 @@
1/*
2 * V4L2 flash LED sub-device registration helpers.
3 *
4 * Copyright (C) 2015 Samsung Electronics Co., Ltd
5 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _V4L2_FLASH_H
13#define _V4L2_FLASH_H
14
15#include <media/v4l2-ctrls.h>
16#include <media/v4l2-subdev.h>
17
18struct led_classdev_flash;
19struct led_classdev;
20struct v4l2_flash;
21enum led_brightness;
22
23/*
24 * struct v4l2_flash_ctrl_data - flash control initialization data, filled
25 * basing on the features declared by the LED flash
26 * class driver in the v4l2_flash_config
27 * @config: initialization data for a control
28 * @cid: contains v4l2 flash control id if the config
29 * field was initialized, 0 otherwise
30 */
31struct v4l2_flash_ctrl_data {
32 struct v4l2_ctrl_config config;
33 u32 cid;
34};
35
36struct v4l2_flash_ops {
37 /* setup strobing the flash by hardware pin state assertion */
38 int (*external_strobe_set)(struct v4l2_flash *v4l2_flash,
39 bool enable);
40 /* convert intensity to brightness in a device specific manner */
41 enum led_brightness (*intensity_to_led_brightness)
42 (struct v4l2_flash *v4l2_flash, s32 intensity);
43 /* convert brightness to intensity in a device specific manner */
44 s32 (*led_brightness_to_intensity)
45 (struct v4l2_flash *v4l2_flash, enum led_brightness);
46};
47
48/**
49 * struct v4l2_flash_config - V4L2 Flash sub-device initialization data
50 * @dev_name: the name of the media entity,
51 unique in the system
52 * @torch_intensity: constraints for the LED in torch mode
53 * @indicator_intensity: constraints for the indicator LED
54 * @flash_faults: bitmask of flash faults that the LED flash class
55 device can report; corresponding LED_FAULT* bit
56 definitions are available in the header file
57 <linux/led-class-flash.h>
58 * @has_external_strobe: external strobe capability
59 */
60struct v4l2_flash_config {
61 char dev_name[32];
62 struct led_flash_setting torch_intensity;
63 struct led_flash_setting indicator_intensity;
64 u32 flash_faults;
65 unsigned int has_external_strobe:1;
66};
67
68/**
69 * struct v4l2_flash - Flash sub-device context
70 * @fled_cdev: LED flash class device controlled by this sub-device
71 * @iled_cdev: LED class device representing indicator LED associated
72 * with the LED flash class device
73 * @ops: V4L2 specific flash ops
74 * @sd: V4L2 sub-device
75 * @hdl: flash controls handler
76 * @ctrls: array of pointers to controls, whose values define
77 * the sub-device state
78 */
79struct v4l2_flash {
80 struct led_classdev_flash *fled_cdev;
81 struct led_classdev_flash *iled_cdev;
82 const struct v4l2_flash_ops *ops;
83
84 struct v4l2_subdev sd;
85 struct v4l2_ctrl_handler hdl;
86 struct v4l2_ctrl **ctrls;
87};
88
89static inline struct v4l2_flash *v4l2_subdev_to_v4l2_flash(
90 struct v4l2_subdev *sd)
91{
92 return container_of(sd, struct v4l2_flash, sd);
93}
94
95static inline struct v4l2_flash *v4l2_ctrl_to_v4l2_flash(struct v4l2_ctrl *c)
96{
97 return container_of(c->handler, struct v4l2_flash, hdl);
98}
99
100#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
101/**
102 * v4l2_flash_init - initialize V4L2 flash led sub-device
103 * @dev: flash device, e.g. an I2C device
104 * @of_node: of_node of the LED, may be NULL if the same as device's
105 * @fled_cdev: LED flash class device to wrap
106 * @iled_cdev: LED flash class device representing indicator LED associated
107 * with fled_cdev, may be NULL
108 * @flash_ops: V4L2 Flash device ops
109 * @config: initialization data for V4L2 Flash sub-device
110 *
111 * Create V4L2 Flash sub-device wrapping given LED subsystem device.
112 *
113 * Returns: A valid pointer, or, when an error occurs, the return
114 * value is encoded using ERR_PTR(). Use IS_ERR() to check and
115 * PTR_ERR() to obtain the numeric return value.
116 */
117struct v4l2_flash *v4l2_flash_init(
118 struct device *dev, struct device_node *of_node,
119 struct led_classdev_flash *fled_cdev,
120 struct led_classdev_flash *iled_cdev,
121 const struct v4l2_flash_ops *ops,
122 struct v4l2_flash_config *config);
123
124/**
125 * v4l2_flash_release - release V4L2 Flash sub-device
126 * @flash: the V4L2 Flash sub-device to release
127 *
128 * Release V4L2 Flash sub-device.
129 */
130void v4l2_flash_release(struct v4l2_flash *v4l2_flash);
131
132#else
133static inline struct v4l2_flash *v4l2_flash_init(
134 struct device *dev, struct device_node *of_node,
135 struct led_classdev_flash *fled_cdev,
136 struct led_classdev_flash *iled_cdev,
137 const struct v4l2_flash_ops *ops,
138 struct v4l2_flash_config *config)
139{
140 return NULL;
141}
142
143static inline void v4l2_flash_release(struct v4l2_flash *v4l2_flash)
144{
145}
146#endif /* CONFIG_V4L2_FLASH_LED_CLASS */
147
148#endif /* _V4L2_FLASH_H */
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index dc20102ff600..4e18318eb425 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -605,6 +605,8 @@ struct v4l2_subdev {
605 struct video_device *devnode; 605 struct video_device *devnode;
606 /* pointer to the physical device, if any */ 606 /* pointer to the physical device, if any */
607 struct device *dev; 607 struct device *dev;
608 /* The device_node of the subdev, usually the same as dev->of_node. */
609 struct device_node *of_node;
608 /* Links this subdev to a global subdev_list or @notifier->done list. */ 610 /* Links this subdev to a global subdev_list or @notifier->done list. */
609 struct list_head async_list; 611 struct list_head async_list;
610 /* Pointer to respective struct v4l2_async_subdev. */ 612 /* Pointer to respective struct v4l2_async_subdev. */