Merge "target: msm8996: add support for HDMI regulators"
diff --git a/platform/msm8996/acpuclock.c b/platform/msm8996/acpuclock.c
index 5d2e7eb..ff0b55c 100644
--- a/platform/msm8996/acpuclock.c
+++ b/platform/msm8996/acpuclock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 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
@@ -687,4 +687,37 @@
 		dprintf(CRITICAL, "Failed to enable %s\n", clk_name);
 		return;
 	}
-}
\ No newline at end of file
+}
+
+void hdmi_clk_enable(void)
+{
+	int ret;
+
+	/* Configure hdmi ahb clock */
+	ret = clk_get_set_enable("hdmi_ahb_clk", 0, 1);
+	if(ret) {
+		dprintf(CRITICAL, "failed to set hdmi_ahb_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	/* Configure hdmi core clock */
+	ret = clk_get_set_enable("hdmi_core_clk", 19200000, 1);
+	if(ret) {
+		dprintf(CRITICAL, "failed to set hdmi_core_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	/* Configure hdmi pixel clock */
+	ret = clk_get_set_enable("hdmi_extp_clk", 148500000, 1);
+	if(ret) {
+		dprintf(CRITICAL, "failed to set hdmi_extp_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+}
+
+void hdmi_clk_disable(void)
+{
+	clk_disable(clk_get("hdmi_extp_clk"));
+	clk_disable(clk_get("hdmi_core_clk"));
+	clk_disable(clk_get("hdmi_ahb_clk"));
+}
diff --git a/platform/msm8996/include/platform/clock.h b/platform/msm8996/include/platform/clock.h
index 6ff55e2..25e6ea9 100644
--- a/platform/msm8996/include/platform/clock.h
+++ b/platform/msm8996/include/platform/clock.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 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
@@ -58,6 +58,13 @@
 #define MMSS_MMAGIC_AHB_CBCR            REG_MM(0x5024)
 #define SMMU_MDP_AHB_CBCR               REG_MM(0x2454)
 #define MDSS_AHB_CBCR                   REG_MM(0x2308)
+#define MDSS_HDMI_AHB_CBCR              REG_MM(0x230C)
+#define MDSS_HDMI_CBCR                  REG_MM(0x2338)
+#define MDSS_EXTPCLK_CBCR               REG_MM(0x2324)
+#define EXTPCLK_CMD_RCGR                REG_MM(0x2060)
+#define EXTPCLK_CFG_RCGR                REG_MM(0x2064)
+#define HDMI_CMD_RCGR                   REG_MM(0x2100)
+#define HDMI_CFG_RCGR                   REG_MM(0x2104)
 
 #define AXI_CMD_RCGR                    REG_MM(0x5040)
 #define AXI_CFG_RCGR                    REG_MM(0x5044)
@@ -126,4 +133,7 @@
 void video_gdsc_disable();
 void clock_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id);
 
+void hdmi_clk_enable(void);
+void hdmi_clk_disable(void);
+
 #endif
diff --git a/platform/msm8996/msm8996-clock.c b/platform/msm8996/msm8996-clock.c
index 8a02900..9074bd6 100644
--- a/platform/msm8996/msm8996-clock.c
+++ b/platform/msm8996/msm8996-clock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 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
@@ -46,6 +46,7 @@
 #define mmpll1_mm_source_val 2
 #define mmpll3_mm_source_val 3
 #define gpll0_mm_source_val 5
+#define hdmipll_mm_source_val 3
 
 struct clk_freq_tbl rcg_dummy_freq = F_END;
 
@@ -813,6 +814,77 @@
 	},
 };
 
+static struct branch_clk mdss_hdmi_ahb_clk = {
+	.cbcr_reg = (uint32_t *) MDSS_HDMI_AHB_CBCR,
+	.has_sibling = 1,
+	.c = {
+		.dbg_name = "mdss_hdmi_ahb_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_hdmi_clk[] = {
+	F_MM( 19200000,  cxo,    1, 0, 0),
+	F_END
+};
+
+static struct rcg_clk hdmi_clk_src = {
+	.cmd_reg = (uint32_t *) HDMI_CMD_RCGR,
+	.cfg_reg = (uint32_t *) HDMI_CFG_RCGR,
+	.set_rate = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl = ftbl_mdss_hdmi_clk,
+	.current_freq = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "hdmi_clk_src",
+		.ops = &clk_ops_rcg,
+	},
+};
+
+static struct branch_clk mdss_hdmi_clk = {
+	.cbcr_reg = (uint32_t *) MDSS_HDMI_CBCR,
+	.has_sibling = 0,
+	.parent = &hdmi_clk_src.c,
+	.c = {
+		.dbg_name = "mdss_hdmi_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_extpclk_clk[] = {
+	F_MDSS( 74250000, hdmipll, 1, 0, 0),
+	F_MDSS( 25200000, hdmipll, 1, 0, 0),
+	F_MDSS( 27000000, hdmipll, 1, 0, 0),
+	F_MDSS( 27030000, hdmipll, 1, 0, 0),
+	F_MDSS( 27070000, hdmipll, 1, 0, 0),
+	F_MDSS( 65000000, hdmipll, 1, 0, 0),
+	F_MDSS(108000000, hdmipll, 1, 0, 0),
+	F_MDSS(148500000, hdmipll, 1, 0, 0),
+	F_MDSS(268500000, hdmipll, 1, 0, 0),
+	F_MDSS(297000000, hdmipll, 1, 0, 0),
+	F_END
+};
+
+static struct rcg_clk extpclk_clk_src = {
+	.cmd_reg = (uint32_t *) EXTPCLK_CMD_RCGR,
+	.cfg_reg = (uint32_t *) EXTPCLK_CFG_RCGR,
+	.set_rate = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl = ftbl_mdss_extpclk_clk,
+	.current_freq = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "extpclk_clk_src",
+		.ops = &clk_ops_rcg,
+	},
+};
+
+static struct branch_clk mdss_extpclk_clk = {
+	.cbcr_reg = (uint32_t *) MDSS_EXTPCLK_CBCR,
+	.has_sibling = 0,
+	.parent = &extpclk_clk_src.c,
+	.c = {
+		.dbg_name = "mdss_extpclk_clk",
+		.ops = &clk_ops_branch,
+	},
+};
 
 /* Clock lookup table */
 static struct clk_lookup msm_msm8996_clocks[] =
@@ -863,6 +935,11 @@
 		gcc_blsp2_qup2_i2c_apps_clk_src.c),
 	CLK_LOOKUP("gcc_blsp2_qup2_i2c_apps_clk",
 		gcc_blsp2_qup2_i2c_apps_clk.c),
+
+	/* HDMI clocks*/
+	CLK_LOOKUP("hdmi_ahb_clk",         mdss_hdmi_ahb_clk.c),
+	CLK_LOOKUP("hdmi_core_clk",        mdss_hdmi_clk.c),
+	CLK_LOOKUP("hdmi_extp_clk",        mdss_extpclk_clk.c),
 };
 
 void platform_clock_init(void)
diff --git a/platform/msm_shared/include/mdp5.h b/platform/msm_shared/include/mdp5.h
index b8deb6d..935e7a6 100644
--- a/platform/msm_shared/include/mdp5.h
+++ b/platform/msm_shared/include/mdp5.h
@@ -265,9 +265,11 @@
 int target_edp_panel_disable(void);
 int target_edp_bl_ctrl(int enable);
 int mdss_hdmi_init(void);
+void mdss_hdmi_display_init(uint32_t rev, void *base);
 int mdss_hdmi_on(struct msm_panel_info *pinfo);
 int mdss_hdmi_config(struct msm_panel_info *pinfo, struct fbcon_config *fb);
 void mdss_hdmi_get_vic(char *buf);
+void hdmi_phy_init(void);
 int msm_display_off();
 void display_shutdown(void);
 
diff --git a/platform/msm_shared/mdss_hdmi.c b/platform/msm_shared/mdss_hdmi.c
index 0741308..4908c19 100644
--- a/platform/msm_shared/mdss_hdmi.c
+++ b/platform/msm_shared/mdss_hdmi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2016, 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
@@ -101,6 +101,8 @@
 		{10240, 247500}, {18816, 247500}, {20480, 247500} }),
 };
 
