leds.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. /*
  2. *
  3. *
  4. * This file is subject to the terms and conditions of the GNU General Public
  5. * License. See the file COPYING in the main directory of this archive for
  6. * more details.
  7. *
  8. * mt65xx leds driver
  9. *
  10. */
  11. #include <linux/module.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/delay.h>
  14. #include <linux/string.h>
  15. #include <linux/ctype.h>
  16. #include <linux/leds.h>
  17. #include <linux/of.h>
  18. /* #include <linux/leds-mt65xx.h> */
  19. #include <linux/workqueue.h>
  20. #include <linux/wakelock.h>
  21. #include <linux/slab.h>
  22. #include <linux/delay.h>
  23. /* #include <mach/mt_pwm.h>
  24. #include <mach/upmu_common_sw.h>
  25. #include <mach/upmu_common.h>
  26. #include <mach/upmu_sw.h>
  27. #include <mach/upmu_hw.h>*/
  28. #ifdef CONFIG_MTK_AAL_SUPPORT
  29. #include <ddp_aal.h>
  30. /* #include <linux/aee.h> */
  31. #endif
  32. #include <mt-plat/mt_pwm.h>
  33. #include <mt-plat/upmu_common.h>
  34. #include "leds_sw.h"
  35. #include "leds_hal.h"
  36. #include "ddp_pwm.h"
  37. #include "mtkfb.h"
  38. /* for LED&Backlight bringup, define the dummy API */
  39. #ifndef CONFIG_MTK_PMIC
  40. u16 pmic_set_register_value(u32 flagname, u32 val)
  41. {
  42. return 0;
  43. }
  44. #endif
  45. #ifndef CONFIG_MTK_PWM
  46. s32 pwm_set_spec_config(struct pwm_spec_config *conf)
  47. {
  48. return 0;
  49. }
  50. void mt_pwm_disable(u32 pwm_no, u8 pmic_pad)
  51. {
  52. }
  53. #endif
  54. static DEFINE_MUTEX(leds_mutex);
  55. static DEFINE_MUTEX(leds_pmic_mutex);
  56. /****************************************************************************
  57. * variables
  58. ***************************************************************************/
  59. /* struct cust_mt65xx_led* bl_setting_hal = NULL; */
  60. static unsigned int bl_brightness_hal = 102;
  61. static unsigned int bl_duty_hal = 21;
  62. static unsigned int bl_div_hal = CLK_DIV1;
  63. static unsigned int bl_frequency_hal = 32000;
  64. /* for button led don't do ISINK disable first time */
  65. static int button_flag_isink0;
  66. static int button_flag_isink1;
  67. static int button_flag_isink2;
  68. static int button_flag_isink3;
  69. struct wake_lock leds_suspend_lock;
  70. char *leds_name[MT65XX_LED_TYPE_TOTAL] = {
  71. "red",
  72. "green",
  73. "blue",
  74. "jogball-backlight",
  75. "keyboard-backlight",
  76. "button-backlight",
  77. "lcd-backlight",
  78. };
  79. struct cust_mt65xx_led *pled_dtsi = NULL;
  80. /****************************************************************************
  81. * DEBUG MACROS
  82. ***************************************************************************/
  83. static int debug_enable_led_hal = 1;
  84. #define LEDS_DEBUG(format, args...) do { \
  85. if (debug_enable_led_hal) { \
  86. pr_debug("[LED]"format, ##args);\
  87. } \
  88. } while (0)
  89. /*****************PWM *************************************************/
  90. #define PWM_DIV_NUM 8
  91. static int time_array_hal[PWM_DIV_NUM] = {
  92. 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 };
  93. static unsigned int div_array_hal[PWM_DIV_NUM] = {
  94. 1, 2, 4, 8, 16, 32, 64, 128 };
  95. static unsigned int backlight_PWM_div_hal = CLK_DIV1; /* this para come from cust_leds. */
  96. /****************************************************************************
  97. * func:return global variables
  98. ***************************************************************************/
  99. void mt_leds_wake_lock_init(void)
  100. {
  101. wake_lock_init(&leds_suspend_lock, WAKE_LOCK_SUSPEND, "leds wakelock");
  102. }
  103. unsigned int mt_get_bl_brightness(void)
  104. {
  105. return bl_brightness_hal;
  106. }
  107. unsigned int mt_get_bl_duty(void)
  108. {
  109. return bl_duty_hal;
  110. }
  111. unsigned int mt_get_bl_div(void)
  112. {
  113. return bl_div_hal;
  114. }
  115. unsigned int mt_get_bl_frequency(void)
  116. {
  117. return bl_frequency_hal;
  118. }
  119. unsigned int *mt_get_div_array(void)
  120. {
  121. return &div_array_hal[0];
  122. }
  123. void mt_set_bl_duty(unsigned int level)
  124. {
  125. bl_duty_hal = level;
  126. }
  127. void mt_set_bl_div(unsigned int div)
  128. {
  129. bl_div_hal = div;
  130. }
  131. void mt_set_bl_frequency(unsigned int freq)
  132. {
  133. bl_frequency_hal = freq;
  134. }
  135. struct cust_mt65xx_led *get_cust_led_dtsi(void)
  136. {
  137. struct device_node *led_node = NULL;
  138. bool isSupportDTS = false;
  139. int i, ret;
  140. int mode, data;
  141. int pwm_config[5] = { 0 };
  142. /*LEDS_DEBUG("get_cust_led_dtsi: get the leds info from device tree\n");*/
  143. if (pled_dtsi == NULL) {
  144. /* this can allocat an new struct array */
  145. pled_dtsi = kmalloc(MT65XX_LED_TYPE_TOTAL *
  146. sizeof(struct
  147. cust_mt65xx_led),
  148. GFP_KERNEL);
  149. if (pled_dtsi == NULL) {
  150. LEDS_DEBUG("get_cust_led_dtsi kmalloc fail\n");
  151. goto out;
  152. }
  153. for (i = 0; i < MT65XX_LED_TYPE_TOTAL; i++) {
  154. char node_name[32] = "mediatek,";
  155. pled_dtsi[i].name = leds_name[i];
  156. led_node =
  157. of_find_compatible_node(NULL, NULL,
  158. strcat(node_name,
  159. leds_name[i]));
  160. if (!led_node) {
  161. LEDS_DEBUG("Cannot find LED node from dts\n");
  162. pled_dtsi[i].mode = 0;
  163. pled_dtsi[i].data = -1;
  164. } else {
  165. isSupportDTS = true;
  166. ret =
  167. of_property_read_u32(led_node, "led_mode",
  168. &mode);
  169. if (!ret) {
  170. pled_dtsi[i].mode = mode;
  171. LEDS_DEBUG
  172. ("The %s's led mode is : %d\n",
  173. pled_dtsi[i].name,
  174. pled_dtsi[i].mode);
  175. } else {
  176. LEDS_DEBUG
  177. ("led dts can not get led mode");
  178. pled_dtsi[i].mode = 0;
  179. }
  180. ret =
  181. of_property_read_u32(led_node, "data",
  182. &data);
  183. if (!ret) {
  184. pled_dtsi[i].data = data;
  185. LEDS_DEBUG
  186. ("The %s's led data is : %ld\n",
  187. pled_dtsi[i].name,
  188. pled_dtsi[i].data);
  189. } else {
  190. LEDS_DEBUG
  191. ("led dts can not get led data");
  192. pled_dtsi[i].data = -1;
  193. }
  194. ret =
  195. of_property_read_u32_array(led_node,
  196. "pwm_config",
  197. pwm_config,
  198. ARRAY_SIZE
  199. (pwm_config));
  200. if (!ret) {
  201. LEDS_DEBUG
  202. ("The %s's pwm config data is %d %d %d %d %d\n",
  203. pled_dtsi[i].name, pwm_config[0],
  204. pwm_config[1], pwm_config[2],
  205. pwm_config[3], pwm_config[4]);
  206. pled_dtsi[i].config_data.clock_source =
  207. pwm_config[0];
  208. pled_dtsi[i].config_data.div =
  209. pwm_config[1];
  210. pled_dtsi[i].config_data.low_duration =
  211. pwm_config[2];
  212. pled_dtsi[i].config_data.High_duration =
  213. pwm_config[3];
  214. pled_dtsi[i].config_data.pmic_pad =
  215. pwm_config[4];
  216. } else
  217. LEDS_DEBUG
  218. ("led dts can not get pwm config data.\n");
  219. switch (pled_dtsi[i].mode) {
  220. case MT65XX_LED_MODE_CUST_LCM:
  221. pled_dtsi[i].data =
  222. (long)mtkfb_set_backlight_level;
  223. LEDS_DEBUG
  224. ("kernel:the backlight hw mode is LCM.\n");
  225. break;
  226. case MT65XX_LED_MODE_CUST_BLS_PWM:
  227. pled_dtsi[i].data =
  228. (long)disp_bls_set_backlight;
  229. LEDS_DEBUG
  230. ("kernel:the backlight hw mode is BLS.\n");
  231. break;
  232. default:
  233. break;
  234. }
  235. }
  236. }
  237. if (!isSupportDTS) {
  238. kfree(pled_dtsi);
  239. pled_dtsi = NULL;
  240. }
  241. }
  242. out:
  243. return pled_dtsi;
  244. }
  245. struct cust_mt65xx_led *mt_get_cust_led_list(void)
  246. {
  247. struct cust_mt65xx_led *cust_led_list = get_cust_led_dtsi();
  248. return cust_led_list;
  249. }
  250. /****************************************************************************
  251. * internal functions
  252. ***************************************************************************/
  253. static int brightness_mapto64(int level)
  254. {
  255. if (level < 30)
  256. return (level >> 1) + 7;
  257. else if (level <= 120)
  258. return (level >> 2) + 14;
  259. else if (level <= 160)
  260. return level / 5 + 20;
  261. else
  262. return (level >> 3) + 33;
  263. }
  264. static int find_time_index(int time)
  265. {
  266. int index = 0;
  267. while (index < 8) {
  268. if (time < time_array_hal[index])
  269. return index;
  270. index++;
  271. }
  272. return PWM_DIV_NUM - 1;
  273. }
  274. int mt_led_set_pwm(int pwm_num, struct nled_setting *led)
  275. {
  276. struct pwm_spec_config pwm_setting;
  277. int time_index = 0;
  278. pwm_setting.pwm_no = pwm_num;
  279. pwm_setting.mode = PWM_MODE_OLD;
  280. LEDS_DEBUG("led_set_pwm: mode=%d,pwm_no=%d\n", led->nled_mode,
  281. pwm_num);
  282. /* We won't choose 32K to be the clock src of old mode because of system performance. */
  283. /* The setting here will be clock src = 26MHz, CLKSEL = 26M/1625 (i.e. 16K) */
  284. pwm_setting.clk_src = PWM_CLK_OLD_MODE_32K;
  285. switch (led->nled_mode) {
  286. /* Actually, the setting still can not to turn off NLED. We should disable PWM to turn off NLED. */
  287. case NLED_OFF:
  288. pwm_setting.PWM_MODE_OLD_REGS.THRESH = 0;
  289. pwm_setting.clk_div = CLK_DIV1;
  290. pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 100 / 2;
  291. break;
  292. case NLED_ON:
  293. pwm_setting.PWM_MODE_OLD_REGS.THRESH = 30 / 2;
  294. pwm_setting.clk_div = CLK_DIV1;
  295. pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 100 / 2;
  296. break;
  297. case NLED_BLINK:
  298. LEDS_DEBUG("LED blink on time = %d offtime = %d\n",
  299. led->blink_on_time, led->blink_off_time);
  300. time_index =
  301. find_time_index(led->blink_on_time + led->blink_off_time);
  302. LEDS_DEBUG("LED div is %d\n", time_index);
  303. pwm_setting.clk_div = time_index;
  304. pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH =
  305. (led->blink_on_time +
  306. led->blink_off_time) * MIN_FRE_OLD_PWM /
  307. div_array_hal[time_index];
  308. pwm_setting.PWM_MODE_OLD_REGS.THRESH =
  309. (led->blink_on_time * 100) / (led->blink_on_time +
  310. led->blink_off_time);
  311. }
  312. pwm_setting.PWM_MODE_FIFO_REGS.IDLE_VALUE = 0;
  313. pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 0;
  314. pwm_setting.PWM_MODE_FIFO_REGS.GDURATION = 0;
  315. pwm_setting.PWM_MODE_FIFO_REGS.WAVE_NUM = 0;
  316. pwm_set_spec_config(&pwm_setting);
  317. return 0;
  318. }
  319. /************************ led breath function*****************************/
  320. /*************************************************************************
  321. //func is to swtich to breath mode from PWM mode of ISINK
  322. //para: enable: 1 : breath mode; 0: PWM mode;
  323. *************************************************************************/
  324. #if 0
  325. static int led_switch_breath_pmic(enum mt65xx_led_pmic pmic_type,
  326. struct nled_setting *led, int enable)
  327. {
  328. /* int time_index = 0; */
  329. /* int duty = 0; */
  330. LEDS_DEBUG("led_blink_pmic: pmic_type=%d\n", pmic_type);
  331. if ((pmic_type != MT65XX_LED_PMIC_NLED_ISINK0
  332. && pmic_type != MT65XX_LED_PMIC_NLED_ISINK1
  333. && pmic_type != MT65XX_LED_PMIC_NLED_ISINK2
  334. && pmic_type != MT65XX_LED_PMIC_NLED_ISINK3)
  335. || led->nled_mode != NLED_BLINK) {
  336. return -1;
  337. }
  338. if (1 == enable) {
  339. switch (pmic_type) {
  340. case MT65XX_LED_PMIC_NLED_ISINK0:
  341. pmic_set_register_value(PMIC_ISINK_CH0_MODE,
  342. ISINK_BREATH_MODE);
  343. pmic_set_register_value(PMIC_ISINK_CH0_STEP, ISINK_3);
  344. pmic_set_register_value(PMIC_ISINK_BREATH0_TR1_SEL,
  345. 0x04);
  346. pmic_set_register_value(PMIC_ISINK_BREATH0_TR2_SEL,
  347. 0x04);
  348. pmic_set_register_value(PMIC_ISINK_BREATH0_TF1_SEL,
  349. 0x04);
  350. pmic_set_register_value(PMIC_ISINK_BREATH0_TF2_SEL,
  351. 0x04);
  352. pmic_set_register_value(PMIC_ISINK_BREATH0_TON_SEL,
  353. 0x02);
  354. pmic_set_register_value(PMIC_ISINK_BREATH0_TOFF_SEL,
  355. 0x03);
  356. pmic_set_register_value(PMIC_ISINK_DIM0_DUTY, 15);
  357. pmic_set_register_value(PMIC_ISINK_DIM0_FSEL, 11);
  358. /* pmic_set_register_value(PMIC_ISINK_CH0_EN,NLED_ON); */
  359. break;
  360. case MT65XX_LED_PMIC_NLED_ISINK1:
  361. pmic_set_register_value(PMIC_ISINK_CH1_MODE,
  362. ISINK_BREATH_MODE);
  363. pmic_set_register_value(PMIC_ISINK_CH1_STEP, ISINK_3);
  364. pmic_set_register_value(PMIC_ISINK_BREATH1_TR1_SEL,
  365. 0x04);
  366. pmic_set_register_value(PMIC_ISINK_BREATH1_TR2_SEL,
  367. 0x04);
  368. pmic_set_register_value(PMIC_ISINK_BREATH1_TF1_SEL,
  369. 0x04);
  370. pmic_set_register_value(PMIC_ISINK_BREATH1_TF2_SEL,
  371. 0x04);
  372. pmic_set_register_value(PMIC_ISINK_BREATH1_TON_SEL,
  373. 0x02);
  374. pmic_set_register_value(PMIC_ISINK_BREATH1_TOFF_SEL,
  375. 0x03);
  376. pmic_set_register_value(PMIC_ISINK_DIM1_DUTY, 15);
  377. pmic_set_register_value(PMIC_ISINK_DIM1_FSEL, 11);
  378. /* pmic_set_register_value(PMIC_ISINK_CH1_EN,NLED_ON); */
  379. break;
  380. case MT65XX_LED_PMIC_NLED_ISINK2:
  381. pmic_set_register_value(PMIC_ISINK_CH2_MODE,
  382. ISINK_BREATH_MODE);
  383. pmic_set_register_value(PMIC_ISINK_CH2_STEP, ISINK_3);
  384. pmic_set_register_value(PMIC_ISINK_BREATH2_TR1_SEL,
  385. 0x04);
  386. pmic_set_register_value(PMIC_ISINK_BREATH2_TR2_SEL,
  387. 0x04);
  388. pmic_set_register_value(PMIC_ISINK_BREATH2_TF1_SEL,
  389. 0x04);
  390. pmic_set_register_value(PMIC_ISINK_BREATH2_TF2_SEL,
  391. 0x04);
  392. pmic_set_register_value(PMIC_ISINK_BREATH2_TON_SEL,
  393. 0x02);
  394. pmic_set_register_value(PMIC_ISINK_BREATH2_TOFF_SEL,
  395. 0x03);
  396. pmic_set_register_value(PMIC_ISINK_DIM2_DUTY, 15);
  397. pmic_set_register_value(PMIC_ISINK_DIM2_FSEL, 11);
  398. /* pmic_set_register_value(PMIC_ISINK_CH2_EN,NLED_ON); */
  399. break;
  400. case MT65XX_LED_PMIC_NLED_ISINK3:
  401. pmic_set_register_value(PMIC_ISINK_CH3_MODE,
  402. ISINK_BREATH_MODE);
  403. pmic_set_register_value(PMIC_ISINK_CH3_STEP, ISINK_3);
  404. pmic_set_register_value(PMIC_ISINK_BREATH3_TR1_SEL,
  405. 0x04);
  406. pmic_set_register_value(PMIC_ISINK_BREATH3_TR2_SEL,
  407. 0x04);
  408. pmic_set_register_value(PMIC_ISINK_BREATH3_TF1_SEL,
  409. 0x04);
  410. pmic_set_register_value(PMIC_ISINK_BREATH3_TF2_SEL,
  411. 0x04);
  412. pmic_set_register_value(PMIC_ISINK_BREATH3_TON_SEL,
  413. 0x02);
  414. pmic_set_register_value(PMIC_ISINK_BREATH3_TOFF_SEL,
  415. 0x03);
  416. pmic_set_register_value(PMIC_ISINK_DIM3_DUTY, 15);
  417. pmic_set_register_value(PMIC_ISINK_DIM3_FSEL, 11);
  418. /* pmic_set_register_value(PMIC_ISINK_CH3_EN,NLED_ON); */
  419. break;
  420. default:
  421. break;
  422. }
  423. } else {
  424. switch (pmic_type) {
  425. case MT65XX_LED_PMIC_NLED_ISINK0:
  426. pmic_set_register_value(PMIC_ISINK_CH3_MODE,
  427. ISINK_PWM_MODE);
  428. break;
  429. case MT65XX_LED_PMIC_NLED_ISINK0:
  430. pmic_set_register_value(PMIC_ISINK_CH3_MODE,
  431. ISINK_PWM_MODE);
  432. break;
  433. case MT65XX_LED_PMIC_NLED_ISINK0:
  434. pmic_set_register_value(PMIC_ISINK_CH3_MODE,
  435. ISINK_PWM_MODE);
  436. break;
  437. case MT65XX_LED_PMIC_NLED_ISINK0:
  438. pmic_set_register_value(PMIC_ISINK_CH3_MODE,
  439. ISINK_PWM_MODE);
  440. break;
  441. default:
  442. break;
  443. }
  444. }
  445. return 0;
  446. }
  447. #endif
  448. #define PMIC_PERIOD_NUM 8
  449. /* 100 * period, ex: 0.01 Hz -> 0.01 * 100 = 1 */
  450. int pmic_period_array[] = { 250, 500, 1000, 1250, 1666, 2000, 2500, 10000 };
  451. /* int pmic_freqsel_array[] = {99999, 9999, 4999, 1999, 999, 499, 199, 4, 0}; */
  452. int pmic_freqsel_array[] = { 0, 4, 199, 499, 999, 1999, 1999, 1999 };
  453. static int find_time_index_pmic(int time_ms)
  454. {
  455. int i;
  456. for (i = 0; i < PMIC_PERIOD_NUM; i++) {
  457. if (time_ms <= pmic_period_array[i])
  458. return i;
  459. }
  460. return PMIC_PERIOD_NUM - 1;
  461. }
  462. int mt_led_blink_pmic(enum mt65xx_led_pmic pmic_type, struct nled_setting *led)
  463. {
  464. int time_index = 0;
  465. int duty = 0;
  466. LEDS_DEBUG("led_blink_pmic: pmic_type=%d\n", pmic_type);
  467. if ((pmic_type != MT65XX_LED_PMIC_NLED_ISINK0
  468. && pmic_type != MT65XX_LED_PMIC_NLED_ISINK1)
  469. || led->nled_mode != NLED_BLINK) {
  470. return -1;
  471. }
  472. LEDS_DEBUG("LED blink on time = %d offtime = %d\n",
  473. led->blink_on_time, led->blink_off_time);
  474. time_index =
  475. find_time_index_pmic(led->blink_on_time + led->blink_off_time);
  476. LEDS_DEBUG("LED index is %d freqsel=%d\n", time_index,
  477. pmic_freqsel_array[time_index]);
  478. duty =
  479. 32 * led->blink_on_time / (led->blink_on_time +
  480. led->blink_off_time);
  481. /* pmic_set_register_value(PMIC_RG_G_DRV_2M_CK_PDN(0X0); // DISABLE POWER DOWN ,Indicator no need) */
  482. pmic_set_register_value(PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */
  483. switch (pmic_type) {
  484. case MT65XX_LED_PMIC_NLED_ISINK0:
  485. pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_PDN, 0);
  486. pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_CKSEL, 0);
  487. pmic_set_register_value(PMIC_ISINK_CH0_MODE, ISINK_PWM_MODE);
  488. pmic_set_register_value(PMIC_ISINK_CH0_STEP, ISINK_3); /* 16mA */
  489. pmic_set_register_value(PMIC_ISINK_DIM0_DUTY, duty);
  490. pmic_set_register_value(PMIC_ISINK_DIM0_FSEL,
  491. pmic_freqsel_array[time_index]);
  492. pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_ON);
  493. break;
  494. case MT65XX_LED_PMIC_NLED_ISINK1:
  495. pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_PDN, 0);
  496. pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_CKSEL, 0);
  497. pmic_set_register_value(PMIC_ISINK_CH1_MODE, ISINK_PWM_MODE);
  498. pmic_set_register_value(PMIC_ISINK_CH1_STEP, ISINK_3); /* 16mA */
  499. pmic_set_register_value(PMIC_ISINK_DIM1_DUTY, duty);
  500. pmic_set_register_value(PMIC_ISINK_DIM1_FSEL,
  501. pmic_freqsel_array[time_index]);
  502. pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_ON);
  503. break;
  504. default:
  505. break;
  506. }
  507. return 0;
  508. }
  509. int mt_backlight_set_pwm(int pwm_num, u32 level, u32 div,
  510. struct PWM_config *config_data)
  511. {
  512. struct pwm_spec_config pwm_setting;
  513. unsigned int BacklightLevelSupport =
  514. Cust_GetBacklightLevelSupport_byPWM();
  515. pwm_setting.pwm_no = pwm_num;
  516. if (BacklightLevelSupport == BACKLIGHT_LEVEL_PWM_256_SUPPORT)
  517. pwm_setting.mode = PWM_MODE_OLD;
  518. else
  519. pwm_setting.mode = PWM_MODE_FIFO; /* New mode fifo and periodical mode */
  520. pwm_setting.pmic_pad = config_data->pmic_pad;
  521. if (config_data->div) {
  522. pwm_setting.clk_div = config_data->div;
  523. backlight_PWM_div_hal = config_data->div;
  524. } else
  525. pwm_setting.clk_div = div;
  526. if (BacklightLevelSupport == BACKLIGHT_LEVEL_PWM_256_SUPPORT) {
  527. if (config_data->clock_source)
  528. pwm_setting.clk_src = PWM_CLK_OLD_MODE_BLOCK;
  529. else
  530. pwm_setting.clk_src = PWM_CLK_OLD_MODE_32K; /* actually.
  531. it's block/1625 = 26M/1625 = 16KHz @ MT6571 */
  532. pwm_setting.PWM_MODE_OLD_REGS.IDLE_VALUE = 0;
  533. pwm_setting.PWM_MODE_OLD_REGS.GUARD_VALUE = 0;
  534. pwm_setting.PWM_MODE_OLD_REGS.GDURATION = 0;
  535. pwm_setting.PWM_MODE_OLD_REGS.WAVE_NUM = 0;
  536. pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 255; /* 256 level */
  537. pwm_setting.PWM_MODE_OLD_REGS.THRESH = level;
  538. LEDS_DEBUG("[LEDS][%d]backlight_set_pwm:duty is %d/%d\n",
  539. BacklightLevelSupport, level,
  540. pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH);
  541. LEDS_DEBUG("[LEDS][%d]backlight_set_pwm:clk_src/div is %d%d\n",
  542. BacklightLevelSupport, pwm_setting.clk_src,
  543. pwm_setting.clk_div);
  544. if (level > 0 && level < 256) {
  545. pwm_set_spec_config(&pwm_setting);
  546. LEDS_DEBUG
  547. ("[LEDS][%d]backlight_set_pwm: old mode: thres/data_width is %d/%d\n",
  548. BacklightLevelSupport,
  549. pwm_setting.PWM_MODE_OLD_REGS.THRESH,
  550. pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH);
  551. } else {
  552. LEDS_DEBUG("[LEDS][%d]Error level in backlight\n",
  553. BacklightLevelSupport);
  554. mt_pwm_disable(pwm_setting.pwm_no,
  555. config_data->pmic_pad);
  556. }
  557. return 0;
  558. } else {
  559. if (config_data->clock_source) {
  560. pwm_setting.clk_src = PWM_CLK_NEW_MODE_BLOCK;
  561. } else {
  562. pwm_setting.clk_src =
  563. PWM_CLK_NEW_MODE_BLOCK_DIV_BY_1625;
  564. }
  565. if (config_data->High_duration && config_data->low_duration) {
  566. pwm_setting.PWM_MODE_FIFO_REGS.HDURATION =
  567. config_data->High_duration;
  568. pwm_setting.PWM_MODE_FIFO_REGS.LDURATION =
  569. pwm_setting.PWM_MODE_FIFO_REGS.HDURATION;
  570. } else {
  571. pwm_setting.PWM_MODE_FIFO_REGS.HDURATION = 4;
  572. pwm_setting.PWM_MODE_FIFO_REGS.LDURATION = 4;
  573. }
  574. pwm_setting.PWM_MODE_FIFO_REGS.IDLE_VALUE = 0;
  575. pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 0;
  576. pwm_setting.PWM_MODE_FIFO_REGS.STOP_BITPOS_VALUE = 31;
  577. pwm_setting.PWM_MODE_FIFO_REGS.GDURATION =
  578. (pwm_setting.PWM_MODE_FIFO_REGS.HDURATION + 1) * 32 - 1;
  579. pwm_setting.PWM_MODE_FIFO_REGS.WAVE_NUM = 0;
  580. LEDS_DEBUG("[LEDS]backlight_set_pwm:duty is %d\n", level);
  581. LEDS_DEBUG
  582. ("[LEDS]backlight_set_pwm:clk_src/div/high/low is %d%d%d%d\n",
  583. pwm_setting.clk_src, pwm_setting.clk_div,
  584. pwm_setting.PWM_MODE_FIFO_REGS.HDURATION,
  585. pwm_setting.PWM_MODE_FIFO_REGS.LDURATION);
  586. if (level > 0 && level <= 32) {
  587. pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 0;
  588. pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA0 =
  589. (1 << level) - 1;
  590. pwm_set_spec_config(&pwm_setting);
  591. } else if (level > 32 && level <= 64) {
  592. pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 1;
  593. level -= 32;
  594. pwm_setting.PWM_MODE_FIFO_REGS.SEND_DATA0 =
  595. (1 << level) - 1;
  596. pwm_set_spec_config(&pwm_setting);
  597. } else {
  598. LEDS_DEBUG("[LEDS]Error level in backlight\n");
  599. mt_pwm_disable(pwm_setting.pwm_no,
  600. config_data->pmic_pad);
  601. }
  602. return 0;
  603. }
  604. }
  605. void mt_led_pwm_disable(int pwm_num)
  606. {
  607. struct cust_mt65xx_led *cust_led_list = get_cust_led_dtsi();
  608. mt_pwm_disable(pwm_num, cust_led_list->config_data.pmic_pad);
  609. }
  610. void mt_backlight_set_pwm_duty(int pwm_num, u32 level, u32 div,
  611. struct PWM_config *config_data)
  612. {
  613. mt_backlight_set_pwm(pwm_num, level, div, config_data);
  614. }
  615. void mt_backlight_set_pwm_div(int pwm_num, u32 level, u32 div,
  616. struct PWM_config *config_data)
  617. {
  618. mt_backlight_set_pwm(pwm_num, level, div, config_data);
  619. }
  620. void mt_backlight_get_pwm_fsel(unsigned int bl_div, unsigned int *bl_frequency)
  621. {
  622. }
  623. void mt_store_pwm_register(unsigned int addr, unsigned int value)
  624. {
  625. }
  626. unsigned int mt_show_pwm_register(unsigned int addr)
  627. {
  628. return 0;
  629. }
  630. int mt_brightness_set_pmic(enum mt65xx_led_pmic pmic_type, u32 level, u32 div)
  631. {
  632. static bool first_time = true;
  633. LEDS_DEBUG("PMIC#%d:%d\n", pmic_type, level);
  634. mutex_lock(&leds_pmic_mutex);
  635. if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK0) {
  636. if ((button_flag_isink0 == 0) && (first_time == true)) { /* button
  637. flag ==0, means this ISINK is not for button backlight */
  638. if (button_flag_isink1 == 0)
  639. pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_OFF); /* sw
  640. workround for sync leds status */
  641. if (button_flag_isink2 == 0)
  642. pmic_set_register_value(PMIC_ISINK_CH2_EN,
  643. NLED_OFF);
  644. if (button_flag_isink3 == 0)
  645. pmic_set_register_value(PMIC_ISINK_CH3_EN,
  646. NLED_OFF);
  647. first_time = false;
  648. }
  649. pmic_set_register_value(PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */
  650. pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_PDN, 0);
  651. pmic_set_register_value(PMIC_RG_DRV_ISINK0_CK_CKSEL, 0);
  652. pmic_set_register_value(PMIC_ISINK_CH0_MODE, ISINK_PWM_MODE);
  653. pmic_set_register_value(PMIC_ISINK_CH0_STEP, ISINK_3); /* 16mA */
  654. pmic_set_register_value(PMIC_ISINK_DIM0_DUTY, 15);
  655. pmic_set_register_value(PMIC_ISINK_DIM0_FSEL, ISINK_1KHZ); /* 1KHz */
  656. if (level)
  657. pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_ON);
  658. else
  659. pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_OFF);
  660. mutex_unlock(&leds_pmic_mutex);
  661. return 0;
  662. } else if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK1) {
  663. if ((button_flag_isink1 == 0) && (first_time == true)) { /* button
  664. flag ==0, means this ISINK is not for button backlight */
  665. if (button_flag_isink0 == 0)
  666. pmic_set_register_value(PMIC_ISINK_CH0_EN, NLED_OFF); /* sw
  667. workround for sync leds status */
  668. if (button_flag_isink2 == 0)
  669. pmic_set_register_value(PMIC_ISINK_CH2_EN,
  670. NLED_OFF);
  671. if (button_flag_isink3 == 0)
  672. pmic_set_register_value(PMIC_ISINK_CH3_EN,
  673. NLED_OFF);
  674. first_time = false;
  675. }
  676. pmic_set_register_value(PMIC_RG_DRV_32K_CK_PDN, 0x0); /* Disable power down */
  677. pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_PDN, 0);
  678. pmic_set_register_value(PMIC_RG_DRV_ISINK1_CK_CKSEL, 0);
  679. pmic_set_register_value(PMIC_ISINK_CH1_MODE, ISINK_PWM_MODE);
  680. pmic_set_register_value(PMIC_ISINK_CH1_STEP, ISINK_3); /* 16mA */
  681. pmic_set_register_value(PMIC_ISINK_DIM1_DUTY, 15);
  682. pmic_set_register_value(PMIC_ISINK_DIM1_FSEL, ISINK_1KHZ); /* 1KHz */
  683. if (level)
  684. pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_ON);
  685. else
  686. pmic_set_register_value(PMIC_ISINK_CH1_EN, NLED_OFF);
  687. mutex_unlock(&leds_pmic_mutex);
  688. return 0;
  689. }
  690. mutex_unlock(&leds_pmic_mutex);
  691. return -1;
  692. }
  693. int mt_brightness_set_pmic_duty_store(u32 level, u32 div)
  694. {
  695. return -1;
  696. }
  697. int mt_mt65xx_led_set_cust(struct cust_mt65xx_led *cust, int level)
  698. {
  699. struct nled_setting led_tmp_setting = { 0, 0, 0 };
  700. int tmp_level = level;
  701. static bool button_flag;
  702. unsigned int BacklightLevelSupport =
  703. Cust_GetBacklightLevelSupport_byPWM();
  704. switch (cust->mode) {
  705. case MT65XX_LED_MODE_PWM:
  706. if (strcmp(cust->name, "lcd-backlight") == 0) {
  707. bl_brightness_hal = level;
  708. if (level == 0) {
  709. mt_pwm_disable(cust->data,
  710. cust->config_data.pmic_pad);
  711. } else {
  712. if (BacklightLevelSupport ==
  713. BACKLIGHT_LEVEL_PWM_256_SUPPORT)
  714. level = brightness_mapping(tmp_level);
  715. else
  716. level = brightness_mapto64(tmp_level);
  717. mt_backlight_set_pwm(cust->data, level,
  718. bl_div_hal,
  719. &cust->config_data);
  720. }
  721. bl_duty_hal = level;
  722. } else {
  723. if (level == 0) {
  724. led_tmp_setting.nled_mode = NLED_OFF;
  725. mt_led_set_pwm(cust->data, &led_tmp_setting);
  726. mt_pwm_disable(cust->data,
  727. cust->config_data.pmic_pad);
  728. } else {
  729. led_tmp_setting.nled_mode = NLED_ON;
  730. mt_led_set_pwm(cust->data, &led_tmp_setting);
  731. }
  732. }
  733. return 1;
  734. case MT65XX_LED_MODE_GPIO:
  735. LEDS_DEBUG("brightness_set_cust:go GPIO mode!!!!!\n");
  736. return ((cust_set_brightness) (cust->data)) (level);
  737. case MT65XX_LED_MODE_PMIC:
  738. /* for button baclight used SINK channel, when set button ISINK,
  739. don't do disable other ISINK channel */
  740. if ((strcmp(cust->name, "button-backlight") == 0)) {
  741. if (button_flag == false) {
  742. switch (cust->data) {
  743. case MT65XX_LED_PMIC_NLED_ISINK0:
  744. button_flag_isink0 = 1;
  745. break;
  746. case MT65XX_LED_PMIC_NLED_ISINK1:
  747. button_flag_isink1 = 1;
  748. break;
  749. case MT65XX_LED_PMIC_NLED_ISINK2:
  750. button_flag_isink2 = 1;
  751. break;
  752. case MT65XX_LED_PMIC_NLED_ISINK3:
  753. button_flag_isink3 = 1;
  754. break;
  755. default:
  756. break;
  757. }
  758. button_flag = true;
  759. }
  760. }
  761. return mt_brightness_set_pmic(cust->data, level, bl_div_hal);
  762. case MT65XX_LED_MODE_CUST_LCM:
  763. if (strcmp(cust->name, "lcd-backlight") == 0)
  764. bl_brightness_hal = level;
  765. LEDS_DEBUG("brightness_set_cust:backlight control by LCM\n");
  766. /* warning for this API revork */
  767. return ((cust_brightness_set) (cust->data)) (level, bl_div_hal);
  768. case MT65XX_LED_MODE_CUST_BLS_PWM:
  769. if (strcmp(cust->name, "lcd-backlight") == 0)
  770. bl_brightness_hal = level;
  771. return ((cust_set_brightness) (cust->data)) (level);
  772. case MT65XX_LED_MODE_NONE:
  773. default:
  774. break;
  775. }
  776. return -1;
  777. }
  778. void mt_mt65xx_led_work(struct work_struct *work)
  779. {
  780. struct mt65xx_led_data *led_data =
  781. container_of(work, struct mt65xx_led_data, work);
  782. LEDS_DEBUG("%s:%d\n", led_data->cust.name, led_data->level);
  783. mutex_lock(&leds_mutex);
  784. mt_mt65xx_led_set_cust(&led_data->cust, led_data->level);
  785. mutex_unlock(&leds_mutex);
  786. }
  787. void mt_mt65xx_led_set(struct led_classdev *led_cdev, enum led_brightness level)
  788. {
  789. struct mt65xx_led_data *led_data =
  790. container_of(led_cdev, struct mt65xx_led_data, cdev);
  791. /* unsigned long flags; */
  792. /* spin_lock_irqsave(&leds_lock, flags); */
  793. #ifdef CONFIG_MTK_AAL_SUPPORT
  794. if (led_data->level != level) {
  795. led_data->level = level;
  796. if (strcmp(led_data->cust.name, "lcd-backlight") != 0) {
  797. LEDS_DEBUG("Set NLED directly %d at time %lu\n",
  798. led_data->level, jiffies);
  799. schedule_work(&led_data->work);
  800. } else {
  801. if (level != 0
  802. && level * CONFIG_LIGHTNESS_MAPPING_VALUE < 255) {
  803. level = 1;
  804. } else {
  805. level =
  806. (level * CONFIG_LIGHTNESS_MAPPING_VALUE) /
  807. 255;
  808. }
  809. LEDS_DEBUG
  810. ("Set Backlight directly %d at time %lu, mapping level is %d\n",
  811. led_data->level, jiffies, level);
  812. /* mt_mt65xx_led_set_cust(&led_data->cust, led_data->level); */
  813. disp_aal_notify_backlight_changed((((1 <<
  814. MT_LED_INTERNAL_LEVEL_BIT_CNT)
  815. - 1) * level +
  816. 127) / 255);
  817. }
  818. }
  819. #else
  820. /* do something only when level is changed */
  821. if (led_data->level != level) {
  822. led_data->level = level;
  823. if (strcmp(led_data->cust.name, "lcd-backlight") != 0) {
  824. LEDS_DEBUG("Set NLED directly %d at time %lu\n",
  825. led_data->level, jiffies);
  826. schedule_work(&led_data->work);
  827. } else {
  828. if (level != 0
  829. && level * CONFIG_LIGHTNESS_MAPPING_VALUE < 255) {
  830. level = 1;
  831. } else {
  832. level =
  833. (level * CONFIG_LIGHTNESS_MAPPING_VALUE) /
  834. 255;
  835. }
  836. LEDS_DEBUG
  837. ("Set Backlight directly %d at time %lu, mapping level is %d\n",
  838. led_data->level, jiffies, level);
  839. if (MT65XX_LED_MODE_CUST_BLS_PWM == led_data->cust.mode) {
  840. mt_mt65xx_led_set_cust(&led_data->cust,
  841. ((((1 <<
  842. MT_LED_INTERNAL_LEVEL_BIT_CNT)
  843. - 1) * level +
  844. 127) / 255));
  845. } else {
  846. mt_mt65xx_led_set_cust(&led_data->cust, level);
  847. }
  848. }
  849. }
  850. /* spin_unlock_irqrestore(&leds_lock, flags); */
  851. #endif
  852. /* if(0!=aee_kernel_Powerkey_is_press()) */
  853. /* aee_kernel_wdt_kick_Powkey_api("mt_mt65xx_led_set",WDT_SETBY_Backlight); */
  854. }
  855. int mt_mt65xx_blink_set(struct led_classdev *led_cdev,
  856. unsigned long *delay_on, unsigned long *delay_off)
  857. {
  858. struct mt65xx_led_data *led_data =
  859. container_of(led_cdev, struct mt65xx_led_data, cdev);
  860. static int got_wake_lock;
  861. struct nled_setting nled_tmp_setting = { 0, 0, 0 };
  862. /* only allow software blink when delay_on or delay_off changed */
  863. if (*delay_on != led_data->delay_on
  864. || *delay_off != led_data->delay_off) {
  865. led_data->delay_on = *delay_on;
  866. led_data->delay_off = *delay_off;
  867. if (led_data->delay_on && led_data->delay_off) { /* enable blink */
  868. led_data->level = 255; /* when enable blink then to set the level (255) */
  869. /* AP PWM all support OLD mode */
  870. if (led_data->cust.mode == MT65XX_LED_MODE_PWM) {
  871. nled_tmp_setting.nled_mode = NLED_BLINK;
  872. nled_tmp_setting.blink_off_time =
  873. led_data->delay_off;
  874. nled_tmp_setting.blink_on_time =
  875. led_data->delay_on;
  876. mt_led_set_pwm(led_data->cust.data,
  877. &nled_tmp_setting);
  878. return 0;
  879. } else if ((led_data->cust.mode == MT65XX_LED_MODE_PMIC)
  880. && (led_data->cust.data ==
  881. MT65XX_LED_PMIC_NLED_ISINK0
  882. || led_data->cust.data ==
  883. MT65XX_LED_PMIC_NLED_ISINK1
  884. || led_data->cust.data ==
  885. MT65XX_LED_PMIC_NLED_ISINK2
  886. || led_data->cust.data ==
  887. MT65XX_LED_PMIC_NLED_ISINK3)) {
  888. nled_tmp_setting.nled_mode = NLED_BLINK;
  889. nled_tmp_setting.blink_off_time =
  890. led_data->delay_off;
  891. nled_tmp_setting.blink_on_time =
  892. led_data->delay_on;
  893. mt_led_blink_pmic(led_data->cust.data,
  894. &nled_tmp_setting);
  895. return 0;
  896. } else if (!got_wake_lock) {
  897. wake_lock(&leds_suspend_lock);
  898. got_wake_lock = 1;
  899. }
  900. } else if (!led_data->delay_on && !led_data->delay_off) { /* disable blink */
  901. /* AP PWM all support OLD mode */
  902. if (led_data->cust.mode == MT65XX_LED_MODE_PWM) {
  903. nled_tmp_setting.nled_mode = NLED_OFF;
  904. mt_led_set_pwm(led_data->cust.data,
  905. &nled_tmp_setting);
  906. return 0;
  907. } else if ((led_data->cust.mode == MT65XX_LED_MODE_PMIC)
  908. && (led_data->cust.data ==
  909. MT65XX_LED_PMIC_NLED_ISINK0
  910. || led_data->cust.data ==
  911. MT65XX_LED_PMIC_NLED_ISINK1
  912. || led_data->cust.data ==
  913. MT65XX_LED_PMIC_NLED_ISINK2
  914. || led_data->cust.data ==
  915. MT65XX_LED_PMIC_NLED_ISINK3)) {
  916. mt_brightness_set_pmic(led_data->cust.data, 0,
  917. 0);
  918. return 0;
  919. } else if (got_wake_lock) {
  920. wake_unlock(&leds_suspend_lock);
  921. got_wake_lock = 0;
  922. }
  923. }
  924. return -1;
  925. }
  926. /* delay_on and delay_off are not changed */
  927. return 0;
  928. }