Merge "usb: msm_otg: Fix bug with hvdcp connect and disconnect processing"
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index 749c594..1aca300 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -52,13 +52,15 @@
RGB Led is a tri-colored led, Red, Blue & Green.
Required properties for RGB led:
-- qcom,mode: mode the led should operate in, options "pwm" and "lpg"
-- qcom,pwm-channel: pwm channel the led will operate on
+- qcom,mode: mode the led should operate in, options "pwm" and "lpg". "manual" mode is not supported for RGB led.
Required properties for PWM mode only:
+- qcom,pwm-channel: pwm channel the led will operate on
- qcom,pwm-us: time the pwm device will modulate at (us)
Required properties for LPG mode only:
+- qcom,pwm-channel: pwm channel the led will operate on
+- qcom,pwm-us: time the pwm device will modulate at (us)
- qcom,duty-pcts: array of values for duty cycle to go through
- qcom,start-idx: starting point duty-pcts array
@@ -93,6 +95,7 @@
Required properties for LPG mode only:
- qcom,pwm-channel: pwm channel the led will operate on
+- qcom,pwm-us: time the pwm device will modulate at (us)
- qcom,duty-pcts: array of values for duty cycle to go through
- qcom,start-idx: starting point duty-pcts array
@@ -106,9 +109,7 @@
and the required rows are enabled by specifying values in the properties.
Required properties for keypad backlight:
-- qcom,mode: mode the led should operate in, options "pwm" and "lpg"
-- qcom,pwm-channel: pwm channel the led will operate on
-- qcom,pwm-us: time the pwm device will modulate at (us)
+- qcom,mode: mode the led should operate in, options "pwm" and "lpg". "manual" mode is not supported for keypad backlight.
- qcom,row-id: specify the id of the row. Supported values are 0 to 3.
Optional properties for keypad backlight:
@@ -118,9 +119,12 @@
- qcom,always-on: specify if the module has to be always on
Required properties for PWM mode only:
+- qcom,pwm-channel: pwm channel the led will operate on
- qcom,pwm-us: time the pwm device will modulate at (us)
Required properties for LPG mode only:
+- qcom,pwm-channel: pwm channel the led will operate on
+- qcom,pwm-us: time the pwm device will modulate at (us)
- qcom,duty-pcts: array of values for duty cycle to go through
- qcom,start-idx: starting point duty-pcts array
@@ -201,6 +205,7 @@
linux,name = "led:rgb_green";
qcom,mode = "lpg";
qcom,pwm-channel = <5>;
+ qcom,pwm-us = <1000>;
qcom,duty-ms = <20>;
qcom,start-idx = <1>;
qcom,idx-len = <10>;
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index 1fb5fd3..1c338f7 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012, 2014 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -454,37 +454,29 @@
/* Disable counter */
armv7_pmnc_disable_counter(idx);
- /*
- * Set event (if destined for PMNx counters)
- * We don't need to set the event if it's a cycle count
- */
- if (idx != ARMV7_IDX_CYCLE_COUNTER) {
- val = hwc->config_base;
- val &= KRAIT_EVENT_MASK;
+ val = hwc->config_base;
+ val &= KRAIT_EVENT_MASK;
- if (val < 0x40) {
- armv7_pmnc_write_evtsel(idx, hwc->config_base);
- } else {
- event = get_krait_evtinfo(val, &evtinfo);
+ /* set event for ARM-architected events, and filter for CC */
+ if ((val < 0x40) || (idx == ARMV7_IDX_CYCLE_COUNTER)) {
+ armv7_pmnc_write_evtsel(idx, hwc->config_base);
+ } else {
+ event = get_krait_evtinfo(val, &evtinfo);
- if (event == -EINVAL)
- goto krait_out;
+ if (event == -EINVAL)
+ goto krait_out;
- /* Restore Mode-exclusion bits */
- event |= (hwc->config_base & KRAIT_MODE_EXCL_MASK);
+ /* Restore Mode-exclusion bits */
+ event |= (hwc->config_base & KRAIT_MODE_EXCL_MASK);
- /*
- * Set event (if destined for PMNx counters)
- * We don't need to set the event if it's a cycle count
- */
- armv7_pmnc_write_evtsel(idx, event);
- val = 0x0;
- asm volatile("mcr p15, 0, %0, c9, c15, 0" : :
- "r" (val));
- val = evtinfo.group_setval;
- gr = evtinfo.groupcode;
- krait_evt_setup(gr, val, evtinfo.armv7_evt_type);
- }
+ /* Set event (if destined for PMNx counters) */
+ armv7_pmnc_write_evtsel(idx, event);
+ val = 0x0;
+ asm volatile("mcr p15, 0, %0, c9, c15, 0" : :
+ "r" (val));
+ val = evtinfo.group_setval;
+ gr = evtinfo.groupcode;
+ krait_evt_setup(gr, val, evtinfo.armv7_evt_type);
}
/* Enable interrupt for this counter */
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 7a7c008..e16bcb1 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3497,8 +3497,36 @@
"fda08400.qcom,csid"),
/* ISPIF clocks */
+
CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
- "fda0a000.qcom,ispif"),
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi0_phy_clk", camss_csi0phy_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi0_clk", camss_csi0_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c,
+ "fda0a000.qcom,ispif"),
+
+ CLK_LOOKUP("csi1_ahb_clk", camss_csi1_ahb_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi1_src_clk", csi1_clk_src.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi1_phy_clk", camss_csi1phy_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi1_clk", camss_csi1_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi1_pix_clk", camss_csi1pix_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi1_rdi_clk", camss_csi1rdi_clk.c,
+ "fda0a000.qcom,ispif"),
CLK_LOOKUP("camss_vfe_vfe_clk", camss_vfe_vfe0_clk.c,
"fda0a000.qcom,ispif"),
CLK_LOOKUP("camss_csi_vfe_clk", camss_csi_vfe0_clk.c,
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index c81720e..a5240cc 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -329,24 +329,40 @@
* before the CPU is brought up.
*/
case CPU_DEAD:
- case CPU_UP_CANCELED:
if (is_clk) {
clk_disable_unprepare(cpu_clk[cpu]);
clk_disable_unprepare(l2_clk);
update_l2_bw(NULL);
}
break;
+ case CPU_UP_CANCELED:
+ if (is_clk) {
+ clk_unprepare(cpu_clk[cpu]);
+ clk_unprepare(l2_clk);
+ update_l2_bw(NULL);
+ }
+ break;
case CPU_UP_PREPARE:
if (is_clk) {
- rc = clk_prepare_enable(l2_clk);
+ rc = clk_prepare(l2_clk);
if (rc < 0)
return NOTIFY_BAD;
- rc = clk_prepare_enable(cpu_clk[cpu]);
+ rc = clk_prepare(cpu_clk[cpu]);
if (rc < 0)
return NOTIFY_BAD;
update_l2_bw(&cpu);
}
break;
+ case CPU_STARTING:
+ if (is_clk) {
+ rc = clk_enable(l2_clk);
+ if (rc < 0)
+ return NOTIFY_BAD;
+ rc = clk_enable(cpu_clk[cpu]);
+ if (rc < 0)
+ return NOTIFY_BAD;
+ }
+ break;
default:
break;
}
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 00aedb6..c94fa0e 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -206,7 +206,7 @@
int check_notifier(int);
const char *get_name(int);
int get_tz_id(int);
-int ocmem_enable_sec_program(int);
+int ocmem_restore_sec_program(int);
int ocmem_enable_dump(enum ocmem_client, unsigned long, unsigned long);
int ocmem_disable_dump(enum ocmem_client, unsigned long, unsigned long);
int check_id(int);
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index 99e54b7..4a8cc39 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -788,6 +788,7 @@
struct device *dev = &pdev->dev;
struct clk *ocmem_core_clk = NULL;
struct clk *ocmem_iface_clk = NULL;
+ int rc;
if (!pdev->dev.of_node) {
dev_info(dev, "Missing Configuration in Device Tree\n");
@@ -830,10 +831,23 @@
platform_set_drvdata(pdev, ocmem_pdata);
+ rc = ocmem_enable_core_clock();
+ if (rc < 0)
+ goto core_clk_fail;
+
+ rc = ocmem_enable_iface_clock();
+ if (rc < 0)
+ goto iface_clk_fail;
+
/* Parameter to be updated based on TZ */
/* Allow the OCMEM CSR to be programmed */
- if (ocmem_enable_sec_program(OCMEM_SECURE_DEV_ID))
+ if (ocmem_restore_sec_program(OCMEM_SECURE_DEV_ID)) {
+ ocmem_disable_iface_clock();
+ ocmem_disable_core_clock();
return -EBUSY;
+ }
+ ocmem_disable_iface_clock();
+ ocmem_disable_core_clock();
if (ocmem_debugfs_init(pdev))
dev_err(dev, "ocmem: No debugfs node available\n");
@@ -860,6 +874,11 @@
dev_dbg(dev, "initialized successfully\n");
return 0;
+
+iface_clk_fail:
+ ocmem_disable_core_clock();
+core_clk_fail:
+ return rc;
}
static int __devexit msm_ocmem_remove(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index f753391..9c2afb9 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -583,7 +583,7 @@
return 0;
}
-int ocmem_enable_sec_program(int sec_id)
+int ocmem_restore_sec_program(int sec_id)
{
return 0;
}
@@ -702,7 +702,7 @@
return rc;
}
-int ocmem_enable_sec_program(int sec_id)
+int ocmem_restore_sec_program(int sec_id)
{
int rc, scm_ret = 0;
struct msm_scm_sec_cfg {
@@ -953,7 +953,6 @@
unsigned end_m = num_banks;
unsigned long region_offset = 0;
struct ocmem_hw_region *region;
- int rc = 0;
if (offset < 0)
return -EINVAL;
@@ -974,14 +973,6 @@
(region_end >= num_regions))
return -EINVAL;
- rc = ocmem_enable_core_clock();
-
- if (rc < 0) {
- pr_err("ocmem: Power transistion request for client %s (id: %d) failed\n",
- get_name(id), id);
- return rc;
- }
-
mutex_lock(®ion_ctrl_lock);
for (i = region_start; i <= region_end; i++) {
@@ -1035,11 +1026,10 @@
}
mutex_unlock(®ion_ctrl_lock);
- ocmem_disable_core_clock();
+
return 0;
invalid_transition:
mutex_unlock(®ion_ctrl_lock);
- ocmem_disable_core_clock();
pr_err("ocmem_core: Invalid state transition detected for %d\n", id);
pr_err("ocmem_core: Offset %lx Len %lx curr_state %x new_state %x\n",
offset, len, curr_state, new_state);
@@ -1122,9 +1112,37 @@
static int ocmem_power_show(struct seq_file *f, void *dummy)
{
+ int rc = 0;
+
+ rc = ocmem_enable_core_clock();
+
+ if (rc < 0)
+ goto core_clock_fail;
+
+ rc = ocmem_enable_iface_clock();
+
+ if (rc < 0)
+ goto iface_clock_fail;
+
+ rc = ocmem_restore_sec_program(OCMEM_SECURE_DEV_ID);
+ if (rc < 0) {
+ pr_err("ocmem: Failed to restore security programming\n");
+ goto restore_config_fail;
+ }
ocmem_power_show_sw_state(f, dummy);
ocmem_power_show_hw_state(f, dummy);
+
+ ocmem_disable_iface_clock();
+ ocmem_disable_core_clock();
+
return 0;
+
+restore_config_fail:
+ ocmem_disable_iface_clock();
+iface_clock_fail:
+ ocmem_disable_core_clock();
+core_clock_fail:
+ return -EINVAL;
}
static int ocmem_power_open(struct inode *inode, struct file *file)
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 8e25bb2..78279ed 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -634,17 +634,11 @@
{
int rc = 0;
- rc = ocmem_enable_core_clock();
+ rc = ocmem_restore_sec_program(OCMEM_SECURE_DEV_ID);
- if (rc < 0)
- goto core_clock_fail;
-
-
- if (is_iface_access(req->owner)) {
- rc = ocmem_enable_iface_clock();
-
- if (rc < 0)
- goto iface_clock_fail;
+ if (rc < 0) {
+ pr_err("ocmem: Failed to restore security programming\n");
+ goto lock_failed;
}
rc = ocmem_lock(req->owner, phys_to_offset(req->req_start), req->req_sz,
@@ -670,11 +664,6 @@
process_map_fail:
ocmem_unlock(req->owner, phys_to_offset(req->req_start), req->req_sz);
lock_failed:
- if (is_iface_access(req->owner))
- ocmem_disable_iface_clock();
-iface_clock_fail:
- ocmem_disable_core_clock();
-core_clock_fail:
pr_err("ocmem: Failed to map ocmem request\n");
return rc;
}
@@ -698,9 +687,6 @@
goto unlock_failed;
}
- if (is_iface_access(req->owner))
- ocmem_disable_iface_clock();
- ocmem_disable_core_clock();
pr_debug("ocmem: Unmapped request %p\n", req);
return 0;
@@ -1345,9 +1331,21 @@
if (rc < 0)
return -EINVAL;
+ rc = ocmem_enable_core_clock();
+
+ if (rc < 0)
+ goto core_clock_fail;
+
+ if (is_iface_access(req->owner)) {
+ rc = ocmem_enable_iface_clock();
+
+ if (rc < 0)
+ goto iface_clock_fail;
+ }
+
rc = process_map(req, req->req_start, req->req_end);
if (rc < 0)
- return -EINVAL;
+ goto map_error;
offset = phys_to_offset(req->req_start);
@@ -1366,7 +1364,14 @@
BUG();
}
return 0;
+
power_ctl_error:
+map_error:
+if (is_iface_access(req->owner))
+ ocmem_disable_iface_clock();
+iface_clock_fail:
+ ocmem_disable_core_clock();
+core_clock_fail:
return -EINVAL;
}
@@ -1536,6 +1541,10 @@
}
}
+ if (is_iface_access(req->owner))
+ ocmem_disable_iface_clock();
+ ocmem_disable_core_clock();
+
rc = do_free(req);
if (rc < 0) {
pr_err("ocmem: Failed to free %p\n", req);
@@ -1556,6 +1565,9 @@
pr_err("Failed to switch OFF memory macros\n");
goto free_fail;
}
+ if (is_iface_access(req->owner))
+ ocmem_disable_iface_clock();
+ ocmem_disable_core_clock();
}
/* free the allocation */
@@ -1658,6 +1670,10 @@
rc = process_unmap(req, req->req_start, req->req_end);
if (rc < 0)
return -EINVAL;
+
+ if (is_iface_access(req->owner))
+ ocmem_disable_iface_clock();
+ ocmem_disable_core_clock();
} else
return -EINVAL;
@@ -1768,6 +1784,9 @@
rc = process_unmap(req, req->req_start, req->req_end);
if (rc < 0)
goto shrink_fail;
+ if (is_iface_access(req->owner))
+ ocmem_disable_iface_clock();
+ ocmem_disable_core_clock();
}
rc = do_free(req);
if (rc < 0)
@@ -2254,6 +2273,17 @@
if (req->req_sz != 0) {
+ rc = ocmem_enable_core_clock();
+
+ if (rc < 0)
+ goto core_clock_fail;
+
+ if (is_iface_access(req->owner)) {
+ rc = ocmem_enable_iface_clock();
+
+ if (rc < 0)
+ goto iface_clock_fail;
+ }
rc = process_map(req, req->req_start, req->req_end);
if (rc < 0)
goto map_error;
@@ -2275,6 +2305,11 @@
map_error:
handle->req = NULL;
do_free(req);
+ if (is_iface_access(req->owner))
+ ocmem_disable_iface_clock();
+iface_clock_fail:
+ ocmem_disable_core_clock();
+core_clock_fail:
do_allocate_error:
ocmem_destroy_req(req);
return -EINVAL;
@@ -2303,6 +2338,17 @@
inc_ocmem_stat(zone_of(req), NR_ASYNC_ALLOCATIONS);
if (req->req_sz != 0) {
+ rc = ocmem_enable_core_clock();
+
+ if (rc < 0)
+ goto core_clock_fail;
+
+ if (is_iface_access(req->owner)) {
+ rc = ocmem_enable_iface_clock();
+
+ if (rc < 0)
+ goto iface_clock_fail;
+ }
rc = process_map(req, req->req_start, req->req_end);
if (rc < 0)
@@ -2333,6 +2379,11 @@
map_error:
handle->req = NULL;
do_free(req);
+ if (is_iface_access(req->owner))
+ ocmem_disable_iface_clock();
+iface_clock_fail:
+ ocmem_disable_core_clock();
+core_clock_fail:
do_allocate_error:
ocmem_destroy_req(req);
return -EINVAL;
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 3a87c78..c4f7d45 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -48,6 +48,7 @@
"23 msm: perf: Fix cpu id logic in tracectr notifier\n"
"24 msm: perf: tracectr: Initialize cnts after hotplug\n"
"25 Perf: Reset pmu after hotplug\n"
+ "26 msm: perf: set filter bits for cycle counter on krait\n"
;
static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 3d52735..947e229 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1519,8 +1519,25 @@
const struct mem_type *type)
{
pte_t *pte, *start_pte;
+ pmd_t *base_pmd;
- start_pte = early_alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
+ base_pmd = pmd_offset(
+ pud_offset(pgd_offset(&init_mm, addr), addr), addr);
+
+ if (pmd_none(*base_pmd) || pmd_bad(*base_pmd)) {
+ start_pte = early_alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
+#ifndef CONFIG_ARM_LPAE
+ /*
+ * Following is needed when new pte is allocated for pmd[1]
+ * cases, which may happen when base (start) address falls
+ * under pmd[1].
+ */
+ if (addr & SECTION_SIZE)
+ start_pte += pte_index(addr);
+#endif
+ } else {
+ start_pte = pte_offset_kernel(base_pmd, addr);
+ }
pte = start_pte;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index ba13ec1..93e932a 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1508,8 +1508,7 @@
return err;
}
if (pkt_type == CALLBACK_DATA_TYPE) {
- if (payload_size > driver->itemsize ||
- payload_size <= MIN_SIZ_ALLOW) {
+ if (payload_size > driver->itemsize) {
pr_err("diag: Dropping packet, invalid packet size. Current payload size %d\n",
payload_size);
driver->dropped_count++;
@@ -1541,6 +1540,11 @@
return ret;
}
/* The packet is for the remote processor */
+ if (payload_size <= MIN_SIZ_ALLOW) {
+ pr_err("diag: Integer underflow in %s, payload size: %d",
+ __func__, payload_size);
+ return -EBADMSG;
+ }
token_offset = 4;
payload_size -= 4;
buf += 4;
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 0659b77..0413472 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -1755,7 +1755,7 @@
return -EINVAL;
}
rc = pwm_lut_config(pwm_cfg->pwm_dev,
- PM_PWM_PERIOD_MIN, /* ignored by hardware */
+ pwm_cfg->pwm_period_us,
pwm_cfg->duty_cycles->duty_pcts,
pwm_cfg->lut_params);
if (rc < 0) {
@@ -2862,7 +2862,7 @@
else
return rc;
- if (pwm_cfg->mode == PWM_MODE) {
+ if (pwm_cfg->mode != MANUAL_MODE) {
rc = of_property_read_u32(node, "qcom,pwm-us", &val);
if (!rc)
pwm_cfg->pwm_period_us = val;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 4700469..805ff0a 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -147,13 +147,13 @@
uint32_t (*get_wm_mask) (uint32_t irq_status0, uint32_t irq_status1);
uint32_t (*get_comp_mask) (uint32_t irq_status0, uint32_t irq_status1);
uint32_t (*get_pingpong_status) (struct vfe_device *vfe_dev);
- long (*halt) (struct vfe_device *vfe_dev);
+ long (*halt) (struct vfe_device *vfe_dev, uint32_t blocking);
};
struct msm_vfe_core_ops {
void (*reg_update) (struct vfe_device *vfe_dev);
long (*reset_hw) (struct vfe_device *vfe_dev,
- enum msm_isp_reset_type reset_type);
+ enum msm_isp_reset_type reset_type, uint32_t blocking);
int (*init_hw) (struct vfe_device *vfe_dev);
void (*init_hw_reg) (struct vfe_device *vfe_dev);
void (*release_hw) (struct vfe_device *vfe_dev);
@@ -167,6 +167,12 @@
int (*get_platform_data) (struct vfe_device *vfe_dev);
void (*get_error_mask) (uint32_t *error_mask0, uint32_t *error_mask1);
void (*process_error_status) (struct vfe_device *vfe_dev);
+ void (*get_overflow_mask) (uint32_t *overflow_mask);
+ void (*get_irq_mask) (struct vfe_device *vfe_dev,
+ uint32_t *irq0_mask, uint32_t *irq1_mask);
+ void (*restore_irq_mask) (struct vfe_device *vfe_dev);
+ void (*get_halt_restart_mask) (uint32_t *irq0_mask,
+ uint32_t *irq1_mask);
};
struct msm_vfe_stats_ops {
int (*get_stats_idx) (enum msm_isp_stats_type stats_type);
@@ -298,6 +304,15 @@
uint32_t runtime_num_burst_capture;
uint8_t runtime_framedrop_update;
uint32_t runtime_output_format;
+ enum msm_vfe_frame_skip_pattern frame_skip_pattern;
+
+};
+
+enum msm_vfe_overflow_state {
+ NO_OVERFLOW,
+ OVERFLOW_DETECTED,
+ HALT_REQUESTED,
+ RESTART_REQUESTED,
};
struct msm_vfe_axi_composite_info {
@@ -314,6 +329,7 @@
uint32_t width;
long pixel_clock;
uint32_t input_format;/*V4L2 pix format with bayer pattern*/
+ uint32_t last_updt_frm_id;
};
enum msm_wm_ub_cfg_type {
@@ -393,6 +409,9 @@
#define MSM_VFE_TASKLETQ_SIZE 200
struct msm_vfe_error_info {
+ atomic_t overflow_state;
+ uint32_t overflow_recover_irq_mask0;
+ uint32_t overflow_recover_irq_mask1;
uint32_t error_mask0;
uint32_t error_mask1;
uint32_t violation_status;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index cf76131..ba1e58c 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -393,19 +393,25 @@
};
static long msm_vfe32_reset_hardware(struct vfe_device *vfe_dev ,
- enum msm_isp_reset_type reset_type)
+ enum msm_isp_reset_type reset_type, uint32_t blocking)
{
uint32_t rst_val;
+ long rc = 0;
if (reset_type >= ISP_RST_MAX) {
pr_err("%s: Error Invalid parameter\n", __func__);
reset_type = ISP_RST_HARD;
}
rst_val = msm_vfe32_reset_values[reset_type];
init_completion(&vfe_dev->reset_complete);
- msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0x4);
- return wait_for_completion_timeout(
- &vfe_dev->reset_complete, msecs_to_jiffies(50));
+ if (blocking) {
+ msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0x4);
+ rc = wait_for_completion_timeout(
+ &vfe_dev->reset_complete, msecs_to_jiffies(50));
+ } else {
+ msm_camera_io_w_mb(0x3EF, vfe_dev->vfe_base + 0x4);
+ }
+ return rc;
}
static void msm_vfe32_axi_reload_wm(
@@ -659,6 +665,7 @@
val &= 0xFFFFFF3F;
val = val | bus_en << 7 | vfe_en << 6;
msm_camera_io_w(val, vfe_dev->vfe_base + 0x1E4);
+ msm_camera_io_w_mb(0x4, vfe_dev->vfe_base + 0x1E0);
msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1E0);
vfe_dev->axi_data.src_info[VFE_PIX_0].active = 1;
} else if (update_state == DISABLE_CAMIF) {
@@ -891,12 +898,15 @@
VFE32_PING_PONG_BASE(wm_idx, pingpong_status));
}
-static long msm_vfe32_axi_halt(struct vfe_device *vfe_dev)
+static long msm_vfe32_axi_halt(struct vfe_device *vfe_dev,
+ uint32_t blocking)
{
uint32_t halt_mask;
- uint32_t axi_busy_flag = true;
-
+ uint32_t axi_busy_flag = false;
msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1D8);
+ if (blocking) {
+ axi_busy_flag = true;
+ }
while (axi_busy_flag) {
if (msm_camera_io_r(
vfe_dev->vfe_base + 0x1DC) & 0x1)
@@ -1067,6 +1077,33 @@
return (irq_status0 >> 13) & 0x7F;
}
+static void msm_vfe32_get_overflow_mask(uint32_t *overflow_mask)
+{
+ *overflow_mask = 0x002FFF7E;
+}
+
+static void msm_vfe32_get_irq_mask(struct vfe_device *vfe_dev,
+ uint32_t *irq0_mask, uint32_t *irq1_mask)
+{
+ *irq0_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x1C);
+ *irq1_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x20);
+}
+
+static void msm_vfe32_restore_irq_mask(struct vfe_device *vfe_dev)
+{
+ msm_camera_io_w(vfe_dev->error_info.overflow_recover_irq_mask0,
+ vfe_dev->vfe_base + 0x1C);
+ msm_camera_io_w(vfe_dev->error_info.overflow_recover_irq_mask1,
+ vfe_dev->vfe_base + 0x20);
+}
+
+static void msm_vfe32_get_halt_restart_mask(uint32_t *irq0_mask,
+ uint32_t *irq1_mask)
+{
+ *irq0_mask = 0x0;
+ *irq1_mask = 0x01800000;
+}
+
static uint32_t msm_vfe32_stats_get_comp_mask(uint32_t irq_status0,
uint32_t irq_status1)
{
@@ -1220,6 +1257,11 @@
.release_hw = msm_vfe32_release_hardware,
.get_platform_data = msm_vfe32_get_platform_data,
.get_error_mask = msm_vfe32_get_error_mask,
+ .get_overflow_mask = msm_vfe32_get_overflow_mask,
+ .get_irq_mask = msm_vfe32_get_irq_mask,
+ .restore_irq_mask = msm_vfe32_restore_irq_mask,
+ .get_halt_restart_mask =
+ msm_vfe32_get_halt_restart_mask,
.process_error_status = msm_vfe32_process_error_status,
},
.stats_ops = {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 04136d0..81e9c74 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -620,18 +620,24 @@
static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev ,
- enum msm_isp_reset_type reset_type)
+ enum msm_isp_reset_type reset_type, uint32_t blocking)
{
uint32_t rst_val;
+ long rc = 0;
if (reset_type >= ISP_RST_MAX) {
pr_err("%s: Error Invalid parameter\n", __func__);
reset_type = ISP_RST_HARD;
}
rst_val = msm_vfe40_reset_values[reset_type];
init_completion(&vfe_dev->reset_complete);
- msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0xC);
- return wait_for_completion_timeout(
- &vfe_dev->reset_complete, msecs_to_jiffies(50));
+ if (blocking) {
+ msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0xC);
+ rc = wait_for_completion_timeout(
+ &vfe_dev->reset_complete, msecs_to_jiffies(50));
+ } else {
+ msm_camera_io_w_mb(0x1EF, vfe_dev->vfe_base + 0xC);
+ }
+ return rc;
}
static void msm_vfe40_axi_reload_wm(
@@ -924,6 +930,7 @@
val &= 0xFFFFFF3F;
val = val | bus_en << 7 | vfe_en << 6;
msm_camera_io_w(val, vfe_dev->vfe_base + 0x2F8);
+ msm_camera_io_w_mb(0x4, vfe_dev->vfe_base + 0x2F4);
msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2F4);
vfe_dev->axi_data.src_info[VFE_PIX_0].active = 1;
} else if (update_state == DISABLE_CAMIF) {
@@ -1165,16 +1172,24 @@
VFE40_PING_PONG_BASE(wm_idx, pingpong_status));
}
-static long msm_vfe40_axi_halt(struct vfe_device *vfe_dev)
+static long msm_vfe40_axi_halt(struct vfe_device *vfe_dev,
+ uint32_t blocking)
{
- uint32_t halt_mask;
- halt_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x2C);
- halt_mask |= (1 << 8);
- msm_camera_io_w_mb(halt_mask, vfe_dev->vfe_base + 0x2C);
+ long rc = 0;
+ /* Keep only restart mask and halt mask*/
+ msm_camera_io_w(BIT(31), vfe_dev->vfe_base + 0x28);
+ msm_camera_io_w(BIT(8), vfe_dev->vfe_base + 0x2C);
+ /* Clear IRQ Status*/
+ msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x30);
+ msm_camera_io_w(0xFEFFFFFF, vfe_dev->vfe_base + 0x34);
init_completion(&vfe_dev->halt_complete);
msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2C0);
- return wait_for_completion_interruptible_timeout(
- &vfe_dev->halt_complete, msecs_to_jiffies(500));
+ if (blocking) {
+ atomic_set(&vfe_dev->error_info.overflow_state, NO_OVERFLOW);
+ rc = wait_for_completion_interruptible_timeout(
+ &vfe_dev->halt_complete, msecs_to_jiffies(500));
+ }
+ return rc;
}
static uint32_t msm_vfe40_get_wm_mask(
@@ -1183,6 +1198,33 @@
return (irq_status0 >> 8) & 0x7F;
}
+static void msm_vfe40_get_overflow_mask(uint32_t *overflow_mask)
+{
+ *overflow_mask = 0x00FFFE7E;
+}
+
+static void msm_vfe40_get_irq_mask(struct vfe_device *vfe_dev,
+ uint32_t *irq0_mask, uint32_t *irq1_mask)
+{
+ *irq0_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
+ *irq1_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x2C);
+}
+
+static void msm_vfe40_restore_irq_mask(struct vfe_device *vfe_dev)
+{
+ msm_camera_io_w(vfe_dev->error_info.overflow_recover_irq_mask0,
+ vfe_dev->vfe_base + 0x28);
+ msm_camera_io_w(vfe_dev->error_info.overflow_recover_irq_mask1,
+ vfe_dev->vfe_base + 0x2C);
+}
+
+static void msm_vfe40_get_halt_restart_mask(uint32_t *irq0_mask,
+ uint32_t *irq1_mask)
+{
+ *irq0_mask = BIT(31);
+ *irq1_mask = BIT(8);
+}
+
static uint32_t msm_vfe40_get_comp_mask(
uint32_t irq_status0, uint32_t irq_status1)
{
@@ -1519,6 +1561,11 @@
.release_hw = msm_vfe40_release_hardware,
.get_platform_data = msm_vfe40_get_platform_data,
.get_error_mask = msm_vfe40_get_error_mask,
+ .get_overflow_mask = msm_vfe40_get_overflow_mask,
+ .get_irq_mask = msm_vfe40_get_irq_mask,
+ .restore_irq_mask = msm_vfe40_restore_irq_mask,
+ .get_halt_restart_mask =
+ msm_vfe40_get_halt_restart_mask,
.process_error_status = msm_vfe40_process_error_status,
},
.stats_ops = {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 508bcec..4c3a3d5 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -20,6 +20,9 @@
#define HANDLE_TO_IDX(handle) (handle & 0xFF)
+#define MSM_ISP_MIN_AB 450000000
+#define MSM_ISP_MIN_IB 900000000
+
int msm_isp_axi_create_stream(
struct msm_vfe_axi_shared_data *axi_data,
struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
@@ -475,7 +478,8 @@
framedrop_period = msm_isp_get_framedrop_period(
stream_cfg_cmd->frame_skip_pattern);
-
+ stream_info->frame_skip_pattern =
+ stream_cfg_cmd->frame_skip_pattern;
if (stream_cfg_cmd->frame_skip_pattern == SKIP_ALL)
stream_info->framedrop_pattern = 0x0;
else
@@ -1069,6 +1073,8 @@
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
uint32_t total_pix_bandwidth = 0, total_rdi_bandwidth = 0;
uint32_t num_pix_streams = 0;
+ uint32_t num_rdi_streams = 0;
+ uint32_t total_streams = 0;
uint64_t total_bandwidth = 0;
for (i = 0; i < MAX_NUM_STREAM; i++) {
@@ -1080,6 +1086,7 @@
num_pix_streams++;
} else {
total_rdi_bandwidth += stream_info->bandwidth;
+ num_rdi_streams++;
}
}
}
@@ -1089,10 +1096,17 @@
((unsigned long)axi_data->src_info[VFE_PIX_0].
pixel_clock) * ISP_DEFAULT_FORMAT_FACTOR / ISP_Q2;
total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
-
+ total_streams = num_pix_streams + num_rdi_streams;
+ if (total_streams == 1) {
+ rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
+ (total_bandwidth - MSM_ISP_MIN_AB) , (total_bandwidth *
+ ISP_BUS_UTILIZATION_FACTOR / ISP_Q2 - MSM_ISP_MIN_IB));
+ }
+ else {
rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
total_bandwidth, total_bandwidth *
ISP_BUS_UTILIZATION_FACTOR / ISP_Q2);
+ }
if (rc < 0)
pr_err("%s: update failed\n", __func__);
@@ -1318,9 +1332,9 @@
if (cur_stream_cnt == 0) {
vfe_dev->ignore_error = 1;
if (camif_update == DISABLE_CAMIF_IMMEDIATELY) {
- vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
+ vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 1);
}
- vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, ISP_RST_HARD);
+ vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, ISP_RST_HARD, 1);
vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
vfe_dev->ignore_error = 0;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
index 7d282bd..2314300 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
@@ -37,6 +37,10 @@
struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd);
+void msm_isp_calculate_framedrop(
+ struct msm_vfe_axi_shared_data *axi_data,
+ struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
+
int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg);
int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg);
int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index cb46e9c..f44f026 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -631,6 +631,33 @@
}
break;
}
+ case VFE_HW_UPDATE_LOCK: {
+ uint32_t update_id =
+ vfe_dev->axi_data.src_info[VFE_PIX_0].last_updt_frm_id;
+ if (vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id != *cfg_data
+ || update_id == *cfg_data) {
+ pr_err("hw update lock failed,acquire id %u\n",
+ *cfg_data);
+ pr_err("hw update lock failed,current id %lu\n",
+ vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
+ pr_err("hw update lock failed,last id %u\n",
+ update_id);
+ return -EINVAL;
+ }
+ break;
+ }
+ case VFE_HW_UPDATE_UNLOCK: {
+ if (vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id
+ != *cfg_data) {
+ pr_err("hw update across frame boundary,begin id %u\n",
+ *cfg_data);
+ pr_err("hw update across frame boundary,end id %lu\n",
+ vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
+ vfe_dev->axi_data.src_info[VFE_PIX_0].last_updt_frm_id =
+ vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
+ }
+ break;
+ }
case VFE_READ: {
int i;
uint32_t *data_ptr = cfg_data +
@@ -720,7 +747,7 @@
}
for (i = 0; i < proc_cmd->num_cfg; i++)
- msm_isp_send_hw_cmd(vfe_dev, ®_cfg_cmd[i],
+ rc = msm_isp_send_hw_cmd(vfe_dev, ®_cfg_cmd[i],
cfg_data, proc_cmd->cmd_len);
if (copy_to_user(proc_cmd->cfg_data,
@@ -981,6 +1008,125 @@
vfe_dev->error_info.error_count++;
}
+static inline void msm_isp_process_overflow_irq(
+ struct vfe_device *vfe_dev,
+ uint32_t *irq_status0, uint32_t *irq_status1)
+{
+ uint32_t overflow_mask;
+ uint32_t halt_restart_mask0, halt_restart_mask1;
+ /*Mask out all other irqs if recovery is started*/
+ if (atomic_read(&vfe_dev->error_info.overflow_state) !=
+ NO_OVERFLOW) {
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ get_halt_restart_mask(&halt_restart_mask0,
+ &halt_restart_mask1);
+ *irq_status0 &= halt_restart_mask0;
+ *irq_status1 &= halt_restart_mask1;
+ return;
+ }
+
+ /*Check if any overflow bit is set*/
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ get_overflow_mask(&overflow_mask);
+ overflow_mask &= *irq_status1;
+ if (overflow_mask) {
+ pr_warning("%s: Bus overflow detected: 0x%x\n",
+ __func__, overflow_mask);
+ atomic_set(&vfe_dev->error_info.overflow_state,
+ OVERFLOW_DETECTED);
+ pr_warning("%s: Start bus overflow recovery\n", __func__);
+ /*Store current IRQ mask*/
+ vfe_dev->hw_info->vfe_ops.core_ops.get_irq_mask(vfe_dev,
+ &vfe_dev->error_info.overflow_recover_irq_mask0,
+ &vfe_dev->error_info.overflow_recover_irq_mask1);
+ /*Stop CAMIF Immediately*/
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ update_camif_state(vfe_dev, DISABLE_CAMIF_IMMEDIATELY);
+ /*Halt the hardware & Clear all other IRQ mask*/
+ vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 0);
+ /*Update overflow state*/
+ atomic_set(&vfe_dev->error_info.overflow_state, HALT_REQUESTED);
+ *irq_status0 = 0;
+ *irq_status1 = 0;
+ }
+}
+
+static inline void msm_isp_reset_burst_count(
+ struct vfe_device *vfe_dev)
+{
+ int i;
+ struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+ struct msm_vfe_axi_stream *stream_info;
+ struct msm_vfe_axi_stream_request_cmd framedrop_info;
+ for (i = 0; i < MAX_NUM_STREAM; i++) {
+ stream_info = &axi_data->stream_info[i];
+ if (stream_info->state != ACTIVE)
+ continue;
+ if (stream_info->stream_type == BURST_STREAM &&
+ stream_info->num_burst_capture != 0) {
+ framedrop_info.burst_count =
+ stream_info->num_burst_capture;
+ framedrop_info.frame_skip_pattern =
+ stream_info->frame_skip_pattern;
+ framedrop_info.init_frame_drop = 0;
+ msm_isp_calculate_framedrop(&vfe_dev->axi_data,
+ &framedrop_info);
+ }
+ }
+}
+
+static void msm_isp_process_overflow_recovery(
+ struct vfe_device *vfe_dev,
+ uint32_t irq_status0, uint32_t irq_status1)
+{
+ uint32_t halt_restart_mask0, halt_restart_mask1;
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ get_halt_restart_mask(&halt_restart_mask0,
+ &halt_restart_mask1);
+ irq_status0 &= halt_restart_mask0;
+ irq_status1 &= halt_restart_mask1;
+ if (irq_status0 == 0 && irq_status1 == 0)
+ return;
+
+ switch (atomic_read(&vfe_dev->error_info.overflow_state)) {
+ case HALT_REQUESTED: {
+ pr_err("%s: Halt done, Restart Pending\n", __func__);
+ /*Reset the hardware*/
+ vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev,
+ ISP_RST_SOFT, 0);
+ /*Update overflow state*/
+ atomic_set(&vfe_dev->error_info.overflow_state,
+ RESTART_REQUESTED);
+ }
+ break;
+ case RESTART_REQUESTED: {
+ pr_err("%s: Restart done, Resuming\n", __func__);
+ /*Reset the burst stream frame drop pattern, in the
+ *case where bus overflow happens during the burstshot,
+ *the framedrop pattern might be updated after reg update
+ *to skip all the frames after the burst shot. The burst shot
+ *might not be completed due to the overflow, so the framedrop
+ *pattern need to change back to the original settings in order
+ *to recovr from overflow.
+ */
+ msm_isp_reset_burst_count(vfe_dev);
+ vfe_dev->hw_info->vfe_ops.axi_ops.
+ reload_wm(vfe_dev, 0xFFFFFFFF);
+ vfe_dev->hw_info->vfe_ops.core_ops.restore_irq_mask(vfe_dev);
+ vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
+ memset(&vfe_dev->error_info, 0, sizeof(vfe_dev->error_info));
+ atomic_set(&vfe_dev->error_info.overflow_state, NO_OVERFLOW);
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ update_camif_state(vfe_dev, ENABLE_CAMIF);
+ }
+ break;
+ case NO_OVERFLOW:
+ case OVERFLOW_DETECTED:
+ default:
+ break;
+ }
+}
+
irqreturn_t msm_isp_process_irq(int irq_num, void *data)
{
unsigned long flags;
@@ -991,6 +1137,8 @@
vfe_dev->hw_info->vfe_ops.irq_ops.
read_irq_status(vfe_dev, &irq_status0, &irq_status1);
+ msm_isp_process_overflow_irq(vfe_dev,
+ &irq_status0, &irq_status1);
vfe_dev->hw_info->vfe_ops.core_ops.
get_error_mask(&error_mask0, &error_mask1);
error_mask0 &= irq_status0;
@@ -1055,6 +1203,13 @@
irq_status1 = queue_cmd->vfeInterruptStatus1;
ts = queue_cmd->ts;
spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
+ if (atomic_read(&vfe_dev->error_info.overflow_state) !=
+ NO_OVERFLOW) {
+ pr_err("There is Overflow, kicking up recovery !!!!");
+ msm_isp_process_overflow_recovery(vfe_dev,
+ irq_status0, irq_status1);
+ continue;
+ }
ISP_DBG("%s: status0: 0x%x status1: 0x%x\n",
__func__, irq_status0, irq_status1);
irq_ops->process_reset_irq(vfe_dev,
@@ -1105,7 +1260,10 @@
return -EBUSY;
}
- rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, ISP_RST_HARD);
+ memset(&vfe_dev->error_info, 0, sizeof(vfe_dev->error_info));
+ atomic_set(&vfe_dev->error_info.overflow_state, NO_OVERFLOW);
+ rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev,
+ ISP_RST_HARD, 1);
if (rc <= 0) {
pr_err("%s: reset timeout\n", __func__);
mutex_unlock(&vfe_dev->core_mutex);
@@ -1157,7 +1315,7 @@
return -ENODEV;
}
- rc = vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
+ rc = vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 1);
if (rc <= 0)
pr_err("%s: halt timeout rc=%ld\n", __func__, rc);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index a08fad7..8f99ff6 100755
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -64,6 +64,25 @@
false : true;
}
+static struct msm_cam_clk_info ispif_8626_reset_clk_info[] = {
+ {"ispif_ahb_clk", NO_SET_RATE},
+ {"camss_top_ahb_clk", NO_SET_RATE},
+ {"csi0_ahb_clk", NO_SET_RATE},
+ {"csi0_src_clk", NO_SET_RATE},
+ {"csi0_phy_clk", NO_SET_RATE},
+ {"csi0_clk", NO_SET_RATE},
+ {"csi0_pix_clk", NO_SET_RATE},
+ {"csi0_rdi_clk", NO_SET_RATE},
+ {"csi1_ahb_clk", NO_SET_RATE},
+ {"csi1_src_clk", NO_SET_RATE},
+ {"csi1_phy_clk", NO_SET_RATE},
+ {"csi1_clk", NO_SET_RATE},
+ {"csi1_pix_clk", NO_SET_RATE},
+ {"csi1_rdi_clk", NO_SET_RATE},
+ {"camss_vfe_vfe_clk", NO_SET_RATE},
+ {"camss_csi_vfe_clk", NO_SET_RATE},
+};
+
static struct msm_cam_clk_info ispif_8974_ahb_clk_info[] = {
{"ispif_ahb_clk", -1},
};
@@ -98,13 +117,26 @@
int rc = 0;
long timeout = 0;
struct clk *reset_clk[ARRAY_SIZE(ispif_8974_reset_clk_info)];
+ struct clk *reset_clk1[ARRAY_SIZE(ispif_8626_reset_clk_info)];
+ ispif->clk_idx = 0;
rc = msm_cam_clk_enable(&ispif->pdev->dev,
ispif_8974_reset_clk_info, reset_clk,
ARRAY_SIZE(ispif_8974_reset_clk_info), 1);
if (rc < 0) {
- pr_err("%s: cannot enable clock, error = %d",
- __func__, rc);
+ rc = msm_cam_clk_enable(&ispif->pdev->dev,
+ ispif_8626_reset_clk_info, reset_clk1,
+ ARRAY_SIZE(ispif_8626_reset_clk_info), 1);
+ if (rc < 0){
+ pr_err("%s: cannot enable clock, error = %d",
+ __func__, rc);
+ } else {
+ /* This is set if device is 8x26 */
+ ispif->clk_idx = 2;
+ }
+ } else {
+ /* This is set if device is 8974 */
+ ispif->clk_idx = 1;
}
init_completion(&ispif->reset_complete[VFE0]);
@@ -121,11 +153,19 @@
timeout = wait_for_completion_timeout(
&ispif->reset_complete[VFE0], msecs_to_jiffies(500));
CDBG("%s: VFE0 done\n", __func__);
+
if (timeout <= 0) {
pr_err("%s: VFE0 reset wait timeout\n", __func__);
- msm_cam_clk_enable(&ispif->pdev->dev,
+ rc = msm_cam_clk_enable(&ispif->pdev->dev,
ispif_8974_reset_clk_info, reset_clk,
ARRAY_SIZE(ispif_8974_reset_clk_info), 0);
+ if (rc < 0){
+ rc = msm_cam_clk_enable(&ispif->pdev->dev,
+ ispif_8626_reset_clk_info, reset_clk1,
+ ARRAY_SIZE(ispif_8626_reset_clk_info), 0);
+ if (rc < 0)
+ pr_err("%s: VFE0 reset wait timeout\n", __func__);
+ }
return -ETIMEDOUT;
}
@@ -143,13 +183,26 @@
}
}
- rc = msm_cam_clk_enable(&ispif->pdev->dev,
- ispif_8974_reset_clk_info, reset_clk,
- ARRAY_SIZE(ispif_8974_reset_clk_info), 0);
- if (rc < 0) {
- pr_err("%s: cannot disable clock, error = %d",
- __func__, rc);
+ if (ispif->clk_idx == 1){
+ rc = msm_cam_clk_enable(&ispif->pdev->dev,
+ ispif_8974_reset_clk_info, reset_clk,
+ ARRAY_SIZE(ispif_8974_reset_clk_info), 0);
+ if (rc < 0) {
+ pr_err("%s: cannot disable clock, error = %d",
+ __func__, rc);
+ }
}
+
+ if (ispif->clk_idx == 2){
+ rc = msm_cam_clk_enable(&ispif->pdev->dev,
+ ispif_8626_reset_clk_info, reset_clk1,
+ ARRAY_SIZE(ispif_8626_reset_clk_info), 0);
+ if (rc < 0) {
+ pr_err("%s: cannot disable clock, error = %d",
+ __func__, rc);
+ }
+ }
+
return rc;
}
@@ -941,11 +994,7 @@
goto error_ahb;
}
- if (of_device_is_compatible(ispif->pdev->dev.of_node,
- "qcom,ispif-v3.0")) {
- /* currently HW reset is implemented for 8974 only */
- msm_ispif_reset_hw(ispif);
- }
+ msm_ispif_reset_hw(ispif);
rc = msm_ispif_reset(ispif);
if (rc == 0) {
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
index 45e7354..10dbfb6 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
@@ -60,5 +60,6 @@
struct clk *ahb_clk;
struct completion reset_complete[VFE_MAX];
uint32_t hw_num_isps;
+ uint32_t clk_idx;
};
#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index 7805930..8e7dc2c 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -156,6 +156,7 @@
settings[i].i2c_operation);
break;
}
+ break;
}
case MSM_ACT_POLL: {
switch (settings[i].data_type) {
@@ -178,6 +179,7 @@
settings[i].i2c_operation);
break;
}
+ break;
}
}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index dbc7d5c..36bf643 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -698,11 +698,11 @@
struct mmc_context_info *context_info = &host->context_info;
bool pending_is_urgent = false;
bool is_urgent = false;
- int err;
+ int err, ret;
unsigned long flags;
while (1) {
- wait_io_event_interruptible(context_info->wait,
+ ret = wait_io_event_interruptible(context_info->wait,
(context_info->is_done_rcv ||
context_info->is_new_req ||
context_info->is_urgent));
@@ -755,7 +755,7 @@
err = MMC_BLK_NEW_REQUEST;
break; /* return err */
}
- } else {
+ } else if (context_info->is_urgent) {
/*
* The case when block layer sent next urgent
* notification before it receives end_io on
@@ -807,6 +807,11 @@
pending_is_urgent = true;
continue; /* wait for done/new/urgent event */
}
+ } else {
+ pr_warn("%s: mmc thread unblocked from waiting by signal, ret=%d\n",
+ mmc_hostname(host),
+ ret);
+ continue;
}
} /* while */
return err;
@@ -3234,7 +3239,8 @@
mmc_release_host(host);
mmc_rpm_release(host, &host->class_dev);
out:
- if (extend_wakelock)
+ /* only extend the wakelock, if suspend has not started yet */
+ if (extend_wakelock && !host->rescan_disable)
wake_lock_timeout(&host->detect_wake_lock, HZ / 2);
if (host->caps & MMC_CAP_NEEDS_POLL)
@@ -3619,16 +3625,15 @@
spin_unlock_irqrestore(&host->lock, flags);
break;
}
+
+ /* since its suspending anyway, disable rescan */
+ host->rescan_disable = 1;
spin_unlock_irqrestore(&host->lock, flags);
/* Wait for pending detect work to be completed */
if (!(host->caps & MMC_CAP_NEEDS_POLL))
flush_work(&host->detect.work);
- spin_lock_irqsave(&host->lock, flags);
- host->rescan_disable = 1;
- spin_unlock_irqrestore(&host->lock, flags);
-
/*
* In some cases, the detect work might be scheduled
* just before rescan_disable is set to true.
@@ -3636,6 +3641,13 @@
*/
cancel_delayed_work_sync(&host->detect);
+ /*
+ * It is possible that the wake-lock has been acquired, since
+ * its being suspended, release the wakelock
+ */
+ if (wake_lock_active(&host->detect_wake_lock))
+ wake_unlock(&host->detect_wake_lock);
+
if (!host->bus_ops || host->bus_ops->suspend)
break;
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 179632c..783f512 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1399,7 +1399,11 @@
*/
#ifdef CONFIG_MMC_PARANOID_SD_INIT
retries = 5;
- while (retries) {
+ /*
+ * Some bad cards may take a long time to init, give preference to
+ * suspend in those cases.
+ */
+ while (retries && !host->rescan_disable) {
err = mmc_sd_init_card(host, host->ocr, NULL);
if (err) {
retries--;
@@ -1417,6 +1421,9 @@
mmc_hostname(host), err);
goto err;
}
+
+ if (host->rescan_disable)
+ goto err;
#else
err = mmc_sd_init_card(host, host->ocr, NULL);
if (err)
@@ -1440,9 +1447,9 @@
mmc_claim_host(host);
err:
mmc_detach_bus(host);
-
- pr_err("%s: error %d whilst initialising SD card\n",
- mmc_hostname(host), err);
+ if (err)
+ pr_err("%s: error %d whilst initialising SD card: rescan: %d\n",
+ mmc_hostname(host), err, host->rescan_disable);
return err;
}
diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c
index 4713d29..c066acd 100644
--- a/drivers/net/wireless/wcnss/wcnss_vreg.c
+++ b/drivers/net/wireless/wcnss/wcnss_vreg.c
@@ -51,6 +51,8 @@
#define WCNSS_PMU_CFG_GC_BUS_MUX_SEL_TOP BIT(5)
#define WCNSS_PMU_CFG_IRIS_XO_CFG_STS BIT(6) /* 1: in progress, 0: done */
+#define WCNSS_PMU_CFG_IRIS_RESET BIT(7)
+#define WCNSS_PMU_CFG_IRIS_RESET_STS BIT(8) /* 1: in progress, 0: done */
#define WCNSS_PMU_CFG_IRIS_XO_READ BIT(9)
#define WCNSS_PMU_CFG_IRIS_XO_READ_STS BIT(10)
@@ -258,6 +260,19 @@
writel_relaxed(reg, pmu_conf_reg);
+ /* Reset IRIS */
+ reg |= WCNSS_PMU_CFG_IRIS_RESET;
+ writel_relaxed(reg, pmu_conf_reg);
+
+ /* Wait for PMU_CFG.iris_reg_reset_sts */
+ while (readl_relaxed(pmu_conf_reg) &
+ WCNSS_PMU_CFG_IRIS_RESET_STS)
+ cpu_relax();
+
+ /* Reset iris reset bit */
+ reg &= ~WCNSS_PMU_CFG_IRIS_RESET;
+ writel_relaxed(reg, pmu_conf_reg);
+
/* Start IRIS XO configuration */
reg |= WCNSS_PMU_CFG_IRIS_XO_CFG;
writel_relaxed(reg, pmu_conf_reg);
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index e03d5be..05264b4 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -129,10 +129,10 @@
#define WCNSS_TSTBUS_CTRL_WRFIFO (0x04 << 1)
#define WCNSS_TSTBUS_CTRL_RDFIFO (0x05 << 1)
#define WCNSS_TSTBUS_CTRL_CTRL (0x07 << 1)
-#define WCNSS_TSTBUS_CTRL_AXIM_CFG0 (0x00 << 6)
-#define WCNSS_TSTBUS_CTRL_AXIM_CFG1 (0x01 << 6)
-#define WCNSS_TSTBUS_CTRL_CTRL_CFG0 (0x00 << 12)
-#define WCNSS_TSTBUS_CTRL_CTRL_CFG1 (0x01 << 12)
+#define WCNSS_TSTBUS_CTRL_AXIM_CFG0 (0x00 << 8)
+#define WCNSS_TSTBUS_CTRL_AXIM_CFG1 (0x01 << 8)
+#define WCNSS_TSTBUS_CTRL_CTRL_CFG0 (0x00 << 28)
+#define WCNSS_TSTBUS_CTRL_CTRL_CFG1 (0x01 << 28)
#define MSM_PRONTO_CCPU_BASE 0xfb205050
#define CCU_PRONTO_INVALID_ADDR_OFFSET 0x08
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 0035349..b4c88cd 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -301,17 +301,9 @@
*/
ngd_slim_runtime_resume(dev->dev);
}
- if ((txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
- SLIM_MSG_MC_RECONFIGURE_NOW)) &&
- dev->state <= MSM_CTRL_IDLE) {
- msm_slim_disconnect_endp(dev, &dev->rx_msgq,
- &dev->use_rx_msgqs);
- msm_slim_disconnect_endp(dev, &dev->tx_msgq,
- &dev->use_tx_msgqs);
- return msm_slim_qmi_power_request(dev, false);
- }
+
else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
- return 0;
+ return -EPROTONOSUPPORT;
if (txn->mt == SLIM_MSG_MT_CORE &&
(txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
@@ -385,6 +377,7 @@
if (report_sat == false && dev->state != MSM_CTRL_AWAKE) {
SLIM_ERR(dev, "controller not ready\n");
mutex_unlock(&dev->tx_lock);
+ pm_runtime_set_suspended(dev->dev);
msm_slim_put_ctrl(dev);
return -EREMOTEIO;
}
@@ -1074,20 +1067,7 @@
ret = msm_slim_qmi_init(dev, false);
/* controller state should be in sync with framework state */
if (!ret) {
- ret = slim_ctrl_clk_pause(&dev->ctrl, false,
- SLIM_CLK_UNSPECIFIED);
complete(&dev->qmi.qmi_comp);
- /*
- * Power-up won't be called if clock pause failed.
- * This can happen if ADSP SSR happened when audio
- * session is in progress. Framework will think that
- * clock pause failed so no need to wakeup controller.
- * Call power-up explicitly in that case, since slimbus
- * HW needs to be powered-on to be in sync with
- * framework state
- */
- if (ret)
- ngd_slim_power_up(dev, false);
if (!pm_runtime_enabled(dev->dev) ||
!pm_runtime_suspended(dev->dev))
ngd_slim_runtime_resume(dev->dev);
@@ -1105,10 +1085,25 @@
return ret;
}
-static int ngd_clk_pause_wakeup(struct slim_controller *ctrl)
+static int ngd_slim_power_down(struct msm_slim_ctrl *dev)
{
- struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
- return ngd_slim_power_up(dev, false);
+ int i;
+ struct slim_controller *ctrl = &dev->ctrl;
+ mutex_lock(&ctrl->m_ctrl);
+ /* Pending response for a message */
+ for (i = 0; i < ctrl->last_tid; i++) {
+ if (ctrl->txnt[i]) {
+ SLIM_INFO(dev, "NGD down:txn-rsp for %d pending", i);
+ mutex_unlock(&ctrl->m_ctrl);
+ return -EBUSY;
+ }
+ }
+ mutex_unlock(&ctrl->m_ctrl);
+ msm_slim_disconnect_endp(dev, &dev->rx_msgq,
+ &dev->use_rx_msgqs);
+ msm_slim_disconnect_endp(dev, &dev->tx_msgq,
+ &dev->use_tx_msgqs);
+ return msm_slim_qmi_power_request(dev, false);
}
static int ngd_slim_rx_msgq_thread(void *data)
@@ -1365,7 +1360,7 @@
dev->ctrl.allocbw = ngd_allocbw;
dev->ctrl.xfer_msg = ngd_xfer_msg;
dev->ctrl.xfer_user_msg = ngd_user_msg;
- dev->ctrl.wakeup = ngd_clk_pause_wakeup;
+ dev->ctrl.wakeup = NULL;
dev->ctrl.alloc_port = msm_alloc_port;
dev->ctrl.dealloc_port = msm_dealloc_port;
dev->ctrl.port_xfer = msm_slim_port_xfer;
@@ -1528,9 +1523,9 @@
struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
int ret = 0;
if (dev->state >= MSM_CTRL_ASLEEP)
- ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
+ ret = ngd_slim_power_up(dev, false);
if (ret) {
- /* Did SSR cause this clock pause failure */
+ /* Did SSR cause this power up failure */
if (dev->state != MSM_CTRL_DOWN)
dev->state = MSM_CTRL_ASLEEP;
else
@@ -1548,10 +1543,10 @@
struct platform_device *pdev = to_platform_device(device);
struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
int ret = 0;
- ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
+ ret = ngd_slim_power_down(dev);
if (ret) {
if (ret != -EBUSY)
- SLIM_INFO(dev, "clk pause not entered:%d\n", ret);
+ SLIM_INFO(dev, "slim resource not idle:%d\n", ret);
dev->state = MSM_CTRL_AWAKE;
} else {
dev->state = MSM_CTRL_ASLEEP;
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 1e17205..6ca3c0d 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -298,6 +298,7 @@
u32 hist_cnt_time;
u32 frame_cnt;
struct completion comp;
+ struct completion first_kick;
u32 data[HIST_V_SIZE];
struct mutex hist_mutex;
spinlock_t hist_lock;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 6b497bb..0c6eb2a 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -81,6 +81,8 @@
#define MDSS_BLOCK_DISP_NUM (MDP_BLOCK_MAX - MDP_LOGICAL_BLOCK_DISP_0)
#define HIST_WAIT_TIMEOUT(frame) ((75 * HZ * (frame)) / 1000)
+#define HIST_KICKOFF_WAIT_FRACTION 4
+
/* hist collect state */
enum {
HIST_UNKNOWN,
@@ -1351,6 +1353,7 @@
/* Kick off collection */
writel_relaxed(1, base + kick_base);
hist_info->col_state = HIST_START;
+ complete(&hist_info->first_kick);
}
}
spin_unlock_irqrestore(&hist_info->hist_lock, flag);
@@ -1788,6 +1791,8 @@
&mdss_pp_res->dspp_hist[i].hist_lock);
init_completion(
&mdss_pp_res->dspp_hist[i].comp);
+ init_completion(
+ &mdss_pp_res->dspp_hist[i].first_kick);
}
}
}
@@ -1797,6 +1802,7 @@
mutex_init(&vig[i].pp_res.hist.hist_mutex);
spin_lock_init(&vig[i].pp_res.hist.hist_lock);
init_completion(&vig[i].pp_res.hist.comp);
+ init_completion(&vig[i].pp_res.hist.first_kick);
}
if (!mdata->pp_bus_hdl) {
pp_bus_pdata = &mdp_pp_bus_scale_table;
@@ -3006,6 +3012,7 @@
spin_unlock_irqrestore(&hist_info->hist_lock, flag);
hist_info->frame_cnt = req->frame_cnt;
INIT_COMPLETION(hist_info->comp);
+ INIT_COMPLETION(hist_info->first_kick);
hist_info->hist_cnt_read = 0;
hist_info->hist_cnt_sent = 0;
hist_info->hist_cnt_time = 0;
@@ -3131,6 +3138,7 @@
spin_unlock_irqrestore(&hist_info->hist_lock, flag);
mdss_mdp_hist_intr_req(&mdata->hist_intr, done_bit, false);
complete_all(&hist_info->comp);
+ complete_all(&hist_info->first_kick);
writel_relaxed(BIT(1), ctl_base);/* cancel */
ret = 0;
exit:
@@ -3363,7 +3371,7 @@
struct pp_hist_col_info *hist_info,
char __iomem *ctl_base, u32 expect_sum)
{
- int wait_ret, ret = 0;
+ int kick_ret, wait_ret, ret = 0;
u32 timeout, sum;
char __iomem *v_base;
unsigned long flag;
@@ -3389,12 +3397,26 @@
pipe = container_of(res, struct mdss_mdp_pipe, pp_res);
pipe->params_changed++;
}
- wait_ret = wait_for_completion_killable_timeout(
+ kick_ret = wait_for_completion_killable_timeout(
+ &(hist_info->first_kick), timeout /
+ HIST_KICKOFF_WAIT_FRACTION);
+ if (kick_ret != 0)
+ wait_ret = wait_for_completion_killable_timeout(
&(hist_info->comp), timeout);
mutex_lock(&hist_info->hist_mutex);
spin_lock_irqsave(&hist_info->hist_lock, flag);
- if (wait_ret == 0) {
+ if (kick_ret == 0) {
+ ret = -ENODATA;
+ pr_debug("histogram kickoff not done yet");
+ spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+ goto hist_collect_exit;
+ } else if (kick_ret < 0) {
+ ret = -EINTR;
+ pr_debug("histogram first kickoff interrupted");
+ spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+ goto hist_collect_exit;
+ } else if (wait_ret == 0) {
ret = -ETIMEDOUT;
pr_debug("bin collection timedout, state %d",
hist_info->col_state);
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 85be7c3..a8e792b 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -133,6 +133,7 @@
u16 grph; /* slimbus group handle */
unsigned long ch_mask;
wait_queue_head_t dai_wait;
+ bool bus_down_in_recovery;
};
#define WCD9XXX_CH(xport, xshift) \
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 3828221..30e7d06 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -240,6 +240,8 @@
VFE_READ_DMI_64BIT,
GET_SOC_HW_VER,
GET_MAX_CLK_RATE,
+ VFE_HW_UPDATE_LOCK,
+ VFE_HW_UPDATE_UNLOCK,
};
struct msm_vfe_cfg_cmd2 {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 2a89d01..61d82fb 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -374,7 +374,7 @@
#endif
}
-static int unix_release_sock(struct sock *sk, int embrion)
+static void unix_release_sock(struct sock *sk, int embrion)
{
struct unix_sock *u = unix_sk(sk);
struct path path;
@@ -443,8 +443,6 @@
if (unix_tot_inflight)
unix_gc(); /* Garbage collect fds */
-
- return 0;
}
static void init_peercred(struct sock *sk)
@@ -694,9 +692,10 @@
if (!sk)
return 0;
+ unix_release_sock(sk, 0);
sock->sk = NULL;
- return unix_release_sock(sk, 0);
+ return 0;
}
static int unix_autobind(struct socket *sock)
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index 9cf37b4..5223070 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -84,7 +84,7 @@
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- int rv;
+ int rv = 0;
struct msm_hdmi_audio_codec_rx_data *codec_data =
dev_get_drvdata(dai->codec->dev);
@@ -92,7 +92,13 @@
codec_data->hdmi_core_pdev, 1);
if (IS_ERR_VALUE(rv)) {
dev_err(dai->dev,
- "%s() HDMI core is not ready\n", __func__);
+ "%s() HDMI core is not ready (rv = %d)\n",
+ __func__, rv);
+ } else if (!rv) {
+ dev_err(dai->dev,
+ "%s() HDMI cable is not connected (ret val = %d)\n",
+ __func__, rv);
+ rv = -EAGAIN;
}
return rv;
@@ -116,8 +122,14 @@
codec_data->hdmi_core_pdev, 1);
if (IS_ERR_VALUE(rv)) {
dev_err(dai->dev,
- "%s() HDMI core is not ready\n", __func__);
+ "%s() HDMI core is not ready (rv = %d)\n",
+ __func__, rv);
return rv;
+ } else if (!rv) {
+ dev_err(dai->dev,
+ "%s() HDMI cable is not connected (rv = %d)\n",
+ __func__, rv);
+ return -EAGAIN;
}
switch (num_channels) {
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 61a0682..38d7901 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -4154,6 +4154,7 @@
switch (event) {
case SND_SOC_DAPM_POST_PMU:
+ dai->bus_down_in_recovery = false;
(void) tapan_codec_enable_slim_chmask(dai, true);
ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
dai->rate, dai->bit_width,
@@ -4162,7 +4163,8 @@
case SND_SOC_DAPM_POST_PMD:
ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
dai->grph);
- ret = tapan_codec_enable_slim_chmask(dai, false);
+ if (!dai->bus_down_in_recovery)
+ ret = tapan_codec_enable_slim_chmask(dai, false);
if (ret < 0) {
ret = wcd9xxx_disconnect_port(core,
&dai->wcd9xxx_ch_list,
@@ -4177,6 +4179,7 @@
pm_runtime_put(core->dev->parent);
dev_dbg(codec->dev, "%s: unvote requested", __func__);
}
+ dai->bus_down_in_recovery = false;
break;
}
return ret;
@@ -4208,6 +4211,7 @@
dai = &tapan_p->dai[w->shift];
switch (event) {
case SND_SOC_DAPM_POST_PMU:
+ dai->bus_down_in_recovery = false;
(void) tapan_codec_enable_slim_chmask(dai, true);
ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
dai->rate, dai->bit_width,
@@ -4216,7 +4220,8 @@
case SND_SOC_DAPM_POST_PMD:
ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
dai->grph);
- ret = tapan_codec_enable_slim_chmask(dai, false);
+ if (!dai->bus_down_in_recovery)
+ ret = tapan_codec_enable_slim_chmask(dai, false);
if (ret < 0) {
ret = wcd9xxx_disconnect_port(core,
&dai->wcd9xxx_ch_list,
@@ -4231,6 +4236,7 @@
pm_runtime_put(core->dev->parent);
dev_dbg(codec->dev, "%s: unvote requested", __func__);
}
+ dai->bus_down_in_recovery = false;
break;
}
return ret;
@@ -5732,6 +5738,7 @@
int rco_clk_rate;
struct snd_soc_codec *codec;
struct tapan_priv *tapan;
+ int count;
codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
tapan = snd_soc_codec_get_drvdata(codec);
@@ -5788,6 +5795,9 @@
tapan->machine_codec_event_cb(codec, WCD9XXX_CODEC_EVENT_CODEC_UP);
+ for (count = 0; count < NUM_CODEC_DAIS; count++)
+ tapan->dai[count].bus_down_in_recovery = true;
+
mutex_unlock(&codec->mutex);
return ret;
}
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index d749715..4c5d327 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -5144,6 +5144,7 @@
switch (event) {
case SND_SOC_DAPM_POST_PMU:
+ dai->bus_down_in_recovery = false;
taiko_codec_enable_int_port(dai, codec);
(void) taiko_codec_enable_slim_chmask(dai, true);
ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
@@ -5153,7 +5154,9 @@
case SND_SOC_DAPM_POST_PMD:
ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
dai->grph);
- ret = taiko_codec_enable_slim_chmask(dai, false);
+ if (!dai->bus_down_in_recovery)
+ ret = taiko_codec_enable_slim_chmask(dai, false);
+
if (ret < 0) {
ret = wcd9xxx_disconnect_port(core,
&dai->wcd9xxx_ch_list,
@@ -5161,6 +5164,7 @@
pr_debug("%s: Disconnect RX port, ret = %d\n",
__func__, ret);
}
+ dai->bus_down_in_recovery = false;
break;
}
return ret;
@@ -5210,6 +5214,7 @@
snd_soc_update_bits(codec,
TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0xC, 0xC);
taiko_codec_enable_int_port(dai, codec);
+ dai->bus_down_in_recovery = false;
(void) taiko_codec_enable_slim_chmask(dai, true);
ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
dai->rate, dai->bit_width,
@@ -5226,6 +5231,8 @@
/*Disable V&I sensing*/
snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
0x88, 0x00);
+
+ dai->bus_down_in_recovery = false;
break;
}
out_vi:
@@ -5255,9 +5262,11 @@
__func__, w->name, event, w->shift);
dai = &taiko_p->dai[w->shift];
+
switch (event) {
case SND_SOC_DAPM_POST_PMU:
taiko_codec_enable_int_port(dai, codec);
+ dai->bus_down_in_recovery = false;
(void) taiko_codec_enable_slim_chmask(dai, true);
ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
dai->rate, dai->bit_width,
@@ -5266,7 +5275,9 @@
case SND_SOC_DAPM_POST_PMD:
ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
dai->grph);
- ret = taiko_codec_enable_slim_chmask(dai, false);
+ if (!dai->bus_down_in_recovery)
+ ret = taiko_codec_enable_slim_chmask(dai, false);
+
if (ret < 0) {
ret = wcd9xxx_disconnect_port(core,
&dai->wcd9xxx_ch_list,
@@ -5274,6 +5285,8 @@
pr_debug("%s: Disconnect RX port, ret = %d\n",
__func__, ret);
}
+
+ dai->bus_down_in_recovery = false;
break;
}
return ret;
@@ -6810,6 +6823,7 @@
struct snd_soc_codec *codec;
struct taiko_priv *taiko;
int rco_clk_rate;
+ int count;
codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
taiko = snd_soc_codec_get_drvdata(codec);
@@ -6866,6 +6880,9 @@
if (ret)
pr_err("%s: Failed to setup irq: %d\n", __func__, ret);
+ for (count = 0; count < NUM_CODEC_DAIS; count++)
+ taiko->dai[count].bus_down_in_recovery = true;
+
mutex_unlock(&codec->mutex);
return ret;
}
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index d405667..8a71891 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -884,7 +884,8 @@
0, WCD9XXX_JACK_MASK);
mbhc->hph_status &= ~(SND_JACK_HEADSET |
SND_JACK_LINEOUT |
- SND_JACK_ANC_HEADPHONE);
+ SND_JACK_ANC_HEADPHONE |
+ SND_JACK_UNSUPPORTED);
}
/* Report insertion */
@@ -3050,11 +3051,14 @@
if (!mbhc->mbhc_cfg->detect_extn_cable &&
retry == NUM_ATTEMPTS_TO_REPORT &&
mbhc->current_plug == PLUG_TYPE_NONE) {
+ WCD9XXX_BCL_LOCK(mbhc->resmgr);
wcd9xxx_report_plug(mbhc, 1,
SND_JACK_HEADPHONE);
+ WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
}
} else if (plug_type == PLUG_TYPE_HEADPHONE) {
pr_debug("Good headphone detected, continue polling\n");
+ WCD9XXX_BCL_LOCK(mbhc->resmgr);
if (mbhc->mbhc_cfg->detect_extn_cable) {
if (mbhc->current_plug != plug_type)
wcd9xxx_report_plug(mbhc, 1,
@@ -3063,9 +3067,11 @@
wcd9xxx_report_plug(mbhc, 1,
SND_JACK_HEADPHONE);
}
+ WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
} else if (plug_type == PLUG_TYPE_HIGH_HPH) {
pr_debug("%s: High HPH detected, continue polling\n",
__func__);
+ WCD9XXX_BCL_LOCK(mbhc->resmgr);
if (mbhc->mbhc_cfg->detect_extn_cable) {
if (mbhc->current_plug != plug_type)
wcd9xxx_report_plug(mbhc, 1,
@@ -3074,6 +3080,7 @@
wcd9xxx_report_plug(mbhc, 1,
SND_JACK_HEADPHONE);
}
+ WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
} else {
if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
pt_gnd_mic_swap_cnt++;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 9c01a08..8aa1e35 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -46,6 +46,7 @@
#define BTSCO_RATE_16KHZ 16000
static int slim0_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
+static int slim0_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
static int hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
#define SAMPLING_RATE_48KHZ 48000
@@ -1318,7 +1319,7 @@
pr_debug("%s()\n", __func__);
param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
- slim0_rx_bit_format);
+ slim0_tx_bit_format);
rate->min = rate->max = 48000;
channels->min = channels->max = msm_slim_0_tx_ch;
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index cdfd042..aa4d88d 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -545,12 +545,6 @@
int dir = IN, ret = 0;
struct audio_client *ac = prtd->audio_client;
uint32_t stream_index;
- struct asm_softpause_params softpause = {
- .enable = SOFT_PAUSE_ENABLE,
- .period = SOFT_PAUSE_PERIOD,
- .step = SOFT_PAUSE_STEP,
- .rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
- };
struct asm_softvolume_params softvol = {
.period = SOFT_VOLUME_PERIOD,
.step = SOFT_VOLUME_STEP,
@@ -584,11 +578,6 @@
if (ret < 0)
pr_err("%s : Set Volume failed : %d", __func__, ret);
- ret = q6asm_set_softpause(ac, &softpause);
- if (ret < 0)
- pr_err("%s: Send SoftPause Param failed ret=%d\n",
- __func__, ret);
-
ret = q6asm_set_softvolume(ac, &softvol);
if (ret < 0)
pr_err("%s: Send SoftVolume Param failed ret=%d\n",