+extern int msm_display_init(struct msm_fb_panel_data *pdata);
+
 /* AVI INFOFRAME DATA */
 #define NUM_MODES_AVI 20
 #define AVI_MAX_DATA_BYTES 13
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index f426e93..be1a5f1 100755
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -582,7 +582,8 @@
 			$(LOCAL_DIR)/mipi_dsi_autopll_thulium.o \
 			$(LOCAL_DIR)/shutdown_detect.o \
 			$(LOCAL_DIR)/i2c_qup.o \
-			$(LOCAL_DIR)/mipi_dsi_i2c.o
+			$(LOCAL_DIR)/mipi_dsi_i2c.o \
+			$(LOCAL_DIR)/mdss_hdmi.o
 endif
 
 ifeq ($(ENABLE_UFS_SUPPORT), 1)
diff --git a/target/msm8996/include/target/display.h b/target/msm8996/include/target/display.h
index 5b21a1f..9ee5ec3 100644
--- a/target/msm8996/include/target/display.h
+++ b/target/msm8996/include/target/display.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, 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
@@ -33,6 +33,7 @@
 /* HEADER files                                                              */
 /*---------------------------------------------------------------------------*/
 #include <display_resource.h>
+#include <msm_panel.h>
 
 /*---------------------------------------------------------------------------*/
 /* Target Physical configuration                                             */
