Merge "coresight: use 2K block size transfers for output via usb"
diff --git a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
index d82284d..53a67a4 100644
--- a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
+++ b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
@@ -5,10 +5,14 @@
 - reg : the location and size of the BAM hardware
 - interrupts : the BAM hardware to apps processor interrupt line
 
+Optional properties:
+-qcom,satellite-mode: the hardware needs to be configured in satellite mode
+
 Example:
 
 	qcom,bam_dmux@fc834000 {
 		compatible = "qcom,bam_dmux";
 		reg = <0xfc834000 0x7000>;
 		interrupts = <0 29 1>;
+		qcom,satellite-mode;
 	};
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 7ba22f4..c475e2d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -193,6 +193,7 @@
 static struct sps_mem_buffer rx_desc_mem_buf;
 static struct sps_register_event tx_register_event;
 static struct sps_register_event rx_register_event;
+static bool satellite_mode;
 
 static struct bam_ch_info bam_ch[BAM_DMUX_NUM_CHANNELS];
 static int bam_mux_initialized;
@@ -2074,7 +2075,7 @@
 	a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
 	a2_props.num_pipes = A2_NUM_PIPES;
 	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
-	if (cpu_is_msm9615())
+	if (cpu_is_msm9615() || satellite_mode)
 		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 	/* need to free on tear down */
 	ret = sps_register_bam_device(&a2_props, &h);
@@ -2246,7 +2247,7 @@
 	a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
 	a2_props.num_pipes = A2_NUM_PIPES;
 	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
-	if (cpu_is_msm9615())
+	if (cpu_is_msm9615() || satellite_mode)
 		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 	ret = sps_register_bam_device(&a2_props, &h);
 	if (ret < 0) {
@@ -2374,10 +2375,14 @@
 			pr_err("%s: irq field missing\n", __func__);
 			return -ENODEV;
 		}
-		DBG("%s: base:%p size:%x irq:%d\n", __func__,
+		satellite_mode = of_property_read_bool(pdev->dev.of_node,
+						"qcom,satellite-mode");
+
+		DBG("%s: base:%p size:%x irq:%d satellite:%d\n", __func__,
 							a2_phys_base,
 							a2_phys_size,
-							a2_bam_irq);
+							a2_bam_irq,
+							satellite_mode);
 	} else { /* fallback to default init data */
 		a2_phys_base = (void *)(A2_PHYS_BASE);
 		a2_phys_size = A2_PHYS_SIZE;
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 2455e93..9b04141 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -29,7 +29,8 @@
 	HDMI_SAMPLE_RATE_88_2KHZ,
 	HDMI_SAMPLE_RATE_96KHZ,
 	HDMI_SAMPLE_RATE_176_4KHZ,
-	HDMI_SAMPLE_RATE_192KHZ
+	HDMI_SAMPLE_RATE_192KHZ,
+	HDMI_SAMPLE_RATE_MAX
 };
 
 int hdmi_audio_enable(bool on , u32 fifo_water_mark);
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 0f17a0b..66d6bda 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -27,4 +27,3 @@
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
 obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
 obj-$(CONFIG_MSM_ULTRASOUND_A) += ultrasound/version_a/
-obj-m += adsprpc.o
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 00a07a0..0b3ffef 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -649,6 +649,16 @@
           block.  Or some systems may want the iMem to be dedicated to a
           different function.
 
+config MSM_ADSPRPC
+        tristate "Qualcomm ADSP RPC driver"
+        depends on MSM_AUDIO_QDSP6 || MSM_AUDIO_QDSP6V2
+        default m
+        help
+          Provides a communication mechanism that allows for clients to
+          make remote method invocations across processor boundary to
+          applications DSP processor. Say M if you want to enable this
+          module.
+
 config MMC_GENERIC_CSDIO
 	tristate "Generic sdio driver"
 	default n
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index c38c26c..8032f0b 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -66,4 +66,5 @@
 obj-$(CONFIG_TILE_SROM)		+= tile-srom.o
 obj-$(CONFIG_MSM_ROTATOR)	+= msm_rotator.o
 obj-$(CONFIG_MMC_GENERIC_CSDIO)	+= csdio.o
