platform: msm8909: Add SPI panel init function to support msm8909w

Add changes to:
1.add SPI panel transfer function
2.add SPI panel display config.

Change-Id: Id8387ee8dcd281af57bbec731a9fa009b5b0cb45
Signed-off-by: Wenjun Zhang <wjzhan@codeaurora.org>
diff --git a/platform/msm_shared/display.c b/platform/msm_shared/display.c
index 8733afa..cf4db48 100644
--- a/platform/msm_shared/display.c
+++ b/platform/msm_shared/display.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, 2018 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -125,6 +125,15 @@
 		if (ret)
 			goto msm_display_config_out;
 		break;
+	case SPI_PANEL:
+		dprintf(INFO, "Config SPI PANEL.\n");
+		ret = mdss_spi_init();
+		if (ret)
+			goto msm_display_config_out;
+		ret = mdss_spi_panel_init(pinfo);
+		if (ret)
+			goto msm_display_config_out;
+		break;
 	case HDMI_PANEL:
 		dprintf(INFO, "Config HDMI PANEL.\n");
 		ret = mdss_hdmi_config(pinfo, &(panel->fb));
@@ -243,6 +252,12 @@
 		if (ret)
 			goto msm_display_on_out;
 		break;
+	case SPI_PANEL:
+		dprintf(INFO, "Turn on SPI_PANEL.\n");
+		ret = mdss_spi_on(pinfo, &(panel->fb));
+		if (ret)
+			goto msm_display_on_out;
+		break;
 #endif
 #ifdef DISPLAY_TYPE_QPIC
 	case QPIC_PANEL:
diff --git a/platform/msm_shared/include/mdp4.h b/platform/msm_shared/include/mdp4.h
index e463302..8bbb3a7 100644
--- a/platform/msm_shared/include/mdp4.h
+++ b/platform/msm_shared/include/mdp4.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2016, 2018 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -124,4 +124,8 @@
 int mdss_hdmi_on(struct msm_panel_info *pinfo);
 int mdss_hdmi_off(struct msm_panel_info *pinfo);
 int mdss_hdmi_config(struct msm_panel_info *pinfo, struct fbcon_config *fb);
+
+int mdss_spi_init(void);
+int mdss_spi_panel_init(struct msm_panel_info *pinfo);
+int mdss_spi_on(struct msm_panel_info *pinfo, struct fbcon_config *fb);
 #endif
diff --git a/platform/msm_shared/include/qup.h b/platform/msm_shared/include/qup.h
index 8a1a825..5253b4c 100755
--- a/platform/msm_shared/include/qup.h
+++ b/platform/msm_shared/include/qup.h
@@ -31,6 +31,9 @@
 
 #include <stdint.h>
 
+#define MAX_READ_SPEED_HZ 9600000
+#define MAX_SPEED_HZ 50000000
+
 /* QUP_IO_MODES fields */
 #define QUP_IO_MODES_OUTPUT_BIT_SHIFT_EN  0x00010000
 #define QUP_IO_MODES_PACK_EN              0x00008000
@@ -89,6 +92,7 @@
  * And make the count be multiple of max bytes per word.
  */
 #define MAX_QUP_MX_OUTPUT_COUNT 0xFFF8
