From 63058268f9ab1c96396d3d138aefc3f7b0f72869 Mon Sep 17 00:00:00 2001
From: Srikant Patnaik
Date: Sun, 11 Jan 2015 20:10:08 +0530
Subject: Fix white screen issue during bootup

Signed-off-by:  Manish Patel <manish.patel@xzadium.com>
---
 drivers/video/wmt/devices/lcd-b079xan01.c | 378 +++++++++++++++++++-----------
 1 file changed, 240 insertions(+), 138 deletions(-)
 mode change 100755 => 100644 drivers/video/wmt/devices/lcd-b079xan01.c

(limited to 'drivers/video/wmt/devices/lcd-b079xan01.c')

diff --git a/drivers/video/wmt/devices/lcd-b079xan01.c b/drivers/video/wmt/devices/lcd-b079xan01.c
old mode 100755
new mode 100644
index 05a6e957..54e5921e
--- a/drivers/video/wmt/devices/lcd-b079xan01.c
+++ b/drivers/video/wmt/devices/lcd-b079xan01.c
@@ -1,82 +1,209 @@
-/*++
- * linux/drivers/video/wmt/lcd-b079xan01.c
- * WonderMedia video post processor (VPP) driver
- *
- * Copyright c 2014  WonderMedia  Technologies, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * WonderMedia Technologies, Inc.
- * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
---*/
-
-#include <linux/delay.h>
+/*++
+	linux/drivers/video/wmt/devices/lcd-b079xan01.c
 
-#include <mach/hardware.h>
+	Copyright (c) 2013  WonderMedia Technologies, Inc.
+
+	This program is free software: you can redistribute it and/or modify it under the
+	terms of the GNU General Public License as published by the Free Software Foundation,
+	either version 2 of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful, but WITHOUT
+	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+	PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+	You should have received a copy of the GNU General Public License along with
+	this program.  If not, see <http://www.gnu.org/licenses/>.
+
+	WonderMedia Technologies, Inc.
+	10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+--*/
+
+#include <linux/delay.h>
 #include <linux/spi/spi.h>
+#include <mach/hardware.h>
 #include <mach/wmt-spi.h>
-
 #include <linux/gpio.h>
 #include <mach/wmt_iomux.h>
-
 #include "../lcd.h"
 
 #define DRIVERNAME	"ssd2828"
