2 * Copyright (C) 2012 Spreadtrum Communications Inc.
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.
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.
14 #include <linux/kernel.h>
15 #include <linux/mutex.h>
16 #include <linux/list.h>
17 #include <linux/delay.h>
19 #include <mach/gpio.h>
20 #ifdef CONFIG_LCD_CLASS_DEVICE
21 #include <linux/platform_device.h>
22 #include <linux/lcd.h>
25 #include "sprdfb_panel.h"
26 #include "sprdfb_dispc_reg.h"
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};
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;
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;
52 extern void sprdfb_panel_remove(struct sprdfb_device *dev);
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);
59 #ifdef ENABLE_CLK_HS_ON_INIT
60 extern int32_t sprdfb_dsi_hs_ready(struct sprdfb_device *dev);
63 static void parse_string_to_hex(unsigned char *input, uint8_t *output, uint8_t len)
65 int i = 0, j = 1, l = 0;
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;
74 pr_err("Error while parsing in %s\n", __FUNCTION__);
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);
82 pr_err("Error parsing in %s\n", __FUNCTION__);
90 static int __init lcd_id_get(char *str)
92 if ((str != NULL) && (str[0] == 'I') && (str[1] == 'D')) {
93 sscanf(&str[2], "%x", &lcd_id_from_uboot);
95 printk(KERN_INFO "sprdfb: [%s]LCD Panel ID from uboot: 0x%x\n", __FUNCTION__, lcd_id_from_uboot);
98 __setup("lcd_id=", lcd_id_get);
99 static int __init lcd_base_get(char *str)
102 sscanf(&str[0], "%lx", &lcd_base_from_uboot);
104 printk(KERN_INFO "sprdfb: [%s]LCD Panel Base from uboot: 0x%lx\n", __FUNCTION__, lcd_base_from_uboot);
107 __setup("lcd_base=", lcd_base_get);
109 static int __init mtp_offset_get(char *str)
112 sscanf(&str[0], "%s", &mtp_offset_from_uboot);
115 parse_string_to_hex(mtp_offset_from_uboot, mtp_offset_t, MTP_LEN + 6);
117 if (mtp_offset_t[30] != 2 || mtp_offset_t[31] != 3 ||
118 mtp_offset_t[32] != 2)
119 g_mtp_offset_error = 1;
121 printk(KERN_INFO "sprdfb: [%s]Panel mtp offset from uboot: %s\n", __FUNCTION__, mtp_offset_from_uboot);
125 __setup("mtp_offset=", mtp_offset_get);
127 static int __init elvss_offset_get(char *str)
130 sscanf(&str[0], "%x", &elvss_offset_from_uboot);
132 printk(KERN_INFO "sprdfb: [%s]Panel elvss offset from uboot: 0x%x\n", __FUNCTION__, elvss_offset_from_uboot);
135 __setup("elvss_offset=", elvss_offset_get);
137 static int __init hbm_offset_get(char *str)
140 sscanf(&str[0], "%s", &hbm_offset_from_uboot);
143 parse_string_to_hex(hbm_offset_from_uboot, hbm_offset_t, 15);
145 printk(KERN_INFO "sprdfb: [%s]Panel hbm offset from uboot: %s\n", __FUNCTION__, hbm_offset_from_uboot);
149 __setup("hbm_offset=", hbm_offset_get);
151 static int __init chip_id_get(char *str)
154 sscanf(&str[0], "%s", &chip_id_from_uboot);
157 parse_string_to_hex(chip_id_from_uboot, chip_id_t, 5);
159 printk(KERN_INFO "sprdfb: [%s]Panel chip id from uboot: %s\n", __FUNCTION__, chip_id_from_uboot);
163 __setup("chip_id=", chip_id_get);
165 static int __init color_offset_get(char *str)
168 sscanf(&str[0], "%s", &color_offset_from_uboot);
171 parse_string_to_hex(color_offset_from_uboot, color_offset_t, 4);
173 printk(KERN_INFO "sprdfb: [%s]Panel color offset from uboot: %s\n", __FUNCTION__, color_offset_from_uboot);
177 __setup("color_offset=", color_offset_get);
179 static int32_t panel_reset_dispc(struct panel_spec *self)
181 uint16_t timing1, timing2, timing3;
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;
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);
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);
210 /* wait 10ms util the lcd is stable */
211 usleep_range(timing3*1000, timing3*1000+500);
216 static int32_t panel_set_resetpin_dispc(struct panel_spec *self, uint32_t status)
218 #ifdef CONFIG_FB_LCD_S6E8AA5X01_MIPI
219 if (gpio_is_valid(self->rst_gpio)) {
221 gpio_direction_output(self->rst_gpio, 1);
223 gpio_direction_output(self->rst_gpio, 0);
227 dispc_write(0, DISPC_RSTN);
229 dispc_write(1, DISPC_RSTN);
235 static int panel_power_on(struct sprdfb_device *dev, bool enable)
237 if((NULL == dev) || (NULL == dev->panel)){
238 printk(KERN_ERR "sprdfb: [%s]: Invalid param\n", __FUNCTION__);
242 pr_debug("sprdfb: [%s], enter\n",__FUNCTION__);
245 if (dev->panel->ops->panel_power_on)
246 dev->panel->ops->panel_power_on(dev, enable);
252 static int panel_reset(struct sprdfb_device *dev)
254 if((NULL == dev) || (NULL == dev->panel)){
255 printk(KERN_ERR "sprdfb: [%s]: Invalid param\n", __FUNCTION__);
259 pr_debug("sprdfb: [%s], enter\n",__FUNCTION__);
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);
265 usleep_range(5000, 5500);
268 dev->panel->ops->panel_reset(dev->panel);
273 static int panel_sleep(struct sprdfb_device *dev)
275 if((NULL == dev) || (NULL == dev->panel)){
276 printk(KERN_ERR "sprdfb: [%s]: Invalid param\n", __FUNCTION__);
280 pr_debug("sprdfb: [%s], enter\n",__FUNCTION__);
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);
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))
291 dev->panel->if_ctrl->panel_if_before_panel_reset(dev);
296 static void panel_set_resetpin(uint16_t dev_id, uint32_t status, struct panel_spec *panel )
298 pr_debug("sprdfb: [%s].\n",__FUNCTION__);
300 /*panel set reset pin status*/
301 if(SPRDFB_MAINLCD_ID == dev_id){
302 panel_set_resetpin_dispc(panel, status);
307 static int32_t panel_before_resume(struct sprdfb_device *dev)
309 /*restore the reset pin to high*/
310 panel_set_resetpin(dev->dev_id, 1, dev->panel);
314 static int32_t panel_after_suspend(struct sprdfb_device *dev)
316 /*set the reset pin to low*/
317 panel_set_resetpin(dev->dev_id, 0, dev->panel);
318 usleep_range(1000, 1100);
323 static bool panel_check(struct panel_cfg *cfg)
327 if(NULL == cfg || NULL == cfg->panel){
328 printk(KERN_ERR "sprdfb: [%s] :Invalid Param!\n", __FUNCTION__);
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);
334 switch(cfg->panel->type){
335 case SPRDFB_PANEL_TYPE_MCU:
336 cfg->panel->if_ctrl = &sprdfb_mcu_ctrl;
338 case SPRDFB_PANEL_TYPE_RGB:
339 case SPRDFB_PANEL_TYPE_LVDS:
340 cfg->panel->if_ctrl = &sprdfb_rgb_ctrl;
342 #ifndef CONFIG_FB_SCX15
343 case SPRDFB_PANEL_TYPE_MIPI:
344 cfg->panel->if_ctrl = &sprdfb_mipi_ctrl;
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;
353 if(cfg->panel->if_ctrl->panel_if_check){
354 rval = cfg->panel->if_ctrl->panel_if_check(cfg->panel);
359 static int panel_mount(struct sprdfb_device *dev, struct panel_spec *panel)
361 printk("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
363 /* TODO: check whether the mode/res are supported */
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;
372 panel->if_ctrl->panel_if_mount(dev);
378 int panel_init(struct sprdfb_device *dev)
380 if((NULL == dev) || (NULL == dev->panel)){
381 printk(KERN_ERR "sprdfb: [%s]: Invalid param\n", __FUNCTION__);
385 pr_debug("sprdfb: [%s], dev_id= %d, type = %d\n",__FUNCTION__, dev->dev_id, dev->panel->type);
387 if(!dev->panel->if_ctrl->panel_if_init(dev)){
388 printk(KERN_ERR "sprdfb: [%s]: panel_if_init fail!\n", __FUNCTION__);
395 int panel_ready(struct sprdfb_device *dev)
397 if((NULL == dev) || (NULL == dev->panel)){
398 printk(KERN_ERR "sprdfb: [%s]: Invalid param\n", __FUNCTION__);
402 pr_debug("sprdfb: [%s], dev_id= %d, type = %d\n",__FUNCTION__, dev->dev_id, dev->panel->type);
404 if(NULL != dev->panel->if_ctrl->panel_if_ready){
405 dev->panel->if_ctrl->panel_if_ready(dev);
412 static struct panel_spec *adapt_panel_from_uboot(uint16_t dev_id)
414 struct panel_cfg *cfg;
415 struct list_head *panel_list;
417 pr_debug("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev_id);
419 if (lcd_id_from_uboot == 0) {
420 printk("sprdfb: [%s]: Not got lcd id from uboot\n", __FUNCTION__);
424 if(SPRDFB_MAINLCD_ID == dev_id){
425 panel_list = &panel_list_main;
427 panel_list = &panel_list_sub;
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);
436 printk(KERN_ERR "sprdfb: [%s]: Failed to match LCD Panel from uboot!\n", __FUNCTION__);
441 static struct panel_spec *adapt_panel_from_readid(struct sprdfb_device *dev)
443 struct panel_cfg *cfg;
444 struct panel_cfg *dummy_cfg = NULL;
445 struct list_head *panel_list;
448 printk("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
450 if(SPRDFB_MAINLCD_ID == dev->dev_id){
451 panel_list = &panel_list_main;
453 panel_list = &panel_list_sub;
456 list_for_each_entry(cfg, panel_list, list) {
457 if(0xFFFFFFFF == cfg->lcd_id){
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);
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);
475 sprdfb_panel_remove(dev);
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);
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);
490 return dummy_cfg->panel;
492 sprdfb_panel_remove(dev);
494 printk(KERN_ERR "sprdfb: [%s]: failed to attach LCD Panel!\n", __FUNCTION__);
499 bool sprdfb_panel_get(struct sprdfb_device *dev)
501 struct panel_spec *panel = NULL;
504 printk("sprdfb: [%s]: Invalid param\n", __FUNCTION__);
508 printk("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
510 panel = adapt_panel_from_uboot(dev->dev_id);
512 dev->panel_ready = true;
513 panel_mount(dev, panel);
515 printk("sprdfb: [%s] got panel\n", __FUNCTION__);
519 printk("sprdfb: [%s] can not got panel\n", __FUNCTION__);
524 #if defined(CONFIG_LCD_CLASS_DEVICE)
525 static ssize_t show_lcd_info(struct device *dev,
526 struct device_attribute *attr, char *buf)
528 struct sprdfb_device *fb_dev = dev_get_drvdata(dev);
529 unsigned int panel_id = lcd_id_from_uboot;
531 if (fb_dev->panel->ops->panel_get_type)
532 return fb_dev->panel->ops->panel_get_type(buf, panel_id);
534 return sprintf(buf, "Unknown panel %X", panel_id);
537 static int sprdfb_set_power(struct lcd_device *ld, int power)
540 struct sprdfb_device *lcd = lcd_get_data(ld);
542 if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
543 power != FB_BLANK_NORMAL)
546 if (lcd->power == power) {
547 printk("power is same as previous mode\n");
553 printk("sprdfb: [%s] power[%d]\n", __FUNCTION__, lcd->power);
558 static int sprdfb_get_power(struct lcd_device *ld)
560 struct sprdfb_device *lcd = lcd_get_data(ld);
562 printk("sprdfb: [%s] power[%d]\n", __FUNCTION__, lcd->power);
567 static struct lcd_ops ld_ops = {
568 .get_power = sprdfb_get_power,
569 .set_power = sprdfb_set_power,
572 static ssize_t show_lcd_info(struct device *dev,
573 struct device_attribute *attr, char *buf);
575 #ifdef CONFIG_FB_DEBUG_LCD_TUNING
576 static ssize_t lcd_init_show(struct device *dev,
577 struct device_attribute *attr,
580 printk("++ [%s] current lcd init seq\n", __func__);
585 static ssize_t lcd_init_store(struct device *dev,
586 struct device_attribute *attr,
587 const char *buf, size_t size)
590 printk("++ [%s] current lcd init seq\n", __func__);
591 ret = lcd_store_panel_init_cmd();
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),
604 static bool sprdfb_lcd_class_register(struct platform_device *pdev,
605 struct sprdfb_device *dev)
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");
615 dev->power = FB_BLANK_UNBLANK;
617 for (i = 0; i < ARRAY_SIZE(lcd_device_attributes); i++) {
618 ret = device_create_file(&dev->ld->dev,
619 &lcd_device_attributes[i]);
621 printk("failed to add ld dev sysfs entries\n");
628 lcd_device_unregister(dev->ld);
633 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE)
634 static int panel_update_brightness(struct backlight_device *bd)
636 struct sprdfb_device *dev = bl_get_data(bd);
639 if (dev->power > FB_BLANK_NORMAL) {
640 pr_err("%s: invalid power[%d]\n", __func__, dev->power);
643 ret = dev->panel->ops->panel_set_brightness(dev, bd->props.brightness);
648 static int panel_get_brightness(struct backlight_device *bd)
650 return bd->props.brightness;
653 static struct backlight_ops backlight_ops = {
654 .get_brightness = panel_get_brightness,
655 .update_status = panel_update_brightness,
658 static bool sprdfb_backlight_class_register(struct platform_device *pdev,
659 struct sprdfb_device *dev)
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");
670 dev->bd->props.max_brightness = 100;
671 dev->bd->props.brightness = 60;
672 dev->bd->props.type = BACKLIGHT_PLATFORM;
679 bool sprdfb_panel_init(struct platform_device *pdev, struct sprdfb_device *dev)
682 if (lcd_id_from_uboot == 0) {
683 printk("sprdfb: panel is not connected\n");
686 #if defined(CONFIG_LCD_CLASS_DEVICE)
687 if(!sprdfb_lcd_class_register(pdev, dev)) {
688 printk("sprdfb: failed to register lcd_class\n");
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");
699 if (dev->panel->ops->panel_dimming_init)
700 dev->panel->ops->panel_dimming_init(dev->panel, &pdev->dev);
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");
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);
713 if (dev->panel->ops->panel_read_offset)
714 dev->panel->ops->panel_read_offset(dev->panel);
719 bool sprdfb_panel_probe(struct platform_device *pdev, struct sprdfb_device *dev)
721 struct panel_spec *panel;
724 printk("sprdfb: [%s]: Invalid param\n", __FUNCTION__);
728 printk("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
730 /* can not be here in normal; we should get correct device id from uboot */
731 panel = adapt_panel_from_readid(dev);
734 if (!sprdfb_panel_init(pdev, dev)) {
735 printk("sprdfb: failed to register panel class\n");
738 printk("sprdfb: [%s] got panel\n", __FUNCTION__);
742 printk("sprdfb: [%s] can not got panel\n", __FUNCTION__);
747 void sprdfb_panel_invalidate_rect(struct panel_spec *self,
748 uint16_t left, uint16_t top,
749 uint16_t right, uint16_t bottom)
752 if(NULL != self->ops->panel_invalidate_rect){
753 self->ops->panel_invalidate_rect(self, left, top, right, bottom);
755 /*Jessica TODO: Need set timing to GRAM timing*/
758 void sprdfb_panel_invalidate(struct panel_spec *self)
761 if(NULL != self->ops->panel_invalidate){
762 self->ops->panel_invalidate(self);
764 /*Jessica TODO: Need set timing to GRAM timing*/
767 void sprdfb_panel_before_refresh(struct sprdfb_device *dev)
769 if(NULL != dev->panel->if_ctrl->panel_if_before_refresh){
770 dev->panel->if_ctrl->panel_if_before_refresh(dev);
774 void sprdfb_panel_after_refresh(struct sprdfb_device *dev)
776 if(NULL != dev->panel->if_ctrl->panel_if_after_refresh){
777 dev->panel->if_ctrl->panel_if_after_refresh(dev);
781 #ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING
782 void sprdfb_panel_change_fps(struct sprdfb_device *dev, int fps_level)
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);
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)
796 uint32_t if_status = 0;
798 // printk("sprdfb: [%s] (%d, %d, %d)\n",__FUNCTION__, dev->check_esd_time, dev->panel_reset_time, dev->reset_dsi_time);
800 dev->check_esd_time++;
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);
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;
821 pr_debug("sprdfb: [%s] esd check got te signal!\n", __FUNCTION__);
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);
834 if(0 == dev->enable){
835 printk("sprdfb: [%s] leave (Invalid device status)!\n", __FUNCTION__);
840 dev->panel_reset_time++;
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);
846 }else if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
847 if_status = 2; /*need reset dsi as default for dpi mode*/
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);
855 if(0 == dev->enable){
856 printk("sprdfb: [%s] leave (Invalid device status)!\n", __FUNCTION__);
860 dev->panel->ops->panel_init(dev->panel);
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);
872 if(0 == dev->enable){
873 printk("sprdfb: [%s] leave (Invalid device status)!\n", __FUNCTION__);
880 if(0 == dev->enable){
881 printk("sprdfb: [%s] leave (Invalid device status)!\n", __FUNCTION__);
885 dev->panel->ops->panel_init(dev->panel);
888 pr_debug("sprdfb: [%s]return 1\n",__FUNCTION__);
891 // pr_debug("sprdfb: [%s]return 0\n",__FUNCTION__);
896 void sprdfb_panel_suspend(struct sprdfb_device *dev)
898 if(NULL == dev->panel){
902 printk("sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
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);
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 */
913 if (dev->panel->ops->panel_enter_sleep != NULL) {
914 dev->panel->ops->panel_enter_sleep(dev->panel,1);
918 //step1 send lcd sleep cmd or reset panel directly
919 if(dev->panel->suspend_mode == SEND_SLEEP_CMD){
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);
931 //step3 turn off mipi
932 if(NULL != dev->panel->if_ctrl->panel_if_suspend){
933 dev->panel->if_ctrl->panel_if_suspend(dev);
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);
942 panel_after_suspend(dev);
945 panel_power_on(dev, false);
948 void sprdfb_panel_resume(struct sprdfb_device *dev, bool from_deep_sleep)
950 if(NULL == dev->panel){
954 printk(KERN_INFO "sprdfb: [%s], dev->enable= %d, from_deep_sleep = %d\n",__FUNCTION__, dev->enable, from_deep_sleep);
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);
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);
968 panel_before_resume(dev);
973 panel_power_on(dev, true);
979 #ifdef ENABLE_CLK_HS_ON_INIT
980 //enable clk lane entern HS
981 sprdfb_dsi_hs_ready(dev);
984 dev->panel->ops->panel_init(dev->panel);
986 //step5 clk/data lane enter HS
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);
996 if(NULL != dev->panel->ops->panel_enter_sleep){
997 dev->panel->ops->panel_enter_sleep(dev->panel,0);
1000 //step4 clk/data lane enter HS
1003 #ifdef CONFIG_SPRDFB_MDNIE_LITE_TUNING
1004 mdnie_state_restore(dev);
1008 void sprdfb_panel_remove(struct sprdfb_device *dev)
1010 if(NULL == dev->panel){
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);
1022 int sprdfb_panel_register(struct panel_cfg *cfg)
1024 pr_debug("sprdfb: [%s], panel id = %d\n",__FUNCTION__, cfg->dev_id);
1026 if(!panel_check(cfg)){
1027 printk("sprdfb: [%s]: panel check fail!id = %d\n",__FUNCTION__, cfg->dev_id);
1031 mutex_lock(&panel_mutex);
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);
1038 list_add_tail(&cfg->list, &panel_list_main);
1039 list_add_tail(&cfg->list, &panel_list_sub);
1042 mutex_unlock(&panel_mutex);