-obj-$(CONFIG_DIAG_CHAR)		+= diag/
\ No newline at end of file
+obj-$(CONFIG_DIAG_CHAR)		+= diag/
+obj-$(CONFIG_MSM_ADSPRPC)       += adsprpc.o
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.c b/drivers/char/adsprpc.c
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc.c
rename to drivers/char/adsprpc.c
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.h b/drivers/char/adsprpc.h
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc.h
rename to drivers/char/adsprpc.h
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
rename to drivers/char/adsprpc_shared.h
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 0a85b93..10c5a17 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -672,9 +672,9 @@
 		qpnp_adc_attr.index = iadc->adc->adc_channels[i].channel_num;
 		qpnp_adc_attr.dev_attr.attr.name =
 						iadc->adc->adc_channels[i].name;
-		sysfs_attr_init(&iadc->sens_attr[i].dev_attr.attr);
 		memcpy(&iadc->sens_attr[i], &qpnp_adc_attr,
 						sizeof(qpnp_adc_attr));
+		sysfs_attr_init(&iadc->sens_attr[i].dev_attr.attr);
 		rc = device_create_file(&spmi->dev,
 				&iadc->sens_attr[i].dev_attr);
 		if (rc) {
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 5690c88..5eef34f 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -714,9 +714,9 @@
 		qpnp_adc_attr.index = vadc->adc->adc_channels[i].channel_num;
 		qpnp_adc_attr.dev_attr.attr.name =
 						vadc->adc->adc_channels[i].name;
-		sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
 		memcpy(&vadc->sens_attr[i], &qpnp_adc_attr,
 						sizeof(qpnp_adc_attr));
+		sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
 		rc = device_create_file(&spmi->dev,
 				&vadc->sens_attr[i].dev_attr);
 		if (rc) {
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index eaf0fcb..8a36d6c 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -4357,6 +4357,11 @@
 						vin_collapse_check_worker);
 	INIT_DELAYED_WORK(&chip->unplug_check_work, unplug_check_worker);
 
+	INIT_WORK(&chip->bms_notify.work, bms_notify);
+	INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
+
+	INIT_DELAYED_WORK(&chip->update_heartbeat_work, update_heartbeat);
+
 	rc = request_irqs(chip, pdev);
 	if (rc) {
 		pr_err("couldn't register interrupts rc=%d\n", rc);
@@ -4393,19 +4398,13 @@
 	}
 	create_debugfs_entries(chip);
 
-	INIT_WORK(&chip->bms_notify.work, bms_notify);
-	INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
-
 	/* determine what state the charger is in */
 	determine_initial_state(chip);
 
-	if (chip->update_time) {
-		INIT_DELAYED_WORK(&chip->update_heartbeat_work,
-							update_heartbeat);
+	if (chip->update_time)
 		schedule_delayed_work(&chip->update_heartbeat_work,
 				      round_jiffies_relative(msecs_to_jiffies
 							(chip->update_time)));
-	}
 	return 0;
 
 free_irq:
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index c2d5f28..d53240f 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -18,6 +18,7 @@
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
 #include <linux/types.h>
+#include <mach/msm_hdmi_audio.h>
 
 #define REG_DUMP 0
 
@@ -40,6 +41,17 @@
 	((d & 0xff) + ((d >> 8) & 0xff) +	\
 	((d >> 16) & 0xff) + ((d >> 24) & 0xff))
 
+/* parameters for clock regeneration */
+struct hdmi_tx_audio_acr {
+	u32 n;
+	u32 cts;
+};
+
+struct hdmi_tx_audio_acr_arry {
+	u32 pclk;
+	struct hdmi_tx_audio_acr lut[HDMI_SAMPLE_RATE_MAX];
+};
+
 static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on);
 static irqreturn_t hdmi_tx_isr(int irq, void *data);
 
@@ -90,6 +102,27 @@
 	 0x07,	0x07,	0x07,	0x07,	0x02, 0x02, 0x02}  /*12*/
 };
 
