aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/Kconfig7
-rw-r--r--drivers/media/video/Makefile1
-rw-r--r--drivers/media/video/as3645a.c904
-rw-r--r--include/media/as3645a.h71
4 files changed, 983 insertions, 0 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 4e8a0c4bc000..0e4d241fc6e6 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -533,6 +533,13 @@ config VIDEO_ADP1653
533 This is a driver for the ADP1653 flash controller. It is used for 533 This is a driver for the ADP1653 flash controller. It is used for
534 example in Nokia N900. 534 example in Nokia N900.
535 535
536config VIDEO_AS3645A
537 tristate "AS3645A flash driver support"
538 depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
539 ---help---
540 This is a driver for the AS3645A and LM3555 flash controllers. It has
541 build in control for flash, torch and indicator LEDs.
542
536comment "Video improvement chips" 543comment "Video improvement chips"
537 544
538config VIDEO_UPD64031A 545config VIDEO_UPD64031A
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index ddeaa6c8ad9a..86aabd64383e 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
74obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ 74obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
75obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o 75obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o
76obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o 76obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o
77obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o
77 78
78obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o 79obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o
79obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o 80obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
diff --git a/drivers/media/video/as3645a.c b/drivers/media/video/as3645a.c
new file mode 100644
index 000000000000..ec859a580651
--- /dev/null
+++ b/drivers/media/video/as3645a.c
@@ -0,0 +1,904 @@
1/*
2 * drivers/media/video/as3645a.c - AS3645A and LM3555 flash controllers driver
3 *
4 * Copyright (C) 2008-2011 Nokia Corporation
5 * Copyright (c) 2011, Intel Corporation.
6 *
7 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.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 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 * TODO:
24 * - Check hardware FSTROBE control when sensor driver add support for this
25 *
26 */
27
28#include <linux/delay.h>
29#include <linux/i2c.h>
30#include <linux/module.h>
31#include <linux/mutex.h>
32
33#include <media/as3645a.h>
34#include <media/v4l2-ctrls.h>
35#include <media/v4l2-device.h>
36
37#define AS_TIMER_MS_TO_CODE(t) (((t) - 100) / 50)
38#define AS_TIMER_CODE_TO_MS(c) (50 * (c) + 100)
39
40/* Register definitions */
41
42/* Read-only Design info register: Reset state: xxxx 0001 */
43#define AS_DESIGN_INFO_REG 0x00
44#define AS_DESIGN_INFO_FACTORY(x) (((x) >> 4))
45#define AS_DESIGN_INFO_MODEL(x) ((x) & 0x0f)
46
47/* Read-only Version control register: Reset state: 0000 0000
48 * for first engineering samples
49 */
50#define AS_VERSION_CONTROL_REG 0x01
51#define AS_VERSION_CONTROL_RFU(x) (((x) >> 4))
52#define AS_VERSION_CONTROL_VERSION(x) ((x) & 0x0f)
53
54/* Read / Write (Indicator and timer register): Reset state: 0000 1111 */
55#define AS_INDICATOR_AND_TIMER_REG 0x02
56#define AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT 0
57#define AS_INDICATOR_AND_TIMER_VREF_SHIFT 4
58#define AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT 6
59
60/* Read / Write (Current set register): Reset state: 0110 1001 */
61#define AS_CURRENT_SET_REG 0x03
62#define AS_CURRENT_ASSIST_LIGHT_SHIFT 0
63#define AS_CURRENT_LED_DET_ON (1 << 3)
64#define AS_CURRENT_FLASH_CURRENT_SHIFT 4
65
66/* Read / Write (Control register): Reset state: 1011 0100 */
67#define AS_CONTROL_REG 0x04
68#define AS_CONTROL_MODE_SETTING_SHIFT 0
69#define AS_CONTROL_STROBE_ON (1 << 2)
70#define AS_CONTROL_OUT_ON (1 << 3)
71#define AS_CONTROL_EXT_TORCH_ON (1 << 4)
72#define AS_CONTROL_STROBE_TYPE_EDGE (0 << 5)
73#define AS_CONTROL_STROBE_TYPE_LEVEL (1 << 5)
74#define AS_CONTROL_COIL_PEAK_SHIFT 6
75
76/* Read only (D3 is read / write) (Fault and info): Reset state: 0000 x000 */
77#define AS_FAULT_INFO_REG 0x05
78#define AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT (1 << 1)
79#define AS_FAULT_INFO_INDICATOR_LED (1 << 2)
80#define AS_FAULT_INFO_LED_AMOUNT (1 << 3)
81#define AS_FAULT_INFO_TIMEOUT (1 << 4)
82#define AS_FAULT_INFO_OVER_TEMPERATURE (1 << 5)
83#define AS_FAULT_INFO_SHORT_CIRCUIT (1 << 6)
84#define AS_FAULT_INFO_OVER_VOLTAGE (1 << 7)
85
86/* Boost register */
87#define AS_BOOST_REG 0x0d
88#define AS_BOOST_CURRENT_DISABLE (0 << 0)
89#define AS_BOOST_CURRENT_ENABLE (1 << 0)
90
91/* Password register is used to unlock boost register writing */
92#define AS_PASSWORD_REG 0x0f
93#define AS_PASSWORD_UNLOCK_VALUE 0x55
94
95enum as_mode {
96 AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT,
97 AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT,
98 AS_MODE_ASSIST = 2 << AS_CONTROL_MODE_SETTING_SHIFT,
99 AS_MODE_FLASH = 3 << AS_CONTROL_MODE_SETTING_SHIFT,
100};
101
102/*
103 * struct as3645a
104 *
105 * @subdev: V4L2 subdev
106 * @pdata: Flash platform data
107 * @power_lock: Protects power_count
108 * @power_count: Power reference count
109 * @led_mode: V4L2 flash LED mode
110 * @timeout: Flash timeout in microseconds
111 * @flash_current: Flash current (0=200mA ... 15=500mA). Maximum
112 * values are 400mA for two LEDs and 500mA for one LED.
113 * @assist_current: Torch/Assist light current (0=20mA, 1=40mA ... 7=160mA)
114 * @indicator_current: Indicator LED current (0=0mA, 1=2.5mA ... 4=10mA)
115 * @strobe_source: Flash strobe source (software or external)
116 */
117struct as3645a {
118 struct v4l2_subdev subdev;
119 const struct as3645a_platform_data *pdata;
120
121 struct mutex power_lock;
122 int power_count;
123
124 /* Controls */
125 struct v4l2_ctrl_handler ctrls;
126
127 enum v4l2_flash_led_mode led_mode;
128 unsigned int timeout;
129 u8 flash_current;
130 u8 assist_current;
131 u8 indicator_current;
132 enum v4l2_flash_strobe_source strobe_source;
133};
134
135#define to_as3645a(sd) container_of(sd, struct as3645a, subdev)
136
137/* Return negative errno else zero on success */
138static int as3645a_write(struct as3645a *flash, u8 addr, u8 val)
139{
140 struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
141 int rval;
142
143 rval = i2c_smbus_write_byte_data(client, addr, val);
144
145 dev_dbg(&client->dev, "Write Addr:%02X Val:%02X %s\n", addr, val,
146 rval < 0 ? "fail" : "ok");
147
148 return rval;
149}
150
151/* Return negative errno else a data byte received from the device. */
152static int as3645a_read(struct as3645a *flash, u8 addr)
153{
154 struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
155 int rval;
156
157 rval = i2c_smbus_read_byte_data(client, addr);
158
159 dev_dbg(&client->dev, "Read Addr:%02X Val:%02X %s\n", addr, rval,
160 rval < 0 ? "fail" : "ok");
161
162 return rval;
163}
164
165/* -----------------------------------------------------------------------------
166 * Hardware configuration and trigger
167 */
168
169/*
170 * as3645a_set_config - Set flash configuration registers
171 * @flash: The flash
172 *
173 * Configure the hardware with flash, assist and indicator currents, as well as
174 * flash timeout.
175 *
176 * Return 0 on success, or a negative error code if an I2C communication error
177 * occurred.
178 */
179static int as3645a_set_config(struct as3645a *flash)
180{
181 int ret;
182 u8 val;
183
184 val = (flash->flash_current << AS_CURRENT_FLASH_CURRENT_SHIFT)
185 | (flash->assist_current << AS_CURRENT_ASSIST_LIGHT_SHIFT)
186 | AS_CURRENT_LED_DET_ON;
187
188 ret = as3645a_write(flash, AS_CURRENT_SET_REG, val);
189 if (ret < 0)
190 return ret;
191
192 val = AS_TIMER_MS_TO_CODE(flash->timeout / 1000)
193 << AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT;
194
195 val |= (flash->pdata->vref << AS_INDICATOR_AND_TIMER_VREF_SHIFT)
196 | ((flash->indicator_current ? flash->indicator_current - 1 : 0)
197 << AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT);
198
199 return as3645a_write(flash, AS_INDICATOR_AND_TIMER_REG, val);
200}
201
202/*
203 * as3645a_set_control - Set flash control register
204 * @flash: The flash
205 * @mode: Desired output mode
206 * @on: Desired output state
207 *
208 * Configure the hardware with output mode and state.
209 *
210 * Return 0 on success, or a negative error code if an I2C communication error
211 * occurred.
212 */
213static int
214as3645a_set_control(struct as3645a *flash, enum as_mode mode, bool on)
215{
216 u8 reg;
217
218 /* Configure output parameters and operation mode. */
219 reg = (flash->pdata->peak << AS_CONTROL_COIL_PEAK_SHIFT)
220 | (on ? AS_CONTROL_OUT_ON : 0)
221 | mode;
222
223 if (flash->led_mode == V4L2_FLASH_LED_MODE_FLASH &&
224 flash->strobe_source == V4L2_FLASH_STROBE_SOURCE_EXTERNAL) {
225 reg |= AS_CONTROL_STROBE_TYPE_LEVEL
226 | AS_CONTROL_STROBE_ON;
227 }
228
229 return as3645a_write(flash, AS_CONTROL_REG, reg);
230}
231
232/*
233 * as3645a_set_output - Configure output and operation mode
234 * @flash: Flash controller
235 * @strobe: Strobe the flash (only valid in flash mode)
236 *
237 * Turn the LEDs output on/off and set the operation mode based on the current
238 * parameters.
239 *
240 * The AS3645A can't control the indicator LED independently of the flash/torch
241 * LED. If the flash controller is in V4L2_FLASH_LED_MODE_NONE mode, set the
242 * chip to indicator mode. Otherwise set it to assist light (torch) or flash
243 * mode.
244 *
245 * In indicator and assist modes, turn the output on/off based on the indicator
246 * and torch currents. In software strobe flash mode, turn the output on/off
247 * based on the strobe parameter.
248 */
249static int as3645a_set_output(struct as3645a *flash, bool strobe)
250{
251 enum as_mode mode;
252 bool on;
253
254 switch (flash->led_mode) {
255 case V4L2_FLASH_LED_MODE_NONE:
256 on = flash->indicator_current != 0;
257 mode = AS_MODE_INDICATOR;
258 break;
259 case V4L2_FLASH_LED_MODE_TORCH:
260 on = true;
261 mode = AS_MODE_ASSIST;
262 break;
263 case V4L2_FLASH_LED_MODE_FLASH:
264 on = strobe;
265 mode = AS_MODE_FLASH;
266 break;
267 default:
268 BUG();
269 }
270
271 /* Configure output parameters and operation mode. */
272 return as3645a_set_control(flash, mode, on);
273}
274
275/* -----------------------------------------------------------------------------
276 * V4L2 controls
277 */
278
279static int as3645a_is_active(struct as3645a *flash)
280{
281 int ret;
282
283 ret = as3645a_read(flash, AS_CONTROL_REG);
284 return ret < 0 ? ret : !!(ret & AS_CONTROL_OUT_ON);
285}
286
287static int as3645a_read_fault(struct as3645a *flash)
288{
289 struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
290 int rval;
291
292 /* NOTE: reading register clear fault status */
293 rval = as3645a_read(flash, AS_FAULT_INFO_REG);
294 if (rval < 0)
295 return rval;
296
297 if (rval & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
298 dev_dbg(&client->dev, "Inductor Peak limit fault\n");
299
300 if (rval & AS_FAULT_INFO_INDICATOR_LED)
301 dev_dbg(&client->dev, "Indicator LED fault: "
302 "Short circuit or open loop\n");
303
304 dev_dbg(&client->dev, "%u connected LEDs\n",
305 rval & AS_FAULT_INFO_LED_AMOUNT ? 2 : 1);
306
307 if (rval & AS_FAULT_INFO_TIMEOUT)
308 dev_dbg(&client->dev, "Timeout fault\n");
309
310 if (rval & AS_FAULT_INFO_OVER_TEMPERATURE)
311 dev_dbg(&client->dev, "Over temperature fault\n");
312
313 if (rval & AS_FAULT_INFO_SHORT_CIRCUIT)
314 dev_dbg(&client->dev, "Short circuit fault\n");
315
316 if (rval & AS_FAULT_INFO_OVER_VOLTAGE)
317 dev_dbg(&client->dev, "Over voltage fault: "
318 "Indicates missing capacitor or open connection\n");
319
320 return rval;
321}
322
323static int as3645a_get_ctrl(struct v4l2_ctrl *ctrl)
324{
325 struct as3645a *flash =
326 container_of(ctrl->handler, struct as3645a, ctrls);
327 struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
328 int value;
329
330 switch (ctrl->id) {
331 case V4L2_CID_FLASH_FAULT:
332 value = as3645a_read_fault(flash);
333 if (value < 0)
334 return value;
335
336 ctrl->cur.val = 0;
337 if (value & AS_FAULT_INFO_SHORT_CIRCUIT)
338 ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
339 if (value & AS_FAULT_INFO_OVER_TEMPERATURE)
340 ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
341 if (value & AS_FAULT_INFO_TIMEOUT)
342 ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
343 if (value & AS_FAULT_INFO_OVER_VOLTAGE)
344 ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
345 if (value & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
346 ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_CURRENT;
347 if (value & AS_FAULT_INFO_INDICATOR_LED)
348 ctrl->cur.val |= V4L2_FLASH_FAULT_INDICATOR;
349 break;
350
351 case V4L2_CID_FLASH_STROBE_STATUS:
352 if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) {
353 ctrl->cur.val = 0;
354 break;
355 }
356
357 value = as3645a_is_active(flash);
358 if (value < 0)
359 return value;
360
361 ctrl->cur.val = value;
362 break;
363 }
364
365 dev_dbg(&client->dev, "G_CTRL %08x:%d\n", ctrl->id, ctrl->cur.val);
366
367 return 0;
368}
369
370static int as3645a_set_ctrl(struct v4l2_ctrl *ctrl)
371{
372 struct as3645a *flash =
373 container_of(ctrl->handler, struct as3645a, ctrls);
374 struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
375 int ret;
376
377 dev_dbg(&client->dev, "S_CTRL %08x:%d\n", ctrl->id, ctrl->val);
378
379 /* If a control that doesn't apply to the current mode is modified,
380 * we store the value and return immediately. The setting will be
381 * applied when the LED mode is changed. Otherwise we apply the setting
382 * immediately.
383 */
384
385 switch (ctrl->id) {
386 case V4L2_CID_FLASH_LED_MODE:
387 if (flash->indicator_current)
388 return -EBUSY;
389
390 ret = as3645a_set_config(flash);
391 if (ret < 0)
392 return ret;
393
394 flash->led_mode = ctrl->val;
395 return as3645a_set_output(flash, false);
396
397 case V4L2_CID_FLASH_STROBE_SOURCE:
398 flash->strobe_source = ctrl->val;
399
400 /* Applies to flash mode only. */
401 if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
402 break;
403
404 return as3645a_set_output(flash, false);
405
406 case V4L2_CID_FLASH_STROBE:
407 if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
408 return -EBUSY;
409
410 return as3645a_set_output(flash, true);
411
412 case V4L2_CID_FLASH_STROBE_STOP:
413 if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
414 return -EBUSY;
415
416 return as3645a_set_output(flash, false);
417
418 case V4L2_CID_FLASH_TIMEOUT:
419 flash->timeout = ctrl->val;
420
421 /* Applies to flash mode only. */
422 if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
423 break;
424
425 return as3645a_set_config(flash);
426
427 case V4L2_CID_FLASH_INTENSITY:
428 flash->flash_current = (ctrl->val - AS3645A_FLASH_INTENSITY_MIN)
429 / AS3645A_FLASH_INTENSITY_STEP;
430
431 /* Applies to flash mode only. */
432 if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
433 break;
434
435 return as3645a_set_config(flash);
436
437 case V4L2_CID_FLASH_TORCH_INTENSITY:
438 flash->assist_current =
439 (ctrl->val - AS3645A_TORCH_INTENSITY_MIN)
440 / AS3645A_TORCH_INTENSITY_STEP;
441
442 /* Applies to torch mode only. */
443 if (flash->led_mode != V4L2_FLASH_LED_MODE_TORCH)
444 break;
445
446 return as3645a_set_config(flash);
447
448 case V4L2_CID_FLASH_INDICATOR_INTENSITY:
449 if (flash->led_mode != V4L2_FLASH_LED_MODE_NONE)
450 return -EBUSY;
451
452 flash->indicator_current =
453 (ctrl->val - AS3645A_INDICATOR_INTENSITY_MIN)
454 / AS3645A_INDICATOR_INTENSITY_STEP;
455
456 ret = as3645a_set_config(flash);
457 if (ret < 0)
458 return ret;
459
460 if ((ctrl->val == 0) == (ctrl->cur.val == 0))
461 break;
462
463 return as3645a_set_output(flash, false);
464 }
465
466 return 0;
467}
468
469static const struct v4l2_ctrl_ops as3645a_ctrl_ops = {
470 .g_volatile_ctrl = as3645a_get_ctrl,
471 .s_ctrl = as3645a_set_ctrl,
472};
473
474/* -----------------------------------------------------------------------------
475 * V4L2 subdev core operations
476 */
477
478/* Put device into know state. */
479static int as3645a_setup(struct as3645a *flash)
480{
481 struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
482 int ret;
483
484 /* clear errors */
485 ret = as3645a_read(flash, AS_FAULT_INFO_REG);
486 if (ret < 0)
487 return ret;
488
489 dev_dbg(&client->dev, "Fault info: %02x\n", ret);
490
491 ret = as3645a_set_config(flash);
492 if (ret < 0)
493 return ret;
494
495 ret = as3645a_set_output(flash, false);
496 if (ret < 0)
497 return ret;
498
499 /* read status */
500 ret = as3645a_read_fault(flash);
501 if (ret < 0)
502 return ret;
503
504 dev_dbg(&client->dev, "AS_INDICATOR_AND_TIMER_REG: %02x\n",
505 as3645a_read(flash, AS_INDICATOR_AND_TIMER_REG));
506 dev_dbg(&client->dev, "AS_CURRENT_SET_REG: %02x\n",
507 as3645a_read(flash, AS_CURRENT_SET_REG));
508 dev_dbg(&client->dev, "AS_CONTROL_REG: %02x\n",
509 as3645a_read(flash, AS_CONTROL_REG));
510
511 return ret & ~AS_FAULT_INFO_LED_AMOUNT ? -EIO : 0;
512}
513
514static int __as3645a_set_power(struct as3645a *flash, int on)
515{
516 int ret;
517
518 if (!on)
519 as3645a_set_control(flash, AS_MODE_EXT_TORCH, false);
520
521 if (flash->pdata->set_power) {
522 ret = flash->pdata->set_power(&flash->subdev, on);
523 if (ret < 0)
524 return ret;
525 }
526
527 if (!on)
528 return 0;
529
530 ret = as3645a_setup(flash);
531 if (ret < 0) {
532 if (flash->pdata->set_power)
533 flash->pdata->set_power(&flash->subdev, 0);
534 }
535
536 return ret;
537}
538
539static int as3645a_set_power(struct v4l2_subdev *sd, int on)
540{
541 struct as3645a *flash = to_as3645a(sd);
542 int ret = 0;
543
544 mutex_lock(&flash->power_lock);
545
546 if (flash->power_count == !on) {
547 ret = __as3645a_set_power(flash, !!on);
548 if (ret < 0)
549 goto done;
550 }
551
552 flash->power_count += on ? 1 : -1;
553 WARN_ON(flash->power_count < 0);
554
555done:
556 mutex_unlock(&flash->power_lock);
557 return ret;
558}
559
560static int as3645a_registered(struct v4l2_subdev *sd)
561{
562 struct as3645a *flash = to_as3645a(sd);
563 struct i2c_client *client = v4l2_get_subdevdata(sd);
564 int rval, man, model, rfu, version;
565 const char *vendor;
566
567 /* Power up the flash driver and read manufacturer ID, model ID, RFU
568 * and version.
569 */
570 rval = as3645a_set_power(&flash->subdev, 1);
571 if (rval < 0)
572 return rval;
573
574 rval = as3645a_read(flash, AS_DESIGN_INFO_REG);
575 if (rval < 0)
576 goto power_off;
577
578 man = AS_DESIGN_INFO_FACTORY(rval);
579 model = AS_DESIGN_INFO_MODEL(rval);
580
581 rval = as3645a_read(flash, AS_VERSION_CONTROL_REG);
582 if (rval < 0)
583 goto power_off;
584
585 rfu = AS_VERSION_CONTROL_RFU(rval);
586 version = AS_VERSION_CONTROL_VERSION(rval);
587
588 /* Verify the chip model and version. */
589 if (model != 0x01 || rfu != 0x00) {
590 dev_err(&client->dev, "AS3645A not detected "
591 "(model %d rfu %d)\n", model, rfu);
592 rval = -ENODEV;
593 goto power_off;
594 }
595
596 switch (man) {
597 case 1:
598 vendor = "AMS, Austria Micro Systems";
599 break;
600 case 2:
601 vendor = "ADI, Analog Devices Inc.";
602 break;
603 case 3:
604 vendor = "NSC, National Semiconductor";
605 break;
606 case 4:
607 vendor = "NXP";
608 break;
609 case 5:
610 vendor = "TI, Texas Instrument";
611 break;
612 default:
613 vendor = "Unknown";
614 }
615
616 dev_info(&client->dev, "Chip vendor: %s (%d) Version: %d\n", vendor,
617 man, version);
618
619 rval = as3645a_write(flash, AS_PASSWORD_REG, AS_PASSWORD_UNLOCK_VALUE);
620 if (rval < 0)
621 goto power_off;
622
623 rval = as3645a_write(flash, AS_BOOST_REG, AS_BOOST_CURRENT_DISABLE);
624 if (rval < 0)
625 goto power_off;
626
627 /* Setup default values. This makes sure that the chip is in a known
628 * state, in case the power rail can't be controlled.
629 */
630 rval = as3645a_setup(flash);
631
632power_off:
633 as3645a_set_power(&flash->subdev, 0);
634
635 return rval;
636}
637
638static int as3645a_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
639{
640 return as3645a_set_power(sd, 1);
641}
642
643static int as3645a_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
644{
645 return as3645a_set_power(sd, 0);
646}
647
648static const struct v4l2_subdev_core_ops as3645a_core_ops = {
649 .s_power = as3645a_set_power,
650};
651
652static const struct v4l2_subdev_ops as3645a_ops = {
653 .core = &as3645a_core_ops,
654};
655
656static const struct v4l2_subdev_internal_ops as3645a_internal_ops = {
657 .registered = as3645a_registered,
658 .open = as3645a_open,
659 .close = as3645a_close,
660};
661
662/* -----------------------------------------------------------------------------
663 * I2C driver
664 */
665#ifdef CONFIG_PM
666
667static int as3645a_suspend(struct device *dev)
668{
669 struct i2c_client *client = to_i2c_client(dev);
670 struct v4l2_subdev *subdev = i2c_get_clientdata(client);
671 struct as3645a *flash = to_as3645a(subdev);
672 int rval;
673
674 if (flash->power_count == 0)
675 return 0;
676
677 rval = __as3645a_set_power(flash, 0);
678
679 dev_dbg(&client->dev, "Suspend %s\n", rval < 0 ? "failed" : "ok");
680
681 return rval;
682}
683
684static int as3645a_resume(struct device *dev)
685{
686 struct i2c_client *client = to_i2c_client(dev);
687 struct v4l2_subdev *subdev = i2c_get_clientdata(client);
688 struct as3645a *flash = to_as3645a(subdev);
689 int rval;
690
691 if (flash->power_count == 0)
692 return 0;
693
694 rval = __as3645a_set_power(flash, 1);
695
696 dev_dbg(&client->dev, "Resume %s\n", rval < 0 ? "fail" : "ok");
697
698 return rval;
699}
700
701#else
702
703#define as3645a_suspend NULL
704#define as3645a_resume NULL
705
706#endif /* CONFIG_PM */
707
708/*
709 * as3645a_init_controls - Create controls
710 * @flash: The flash
711 *
712 * The number of LEDs reported in platform data is used to compute default
713 * limits. Parameters passed through platform data can override those limits.
714 */
715static int as3645a_init_controls(struct as3645a *flash)
716{
717 const struct as3645a_platform_data *pdata = flash->pdata;
718 struct v4l2_ctrl *ctrl;
719 int maximum;
720
721 v4l2_ctrl_handler_init(&flash->ctrls, 10);
722
723 /* V4L2_CID_FLASH_LED_MODE */
724 v4l2_ctrl_new_std_menu(&flash->ctrls, &as3645a_ctrl_ops,
725 V4L2_CID_FLASH_LED_MODE, 2, ~7,
726 V4L2_FLASH_LED_MODE_NONE);
727
728 /* V4L2_CID_FLASH_STROBE_SOURCE */
729 v4l2_ctrl_new_std_menu(&flash->ctrls, &as3645a_ctrl_ops,
730 V4L2_CID_FLASH_STROBE_SOURCE,
731 pdata->ext_strobe ? 1 : 0,
732 pdata->ext_strobe ? ~3 : ~1,
733 V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
734
735 flash->strobe_source = V4L2_FLASH_STROBE_SOURCE_SOFTWARE;
736
737 /* V4L2_CID_FLASH_STROBE */
738 v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
739 V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
740
741 /* V4L2_CID_FLASH_STROBE_STOP */
742 v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
743 V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
744
745 /* V4L2_CID_FLASH_STROBE_STATUS */
746 ctrl = v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
747 V4L2_CID_FLASH_STROBE_STATUS, 0, 1, 1, 1);
748 if (ctrl != NULL)
749 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
750
751 /* V4L2_CID_FLASH_TIMEOUT */
752 maximum = pdata->timeout_max;
753
754 v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
755 V4L2_CID_FLASH_TIMEOUT, AS3645A_FLASH_TIMEOUT_MIN,
756 maximum, AS3645A_FLASH_TIMEOUT_STEP, maximum);
757
758 flash->timeout = maximum;
759
760 /* V4L2_CID_FLASH_INTENSITY */
761 maximum = pdata->flash_max_current;
762
763 v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
764 V4L2_CID_FLASH_INTENSITY, AS3645A_FLASH_INTENSITY_MIN,
765 maximum, AS3645A_FLASH_INTENSITY_STEP, maximum);
766
767 flash->flash_current = (maximum - AS3645A_FLASH_INTENSITY_MIN)
768 / AS3645A_FLASH_INTENSITY_STEP;
769
770 /* V4L2_CID_FLASH_TORCH_INTENSITY */
771 maximum = pdata->torch_max_current;
772
773 v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
774 V4L2_CID_FLASH_TORCH_INTENSITY,
775 AS3645A_TORCH_INTENSITY_MIN, maximum,
776 AS3645A_TORCH_INTENSITY_STEP,
777 AS3645A_TORCH_INTENSITY_MIN);
778
779 flash->assist_current = 0;
780
781 /* V4L2_CID_FLASH_INDICATOR_INTENSITY */
782 v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
783 V4L2_CID_FLASH_INDICATOR_INTENSITY,
784 AS3645A_INDICATOR_INTENSITY_MIN,
785 AS3645A_INDICATOR_INTENSITY_MAX,
786 AS3645A_INDICATOR_INTENSITY_STEP,
787 AS3645A_INDICATOR_INTENSITY_MIN);
788
789 flash->indicator_current = 0;
790
791 /* V4L2_CID_FLASH_FAULT */
792 ctrl = v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
793 V4L2_CID_FLASH_FAULT, 0,
794 V4L2_FLASH_FAULT_OVER_VOLTAGE |
795 V4L2_FLASH_FAULT_TIMEOUT |
796 V4L2_FLASH_FAULT_OVER_TEMPERATURE |
797 V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
798 if (ctrl != NULL)
799 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
800
801 flash->subdev.ctrl_handler = &flash->ctrls;
802
803 return flash->ctrls.error;
804}
805
806static int as3645a_probe(struct i2c_client *client,
807 const struct i2c_device_id *devid)
808{
809 struct as3645a *flash;
810 int ret;
811
812 if (client->dev.platform_data == NULL)
813 return -ENODEV;
814
815 flash = kzalloc(sizeof(*flash), GFP_KERNEL);
816 if (flash == NULL)
817 return -ENOMEM;
818
819 flash->pdata = client->dev.platform_data;
820
821 v4l2_i2c_subdev_init(&flash->subdev, client, &as3645a_ops);
822 flash->subdev.internal_ops = &as3645a_internal_ops;
823 flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
824
825 ret = as3645a_init_controls(flash);
826 if (ret < 0)
827 goto done;
828
829 ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
830 if (ret < 0)
831 goto done;
832
833 flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
834
835 mutex_init(&flash->power_lock);
836
837 flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
838
839done:
840 if (ret < 0) {
841 v4l2_ctrl_handler_free(&flash->ctrls);
842 kfree(flash);
843 }
844
845 return ret;
846}
847
848static int __exit as3645a_remove(struct i2c_client *client)
849{
850 struct v4l2_subdev *subdev = i2c_get_clientdata(client);
851 struct as3645a *flash = to_as3645a(subdev);
852
853 v4l2_device_unregister_subdev(subdev);
854 v4l2_ctrl_handler_free(&flash->ctrls);
855 media_entity_cleanup(&flash->subdev.entity);
856 mutex_destroy(&flash->power_lock);
857 kfree(flash);
858
859 return 0;
860}
861
862static const struct i2c_device_id as3645a_id_table[] = {
863 { AS3645A_NAME, 0 },
864 { },
865};
866MODULE_DEVICE_TABLE(i2c, as3645a_id_table);
867
868static const struct dev_pm_ops as3645a_pm_ops = {
869 .suspend = as3645a_suspend,
870 .resume = as3645a_resume,
871};
872
873static struct i2c_driver as3645a_i2c_driver = {
874 .driver = {
875 .name = AS3645A_NAME,
876 .pm = &as3645a_pm_ops,
877 },
878 .probe = as3645a_probe,
879 .remove = __exit_p(as3645a_remove),
880 .id_table = as3645a_id_table,
881};
882
883static int __init as3645a_init(void)
884{
885 int rval;
886
887 rval = i2c_add_driver(&as3645a_i2c_driver);
888 if (rval)
889 pr_err("%s: Failed to register the driver\n", AS3645A_NAME);
890
891 return rval;
892}
893
894static void __exit as3645a_exit(void)
895{
896 i2c_del_driver(&as3645a_i2c_driver);
897}
898
899module_init(as3645a_init);
900module_exit(as3645a_exit);
901
902MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
903MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones");
904MODULE_LICENSE("GPL");
diff --git a/include/media/as3645a.h b/include/media/as3645a.h
new file mode 100644
index 000000000000..5075496d2c9e
--- /dev/null
+++ b/include/media/as3645a.h
@@ -0,0 +1,71 @@
1/*
2 * include/media/as3645a.h
3 *
4 * Copyright (C) 2008-2011 Nokia Corporation
5 *
6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.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 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __AS3645A_H__
25#define __AS3645A_H__
26
27#include <media/v4l2-subdev.h>
28
29#define AS3645A_NAME "as3645a"
30#define AS3645A_I2C_ADDR (0x60 >> 1) /* W:0x60, R:0x61 */
31
32#define AS3645A_FLASH_TIMEOUT_MIN 100000 /* us */
33#define AS3645A_FLASH_TIMEOUT_MAX 850000
34#define AS3645A_FLASH_TIMEOUT_STEP 50000
35
36#define AS3645A_FLASH_INTENSITY_MIN 200 /* mA */
37#define AS3645A_FLASH_INTENSITY_MAX_1LED 500
38#define AS3645A_FLASH_INTENSITY_MAX_2LEDS 400
39#define AS3645A_FLASH_INTENSITY_STEP 20
40
41#define AS3645A_TORCH_INTENSITY_MIN 20 /* mA */
42#define AS3645A_TORCH_INTENSITY_MAX 160
43#define AS3645A_TORCH_INTENSITY_STEP 20
44
45#define AS3645A_INDICATOR_INTENSITY_MIN 0 /* uA */
46#define AS3645A_INDICATOR_INTENSITY_MAX 10000
47#define AS3645A_INDICATOR_INTENSITY_STEP 2500
48
49/*
50 * as3645a_platform_data - Flash controller platform data
51 * @set_power: Set power callback
52 * @vref: VREF offset (0=0V, 1=+0.3V, 2=-0.3V, 3=+0.6V)
53 * @peak: Inductor peak current limit (0=1.25A, 1=1.5A, 2=1.75A, 3=2.0A)
54 * @ext_strobe: True if external flash strobe can be used
55 * @flash_max_current: Max flash current (mA, <= AS3645A_FLASH_INTENSITY_MAX)
56 * @torch_max_current: Max torch current (mA, >= AS3645A_TORCH_INTENSITY_MAX)
57 * @timeout_max: Max flash timeout (us, <= AS3645A_FLASH_TIMEOUT_MAX)
58 */
59struct as3645a_platform_data {
60 int (*set_power)(struct v4l2_subdev *subdev, int on);
61 unsigned int vref;
62 unsigned int peak;
63 bool ext_strobe;
64
65 /* Flash and torch currents and timeout limits */
66 unsigned int flash_max_current;
67 unsigned int torch_max_current;
68 unsigned int timeout_max;
69};
70
71#endif /* __AS3645A_H__ */