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 */
{