+/* Audio constants lookup table for hdmi_tx_audio_acr_setup */
+/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
+static const struct hdmi_tx_audio_acr_arry hdmi_tx_audio_acr_lut[] = {
+	/*  25.200MHz  */
+	{25200, {{4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000},
+		{12288, 25200}, {25088, 28000}, {24576, 25200} } },
+	/*  27.000MHz  */
+	{27000, {{4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
+		{12288, 27000}, {25088, 30000}, {24576, 27000} } },
+	/*  27.027MHz */
+	{27030, {{4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
+		{12288, 27027}, {25088, 30030}, {24576, 27027} } },
+	/*  74.250MHz */
+	{74250, {{4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
+		{12288, 74250}, {25088, 82500}, {24576, 74250} } },
+	/* 148.500MHz */
+	{148500, {{4096, 148500}, {6272, 165000}, {6144, 148500},
+		{12544, 165000}, {12288, 148500}, {25088, 165000},
+		{24576, 148500} } },
+};
+
 const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
 {
 	switch (module) {
@@ -335,8 +368,8 @@
 
 static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
-	struct dss_io_data *io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
-	return !(DSS_REG_R_ND(io, HDMI_CTRL) & BIT(1));
+	return hdmi_edid_get_sink_mode(
+		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
 } /* hdmi_tx_is_dvi_mode */
 
 static int hdmi_tx_init_panel_info(uint32_t resolution,
@@ -1275,6 +1308,335 @@
 	DSS_REG_W_ND(io, HDMI_PHY_PD_CTRL0, 0x7F);
 } /* hdmi_tx_powerdown_phy */
 
+static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
+	bool enabled, int num_of_channels)
+{
+	/* Read first before writing */
+	u32 acr_pck_ctrl_reg;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return -EINVAL;
+	}
+
+	acr_pck_ctrl_reg = DSS_REG_R(io, HDMI_ACR_PKT_CTRL);
+
+	if (enabled) {
+		const struct hdmi_disp_mode_timing_type *timing =
+			hdmi_get_supported_mode(hdmi_ctrl->video_resolution);
+		const struct hdmi_tx_audio_acr_arry *audio_acr =
+			&hdmi_tx_audio_acr_lut[0];
+		const int lut_size = sizeof(hdmi_tx_audio_acr_lut)
+			/ sizeof(*hdmi_tx_audio_acr_lut);
+		u32 i, n, cts, layout, multiplier, aud_pck_ctrl_2_reg;
+
+		if (timing == NULL) {
+			DEV_WARN("%s: video format %d not supported\n",
+				__func__, hdmi_ctrl->video_resolution);
+			return -EPERM;
+		}
+
+		for (i = 0; i < lut_size;
+			audio_acr = &hdmi_tx_audio_acr_lut[++i]) {
+			if (audio_acr->pclk == timing->pixel_freq)
+				break;
+		}
+		if (i >= lut_size) {
+			DEV_WARN("%s: pixel clk %d not supported\n", __func__,
+				timing->pixel_freq);
+			return -EPERM;
+		}
+
+		n = audio_acr->lut[hdmi_ctrl->audio_sample_rate].n;
+		cts = audio_acr->lut[hdmi_ctrl->audio_sample_rate].cts;
+		layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+
+		if (
+		(HDMI_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+			multiplier = 4;
+			n >>= 2; /* divide N by 4 and use multiplier */
+		} else if (
+		(HDMI_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate)) {
+			multiplier = 2;
+			n >>= 1; /* divide N by 2 and use multiplier */
+		} else {
+			multiplier = 1;
+		}
+		DEV_DBG("%s: n=%u, cts=%u, layout=%u\n", __func__, n, cts,
+			layout);
+
+		/* AUDIO_PRIORITY | SOURCE */
+		acr_pck_ctrl_reg |= 0x80000100;
+		/* N_MULTIPLE(multiplier) */
+		acr_pck_ctrl_reg |= (multiplier & 7) << 16;
+
+		if ((HDMI_SAMPLE_RATE_48KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate)) {
+			/* SELECT(3) */
+			acr_pck_ctrl_reg |= 3 << 4;
+			/* CTS_48 */
+			cts <<= 12;
+
+			/* CTS: need to determine how many fractional bits */
+			DSS_REG_W(io, HDMI_ACR_48_0, cts);
+			/* N */
+			DSS_REG_W(io, HDMI_ACR_48_1, n);
+		} else if (
+		(HDMI_SAMPLE_RATE_44_1KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+			/* SELECT(2) */
+			acr_pck_ctrl_reg |= 2 << 4;
+			/* CTS_44 */
+			cts <<= 12;
+
+			/* CTS: need to determine how many fractional bits */
+			DSS_REG_W(io, HDMI_ACR_44_0, cts);
+			/* N */
+			DSS_REG_W(io, HDMI_ACR_44_1, n);
+		} else {	/* default to 32k */
+			/* SELECT(1) */
+			acr_pck_ctrl_reg |= 1 << 4;
+			/* CTS_32 */
+			cts <<= 12;
+
+			/* CTS: need to determine how many fractional bits */
+			DSS_REG_W(io, HDMI_ACR_32_0, cts);
+			/* N */
+			DSS_REG_W(io, HDMI_ACR_32_1, n);
+		}
+		/* Payload layout depends on number of audio channels */
+		/* LAYOUT_SEL(layout) */
+		aud_pck_ctrl_2_reg = 1 | (layout << 1);
+		/* override | layout */
+		DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL2, aud_pck_ctrl_2_reg);
+
+		/* SEND | CONT */
+		acr_pck_ctrl_reg |= 0x00000003;
+	} else {
+		/* ~(SEND | CONT) */
+		acr_pck_ctrl_reg &= ~0x00000003;
+	}
+	DSS_REG_W(io, HDMI_ACR_PKT_CTRL, acr_pck_ctrl_reg);
+
+	return 0;
+} /* hdmi_tx_audio_acr_setup */
+
+static int hdmi_tx_audio_info_setup(void *priv_d, bool enabled,
+	u32 num_of_channels, u32 channel_allocation, u32 level_shift,
+	bool down_mix)
+{
+	struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)priv_d;
+	struct dss_io_data *io = NULL;
+
+	u32 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
+	u32 check_sum, audio_info_0_reg, audio_info_1_reg;
+	u32 audio_info_ctrl_reg;
+	u32 aud_pck_ctrl_2_reg;
+	u32 layout;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return -EINVAL;
+	}
+
+	layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+	aud_pck_ctrl_2_reg = 1 | (layout << 1);
+	DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL2, aud_pck_ctrl_2_reg);
+
+	/*
+	 * Please see table 20 Audio InfoFrame in HDMI spec
+	 * FL  = front left
+	 * FC  = front Center
+	 * FR  = front right
+	 * FLC = front left center
+	 * FRC = front right center
+	 * RL  = rear left
+	 * RC  = rear center
+	 * RR  = rear right
+	 * RLC = rear left center
+	 * RRC = rear right center
+	 * LFE = low frequency effect
+	 */
+
+	/* Read first then write because it is bundled with other controls */
+	audio_info_ctrl_reg = DSS_REG_R(io, HDMI_INFOFRAME_CTRL0);
+
+	if (enabled) {
+		switch (num_of_channels) {
+		case MSM_HDMI_AUDIO_CHANNEL_2:
+			channel_allocation = 0;	/* Default to FR, FL */
+			break;
+		case MSM_HDMI_AUDIO_CHANNEL_4:
+			channel_count = 3;
+			/* FC, LFE, FR, FL */
+			channel_allocation = 0x3;
+			break;
+		case MSM_HDMI_AUDIO_CHANNEL_6:
+			channel_count = 5;
+			/* RR, RL, FC, LFE, FR, FL */
+			channel_allocation = 0xB;
+			break;
+		case MSM_HDMI_AUDIO_CHANNEL_8:
+			channel_count = 7;
+			/* FRC, FLC, RR, RL, FC, LFE, FR, FL */
+			channel_allocation = 0x1f;
+			break;
+		default:
+			DEV_ERR("%s: Unsupported num_of_channels = %u\n",
+				__func__, num_of_channels);
+			return -EINVAL;
+		}
+
+		/* Program the Channel-Speaker allocation */
+		audio_info_1_reg = 0;
+		/* CA(channel_allocation) */
+		audio_info_1_reg |= channel_allocation & 0xff;
+		/* Program the Level shifter */
+		audio_info_1_reg |= (level_shift << 11) & 0x00007800;
+		/* Program the Down-mix Inhibit Flag */
+		audio_info_1_reg |= (down_mix << 15) & 0x00008000;
+
+		DSS_REG_W(io, HDMI_AUDIO_INFO1, audio_info_1_reg);
+
+		/*
+		 * Calculate CheckSum: Sum of all the bytes in the
+		 * Audio Info Packet (See table 8.4 in HDMI spec)
+		 */
+		check_sum = 0;
+		/* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_TYPE[0x84] */
+		check_sum += 0x84;
+		/* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_VERSION[0x01] */
+		check_sum += 1;
+		/* HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH[0x0A] */
+		check_sum += 0x0A;
+		check_sum += channel_count;
+		check_sum += channel_allocation;
+		/* See Table 8.5 in HDMI spec */
+		check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7;
+		check_sum &= 0xFF;
+		check_sum = (u8) (256 - check_sum);
+
+		audio_info_0_reg = 0;
+		/* CHECKSUM(check_sum) */
+		audio_info_0_reg |= check_sum & 0xff;
+		/* CC(channel_count) */
+		audio_info_0_reg |= (channel_count << 8) & 0x00000700;
+
+		DSS_REG_W(io, HDMI_AUDIO_INFO0, audio_info_0_reg);
+
+		/*
+		 * Set these flags
+		 * AUDIO_INFO_UPDATE |
+		 * AUDIO_INFO_SOURCE |
+		 * AUDIO_INFO_CONT   |
+		 * AUDIO_INFO_SEND
+		 */
+		audio_info_ctrl_reg |= 0x000000F0;
+	} else {
+		/*Clear these flags
+		 * ~(AUDIO_INFO_UPDATE |
+		 *   AUDIO_INFO_SOURCE |
+		 *   AUDIO_INFO_CONT   |
+		 *   AUDIO_INFO_SEND)
+		 */
+		audio_info_ctrl_reg &= ~0x000000F0;
+	}
+	DSS_REG_W(io, HDMI_INFOFRAME_CTRL0, audio_info_ctrl_reg);
+
+	dss_reg_dump(io->base, io->len, "HDMI-AUDIO-ON: ", REG_DUMP);
+
+	return 0;
+} /* hdmi_tx_audio_info_setup */
+
+static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int rc = 0;
+	const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true, channels);
+	if (rc) {
+		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed. rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	rc = hdmi_tx_audio_info_setup(hdmi_ctrl, true, channels, 0, 0, false);
+	if (rc) {
+		DEV_ERR("%s: hdmi_tx_audio_info_setup failed. rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	DEV_INFO("HDMI Audio: Enabled\n");
+
+	return 0;
+} /* hdmi_tx_audio_setup */
+
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int i;
+	u32 audio_pkt_ctrl, audio_cfg;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return;
+	}
+
+	/* Number of wait iterations */
+	i = 10;
+	do {
+		audio_pkt_ctrl = DSS_REG_R_ND(io, HDMI_AUDIO_PKT_CTRL);
+		audio_cfg = DSS_REG_R_ND(io, HDMI_AUDIO_CFG);
+		DEV_DBG("%s: i=%d, AUDIO PACKET=%08x, AUDIO CFG=%08x",
+			__func__, i, audio_pkt_ctrl, audio_cfg);
+		msleep(20);
+	} while (((audio_pkt_ctrl & BIT(0)) || (audio_cfg & BIT(0))) && i--);
+
+	if (hdmi_tx_audio_info_setup(hdmi_ctrl, false, 0, 0, 0, false))
+		DEV_ERR("%s: hdmi_tx_audio_info_setup failed.\n", __func__);
+
+	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false, 0))
+		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);
+
+	DEV_INFO("HDMI Audio: Disabled\n");
+} /* hdmi_tx_audio_off */
+
 static int hdmi_tx_start(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	int rc = 0;
@@ -1290,8 +1652,6 @@
 		return -EINVAL;
 	}
 