+#define MAX_QUP_MX_TRANSFER_COUNT 0xFFF8
 
 /* QUP Registers */
 enum {
@@ -104,6 +108,7 @@
 	QUP_HW_VERSION = 0x30,
 	QUP_MX_READ_CNT = 0x208,
 	QUP_MX_INPUT_CNT = 0x200,
+	QUP_MX_INPUT_CNT_CURRENT = 0x204,
 	QUP_MX_OUTPUT_CNT = 0x100,
 	QUP_MX_OUTPUT_CNT_CURRENT = 0x104,
 	QUP_OUTPUT_DEBUG = 0x108,
diff --git a/platform/msm_shared/include/spi_qup.h b/platform/msm_shared/include/spi_qup.h
index 27731d7..b91ab5c 100755
--- a/platform/msm_shared/include/spi_qup.h
+++ b/platform/msm_shared/include/spi_qup.h
@@ -64,6 +64,7 @@
 #define SPI_IO_C_CS0_ACTIVE_HIGH	BIT(4)
 #define SPI_IO_C_CS_SELECT_CS0		00 << 2
 #define SPI_IO_C_CLK_IDLE_HIGH		BIT(10)
+#define SPI_IO_C_FORCE_CS              BIT(11)
 
 /* SPI_CONFIG fields */
 #define SPI_CONFIG_HS_MODE			BIT(10)
@@ -85,6 +86,8 @@
 struct spi_transfer {
 	const unsigned char	*tx_buf;
 	int	len;
+	unsigned char *rx_buf;
+	unsigned int speed_hz;
 };
 
 /**
@@ -99,10 +102,14 @@
 	unsigned int qup_base;
 	int qup_irq;
 	int tx_bytes;
+	int rx_bytes;
 	unsigned int bytes_per_word;
 	unsigned int bit_shift_en;
 	unsigned int unpack_en;
 	struct spi_transfer *xfer;
+	unsigned int max_speed_hz;
+	uint8_t blsp_id;
+	uint8_t qup_id;
 };
 
 /* Function Definitions */
diff --git a/platform/msm_shared/mdss_spi.c b/platform/msm_shared/mdss_spi.c
new file mode 100644
index 0000000..4819478
--- /dev/null
+++ b/platform/msm_shared/mdss_spi.c
@@ -0,0 +1,173 @@
+/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <spi_qup.h>
+#include <msm_panel.h>
+#include <target/display.h>
+#include <platform/gpio.h>
+
+#define SUCCESS		0
+#define FAIL		1
+
+static struct qup_spi_dev *dev = NULL;
+
+static int mdss_spi_write_cmd(const char *buf)
+{
+	int ret = 0;
+
+	if (!dev) {
+		dprintf(CRITICAL, "SPI has not been initialized\n");
+		return -ENODEV;
+	}
+
+	dev->bytes_per_word = 1;
+	dev->bit_shift_en = 1;
+
+	gpio_set(spi_dc_gpio.pin_id, 0);
+	ret = spi_qup_transfer(dev, buf, 1);
+	gpio_set(spi_dc_gpio.pin_id, 2);
+	if (ret)
+		dprintf(CRITICAL, "Send SPI command to panel failed\n");
+
+	return ret;
+}
+
+static int mdss_spi_write_data(const char *buf, size_t len)
+{
+	int ret = 0;
+
+	if (!dev) {
+		dprintf(CRITICAL, "SPI has not been initialized\n");
+		return -ENODEV;
+	}
+
+	dev->bytes_per_word = 1;
+	dev->bit_shift_en = 1;
+
+	gpio_set(spi_dc_gpio.pin_id, 2);
+	ret = spi_qup_transfer(dev, buf, len);
+	if (ret)
+		dprintf(CRITICAL, "Send SPI parameters to panel failed\n");
+
+	return ret;
+}
+
+static int mdss_spi_write_frame(const char *buf, size_t len)
+{
+	int ret = 0;
+
+	if (!dev) {
+		dprintf(CRITICAL, "SPI has not been initialized\n");
+		return -ENODEV;
+	}
+
+	dev->bytes_per_word = 2;
+	dev->bit_shift_en = 1;
+	dev->unpack_en = 0;
+
+	gpio_set(spi_dc_gpio.pin_id, 2);
+	ret = spi_qup_transfer(dev, buf, len);
+
+	return ret;
+}
+
+static void spi_read_panel_data(unsigned char *buf,  int len)
+{
+	int ret = 0;
+
+	if (!dev) {
+		 dprintf(CRITICAL, "SPI has not been initialized\n");
+		 return -ENODEV;
+	}
+	dev->bytes_per_word = 1;
+	dev->bit_shift_en = 1;
+
+	gpio_set(spi_dc_gpio.pin_id, 0);
+	ret = spi_qup_transfer(dev, buf, len);
+	gpio_set(spi_dc_gpio.pin_id, 2);
+
+	if (ret)
+		dprintf(CRITICAL, "Send SPI command to panel failed\n");
+
+	return;
+}
+
+int mdss_spi_init(void)
+{
+	if (!dev) {
+		dev = qup_blsp_spi_init(SPI_BLSP_ID, SPI_QUP_ID);
+		if (!dev) {
+			dprintf(CRITICAL, "Failed initializing SPI\n");
+			return -ENODEV;
+		}
+	}
+
+	gpio_tlmm_config(spi_dc_gpio.pin_id, 0, spi_dc_gpio.pin_direction,
+			spi_dc_gpio.pin_pull, spi_dc_gpio.pin_strength,
+			spi_dc_gpio.pin_state);
+	return SUCCESS;
+}
+
+int mdss_spi_panel_init(struct msm_panel_info *pinfo)
+{
+	int cmd_count = 0;
+	int ret = 0;
+
+	while (cmd_count < pinfo->spi.num_of_panel_cmds) {
+		if (pinfo->spi.panel_cmds[cmd_count].cmds_post_tg){
+			cmd_count ++;
+			continue;
+		}
+
+		mdss_spi_write_cmd(pinfo->spi.panel_cmds[cmd_count].payload);
+		if (pinfo->spi.panel_cmds[cmd_count].size > 1)
+			mdss_spi_write_data(
+				pinfo->spi.panel_cmds[cmd_count].payload + 1,
+				pinfo->spi.panel_cmds[cmd_count].size - 1);
+
+		if (pinfo->spi.panel_cmds[cmd_count].wait)
+			mdelay(pinfo->spi.panel_cmds[cmd_count].wait);
+
+		cmd_count ++;
+	}
+	return SUCCESS;
+}
+
+int mdss_spi_on(struct msm_panel_info *pinfo, struct fbcon_config *fb)
+{
+	int buf_size = 0;
+	int ret = 0;
+
+	buf_size =  fb->width * fb->height * (fb->bpp / 8);
+	ret = mdss_spi_write_frame(fb->base, buf_size);
+	if (ret)
+		dprintf(CRITICAL, "Send SPI frame data to panel failed\n");
+
+	return ret;
+}
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index 69a0b15..f8460ff 100755
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -531,7 +531,8 @@
 			$(LOCAL_DIR)/mipi_dsi.o \
 			$(LOCAL_DIR)/mipi_dsi_phy.o \
 			$(LOCAL_DIR)/flash-ubi.o \
-			$(LOCAL_DIR)/mipi_dsi_autopll.o
+			$(LOCAL_DIR)/mipi_dsi_autopll.o\
+			$(LOCAL_DIR)/mdss_spi.o
 endif
 
 ifeq ($(PLATFORM),mdm9607)
diff --git a/target/target_display.c b/target/target_display.c
index 6904825..d32e90d 100644
--- a/target/target_display.c
+++ b/target/target_display.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015,2018 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -131,3 +131,18 @@
 {
 	return 0;
 }
+
+__WEAK int mdss_spi_init(void)
+{
+	return 0;
+}
+
+__WEAK int mdss_spi_panel_init(struct msm_panel_info *pinfo)
+{
+	return 0;
+}
+
+__WEAK int mdss_spi_on(struct msm_panel_info *pinfo, struct fbcon_config *fb)
+{
+	return 0;
+}