aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/omap3isp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/omap3isp')
-rw-r--r--drivers/media/platform/omap3isp/cfa_coef_table.h10
-rw-r--r--drivers/media/platform/omap3isp/gamma_table.h10
-rw-r--r--drivers/media/platform/omap3isp/isp.c20
-rw-r--r--drivers/media/platform/omap3isp/isp.h10
-rw-r--r--drivers/media/platform/omap3isp/ispccdc.c424
-rw-r--r--drivers/media/platform/omap3isp/ispccdc.h21
-rw-r--r--drivers/media/platform/omap3isp/ispccp2.c10
-rw-r--r--drivers/media/platform/omap3isp/ispccp2.h10
-rw-r--r--drivers/media/platform/omap3isp/ispcsi2.c10
-rw-r--r--drivers/media/platform/omap3isp/ispcsi2.h10
-rw-r--r--drivers/media/platform/omap3isp/ispcsiphy.c10
-rw-r--r--drivers/media/platform/omap3isp/ispcsiphy.h10
-rw-r--r--drivers/media/platform/omap3isp/isph3a.h10
-rw-r--r--drivers/media/platform/omap3isp/isph3a_aewb.c10
-rw-r--r--drivers/media/platform/omap3isp/isph3a_af.c10
-rw-r--r--drivers/media/platform/omap3isp/isphist.c10
-rw-r--r--drivers/media/platform/omap3isp/isphist.h10
-rw-r--r--drivers/media/platform/omap3isp/isppreview.c10
-rw-r--r--drivers/media/platform/omap3isp/isppreview.h10
-rw-r--r--drivers/media/platform/omap3isp/ispreg.h20
-rw-r--r--drivers/media/platform/omap3isp/ispresizer.c80
-rw-r--r--drivers/media/platform/omap3isp/ispresizer.h13
-rw-r--r--drivers/media/platform/omap3isp/ispstat.c10
-rw-r--r--drivers/media/platform/omap3isp/ispstat.h10
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.c59
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.h12
-rw-r--r--drivers/media/platform/omap3isp/luma_enhance_table.h10
-rw-r--r--drivers/media/platform/omap3isp/noise_filter_table.h10
28 files changed, 406 insertions, 443 deletions
diff --git a/drivers/media/platform/omap3isp/cfa_coef_table.h b/drivers/media/platform/omap3isp/cfa_coef_table.h
index c84df0706f3e..e75b0eb2519b 100644
--- a/drivers/media/platform/omap3isp/cfa_coef_table.h
+++ b/drivers/media/platform/omap3isp/cfa_coef_table.h
@@ -11,16 +11,6 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
{ 244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244,
diff --git a/drivers/media/platform/omap3isp/gamma_table.h b/drivers/media/platform/omap3isp/gamma_table.h
index 78deebf7d965..3b507078016d 100644
--- a/drivers/media/platform/omap3isp/gamma_table.h
+++ b/drivers/media/platform/omap3isp/gamma_table.h
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
0, 0, 1, 2, 3, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20,
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 2c7aa6720569..72265e58ca60 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -40,16 +40,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <asm/cacheflush.h>
@@ -999,16 +989,14 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
video, s_stream, 0);
}
- v4l2_subdev_call(subdev, video, s_stream, 0);
+ ret = v4l2_subdev_call(subdev, video, s_stream, 0);
if (subdev == &isp->isp_res.subdev)
- ret = isp_pipeline_wait(isp, isp_pipeline_wait_resizer);
+ ret |= isp_pipeline_wait(isp, isp_pipeline_wait_resizer);
else if (subdev == &isp->isp_prev.subdev)
- ret = isp_pipeline_wait(isp, isp_pipeline_wait_preview);
+ ret |= isp_pipeline_wait(isp, isp_pipeline_wait_preview);
else if (subdev == &isp->isp_ccdc.subdev)
- ret = isp_pipeline_wait(isp, isp_pipeline_wait_ccdc);
- else
- ret = 0;
+ ret |= isp_pipeline_wait(isp, isp_pipeline_wait_ccdc);
/* Handle stop failures. An entity that fails to stop can
* usually just be restarted. Flag the stop failure nonetheless
diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h
index 2c314eea1252..cfdfc8714b6b 100644
--- a/drivers/media/platform/omap3isp/isp.h
+++ b/drivers/media/platform/omap3isp/isp.h
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_CORE_H
diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
index 9f727d20f06d..81a9dc053d58 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <linux/module.h>
@@ -491,14 +481,13 @@ done:
static inline int ccdc_lsc_is_configured(struct isp_ccdc_device *ccdc)
{
unsigned long flags;
+ int ret;
spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
- if (ccdc->lsc.active) {
- spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
- return 1;
- }
+ ret = ccdc->lsc.active != NULL;
spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
- return 0;
+
+ return ret;
}
static int ccdc_lsc_enable(struct isp_ccdc_device *ccdc)
@@ -818,29 +807,48 @@ static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
struct isp_device *isp = to_isp_device(ccdc);
const struct isp_format_info *info;
+ struct v4l2_mbus_framefmt *format;
unsigned long l3_ick = pipe->l3_ick;
unsigned int max_div = isp->revision == ISP_REVISION_15_0 ? 64 : 8;
unsigned int div = 0;
- u32 fmtcfg_vp;
+ u32 fmtcfg = ISPCCDC_FMTCFG_VPEN;
+
+ format = &ccdc->formats[CCDC_PAD_SOURCE_VP];
+
+ if (!format->code) {
+ /* Disable the video port when the input format isn't supported.
+ * This is indicated by a pixel code set to 0.
+ */
+ isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
+ return;
+ }
+
+ isp_reg_writel(isp, (0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
+ (format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ);
+ isp_reg_writel(isp, (0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
+ ((format->height + 1) << ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT);
- fmtcfg_vp = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG)
- & ~(ISPCCDC_FMTCFG_VPIN_MASK | ISPCCDC_FMTCFG_VPIF_FRQ_MASK);
+ isp_reg_writel(isp, (format->width << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
+ (format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
info = omap3isp_video_format_info(ccdc->formats[CCDC_PAD_SINK].code);
switch (info->width) {
case 8:
case 10:
- fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
+ fmtcfg |= ISPCCDC_FMTCFG_VPIN_9_0;
break;
case 11:
- fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
+ fmtcfg |= ISPCCDC_FMTCFG_VPIN_10_1;
break;
case 12:
- fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
+ fmtcfg |= ISPCCDC_FMTCFG_VPIN_11_2;
break;
case 13:
- fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
+ fmtcfg |= ISPCCDC_FMTCFG_VPIN_12_3;
break;
}
@@ -850,75 +858,59 @@ static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
div = l3_ick / pipe->external_rate;
div = clamp(div, 2U, max_div);
- fmtcfg_vp |= (div - 2) << ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT;
+ fmtcfg |= (div - 2) << ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT;
- isp_reg_writel(isp, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
-}
-
-/*
- * ccdc_enable_vp - Enable Video Port.
- * @ccdc: Pointer to ISP CCDC device.
- * @enable: 0 Disables VP, 1 Enables VP
- *
- * This is needed for outputting image to Preview, H3A and HIST ISP submodules.
- */
-static void ccdc_enable_vp(struct isp_ccdc_device *ccdc, u8 enable)
-{
- struct isp_device *isp = to_isp_device(ccdc);
-
- isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
- ISPCCDC_FMTCFG_VPEN, enable ? ISPCCDC_FMTCFG_VPEN : 0);
+ isp_reg_writel(isp, fmtcfg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
}
/*
* ccdc_config_outlineoffset - Configure memory saving output line offset
* @ccdc: Pointer to ISP CCDC device.
- * @offset: Address offset to start a new line. Must be twice the
- * Output width and aligned on 32 byte boundary
- * @oddeven: Specifies the odd/even line pattern to be chosen to store the
- * output.
- * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
+ * @bpl: Number of bytes per line when stored in memory.
+ * @field: Field order when storing interlaced formats in memory.
+ *
+ * Configure the offsets for the line output control:
+ *
+ * - The horizontal line offset is defined as the number of bytes between the
+ * start of two consecutive lines in memory. Set it to the given bytes per
+ * line value.
+ *
+ * - The field offset value is defined as the number of lines to offset the
+ * start of the field identified by FID = 1. Set it to one.
*
- * - Configures the output line offset when stored in memory
- * - Sets the odd/even line pattern to store the output
- * (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
- * - Configures the number of even and odd line fields in case of rearranging
- * the lines.
+ * - The line offset values are defined as the number of lines (as defined by
+ * the horizontal line offset) between the start of two consecutive lines for
+ * all combinations of odd/even lines in odd/even fields. When interleaving
+ * fields set them all to two lines, and to one line otherwise.
*/
static void ccdc_config_outlineoffset(struct isp_ccdc_device *ccdc,
- u32 offset, u8 oddeven, u8 numlines)
+ unsigned int bpl,
+ enum v4l2_field field)
{
struct isp_device *isp = to_isp_device(ccdc);
+ u32 sdofst = 0;
- isp_reg_writel(isp, offset & 0xffff,
- OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF);
+ isp_reg_writel(isp, bpl & 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,
- (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
- break;
- case ODDEVEN:
- isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
- (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
- break;
- case EVENODD:
- isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
- (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
- break;
- case ODDODD:
- isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
- (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
+ switch (field) {
+ case V4L2_FIELD_INTERLACED_TB:
+ case V4L2_FIELD_INTERLACED_BT:
+ /* When interleaving fields in memory offset field one by one
+ * line and set the line offset to two lines.
+ */
+ sdofst |= (1 << ISPCCDC_SDOFST_LOFST0_SHIFT)
+ | (1 << ISPCCDC_SDOFST_LOFST1_SHIFT)
+ | (1 << ISPCCDC_SDOFST_LOFST2_SHIFT)
+ | (1 << ISPCCDC_SDOFST_LOFST3_SHIFT);
break;
+
default:
+ /* In all other cases set the line offsets to one line. */
break;
}
+
+ isp_reg_writel(isp, sdofst, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST);
}
/*
@@ -981,10 +973,16 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
format->code == V4L2_MBUS_FMT_UYVY8_2X8) {
- /* The bridge is enabled for YUV8 formats. Configure the input
- * mode accordingly.
+ /* According to the OMAP3 TRM the input mode only affects SYNC
+ * mode, enabling BT.656 mode should take precedence. However,
+ * in practice setting the input mode to YCbCr data on 8 bits
+ * seems to be required in BT.656 mode. In SYNC mode set it to
+ * YCbCr on 16 bits as the bridge is enabled in that case.
*/
- syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
+ if (ccdc->bt656)
+ syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
+ else
+ syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
}
switch (data_size) {
@@ -1008,9 +1006,15 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
if (pdata && pdata->hs_pol)
syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
- if (pdata && pdata->vs_pol)
+ /* The polarity of the vertical sync signal output by the BT.656
+ * decoder is not documented and seems to be active low.
+ */
+ if ((pdata && pdata->vs_pol) || ccdc->bt656)
syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
+ if (pdata && pdata->fld_pol)
+ syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
+
isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
/* The CCDC_CFG.Y8POS bit is used in YCbCr8 input mode only. The
@@ -1023,8 +1027,16 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
ISPCCDC_CFG_Y8POS);
- isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
- ISPCCDC_REC656IF_R656ON);
+ /* Enable or disable BT.656 mode, including error correction for the
+ * synchronization codes.
+ */
+ if (ccdc->bt656)
+ isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
+ ISPCCDC_REC656IF_R656ON | ISPCCDC_REC656IF_ECCFVH);
+ else
+ isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
+ ISPCCDC_REC656IF_R656ON | ISPCCDC_REC656IF_ECCFVH);
+
}
/* CCDC formats descriptions */
@@ -1115,17 +1127,33 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
unsigned long flags;
unsigned int bridge;
unsigned int shift;
+ unsigned int nph;
+ unsigned int sph;
u32 syn_mode;
u32 ccdc_pattern;
+ ccdc->bt656 = false;
+ ccdc->fields = 0;
+
pad = media_entity_remote_pad(&ccdc->pads[CCDC_PAD_SINK]);
sensor = media_entity_to_v4l2_subdev(pad->entity);
- if (ccdc->input == CCDC_INPUT_PARALLEL)
+ if (ccdc->input == CCDC_INPUT_PARALLEL) {
+ struct v4l2_mbus_config cfg;
+ int ret;
+
+ ret = v4l2_subdev_call(sensor, video, g_mbus_config, &cfg);
+ if (!ret)
+ ccdc->bt656 = cfg.type == V4L2_MBUS_BT656;
+
pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
->bus.parallel;
+ }
+
+ /* CCDC_PAD_SINK */
+ format = &ccdc->formats[CCDC_PAD_SINK];
/* Compute the lane shifter shift value and enable the bridge when the
- * input format is YUV.
+ * input format is a non-BT.656 YUV variant.
*/
fmt_src.pad = pad->index;
fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
@@ -1134,12 +1162,13 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
depth_in = fmt_info->width;
}
- fmt_info = omap3isp_video_format_info
- (isp->isp_ccdc.formats[CCDC_PAD_SINK].code);
+ fmt_info = omap3isp_video_format_info(format->code);
depth_out = fmt_info->width;
shift = depth_in - depth_out;
- if (fmt_info->code == V4L2_MBUS_FMT_YUYV8_2X8)
+ if (ccdc->bt656)
+ bridge = ISPCTRL_PAR_BRIDGE_DISABLE;
+ else if (fmt_info->code == V4L2_MBUS_FMT_YUYV8_2X8)
bridge = ISPCTRL_PAR_BRIDGE_LENDIAN;
else if (fmt_info->code == V4L2_MBUS_FMT_UYVY8_2X8)
bridge = ISPCTRL_PAR_BRIDGE_BENDIAN;
@@ -1148,6 +1177,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
omap3isp_configure_bridge(isp, ccdc->input, pdata, shift, bridge);
+ /* Configure the sync interface. */
ccdc_config_sync_if(ccdc, pdata, depth_out);
syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
@@ -1167,9 +1197,6 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
else
syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
- /* CCDC_PAD_SINK */
- format = &ccdc->formats[CCDC_PAD_SINK];
-
/* Mosaic filter */
switch (format->code) {
case V4L2_MBUS_FMT_SRGGB10_1X10:
@@ -1202,16 +1229,40 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
format = &ccdc->formats[CCDC_PAD_SOURCE_OF];
crop = &ccdc->crop;
- isp_reg_writel(isp, (crop->left << ISPCCDC_HORZ_INFO_SPH_SHIFT) |
- ((crop->width - 1) << ISPCCDC_HORZ_INFO_NPH_SHIFT),
+ /* The horizontal coordinates are expressed in pixel clock cycles. We
+ * need two cycles per pixel in BT.656 mode, and one cycle per pixel in
+ * SYNC mode regardless of the format as the bridge is enabled for YUV
+ * formats in that case.
+ */
+ if (ccdc->bt656) {
+ sph = crop->left * 2;
+ nph = crop->width * 2 - 1;
+ } else {
+ sph = crop->left;
+ nph = crop->width - 1;
+ }
+
+ isp_reg_writel(isp, (sph << ISPCCDC_HORZ_INFO_SPH_SHIFT) |
+ (nph << ISPCCDC_HORZ_INFO_NPH_SHIFT),
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO);
- isp_reg_writel(isp, crop->top << ISPCCDC_VERT_START_SLV0_SHIFT,
+ isp_reg_writel(isp, (crop->top << ISPCCDC_VERT_START_SLV0_SHIFT) |
+ (crop->top << ISPCCDC_VERT_START_SLV1_SHIFT),
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START);
isp_reg_writel(isp, (crop->height - 1)
<< ISPCCDC_VERT_LINES_NLV_SHIFT,
OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES);
- ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, 0, 0);
+ ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value,
+ format->field);
+
+ /* When interleaving fields enable processing of the field input signal.
+ * This will cause the line output control module to apply the field
+ * offset to field 1.
+ */
+ if (ccdc->formats[CCDC_PAD_SINK].field == V4L2_FIELD_ALTERNATE &&
+ (format->field == V4L2_FIELD_INTERLACED_TB ||
+ format->field == V4L2_FIELD_INTERLACED_BT))
+ syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
/* The CCDC outputs data in UYVY order by default. Swap bytes to get
* YUYV.
@@ -1223,8 +1274,11 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
ISPCCDC_CFG_BSWD);
- /* Use PACK8 mode for 1byte per pixel formats. */
- if (omap3isp_video_format_info(format->code)->width <= 8)
+ /* Use PACK8 mode for 1byte per pixel formats. Check for BT.656 mode
+ * explicitly as the driver reports 1X16 instead of 2X8 at the OF pad
+ * for simplicity.
+ */
+ if (omap3isp_video_format_info(format->code)->width <= 8 || ccdc->bt656)
syn_mode |= ISPCCDC_SYN_MODE_PACK8;
else
syn_mode &= ~ISPCCDC_SYN_MODE_PACK8;
@@ -1232,18 +1286,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
/* CCDC_PAD_SOURCE_VP */
- format = &ccdc->formats[CCDC_PAD_SOURCE_VP];
-
- isp_reg_writel(isp, (0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
- (format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
- OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ);
- isp_reg_writel(isp, (0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
- ((format->height + 1) << ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
- OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT);
-
- isp_reg_writel(isp, (format->width << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
- (format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
- OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
+ ccdc_config_vp(ccdc);
/* Lens shading correction. */
spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
@@ -1277,6 +1320,8 @@ static void __ccdc_enable(struct isp_ccdc_device *ccdc, int enable)
isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR,
ISPCCDC_PCR_EN, enable ? ISPCCDC_PCR_EN : 0);
+
+ ccdc->running = enable;
}
static int ccdc_disable(struct isp_ccdc_device *ccdc)
@@ -1287,6 +1332,8 @@ static int ccdc_disable(struct isp_ccdc_device *ccdc)
spin_lock_irqsave(&ccdc->lock, flags);
if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS)
ccdc->stopping = CCDC_STOP_REQUEST;
+ if (!ccdc->running)
+ ccdc->stopping = CCDC_STOP_FINISHED;
spin_unlock_irqrestore(&ccdc->lock, flags);
ret = wait_event_timeout(ccdc->wait,
@@ -1369,14 +1416,14 @@ static int ccdc_sbl_wait_idle(struct isp_ccdc_device *ccdc,
return -EBUSY;
}
-/* __ccdc_handle_stopping - Handle CCDC and/or LSC stopping sequence
+/* ccdc_handle_stopping - Handle CCDC and/or LSC stopping sequence
* @ccdc: Pointer to ISP CCDC device.
* @event: Pointing which event trigger handler
*
* Return 1 when the event and stopping request combination is satisfied,
* zero otherwise.
*/
-static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
+static int ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
{
int rval = 0;
@@ -1458,7 +1505,7 @@ static void ccdc_lsc_isr(struct isp_ccdc_device *ccdc, u32 events)
if (ccdc->lsc.state == LSC_STATE_STOPPING)
ccdc->lsc.state = LSC_STATE_STOPPED;
- if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_LSC_DONE))
+ if (ccdc_handle_stopping(ccdc, CCDC_EVENT_LSC_DONE))
goto done;
if (ccdc->lsc.state != LSC_STATE_RECONFIG)
@@ -1486,12 +1533,59 @@ done:
spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
}
+/*
+ * Check whether the CCDC has captured all fields necessary to complete the
+ * buffer.
+ */
+static bool ccdc_has_all_fields(struct isp_ccdc_device *ccdc)
+{
+ struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
+ struct isp_device *isp = to_isp_device(ccdc);
+ enum v4l2_field of_field = ccdc->formats[CCDC_PAD_SOURCE_OF].field;
+ enum v4l2_field field;
+
+ /* When the input is progressive fields don't matter. */
+ if (of_field == V4L2_FIELD_NONE)
+ return true;
+
+ /* Read the current field identifier. */
+ field = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE)
+ & ISPCCDC_SYN_MODE_FLDSTAT
+ ? V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP;
+
+ /* When capturing fields in alternate order just store the current field
+ * identifier in the pipeline.
+ */
+ if (of_field == V4L2_FIELD_ALTERNATE) {
+ pipe->field = field;
+ return true;
+ }
+
+ /* The format is interlaced. Make sure we've captured both fields. */
+ ccdc->fields |= field == V4L2_FIELD_BOTTOM
+ ? CCDC_FIELD_BOTTOM : CCDC_FIELD_TOP;
+
+ if (ccdc->fields != CCDC_FIELD_BOTH)
+ return false;
+
+ /* Verify that the field just captured corresponds to the last field
+ * needed based on the desired field order.
+ */
+ if ((of_field == V4L2_FIELD_INTERLACED_TB && field == V4L2_FIELD_TOP) ||
+ (of_field == V4L2_FIELD_INTERLACED_BT && field == V4L2_FIELD_BOTTOM))
+ return false;
+
+ /* The buffer can be completed, reset the fields for the next buffer. */
+ ccdc->fields = 0;
+
+ return true;
+}
+
static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
{
struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
struct isp_device *isp = to_isp_device(ccdc);
struct isp_buffer *buffer;
- int restart = 0;
/* The CCDC generates VD0 interrupts even when disabled (the datasheet
* doesn't explicitly state if that's supposed to happen or not, so it
@@ -1500,30 +1594,31 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
* would thus not be enough, we need to handle the situation explicitly.
*/
if (list_empty(&ccdc->video_out.dmaqueue))
- goto done;
+ return 0;
/* We're in continuous mode, and memory writes were disabled due to a
* buffer underrun. Reenable them now that we have a buffer. The buffer
* address has been set in ccdc_video_queue.
*/
if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && ccdc->underrun) {
- restart = 1;
ccdc->underrun = 0;
- goto done;
+ return 1;
}
+ /* Wait for the CCDC to become idle. */
if (ccdc_sbl_wait_idle(ccdc, 1000)) {
dev_info(isp->dev, "CCDC won't become idle!\n");
isp->crashed |= 1U << ccdc->subdev.entity.id;
omap3isp_pipeline_cancel_stream(pipe);
- goto done;
+ return 0;
}
+ if (!ccdc_has_all_fields(ccdc))
+ return 1;
+
buffer = omap3isp_video_buffer_next(&ccdc->video_out);
- if (buffer != NULL) {
+ if (buffer != NULL)
ccdc_set_outaddr(ccdc, buffer->dma);
- restart = 1;
- }
pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
@@ -1532,8 +1627,7 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
omap3isp_pipeline_set_stream(pipe,
ISP_PIPELINE_STREAM_SINGLESHOT);
-done:
- return restart;
+ return buffer != NULL;
}
/*
@@ -1547,11 +1641,38 @@ static void ccdc_vd0_isr(struct isp_ccdc_device *ccdc)
unsigned long flags;
int restart = 0;
+ /* In BT.656 mode the CCDC doesn't generate an HS/VS interrupt. We thus
+ * need to increment the frame counter here.
+ */
+ if (ccdc->bt656) {
+ struct isp_pipeline *pipe =
+ to_isp_pipeline(&ccdc->subdev.entity);
+
+ atomic_inc(&pipe->frame_number);
+ }
+
+ /* Emulate a VD1 interrupt for BT.656 mode, as we can't stop the CCDC in
+ * the VD1 interrupt handler in that mode without risking a CCDC stall
+ * if a short frame is received.
+ */
+ if (ccdc->bt656) {
+ spin_lock_irqsave(&ccdc->lock, flags);
+ if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
+ ccdc->output & CCDC_OUTPUT_MEMORY) {
+ if (ccdc->lsc.state != LSC_STATE_STOPPED)
+ __ccdc_lsc_enable(ccdc, 0);
+ __ccdc_enable(ccdc, 0);
+ }
+ ccdc_handle_stopping(ccdc, CCDC_EVENT_VD1);
+ spin_unlock_irqrestore(&ccdc->lock, flags);
+ }
+
if (ccdc->output & CCDC_OUTPUT_MEMORY)
restart = ccdc_isr_buffer(ccdc);
spin_lock_irqsave(&ccdc->lock, flags);
- if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD0)) {
+
+ if (ccdc_handle_stopping(ccdc, CCDC_EVENT_VD0)) {
spin_unlock_irqrestore(&ccdc->lock, flags);
return;
}
@@ -1572,6 +1693,18 @@ static void ccdc_vd1_isr(struct isp_ccdc_device *ccdc)
{
unsigned long flags;
+ /* In BT.656 mode the synchronization signals are generated by the CCDC
+ * from the embedded sync codes. The VD0 and VD1 interrupts are thus
+ * only triggered when the CCDC is enabled, unlike external sync mode
+ * where the line counter runs even when the CCDC is stopped. We can't
+ * disable the CCDC at VD1 time, as no VD0 interrupt would be generated
+ * for a short frame, which would result in the CCDC being stopped and
+ * no VD interrupt generated anymore. The CCDC is stopped from the VD0
+ * interrupt handler instead for BT.656.
+ */
+ if (ccdc->bt656)
+ return;
+
spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
/*
@@ -1601,7 +1734,7 @@ static void ccdc_vd1_isr(struct isp_ccdc_device *ccdc)
break;
}
- if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD1))
+ if (ccdc_handle_stopping(ccdc, CCDC_EVENT_VD1))
goto done;
if (ccdc->lsc.request == NULL)
@@ -1656,6 +1789,8 @@ int omap3isp_ccdc_isr(struct isp_ccdc_device *ccdc, u32 events)
static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
{
struct isp_ccdc_device *ccdc = &video->isp->isp_ccdc;
+ unsigned long flags;
+ bool restart = false;
if (!(ccdc->output & CCDC_OUTPUT_MEMORY))
return -ENODEV;
@@ -1664,9 +1799,20 @@ static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
/* We now have a buffer queued on the output, restart the pipeline
* on the next CCDC interrupt if running in continuous mode (or when
- * starting the stream).
+ * starting the stream) in external sync mode, or immediately in BT.656
+ * sync mode as no CCDC interrupt is generated when the CCDC is stopped
+ * in that case.
*/
- ccdc->underrun = 1;
+ spin_lock_irqsave(&ccdc->lock, flags);
+ if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && !ccdc->running &&
+ ccdc->bt656)
+ restart = true;
+ else
+ ccdc->underrun = 1;
+ spin_unlock_irqrestore(&ccdc->lock, flags);
+
+ if (restart)
+ ccdc_enable(ccdc);
return 0;
}
@@ -1753,11 +1899,6 @@ static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
ccdc_configure(ccdc);
- /* TODO: Don't configure the video port if all of its output
- * links are inactive.
- */
- ccdc_config_vp(ccdc);
- ccdc_enable_vp(ccdc, 1);
ccdc_print_status(ccdc);
}
@@ -1830,6 +1971,7 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
unsigned int width = fmt->width;
unsigned int height = fmt->height;
struct v4l2_rect *crop;
+ enum v4l2_field field;
unsigned int i;
switch (pad) {
@@ -1846,14 +1988,24 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
/* Clamp the input size. */
fmt->width = clamp_t(u32, width, 32, 4096);
fmt->height = clamp_t(u32, height, 32, 4096);
+
+ /* Default to progressive field order. */
+ if (fmt->field == V4L2_FIELD_ANY)
+ fmt->field = V4L2_FIELD_NONE;
+
break;
case CCDC_PAD_SOURCE_OF:
pixelcode = fmt->code;
+ field = fmt->field;
*fmt = *__ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
- /* YUV formats are converted from 2X8 to 1X16 by the bridge and
- * can be byte-swapped.
+ /* In SYNC mode the bridge converts YUV formats from 2X8 to
+ * 1X16. In BT.656 no such conversion occurs. As we don't know
+ * at this point whether the source will use SYNC or BT.656 mode
+ * let's pretend the conversion always occurs. The CCDC will be
+ * configured to pack bytes in BT.656, hiding the inaccuracy.
+ * In all cases bytes can be swapped.
*/
if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
fmt->code == V4L2_MBUS_FMT_UYVY8_2X8) {
@@ -1874,6 +2026,17 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
crop = __ccdc_get_crop(ccdc, fh, which);
fmt->width = crop->width;
fmt->height = crop->height;
+
+ /* When input format is interlaced with alternating fields the
+ * CCDC can interleave the fields.
+ */
+ if (fmt->field == V4L2_FIELD_ALTERNATE &&
+ (field == V4L2_FIELD_INTERLACED_TB ||
+ field == V4L2_FIELD_INTERLACED_BT)) {
+ fmt->field = field;
+ fmt->height *= 2;
+ }
+
break;
case CCDC_PAD_SOURCE_VP:
@@ -1901,7 +2064,6 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
* stored on 2 bytes.
*/
fmt->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->field = V4L2_FIELD_NONE;
}
/*
diff --git a/drivers/media/platform/omap3isp/ispccdc.h b/drivers/media/platform/omap3isp/ispccdc.h
index f65061602c71..3440a7097940 100644
--- a/drivers/media/platform/omap3isp/ispccdc.h
+++ b/drivers/media/platform/omap3isp/ispccdc.h
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_CCDC_H
@@ -103,6 +93,10 @@ struct ispccdc_lsc {
#define CCDC_PAD_SOURCE_VP 2
#define CCDC_PADS_NUM 3
+#define CCDC_FIELD_TOP 1
+#define CCDC_FIELD_BOTTOM 2
+#define CCDC_FIELD_BOTH 3
+
/*
* struct isp_ccdc_device - Structure for the CCDC module to store its own
* information
@@ -123,11 +117,14 @@ struct ispccdc_lsc {
* @lsc: Lens shading compensation configuration
* @update: Bitmask of controls to update during the next interrupt
* @shadow_update: Controls update in progress by userspace
+ * @bt656: Whether the input interface uses BT.656 synchronization
+ * @fields: The fields (CCDC_FIELD_*) stored in the current buffer
* @underrun: A buffer underrun occurred and a new buffer has been queued
* @state: Streaming state
* @lock: Serializes shadow_update with interrupt handler
* @wait: Wait queue used to stop the module
* @stopping: Stopping state
+ * @running: Is the CCDC hardware running
* @ioctl_lock: Serializes ioctl calls and LSC requests freeing
*/
struct isp_ccdc_device {
@@ -151,11 +148,15 @@ struct isp_ccdc_device {
unsigned int update;
unsigned int shadow_update;
+ bool bt656;
+ unsigned int fields;
+
unsigned int underrun:1;
enum isp_pipeline_stream_state state;
spinlock_t lock;
wait_queue_head_t wait;
unsigned int stopping;
+ bool running;
struct mutex ioctl_lock;
};
diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c
index f3801db9095c..9cb49b3c04bd 100644
--- a/drivers/media/platform/omap3isp/ispccp2.c
+++ b/drivers/media/platform/omap3isp/ispccp2.c
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <linux/delay.h>
diff --git a/drivers/media/platform/omap3isp/ispccp2.h b/drivers/media/platform/omap3isp/ispccp2.h
index 76d65f4576ef..4662bffa79e3 100644
--- a/drivers/media/platform/omap3isp/ispccp2.h
+++ b/drivers/media/platform/omap3isp/ispccp2.h
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_CCP2_H
diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c
index 5a2e47e58b84..6530b255f103 100644
--- a/drivers/media/platform/omap3isp/ispcsi2.c
+++ b/drivers/media/platform/omap3isp/ispcsi2.c
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <linux/delay.h>
#include <media/v4l2-common.h>
diff --git a/drivers/media/platform/omap3isp/ispcsi2.h b/drivers/media/platform/omap3isp/ispcsi2.h
index c57729b7e86e..453ed62fe394 100644
--- a/drivers/media/platform/omap3isp/ispcsi2.h
+++ b/drivers/media/platform/omap3isp/ispcsi2.h
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_CSI2_H
diff --git a/drivers/media/platform/omap3isp/ispcsiphy.c b/drivers/media/platform/omap3isp/ispcsiphy.c
index c09de32f986a..e033f2237a72 100644
--- a/drivers/media/platform/omap3isp/ispcsiphy.c
+++ b/drivers/media/platform/omap3isp/ispcsiphy.c
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <linux/delay.h>
diff --git a/drivers/media/platform/omap3isp/ispcsiphy.h b/drivers/media/platform/omap3isp/ispcsiphy.h
index 14551fd77697..e17c88beab92 100644
--- a/drivers/media/platform/omap3isp/ispcsiphy.h
+++ b/drivers/media/platform/omap3isp/ispcsiphy.h
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_CSI_PHY_H
diff --git a/drivers/media/platform/omap3isp/isph3a.h b/drivers/media/platform/omap3isp/isph3a.h
index fb09fd4ca755..e5b28d0f3b0f 100644
--- a/drivers/media/platform/omap3isp/isph3a.h
+++ b/drivers/media/platform/omap3isp/isph3a.h
@@ -13,16 +13,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_H3A_H
diff --git a/drivers/media/platform/omap3isp/isph3a_aewb.c b/drivers/media/platform/omap3isp/isph3a_aewb.c
index d6811ce263eb..b208c5417146 100644
--- a/drivers/media/platform/omap3isp/isph3a_aewb.c
+++ b/drivers/media/platform/omap3isp/isph3a_aewb.c
@@ -13,16 +13,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <linux/slab.h>
diff --git a/drivers/media/platform/omap3isp/isph3a_af.c b/drivers/media/platform/omap3isp/isph3a_af.c
index 6fc960cd30f5..8a83e195f3e3 100644
--- a/drivers/media/platform/omap3isp/isph3a_af.c
+++ b/drivers/media/platform/omap3isp/isph3a_af.c
@@ -13,16 +13,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
/* Linux specific include files */
diff --git a/drivers/media/platform/omap3isp/isphist.c b/drivers/media/platform/omap3isp/isphist.c
index 06a5f8164eaa..ce822c34c843 100644
--- a/drivers/media/platform/omap3isp/isphist.c
+++ b/drivers/media/platform/omap3isp/isphist.c
@@ -13,16 +13,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <linux/delay.h>
diff --git a/drivers/media/platform/omap3isp/isphist.h b/drivers/media/platform/omap3isp/isphist.h
index 0b2a38ec94c4..3b5415517dcd 100644
--- a/drivers/media/platform/omap3isp/isphist.h
+++ b/drivers/media/platform/omap3isp/isphist.h
@@ -13,16 +13,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_HIST_H
diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c
index 720809b07e75..605f57ef0a49 100644
--- a/drivers/media/platform/omap3isp/isppreview.c
+++ b/drivers/media/platform/omap3isp/isppreview.c
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <linux/device.h>
diff --git a/drivers/media/platform/omap3isp/isppreview.h b/drivers/media/platform/omap3isp/isppreview.h
index f66923407f8c..16fdc03a3d43 100644
--- a/drivers/media/platform/omap3isp/isppreview.h
+++ b/drivers/media/platform/omap3isp/isppreview.h
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_PREVIEW_H
diff --git a/drivers/media/platform/omap3isp/ispreg.h b/drivers/media/platform/omap3isp/ispreg.h
index b7d90e6fb01d..b5ea8da0b904 100644
--- a/drivers/media/platform/omap3isp/ispreg.h
+++ b/drivers/media/platform/omap3isp/ispreg.h
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_REG_H
@@ -740,17 +730,13 @@
#define ISPCCDC_HSIZE_OFF_SHIFT 0
-#define ISPCCDC_SDOFST_FINV (1 << 14)
-#define ISPCCDC_SDOFST_FOFST_1L 0
-#define ISPCCDC_SDOFST_FOFST_4L (3 << 12)
+#define ISPCCDC_SDOFST_FIINV (1 << 14)
+#define ISPCCDC_SDOFST_FOFST_SHIFT 12
+#define ISPCCDC_SDOFST_FOFST_MASK (3 << 12)
#define ISPCCDC_SDOFST_LOFST3_SHIFT 0
#define ISPCCDC_SDOFST_LOFST2_SHIFT 3
#define ISPCCDC_SDOFST_LOFST1_SHIFT 6
#define ISPCCDC_SDOFST_LOFST0_SHIFT 9
-#define EVENEVEN 1
-#define ODDEVEN 2
-#define EVENODD 3
-#define ODDODD 4
#define ISPCCDC_CLAMP_OBGAIN_SHIFT 0
#define ISPCCDC_CLAMP_OBST_SHIFT 10
diff --git a/drivers/media/platform/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c
index 6f077c2377db..05d1ace57451 100644
--- a/drivers/media/platform/omap3isp/ispresizer.c
+++ b/drivers/media/platform/omap3isp/ispresizer.c
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <linux/device.h>
@@ -239,7 +229,7 @@ static void resizer_set_phase(struct isp_res_device *res, u32 h_phase,
u32 v_phase)
{
struct isp_device *isp = to_isp_device(res);
- u32 rgval = 0;
+ u32 rgval;
rgval = isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK);
@@ -275,7 +265,7 @@ static void resizer_set_luma(struct isp_res_device *res,
struct resizer_luma_yenh *luma)
{
struct isp_device *isp = to_isp_device(res);
- u32 rgval = 0;
+ u32 rgval;
rgval = (luma->algo << ISPRSZ_YENH_ALGO_SHIFT)
& ISPRSZ_YENH_ALGO_MASK;
@@ -322,7 +312,7 @@ static void resizer_set_ratio(struct isp_res_device *res,
{
struct isp_device *isp = to_isp_device(res);
const u16 *h_filter, *v_filter;
- u32 rgval = 0;
+ u32 rgval;
rgval = isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK);
@@ -365,9 +355,8 @@ static void resizer_set_output_size(struct isp_res_device *res,
u32 width, u32 height)
{
struct isp_device *isp = to_isp_device(res);
- u32 rgval = 0;
+ u32 rgval;
- dev_dbg(isp->dev, "Output size[w/h]: %dx%d\n", width, height);
rgval = (width << ISPRSZ_OUT_SIZE_HORZ_SHIFT)
& ISPRSZ_OUT_SIZE_HORZ_MASK;
rgval |= (height << ISPRSZ_OUT_SIZE_VERT_SHIFT)
@@ -409,7 +398,7 @@ static void resizer_set_output_offset(struct isp_res_device *res, u32 offset)
static void resizer_set_start(struct isp_res_device *res, u32 left, u32 top)
{
struct isp_device *isp = to_isp_device(res);
- u32 rgval = 0;
+ u32 rgval;
rgval = (left << ISPRSZ_IN_START_HORZ_ST_SHIFT)
& ISPRSZ_IN_START_HORZ_ST_MASK;
@@ -429,9 +418,7 @@ static void resizer_set_input_size(struct isp_res_device *res,
u32 width, u32 height)
{
struct isp_device *isp = to_isp_device(res);
- u32 rgval = 0;
-
- dev_dbg(isp->dev, "Input size[w/h]: %dx%d\n", width, height);
+ u32 rgval;
rgval = (width << ISPRSZ_IN_SIZE_HORZ_SHIFT)
& ISPRSZ_IN_SIZE_HORZ_MASK;
@@ -1075,10 +1062,13 @@ static void resizer_isr_buffer(struct isp_res_device *res)
void omap3isp_resizer_isr(struct isp_res_device *res)
{
struct v4l2_mbus_framefmt *informat, *outformat;
+ unsigned long flags;
if (omap3isp_module_sync_is_stopping(&res->wait, &res->stopping))
return;
+ spin_lock_irqsave(&res->lock, flags);
+
if (res->applycrop) {
outformat = __resizer_get_format(res, NULL, RESZ_PAD_SOURCE,
V4L2_SUBDEV_FORMAT_ACTIVE);
@@ -1088,6 +1078,8 @@ void omap3isp_resizer_isr(struct isp_res_device *res)
res->applycrop = 0;
}
+ spin_unlock_irqrestore(&res->lock, flags);
+
resizer_isr_buffer(res);
}
@@ -1290,8 +1282,10 @@ static int resizer_set_selection(struct v4l2_subdev *sd,
{
struct isp_res_device *res = v4l2_get_subdevdata(sd);
struct isp_device *isp = to_isp_device(res);
- struct v4l2_mbus_framefmt *format_sink, *format_source;
+ const struct v4l2_mbus_framefmt *format_sink;
+ struct v4l2_mbus_framefmt format_source;
struct resizer_ratio ratio;
+ unsigned long flags;
if (sel->target != V4L2_SEL_TGT_CROP ||
sel->pad != RESZ_PAD_SINK)
@@ -1299,16 +1293,14 @@ static int resizer_set_selection(struct v4l2_subdev *sd,
format_sink = __resizer_get_format(res, fh, RESZ_PAD_SINK,
sel->which);
- format_source = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
- sel->which);
-
- dev_dbg(isp->dev, "%s: L=%d,T=%d,W=%d,H=%d,which=%d\n", __func__,
- sel->r.left, sel->r.top, sel->r.width, sel->r.height,
- sel->which);
+ format_source = *__resizer_get_format(res, fh, RESZ_PAD_SOURCE,
+ sel->which);
- dev_dbg(isp->dev, "%s: input=%dx%d, output=%dx%d\n", __func__,
+ dev_dbg(isp->dev, "%s(%s): req %ux%u -> (%d,%d)/%ux%u -> %ux%u\n",
+ __func__, sel->which == V4L2_SUBDEV_FORMAT_TRY ? "try" : "act",
format_sink->width, format_sink->height,
- format_source->width, format_source->height);
+ sel->r.left, sel->r.top, sel->r.width, sel->r.height,
+ format_source.width, format_source.height);
/* Clamp the crop rectangle to the bounds, and then mangle it further to
* fulfill the TRM equations. Store the clamped but otherwise unmangled
@@ -1318,23 +1310,39 @@ static int resizer_set_selection(struct v4l2_subdev *sd,
* smaller input crop rectangle every time the output size is set if we
* stored the mangled rectangle.
*/
- resizer_try_crop(format_sink, format_source, &sel->r);
+ resizer_try_crop(format_sink, &format_source, &sel->r);
*__resizer_get_crop(res, fh, sel->which) = sel->r;
- resizer_calc_ratios(res, &sel->r, format_source, &ratio);
+ resizer_calc_ratios(res, &sel->r, &format_source, &ratio);
- if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
+ dev_dbg(isp->dev, "%s(%s): got %ux%u -> (%d,%d)/%ux%u -> %ux%u\n",
+ __func__, sel->which == V4L2_SUBDEV_FORMAT_TRY ? "try" : "act",
+ format_sink->width, format_sink->height,
+ sel->r.left, sel->r.top, sel->r.width, sel->r.height,
+ format_source.width, format_source.height);
+
+ if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
+ *__resizer_get_format(res, fh, RESZ_PAD_SOURCE, sel->which) =
+ format_source;
return 0;
+ }
+
+ /* Update the source format, resizing ratios and crop rectangle. If
+ * streaming is on the IRQ handler will reprogram the resizer after the
+ * current frame. We thus we need to protect against race conditions.
+ */
+ spin_lock_irqsave(&res->lock, flags);
+
+ *__resizer_get_format(res, fh, RESZ_PAD_SOURCE, sel->which) =
+ format_source;
res->ratio = ratio;
res->crop.active = sel->r;
- /*
- * set_selection can be called while streaming is on. In this case the
- * crop values will be set in the next IRQ.
- */
if (res->state != ISP_PIPELINE_STREAM_STOPPED)
res->applycrop = 1;
+ spin_unlock_irqrestore(&res->lock, flags);
+
return 0;
}
@@ -1781,6 +1789,8 @@ int omap3isp_resizer_init(struct isp_device *isp)
init_waitqueue_head(&res->wait);
atomic_set(&res->stopping, 0);
+ spin_lock_init(&res->lock);
+
return resizer_init_entities(res);
}
diff --git a/drivers/media/platform/omap3isp/ispresizer.h b/drivers/media/platform/omap3isp/ispresizer.h
index 9b01e9047c15..5414542912e2 100644
--- a/drivers/media/platform/omap3isp/ispresizer.h
+++ b/drivers/media/platform/omap3isp/ispresizer.h
@@ -12,21 +12,12 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_RESIZER_H
#define OMAP3_ISP_RESIZER_H
+#include <linux/spinlock.h>
#include <linux/types.h>
/*
@@ -96,6 +87,7 @@ enum resizer_input_entity {
/*
* struct isp_res_device - OMAP3 ISP resizer module
+ * @lock: Protects formats and crop rectangles between set_selection and IRQ
* @crop.request: Crop rectangle requested by the user
* @crop.active: Active crop rectangle (based on hardware requirements)
*/
@@ -116,6 +108,7 @@ struct isp_res_device {
enum isp_pipeline_stream_state state;
wait_queue_head_t wait;
atomic_t stopping;
+ spinlock_t lock;
struct {
struct v4l2_rect request;
diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index e6cbc1eaf4ca..a94e8340508f 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -13,16 +13,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <linux/dma-mapping.h>
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index 58d6ac7cb664..b32b29677e2c 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -13,16 +13,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_STAT_H
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index e36bac26476c..bc38c88c7bd9 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -11,16 +11,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#include <asm/cacheflush.h>
@@ -319,10 +309,11 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
vfh->format.fmt.pix.height != format.fmt.pix.height ||
vfh->format.fmt.pix.width != format.fmt.pix.width ||
vfh->format.fmt.pix.bytesperline != format.fmt.pix.bytesperline ||
- vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage)
+ vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage ||
+ vfh->format.fmt.pix.field != format.fmt.pix.field)
return -EINVAL;
- return ret;
+ return 0;
}
/* -----------------------------------------------------------------------------
@@ -491,6 +482,11 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
else
buf->vb.v4l2_buf.sequence = atomic_read(&pipe->frame_number);
+ if (pipe->field != V4L2_FIELD_NONE)
+ buf->vb.v4l2_buf.sequence /= 2;
+
+ buf->vb.v4l2_buf.field = pipe->field;
+
/* Report pipeline errors to userspace on the capture device side. */
if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
state = VB2_BUF_STATE_ERROR;
@@ -641,7 +637,40 @@ isp_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
if (format->type != video->type)
return -EINVAL;
- mutex_lock(&video->mutex);
+ /* Replace unsupported field orders with sane defaults. */
+ switch (format->fmt.pix.field) {
+ case V4L2_FIELD_NONE:
+ /* Progressive is supported everywhere. */
+ break;
+ case V4L2_FIELD_ALTERNATE:
+ /* ALTERNATE is not supported on output nodes. */
+ if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ format->fmt.pix.field = V4L2_FIELD_NONE;
+ break;
+ case V4L2_FIELD_INTERLACED:
+ /* The ISP has no concept of video standard, select the
+ * top-bottom order when the unqualified interlaced order is
+ * requested.
+ */
+ format->fmt.pix.field = V4L2_FIELD_INTERLACED_TB;
+ /* Fall-through */
+ case V4L2_FIELD_INTERLACED_TB:
+ case V4L2_FIELD_INTERLACED_BT:
+ /* Interlaced orders are only supported at the CCDC output. */
+ if (video != &video->isp->isp_ccdc.video_out)
+ format->fmt.pix.field = V4L2_FIELD_NONE;
+ break;
+ case V4L2_FIELD_TOP:
+ case V4L2_FIELD_BOTTOM:
+ case V4L2_FIELD_SEQ_TB:
+ case V4L2_FIELD_SEQ_BT:
+ default:
+ /* All other field orders are currently unsupported, default to
+ * progressive.
+ */
+ format->fmt.pix.field = V4L2_FIELD_NONE;
+ break;
+ }
/* Fill the bytesperline and sizeimage fields by converting to media bus
* format and back to pixel format.
@@ -649,9 +678,10 @@ isp_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
isp_video_pix_to_mbus(&format->fmt.pix, &fmt);
isp_video_mbus_to_pix(video, &fmt, &format->fmt.pix);
+ mutex_lock(&video->mutex);
vfh->format = *format;
-
mutex_unlock(&video->mutex);
+
return 0;
}
@@ -1039,6 +1069,7 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
video->queue = &vfh->queue;
INIT_LIST_HEAD(&video->dmaqueue);
atomic_set(&pipe->frame_number, -1);
+ pipe->field = vfh->format.fmt.pix.field;
mutex_lock(&video->queue_lock);
ret = vb2_streamon(&vfh->queue, type);
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 7d2e82122ecd..0b7efedc3da9 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -11,16 +11,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
#ifndef OMAP3_ISP_VIDEO_H
@@ -88,6 +78,7 @@ enum isp_pipeline_state {
/*
* struct isp_pipeline - An ISP hardware pipeline
+ * @field: The field being processed by the pipeline
* @error: A hardware error occurred during capture
* @entities: Bitmask of entities in the pipeline (indexed by entity ID)
*/
@@ -101,6 +92,7 @@ struct isp_pipeline {
u32 entities;
unsigned long l3_ick;
unsigned int max_rate;
+ enum v4l2_field field;
atomic_t frame_number;
bool do_propagation; /* of frame number */
bool error;
diff --git a/drivers/media/platform/omap3isp/luma_enhance_table.h b/drivers/media/platform/omap3isp/luma_enhance_table.h
index 098b45e2280f..81c5b1566469 100644
--- a/drivers/media/platform/omap3isp/luma_enhance_table.h
+++ b/drivers/media/platform/omap3isp/luma_enhance_table.h
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552,
diff --git a/drivers/media/platform/omap3isp/noise_filter_table.h b/drivers/media/platform/omap3isp/noise_filter_table.h
index d50451a4a242..5073f9847937 100644
--- a/drivers/media/platform/omap3isp/noise_filter_table.h
+++ b/drivers/media/platform/omap3isp/noise_filter_table.h
@@ -12,16 +12,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
*/
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,