leds-mt6360.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. #include <linux/bitops.h>
  3. #include <linux/delay.h>
  4. #include <linux/init.h>
  5. #include <linux/interrupt.h>
  6. #include <linux/kernel.h>
  7. #include <linux/led-class-flash.h>
  8. #include <linux/led-class-multicolor.h>
  9. #include <linux/module.h>
  10. #include <linux/mutex.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/property.h>
  13. #include <linux/regmap.h>
  14. #include <media/v4l2-flash-led-class.h>
  15. enum {
  16. MT6360_LED_ISNK1 = 0,
  17. MT6360_LED_ISNK2,
  18. MT6360_LED_ISNK3,
  19. MT6360_LED_ISNKML,
  20. MT6360_LED_FLASH1,
  21. MT6360_LED_FLASH2,
  22. MT6360_MAX_LEDS
  23. };
  24. #define MT6360_REG_RGBEN 0x380
  25. #define MT6360_REG_ISNK(_led_no) (0x381 + (_led_no))
  26. #define MT6360_ISNK_ENMASK(_led_no) BIT(7 - (_led_no))
  27. #define MT6360_ISNK_MASK GENMASK(4, 0)
  28. #define MT6360_CHRINDSEL_MASK BIT(3)
  29. /* Virtual definition for multicolor */
  30. #define MT6360_VIRTUAL_MULTICOLOR (MT6360_MAX_LEDS + 1)
  31. #define MULTICOLOR_NUM_CHANNELS 3
  32. #define MT6360_REG_FLEDEN 0x37E
  33. #define MT6360_REG_STRBTO 0x373
  34. #define MT6360_REG_FLEDBASE(_id) (0x372 + 4 * (_id - MT6360_LED_FLASH1))
  35. #define MT6360_REG_FLEDISTRB(_id) (MT6360_REG_FLEDBASE(_id) + 2)
  36. #define MT6360_REG_FLEDITOR(_id) (MT6360_REG_FLEDBASE(_id) + 3)
  37. #define MT6360_REG_CHGSTAT2 0x3E1
  38. #define MT6360_REG_FLEDSTAT1 0x3E9
  39. #define MT6360_ITORCH_MASK GENMASK(4, 0)
  40. #define MT6360_ISTROBE_MASK GENMASK(6, 0)
  41. #define MT6360_STRBTO_MASK GENMASK(6, 0)
  42. #define MT6360_TORCHEN_MASK BIT(3)
  43. #define MT6360_STROBEN_MASK BIT(2)
  44. #define MT6360_FLCSEN_MASK(_id) BIT(MT6360_LED_FLASH2 - _id)
  45. #define MT6360_FLEDCHGVINOVP_MASK BIT(3)
  46. #define MT6360_FLED1STRBTO_MASK BIT(11)
  47. #define MT6360_FLED2STRBTO_MASK BIT(10)
  48. #define MT6360_FLED1STRB_MASK BIT(9)
  49. #define MT6360_FLED2STRB_MASK BIT(8)
  50. #define MT6360_FLED1SHORT_MASK BIT(7)
  51. #define MT6360_FLED2SHORT_MASK BIT(6)
  52. #define MT6360_FLEDLVF_MASK BIT(3)
  53. #define MT6360_ISNKRGB_STEPUA 2000
  54. #define MT6360_ISNKRGB_MAXUA 24000
  55. #define MT6360_ISNKML_STEPUA 5000
  56. #define MT6360_ISNKML_MAXUA 150000
  57. #define MT6360_ITORCH_MINUA 25000
  58. #define MT6360_ITORCH_STEPUA 12500
  59. #define MT6360_ITORCH_MAXUA 400000
  60. #define MT6360_ISTRB_MINUA 50000
  61. #define MT6360_ISTRB_STEPUA 12500
  62. #define MT6360_ISTRB_MAXUA 1500000
  63. #define MT6360_STRBTO_MINUS 64000
  64. #define MT6360_STRBTO_STEPUS 32000
  65. #define MT6360_STRBTO_MAXUS 2432000
  66. struct mt6360_led {
  67. union {
  68. struct led_classdev isnk;
  69. struct led_classdev_mc mc;
  70. struct led_classdev_flash flash;
  71. };
  72. struct v4l2_flash *v4l2_flash;
  73. struct mt6360_priv *priv;
  74. u32 led_no;
  75. enum led_default_state default_state;
  76. };
  77. struct mt6360_priv {
  78. struct device *dev;
  79. struct regmap *regmap;
  80. struct mutex lock;
  81. unsigned int fled_strobe_used;
  82. unsigned int fled_torch_used;
  83. unsigned int leds_active;
  84. unsigned int leds_count;
  85. struct mt6360_led leds[] __counted_by(leds_count);
  86. };
  87. static int mt6360_mc_brightness_set(struct led_classdev *lcdev,
  88. enum led_brightness level)
  89. {
  90. struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev);
  91. struct mt6360_led *led = container_of(mccdev, struct mt6360_led, mc);
  92. struct mt6360_priv *priv = led->priv;
  93. u32 real_bright, enable_mask = 0, enable = 0;
  94. int i, ret;
  95. mutex_lock(&priv->lock);
  96. led_mc_calc_color_components(mccdev, level);
  97. for (i = 0; i < mccdev->num_colors; i++) {
  98. struct mc_subled *subled = mccdev->subled_info + i;
  99. real_bright = min(lcdev->max_brightness, subled->brightness);
  100. ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(i),
  101. MT6360_ISNK_MASK, real_bright);
  102. if (ret)
  103. goto out;
  104. enable_mask |= MT6360_ISNK_ENMASK(subled->channel);
  105. if (real_bright)
  106. enable |= MT6360_ISNK_ENMASK(subled->channel);
  107. }
  108. ret = regmap_update_bits(priv->regmap, MT6360_REG_RGBEN, enable_mask,
  109. enable);
  110. out:
  111. mutex_unlock(&priv->lock);
  112. return ret;
  113. }
  114. static int mt6360_isnk_brightness_set(struct led_classdev *lcdev,
  115. enum led_brightness level)
  116. {
  117. struct mt6360_led *led = container_of(lcdev, struct mt6360_led, isnk);
  118. struct mt6360_priv *priv = led->priv;
  119. u32 enable_mask = MT6360_ISNK_ENMASK(led->led_no);
  120. u32 val = level ? MT6360_ISNK_ENMASK(led->led_no) : 0;
  121. int ret;
  122. mutex_lock(&priv->lock);
  123. ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(led->led_no),
  124. MT6360_ISNK_MASK, level);
  125. if (ret)
  126. goto out;
  127. ret = regmap_update_bits(priv->regmap, MT6360_REG_RGBEN, enable_mask,
  128. val);
  129. out:
  130. mutex_unlock(&priv->lock);
  131. return ret;
  132. }
  133. static int mt6360_torch_brightness_set(struct led_classdev *lcdev,
  134. enum led_brightness level)
  135. {
  136. struct mt6360_led *led =
  137. container_of(lcdev, struct mt6360_led, flash.led_cdev);
  138. struct mt6360_priv *priv = led->priv;
  139. u32 enable_mask = MT6360_TORCHEN_MASK | MT6360_FLCSEN_MASK(led->led_no);
  140. u32 val = level ? MT6360_FLCSEN_MASK(led->led_no) : 0;
  141. u32 prev = priv->fled_torch_used, curr;
  142. int ret;
  143. mutex_lock(&priv->lock);
  144. /*
  145. * Only one set of flash control logic, use the flag to avoid strobe is
  146. * currently used.
  147. */
  148. if (priv->fled_strobe_used) {
  149. dev_warn(lcdev->dev, "Please disable strobe first [%d]\n",
  150. priv->fled_strobe_used);
  151. ret = -EBUSY;
  152. goto unlock;
  153. }
  154. if (level)
  155. curr = prev | BIT(led->led_no);
  156. else
  157. curr = prev & ~BIT(led->led_no);
  158. if (curr)
  159. val |= MT6360_TORCHEN_MASK;
  160. if (level) {
  161. ret = regmap_update_bits(priv->regmap,
  162. MT6360_REG_FLEDITOR(led->led_no),
  163. MT6360_ITORCH_MASK, level - 1);
  164. if (ret)
  165. goto unlock;
  166. }
  167. ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, enable_mask,
  168. val);
  169. if (ret)
  170. goto unlock;
  171. priv->fled_torch_used = curr;
  172. unlock:
  173. mutex_unlock(&priv->lock);
  174. return ret;
  175. }
  176. static int mt6360_flash_brightness_set(struct led_classdev_flash *fl_cdev,
  177. u32 brightness)
  178. {
  179. /*
  180. * Due to the current spike when turning on flash, let brightness to be
  181. * kept by framework.
  182. * This empty function is used to prevent led_classdev_flash register
  183. * ops check failure.
  184. */
  185. return 0;
  186. }
  187. static int _mt6360_flash_brightness_set(struct led_classdev_flash *fl_cdev,
  188. u32 brightness)
  189. {
  190. struct mt6360_led *led =
  191. container_of(fl_cdev, struct mt6360_led, flash);
  192. struct mt6360_priv *priv = led->priv;
  193. struct led_flash_setting *s = &fl_cdev->brightness;
  194. u32 val = (brightness - s->min) / s->step;
  195. return regmap_update_bits(priv->regmap,
  196. MT6360_REG_FLEDISTRB(led->led_no),
  197. MT6360_ISTROBE_MASK, val);
  198. }
  199. static int mt6360_strobe_set(struct led_classdev_flash *fl_cdev, bool state)
  200. {
  201. struct mt6360_led *led =
  202. container_of(fl_cdev, struct mt6360_led, flash);
  203. struct mt6360_priv *priv = led->priv;
  204. struct led_classdev *lcdev = &fl_cdev->led_cdev;
  205. struct led_flash_setting *s = &fl_cdev->brightness;
  206. u32 enable_mask = MT6360_STROBEN_MASK | MT6360_FLCSEN_MASK(led->led_no);
  207. u32 val = state ? MT6360_FLCSEN_MASK(led->led_no) : 0;
  208. u32 prev = priv->fled_strobe_used, curr;
  209. int ret = 0;
  210. mutex_lock(&priv->lock);
  211. /*
  212. * If the state of the upcoming change is the same as the current LED
  213. * device state, then skip the subsequent code to avoid conflict
  214. * with the flow of turning on LED torch mode in V4L2.
  215. */
  216. if (state == !!(BIT(led->led_no) & prev)) {
  217. dev_info(lcdev->dev, "No change in strobe state [0x%x]\n", prev);
  218. goto unlock;
  219. }
  220. /*
  221. * Only one set of flash control logic, use the flag to avoid torch is
  222. * currently used
  223. */
  224. if (priv->fled_torch_used) {
  225. dev_warn(lcdev->dev, "Please disable torch first [0x%x]\n",
  226. priv->fled_torch_used);
  227. ret = -EBUSY;
  228. goto unlock;
  229. }
  230. if (state)
  231. curr = prev | BIT(led->led_no);
  232. else
  233. curr = prev & ~BIT(led->led_no);
  234. if (curr)
  235. val |= MT6360_STROBEN_MASK;
  236. ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, enable_mask,
  237. val);
  238. if (ret) {
  239. dev_err(lcdev->dev, "[%d] control current source %d fail\n",
  240. led->led_no, state);
  241. goto unlock;
  242. }
  243. /*
  244. * If the flash need to be on, config the flash current ramping up to
  245. * the setting value.
  246. * Else, always recover back to the minimum one
  247. */
  248. ret = _mt6360_flash_brightness_set(fl_cdev, state ? s->val : s->min);
  249. if (ret)
  250. goto unlock;
  251. /*
  252. * For the flash turn on/off, HW rampping up/down time is 5ms/500us,
  253. * respectively.
  254. */
  255. if (!prev && curr)
  256. usleep_range(5000, 6000);
  257. else if (prev && !curr)
  258. udelay(500);
  259. priv->fled_strobe_used = curr;
  260. unlock:
  261. mutex_unlock(&priv->lock);
  262. return ret;
  263. }
  264. static int mt6360_strobe_get(struct led_classdev_flash *fl_cdev, bool *state)
  265. {
  266. struct mt6360_led *led =
  267. container_of(fl_cdev, struct mt6360_led, flash);
  268. struct mt6360_priv *priv = led->priv;
  269. mutex_lock(&priv->lock);
  270. *state = !!(priv->fled_strobe_used & BIT(led->led_no));
  271. mutex_unlock(&priv->lock);
  272. return 0;
  273. }
  274. static int mt6360_timeout_set(struct led_classdev_flash *fl_cdev, u32 timeout)
  275. {
  276. struct mt6360_led *led =
  277. container_of(fl_cdev, struct mt6360_led, flash);
  278. struct mt6360_priv *priv = led->priv;
  279. struct led_flash_setting *s = &fl_cdev->timeout;
  280. u32 val = (timeout - s->min) / s->step;
  281. int ret;
  282. mutex_lock(&priv->lock);
  283. ret = regmap_update_bits(priv->regmap, MT6360_REG_STRBTO,
  284. MT6360_STRBTO_MASK, val);
  285. mutex_unlock(&priv->lock);
  286. return ret;
  287. }
  288. static int mt6360_fault_get(struct led_classdev_flash *fl_cdev, u32 *fault)
  289. {
  290. struct mt6360_led *led =
  291. container_of(fl_cdev, struct mt6360_led, flash);
  292. struct mt6360_priv *priv = led->priv;
  293. u16 fled_stat;
  294. unsigned int chg_stat, strobe_timeout_mask, fled_short_mask;
  295. u32 rfault = 0;
  296. int ret;
  297. mutex_lock(&priv->lock);
  298. ret = regmap_read(priv->regmap, MT6360_REG_CHGSTAT2, &chg_stat);
  299. if (ret)
  300. goto unlock;
  301. ret = regmap_raw_read(priv->regmap, MT6360_REG_FLEDSTAT1, &fled_stat,
  302. sizeof(fled_stat));
  303. if (ret)
  304. goto unlock;
  305. if (led->led_no == MT6360_LED_FLASH1) {
  306. strobe_timeout_mask = MT6360_FLED1STRBTO_MASK;
  307. fled_short_mask = MT6360_FLED1SHORT_MASK;
  308. } else {
  309. strobe_timeout_mask = MT6360_FLED2STRBTO_MASK;
  310. fled_short_mask = MT6360_FLED2SHORT_MASK;
  311. }
  312. if (chg_stat & MT6360_FLEDCHGVINOVP_MASK)
  313. rfault |= LED_FAULT_INPUT_VOLTAGE;
  314. if (fled_stat & strobe_timeout_mask)
  315. rfault |= LED_FAULT_TIMEOUT;
  316. if (fled_stat & fled_short_mask)
  317. rfault |= LED_FAULT_SHORT_CIRCUIT;
  318. if (fled_stat & MT6360_FLEDLVF_MASK)
  319. rfault |= LED_FAULT_UNDER_VOLTAGE;
  320. *fault = rfault;
  321. unlock:
  322. mutex_unlock(&priv->lock);
  323. return ret;
  324. }
  325. static const struct led_flash_ops mt6360_flash_ops = {
  326. .flash_brightness_set = mt6360_flash_brightness_set,
  327. .strobe_set = mt6360_strobe_set,
  328. .strobe_get = mt6360_strobe_get,
  329. .timeout_set = mt6360_timeout_set,
  330. .fault_get = mt6360_fault_get,
  331. };
  332. static int mt6360_isnk_init_default_state(struct mt6360_led *led)
  333. {
  334. struct mt6360_priv *priv = led->priv;
  335. unsigned int regval;
  336. u32 level;
  337. int ret;
  338. ret = regmap_read(priv->regmap, MT6360_REG_ISNK(led->led_no), &regval);
  339. if (ret)
  340. return ret;
  341. level = regval & MT6360_ISNK_MASK;
  342. ret = regmap_read(priv->regmap, MT6360_REG_RGBEN, &regval);
  343. if (ret)
  344. return ret;
  345. if (!(regval & MT6360_ISNK_ENMASK(led->led_no)))
  346. level = LED_OFF;
  347. switch (led->default_state) {
  348. case LEDS_DEFSTATE_ON:
  349. led->isnk.brightness = led->isnk.max_brightness;
  350. break;
  351. case LEDS_DEFSTATE_KEEP:
  352. led->isnk.brightness = min(level, led->isnk.max_brightness);
  353. break;
  354. default:
  355. led->isnk.brightness = LED_OFF;
  356. }
  357. return mt6360_isnk_brightness_set(&led->isnk, led->isnk.brightness);
  358. }
  359. static int mt6360_flash_init_default_state(struct mt6360_led *led)
  360. {
  361. struct led_classdev_flash *flash = &led->flash;
  362. struct mt6360_priv *priv = led->priv;
  363. u32 enable_mask = MT6360_TORCHEN_MASK | MT6360_FLCSEN_MASK(led->led_no);
  364. u32 level;
  365. unsigned int regval;
  366. int ret;
  367. ret = regmap_read(priv->regmap, MT6360_REG_FLEDITOR(led->led_no),
  368. &regval);
  369. if (ret)
  370. return ret;
  371. level = regval & MT6360_ITORCH_MASK;
  372. ret = regmap_read(priv->regmap, MT6360_REG_FLEDEN, &regval);
  373. if (ret)
  374. return ret;
  375. if ((regval & enable_mask) == enable_mask)
  376. level += 1;
  377. else
  378. level = LED_OFF;
  379. switch (led->default_state) {
  380. case LEDS_DEFSTATE_ON:
  381. flash->led_cdev.brightness = flash->led_cdev.max_brightness;
  382. break;
  383. case LEDS_DEFSTATE_KEEP:
  384. flash->led_cdev.brightness =
  385. min(level, flash->led_cdev.max_brightness);
  386. break;
  387. default:
  388. flash->led_cdev.brightness = LED_OFF;
  389. }
  390. return mt6360_torch_brightness_set(&flash->led_cdev,
  391. flash->led_cdev.brightness);
  392. }
  393. #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
  394. static int mt6360_flash_external_strobe_set(struct v4l2_flash *v4l2_flash,
  395. bool enable)
  396. {
  397. struct led_classdev_flash *flash = v4l2_flash->fled_cdev;
  398. struct mt6360_led *led = container_of(flash, struct mt6360_led, flash);
  399. struct mt6360_priv *priv = led->priv;
  400. u32 mask = MT6360_FLCSEN_MASK(led->led_no);
  401. u32 val = enable ? mask : 0;
  402. int ret;
  403. mutex_lock(&priv->lock);
  404. ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, mask, val);
  405. if (ret)
  406. goto unlock;
  407. if (enable)
  408. priv->fled_strobe_used |= BIT(led->led_no);
  409. else
  410. priv->fled_strobe_used &= ~BIT(led->led_no);
  411. unlock:
  412. mutex_unlock(&priv->lock);
  413. return ret;
  414. }
  415. static const struct v4l2_flash_ops v4l2_flash_ops = {
  416. .external_strobe_set = mt6360_flash_external_strobe_set,
  417. };
  418. static void mt6360_init_v4l2_flash_config(struct mt6360_led *led,
  419. struct v4l2_flash_config *config)
  420. {
  421. struct led_classdev *lcdev;
  422. struct led_flash_setting *s = &config->intensity;
  423. lcdev = &led->flash.led_cdev;
  424. s->min = MT6360_ITORCH_MINUA;
  425. s->step = MT6360_ITORCH_STEPUA;
  426. s->val = s->max = s->min + (lcdev->max_brightness - 1) * s->step;
  427. config->has_external_strobe = 1;
  428. strscpy(config->dev_name, lcdev->dev->kobj.name,
  429. sizeof(config->dev_name));
  430. config->flash_faults = LED_FAULT_SHORT_CIRCUIT | LED_FAULT_TIMEOUT |
  431. LED_FAULT_INPUT_VOLTAGE |
  432. LED_FAULT_UNDER_VOLTAGE;
  433. }
  434. #else
  435. static const struct v4l2_flash_ops v4l2_flash_ops;
  436. static void mt6360_init_v4l2_flash_config(struct mt6360_led *led,
  437. struct v4l2_flash_config *config)
  438. {
  439. }
  440. #endif
  441. static int mt6360_led_register(struct device *parent, struct mt6360_led *led,
  442. struct led_init_data *init_data)
  443. {
  444. struct mt6360_priv *priv = led->priv;
  445. struct v4l2_flash_config v4l2_config = {0};
  446. int ret;
  447. if ((led->led_no == MT6360_LED_ISNK1 ||
  448. led->led_no == MT6360_VIRTUAL_MULTICOLOR) &&
  449. (priv->leds_active & BIT(MT6360_LED_ISNK1))) {
  450. /*
  451. * Change isink1 to SW control mode, disconnect it with
  452. * charger state
  453. */
  454. ret = regmap_update_bits(priv->regmap, MT6360_REG_RGBEN,
  455. MT6360_CHRINDSEL_MASK,
  456. MT6360_CHRINDSEL_MASK);
  457. if (ret) {
  458. dev_err(parent, "Failed to config ISNK1 to SW mode\n");
  459. return ret;
  460. }
  461. }
  462. switch (led->led_no) {
  463. case MT6360_VIRTUAL_MULTICOLOR:
  464. ret = mt6360_mc_brightness_set(&led->mc.led_cdev, LED_OFF);
  465. if (ret) {
  466. dev_err(parent,
  467. "Failed to init multicolor brightness\n");
  468. return ret;
  469. }
  470. ret = devm_led_classdev_multicolor_register_ext(parent,
  471. &led->mc, init_data);
  472. if (ret) {
  473. dev_err(parent, "Couldn't register multicolor\n");
  474. return ret;
  475. }
  476. break;
  477. case MT6360_LED_ISNK1 ... MT6360_LED_ISNKML:
  478. ret = mt6360_isnk_init_default_state(led);
  479. if (ret) {
  480. dev_err(parent, "Failed to init %d isnk state\n",
  481. led->led_no);
  482. return ret;
  483. }
  484. ret = devm_led_classdev_register_ext(parent, &led->isnk,
  485. init_data);
  486. if (ret) {
  487. dev_err(parent, "Couldn't register isink %d\n",
  488. led->led_no);
  489. return ret;
  490. }
  491. break;
  492. default:
  493. ret = mt6360_flash_init_default_state(led);
  494. if (ret) {
  495. dev_err(parent, "Failed to init %d flash state\n",
  496. led->led_no);
  497. return ret;
  498. }
  499. ret = devm_led_classdev_flash_register_ext(parent, &led->flash,
  500. init_data);
  501. if (ret) {
  502. dev_err(parent, "Couldn't register flash %d\n",
  503. led->led_no);
  504. return ret;
  505. }
  506. mt6360_init_v4l2_flash_config(led, &v4l2_config);
  507. led->v4l2_flash = v4l2_flash_init(parent, init_data->fwnode,
  508. &led->flash,
  509. &v4l2_flash_ops,
  510. &v4l2_config);
  511. if (IS_ERR(led->v4l2_flash)) {
  512. dev_err(parent, "Failed to register %d v4l2 sd\n",
  513. led->led_no);
  514. return PTR_ERR(led->v4l2_flash);
  515. }
  516. }
  517. return 0;
  518. }
  519. static u32 clamp_align(u32 val, u32 min, u32 max, u32 step)
  520. {
  521. u32 retval;
  522. retval = clamp_val(val, min, max);
  523. if (step > 1)
  524. retval = rounddown(retval - min, step) + min;
  525. return retval;
  526. }
  527. static int mt6360_init_isnk_properties(struct mt6360_led *led,
  528. struct led_init_data *init_data)
  529. {
  530. struct led_classdev *lcdev;
  531. struct mt6360_priv *priv = led->priv;
  532. struct fwnode_handle *child;
  533. u32 step_uA = MT6360_ISNKRGB_STEPUA, max_uA = MT6360_ISNKRGB_MAXUA;
  534. u32 val;
  535. int num_color = 0, ret;
  536. if (led->led_no == MT6360_VIRTUAL_MULTICOLOR) {
  537. struct mc_subled *sub_led;
  538. sub_led = devm_kzalloc(priv->dev,
  539. sizeof(*sub_led) * MULTICOLOR_NUM_CHANNELS, GFP_KERNEL);
  540. if (!sub_led)
  541. return -ENOMEM;
  542. fwnode_for_each_child_node(init_data->fwnode, child) {
  543. u32 reg, color;
  544. ret = fwnode_property_read_u32(child, "reg", &reg);
  545. if (ret || reg > MT6360_LED_ISNK3 ||
  546. priv->leds_active & BIT(reg)) {
  547. fwnode_handle_put(child);
  548. return -EINVAL;
  549. }
  550. ret = fwnode_property_read_u32(child, "color", &color);
  551. if (ret) {
  552. dev_err(priv->dev,
  553. "led %d, no color specified\n",
  554. led->led_no);
  555. fwnode_handle_put(child);
  556. return ret;
  557. }
  558. priv->leds_active |= BIT(reg);
  559. sub_led[num_color].color_index = color;
  560. sub_led[num_color].channel = reg;
  561. num_color++;
  562. }
  563. if (num_color < 2) {
  564. dev_err(priv->dev,
  565. "Multicolor must include 2 or more led channel\n");
  566. return -EINVAL;
  567. }
  568. led->mc.num_colors = num_color;
  569. led->mc.subled_info = sub_led;
  570. lcdev = &led->mc.led_cdev;
  571. lcdev->brightness_set_blocking = mt6360_mc_brightness_set;
  572. } else {
  573. if (led->led_no == MT6360_LED_ISNKML) {
  574. step_uA = MT6360_ISNKML_STEPUA;
  575. max_uA = MT6360_ISNKML_MAXUA;
  576. }
  577. lcdev = &led->isnk;
  578. lcdev->brightness_set_blocking = mt6360_isnk_brightness_set;
  579. }
  580. ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp",
  581. &val);
  582. if (ret) {
  583. dev_warn(priv->dev,
  584. "Not specified led-max-microamp, config to the minimum\n");
  585. val = step_uA;
  586. } else
  587. val = clamp_align(val, 0, max_uA, step_uA);
  588. lcdev->max_brightness = val / step_uA;
  589. fwnode_property_read_string(init_data->fwnode, "linux,default-trigger",
  590. &lcdev->default_trigger);
  591. return 0;
  592. }
  593. static int mt6360_init_flash_properties(struct mt6360_led *led,
  594. struct led_init_data *init_data)
  595. {
  596. struct led_classdev_flash *flash = &led->flash;
  597. struct led_classdev *lcdev = &flash->led_cdev;
  598. struct mt6360_priv *priv = led->priv;
  599. struct led_flash_setting *s;
  600. u32 val;
  601. int ret;
  602. ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp",
  603. &val);
  604. if (ret) {
  605. dev_warn(priv->dev,
  606. "Not specified led-max-microamp, config to the minimum\n");
  607. val = MT6360_ITORCH_MINUA;
  608. } else
  609. val = clamp_align(val, MT6360_ITORCH_MINUA, MT6360_ITORCH_MAXUA,
  610. MT6360_ITORCH_STEPUA);
  611. lcdev->max_brightness =
  612. (val - MT6360_ITORCH_MINUA) / MT6360_ITORCH_STEPUA + 1;
  613. lcdev->brightness_set_blocking = mt6360_torch_brightness_set;
  614. lcdev->flags |= LED_DEV_CAP_FLASH;
  615. ret = fwnode_property_read_u32(init_data->fwnode, "flash-max-microamp",
  616. &val);
  617. if (ret) {
  618. dev_warn(priv->dev,
  619. "Not specified flash-max-microamp, config to the minimum\n");
  620. val = MT6360_ISTRB_MINUA;
  621. } else
  622. val = clamp_align(val, MT6360_ISTRB_MINUA, MT6360_ISTRB_MAXUA,
  623. MT6360_ISTRB_STEPUA);
  624. s = &flash->brightness;
  625. s->min = MT6360_ISTRB_MINUA;
  626. s->step = MT6360_ISTRB_STEPUA;
  627. s->val = s->max = val;
  628. /*
  629. * Always configure as min level when off to prevent flash current
  630. * spike.
  631. */
  632. ret = _mt6360_flash_brightness_set(flash, s->min);
  633. if (ret)
  634. return ret;
  635. ret = fwnode_property_read_u32(init_data->fwnode,
  636. "flash-max-timeout-us", &val);
  637. if (ret) {
  638. dev_warn(priv->dev,
  639. "Not specified flash-max-timeout-us, config to the minimum\n");
  640. val = MT6360_STRBTO_MINUS;
  641. } else
  642. val = clamp_align(val, MT6360_STRBTO_MINUS, MT6360_STRBTO_MAXUS,
  643. MT6360_STRBTO_STEPUS);
  644. s = &flash->timeout;
  645. s->min = MT6360_STRBTO_MINUS;
  646. s->step = MT6360_STRBTO_STEPUS;
  647. s->val = s->max = val;
  648. flash->ops = &mt6360_flash_ops;
  649. return 0;
  650. }
  651. static void mt6360_v4l2_flash_release(struct mt6360_priv *priv)
  652. {
  653. int i;
  654. for (i = 0; i < priv->leds_count; i++) {
  655. struct mt6360_led *led = priv->leds + i;
  656. if (led->v4l2_flash)
  657. v4l2_flash_release(led->v4l2_flash);
  658. }
  659. }
  660. static int mt6360_led_probe(struct platform_device *pdev)
  661. {
  662. struct mt6360_priv *priv;
  663. size_t count;
  664. int i = 0, ret;
  665. count = device_get_child_node_count(&pdev->dev);
  666. if (!count || count > MT6360_MAX_LEDS) {
  667. dev_err(&pdev->dev,
  668. "No child node or node count over max led number %zu\n",
  669. count);
  670. return -EINVAL;
  671. }
  672. priv = devm_kzalloc(&pdev->dev,
  673. struct_size(priv, leds, count), GFP_KERNEL);
  674. if (!priv)
  675. return -ENOMEM;
  676. priv->leds_count = count;
  677. priv->dev = &pdev->dev;
  678. mutex_init(&priv->lock);
  679. priv->regmap = dev_get_regmap(pdev->dev.parent, NULL);
  680. if (!priv->regmap) {
  681. dev_err(&pdev->dev, "Failed to get parent regmap\n");
  682. return -ENODEV;
  683. }
  684. device_for_each_child_node_scoped(&pdev->dev, child) {
  685. struct mt6360_led *led = priv->leds + i;
  686. struct led_init_data init_data = { .fwnode = child, };
  687. u32 reg, led_color;
  688. ret = fwnode_property_read_u32(child, "color", &led_color);
  689. if (ret)
  690. goto out_flash_release;
  691. if (led_color == LED_COLOR_ID_RGB ||
  692. led_color == LED_COLOR_ID_MULTI)
  693. reg = MT6360_VIRTUAL_MULTICOLOR;
  694. else {
  695. ret = fwnode_property_read_u32(child, "reg", &reg);
  696. if (ret)
  697. goto out_flash_release;
  698. if (reg >= MT6360_MAX_LEDS) {
  699. ret = -EINVAL;
  700. goto out_flash_release;
  701. }
  702. }
  703. if (priv->leds_active & BIT(reg)) {
  704. ret = -EINVAL;
  705. goto out_flash_release;
  706. }
  707. priv->leds_active |= BIT(reg);
  708. led->led_no = reg;
  709. led->priv = priv;
  710. led->default_state = led_init_default_state_get(child);
  711. if (reg == MT6360_VIRTUAL_MULTICOLOR ||
  712. reg <= MT6360_LED_ISNKML)
  713. ret = mt6360_init_isnk_properties(led, &init_data);
  714. else
  715. ret = mt6360_init_flash_properties(led, &init_data);
  716. if (ret)
  717. goto out_flash_release;
  718. ret = mt6360_led_register(&pdev->dev, led, &init_data);
  719. if (ret)
  720. goto out_flash_release;
  721. i++;
  722. }
  723. platform_set_drvdata(pdev, priv);
  724. return 0;
  725. out_flash_release:
  726. mt6360_v4l2_flash_release(priv);
  727. return ret;
  728. }
  729. static void mt6360_led_remove(struct platform_device *pdev)
  730. {
  731. struct mt6360_priv *priv = platform_get_drvdata(pdev);
  732. mt6360_v4l2_flash_release(priv);
  733. }
  734. static const struct of_device_id __maybe_unused mt6360_led_of_id[] = {
  735. { .compatible = "mediatek,mt6360-led", },
  736. {}
  737. };
  738. MODULE_DEVICE_TABLE(of, mt6360_led_of_id);
  739. static struct platform_driver mt6360_led_driver = {
  740. .driver = {
  741. .name = "mt6360-led",
  742. .of_match_table = mt6360_led_of_id,
  743. },
  744. .probe = mt6360_led_probe,
  745. .remove_new = mt6360_led_remove,
  746. };
  747. module_platform_driver(mt6360_led_driver);
  748. MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
  749. MODULE_DESCRIPTION("MT6360 LED Driver");
  750. MODULE_LICENSE("GPL v2");