leds-as3645a.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * drivers/leds/leds-as3645a.c - AS3645A and LM3555 flash controllers driver
  4. *
  5. * Copyright (C) 2008-2011 Nokia Corporation
  6. * Copyright (c) 2011, 2017 Intel Corporation.
  7. *
  8. * Based on drivers/media/i2c/as3645a.c.
  9. *
  10. * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  11. */
  12. #include <linux/delay.h>
  13. #include <linux/gpio/consumer.h>
  14. #include <linux/i2c.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/property.h>
  20. #include <linux/slab.h>
  21. #include <media/v4l2-flash-led-class.h>
  22. #define AS_TIMER_US_TO_CODE(t) (((t) / 1000 - 100) / 50)
  23. #define AS_TIMER_CODE_TO_US(c) ((50 * (c) + 100) * 1000)
  24. /* Register definitions */
  25. /* Read-only Design info register: Reset state: xxxx 0001 */
  26. #define AS_DESIGN_INFO_REG 0x00
  27. #define AS_DESIGN_INFO_FACTORY(x) (((x) >> 4))
  28. #define AS_DESIGN_INFO_MODEL(x) ((x) & 0x0f)
  29. /* Read-only Version control register: Reset state: 0000 0000
  30. * for first engineering samples
  31. */
  32. #define AS_VERSION_CONTROL_REG 0x01
  33. #define AS_VERSION_CONTROL_RFU(x) (((x) >> 4))
  34. #define AS_VERSION_CONTROL_VERSION(x) ((x) & 0x0f)
  35. /* Read / Write (Indicator and timer register): Reset state: 0000 1111 */
  36. #define AS_INDICATOR_AND_TIMER_REG 0x02
  37. #define AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT 0
  38. #define AS_INDICATOR_AND_TIMER_VREF_SHIFT 4
  39. #define AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT 6
  40. /* Read / Write (Current set register): Reset state: 0110 1001 */
  41. #define AS_CURRENT_SET_REG 0x03
  42. #define AS_CURRENT_ASSIST_LIGHT_SHIFT 0
  43. #define AS_CURRENT_LED_DET_ON (1 << 3)
  44. #define AS_CURRENT_FLASH_CURRENT_SHIFT 4
  45. /* Read / Write (Control register): Reset state: 1011 0100 */
  46. #define AS_CONTROL_REG 0x04
  47. #define AS_CONTROL_MODE_SETTING_SHIFT 0
  48. #define AS_CONTROL_STROBE_ON (1 << 2)
  49. #define AS_CONTROL_OUT_ON (1 << 3)
  50. #define AS_CONTROL_EXT_TORCH_ON (1 << 4)
  51. #define AS_CONTROL_STROBE_TYPE_EDGE (0 << 5)
  52. #define AS_CONTROL_STROBE_TYPE_LEVEL (1 << 5)
  53. #define AS_CONTROL_COIL_PEAK_SHIFT 6
  54. /* Read only (D3 is read / write) (Fault and info): Reset state: 0000 x000 */
  55. #define AS_FAULT_INFO_REG 0x05
  56. #define AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT (1 << 1)
  57. #define AS_FAULT_INFO_INDICATOR_LED (1 << 2)
  58. #define AS_FAULT_INFO_LED_AMOUNT (1 << 3)
  59. #define AS_FAULT_INFO_TIMEOUT (1 << 4)
  60. #define AS_FAULT_INFO_OVER_TEMPERATURE (1 << 5)
  61. #define AS_FAULT_INFO_SHORT_CIRCUIT (1 << 6)
  62. #define AS_FAULT_INFO_OVER_VOLTAGE (1 << 7)
  63. /* Boost register */
  64. #define AS_BOOST_REG 0x0d
  65. #define AS_BOOST_CURRENT_DISABLE (0 << 0)
  66. #define AS_BOOST_CURRENT_ENABLE (1 << 0)
  67. /* Password register is used to unlock boost register writing */
  68. #define AS_PASSWORD_REG 0x0f
  69. #define AS_PASSWORD_UNLOCK_VALUE 0x55
  70. #define AS_NAME "as3645a"
  71. #define AS_I2C_ADDR (0x60 >> 1) /* W:0x60, R:0x61 */
  72. #define AS_FLASH_TIMEOUT_MIN 100000 /* us */
  73. #define AS_FLASH_TIMEOUT_MAX 850000
  74. #define AS_FLASH_TIMEOUT_STEP 50000
  75. #define AS_FLASH_INTENSITY_MIN 200000 /* uA */
  76. #define AS_FLASH_INTENSITY_MAX_1LED 500000
  77. #define AS_FLASH_INTENSITY_MAX_2LEDS 400000
  78. #define AS_FLASH_INTENSITY_STEP 20000
  79. #define AS_TORCH_INTENSITY_MIN 20000 /* uA */
  80. #define AS_TORCH_INTENSITY_MAX 160000
  81. #define AS_TORCH_INTENSITY_STEP 20000
  82. #define AS_INDICATOR_INTENSITY_MIN 0 /* uA */
  83. #define AS_INDICATOR_INTENSITY_MAX 10000
  84. #define AS_INDICATOR_INTENSITY_STEP 2500
  85. #define AS_PEAK_mA_MAX 2000
  86. #define AS_PEAK_mA_TO_REG(a) \
  87. ((min_t(u32, AS_PEAK_mA_MAX, a) - 1250) / 250)
  88. /* LED numbers for Devicetree */
  89. #define AS_LED_FLASH 0
  90. #define AS_LED_INDICATOR 1
  91. enum as_mode {
  92. AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT,
  93. AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT,
  94. AS_MODE_ASSIST = 2 << AS_CONTROL_MODE_SETTING_SHIFT,
  95. AS_MODE_FLASH = 3 << AS_CONTROL_MODE_SETTING_SHIFT,
  96. };
  97. struct as3645a_config {
  98. u32 flash_timeout_us;
  99. u32 flash_max_ua;
  100. u32 assist_max_ua;
  101. u32 indicator_max_ua;
  102. u32 voltage_reference;
  103. u32 peak;
  104. };
  105. struct as3645a {
  106. struct i2c_client *client;
  107. struct mutex mutex;
  108. struct led_classdev_flash fled;
  109. struct led_classdev iled_cdev;
  110. struct v4l2_flash *vf;
  111. struct v4l2_flash *vfind;
  112. struct fwnode_handle *flash_node;
  113. struct fwnode_handle *indicator_node;
  114. struct as3645a_config cfg;
  115. enum as_mode mode;
  116. unsigned int timeout;
  117. unsigned int flash_current;
  118. unsigned int assist_current;
  119. unsigned int indicator_current;
  120. enum v4l2_flash_strobe_source strobe_source;
  121. };
  122. #define fled_to_as3645a(__fled) container_of(__fled, struct as3645a, fled)
  123. #define iled_cdev_to_as3645a(__iled_cdev) \
  124. container_of(__iled_cdev, struct as3645a, iled_cdev)
  125. /* Return negative errno else zero on success */
  126. static int as3645a_write(struct as3645a *flash, u8 addr, u8 val)
  127. {
  128. struct i2c_client *client = flash->client;
  129. int rval;
  130. rval = i2c_smbus_write_byte_data(client, addr, val);
  131. dev_dbg(&client->dev, "Write Addr:%02X Val:%02X %s\n", addr, val,
  132. rval < 0 ? "fail" : "ok");
  133. return rval;
  134. }
  135. /* Return negative errno else a data byte received from the device. */
  136. static int as3645a_read(struct as3645a *flash, u8 addr)
  137. {
  138. struct i2c_client *client = flash->client;
  139. int rval;
  140. rval = i2c_smbus_read_byte_data(client, addr);
  141. dev_dbg(&client->dev, "Read Addr:%02X Val:%02X %s\n", addr, rval,
  142. rval < 0 ? "fail" : "ok");
  143. return rval;
  144. }
  145. /* -----------------------------------------------------------------------------
  146. * Hardware configuration and trigger
  147. */
  148. /**
  149. * as3645a_set_config - Set flash configuration registers
  150. * @flash: The flash
  151. *
  152. * Configure the hardware with flash, assist and indicator currents, as well as
  153. * flash timeout.
  154. *
  155. * Return 0 on success, or a negative error code if an I2C communication error
  156. * occurred.
  157. */
  158. static int as3645a_set_current(struct as3645a *flash)
  159. {
  160. u8 val;
  161. val = (flash->flash_current << AS_CURRENT_FLASH_CURRENT_SHIFT)
  162. | (flash->assist_current << AS_CURRENT_ASSIST_LIGHT_SHIFT)
  163. | AS_CURRENT_LED_DET_ON;
  164. return as3645a_write(flash, AS_CURRENT_SET_REG, val);
  165. }
  166. static int as3645a_set_timeout(struct as3645a *flash)
  167. {
  168. u8 val;
  169. val = flash->timeout << AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT;
  170. val |= (flash->cfg.voltage_reference
  171. << AS_INDICATOR_AND_TIMER_VREF_SHIFT)
  172. | ((flash->indicator_current ? flash->indicator_current - 1 : 0)
  173. << AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT);
  174. return as3645a_write(flash, AS_INDICATOR_AND_TIMER_REG, val);
  175. }
  176. /**
  177. * as3645a_set_control - Set flash control register
  178. * @flash: The flash
  179. * @mode: Desired output mode
  180. * @on: Desired output state
  181. *
  182. * Configure the hardware with output mode and state.
  183. *
  184. * Return 0 on success, or a negative error code if an I2C communication error
  185. * occurred.
  186. */
  187. static int
  188. as3645a_set_control(struct as3645a *flash, enum as_mode mode, bool on)
  189. {
  190. u8 reg;
  191. /* Configure output parameters and operation mode. */
  192. reg = (flash->cfg.peak << AS_CONTROL_COIL_PEAK_SHIFT)
  193. | (on ? AS_CONTROL_OUT_ON : 0)
  194. | mode;
  195. if (mode == AS_MODE_FLASH &&
  196. flash->strobe_source == V4L2_FLASH_STROBE_SOURCE_EXTERNAL)
  197. reg |= AS_CONTROL_STROBE_TYPE_LEVEL
  198. | AS_CONTROL_STROBE_ON;
  199. return as3645a_write(flash, AS_CONTROL_REG, reg);
  200. }
  201. static int as3645a_get_fault(struct led_classdev_flash *fled, u32 *fault)
  202. {
  203. struct as3645a *flash = fled_to_as3645a(fled);
  204. int rval;
  205. /* NOTE: reading register clears fault status */
  206. rval = as3645a_read(flash, AS_FAULT_INFO_REG);
  207. if (rval < 0)
  208. return rval;
  209. if (rval & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
  210. *fault |= LED_FAULT_OVER_CURRENT;
  211. if (rval & AS_FAULT_INFO_INDICATOR_LED)
  212. *fault |= LED_FAULT_INDICATOR;
  213. dev_dbg(&flash->client->dev, "%u connected LEDs\n",
  214. rval & AS_FAULT_INFO_LED_AMOUNT ? 2 : 1);
  215. if (rval & AS_FAULT_INFO_TIMEOUT)
  216. *fault |= LED_FAULT_TIMEOUT;
  217. if (rval & AS_FAULT_INFO_OVER_TEMPERATURE)
  218. *fault |= LED_FAULT_OVER_TEMPERATURE;
  219. if (rval & AS_FAULT_INFO_SHORT_CIRCUIT)
  220. *fault |= LED_FAULT_OVER_CURRENT;
  221. if (rval & AS_FAULT_INFO_OVER_VOLTAGE)
  222. *fault |= LED_FAULT_INPUT_VOLTAGE;
  223. return rval;
  224. }
  225. static unsigned int __as3645a_current_to_reg(unsigned int min, unsigned int max,
  226. unsigned int step,
  227. unsigned int val)
  228. {
  229. if (val < min)
  230. val = min;
  231. if (val > max)
  232. val = max;
  233. return (val - min) / step;
  234. }
  235. static unsigned int as3645a_current_to_reg(struct as3645a *flash, bool is_flash,
  236. unsigned int ua)
  237. {
  238. if (is_flash)
  239. return __as3645a_current_to_reg(AS_TORCH_INTENSITY_MIN,
  240. flash->cfg.assist_max_ua,
  241. AS_TORCH_INTENSITY_STEP, ua);
  242. else
  243. return __as3645a_current_to_reg(AS_FLASH_INTENSITY_MIN,
  244. flash->cfg.flash_max_ua,
  245. AS_FLASH_INTENSITY_STEP, ua);
  246. }
  247. static int as3645a_set_indicator_brightness(struct led_classdev *iled_cdev,
  248. enum led_brightness brightness)
  249. {
  250. struct as3645a *flash = iled_cdev_to_as3645a(iled_cdev);
  251. int rval;
  252. flash->indicator_current = brightness;
  253. rval = as3645a_set_timeout(flash);
  254. if (rval)
  255. return rval;
  256. return as3645a_set_control(flash, AS_MODE_INDICATOR, brightness);
  257. }
  258. static int as3645a_set_assist_brightness(struct led_classdev *fled_cdev,
  259. enum led_brightness brightness)
  260. {
  261. struct led_classdev_flash *fled = lcdev_to_flcdev(fled_cdev);
  262. struct as3645a *flash = fled_to_as3645a(fled);
  263. int rval;
  264. if (brightness) {
  265. /* Register value 0 is 20 mA. */
  266. flash->assist_current = brightness - 1;
  267. rval = as3645a_set_current(flash);
  268. if (rval)
  269. return rval;
  270. }
  271. return as3645a_set_control(flash, AS_MODE_ASSIST, brightness);
  272. }
  273. static int as3645a_set_flash_brightness(struct led_classdev_flash *fled,
  274. u32 brightness_ua)
  275. {
  276. struct as3645a *flash = fled_to_as3645a(fled);
  277. flash->flash_current = as3645a_current_to_reg(flash, true,
  278. brightness_ua);
  279. return as3645a_set_current(flash);
  280. }
  281. static int as3645a_set_flash_timeout(struct led_classdev_flash *fled,
  282. u32 timeout_us)
  283. {
  284. struct as3645a *flash = fled_to_as3645a(fled);
  285. flash->timeout = AS_TIMER_US_TO_CODE(timeout_us);
  286. return as3645a_set_timeout(flash);
  287. }
  288. static int as3645a_set_strobe(struct led_classdev_flash *fled, bool state)
  289. {
  290. struct as3645a *flash = fled_to_as3645a(fled);
  291. return as3645a_set_control(flash, AS_MODE_FLASH, state);
  292. }
  293. static const struct led_flash_ops as3645a_led_flash_ops = {
  294. .flash_brightness_set = as3645a_set_flash_brightness,
  295. .timeout_set = as3645a_set_flash_timeout,
  296. .strobe_set = as3645a_set_strobe,
  297. .fault_get = as3645a_get_fault,
  298. };
  299. static int as3645a_setup(struct as3645a *flash)
  300. {
  301. struct device *dev = &flash->client->dev;
  302. u32 fault = 0;
  303. int rval;
  304. /* clear errors */
  305. rval = as3645a_read(flash, AS_FAULT_INFO_REG);
  306. if (rval < 0)
  307. return rval;
  308. dev_dbg(dev, "Fault info: %02x\n", rval);
  309. rval = as3645a_set_current(flash);
  310. if (rval < 0)
  311. return rval;
  312. rval = as3645a_set_timeout(flash);
  313. if (rval < 0)
  314. return rval;
  315. rval = as3645a_set_control(flash, AS_MODE_INDICATOR, false);
  316. if (rval < 0)
  317. return rval;
  318. /* read status */
  319. rval = as3645a_get_fault(&flash->fled, &fault);
  320. if (rval < 0)
  321. return rval;
  322. dev_dbg(dev, "AS_INDICATOR_AND_TIMER_REG: %02x\n",
  323. as3645a_read(flash, AS_INDICATOR_AND_TIMER_REG));
  324. dev_dbg(dev, "AS_CURRENT_SET_REG: %02x\n",
  325. as3645a_read(flash, AS_CURRENT_SET_REG));
  326. dev_dbg(dev, "AS_CONTROL_REG: %02x\n",
  327. as3645a_read(flash, AS_CONTROL_REG));
  328. return rval & ~AS_FAULT_INFO_LED_AMOUNT ? -EIO : 0;
  329. }
  330. static int as3645a_detect(struct as3645a *flash)
  331. {
  332. struct device *dev = &flash->client->dev;
  333. int rval, man, model, rfu, version;
  334. const char *vendor;
  335. rval = as3645a_read(flash, AS_DESIGN_INFO_REG);
  336. if (rval < 0) {
  337. dev_err(dev, "can't read design info reg\n");
  338. return rval;
  339. }
  340. man = AS_DESIGN_INFO_FACTORY(rval);
  341. model = AS_DESIGN_INFO_MODEL(rval);
  342. rval = as3645a_read(flash, AS_VERSION_CONTROL_REG);
  343. if (rval < 0) {
  344. dev_err(dev, "can't read version control reg\n");
  345. return rval;
  346. }
  347. rfu = AS_VERSION_CONTROL_RFU(rval);
  348. version = AS_VERSION_CONTROL_VERSION(rval);
  349. /* Verify the chip model and version. */
  350. if (model != 0x01 || rfu != 0x00) {
  351. dev_err(dev, "AS3645A not detected (model %d rfu %d)\n",
  352. model, rfu);
  353. return -ENODEV;
  354. }
  355. switch (man) {
  356. case 1:
  357. vendor = "AMS, Austria Micro Systems";
  358. break;
  359. case 2:
  360. vendor = "ADI, Analog Devices Inc.";
  361. break;
  362. case 3:
  363. vendor = "NSC, National Semiconductor";
  364. break;
  365. case 4:
  366. vendor = "NXP";
  367. break;
  368. case 5:
  369. vendor = "TI, Texas Instrument";
  370. break;
  371. default:
  372. vendor = "Unknown";
  373. }
  374. dev_info(dev, "Chip vendor: %s (%d) Version: %d\n", vendor,
  375. man, version);
  376. rval = as3645a_write(flash, AS_PASSWORD_REG, AS_PASSWORD_UNLOCK_VALUE);
  377. if (rval < 0)
  378. return rval;
  379. return as3645a_write(flash, AS_BOOST_REG, AS_BOOST_CURRENT_DISABLE);
  380. }
  381. static int as3645a_parse_node(struct as3645a *flash,
  382. struct fwnode_handle *fwnode)
  383. {
  384. struct as3645a_config *cfg = &flash->cfg;
  385. struct fwnode_handle *child;
  386. int rval;
  387. fwnode_for_each_child_node(fwnode, child) {
  388. u32 id = 0;
  389. fwnode_property_read_u32(child, "reg", &id);
  390. switch (id) {
  391. case AS_LED_FLASH:
  392. flash->flash_node = child;
  393. fwnode_handle_get(child);
  394. break;
  395. case AS_LED_INDICATOR:
  396. flash->indicator_node = child;
  397. fwnode_handle_get(child);
  398. break;
  399. default:
  400. dev_warn(&flash->client->dev,
  401. "unknown LED %u encountered, ignoring\n", id);
  402. break;
  403. }
  404. }
  405. if (!flash->flash_node) {
  406. dev_err(&flash->client->dev, "can't find flash node\n");
  407. return -ENODEV;
  408. }
  409. rval = fwnode_property_read_u32(flash->flash_node, "flash-timeout-us",
  410. &cfg->flash_timeout_us);
  411. if (rval < 0) {
  412. dev_err(&flash->client->dev,
  413. "can't read flash-timeout-us property for flash\n");
  414. goto out_err;
  415. }
  416. rval = fwnode_property_read_u32(flash->flash_node, "flash-max-microamp",
  417. &cfg->flash_max_ua);
  418. if (rval < 0) {
  419. dev_err(&flash->client->dev,
  420. "can't read flash-max-microamp property for flash\n");
  421. goto out_err;
  422. }
  423. rval = fwnode_property_read_u32(flash->flash_node, "led-max-microamp",
  424. &cfg->assist_max_ua);
  425. if (rval < 0) {
  426. dev_err(&flash->client->dev,
  427. "can't read led-max-microamp property for flash\n");
  428. goto out_err;
  429. }
  430. fwnode_property_read_u32(flash->flash_node, "voltage-reference",
  431. &cfg->voltage_reference);
  432. fwnode_property_read_u32(flash->flash_node, "ams,input-max-microamp",
  433. &cfg->peak);
  434. cfg->peak = AS_PEAK_mA_TO_REG(cfg->peak);
  435. if (!flash->indicator_node) {
  436. dev_warn(&flash->client->dev,
  437. "can't find indicator node\n");
  438. rval = -ENODEV;
  439. goto out_err;
  440. }
  441. rval = fwnode_property_read_u32(flash->indicator_node,
  442. "led-max-microamp",
  443. &cfg->indicator_max_ua);
  444. if (rval < 0) {
  445. dev_err(&flash->client->dev,
  446. "can't read led-max-microamp property for indicator\n");
  447. goto out_err;
  448. }
  449. return 0;
  450. out_err:
  451. fwnode_handle_put(flash->flash_node);
  452. fwnode_handle_put(flash->indicator_node);
  453. return rval;
  454. }
  455. static int as3645a_led_class_setup(struct as3645a *flash)
  456. {
  457. struct led_classdev *fled_cdev = &flash->fled.led_cdev;
  458. struct led_classdev *iled_cdev = &flash->iled_cdev;
  459. struct led_init_data init_data = {};
  460. struct led_flash_setting *cfg;
  461. int rval;
  462. iled_cdev->brightness_set_blocking = as3645a_set_indicator_brightness;
  463. iled_cdev->max_brightness =
  464. flash->cfg.indicator_max_ua / AS_INDICATOR_INTENSITY_STEP;
  465. iled_cdev->flags = LED_CORE_SUSPENDRESUME;
  466. init_data.fwnode = flash->indicator_node;
  467. init_data.devicename = AS_NAME;
  468. init_data.default_label = "indicator";
  469. rval = led_classdev_register_ext(&flash->client->dev, iled_cdev,
  470. &init_data);
  471. if (rval < 0)
  472. return rval;
  473. cfg = &flash->fled.brightness;
  474. cfg->min = AS_FLASH_INTENSITY_MIN;
  475. cfg->max = flash->cfg.flash_max_ua;
  476. cfg->step = AS_FLASH_INTENSITY_STEP;
  477. cfg->val = flash->cfg.flash_max_ua;
  478. cfg = &flash->fled.timeout;
  479. cfg->min = AS_FLASH_TIMEOUT_MIN;
  480. cfg->max = flash->cfg.flash_timeout_us;
  481. cfg->step = AS_FLASH_TIMEOUT_STEP;
  482. cfg->val = flash->cfg.flash_timeout_us;
  483. flash->fled.ops = &as3645a_led_flash_ops;
  484. fled_cdev->brightness_set_blocking = as3645a_set_assist_brightness;
  485. /* Value 0 is off in LED class. */
  486. fled_cdev->max_brightness =
  487. as3645a_current_to_reg(flash, false,
  488. flash->cfg.assist_max_ua) + 1;
  489. fled_cdev->flags = LED_DEV_CAP_FLASH | LED_CORE_SUSPENDRESUME;
  490. init_data.fwnode = flash->flash_node;
  491. init_data.devicename = AS_NAME;
  492. init_data.default_label = "flash";
  493. rval = led_classdev_flash_register_ext(&flash->client->dev,
  494. &flash->fled, &init_data);
  495. if (rval)
  496. goto out_err;
  497. return rval;
  498. out_err:
  499. led_classdev_unregister(iled_cdev);
  500. dev_err(&flash->client->dev,
  501. "led_classdev_flash_register() failed, error %d\n",
  502. rval);
  503. return rval;
  504. }
  505. static int as3645a_v4l2_setup(struct as3645a *flash)
  506. {
  507. struct led_classdev_flash *fled = &flash->fled;
  508. struct led_classdev *led = &fled->led_cdev;
  509. struct v4l2_flash_config cfg = {
  510. .intensity = {
  511. .min = AS_TORCH_INTENSITY_MIN,
  512. .max = flash->cfg.assist_max_ua,
  513. .step = AS_TORCH_INTENSITY_STEP,
  514. .val = flash->cfg.assist_max_ua,
  515. },
  516. };
  517. struct v4l2_flash_config cfgind = {
  518. .intensity = {
  519. .min = AS_INDICATOR_INTENSITY_MIN,
  520. .max = flash->cfg.indicator_max_ua,
  521. .step = AS_INDICATOR_INTENSITY_STEP,
  522. .val = flash->cfg.indicator_max_ua,
  523. },
  524. };
  525. strlcpy(cfg.dev_name, led->dev->kobj.name, sizeof(cfg.dev_name));
  526. strlcpy(cfgind.dev_name, flash->iled_cdev.dev->kobj.name,
  527. sizeof(cfgind.dev_name));
  528. flash->vf = v4l2_flash_init(
  529. &flash->client->dev, flash->flash_node, &flash->fled, NULL,
  530. &cfg);
  531. if (IS_ERR(flash->vf))
  532. return PTR_ERR(flash->vf);
  533. flash->vfind = v4l2_flash_indicator_init(
  534. &flash->client->dev, flash->indicator_node, &flash->iled_cdev,
  535. &cfgind);
  536. if (IS_ERR(flash->vfind)) {
  537. v4l2_flash_release(flash->vf);
  538. return PTR_ERR(flash->vfind);
  539. }
  540. return 0;
  541. }
  542. static int as3645a_probe(struct i2c_client *client)
  543. {
  544. struct as3645a *flash;
  545. int rval;
  546. if (!dev_fwnode(&client->dev))
  547. return -ENODEV;
  548. flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
  549. if (flash == NULL)
  550. return -ENOMEM;
  551. flash->client = client;
  552. rval = as3645a_parse_node(flash, dev_fwnode(&client->dev));
  553. if (rval < 0)
  554. return rval;
  555. rval = as3645a_detect(flash);
  556. if (rval < 0)
  557. goto out_put_nodes;
  558. mutex_init(&flash->mutex);
  559. i2c_set_clientdata(client, flash);
  560. rval = as3645a_setup(flash);
  561. if (rval)
  562. goto out_mutex_destroy;
  563. rval = as3645a_led_class_setup(flash);
  564. if (rval)
  565. goto out_mutex_destroy;
  566. rval = as3645a_v4l2_setup(flash);
  567. if (rval)
  568. goto out_led_classdev_flash_unregister;
  569. return 0;
  570. out_led_classdev_flash_unregister:
  571. led_classdev_flash_unregister(&flash->fled);
  572. out_mutex_destroy:
  573. mutex_destroy(&flash->mutex);
  574. out_put_nodes:
  575. fwnode_handle_put(flash->flash_node);
  576. fwnode_handle_put(flash->indicator_node);
  577. return rval;
  578. }
  579. static int as3645a_remove(struct i2c_client *client)
  580. {
  581. struct as3645a *flash = i2c_get_clientdata(client);
  582. as3645a_set_control(flash, AS_MODE_EXT_TORCH, false);
  583. v4l2_flash_release(flash->vf);
  584. v4l2_flash_release(flash->vfind);
  585. led_classdev_flash_unregister(&flash->fled);
  586. led_classdev_unregister(&flash->iled_cdev);
  587. mutex_destroy(&flash->mutex);
  588. fwnode_handle_put(flash->flash_node);
  589. fwnode_handle_put(flash->indicator_node);
  590. return 0;
  591. }
  592. static const struct i2c_device_id as3645a_id_table[] = {
  593. { AS_NAME, 0 },
  594. { },
  595. };
  596. MODULE_DEVICE_TABLE(i2c, as3645a_id_table);
  597. static const struct of_device_id as3645a_of_table[] = {
  598. { .compatible = "ams,as3645a" },
  599. { },
  600. };
  601. MODULE_DEVICE_TABLE(of, as3645a_of_table);
  602. static struct i2c_driver as3645a_i2c_driver = {
  603. .driver = {
  604. .of_match_table = as3645a_of_table,
  605. .name = AS_NAME,
  606. },
  607. .probe_new = as3645a_probe,
  608. .remove = as3645a_remove,
  609. .id_table = as3645a_id_table,
  610. };
  611. module_i2c_driver(as3645a_i2c_driver);
  612. MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
  613. MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
  614. MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones");
  615. MODULE_LICENSE("GPL v2");