+#define DELAY_MASK	0xff000000
+
+#undef pr_err
+#undef pr_info
+#undef pr_warning
+#define pr_err(fmt, args...)		printk("[" DRIVERNAME "] " fmt, ##args)
+#define pr_info(fmt, args...)		printk("[" DRIVERNAME "] " fmt, ##args)
+#define pr_warning(fmt, args...)	printk("[" DRIVERNAME "] " fmt, ##args)
+
+extern void lcd_power_on(bool on);
+
+struct ssd2828_chip {
+	struct spi_device *spi;
+	int id;
+	int gpio_reset;
+};
+
+static int wmt_lcd_panel_id(void)
+{
+	char buf[96];
+	int len = sizeof(buf);
+	int type, id = 0;
+
+	if (wmt_getsyspara("wmt.display.param", buf, &len)) {
+		return -ENODEV;
+	}
 
-static struct lcd_parm_t lcd_b079xan01_parm = {
-	.bits_per_pixel = 24,
-	.capability = 0,
+	sscanf(buf, "%d:%d", &type, &id);
+	return id;
+}
+
+// B079XAN01
+
+static const uint32_t b079xan01_init_sequence[] = {
+	0x7000B1, 0x723240,	//VSA=50, HAS=64
+	0x7000B2, 0x725078,	//VBP=30+50, HBP=56+64
+	0x7000B3, 0x72243C,	//VFP=36, HFP=60
+	0x7000B4, 0x720300,	//HACT=768
+	0x7000B5, 0x720400,	//VACT=1024
+	0x7000B6, 0x72000b,	//burst mode, 24bpp loosely packed
+	0x7000DE, 0x720003,	//no of lane=4
+	0x7000D6, 0x720005,	//RGB order and packet number in blanking period
+	0x7000B9, 0x720000,	//disable PLL
+
+	//lane speed=576 (24MHz * 24 = 576)
+	//may modify according to requirement, 500Mbps to 560Mbps
+	//LP clock : 576 / 9 / 8 = 8 MHz
+	0x7000BA, 0x728018,
+	0x7000BB, 0x720008,
+
+	0x7000B9, 0x720001,	//enable PPL
+	0x7000C4, 0x720001,	//enable BTA
+	0x7000B7, 0x720342,	//enter LP mode
+	0x7000B8, 0x720000,	//VC
+	0x7000BC, 0x720000,	//set packet size
+
+	0x700011,		//sleep out cmd
+	
+	DELAY_MASK + 200,
+
+	0x700029,		//display on
+	
+	DELAY_MASK + 200,
+
+	0x7000B7, 0x72030b,	//video mode on
+};
+
+static lcd_parm_t lcd_b079xan01_parm = {
+	.bits_per_pixel		= 24,
+	.capability		= 0,
 	.vmode = {
-		.name = "B079XAN01",
-		.refresh = 60,
-		.xres = 768,
-		.yres = 1024,
-		.pixclock = KHZ2PICOS(64800),
-		.left_margin = 56,
-		.right_margin = 60,
-		.upper_margin = 30,
-		.lower_margin = 36,
-		.hsync_len = 64,
-		.vsync_len = 50,
-		.sync = 0, /* FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, */
-		.vmode = 0,
-		.flag = 0,
+		.name		= "B079XAN01",
+		.refresh	= 60,
+		.xres		= 768,
+		.yres		= 1024,
+		.pixclock	= KHZ2PICOS(64800),
+		.left_margin	= 56,
+		.right_margin	= 60,
+		.upper_margin	= 30,
+		.lower_margin	= 36,
+		.hsync_len	= 64,
+		.vsync_len	= 50,
+		.sync		= 0,
+		.vmode		= 0,
+		.flag		= 0,
 	},
-	.width = 120,
-	.height = 160,
-#if 0
-	.initial = lcd_power_on,
-	.uninitial = lcd_power_off,
-#endif
 };
 
-static struct lcd_parm_t *lcd_b079xan01_get_parm(int arg)
+static lcd_parm_t *lcd_b079xan01_get_parm(int arg)
 {
 	return &lcd_b079xan01_parm;
 }
 
-static int lcd_b079xan01_init(void)
-{
-	return lcd_panel_register(LCD_B079XAN01,
-		(void *) lcd_b079xan01_get_parm);
-}
+// BP080WX7
 
-struct ssd2828_chip {
-	struct spi_device *spi;
-	int gpio_reset;
+static const uint32_t bp080wx7_init_sequence[] = {
+	0x7000B1, 0x720202,	// VSA=02 , HSA=02
+	0x7000B2, 0x720828,	// VBP+VSA=8, HBP+HSA=40
+	0x7000B3, 0x72040A,	// VFP=04 , HFP=10
+	0x7000B4, 0x720500,	// HACT=1280
+	0x7000B5, 0x720320,	// vACT=800
+	0x7000B6, 0x720007,	// Non burst mode with sync event  24bpp
+
+	//DELAY_MASK + 10,
+
+	0x7000DE, 0x720003,	// 4lanes
+	0x7000D6, 0x720005,	// BGR
+	0x7000B9, 0x720000,	
+
+	//DELAY_MASK + 10,
+
+	0x7000BA, 0x72C012,	// PLL=24*16 = 384MHz
+	0x7000BB, 0x720008,	// LP CLK=8.3MHz
+	0x7000B9, 0x720001,	
+
+	//DELAY_MASK + 200,	
+
+	0x7000B8, 0x720000,	// Virtual Channel 0
+	0x7000B7, 0x720342,	// LP Mode 
+
+	//DELAY_MASK + 10,
+
+	0x7000BC, 0x720000,
+	0x700011,		//sleep out
+
+	DELAY_MASK + 200,
+
+	0x7000BC, 0x720000,
+	0x700029,		//display on
+
+	//DELAY_MASK + 50,
+
+	0x7000B7, 0x72034B,	//Video Mode
+
+	DELAY_MASK + 200,
+
+	0x7000BC, 0x720000,
+	0x700029, //display on
 };
 
+//Timing parameter for 3.0" QVGA LCD
+#define VBPD 		(6)
+#define VFPD 		(4)
+#define VSPW 		(2)
+
+#define HBPD 		(38)
+#define HFPD 		(10)
+#define HSPW 		(2)
+
+// setenv wmt.display.tmr 64800:0:8:47:1280:45:4:16:800:16
+
+static lcd_parm_t lcd_bp080wx7_parm = {
+	.bits_per_pixel		= 24,
+	.capability		= 0,
+	.vmode = {
+		.name		= "BP080WX7",
+		.refresh	= 60,
+		.xres		= 1280,
+		.yres		= 800,
+		.pixclock	= KHZ2PICOS(64800),
+		.left_margin	= HBPD,
+		.right_margin	= HFPD,
+		.upper_margin	= VBPD,
+		.lower_margin	= VFPD,
+		.hsync_len	= HSPW,
+		.vsync_len	= VSPW,
+		.sync		= 0,
+		.vmode		= 0,
+		.flag		= 0,
+	},
+};
+
+static lcd_parm_t *lcd_bp080wx7_get_parm(int arg)
+{
+	return &lcd_bp080wx7_parm;
+}
+
+// SSD2828 api
 static int ssd2828_read(struct spi_device *spi, uint8_t reg)
 {
 	int ret;
@@ -88,13 +215,12 @@ static int ssd2828_read(struct spi_device *spi, uint8_t reg)
 	ret = spi_write(spi, buf1, 3);
 	if (ret) {
 		pr_err("spi_write ret=%d\n", ret);
-		return -EIO;
+		return ret;
 	}
 
 	ret = spi_w8r16(spi, buf2[0]);
 	if (ret < 0) {
 		pr_err("spi_write ret=%d\n", ret);
-		return ret;
 	}
 
 	return ret;
@@ -142,35 +268,7 @@ static inline int spi_write_24bit(struct spi_device *spi, uint32_t data)
 	return ret;
 }
 
-static const uint32_t ssd2828_init_sequence[] = {
-	0x7000B1, 0x723240, /* VSA=50, HAS=64 */
-	0x7000B2, 0x725078, /* VBP=30+50, HBP=56+64 */
-	0x7000B3, 0x72243C, /* VFP=36, HFP=60 */
-	0x7000B4, 0x720300, /* HACT=768 */
-	0x7000B5, 0x720400, /* VACT=1024 */
-	0x7000B6, 0x72000b, /* burst mode, 24bpp loosely packed */
-	0x7000DE, 0x720003, /* no of lane=4 */
-	0x7000D6, 0x720005, /* RGB order and packet number in blanking period */
-	0x7000B9, 0x720000, /* disable PLL */
-
-	/* lane speed=576 (24MHz * 24 = 576) */
-	/* may modify according to requirement, 500Mbps to 560Mbps */
-	/* LP clock : 576 / 9 / 8 = 8 MHz */
-	0x7000BA, 0x728018,
-	0x7000BB, 0x720008,
-
-	0x7000B9, 0x720001, /* enable PPL */
-	0x7000C4, 0x720001, /* enable BTA */
-	0x7000B7, 0x720342, /* enter LP mode */
-	0x7000B8, 0x720000, /* VC */
-	0x7000BC, 0x720000, /* set packet size */
-
-	0x700011, 0xff0000 + 200, /* sleep out cmd */
-	0x700029, 0xff0000 + 200, /* display on */
-	0x7000B7, 0x72030b, /* video mode on */
-};
-
-static int ssd2828_hw_reset(struct ssd2828_chip *chip)
+static inline void ssd2828_hw_reset(struct ssd2828_chip *chip)
 {
 	lcd_power_on(1);
 	msleep(10);
@@ -178,16 +276,16 @@ static int ssd2828_hw_reset(struct ssd2828_chip *chip)
 	gpio_direction_output(chip->gpio_reset, 1);
 	msleep(10);
 	gpio_direction_output(chip->gpio_reset, 0);
-	msleep(20);
+	msleep(200);
 	gpio_direction_output(chip->gpio_reset, 1);
-	msleep(20);
-	return 0;
+	msleep(200);
 }
 
 static int ssd2828_hw_init(struct ssd2828_chip *chip)
 {
-	int ret = 0;
-	int i;
+	const uint32_t *init_sequence;
+	size_t n;
+	int i, ret = 0;
 
 	ssd2828_hw_reset(chip);
 
@@ -197,14 +295,27 @@ static int ssd2828_hw_init(struct ssd2828_chip *chip)
 		return -ENODEV;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(ssd2828_init_sequence); i++) {
-		if (ssd2828_init_sequence[i] & 0xff000000) {
-			msleep(ssd2828_init_sequence[i] & 0xff);
-			continue;
+	switch (chip->id) {
+	case LCD_B079XAN01:
+		init_sequence = b079xan01_init_sequence;
+		n = ARRAY_SIZE(b079xan01_init_sequence);
+		break;
+	case LCD_BP080WX7:
+		init_sequence = bp080wx7_init_sequence;
+		n = ARRAY_SIZE(bp080wx7_init_sequence);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	for (i = 0; i < n; i++) {
+		if ((init_sequence[i] & DELAY_MASK) == DELAY_MASK) {
+			msleep(init_sequence[i] & 0xff);
+		} else {
+			ret = spi_write_24bit(chip->spi, init_sequence[i]);
+			if (ret)
+				break;
 		}
-		ret = spi_write_24bit(chip->spi, ssd2828_init_sequence[i]);
-		if (ret)
-			break;
 	}
 
 	return ret;
@@ -232,7 +343,7 @@ static ssize_t option_port_testmode_show(struct device *dev,
 	s += sprintf(s, "=========\n");
 
 out:
-	return s - buf;
+	return (s - buf);
 }
 
 static ssize_t option_port_testmode_store(struct device *dev,
@@ -246,7 +357,7 @@ static DEVICE_ATTR(testmode, S_IRUGO,
 		   option_port_testmode_show,
 		   option_port_testmode_store);
 
-static int __devinit ssd2828_probe(struct spi_device *spi)
+static int __devinit ssd2828_spi_probe(struct spi_device *spi)
 {
 	struct ssd2828_chip *chip;
 	int gpio = WMT_PIN_GP0_GPIO0;
@@ -269,12 +380,14 @@ static int __devinit ssd2828_probe(struct spi_device *spi)
 		return -ENOMEM;
 
 	chip->spi = spi;
+	chip->id = wmt_lcd_panel_id();
 	chip->gpio_reset = gpio;
 	spi_set_drvdata(spi, chip);
 
 	ret = sysfs_create_file(&spi->dev.kobj, &dev_attr_testmode.attr);
-	if (unlikely(ret))
+	if (unlikely(ret)) {
 		pr_err("ssd2828 sysfs_create_file failed\n");
+	}
 
 	return ret;
 }
@@ -287,15 +400,11 @@ static int ssd2828_spi_resume(struct spi_device *spi)
 
 static struct spi_driver ssd2828_driver = {
 	.driver = {
-		.name	= DRIVERNAME,
-		.owner	= THIS_MODULE,
+		.name = DRIVERNAME,
+		.owner = THIS_MODULE,
 	},
-	.probe		= ssd2828_probe,
-	.resume		= ssd2828_spi_resume,
-#if 0
-	.remove		= __devexit_p(ssd2828_remove),
-	.shutdown	= ssd2828_shutdown,
-#endif
+	.probe = ssd2828_spi_probe,
+	.resume = ssd2828_spi_resume,
 };
 
 static struct spi_board_info ssd2828_spi_info[] __initdata = {
@@ -309,25 +418,16 @@ static struct spi_board_info ssd2828_spi_info[] __initdata = {
 	},
 };
 
-static int wmt_lcd_panel(void)
-{
-	char buf[96];
-	int len = sizeof(buf);
-	int type, id = 0;
-
-	if (wmt_getsyspara("wmt.display.param", buf, &len))
-		return -ENODEV;
-
-	sscanf(buf, "%d:%d", &type, &id);
-	return id;
-}
-
-static int __init b079xan01_init(void)
+static int __init ssd2828_init(void)
 {
 	int ret;
 
-	if (wmt_lcd_panel() != LCD_B079XAN01) {
-		pr_err("LCD B079XAN01 not found\n");
+	switch (wmt_lcd_panel_id()) {
+	case LCD_B079XAN01:
+	case LCD_BP080WX7:
+		break;
+	default:
+		pr_warning("lcd for ssd2828 not found\n");
 		return -EINVAL;
 	}
 
@@ -341,23 +441,25 @@ static int __init b079xan01_init(void)
 	ret = spi_register_driver(&ssd2828_driver);
 	if (ret) {
 		pr_err("spi_register_driver failed\n");
-		return -EIO;
+		return ret;
 	}
 
-	if (lcd_b079xan01_init()) {
-		spi_unregister_driver(&ssd2828_driver);
-		return -ENODEV;
-	}
+	lcd_panel_register(LCD_B079XAN01, (void *)lcd_b079xan01_get_parm);
+	lcd_panel_register(LCD_BP080WX7,  (void *)lcd_bp080wx7_get_parm);
 
 	pr_info("spi %s register success\n", DRIVERNAME);
-
 	return 0;
 }
 
-static void b079xan01_exit(void)
+static void ssd2828_exit(void)
 {
 	spi_unregister_driver(&ssd2828_driver);
 }
 
-module_init(b079xan01_init);
-module_exit(b079xan01_exit);
+module_init(ssd2828_init);
+module_exit(ssd2828_exit);
+
+MODULE_AUTHOR("Sam Mei");
+MODULE_DESCRIPTION("WonderMedia Mipi LCD Driver");
+MODULE_LICENSE("GPL");
+
-- 
cgit