leds-mt6360.c 22 KB

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