-	/* todo: Audio */
-
 	hdmi_tx_set_mode(hdmi_ctrl, false);
 	hdmi_tx_init_phy(hdmi_ctrl);
 	DSS_REG_W(io, HDMI_USEC_REFTIMER, 0x0001001B);
@@ -1299,7 +1659,21 @@
 	hdmi_tx_set_mode(hdmi_ctrl, true);
 
 	hdmi_tx_video_setup(hdmi_ctrl, hdmi_ctrl->video_resolution);
-	/* todo: Audio */
+
+	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
+		rc = hdmi_tx_audio_setup(hdmi_ctrl);
+		if (rc) {
+			DEV_ERR("%s: hdmi_msm_audio_setup failed. rc=%d\n",
+				__func__, rc);
+			hdmi_tx_set_mode(hdmi_ctrl, false);
+			return rc;
+		}
+
+		switch_set_state(&hdmi_ctrl->audio_sdev, 1);
+		DEV_INFO("%s: hdmi_audio state switch to %d\n", __func__,
+			hdmi_ctrl->audio_sdev.state);
+	}
+
 	hdmi_tx_set_avi_infoframe(hdmi_ctrl);
 	/* todo: CONFIG_FB_MSM_HDMI_3D */
 	hdmi_tx_set_spd_infoframe(hdmi_ctrl);
