bool wcd9xxx_spmi_lock_sleep()
{
	/*
	 * wcd9xxx_spmi_{lock/unlock}_sleep will be called by wcd9xxx_spmi_irq_thread
	 * and its subroutines only motly.
	 * but btn0_lpress_fn is not wcd9xxx_spmi_irq_thread's subroutine and
	 * It can race with wcd9xxx_spmi_irq_thread.
	 * So need to embrace wlock_holders with mutex.
	 */
	mutex_lock(&map.pm_lock);
	if (map.wlock_holders++ == 0) {
		pr_debug("%s: holding wake lock\n", __func__);
		pm_qos_update_request(&map.pm_qos_req,
				      msm_cpuidle_get_deep_idle_latency());
		#ifdef VENDOR_EDIT
		//[email protected], 2015/03/19, Add for Qcom patch,
		//Headset sometime not detected when phone is sleep
		pm_stay_awake(&map.spmi[0]->dev);
		#endif /* VENDOR_EDIT */
	}
	mutex_unlock(&map.pm_lock);
	pr_debug("%s: wake lock counter %d\n", __func__,
			map.wlock_holders);
	pr_debug("%s: map.pm_state = %d\n", __func__, map.pm_state);

	if (!wait_event_timeout(map.pm_wq,
				((wcd9xxx_spmi_pm_cmpxchg(
					WCD9XXX_PM_SLEEPABLE,
					WCD9XXX_PM_AWAKE)) ==
					WCD9XXX_PM_SLEEPABLE ||
					(wcd9xxx_spmi_pm_cmpxchg(
						 WCD9XXX_PM_SLEEPABLE,
						 WCD9XXX_PM_AWAKE) ==
						 WCD9XXX_PM_AWAKE)),
					msecs_to_jiffies(
					WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
		pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
			__func__,
			WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, map.pm_state,
			map.wlock_holders);
		wcd9xxx_spmi_unlock_sleep();
		return false;
	}
	wake_up_all(&map.pm_wq);
	pr_debug("%s: leaving pm_state = %d\n", __func__, map.pm_state);
	return true;
}
Exemplo n.º 2
0
bool wcd9xxx_spmi_lock_sleep()
{
	/*
	 * wcd9xxx_spmi_{lock/unlock}_sleep will be called by
	 * wcd9xxx_spmi_irq_thread
	 * and its subroutines only motly.
	 * but btn0_lpress_fn is not wcd9xxx_spmi_irq_thread's subroutine and
	 * It can race with wcd9xxx_spmi_irq_thread.
	 * So need to embrace wlock_holders with mutex.
	 */
	pr_info("%s, wlock_holders=%d\n", __func__, map.wlock_holders);
	mutex_lock(&map.pm_lock);
	if (map.wlock_holders++ == 0) {
		pr_info("%s: holding wake lock\n", __func__);
		pm_qos_update_request(&map.pm_qos_req,
				      msm_cpuidle_get_deep_idle_latency());
		pm_stay_awake(&map.spmi[0]->dev);
	}
	mutex_unlock(&map.pm_lock);
	pr_info("%s: wake lock counter %d\n", __func__,
			map.wlock_holders);
	pr_info("%s: map.pm_state = %d\n", __func__, map.pm_state);

	if (!wait_event_timeout(map.pm_wq,
				((wcd9xxx_spmi_pm_cmpxchg(
					WCD9XXX_PM_SLEEPABLE,
					WCD9XXX_PM_AWAKE)) ==
					WCD9XXX_PM_SLEEPABLE ||
					(wcd9xxx_spmi_pm_cmpxchg(
						 WCD9XXX_PM_SLEEPABLE,
						 WCD9XXX_PM_AWAKE) ==
						 WCD9XXX_PM_AWAKE)),
					msecs_to_jiffies(
					WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
		pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
			__func__,
			WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, map.pm_state,
			map.wlock_holders);
		wcd9xxx_spmi_unlock_sleep();
		return false;
	}
	wake_up_all(&map.pm_wq);
	pr_debug("%s: leaving pm_state = %d\n", __func__, map.pm_state);
	return true;
}
Exemplo n.º 3
0
bool wcd9xxx_spmi_lock_sleep()
{
	/*
	 * wcd9xxx_spmi_{lock/unlock}_sleep will be called by wcd9xxx_spmi_irq_thread
	 * and its subroutines only motly.
	 * but btn0_lpress_fn is not wcd9xxx_spmi_irq_thread's subroutine and
	 * It can race with wcd9xxx_spmi_irq_thread.
	 * So need to embrace wlock_holders with mutex.
	 *
	 * If system didn't resume, we can simply return false so codec driver's
	 * IRQ handler can return without handling IRQ.
	 * As interrupt line is still active, codec will have another IRQ to
	 * retry shortly.
	 */
	mutex_lock(&map.pm_lock);
	if (map.wlock_holders++ == 0) {
		pr_debug("%s: holding wake lock\n", __func__);
		pm_qos_update_request(&map.pm_qos_req,
				      msm_cpuidle_get_deep_idle_latency());
	}
	mutex_unlock(&map.pm_lock);
	pr_debug("%s: wake lock counter %d\n", __func__,
			map.wlock_holders);

	if (!wait_event_timeout(map.pm_wq,
				((wcd9xxx_spmi_pm_cmpxchg(
					WCD9XXX_PM_SLEEPABLE,
					WCD9XXX_PM_AWAKE)) ==
					WCD9XXX_PM_SLEEPABLE ||
					(wcd9xxx_spmi_pm_cmpxchg(
						 WCD9XXX_PM_SLEEPABLE,
						 WCD9XXX_PM_AWAKE) ==
						 WCD9XXX_PM_AWAKE)),
					msecs_to_jiffies(
					WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
		pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
			__func__,
			WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, map.pm_state,
			map.wlock_holders);
		wcd9xxx_spmi_unlock_sleep();
		return false;
	}
	wake_up_all(&map.pm_wq);
	return true;
}
Exemplo n.º 4
0
static irqreturn_t wcd9xxx_spmi_irq_handler(int linux_irq, void *data)
{
	int irq, i, j;
	unsigned long status[NUM_IRQ_REGS] = {0};

	printk("%s\n", __func__);
	if (unlikely(wcd9xxx_spmi_lock_sleep() == false)) {
		pr_err("Failed to hold suspend\n");
		return IRQ_NONE;
	}

	irq = get_irq_bit(linux_irq);
	if (irq == MAX_NUM_IRQS)
		return IRQ_HANDLED;

	status[BIT_BYTE(irq)] |= BYTE_BIT_MASK(irq);
	for (i = 0; i < NUM_IRQ_REGS; i++) {
		status[i] |= snd_soc_read(map.codec,
				BIT_BYTE(irq) * 0x100 +
			MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS);
		status[i] &= ~map.mask[i];
	}
	for (i = 0; i < MAX_NUM_IRQS; i++) {
		j = get_order_irq(i);
		if ((status[BIT_BYTE(j)] & BYTE_BIT_MASK(j)) &&
			((map.handled[BIT_BYTE(j)] &
			BYTE_BIT_MASK(j)) == 0)) {
			map.handler[j](irq, data);
			map.handled[BIT_BYTE(j)] |=
					BYTE_BIT_MASK(j);
		}
	}
	map.handled[BIT_BYTE(irq)] &= ~BYTE_BIT_MASK(irq);
	wcd9xxx_spmi_unlock_sleep();

	return IRQ_HANDLED;
}