From 42e7733cc7eb9d73b68719db8941dbfae4c06f87 Mon Sep 17 00:00:00 2001 From: Xia Yang Date: Fri, 20 Feb 2015 15:45:52 -0800 Subject: [PATCH] misc: tegra-cec: Short-circuit init on suspend Bug 1591149 Initialization of cec engine is slow. Short-circuit the init in event of suspend. Change-Id: Ibfbd6f36883a7bf45fdb5137120b041a52f42086 Signed-off-by: Xia Yang Reviewed-on: http://git-master/r/714423 (cherry picked from commit d5f4a6602678c87e8caa5032e43f2415c314d800) Reviewed-on: http://git-master/r/716496 Reviewed-on: http://git-master/r/1164147 (cherry picked from commit 82a640a1ea11e850f769b78b5d0c531731b1ffd8) --- drivers/misc/tegra-cec/tegra_cec.c | 21 ++++++++++++++++++++- drivers/misc/tegra-cec/tegra_cec.h | 6 +++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/misc/tegra-cec/tegra_cec.c b/drivers/misc/tegra-cec/tegra_cec.c index 2758e8af..cfdb2d05 100644 --- a/drivers/misc/tegra-cec/tegra_cec.c +++ b/drivers/misc/tegra-cec/tegra_cec.c @@ -1,7 +1,7 @@ /* * drivers/misc/tegra-cec/tegra_cec.c * - * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -298,7 +298,15 @@ static void tegra_cec_init(struct tegra_cec *cec) writel(0x00, cec->cec_base + TEGRA_CEC_HW_CONTROL); writel(0x00, cec->cec_base + TEGRA_CEC_INT_MASK); writel(0xffffffff, cec->cec_base + TEGRA_CEC_INT_STAT); + +#ifdef CONFIG_PM + if (wait_event_interruptible_timeout(cec->suspend_waitq, + atomic_xchg(&cec->init_cancel, 0) == 1, + msecs_to_jiffies(1000)) > 0) + return; +#else msleep(1000); +#endif writel(0x00, cec->cec_base + TEGRA_CEC_SW_CONTROL); @@ -475,6 +483,11 @@ static int tegra_cec_probe(struct platform_device *pdev) init_waitqueue_head(&cec->tx_waitq); init_waitqueue_head(&cec->init_waitq); +#ifdef CONFIG_PM + init_waitqueue_head(&cec->suspend_waitq); + atomic_set(&cec->init_cancel, 0); +#endif + platform_set_drvdata(pdev, cec); /* clear out the hardware. */ @@ -539,10 +552,16 @@ static int tegra_cec_suspend(struct platform_device *pdev, pm_message_t state) { struct tegra_cec *cec = platform_get_drvdata(pdev); + atomic_set(&cec->init_cancel, 1); + wmb(); + + wake_up_interruptible(&cec->suspend_waitq); + /* cancel the work queue */ cancel_work_sync(&cec->work); atomic_set(&cec->init_done, 0); + atomic_set(&cec->init_cancel, 0); clk_disable(cec->clk); diff --git a/drivers/misc/tegra-cec/tegra_cec.h b/drivers/misc/tegra-cec/tegra_cec.h index 5e2e5981..12913a25 100644 --- a/drivers/misc/tegra-cec/tegra_cec.h +++ b/drivers/misc/tegra-cec/tegra_cec.h @@ -1,7 +1,7 @@ /* * drivers/misc/tegra-cec/tegra_cec.h * - * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -35,6 +35,10 @@ struct tegra_cec { wait_queue_head_t tx_waitq; wait_queue_head_t init_waitq; atomic_t init_done; +#ifdef CONFIG_PM + wait_queue_head_t suspend_waitq; + atomic_t init_cancel; +#endif u16 logical_addr; struct work_struct work; unsigned int rx_wake;