@@ -1324,8 +1698,16 @@
 		return -EINVAL;
 	}
 
-	DEV_INFO("%s: power: OFF (audio off, Reset Core)\n", __func__);
-	/* todo: Audio */
+	DEV_INFO("%s: HDMI Core: OFF\n", __func__);
+
+	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
+		switch_set_state(&hdmi_ctrl->audio_sdev, 0);
+		DEV_INFO("%s: hdmi_audio state switch to %d\n", __func__,
+			hdmi_ctrl->audio_sdev.state);
+
+		hdmi_tx_audio_off(hdmi_ctrl);
+	}
+
 	hdmi_tx_powerdown_phy(hdmi_ctrl);
 	hdmi_ctrl->panel_power_on = false;
 	hdmi_tx_core_off(hdmi_ctrl);
@@ -1546,6 +1928,7 @@
 	if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID])
 		hdmi_edid_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]);
 
+	switch_dev_unregister(&hdmi_ctrl->audio_sdev);
 	switch_dev_unregister(&hdmi_ctrl->sdev);
 	del_timer_sync(&hdmi_ctrl->hpd_state_timer);
 	if (hdmi_ctrl->workq)
@@ -1581,6 +1964,7 @@
 	hdmi_ctrl->workq = create_workqueue("hdmi_tx_workq");
 	if (!hdmi_ctrl->workq) {
 		DEV_ERR("%s: hdmi_tx_workq creation failed.\n", __func__);
+		rc = -EPERM;
 		goto fail_create_workq;
 	}
 
