tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / video / sprdfb / sprdfb_panel.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/mutex.h>
16 #include <linux/list.h>
17 #include <linux/delay.h>
18 #include <linux/fb.h>
19 #include <mach/gpio.h>
20 #ifdef CONFIG_LCD_CLASS_DEVICE
21 #include <linux/platform_device.h>
22 #include <linux/lcd.h>
23 #endif
24 #include "sprdfb.h"
25 #include "sprdfb_panel.h"
26 #include "sprdfb_dispc_reg.h"
27
28 #define MTP_LEN 0x21
29
30 static LIST_HEAD(panel_list_main);/* for main_lcd*/
31 static LIST_HEAD(panel_list_sub);/* for sub_lcd */
32 static DEFINE_MUTEX(panel_mutex);
33 static unsigned char mtp_offset_from_uboot[((MTP_LEN + 6) * 2) + 1] = {0};
34 static unsigned char hbm_offset_from_uboot[(15 * 2) + 1] = {0};
35 static unsigned char chip_id_from_uboot[(5 * 2) + 1] = {0};
36 static unsigned char color_offset_from_uboot[(4 * 2) + 1] = {0};
37
38 uint32_t lcd_id_from_uboot = 0;
39 unsigned long lcd_base_from_uboot = 0;
40 uint8_t elvss_offset_from_uboot = 0;
41 uint8_t mtp_offset_t[MTP_LEN + 6] = {0};
42 uint8_t hbm_offset_t[15] = {0};
43 uint8_t chip_id_t[5] = {0};
44 uint8_t color_offset_t[4] = {0};
45 uint8_t g_mtp_offset_error = 0;
46
47 extern struct panel_if_ctrl sprdfb_mcu_ctrl;
48 extern struct panel_if_ctrl sprdfb_rgb_ctrl;
49 #ifndef CONFIG_FB_SCX15
50 extern struct panel_if_ctrl sprdfb_mipi_ctrl;
51 #endif
52 extern void sprdfb_panel_remove(struct sprdfb_device *dev);
53
54 #ifdef CONFIG_SPRDFB_MDNIE_LITE_TUNING
55 extern int sprdfb_mdnie_reg (struct sprdfb_device *dev, mdnie_w w, mdnie_r r, mdnie_c c);
56 extern void mdnie_state_restore(struct sprdfb_device *fb_dev);
57 #endif
58
59 #ifdef ENABLE_CLK_HS_ON_INIT
60 extern int32_t sprdfb_dsi_hs_ready(struct sprdfb_device *dev);
61 #endif
62
63 static void parse_string_to_hex(unsigned char *input, uint8_t *output, uint8_t len)
64 {
65         int i = 0, j = 1, l = 0;
66
67         while (input[i] != '\0' && l < len) {
68                 if (input[j] >= '0' && input[j] <= '9') {
69                         output[l] = input[j] - '0';
70                 } else if (input[j] >= 'a' && input[j] <= 'f') {
71                         output[l] = input[j] - 'a' + 10;
72                 } else {
73                         output[l] = 0;
74                         pr_err("Error while parsing in %s\n", __FUNCTION__);
75                 }
76
77                 if (input[i] >= '0' && input[i] <= '9') {
78                         output[l] = output[l] + ((input[i] - '0') * 16);
79                 } else if (input[i] >= 'a' && input[i] <= 'f') {
80                         output[l] = output[l] + ((input[i] - 'a' + 10) * 16);
81                 } else {
82                         pr_err("Error parsing in %s\n", __FUNCTION__);
83                 }
84                 l++;
85                 i = i + 2;
86                 j = j + 2;
87         }
88 }
89
90 static int __init lcd_id_get(char *str)
91 {
92         if ((str != NULL) && (str[0] == 'I') && (str[1] == 'D')) {
93                 sscanf(&str[2], "%x", &lcd_id_from_uboot);
94         }
95         printk(KERN_INFO "sprdfb: [%s]LCD Panel ID from uboot: 0x%x\n", __FUNCTION__, lcd_id_from_uboot);
96         return 1;
97 }
98 __setup("lcd_id=", lcd_id_get);
99 static int __init lcd_base_get(char *str)
100 {
101         if (str != NULL) {
102                 sscanf(&str[0], "%lx", &lcd_base_from_uboot);
103         }
104         printk(KERN_INFO "sprdfb: [%s]LCD Panel Base from uboot: 0x%lx\n", __FUNCTION__, lcd_base_from_uboot);
105         return 1;
106 }
107 __setup("lcd_base=", lcd_base_get);
108
109 static int __init mtp_offset_get(char *str)
110 {
111         if (str != NULL) {
112                 sscanf(&str[0], "%s", &mtp_offset_from_uboot);
113         }
114
115         parse_string_to_hex(mtp_offset_from_uboot, mtp_offset_t, MTP_LEN + 6);
116
117         if (mtp_offset_t[30] != 2 || mtp_offset_t[31] != 3 ||
118                 mtp_offset_t[32] != 2)
119                 g_mtp_offset_error = 1;
120
121         printk(KERN_INFO "sprdfb: [%s]Panel mtp offset from uboot: %s\n", __FUNCTION__, mtp_offset_from_uboot);
122
123         return 1;
124 }
125 __setup("mtp_offset=", mtp_offset_get);
126
127 static int __init elvss_offset_get(char *str)
128 {
129         if (str != NULL) {
130                 sscanf(&str[0], "%x", &elvss_offset_from_uboot);
131         }
132         printk(KERN_INFO "sprdfb: [%s]Panel elvss offset from uboot: 0x%x\n", __FUNCTION__, elvss_offset_from_uboot);
133         return 1;
134 }
135 __setup("elvss_offset=", elvss_offset_get);
136
137 static int __init hbm_offset_get(char *str)
138 {
139         if (str != NULL) {
140                 sscanf(&str[0], "%s", &hbm_offset_from_uboot);
141         }
142
143         parse_string_to_hex(hbm_offset_from_uboot, hbm_offset_t, 15);
144
145         printk(KERN_INFO "sprdfb: [%s]Panel hbm offset from uboot: %s\n", __FUNCTION__, hbm_offset_from_uboot);
146
147         return 1;
148 }
149 __setup("hbm_offset=", hbm_offset_get);
150
151 static int __init chip_id_get(char *str)
152 {
153         if (str != NULL) {
154                 sscanf(&str[0], "%s", &chip_id_from_uboot);
155         }
156
157         parse_string_to_hex(chip_id_from_uboot, chip_id_t, 5);
158
159         printk(KERN_INFO "sprdfb: [%s]Panel chip id from uboot: %s\n", __FUNCTION__, chip_id_from_uboot);
160
161         return 1;
162 }
163 __setup("chip_id=", chip_id_get);
164
165 static int __init color_offset_get(char *str)
166 {
167         if (str != NULL) {
168                 sscanf(&str[0], "%s", &color_offset_from_uboot);
169         }
170
171         parse_string_to_hex(color_offset_from_uboot, color_offset_t, 4);
172
173         printk(KERN_INFO "sprdfb: [%s]Panel color offset from uboot: %s\n", __FUNCTION__, color_offset_from_uboot);
174
175         return 1;
176 }
177 __setup("color_offset=", color_offset_get);
178
179 static int32_t panel_reset_dispc(struct panel_spec *self)
180 {
181         uint16_t timing1, timing2, timing3;
182
183         if((NULL != self) && (0 != self->reset_timing.time1) &&
184             (0 != self->reset_timing.time2) && (0 != self->reset_timing.time3)) {
185             timing1 = self->reset_timing.time1;
186             timing2 = self->reset_timing.time2;
187             timing3 = self->reset_timing.time3;
188         }else {
189             timing1 = 20;
190             timing2 = 20;
191             timing3 = 20;
192         }
193 #ifdef CONFIG_FB_LCD_S6E8AA5X01_MIPI
194         if (gpio_is_valid(self->rst_gpio)) {
195                 gpio_direction_output(self->rst_gpio, 1);
196                 usleep_range(10000, 11000);
197                 gpio_direction_output(self->rst_gpio, 0);
198                 usleep_range(5000, 6000);
199                 gpio_direction_output(self->rst_gpio, 1);
200                 /* wait 10ms util the lcd is stable */
201                 usleep_range(5000, 6000);
202         }
203 #else
204         dispc_write(1, DISPC_RSTN);
205         usleep_range(timing1*1000, timing1*1000+500);
206         dispc_write(0, DISPC_RSTN);
207         usleep_range(timing2*1000, timing2*1000+500);
208         dispc_write(1, DISPC_RSTN);
209
210         /* wait 10ms util the lcd is stable */
211         usleep_range(timing3*1000, timing3*1000+500);
212 #endif
213         return 0;
214 }
215
216 static int32_t panel_set_resetpin_dispc(struct panel_spec *self, uint32_t status)
217 {
218 #ifdef CONFIG_FB_LCD_S6E8AA5X01_MIPI
219         if (gpio_is_valid(self->rst_gpio)) {
220                 if (status)
221                         gpio_direction_output(self->rst_gpio, 1);
222                 else
223                         gpio_direction_output(self->rst_gpio, 0);
224         }
225 #else
226         if(0 == status){
227                 dispc_write(0, DISPC_RSTN);
228         }else{
229                 dispc_write(1, DISPC_RSTN);
230         }
231 #endif
232         return 0;
233 }
234
235 static int panel_power_on(struct sprdfb_device *dev, bool enable)
236 {
237         if((NULL == dev) || (NULL == dev->panel)){
238                 printk(KERN_ERR "sprdfb: [%s]: Invalid param\n", __FUNCTION__);
239                 return -1;
240         }
241
242         pr_debug("sprdfb: [%s], enter\n",__FUNCTION__);
243
244         /* panel ldo en*/
245         if (dev->panel->ops->panel_power_on)
246                 dev->panel->ops->panel_power_on(dev, enable);
247
248         return 0;
249 }
250
251
252 static int panel_reset(struct sprdfb_device *dev)
253 {
254         if((NULL == dev) || (NULL == dev->panel)){
255                 printk(KERN_ERR "sprdfb: [%s]: Invalid param\n", __FUNCTION__);
256                 return -1;
257         }
258
259         pr_debug("sprdfb: [%s], enter\n",__FUNCTION__);
260
261         //clk/data lane enter LP
262         if(NULL != dev->panel->if_ctrl->panel_if_before_panel_reset){
263                 dev->panel->if_ctrl->panel_if_before_panel_reset(dev);
264         }
265         usleep_range(5000, 5500);
266
267         //reset panel
268         dev->panel->ops->panel_reset(dev->panel);
269
270         return 0;
271 }
272
273 static int panel_sleep(struct sprdfb_device *dev)
274 {
275         if((NULL == dev) || (NULL == dev->panel)){
276                 printk(KERN_ERR "sprdfb: [%s]: Invalid param\n", __FUNCTION__);
277                 return -1;
278         }
279
280         pr_debug("sprdfb: [%s], enter\n",__FUNCTION__);
281
282         //send sleep cmd to lcd
283         if (dev->panel->ops->panel_enter_sleep != NULL) {
284                 dev->panel->ops->panel_enter_sleep(dev->panel,1);
285         }
286         msleep(100);
287         //clk/data lane enter LP
288         if((NULL != dev->panel->if_ctrl->panel_if_before_panel_reset)
289                 &&(SPRDFB_PANEL_TYPE_MIPI == dev->panel->type))
290         {
291                 dev->panel->if_ctrl->panel_if_before_panel_reset(dev);
292         }
293         return 0;
294 }
295
296 static void panel_set_resetpin(uint16_t dev_id,  uint32_t status, struct panel_spec *panel )
297 {
298         pr_debug("sprdfb: [%s].\n",__FUNCTION__);
299
300         /*panel set reset pin status*/
301         if(SPRDFB_MAINLCD_ID == dev_id){
302                 panel_set_resetpin_dispc(panel, status);
303         }
304 }
305
306
307 static int32_t panel_before_resume(struct sprdfb_device *dev)
308 {
309         /*restore  the reset pin to high*/
310         panel_set_resetpin(dev->dev_id, 1, dev->panel);
311         return 0;
312 }
313
314 static int32_t panel_after_suspend(struct sprdfb_device *dev)
315 {
316         /*set the reset pin to low*/
317         panel_set_resetpin(dev->dev_id, 0, dev->panel);
318         usleep_range(1000, 1100);
319
320         return 0;
321 }
322
323 static bool panel_check(struct panel_cfg *cfg)
324 {
325         bool rval = true;
326
327         if(NULL == cfg || NULL == cfg->panel){
328                 printk(KERN_ERR "sprdfb: [%s] :Invalid Param!\n", __FUNCTION__);
329                 return false;
330         }
331
332         pr_debug("sprdfb: [%s], dev_id = %d, lcd_id = 0x%x, type = %d\n",__FUNCTION__, cfg->dev_id, cfg->lcd_id, cfg->panel->type);
333
334         switch(cfg->panel->type){
335         case SPRDFB_PANEL_TYPE_MCU:
336                 cfg->panel->if_ctrl = &sprdfb_mcu_ctrl;
337                 break;
338         case SPRDFB_PANEL_TYPE_RGB:
339         case SPRDFB_PANEL_TYPE_LVDS:
340                 cfg->panel->if_ctrl = &sprdfb_rgb_ctrl;
341                 break;
342 #ifndef CONFIG_FB_SCX15
343         case SPRDFB_PANEL_TYPE_MIPI:
344                 cfg->panel->if_ctrl = &sprdfb_mipi_ctrl;
345                 break;
346 #endif
347         default:
348                 printk("sprdfb: [%s]: erro panel type.(%d,%d, %d)",__FUNCTION__, cfg->dev_id, cfg->lcd_id, cfg->panel->type);
349                 cfg->panel->if_ctrl = NULL;
350                 break;
351         };
352
353         if(cfg->panel->if_ctrl->panel_if_check){
354                 rval = cfg->panel->if_ctrl->panel_if_check(cfg->panel);
355         }
356         return rval;
357 }
358
359 static int panel_mount(struct sprdfb_device *dev, struct panel_spec *panel)
360 {
361         printk("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
362
363         /* TODO: check whether the mode/res are supported */
364         dev->panel = panel;
365
366         if(NULL == dev->panel->ops->panel_reset){
367                 if(SPRDFB_MAINLCD_ID == dev->dev_id){
368                         dev->panel->ops->panel_reset = panel_reset_dispc;
369                 }
370         }
371
372         panel->if_ctrl->panel_if_mount(dev);
373
374         return 0;
375 }
376
377
378 int panel_init(struct sprdfb_device *dev)
379 {
380         if((NULL == dev) || (NULL == dev->panel)){
381                 printk(KERN_ERR "sprdfb: [%s]: Invalid param\n", __FUNCTION__);
382                 return -1;
383         }
384
385         pr_debug("sprdfb: [%s], dev_id= %d, type = %d\n",__FUNCTION__, dev->dev_id, dev->panel->type);
386
387         if(!dev->panel->if_ctrl->panel_if_init(dev)){
388                 printk(KERN_ERR "sprdfb: [%s]: panel_if_init fail!\n", __FUNCTION__);
389                 return -1;
390         }
391
392         return 0;
393 }
394
395 int panel_ready(struct sprdfb_device *dev)
396 {
397         if((NULL == dev) || (NULL == dev->panel)){
398                 printk(KERN_ERR "sprdfb: [%s]: Invalid param\n", __FUNCTION__);
399                 return -1;
400         }
401
402         pr_debug("sprdfb: [%s], dev_id= %d, type = %d\n",__FUNCTION__, dev->dev_id, dev->panel->type);
403
404         if(NULL != dev->panel->if_ctrl->panel_if_ready){
405                 dev->panel->if_ctrl->panel_if_ready(dev);
406         }
407
408         return 0;
409 }
410
411
412 static struct panel_spec *adapt_panel_from_uboot(uint16_t dev_id)
413 {
414         struct panel_cfg *cfg;
415         struct list_head *panel_list;
416
417         pr_debug("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev_id);
418
419         if (lcd_id_from_uboot == 0) {
420                 printk("sprdfb: [%s]: Not got lcd id from uboot\n", __FUNCTION__);
421                 return NULL;
422         }
423
424         if(SPRDFB_MAINLCD_ID == dev_id){
425                 panel_list = &panel_list_main;
426         }else{
427                 panel_list = &panel_list_sub;
428         }
429
430         list_for_each_entry(cfg, panel_list, list) {
431                 if(lcd_id_from_uboot == cfg->lcd_id) {
432                         printk(KERN_INFO "sprdfb: [%s]: LCD Panel 0x%x is attached!\n", __FUNCTION__,cfg->lcd_id);
433                         return cfg->panel;
434                 }
435         }
436         printk(KERN_ERR "sprdfb: [%s]: Failed to match LCD Panel from uboot!\n", __FUNCTION__);
437
438         return NULL;
439 }
440
441 static struct panel_spec *adapt_panel_from_readid(struct sprdfb_device *dev)
442 {
443         struct panel_cfg *cfg;
444         struct panel_cfg *dummy_cfg = NULL;
445         struct list_head *panel_list;
446         uint32_t id;
447
448         printk("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
449
450         if(SPRDFB_MAINLCD_ID == dev->dev_id){
451                 panel_list = &panel_list_main;
452         }else{
453                 panel_list = &panel_list_sub;
454         }
455
456         list_for_each_entry(cfg, panel_list, list) {
457                 if(0xFFFFFFFF == cfg->lcd_id){
458                         dummy_cfg = cfg;
459                         continue;
460                 }
461                 printk("sprdfb: [%s]: try panel 0x%x\n", __FUNCTION__, cfg->lcd_id);
462                 panel_mount(dev, cfg->panel);
463 #ifndef CONFIG_SC_FPGA
464                 dev->ctrl->update_clk(dev);
465 #endif
466                 panel_init(dev);
467                 panel_reset(dev);
468                 id = dev->panel->ops->panel_readid(dev->panel);
469                 if(id == cfg->lcd_id) {
470                         pr_debug(KERN_INFO "sprdfb: [%s]: LCD Panel 0x%x is attached!\n", __FUNCTION__, cfg->lcd_id);
471                         dev->panel->ops->panel_init(dev->panel);
472                         panel_ready(dev);
473                         return cfg->panel;
474                 }
475                 sprdfb_panel_remove(dev);
476         }
477         if(dummy_cfg != NULL){
478                 printk("sprdfb: [%s]: Can't find read panel, Use dummy panel!\n", __FUNCTION__);
479                 panel_mount(dev, dummy_cfg->panel);
480 #ifndef CONFIG_SC_FPGA
481                 dev->ctrl->update_clk(dev);
482 #endif
483                 panel_init(dev);
484                 panel_reset(dev);
485                 id = dev->panel->ops->panel_readid(dev->panel);
486                 if(id == dummy_cfg->lcd_id) {
487                         pr_debug(KERN_INFO "sprdfb: [%s]: LCD Panel 0x%x is attached!\n", __FUNCTION__, dummy_cfg->lcd_id);
488                         dev->panel->ops->panel_init(dev->panel);
489                         panel_ready(dev);
490                         return dummy_cfg->panel;
491                 }
492                 sprdfb_panel_remove(dev);
493         }
494         printk(KERN_ERR "sprdfb:  [%s]: failed to attach LCD Panel!\n", __FUNCTION__);
495         return NULL;
496 }
497
498
499 bool sprdfb_panel_get(struct sprdfb_device *dev)
500 {
501         struct panel_spec *panel = NULL;
502
503         if(NULL == dev){
504                 printk("sprdfb: [%s]: Invalid param\n", __FUNCTION__);
505                 return false;
506         }
507
508         printk("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
509
510         panel = adapt_panel_from_uboot(dev->dev_id);
511         if (panel) {
512                 dev->panel_ready = true;
513                 panel_mount(dev, panel);
514                 panel_init(dev);
515                 printk("sprdfb: [%s] got panel\n", __FUNCTION__);
516                 return true;
517         }
518
519         printk("sprdfb: [%s] can not got panel\n", __FUNCTION__);
520
521         return false;
522 }
523
524 #if defined(CONFIG_LCD_CLASS_DEVICE)
525 static ssize_t show_lcd_info(struct device *dev,
526                         struct device_attribute *attr, char *buf)
527 {
528         struct sprdfb_device *fb_dev = dev_get_drvdata(dev);
529         unsigned int panel_id = lcd_id_from_uboot;
530
531         if (fb_dev->panel->ops->panel_get_type)
532                 return fb_dev->panel->ops->panel_get_type(buf, panel_id);
533
534         return sprintf(buf, "Unknown panel %X", panel_id);
535 }
536
537 static int sprdfb_set_power(struct lcd_device *ld, int power)
538 {
539         int ret = 0;
540         struct sprdfb_device *lcd = lcd_get_data(ld);
541
542         if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
543                 power != FB_BLANK_NORMAL)
544                 return -EINVAL;
545
546         if (lcd->power == power) {
547                 printk("power is same as previous mode\n");
548                 return -EINVAL;
549         }
550
551         lcd->power = power;
552
553         printk("sprdfb: [%s] power[%d]\n", __FUNCTION__, lcd->power);
554
555         return ret;
556 }
557
558 static int sprdfb_get_power(struct lcd_device *ld)
559 {
560         struct sprdfb_device *lcd = lcd_get_data(ld);
561
562         printk("sprdfb: [%s] power[%d]\n", __FUNCTION__, lcd->power);
563
564         return lcd->power;
565 }
566
567 static struct lcd_ops ld_ops = {
568         .get_power = sprdfb_get_power,
569         .set_power = sprdfb_set_power,
570 };
571
572 static ssize_t show_lcd_info(struct device *dev,
573                         struct device_attribute *attr, char *buf);
574
575 #ifdef CONFIG_FB_DEBUG_LCD_TUNING
576 static ssize_t lcd_init_show(struct device *dev,
577                                 struct device_attribute *attr,
578                                 char *buf)
579 {
580         printk("++ [%s] current lcd init seq\n", __func__);
581
582         return 0;
583 }
584
585 static ssize_t lcd_init_store(struct device *dev,
586                                 struct device_attribute *attr,
587                                 const char *buf, size_t size)
588 {
589         int ret = 0;
590         printk("++ [%s] current lcd init seq\n", __func__);
591         ret = lcd_store_panel_init_cmd();
592
593         return ret;
594 }
595 #endif
596
597 static struct device_attribute lcd_device_attributes[] = {
598         __ATTR(lcd_type, S_IRUGO, show_lcd_info, NULL),
599 #ifdef CONFIG_FB_DEBUG_LCD_TUNING
600         __ATTR(lcd_tune, 0664, lcd_init_show, lcd_init_store),
601 #endif
602 };
603
604 static bool sprdfb_lcd_class_register(struct platform_device *pdev,
605                                                 struct sprdfb_device *dev)
606 {
607         int i, ret;
608
609         dev->ld = lcd_device_register("panel", &pdev->dev, dev, &ld_ops);
610         if (IS_ERR(dev->ld)) {
611                 printk("failed to register ld ops\n");
612                 return false;
613         }
614
615         dev->power = FB_BLANK_UNBLANK;
616
617         for (i = 0; i < ARRAY_SIZE(lcd_device_attributes); i++) {
618                 ret = device_create_file(&dev->ld->dev,
619                                 &lcd_device_attributes[i]);
620                 if (ret < 0) {
621                         printk("failed to add ld dev sysfs entries\n");
622                         goto err_lcd;
623                 }
624         }
625
626         return true;
627 err_lcd:
628         lcd_device_unregister(dev->ld);
629         return false;
630 }
631 #endif
632
633 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE)
634 static int panel_update_brightness(struct backlight_device *bd)
635 {
636         struct sprdfb_device *dev = bl_get_data(bd);
637         int ret = 0;
638
639         if (dev->power > FB_BLANK_NORMAL) {
640                 pr_err("%s: invalid power[%d]\n", __func__, dev->power);
641                 return -EPERM;
642         }
643         ret = dev->panel->ops->panel_set_brightness(dev, bd->props.brightness);
644
645         return ret;
646 }
647
648 static int panel_get_brightness(struct backlight_device *bd)
649 {
650         return bd->props.brightness;
651 }
652
653 static struct backlight_ops backlight_ops = {
654         .get_brightness = panel_get_brightness,
655         .update_status = panel_update_brightness,
656 };
657
658 static bool sprdfb_backlight_class_register(struct platform_device *pdev,
659                                                 struct sprdfb_device *dev)
660 {
661         int ret;
662
663         dev->bd = backlight_device_register("panel", &pdev->dev, dev,
664                         &backlight_ops, NULL);
665         if (IS_ERR(dev->bd)) {
666                 dev_err(&pdev->dev, "failed to register backlight ops.\n");
667                 return false;
668         }
669
670         dev->bd->props.max_brightness = 100;
671         dev->bd->props.brightness = 60;
672         dev->bd->props.type = BACKLIGHT_PLATFORM;
673
674         return true;
675 }
676 #endif
677
678
679 bool sprdfb_panel_init(struct platform_device *pdev, struct sprdfb_device *dev)
680 {
681
682         if (lcd_id_from_uboot == 0) {
683                 printk("sprdfb: panel is not connected\n");
684                 return true;
685         }
686 #if defined(CONFIG_LCD_CLASS_DEVICE)
687         if(!sprdfb_lcd_class_register(pdev, dev)) {
688                 printk("sprdfb: failed to register lcd_class\n");
689                 return false;
690         }
691 #endif
692
693 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE)
694         if (dev->panel->oled) {
695                 if (!sprdfb_backlight_class_register(pdev, dev)) {
696                         printk("sprdfb: failed to register backlight_class\n");
697                         return false;
698                 }
699                 if (dev->panel->ops->panel_dimming_init)
700                         dev->panel->ops->panel_dimming_init(dev->panel, &pdev->dev);
701         }
702 #endif
703         if (dev->panel->ops->panel_initialize) {
704                 if (dev->panel->ops->panel_initialize(dev, &pdev->dev)) {
705                         printk("sprdfb: failed to intialize panel.\n");
706                         return false;
707                 }
708         }
709 #ifdef CONFIG_SPRDFB_MDNIE_LITE_TUNING
710         sprdfb_mdnie_reg(dev, dev->panel->ops->panel_send_mdnie_cmds, NULL, dev->panel->ops->panel_get_color_coordinates);
711 #endif
712
713         if (dev->panel->ops->panel_read_offset)
714                 dev->panel->ops->panel_read_offset(dev->panel);
715
716         return true;
717 }
718
719 bool sprdfb_panel_probe(struct platform_device *pdev, struct sprdfb_device *dev)
720 {
721         struct panel_spec *panel;
722
723         if(NULL == dev){
724                 printk("sprdfb: [%s]: Invalid param\n", __FUNCTION__);
725                 return false;
726         }
727
728         printk("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
729
730         /* can not be here in normal; we should get correct device id from uboot */
731         panel = adapt_panel_from_readid(dev);
732
733         if (panel) {
734                 if (!sprdfb_panel_init(pdev, dev)) {
735                         printk("sprdfb: failed to register panel class\n");
736                         return false;
737                 }
738                 printk("sprdfb: [%s] got panel\n", __FUNCTION__);
739                 return true;
740         }
741
742         printk("sprdfb: [%s] can not got panel\n", __FUNCTION__);
743
744         return false;
745 }
746
747 void sprdfb_panel_invalidate_rect(struct panel_spec *self,
748                                 uint16_t left, uint16_t top,
749                                 uint16_t right, uint16_t bottom)
750 {
751         /*Jessica TODO: */
752         if(NULL != self->ops->panel_invalidate_rect){
753                 self->ops->panel_invalidate_rect(self, left, top, right, bottom);
754         }
755         /*Jessica TODO: Need set timing to GRAM timing*/
756 }
757
758 void sprdfb_panel_invalidate(struct panel_spec *self)
759 {
760         /*Jessica TODO:*/
761         if(NULL != self->ops->panel_invalidate){
762                 self->ops->panel_invalidate(self);
763         }
764         /*Jessica TODO: Need set timing to GRAM timing*/
765 }
766
767 void sprdfb_panel_before_refresh(struct sprdfb_device *dev)
768 {
769         if(NULL != dev->panel->if_ctrl->panel_if_before_refresh){
770                 dev->panel->if_ctrl->panel_if_before_refresh(dev);
771         }
772 }
773
774 void sprdfb_panel_after_refresh(struct sprdfb_device *dev)
775 {
776         if(NULL != dev->panel->if_ctrl->panel_if_after_refresh){
777                 dev->panel->if_ctrl->panel_if_after_refresh(dev);
778         }
779 }
780
781 #ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING
782 void sprdfb_panel_change_fps(struct sprdfb_device *dev, int fps_level)
783 {
784         if (dev->panel->ops->panel_change_fps!= NULL) {
785                 printk("sprdfb: [%s] fps_level= %d\n", __FUNCTION__,fps_level);
786                 dev->panel->ops->panel_change_fps(dev->panel,fps_level);
787         }
788 }
789 #endif
790
791 #ifdef CONFIG_FB_ESD_SUPPORT
792 /*return value:  0--panel OK.1-panel has been reset*/
793 uint32_t sprdfb_panel_ESD_check(struct sprdfb_device *dev)
794 {
795         int32_t result = 0;
796         uint32_t if_status = 0;
797
798 //      printk("sprdfb: [%s] (%d, %d, %d)\n",__FUNCTION__, dev->check_esd_time, dev->panel_reset_time, dev->reset_dsi_time);
799
800         dev->check_esd_time++;
801
802         if(SPRDFB_PANEL_IF_EDPI == dev->panel_if_type){
803                 if (dev->panel->ops->panel_esd_check != NULL) {
804                         result = dev->panel->ops->panel_esd_check(dev->panel);
805                         pr_debug("sprdfb: [%s] panel check return %d\n", __FUNCTION__, result);
806                 }
807         }else if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
808 #ifdef FB_CHECK_ESD_BY_TE_SUPPORT
809                 dev->esd_te_waiter++;
810                 dev->esd_te_done = 0;
811                 dispc_set_bits(BIT(1), DISPC_INT_EN);
812                 result  = wait_event_interruptible_timeout(dev->esd_te_queue,
813                                   dev->esd_te_done, msecs_to_jiffies(600));
814                 pr_debug("sprdfb: after wait (%d)\n", result);
815                 dispc_clear_bits(BIT(1), DISPC_INT_EN);
816                 if(!result){ /*time out*/
817                         printk("sprdfb: [%s] esd check  not got te signal!!!!\n", __FUNCTION__);
818                         dev->esd_te_waiter = 0;
819                         result = 0;
820                 }else{
821                         pr_debug("sprdfb: [%s] esd check  got te signal!\n", __FUNCTION__);
822                         result = 1;
823                 }
824 #else
825                 if (dev->panel->ops->panel_esd_check != NULL) {
826                         result = dev->panel->ops->panel_esd_check(dev->panel);
827 //                      pr_debug("sprdfb: [%s] panel check return %d\n", __FUNCTION__, result);
828                 }
829
830 #endif
831         }
832
833
834         if(0 == dev->enable){
835                 printk("sprdfb: [%s] leave (Invalid device status)!\n", __FUNCTION__);
836                 return 0;
837         }
838
839         if(result == 0){
840                 dev->panel_reset_time++;
841
842                 if(SPRDFB_PANEL_IF_EDPI == dev->panel_if_type){
843                         if(NULL != dev->panel->if_ctrl->panel_if_get_status){
844                                 if_status = dev->panel->if_ctrl->panel_if_get_status(dev);
845                         }
846                 }else if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
847                         if_status = 2; /*need reset dsi as default for dpi mode*/
848                 }
849
850                 if(0 == if_status){
851                         printk("sprdfb: [%s] fail! Need reset panel.(%d,%d,%d)\n",      __FUNCTION__,
852                             dev->check_esd_time, dev->panel_reset_time, dev->reset_dsi_time);
853                         panel_reset(dev);
854
855                         if(0 == dev->enable){
856                                 printk("sprdfb: [%s] leave (Invalid device status)!\n", __FUNCTION__);
857                                 return 0;
858                         }
859
860                         dev->panel->ops->panel_init(dev->panel);
861                         panel_ready(dev);
862                 }else{
863                         printk("sprdfb: [%s] fail! Need reset panel and panel if!!!!(%d,%d,%d)\n",__FUNCTION__,
864                             dev->check_esd_time, dev->panel_reset_time, dev->reset_dsi_time);
865                         dev->reset_dsi_time++;
866                         if(NULL != dev->panel->if_ctrl->panel_if_suspend){
867                                 dev->panel->if_ctrl->panel_if_suspend(dev);
868                         }
869
870                         mdelay(10);
871
872                         if(0 == dev->enable){
873                                 printk("sprdfb: [%s] leave (Invalid device status)!\n", __FUNCTION__);
874                                 return 0;
875                         }
876
877                         panel_init(dev);
878                         panel_reset(dev);
879
880                         if(0 == dev->enable){
881                                 printk("sprdfb: [%s] leave (Invalid device status)!\n", __FUNCTION__);
882                                 return 0;
883                         }
884
885                         dev->panel->ops->panel_init(dev->panel);
886                         panel_ready(dev);
887                 }
888                 pr_debug("sprdfb: [%s]return 1\n",__FUNCTION__);
889                 return 1;
890         }
891 //      pr_debug("sprdfb: [%s]return 0\n",__FUNCTION__);
892         return 0;
893 }
894 #endif
895
896 void sprdfb_panel_suspend(struct sprdfb_device *dev)
897 {
898         if(NULL == dev->panel){
899                 return;
900         }
901
902         printk("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
903 #if 0
904         //step1-1 clk/data lane enter LP
905         if(NULL != dev->panel->if_ctrl->panel_if_before_panel_reset){
906                 dev->panel->if_ctrl->panel_if_before_panel_reset(dev);
907         }
908
909         //step1-2 enter sleep  (another way : reset panel)
910         /*Jessica TODO: Need do some I2c, SPI, mipi sleep here*/
911         /* let lcdc sleep in */
912
913         if (dev->panel->ops->panel_enter_sleep != NULL) {
914                 dev->panel->ops->panel_enter_sleep(dev->panel,1);
915         }
916         msleep(100);
917 #else
918         //step1 send lcd sleep cmd or reset panel directly
919         if(dev->panel->suspend_mode == SEND_SLEEP_CMD){
920                 panel_sleep(dev);
921         }else{
922                 panel_reset(dev);
923         }
924 #endif
925
926         //step2 clk/data lane enter ulps
927         if(NULL != dev->panel->if_ctrl->panel_if_enter_ulps){
928                 dev->panel->if_ctrl->panel_if_enter_ulps(dev);
929         }
930
931         //step3 turn off mipi
932         if(NULL != dev->panel->if_ctrl->panel_if_suspend){
933                 dev->panel->if_ctrl->panel_if_suspend(dev);
934         }
935
936         //step4 reset pin to low
937         if (dev->panel->ops->panel_after_suspend != NULL) {
938                 //himax mipi lcd may define empty function
939                 dev->panel->ops->panel_after_suspend(dev->panel);
940         }
941         else{
942                 panel_after_suspend(dev);
943         }
944
945         panel_power_on(dev, false);
946 }
947
948 void sprdfb_panel_resume(struct sprdfb_device *dev, bool from_deep_sleep)
949 {
950         if(NULL == dev->panel){
951                 return;
952         }
953
954         printk(KERN_INFO "sprdfb: [%s], dev->enable= %d, from_deep_sleep = %d\n",__FUNCTION__, dev->enable, from_deep_sleep);
955 #if 0
956         /*Jessica TODO: resume i2c, spi, mipi*/
957         if(NULL != dev->panel->if_ctrl->panel_if_resume){
958                 dev->panel->if_ctrl->panel_if_resume(dev);
959         }
960         panel_ready(dev);
961 #endif
962         //step1 reset pin to high
963         if (dev->panel->ops->panel_before_resume != NULL) {
964                 //himax mipi lcd may define empty function
965                 dev->panel->ops->panel_before_resume(dev->panel);
966         }
967         else{
968                 panel_before_resume(dev);
969         }
970
971         if(from_deep_sleep){
972
973                 panel_power_on(dev, true);
974                 //step2 turn on mipi
975                 panel_init(dev);
976
977                 //step3 reset panel
978                 panel_reset(dev);
979 #ifdef ENABLE_CLK_HS_ON_INIT
980                 //enable clk lane entern HS
981                 sprdfb_dsi_hs_ready(dev);
982 #endif
983                 //step4 panel init
984                 dev->panel->ops->panel_init(dev->panel);
985
986                 //step5 clk/data lane enter HS
987                 panel_ready(dev);
988         }else{
989                 //step2 turn on mipi
990                 /*Jessica TODO: resume i2c, spi, mipi*/
991                 if(NULL != dev->panel->if_ctrl->panel_if_resume){
992                         dev->panel->if_ctrl->panel_if_resume(dev);
993                 }
994
995                 //step3 sleep out
996                 if(NULL != dev->panel->ops->panel_enter_sleep){
997                         dev->panel->ops->panel_enter_sleep(dev->panel,0);
998                 }
999
1000                 //step4 clk/data lane enter HS
1001                 panel_ready(dev);
1002         }
1003 #ifdef CONFIG_SPRDFB_MDNIE_LITE_TUNING
1004         mdnie_state_restore(dev);
1005 #endif
1006 }
1007
1008 void sprdfb_panel_remove(struct sprdfb_device *dev)
1009 {
1010         if(NULL == dev->panel){
1011                 return;
1012         }
1013
1014         /*Jessica TODO:close panel, i2c, spi, mipi*/
1015         if(NULL != dev->panel->if_ctrl->panel_if_uninit){
1016                 dev->panel->if_ctrl->panel_if_uninit(dev);
1017         }
1018         dev->panel = NULL;
1019 }
1020
1021
1022 int sprdfb_panel_register(struct panel_cfg *cfg)
1023 {
1024         pr_debug("sprdfb: [%s], panel id = %d\n",__FUNCTION__, cfg->dev_id);
1025
1026         if(!panel_check(cfg)){
1027                 printk("sprdfb: [%s]: panel check fail!id = %d\n",__FUNCTION__,  cfg->dev_id);
1028                 return -1;
1029         }
1030
1031         mutex_lock(&panel_mutex);
1032
1033         if (cfg->dev_id == SPRDFB_MAINLCD_ID) {
1034                 list_add_tail(&cfg->list, &panel_list_main);
1035         } else if (cfg->dev_id == SPRDFB_SUBLCD_ID) {
1036                 list_add_tail(&cfg->list, &panel_list_sub);
1037         } else {
1038                 list_add_tail(&cfg->list, &panel_list_main);
1039                 list_add_tail(&cfg->list, &panel_list_sub);
1040         }
1041
1042         mutex_unlock(&panel_mutex);
1043
1044         return 0;
1045 }
1046
1047