Merge branch 'develop' of 10.10.10.29:/home/rockchip/kernel into develop
[firefly-linux-kernel-4.4.55.git] / drivers / power / wm831x_charger_display.c
1 /* drivers/power/wm831x_charger_display.c
2  *
3  * battery detect driver for the rk2818 
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/slab.h>
18 #include <linux/kernel.h>
19 #include <linux/errno.h>
20 #include <linux/input.h>
21 #include <linux/interrupt.h>
22 #include <linux/fb.h>
23 #include <linux/delay.h>
24 #include <linux/suspend.h>
25 #include <linux/linux_logo.h>
26 #include <linux/regulator/consumer.h>
27 #include <linux/platform_device.h>
28 #include <linux/workqueue.h>
29 #include <linux/mfd/wm831x/core.h>
30 #include <mach/gpio.h>
31 #include <mach/iomux.h>
32 #include <mach/rk29_iomap.h>
33
34 #include <linux/mfd/wm831x/core.h>
35 #include <linux/mfd/wm831x/auxadc.h>
36 #include <linux/mfd/wm831x/pmu.h>
37 #include <linux/mfd/wm831x/pdata.h>
38 #include <linux/mfd/wm831x/irq.h>
39 #include <linux/power_supply.h>
40
41
42 #define READ_ON_PIN_CNT 20/*11*/
43 #define BACKLIGHT_CNT   2
44 #define OPEN_CNT                18
45 #define MC_OPEN 7/*10*/ 
46 #define BAT_CHARGING    1
47 #define BAT_DISCHARGING 0
48 #define BL_DELAY_TIME   (8*1000)
49
50
51 #define SET_BACKLIGHT_ON        1
52 #define OPEN_SYSTEM                     2
53 #define SUSPEND_SYSTEM          3
54
55 #if 0
56 #define DBG(x...)   printk(x)
57 #else
58 #define DBG(x...)
59 #endif 
60
61 extern void request_suspend_state(suspend_state_t new_state);
62 extern void kernel_restart(char *cmd);
63 extern void kernel_power_off(void);
64
65 extern unsigned g_vbus_status_register;
66 extern unsigned long *g_pcd_for_charger;
67
68 extern int rk29_backlight_ctrl(int open);
69
70 extern void fb_show_charge_logo(struct linux_logo *logo);
71
72 extern void kernel_restart_prepare(char *cmd);
73 extern int dwc_vbus_status( void );
74 extern int dwc_otg_pcd_check_vbus_detech( unsigned long pdata );
75
76 #if defined(CONFIG_LOGO_CHARGER_CLUT224)
77 extern struct linux_logo logo_charger01_clut224;
78 extern struct linux_logo logo_charger02_clut224;
79 extern struct linux_logo logo_charger03_clut224;
80 extern struct linux_logo logo_charger04_clut224;
81 extern struct linux_logo logo_charger05_clut224;
82 extern struct linux_logo logo_charger06_clut224;
83 extern struct linux_logo logo_charger07_clut224;
84 extern struct linux_logo logo_charger08_clut224;
85 #endif
86
87 extern struct fb_info *g_fb0_inf;
88
89 static struct linux_logo* g_chargerlogo[8]= {
90 #if defined(CONFIG_LOGO_CHARGER_CLUT224)
91         &logo_charger01_clut224,&logo_charger02_clut224,&logo_charger03_clut224,&logo_charger04_clut224,
92                 &logo_charger05_clut224,&logo_charger06_clut224,&logo_charger07_clut224,&logo_charger08_clut224
93 #endif
94 };
95
96 #if 1
97 struct wm831x_chg {
98         struct wm831x *wm831x;
99         int logo_id;
100         int flag_chg;
101         int bat_vol;
102         int cnt_on;
103         int cnt_disp;
104         int flag_bl;
105         int flag_suspend;
106         
107 };
108
109 static int charger_logo_display(struct linux_logo *logo)
110 {
111         fb_show_charge_logo(logo);
112         fb_show_logo(g_fb0_inf, 0);
113         return 0;
114 }
115
116 static int charger_backlight_ctrl(int open)
117 {
118         DBG("%s:open=%d\n",__FUNCTION__,open);
119         return rk29_backlight_ctrl(open);
120 }
121
122 static int wm831x_read_on_pin_status(struct wm831x_chg *wm831x_chg)
123 {
124         int ret;
125         
126         if(!wm831x_chg)
127         {
128                 printk("err:%s:wm831x_chg address is 0\n",__FUNCTION__);
129                 return -1;
130         }
131         
132         ret = wm831x_reg_read(wm831x_chg->wm831x, WM831X_ON_PIN_CONTROL);
133         if (ret < 0)
134                 return ret;
135
136         return !(ret & WM831X_ON_PIN_STS) ? 1 : 0;
137 }
138
139
140 static int wm831x_read_chg_status(struct wm831x_chg *wm831x_chg)
141 {
142         int ret, usb_chg = 0, wall_chg = 0;
143         
144         if(!wm831x_chg)
145         {
146                 printk("err:%s:wm831x_chg address is 0\n",__FUNCTION__);
147                 return -1;
148         }
149         
150         ret = wm831x_reg_read(wm831x_chg->wm831x, WM831X_SYSTEM_STATUS);
151         if (ret < 0)
152                 return ret;
153
154         if (ret & WM831X_PWR_USB)
155                 usb_chg = 1;
156         if (ret & WM831X_PWR_WALL)
157                 wall_chg = 1;
158
159         return ((usb_chg | wall_chg) ? 1 : 0);
160 }
161
162 static int wm831x_bat_check_status(struct wm831x *wm831x, int *status)
163 {
164         int ret;
165
166         ret = wm831x_reg_read(wm831x, WM831X_SYSTEM_STATUS);
167         if (ret < 0)
168                 return ret;
169
170         if (ret & WM831X_PWR_SRC_BATT) {
171                 *status = POWER_SUPPLY_STATUS_DISCHARGING;
172                 return 0;
173         }
174
175         ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS);
176         if (ret < 0)
177                 return ret;
178
179         
180         switch (ret & WM831X_CHG_STATE_MASK) {
181         case WM831X_CHG_STATE_OFF:
182                 *status = POWER_SUPPLY_STATUS_NOT_CHARGING;
183                 break;
184         case WM831X_CHG_STATE_TRICKLE:
185         case WM831X_CHG_STATE_FAST:
186                 *status = POWER_SUPPLY_STATUS_CHARGING;
187                 break;
188
189         default:
190                 *status = POWER_SUPPLY_STATUS_UNKNOWN;
191                 break;
192         }
193
194         return 0;
195 }
196
197 static int wm831x_read_bat_charging_status(struct wm831x_chg *wm831x_chg)
198 {
199         int ret, status;
200         
201         if(!wm831x_chg)
202         {
203                 printk("err:%s:g_wm831x_power address is 0\n",__FUNCTION__);
204                 return -1;
205         }
206         
207         ret = wm831x_bat_check_status(wm831x_chg->wm831x, &status);
208         if (ret < 0)
209                 return ret;
210         if (status == POWER_SUPPLY_STATUS_CHARGING) 
211                 return 1;
212         return 0;
213 }
214
215 static int wm831x_read_batt_voltage(struct wm831x_chg *wm831x_chg)
216 {
217         int ret = 0;
218         
219         if(!wm831x_chg)
220         {
221                 printk("err:%s:wm831x_chg address is 0\n",__FUNCTION__);
222                 return -1;
223         }
224         
225         ret = wm831x_auxadc_read_uv(wm831x_chg->wm831x, WM831X_AUX_BATT);
226         return ret / 1000;
227 }
228
229
230 static int get_charger_logo_start_num(struct wm831x_chg *wm831x_chg)
231 {
232         int rlogonum, bat_vol;
233
234         /*check charger voltage*/
235         bat_vol = wm831x_read_batt_voltage(wm831x_chg);
236         if(bat_vol <= 3610) {
237                 rlogonum = 0;
238         }
239         else if(bat_vol <= 3700) {
240                 rlogonum = 1;
241         }
242         else if(bat_vol <= 3760) {
243                 rlogonum = 2;
244         }
245         else if(bat_vol <= 3840) {
246                 rlogonum = 3;
247         }
248         else if(bat_vol <= 3900) {
249                 rlogonum = 4;
250         }
251         else if(bat_vol <= 3990) {
252                 rlogonum = 5;
253         }
254         else if(bat_vol <= 4130) {
255                 rlogonum = 6;
256         }
257         else if(bat_vol <= 4200) {
258                 rlogonum = 7;
259         }
260         else{
261                 rlogonum = 7;
262         }
263                 
264         return rlogonum;
265 }
266
267 static int wm831x_check_on_pin(struct wm831x_chg *wm831x_chg)
268 {
269         int ret;
270         ret = wm831x_read_on_pin_status(wm831x_chg);
271         if(ret)
272         {
273                 if(wm831x_chg->cnt_on++ > 1000)
274                         wm831x_chg->cnt_on = 1000;
275         }
276         else
277         {
278                 //control backlight if press on pin
279                 if(wm831x_chg->cnt_on >= 1)
280                 {
281                         wm831x_chg->flag_bl = !wm831x_chg->flag_bl;
282                         charger_backlight_ctrl(wm831x_chg->flag_bl);                    
283                         wm831x_chg->cnt_on = 0; 
284                         if(wm831x_chg->flag_bl)
285                         {
286                                 wm831x_chg->flag_suspend = 0;
287                                 wm831x_chg->cnt_disp = 0;
288                         }
289                 }
290         }
291
292         return 0;
293 }
294
295 static int rk29_charger_display(struct wm831x_chg *wm831x_chg)
296 {
297         int status;
298         struct linux_logo* chargerlogo[8];
299         int ret,i;
300         
301         wm831x_chg->flag_chg = wm831x_read_chg_status(wm831x_chg);
302         if(!wm831x_chg->flag_chg)
303                 return -1;
304
305         while(1)
306         {
307                 wm831x_chg->flag_chg = wm831x_read_chg_status(wm831x_chg);
308                 if(!wm831x_chg->flag_chg)
309                         kernel_power_off();
310
311                 status = wm831x_read_bat_charging_status(wm831x_chg);
312
313                 for(i=0; i<8; i++)
314                 chargerlogo[i] = g_chargerlogo[i];
315         
316                 if(status == BAT_CHARGING)
317                 {       
318                         for(i=get_charger_logo_start_num(wm831x_chg); i<8; i++ )
319                         {
320                                 wm831x_chg->flag_chg = wm831x_read_chg_status(wm831x_chg);
321                                 if(!wm831x_chg->flag_chg)
322                                 kernel_power_off();
323                                 if(wm831x_chg->flag_bl != 0)
324                                 ret = charger_logo_display(chargerlogo[i]);
325
326                                 DBG("%s:i=%d\n",__FUNCTION__,i);
327
328                                 msleep(200);    
329                                 wm831x_check_on_pin(wm831x_chg);
330                                 msleep(200);
331                                 wm831x_check_on_pin(wm831x_chg);
332
333                         }
334                                         
335                 }
336                 else if(status == BAT_DISCHARGING)
337                 {
338                         if(wm831x_chg->flag_bl != 0)
339                         charger_logo_display(chargerlogo[7]);
340                         msleep(200);
341                         wm831x_check_on_pin(wm831x_chg);
342                         msleep(200);
343                         wm831x_check_on_pin(wm831x_chg);
344                 }
345                 
346                 //suspend when timeout(about 50*200ms)
347                 if(wm831x_chg->cnt_disp++ > 50)
348                 {
349                         if(wm831x_chg->flag_suspend == 0)
350                         {
351                                 wm831x_chg->flag_suspend = 1;
352                                 wm831x_chg->cnt_disp = 0;
353                                 wm831x_chg->flag_bl = 0;
354                                 charger_backlight_ctrl(wm831x_chg->flag_bl);
355                         }
356                         wm831x_chg->cnt_disp = 0;
357                 }
358
359                 printk("%s,status=%d,cnt_on=%d,cnt_disp=%d\n",__FUNCTION__,status,wm831x_chg->cnt_on,wm831x_chg->cnt_disp);
360
361                 //open system if long time press
362                 if(wm831x_chg->cnt_on > 4)
363                 {
364                         wm831x_chg->cnt_on = 0;
365                         wm831x_chg->flag_bl = 1;
366                         charger_backlight_ctrl(wm831x_chg->flag_bl);
367                         wm831x_chg->flag_suspend = 0;
368                         wm831x_chg->cnt_disp = 0;
369                         break;
370                 }       
371                 
372         }
373
374         return 0;
375
376 }
377
378 static int __devinit wm831x_chg_probe(struct platform_device *pdev)
379 {
380         struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);;
381         struct wm831x_chg *wm831x_chg;
382         int ret;
383         
384         wm831x_chg = kzalloc(sizeof(struct wm831x_chg), GFP_KERNEL);
385         if (!wm831x_chg) {
386                 dev_err(&pdev->dev, "Can't allocate data\n");
387                 return -ENOMEM;
388         }
389         printk("%s:start\n",__FUNCTION__);
390         wm831x_chg->wm831x = wm831x;
391         wm831x_chg->flag_chg = 0;
392         wm831x_chg->logo_id = 0;
393         wm831x_chg->flag_bl = 1;
394         wm831x_chg->cnt_on = 0;
395         wm831x_chg->flag_suspend = 0;
396         
397         platform_set_drvdata(pdev, wm831x_chg);
398         disable_irq_nosync(wm831x_chg->wm831x->irq_base + WM831X_IRQ_ON);
399         ret = rk29_charger_display(wm831x_chg);
400         enable_irq(wm831x_chg->wm831x->irq_base + WM831X_IRQ_ON);
401         wm831x_chg->flag_chg = 0;
402         wm831x_chg->flag_bl = 1;
403         wm831x_chg->cnt_on = 0;
404         wm831x_chg->flag_suspend = 0;
405
406         printk("%s:exit\n",__FUNCTION__);
407         return 0;
408
409 }
410
411
412 static int __devexit wm831x_chg_remove(struct platform_device *pdev)
413 {
414         struct wm831x_chg *wm831x_chg = platform_get_drvdata(pdev);
415
416         kfree(wm831x_chg);
417
418         return 0;
419 }
420
421 static struct platform_driver wm831x_chg_driver = {
422         .probe          = wm831x_chg_probe,
423         .remove         = __devexit_p(wm831x_chg_remove),
424         .driver         = {
425                 .name   = "wm831x_charger_display",
426                 .owner  = THIS_MODULE,
427         },
428 };
429
430 static int __init wm831x_chg_init(void)
431 {
432         return platform_driver_register(&wm831x_chg_driver);
433 }
434 late_initcall(wm831x_chg_init);
435
436 static void __exit wm831x_chg_exit(void)
437 {
438         platform_driver_unregister(&wm831x_chg_driver);
439 }
440 module_exit(wm831x_chg_exit);
441 #endif
442
443
444 MODULE_LICENSE("GPL");
445 MODULE_AUTHOR("linjh<linjh@rock-chips.com>");
446 MODULE_DESCRIPTION("charger display");