From patchwork Wed Nov 18 11:34:35 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hiremath, Vaibhav" X-Patchwork-Id: 2102 Return-path: Envelope-to: mchehab@infradead.org Delivery-date: Wed, 18 Nov 2009 11:34:48 +0000 Received: from bombadil.infradead.org [18.85.46.34] by pedra.chehab.org with IMAP (fetchmail-6.3.6) for (single-drop); Wed, 18 Nov 2009 09:35:17 -0200 (BRST) Received: from vger.kernel.org ([209.132.176.167]) by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) id 1NAioB-0004ts-SR; Wed, 18 Nov 2009 11:34:48 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751572AbZKRLek (ORCPT + 1 other); Wed, 18 Nov 2009 06:34:40 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751596AbZKRLek (ORCPT ); Wed, 18 Nov 2009 06:34:40 -0500 Received: from arroyo.ext.ti.com ([192.94.94.40]:47699 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751568AbZKRLej (ORCPT ); Wed, 18 Nov 2009 06:34:39 -0500 Received: from dbdp31.itg.ti.com ([172.24.170.98]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id nAIBYe0p022801 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 18 Nov 2009 05:34:43 -0600 Received: from localhost.localdomain (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id nAIBYaFJ013140; Wed, 18 Nov 2009 17:04:36 +0530 (IST) From: hvaibhav@ti.com To: linux-media@vger.kernel.org Cc: hverkuil@xs4all.nl, m-karicheri2@ti.com, Vaibhav Hiremath Subject: [PATCH] Davinci VPFE Capture: Add Suspend/Resume Support Date: Wed, 18 Nov 2009 17:04:35 +0530 Message-Id: <1258544075-28771-1-git-send-email-hvaibhav@ti.com> X-Mailer: git-send-email 1.6.2.4 In-Reply-To: References: Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Vaibhav Hiremath Validated on AM3517 Platform. Signed-off-by: Vaibhav Hiremath --- drivers/media/video/davinci/ccdc_hw_device.h | 4 + drivers/media/video/davinci/dm644x_ccdc.c | 87 ++++++++++++++++++++++++++ drivers/media/video/davinci/vpfe_capture.c | 29 ++++++--- 3 files changed, 112 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/davinci/ccdc_hw_device.h b/drivers/media/video/davinci/ccdc_hw_device.h index 86b9b35..2a1ead4 100644 --- a/drivers/media/video/davinci/ccdc_hw_device.h +++ b/drivers/media/video/davinci/ccdc_hw_device.h @@ -91,6 +91,10 @@ struct ccdc_hw_ops { void (*setfbaddr) (unsigned long addr); /* Pointer to function to get field id */ int (*getfid) (void); + + /* suspend/resume support */ + void (*save_context)(void); + void (*restore_context)(void); }; struct ccdc_hw_device { diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c index 5dff8d9..fdab823 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/video/davinci/dm644x_ccdc.c @@ -88,6 +88,10 @@ static void *__iomem ccdc_base_addr; static int ccdc_addr_size; static enum vpfe_hw_if_type ccdc_if_type; +#define CCDC_SZ_REGS SZ_1K + +static u32 ccdc_ctx[CCDC_SZ_REGS / sizeof(u32)]; + /* register access routines */ static inline u32 regr(u32 offset) { @@ -834,6 +838,87 @@ static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) return 0; } +static void ccdc_save_context(void) +{ + ccdc_ctx[CCDC_PCR] = regr(CCDC_PCR); + ccdc_ctx[CCDC_SYN_MODE] = regr(CCDC_SYN_MODE); + ccdc_ctx[CCDC_HD_VD_WID] = regr(CCDC_HD_VD_WID); + ccdc_ctx[CCDC_PIX_LINES] = regr(CCDC_PIX_LINES); + ccdc_ctx[CCDC_HORZ_INFO] = regr(CCDC_HORZ_INFO); + ccdc_ctx[CCDC_VERT_START] = regr(CCDC_VERT_START); + ccdc_ctx[CCDC_VERT_LINES] = regr(CCDC_VERT_LINES); + ccdc_ctx[CCDC_CULLING] = regr(CCDC_CULLING); + ccdc_ctx[CCDC_HSIZE_OFF] = regr(CCDC_HSIZE_OFF); + ccdc_ctx[CCDC_SDOFST] = regr(CCDC_SDOFST); + ccdc_ctx[CCDC_SDR_ADDR] = regr(CCDC_SDR_ADDR); + ccdc_ctx[CCDC_CLAMP] = regr(CCDC_CLAMP); + ccdc_ctx[CCDC_DCSUB] = regr(CCDC_DCSUB); + ccdc_ctx[CCDC_COLPTN] = regr(CCDC_COLPTN); + ccdc_ctx[CCDC_BLKCMP] = regr(CCDC_BLKCMP); + ccdc_ctx[CCDC_FPC] = regr(CCDC_FPC); + ccdc_ctx[CCDC_FPC_ADDR] = regr(CCDC_FPC_ADDR); + ccdc_ctx[CCDC_VDINT] = regr(CCDC_VDINT); + ccdc_ctx[CCDC_ALAW] = regr(CCDC_ALAW); + ccdc_ctx[CCDC_REC656IF] = regr(CCDC_REC656IF); + ccdc_ctx[CCDC_CCDCFG] = regr(CCDC_CCDCFG); + ccdc_ctx[CCDC_FMTCFG] = regr(CCDC_FMTCFG); + ccdc_ctx[CCDC_FMT_HORZ] = regr(CCDC_FMT_HORZ); + ccdc_ctx[CCDC_FMT_VERT] = regr(CCDC_FMT_VERT); + ccdc_ctx[CCDC_FMT_ADDR0] = regr(CCDC_FMT_ADDR0); + ccdc_ctx[CCDC_FMT_ADDR1] = regr(CCDC_FMT_ADDR1); + ccdc_ctx[CCDC_FMT_ADDR2] = regr(CCDC_FMT_ADDR2); + ccdc_ctx[CCDC_FMT_ADDR3] = regr(CCDC_FMT_ADDR3); + ccdc_ctx[CCDC_FMT_ADDR4] = regr(CCDC_FMT_ADDR4); + ccdc_ctx[CCDC_FMT_ADDR5] = regr(CCDC_FMT_ADDR5); + ccdc_ctx[CCDC_FMT_ADDR6] = regr(CCDC_FMT_ADDR6); + ccdc_ctx[CCDC_FMT_ADDR7] = regr(CCDC_FMT_ADDR7); + ccdc_ctx[CCDC_PRGEVEN_0] = regr(CCDC_PRGEVEN_0); + ccdc_ctx[CCDC_PRGEVEN_1] = regr(CCDC_PRGEVEN_1); + ccdc_ctx[CCDC_PRGODD_0] = regr(CCDC_PRGODD_0); + ccdc_ctx[CCDC_PRGODD_1] = regr(CCDC_PRGODD_1); + ccdc_ctx[CCDC_VP_OUT] = regr(CCDC_VP_OUT); +} + +static void ccdc_restore_context(void) +{ + regw(ccdc_ctx[CCDC_SYN_MODE], CCDC_SYN_MODE); + regw(ccdc_ctx[CCDC_HD_VD_WID], CCDC_HD_VD_WID); + regw(ccdc_ctx[CCDC_PIX_LINES], CCDC_PIX_LINES); + regw(ccdc_ctx[CCDC_HORZ_INFO], CCDC_HORZ_INFO); + regw(ccdc_ctx[CCDC_VERT_START], CCDC_VERT_START); + regw(ccdc_ctx[CCDC_VERT_LINES], CCDC_VERT_LINES); + regw(ccdc_ctx[CCDC_CULLING], CCDC_CULLING); + regw(ccdc_ctx[CCDC_HSIZE_OFF], CCDC_HSIZE_OFF); + regw(ccdc_ctx[CCDC_SDOFST], CCDC_SDOFST); + regw(ccdc_ctx[CCDC_SDR_ADDR], CCDC_SDR_ADDR); + regw(ccdc_ctx[CCDC_CLAMP], CCDC_CLAMP); + regw(ccdc_ctx[CCDC_DCSUB], CCDC_DCSUB); + regw(ccdc_ctx[CCDC_COLPTN], CCDC_COLPTN); + regw(ccdc_ctx[CCDC_BLKCMP], CCDC_BLKCMP); + regw(ccdc_ctx[CCDC_FPC], CCDC_FPC); + regw(ccdc_ctx[CCDC_FPC_ADDR], CCDC_FPC_ADDR); + regw(ccdc_ctx[CCDC_VDINT], CCDC_VDINT); + regw(ccdc_ctx[CCDC_ALAW], CCDC_ALAW); + regw(ccdc_ctx[CCDC_REC656IF], CCDC_REC656IF); + regw(ccdc_ctx[CCDC_CCDCFG], CCDC_CCDCFG); + regw(ccdc_ctx[CCDC_FMTCFG], CCDC_FMTCFG); + regw(ccdc_ctx[CCDC_FMT_HORZ], CCDC_FMT_HORZ); + regw(ccdc_ctx[CCDC_FMT_VERT], CCDC_FMT_VERT); + regw(ccdc_ctx[CCDC_FMT_ADDR0], CCDC_FMT_ADDR0); + regw(ccdc_ctx[CCDC_FMT_ADDR1], CCDC_FMT_ADDR1); + regw(ccdc_ctx[CCDC_FMT_ADDR2], CCDC_FMT_ADDR2); + regw(ccdc_ctx[CCDC_FMT_ADDR3], CCDC_FMT_ADDR3); + regw(ccdc_ctx[CCDC_FMT_ADDR4], CCDC_FMT_ADDR4); + regw(ccdc_ctx[CCDC_FMT_ADDR5], CCDC_FMT_ADDR5); + regw(ccdc_ctx[CCDC_FMT_ADDR6], CCDC_FMT_ADDR6); + regw(ccdc_ctx[CCDC_FMT_ADDR7], CCDC_FMT_ADDR7); + regw(ccdc_ctx[CCDC_PRGEVEN_0], CCDC_PRGEVEN_0); + regw(ccdc_ctx[CCDC_PRGEVEN_1], CCDC_PRGEVEN_1); + regw(ccdc_ctx[CCDC_PRGODD_0], CCDC_PRGODD_0); + regw(ccdc_ctx[CCDC_PRGODD_1], CCDC_PRGODD_1); + regw(ccdc_ctx[CCDC_VP_OUT], CCDC_VP_OUT); + regw(ccdc_ctx[CCDC_PCR], CCDC_PCR); +} static struct ccdc_hw_device ccdc_hw_dev = { .name = "DM6446 CCDC", .owner = THIS_MODULE, @@ -858,6 +943,8 @@ static struct ccdc_hw_device ccdc_hw_dev = { .get_line_length = ccdc_get_line_length, .setfbaddr = ccdc_setfbaddr, .getfid = ccdc_getfid, + .save_context = ccdc_save_context, + .restore_context = ccdc_restore_context, }, }; diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 9c859a7..9b6b254 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -2394,18 +2394,31 @@ static int vpfe_remove(struct platform_device *pdev) return 0; } -static int -vpfe_suspend(struct device *dev) +static int vpfe_suspend(struct device *dev) { - /* add suspend code here later */ - return -1; + struct vpfe_device *vpfe_dev = dev_get_drvdata(dev);; + + if (ccdc_dev->hw_ops.save_context) + ccdc_dev->hw_ops.save_context(); + ccdc_dev->hw_ops.enable(0); + + if (vpfe_dev) + vpfe_disable_clock(vpfe_dev); + + return 0; } -static int -vpfe_resume(struct device *dev) +static int vpfe_resume(struct device *dev) { - /* add resume code here later */ - return -1; + struct vpfe_device *vpfe_dev = dev_get_drvdata(dev);; + + if (vpfe_dev) + vpfe_enable_clock(vpfe_dev); + + if (ccdc_dev->hw_ops.restore_context) + ccdc_dev->hw_ops.restore_context(); + + return 0; } static struct dev_pm_ops vpfe_dev_pm_ops = {