@@ -67,6 +68,7 @@
 #define DISPLAY_CMDLINE_PREFIX " mdss_mdp.panel="
 
 #define MIPI_FB_ADDR  0x83400000
+#define HDMI_FB_ADDR  0xB1C00000
 
 #define MIPI_HSYNC_PULSE_WIDTH       16
 #define MIPI_HSYNC_BACK_PORCH_DCLK   32
@@ -79,7 +81,8 @@
 #define PWM_BL_LPG_CHAN_ID           4	/* lpg_out<3> */
 
 #define HDMI_PANEL_NAME              "hdmi"
-#define HDMI_CONTROLLER_STRING       "hdmi:0"
+#define HDMI_CONTROLLER_STRING       "hdmi:"
+#define HDMI_VIC_LEN                 5
 
 /*---------------------------------------------------------------------------*/
 /* Functions		                                                     */
@@ -93,5 +96,9 @@
 void target_force_cont_splash_disable(uint8_t override);
 uint8_t target_panel_auto_detect_enabled();
 void target_set_switch_gpio(int enable_dsi2hdmibridge);
+int target_hdmi_pll_clock(uint8_t enable, struct msm_panel_info *pinfo);
+int target_hdmi_panel_clock(uint8_t enable, struct msm_panel_info *pinfo);
+int target_hdmi_regulator_ctrl(uint8_t enable);
+int target_hdmi_gpio_ctrl(uint8_t enable);
 
 #endif
diff --git a/target/msm8996/regulator.c b/target/msm8996/regulator.c
index 909082d..a95a42f 100644
--- a/target/msm8996/regulator.c
+++ b/target/msm8996/regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 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
@@ -48,6 +48,23 @@
 	},
 };
 