@@ -1594,14 +1978,27 @@
 	hdmi_ctrl->hpd_state_timer.data = (u32)hdmi_ctrl;
 	hdmi_ctrl->hpd_state_timer.expires = 0xffffffffL;
 
+	hdmi_ctrl->audio_sample_rate = HDMI_SAMPLE_RATE_48KHZ;
+
 	hdmi_ctrl->sdev.name = "hdmi";
 	if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
 		DEV_ERR("%s: Hdmi switch registration failed\n", __func__);
+		rc = -ENODEV;
 		goto fail_switch_dev;
 	}
 
+	hdmi_ctrl->audio_sdev.name = "hdmi_audio";
+	if (switch_dev_register(&hdmi_ctrl->audio_sdev) < 0) {
+		DEV_ERR("%s: hdmi_audio switch registration failed\n",
+			__func__);
+		rc = -ENODEV;
+		goto fail_audio_switch_dev;
+	}
+
 	return 0;
 
+fail_audio_switch_dev:
+	switch_dev_unregister(&hdmi_ctrl->sdev);
 fail_switch_dev:
 	del_timer_sync(&hdmi_ctrl->hpd_state_timer);
 fail_create_workq:
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 94e0fda..437f681 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -41,9 +41,12 @@
 	struct hdmi_tx_platform_data pdata;
 	struct mdss_panel_data panel_data;
 
+	int audio_sample_rate;
+
 	struct mutex mutex;
 	struct kobject *kobj;
 	struct switch_dev sdev;
+	struct switch_dev audio_sdev;
 	struct workqueue_struct *workq;
 
 	uint32_t video_resolution;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index 8cfa95b..2c41ab4 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -493,6 +493,7 @@
 				ddl_get_state_string(ddl->client_state));
 			ddl_calc_core_proc_time(__func__, DEC_OP_TIME, ddl);
 			ddl_reset_core_time_variables(DEC_OP_TIME);
+			ddl_vidc_decode_reset_avg_time(ddl);
 			ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
 			ddl_vidc_decode_frame_run(ddl);
 			ret_status = false;
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index b3db9e1..08cd06c 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -788,6 +788,18 @@
 	return 0;
 }
 
+static int msm8930_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+	SNDRV_PCM_HW_PARAM_RATE);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
 static int msm8930_aux_pcm_get_gpios(void)
 {
 	int ret = 0;
@@ -1195,6 +1207,7 @@
 		.codec_dai_name = "msm-stub-rx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+		.be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
 	},
 	{
@@ -1206,6 +1219,7 @@
 		.codec_dai_name = "msm-stub-tx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+		.be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
 	},
 	/* AUX PCM Backend DAI Links */
 	{