From patchwork Sun Oct 9 13:26:43 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Javier Martinez Canillas X-Patchwork-Id: 8103 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.72) (envelope-from ) id 1RCtPG-0008HV-Mo; Sun, 09 Oct 2011 15:27:25 +0200 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.75/mailfrontend-2) with esmtp id 1RCtPF-0001cb-J1; Sun, 09 Oct 2011 15:27:06 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751412Ab1JIN1D (ORCPT + 3 others); Sun, 9 Oct 2011 09:27:03 -0400 Received: from mail-wy0-f174.google.com ([74.125.82.174]:39585 "EHLO mail-wy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750922Ab1JIN1B (ORCPT ); Sun, 9 Oct 2011 09:27:01 -0400 Received: by mail-wy0-f174.google.com with SMTP id 34so5137571wyg.19 for ; Sun, 09 Oct 2011 06:27:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=9DHp0rLlQdG1Zkzyz1RGIssD8iXIwFWL2XYbwBFXZLo=; b=j9p+KuhFWOlNQ9RvFWZzdp4zOiLoxwaPs8/YSQLNZBJfherxQxKZiHF5yVo/+wiiEU SxU47OIDojWDCeND+ViKdaQH6e39JfCNzQJ83TE+W/2Zgu5+LqXjmXo2ozqQGF6dGR1Q OqZIXiDBE2MeWpQGwyXhVzQf7acpMriXKCBCE= Received: by 10.227.11.147 with SMTP id t19mr4890748wbt.72.1318166820961; Sun, 09 Oct 2011 06:27:00 -0700 (PDT) Received: from localhost.localdomain (216.Red-79-152-171.dynamicIP.rima-tde.net. [79.152.171.216]) by mx.google.com with ESMTPS id h39sm27131131wbo.0.2011.10.09.06.26.59 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 09 Oct 2011 06:27:00 -0700 (PDT) From: Javier Martinez Canillas To: Laurent Pinchart Cc: Sakari Ailus , Enrico , Gary Thomas , Adam Pledger , Deepthy Ravi , linux-media@vger.kernel.org, Javier Martinez Canillas Subject: [PATCH v2 3/3] omap3isp: ccdc: Add support to ITU-R BT.656 video data format Date: Sun, 9 Oct 2011 15:26:43 +0200 Message-Id: <1318166803-7392-4-git-send-email-martinez.javier@gmail.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1318166803-7392-1-git-send-email-martinez.javier@gmail.com> References: <1318166803-7392-1-git-send-email-martinez.javier@gmail.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 5.6.1.2065439, Antispam-Engine: 2.7.2.376379, Antispam-Data: 2011.10.9.131518 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report=' FORGED_FROM_GMAIL 0.1, MULTIPLE_RCPTS 0.1, BODY_SIZE_6000_6999 0, BODY_SIZE_7000_LESS 0, FROM_NAME_PHRASE 0, __ANY_URI 0, __CP_MEDIA_BODY 0, __CP_URI_IN_BODY 0, __FRAUD_BODY_WEBMAIL 0, __FRAUD_WEBMAIL 0, __FRAUD_WEBMAIL_FROM 0, __FROM_GMAIL 0, __HAS_MSGID 0, __HAS_X_MAILER 0, __HAS_X_MAILING_LIST 0, __LINES_OF_YELLING 0, __MIME_TEXT_ONLY 0, __MULTIPLE_RCPTS_CC_X2 0, __PHISH_SPEAR_STRUCTURE_1 0, __SANE_MSGID 0, __SUBJ_ALPHA_END 0, __TO_MALFORMED_2 0, __URI_NO_WWW 0, __URI_NS ' X-LSpam-Score: 1.1 (+) X-LSpam-Report: No, score=1.1 required=5.0 tests=BAYES_00=-1.9, FREEMAIL_FROM=0.001, KB_DATE_CONTAINS_TAB=2.751, RCVD_IN_DNSWL_MED=-2.3, TAB_IN_FROM=2.494, T_DKIM_INVALID=0.01 autolearn=no This patch adds to the ISP CCDC driver the ability to deinterlace video data when configured in interlaced mode and send progressive frames to user-space V4L2 applications. Signed-off-by: Javier Martinez Canillas --- drivers/media/video/omap3isp/ispccdc.c | 104 ++++++++++++++++++++++++++------ 1 files changed, 85 insertions(+), 19 deletions(-) diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c index c25db54..7907081 100644 --- a/drivers/media/video/omap3isp/ispccdc.c +++ b/drivers/media/video/omap3isp/ispccdc.c @@ -40,6 +40,8 @@ static struct v4l2_mbus_framefmt * __ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh, unsigned int pad, enum v4l2_subdev_format_whence which); +static bool ccdc_input_is_bt656(struct isp_ccdc_device *ccdc); +static bool ccdc_input_is_fldmode(struct isp_ccdc_device *ccdc); static const unsigned int ccdc_fmts[] = { V4L2_MBUS_FMT_Y8_1X8, @@ -889,12 +891,6 @@ static void ccdc_config_outlineoffset(struct isp_ccdc_device *ccdc, isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF); - isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, - ISPCCDC_SDOFST_FINV); - - isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, - ISPCCDC_SDOFST_FOFST_4L); - switch (oddeven) { case EVENEVEN: isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, @@ -1010,6 +1006,9 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc, if (pdata && pdata->vs_pol) syn_mode |= ISPCCDC_SYN_MODE_VDPOL; + if (pdata && pdata->fldmode) + syn_mode |= ISPCCDC_SYN_MODE_FLDMODE; + isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); if (format->code == V4L2_MBUS_FMT_UYVY8_2X8) @@ -1115,6 +1114,10 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) unsigned int shift; u32 syn_mode; u32 ccdc_pattern; + u32 nph; + u32 nlv; + u32 vd0; + u32 vd1; pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]); sensor = media_entity_to_v4l2_subdev(pad->entity); @@ -1185,26 +1188,49 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) } ccdc_config_imgattr(ccdc, ccdc_pattern); + /* In BT.656 a pixel is representd using two bytes */ + if (pdata->bt656) + nph = format->width * 2 - 1; + else + nph = format->width - 1; + + /* In interlaced mode a frame is composed fo two subrames */ + if (pdata->fldmode) { + vd0 = nlv = format->height / 2 - 1; + vd1 = format->height / 3; + } else { + vd0 = nlv = format->height - 2; + vd1 = format->height * 2 / 3; + } + /* Generate VD0 on the last line of the image and VD1 on the * 2/3 height line. */ - isp_reg_writel(isp, ((format->height - 2) << ISPCCDC_VDINT_0_SHIFT) | - ((format->height * 2 / 3) << ISPCCDC_VDINT_1_SHIFT), + isp_reg_writel(isp, (vd0 << ISPCCDC_VDINT_0_SHIFT) | + (vd1 << ISPCCDC_VDINT_1_SHIFT), OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT); /* CCDC_PAD_SOURCE_OF */ format = &ccdc->formats[CCDC_PAD_SOURCE_OF]; isp_reg_writel(isp, (0 << ISPCCDC_HORZ_INFO_SPH_SHIFT) | - ((format->width - 1) << ISPCCDC_HORZ_INFO_NPH_SHIFT), + (nph << ISPCCDC_HORZ_INFO_NPH_SHIFT), OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO); isp_reg_writel(isp, 0 << ISPCCDC_VERT_START_SLV0_SHIFT, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START); - isp_reg_writel(isp, (format->height - 1) - << ISPCCDC_VERT_LINES_NLV_SHIFT, + isp_reg_writel(isp, nlv << ISPCCDC_VERT_LINES_NLV_SHIFT, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES); + isp_reg_writel(isp, 0 << ISPCCDC_VERT_START_SLV1_SHIFT, + OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START); - ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, 0, 0); + + if (pdata->fldmode) { + ccdc_config_outlineoffset(ccdc, nph, EVENEVEN, 1); + ccdc_config_outlineoffset(ccdc, nph, EVENODD, 1); + ccdc_config_outlineoffset(ccdc, nph, ODDEVEN, 1); + ccdc_config_outlineoffset(ccdc, nph, ODDODD, 1); + } else + ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, 0, 0); /* CCDC_PAD_SOURCE_VP */ format = &ccdc->formats[CCDC_PAD_SOURCE_VP]; @@ -1495,10 +1521,30 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc) goto done; } - buffer = omap3isp_video_buffer_next(&ccdc->video_out, ccdc->error); - if (buffer != NULL) { - ccdc_set_outaddr(ccdc, buffer->isp_addr); - restart = 1; + /* In interlaced mode a frame is composed of two subframes so we don't have + * to change the CCDC output memory on every end of frame. + */ + if (!ccdc_input_is_fldmode(ccdc)) { + if (!ccdc->interlaced_cnt) { + ccdc->interlaced_cnt = 1; + restart = 1; + } else { + ccdc->interlaced_cnt = 0; + buffer = omap3isp_video_buffer_next(&ccdc->video_out, + ccdc->error); + if (buffer != NULL) { + ccdc_set_outaddr(ccdc, buffer->isp_addr); + restart = 1; + } + } + } else { + buffer = omap3isp_video_buffer_next(&ccdc->video_out, + ccdc->error); + if (buffer != NULL) { + ccdc_set_outaddr(ccdc, buffer->isp_addr); + restart = 1; + } + } pipe->state |= ISP_PIPELINE_IDLE_OUTPUT; @@ -1764,6 +1810,7 @@ static int ccdc_set_stream(struct v4l2_subdev *sd, int enable) omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CCDC_WRITE); omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_CCDC); ccdc->underrun = 0; + ccdc->interlaced_cnt = 0; break; } @@ -1781,9 +1828,9 @@ __ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh, return &ccdc->formats[pad]; } -static bool ccdc_input_is_bt656(struct isp_ccdc_device *ccdc) +struct isp_parallel_platform_data *ccdc_get_pdata(struct isp_ccdc_device *ccdc) { - const struct isp_parallel_platform_data *pdata = NULL; + struct isp_parallel_platform_data *pdata = NULL; const struct v4l2_subdev *sensor; const struct media_pad *pad; @@ -1793,7 +1840,26 @@ static bool ccdc_input_is_bt656(struct isp_ccdc_device *ccdc) pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]); sensor = media_entity_to_v4l2_subdev(pad->entity); pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv) - ->bus.parallel; + ->bus.parallel; + + return pdata; +} + +static bool ccdc_input_is_fldmode(struct isp_ccdc_device *ccdc) + +{ + const struct isp_parallel_platform_data *pdata = NULL; + + pdata = ccdc_get_pdata(ccdc); + + return pdata && pdata->bt656; +} + +static bool ccdc_input_is_bt656(struct isp_ccdc_device *ccdc) +{ + const struct isp_parallel_platform_data *pdata = NULL; + + pdata = ccdc_get_pdata(ccdc); return pdata && pdata->bt656; }