1 /* drivers/power/wm831x_charger_display.c
3 * battery detect driver for the rk2818
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.
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.
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>
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>
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>
41 #define READ_ON_PIN_CNT 20/*11*/
42 #define BACKLIGHT_CNT 2
44 #define MC_OPEN 7/*10*/
45 #define BAT_CHARGING 1
46 #define BAT_DISCHARGING 0
47 #define BL_DELAY_TIME (8*1000)
50 #define SET_BACKLIGHT_ON 1
52 #define SUSPEND_SYSTEM 3
55 #define DBG(x...) printk(x)
60 extern void request_suspend_state(suspend_state_t new_state);
61 extern void kernel_restart(char *cmd);
62 extern void kernel_power_off(void);
64 extern unsigned g_vbus_status_register;
65 extern unsigned long *g_pcd_for_charger;
67 extern int rk29_backlight_ctrl(int open);
69 extern void fb_show_charge_logo(struct linux_logo *logo);
71 extern void kernel_restart_prepare(char *cmd);
72 extern int dwc_vbus_status( void );
73 extern int dwc_otg_pcd_check_vbus_detech( unsigned long pdata );
75 #if defined(CONFIG_LOGO_CHARGER_CLUT224)
76 extern struct linux_logo logo_charger01_clut224;
77 extern struct linux_logo logo_charger02_clut224;
78 extern struct linux_logo logo_charger03_clut224;
79 extern struct linux_logo logo_charger04_clut224;
80 extern struct linux_logo logo_charger05_clut224;
81 extern struct linux_logo logo_charger06_clut224;
82 extern struct linux_logo logo_charger07_clut224;
83 extern struct linux_logo logo_charger08_clut224;
86 extern struct fb_info *g_fb0_inf;
88 static struct linux_logo* g_chargerlogo[8]= {
89 #if defined(CONFIG_LOGO_CHARGER_CLUT224)
90 &logo_charger01_clut224,&logo_charger02_clut224,&logo_charger03_clut224,&logo_charger04_clut224,
91 &logo_charger05_clut224,&logo_charger06_clut224,&logo_charger07_clut224,&logo_charger08_clut224
97 struct wm831x *wm831x;
108 static int charger_logo_display(struct linux_logo *logo)
110 fb_show_charge_logo(logo);
111 fb_show_logo(g_fb0_inf, 0);
115 extern int charger_suspend(void);//xsf
117 static int charger_backlight_ctrl(int open)
119 DBG("%s:open=%d\n",__FUNCTION__,open);
122 #ifdef CONFIG_RK29_CHARGE_EARLYSUSPEND
126 return rk29_backlight_ctrl(open);
132 static int wm831x_read_on_pin_status(struct wm831x_chg *wm831x_chg)
138 printk("err:%s:wm831x_chg address is 0\n",__FUNCTION__);
142 ret = wm831x_reg_read(wm831x_chg->wm831x, WM831X_ON_PIN_CONTROL);
146 return !(ret & WM831X_ON_PIN_STS) ? 1 : 0;
150 static int wm831x_read_chg_status(struct wm831x_chg *wm831x_chg)
152 int ret, usb_chg = 0, wall_chg = 0;
156 printk("err:%s:wm831x_chg address is 0\n",__FUNCTION__);
160 ret = wm831x_reg_read(wm831x_chg->wm831x, WM831X_SYSTEM_STATUS);
164 if (ret & WM831X_PWR_USB)
166 if (ret & WM831X_PWR_WALL)
169 return ((usb_chg | wall_chg) ? 1 : 0);
172 static int wm831x_bat_check_status(struct wm831x *wm831x, int *status)
176 ret = wm831x_reg_read(wm831x, WM831X_SYSTEM_STATUS);
180 if (ret & WM831X_PWR_SRC_BATT) {
181 *status = POWER_SUPPLY_STATUS_DISCHARGING;
185 ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS);
190 switch (ret & WM831X_CHG_STATE_MASK) {
191 case WM831X_CHG_STATE_OFF:
192 *status = POWER_SUPPLY_STATUS_NOT_CHARGING;
194 case WM831X_CHG_STATE_TRICKLE:
195 case WM831X_CHG_STATE_FAST:
196 *status = POWER_SUPPLY_STATUS_CHARGING;
200 *status = POWER_SUPPLY_STATUS_UNKNOWN;
207 static int wm831x_read_bat_charging_status(struct wm831x_chg *wm831x_chg)
213 printk("err:%s:g_wm831x_power address is 0\n",__FUNCTION__);
217 ret = wm831x_bat_check_status(wm831x_chg->wm831x, &status);
220 if (status == POWER_SUPPLY_STATUS_CHARGING)
225 static int wm831x_read_batt_voltage(struct wm831x_chg *wm831x_chg)
231 printk("err:%s:wm831x_chg address is 0\n",__FUNCTION__);
235 ret = wm831x_auxadc_read_uv(wm831x_chg->wm831x, WM831X_AUX_BATT);
240 static int get_charger_logo_start_num(struct wm831x_chg *wm831x_chg)
242 int rlogonum, bat_vol;
244 /*check charger voltage*/
245 bat_vol = wm831x_read_batt_voltage(wm831x_chg);
246 if(bat_vol <= 3610) {
249 else if(bat_vol <= 3700) {
252 else if(bat_vol <= 3760) {
255 else if(bat_vol <= 3840) {
258 else if(bat_vol <= 3900) {
261 else if(bat_vol <= 3990) {
264 else if(bat_vol <= 4130) {
267 else if(bat_vol <= 4200) {
277 static int wm831x_check_on_pin(struct wm831x_chg *wm831x_chg)
280 ret = wm831x_read_on_pin_status(wm831x_chg);
283 if(wm831x_chg->cnt_on++ > 1000)
284 wm831x_chg->cnt_on = 1000;
288 //control backlight if press on pin
289 if(wm831x_chg->cnt_on >= 1)
291 wm831x_chg->flag_bl = !wm831x_chg->flag_bl;
292 charger_backlight_ctrl(wm831x_chg->flag_bl);
293 wm831x_chg->cnt_on = 0;
294 if(wm831x_chg->flag_bl)
296 wm831x_chg->flag_suspend = 0;
297 wm831x_chg->cnt_disp = 0;
305 static int rk29_charger_display(struct wm831x_chg *wm831x_chg)
308 struct linux_logo* chargerlogo[8];
312 wm831x_chg->flag_chg = wm831x_read_chg_status(wm831x_chg);
313 if(!wm831x_chg->flag_chg)
318 wm831x_chg->flag_chg = wm831x_read_chg_status(wm831x_chg);
319 if(!wm831x_chg->flag_chg)
322 status = wm831x_read_bat_charging_status(wm831x_chg);
325 chargerlogo[i] = g_chargerlogo[i];
327 if(status == BAT_CHARGING)
329 for(i=get_charger_logo_start_num(wm831x_chg); i<8; i++ )
331 wm831x_chg->flag_chg = wm831x_read_chg_status(wm831x_chg);
332 if(!wm831x_chg->flag_chg)
334 #ifdef CONFIG_RK29_CHARGE_EARLYSUSPEND
335 ret = charger_logo_display(chargerlogo[i]);
337 if(wm831x_chg->flag_bl != 0)
338 ret = charger_logo_display(chargerlogo[i]);
340 DBG("%s:i=%d\n",__FUNCTION__,i);
343 wm831x_check_on_pin(wm831x_chg);
345 wm831x_check_on_pin(wm831x_chg);
350 else if(status == BAT_DISCHARGING)
353 #ifdef CONFIG_RK29_CHARGE_EARLYSUSPEND
354 charger_logo_display(chargerlogo[7]);
356 if(wm831x_chg->flag_bl != 0)
357 charger_logo_display(chargerlogo[7]);
360 wm831x_check_on_pin(wm831x_chg);
362 wm831x_check_on_pin(wm831x_chg);
365 //suspend when timeout(about 50*200ms)
366 if(wm831x_chg->cnt_disp++ > 50)
368 if(wm831x_chg->flag_suspend == 0)
370 wm831x_chg->flag_suspend = 1;
371 wm831x_chg->cnt_disp = 0;
372 wm831x_chg->flag_bl = 0;
373 charger_backlight_ctrl(wm831x_chg->flag_bl);
374 #ifdef CONFIG_RK29_CHARGE_EARLYSUSPEND
375 wm831x_chg->flag_suspend = 0;
379 wm831x_chg->cnt_disp = 0;
382 printk("%s,status=%d,cnt_on=%d,cnt_disp=%d\n",__FUNCTION__,status,wm831x_chg->cnt_on,wm831x_chg->cnt_disp);
384 //open system if long time press
385 if(wm831x_chg->cnt_on > 4)
387 wm831x_chg->cnt_on = 0;
388 wm831x_chg->flag_bl = 1;
389 charger_backlight_ctrl(wm831x_chg->flag_bl);
390 wm831x_chg->flag_suspend = 0;
391 wm831x_chg->cnt_disp = 0;
401 static irqreturn_t wm831x_charge_irq(int irq, void *data)
404 printk("wm831x_charge_irqxxaddxsf\n");
409 extern struct wm831x_on *g_wm831x_on;
410 irqreturn_t wm831x_on_irq(int irq, void *data);
412 static int __devinit wm831x_chg_probe(struct platform_device *pdev)
414 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);;
415 struct wm831x_chg *wm831x_chg;
417 // struct wm831x_on *wm831x_on = container_of(wm831x,struct wm831x_on,*(wm831x));
422 wm831x_chg = kzalloc(sizeof(struct wm831x_chg), GFP_KERNEL);
424 dev_err(&pdev->dev, "Can't allocate data\n");
428 printk("%s:start\n",__FUNCTION__);
429 wm831x_chg->wm831x = wm831x;
430 wm831x_chg->flag_chg = 0;
431 wm831x_chg->logo_id = 0;
432 wm831x_chg->flag_bl = 1;
433 wm831x_chg->cnt_on = 0;
434 wm831x_chg->flag_suspend = 0;
435 platform_set_drvdata(pdev, wm831x_chg);
437 #ifdef CONFIG_RK29_CHARGE_EARLYSUSPEND
438 wm831x_chg->flag_chg = wm831x_read_chg_status(wm831x_chg);
439 if(wm831x_chg->flag_chg != 0)
441 free_irq(wm831x_chg->wm831x->irq_base + WM831X_IRQ_ON,g_wm831x_on);
442 request_threaded_irq(wm831x_chg->wm831x->irq_base + WM831X_IRQ_ON,
443 NULL, wm831x_charge_irq,IRQF_TRIGGER_RISING, "wm831x_charge",
446 ret = rk29_charger_display(wm831x_chg);
449 free_irq(wm831x_chg->wm831x->irq_base + WM831X_IRQ_ON,wm831x_chg);
450 request_threaded_irq(wm831x_chg->wm831x->irq_base + WM831X_IRQ_ON,
451 NULL, wm831x_on_irq,IRQF_TRIGGER_RISING, "wm831x_on", g_wm831x_on);
454 disable_irq_nosync(wm831x_chg->wm831x->irq_base + WM831X_IRQ_ON);
455 ret = rk29_charger_display(wm831x_chg);
456 enable_irq(wm831x_chg->wm831x->irq_base + WM831X_IRQ_ON);
458 wm831x_chg->flag_chg = 0;
459 wm831x_chg->flag_bl = 1;
460 wm831x_chg->cnt_on = 0;
461 wm831x_chg->flag_suspend = 0;
463 printk("%s:exit\n",__FUNCTION__);
469 static int __devexit wm831x_chg_remove(struct platform_device *pdev)
471 struct wm831x_chg *wm831x_chg = platform_get_drvdata(pdev);
478 static struct platform_driver wm831x_chg_driver = {
479 .probe = wm831x_chg_probe,
480 .remove = __devexit_p(wm831x_chg_remove),
482 .name = "wm831x_charger_display",
483 .owner = THIS_MODULE,
487 static int __init wm831x_chg_init(void)
489 return platform_driver_register(&wm831x_chg_driver);
491 late_initcall(wm831x_chg_init);
493 static void __exit wm831x_chg_exit(void)
495 platform_driver_unregister(&wm831x_chg_driver);
497 module_exit(wm831x_chg_exit);
501 MODULE_LICENSE("GPL");
502 MODULE_AUTHOR("linjh<linjh@rock-chips.com>");
503 MODULE_DESCRIPTION("charger display");