+static uint32_t ldo12[][11]=
+{
+	{
+		LDOA_RES_TYPE, 12,
+		KEY_SOFTWARE_ENABLE, 4, GENERIC_DISABLE,
+		KEY_MICRO_VOLT, 4, 0,
+		KEY_CURRENT, 4, 0,
+	},
+
+	{
+		LDOA_RES_TYPE, 12,
+		KEY_SOFTWARE_ENABLE, 4, GENERIC_ENABLE,
+		KEY_MICRO_VOLT, 4, 1800000,
+		KEY_CURRENT, 4, 11,
+	},
+};
+
 static uint32_t ldo14[][11]=
 {
 	{
@@ -88,6 +105,9 @@
 	if (enable & REG_LDO2)
 		rpm_send_data(&ldo2[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
 
+	if (enable & REG_LDO12)
+		rpm_send_data(&ldo12[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
+
 	if (enable & REG_LDO14)
 		rpm_send_data(&ldo14[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
 
@@ -100,6 +120,9 @@
 	if (enable & REG_LDO2)
 		rpm_send_data(&ldo2[GENERIC_DISABLE][0], 36, RPM_REQUEST_TYPE);
 
+	if (enable & REG_LDO12)
+		rpm_send_data(&ldo12[GENERIC_DISABLE][0], 36, RPM_REQUEST_TYPE);
+
 	if (enable & REG_LDO14)
 		rpm_send_data(&ldo14[GENERIC_DISABLE][0], 36, RPM_REQUEST_TYPE);
 
diff --git a/target/msm8996/target_display.c b/target/msm8996/target_display.c
index 5086451..3709094 100644
--- a/target/msm8996/target_display.c
+++ b/target/msm8996/target_display.c
@@ -92,6 +92,88 @@
   "msmgpio", 105, 3, 1, 0, 1
 };
 
+/* gpio name, id, strength, direction, pull, state. */
+static struct gpio_pin hdmi_cec_gpio = {        /* CEC */
+  "msmgpio", 31, 0, 2, 3, 1
+};
+
+static struct gpio_pin hdmi_ddc_clk_gpio = {   /* DDC CLK */
+  "msmgpio", 32, 0, 2, 3, 1
+};
+
+static struct gpio_pin hdmi_ddc_data_gpio = {  /* DDC DATA */
+  "msmgpio", 33, 0, 2, 3, 1
+};
+
+static struct gpio_pin hdmi_hpd_gpio = {       /* HPD, input */
+  "msmgpio", 34, 7, 0, 1, 1
+};
+
+static void target_hdmi_ldo_enable(uint8_t enable)
+{
+	if (enable)
+		regulator_enable(REG_LDO12);
+	else
+		regulator_disable(REG_LDO12);
+}
+
+static void target_hdmi_mpp4_enable(uint8_t enable)
+{
+	struct pm8x41_mpp mpp;
+
+	/* Enable MPP4 */
+	pmi8994_config_mpp_slave_id(0);
+
+        mpp.base = PM8x41_MMP4_BASE;
+	mpp.vin = MPP_VIN2;
+	mpp.mode = MPP_HIGH;;
+	if (enable) {
+		pm8x41_config_output_mpp(&mpp);
+		pm8x41_enable_mpp(&mpp, MPP_ENABLE);
+	} else {
+		pm8x41_enable_mpp(&mpp, MPP_DISABLE);
+	}
+
+	/* Need delay before power on regulators */
+	mdelay(20);
+}
+
+int target_hdmi_regulator_ctrl(uint8_t enable)
+{
+	target_hdmi_ldo_enable(enable);
+
+	target_hdmi_mpp4_enable(enable);
+
+	return 0;
+}
+
+int target_hdmi_gpio_ctrl(uint8_t enable)
+{
+	gpio_tlmm_config(hdmi_cec_gpio.pin_id, 1,	/* gpio 31, CEC */
+		hdmi_cec_gpio.pin_direction, hdmi_cec_gpio.pin_pull,
+		hdmi_cec_gpio.pin_strength, hdmi_cec_gpio.pin_state);
+
+	gpio_tlmm_config(hdmi_ddc_clk_gpio.pin_id, 1,	/* gpio 32, DDC CLK */
+		hdmi_ddc_clk_gpio.pin_direction, hdmi_ddc_clk_gpio.pin_pull,
+		hdmi_ddc_clk_gpio.pin_strength, hdmi_ddc_clk_gpio.pin_state);
+
+
+	gpio_tlmm_config(hdmi_ddc_data_gpio.pin_id, 1,	/* gpio 33, DDC DATA */
+		hdmi_ddc_data_gpio.pin_direction, hdmi_ddc_data_gpio.pin_pull,
+		hdmi_ddc_data_gpio.pin_strength, hdmi_ddc_data_gpio.pin_state);
+
+	gpio_tlmm_config(hdmi_hpd_gpio.pin_id, 1,	/* gpio 34, HPD */
+		hdmi_hpd_gpio.pin_direction, hdmi_hpd_gpio.pin_pull,
+		hdmi_hpd_gpio.pin_strength, hdmi_hpd_gpio.pin_state);
+
+	gpio_set(hdmi_cec_gpio.pin_id,      hdmi_cec_gpio.pin_direction);
+	gpio_set(hdmi_ddc_clk_gpio.pin_id,  hdmi_ddc_clk_gpio.pin_direction);
+	gpio_set(hdmi_ddc_data_gpio.pin_id, hdmi_ddc_data_gpio.pin_direction);
+	gpio_set(hdmi_hpd_gpio.pin_id,      hdmi_hpd_gpio.pin_direction);
+
+	return NO_ERROR;
+}
+
 static uint32_t thulium_dsi_pll_lock_status(uint32_t pll_base, uint32_t off,
 	uint32_t bit)
 {
@@ -579,6 +661,7 @@
 	int prefix_string_len = strlen(DISPLAY_CMDLINE_PREFIX);
 	bool ret = true;
 	struct oem_panel_data oem = mdss_dsi_get_oem_data();
+	char vic_buf[HDMI_VIC_LEN] = "0";
 
 	if (!strcmp(oem.panel, HDMI_PANEL_NAME)) {
 		if (buf_size < (prefix_string_len + LK_OVERRIDE_PANEL_LEN +
@@ -592,6 +675,9 @@
 		strlcat(pbuf, LK_OVERRIDE_PANEL, buf_size);
 		buf_size -= LK_OVERRIDE_PANEL_LEN;
 		strlcat(pbuf, HDMI_CONTROLLER_STRING, buf_size);
+		buf_size -= strlen(HDMI_CONTROLLER_STRING);
+		mdss_hdmi_get_vic(vic_buf);
+		strlcat(pbuf, vic_buf, buf_size);
 	} else {
 		ret = gcdb_display_cmdline_arg(pbuf, buf_size);
 	}
@@ -629,6 +715,8 @@
 			oem.panel);
 		return;
 	} else if (!strcmp(oem.panel, HDMI_PANEL_NAME)) {
+		dprintf(INFO, "%s: HDMI is primary\n", __func__);
+		mdss_hdmi_display_init(MDP_REV_50, (void *) HDMI_FB_ADDR);
 		return;
 	}