old mode 100644
new mode 100755
@@ -191,6 +191,7 @@ struct isp_sgdma ispsg;
* @resizer_input_height: ISP Resizer module input image height.
* @resizer_output_width: ISP Resizer module output image width.
* @resizer_output_height: ISP Resizer module output image height.
+ * @current_field: Current field for interlaced capture.
*/
struct ispmodule {
unsigned int isp_pipeline;
@@ -209,6 +210,7 @@ struct ispmodule {
unsigned int resizer_input_height;
unsigned int resizer_output_width;
unsigned int resizer_output_height;
+ int current_field;
};
static struct ispmodule ispmodule_obj = {
@@ -224,11 +226,14 @@ static struct ispmodule ispmodule_obj = {
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 0,
},
+ .current_field = 0,
};
/* Structure for saving/restoring ISP module registers */
static struct isp_reg isp_reg_list[] = {
{ISP_SYSCONFIG, 0},
+ {ISP_IRQ0ENABLE, 0},
+ {ISP_IRQ1ENABLE, 0},
{ISP_TCTRL_GRESET_LENGTH, 0},
{ISP_TCTRL_PSTRB_REPLAY, 0},
{ISP_CTRL, 0},
@@ -550,6 +555,11 @@ EXPORT_SYMBOL(isp_unset_callback);
**/
int isp_request_interface(enum isp_interface_type if_t)
{
+ enum isp_interface_type temp_if_t = if_t;
+
+ if (if_t == ISP_PARLL_YUV_BT)
+ if_t = ISP_PARLL;
+
if (isp_obj.if_status & if_t) {
DPRINTK_ISPCTRL("ISP_ERR : Requested Interface already \
allocated\n");
@@ -569,7 +579,7 @@ int isp_request_interface(enum isp_interface_type if_t)
((isp_obj.if_status == ISP_CSIB) &&
(if_t == ISP_CSIA)) ||
(isp_obj.if_status == 0)) {
- isp_obj.if_status |= if_t;
+ isp_obj.if_status |= (if_t | temp_if_t);
return 0;
} else {
DPRINTK_ISPCTRL("ISP_ERR : Invalid Combination Serial- \
@@ -587,6 +597,9 @@ EXPORT_SYMBOL(isp_request_interface);
**/
int isp_free_interface(enum isp_interface_type if_t)
{
+ if ((if_t == ISP_PARLL) || (if_t == ISP_PARLL_YUV_BT))
+ if_t |= (ISP_PARLL | ISP_PARLL_YUV_BT);
+
isp_obj.if_status &= ~if_t;
return 0;
}
@@ -888,6 +901,7 @@ int isp_configure_interface(struct isp_interface_config *config)
ispctrl_val &= (ISPCTRL_PAR_SER_CLK_SEL_MASK);
switch (config->ccdc_par_ser) {
case ISP_PARLL:
+ case ISP_PARLL_YUV_BT:
ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
ispctrl_val |= (config->u.par.par_clk_pol
<< ISPCTRL_PAR_CLK_POL_SHIFT);
@@ -1122,6 +1136,11 @@ out:
omap_writel(irqstatus, ISP_IRQ0STATUS);
spin_unlock_irqrestore(&isp_obj.lock, irqflags);
+ /* TODO: Workaround suggested by Tony for spurious
+ * interrupt issue
+ */
+ irqstatus = omap_readl(ISP_IRQ0STATUS);
+
if (is_irqhandled)
return IRQ_HANDLED;
else
@@ -1345,9 +1364,14 @@ u32 isp_calc_pipeline(struct v4l2_pix_format *pix_input,
ispccdc_request();
if (pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10)
ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP_MEM);
- else
- ispccdc_config_datapath(CCDC_YUV_SYNC,
- CCDC_OTHERS_MEM);
+ else {
+ if (isp_obj.if_status & ISP_PARLL_YUV_BT)
+ ispccdc_config_datapath(CCDC_YUV_BT,
+ CCDC_OTHERS_MEM);
+ else
+ ispccdc_config_datapath(CCDC_YUV_SYNC,
+ CCDC_OTHERS_MEM);
+ }
}
return 0;
}
@@ -1381,6 +1405,31 @@ void isp_config_pipeline(struct v4l2_pix_format *pix_input,
ispmodule_obj.resizer_output_width,
ispmodule_obj.resizer_output_height);
}
+ if (pix_input->pixelformat == V4L2_PIX_FMT_UYVY)
+ ispccdc_config_y8pos(Y8POS_ODD);
+ else if (pix_input->pixelformat == V4L2_PIX_FMT_YUYV)
+ ispccdc_config_y8pos(Y8POS_EVEN);
+
+ if (((pix_input->pixelformat == V4L2_PIX_FMT_UYVY) &&
+ (pix_output->pixelformat == V4L2_PIX_FMT_UYVY)) ||
+ ((pix_input->pixelformat == V4L2_PIX_FMT_YUYV) &&
+ (pix_output->pixelformat == V4L2_PIX_FMT_YUYV)))
+ /* input and output formats are in same order */
+ ispccdc_config_byteswap(0);
+ else if (((pix_input->pixelformat == V4L2_PIX_FMT_YUYV) &&
+ (pix_output->pixelformat == V4L2_PIX_FMT_UYVY)) ||
+ ((pix_input->pixelformat == V4L2_PIX_FMT_UYVY) &&
+ (pix_output->pixelformat == V4L2_PIX_FMT_YUYV)))
+ /* input and output formats are in reverse order */
+ ispccdc_config_byteswap(1);
+
+ /*
+ * Configure Pitch - This enables application to use a different pitch
+ * other than active pixels per line.
+ */
+ if (isp_obj.if_status & ISP_PARLL_YUV_BT)
+ ispccdc_config_outlineoffset(ispmodule_obj.pix.bytesperline,
+ 0, 0);
if (pix_output->pixelformat == V4L2_PIX_FMT_UYVY) {
isppreview_config_ycpos(YCPOS_YCrYCb);
@@ -1407,9 +1456,20 @@ void isp_vbq_done(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2)
int notify = 0;
int rval = 0;
unsigned long flags;
+ unsigned long fld_stat = (omap_readl(ISPCCDC_SYN_MODE) >> 15) & 0x1;
switch (status) {
case CCDC_VD0:
+ if (ispmodule_obj.pix.field == V4L2_FIELD_INTERLACED) {
+ spin_lock(&isp_obj.isp_temp_buf_lock);
+ /* Skip even fields */
+ if (ispmodule_obj.current_field == 0) {
+ spin_unlock(&isp_obj.isp_temp_buf_lock);
+ return;
+ }
+ spin_unlock(&isp_obj.isp_temp_buf_lock);
+ }
+
ispccdc_config_shadow_registers();
if ((ispmodule_obj.isp_pipeline & OMAP_ISP_RESIZER) ||
(ispmodule_obj.isp_pipeline & OMAP_ISP_PREVIEW))
@@ -1427,6 +1487,15 @@ void isp_vbq_done(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2)
}
break;
case CCDC_VD1:
+ if (ispmodule_obj.pix.field == V4L2_FIELD_INTERLACED) {
+ spin_lock(&isp_obj.isp_temp_buf_lock);
+ if (ispmodule_obj.current_field == 0) {
+ spin_unlock(&isp_obj.isp_temp_buf_lock);
+ return;
+ }
+ spin_unlock(&isp_obj.isp_temp_buf_lock);
+ }
+
if ((ispmodule_obj.isp_pipeline & OMAP_ISP_RESIZER) ||
(ispmodule_obj.isp_pipeline & OMAP_ISP_PREVIEW))
return;
@@ -1472,13 +1541,26 @@ void isp_vbq_done(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2)
}
break;
case HS_VS:
- spin_lock(&isp_obj.isp_temp_buf_lock);
- if (ispmodule_obj.isp_temp_state == ISP_BUF_TRAN) {
- isp_CCDC_VD01_enable();
- ispmodule_obj.isp_temp_state = ISP_BUF_INIT;
+ if (ispmodule_obj.pix.field == V4L2_FIELD_INTERLACED) {
+ ispmodule_obj.current_field ^= 1;
+ spin_lock(&isp_obj.isp_temp_buf_lock);
+ if ((ispmodule_obj.isp_temp_state == ISP_BUF_TRAN) &&
+ (fld_stat == 1)) {
+ isp_CCDC_VD01_enable();
+ ispmodule_obj.current_field = fld_stat;
+ ispmodule_obj.isp_temp_state = ISP_BUF_INIT;
+ }
+ spin_unlock(&isp_obj.isp_temp_buf_lock);
+ return;
+ } else {
+ spin_lock(&isp_obj.isp_temp_buf_lock);
+ if (ispmodule_obj.isp_temp_state == ISP_BUF_TRAN) {
+ isp_CCDC_VD01_enable();
+ ispmodule_obj.isp_temp_state = ISP_BUF_INIT;
+ }
+ spin_unlock(&isp_obj.isp_temp_buf_lock);
+ return;
}
- spin_unlock(&isp_obj.isp_temp_buf_lock);
- return;
default:
return;
}
@@ -2200,15 +2282,25 @@ int isp_try_fmt(struct v4l2_pix_format *pix_input,
if (ifmt == NUM_ISP_CAPTURE_FORMATS)
ifmt = 1;
pix_output->pixelformat = isp_formats[ifmt].pixelformat;
- pix_output->field = V4L2_FIELD_NONE;
- pix_output->bytesperline = pix_output->width * ISP_BYTES_PER_PIXEL;
+
+ if (isp_obj.if_status & ISP_PARLL_YUV_BT)
+ pix_output->field = pix_input->field;
+ else {
+ pix_output->field = V4L2_FIELD_NONE;
+ pix_output->bytesperline =
+ pix_output->width * ISP_BYTES_PER_PIXEL;
+ }
+
pix_output->sizeimage =
PAGE_ALIGN(pix_output->bytesperline * pix_output->height);
pix_output->priv = 0;
switch (pix_output->pixelformat) {
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_UYVY:
- pix_output->colorspace = V4L2_COLORSPACE_JPEG;
+ if (isp_obj.if_status & ISP_PARLL_YUV_BT)
+ pix_output->colorspace = pix_input->colorspace;
+ else
+ pix_output->colorspace = V4L2_COLORSPACE_JPEG;
break;
default:
pix_output->colorspace = V4L2_COLORSPACE_SRGB;
@@ -73,7 +73,8 @@ typedef void (*isp_callback_t) (unsigned long status,
enum isp_interface_type {
ISP_PARLL = 1,
ISP_CSIA = 2,
- ISP_CSIB = 4
+ ISP_CSIB = 4,
+ ISP_PARLL_YUV_BT = 8
};
enum isp_irqevents {
@@ -302,6 +303,10 @@ int isp_try_size(struct v4l2_pix_format *pix_input,
int isp_try_fmt(struct v4l2_pix_format *pix_input,
struct v4l2_pix_format *pix_output);
+int isp_configure_std(struct v4l2_pix_format *fmt);
+
+int isp_check_format(struct v4l2_pix_format *pixfmt);
+
int isp_handle_private(int cmd, void *arg);
void isp_save_context(struct isp_reg *);
@@ -566,9 +566,17 @@ int ispccdc_config_datapath(enum ccdc_input input, enum ccdc_output output)
syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
syn_mode |= ISPCCDC_SYN_MODE_WEN;
- syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
- omap_writel((omap_readl(ISPCCDC_CFG)) & ~ISPCCDC_CFG_WENLOG,
- ISPCCDC_CFG);
+ if (input != CCDC_YUV_BT) {
+ syn_mode |= ISPCCDC_SYN_MODE_EXWEN;
+ omap_writel((omap_readl(ISPCCDC_CFG)) |
+ ISPCCDC_CFG_WENLOG,
+ ISPCCDC_CFG);
+ } else {
+ syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
+ omap_writel((omap_readl(ISPCCDC_CFG)) &
+ ~ISPCCDC_CFG_WENLOG,
+ ISPCCDC_CFG);
+ }
vpcfg.bitshift_sel = BIT11_2;
vpcfg.freq_sel = PIXCLKBY2;
ispccdc_config_vp(vpcfg);
@@ -627,12 +635,28 @@ int ispccdc_config_datapath(enum ccdc_input input, enum ccdc_output output)
syncif.hdpol = 0;
syncif.ipmod = YUV16;
syncif.vdpol = 0;
+ syncif.bt_r656_en = 0;
ispccdc_config_imgattr(0);
ispccdc_config_sync_if(syncif);
blkcfg.dcsubval = 0;
ispccdc_config_black_clamp(blkcfg);
break;
case CCDC_YUV_BT:
+ syncif.ccdc_mastermode = 0;
+ syncif.datapol = 0;
+ syncif.datsz = DAT8;
+ syncif.fldmode = 1;
+ syncif.fldout = 0;
+ syncif.fldpol = 0;
+ syncif.fldstat = 0;
+ syncif.hdpol = 0;
+ syncif.ipmod = YUV8;
+ syncif.vdpol = 1;
+ syncif.bt_r656_en = 1;
+ ispccdc_config_imgattr(0);
+ ispccdc_config_sync_if(syncif);
+ blkcfg.dcsubval = 0;
+ ispccdc_config_black_clamp(blkcfg);
break;
case CCDC_OTHERS:
break;
@@ -677,6 +701,8 @@ void ispccdc_config_sync_if(struct ispccdc_syncif syncif)
break;
case YUV8:
syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
+ if (syncif.bt_r656_en)
+ syn_mode |= ISPCCDC_SYN_MODE_PACK8;
break;
};
@@ -741,6 +767,11 @@ void ispccdc_config_sync_if(struct ispccdc_syncif syncif)
omap_writel((omap_readl(ISPCCDC_REC656IF)) &
~ISPCCDC_REC656IF_R656ON,
ISPCCDC_REC656IF);
+ } else {
+ omap_writel((omap_readl(ISPCCDC_REC656IF)) |
+ (ISPCCDC_REC656IF_R656ON |
+ ISPCCDC_REC656IF_ECCFVH),
+ ISPCCDC_REC656IF);
}
}
EXPORT_SYMBOL(ispccdc_config_sync_if);
@@ -1178,35 +1209,72 @@ int ispccdc_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h)
} else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM) {
omap_writel(0, ISPCCDC_VP_OUT);
if (cpu_is_omap3410()) {
- omap_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
+ if (ispccdc_obj.ccdc_inpfmt != CCDC_YUV_BT)
+ omap_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
((ispccdc_obj.ccdcout_w - 1) <<
- ISPCCDC_HORZ_INFO_NPH_SHIFT),
+ ISPCCDC_HORZ_INFO_NPH_SHIFT),
ISPCCDC_HORZ_INFO);
+ else
+ omap_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
+ (((ispccdc_obj.ccdcout_w << 1) - 1) <<
+ ISPCCDC_HORZ_INFO_NPH_SHIFT),
+ ISPCCDC_HORZ_INFO);
} else {
- if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) {
- omap_writel(1 << ISPCCDC_HORZ_INFO_SPH_SHIFT
- | ((ispccdc_obj.ccdcout_w - 1)
- << ISPCCDC_HORZ_INFO_NPH_SHIFT),
- ISPCCDC_HORZ_INFO);
- } else {
- omap_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT
- | ((ispccdc_obj.ccdcout_w - 1)
- << ISPCCDC_HORZ_INFO_NPH_SHIFT),
- ISPCCDC_HORZ_INFO);
- }
+ if (ispccdc_obj.ccdc_inpfmt != CCDC_YUV_BT)
+ omap_writel(1 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
+ ((ispccdc_obj.ccdcout_w - 1) <<
+ ISPCCDC_HORZ_INFO_NPH_SHIFT),
+ ISPCCDC_HORZ_INFO);
+ else
+ omap_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
+ (((ispccdc_obj.ccdcout_w << 1) - 1) <<
+ ISPCCDC_HORZ_INFO_NPH_SHIFT),
+ ISPCCDC_HORZ_INFO);
+ }
+
+ if (ispccdc_obj.ccdc_inpfmt != CCDC_YUV_BT) {
+ omap_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
+ ISPCCDC_VERT_START);
+ omap_writel((ispccdc_obj.ccdcout_h - 1) <<
+ ISPCCDC_VERT_LINES_NLV_SHIFT,
+ ISPCCDC_VERT_LINES);
+ } else {
+ omap_writel(2 << ISPCCDC_VERT_START_SLV0_SHIFT |
+ 2 << ISPCCDC_VERT_START_SLV1_SHIFT,
+ ISPCCDC_VERT_START);
+ omap_writel(((ispccdc_obj.ccdcout_h >> 1) - 1) <<
+ ISPCCDC_VERT_LINES_NLV_SHIFT,
+ ISPCCDC_VERT_LINES);
}
- omap_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
- ISPCCDC_VERT_START);
- omap_writel((ispccdc_obj.ccdcout_h - 1) <<
- ISPCCDC_VERT_LINES_NLV_SHIFT,
- ISPCCDC_VERT_LINES);
ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0);
- omap_writel((((ispccdc_obj.ccdcout_h - 2) &
+
+ if (ispccdc_obj.ccdc_inpfmt != CCDC_YUV_BT) {
+ omap_writel((((ispccdc_obj.ccdcout_h - 1) &
ISPCCDC_VDINT_0_MASK) <<
ISPCCDC_VDINT_0_SHIFT) |
((50 & ISPCCDC_VDINT_1_MASK) <<
ISPCCDC_VDINT_1_SHIFT), ISPCCDC_VDINT);
+ } else {
+ ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2,
+ EVENEVEN,
+ 1);
+ ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2,
+ ODDEVEN,
+ 1);
+ ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2,
+ EVENODD,
+ 1);
+ ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2,
+ ODDODD,
+ 1);
+
+ omap_writel(((((ispccdc_obj.ccdcout_h >> 1) - 1) &
+ ISPCCDC_VDINT_0_MASK) <<
+ ISPCCDC_VDINT_0_SHIFT) |
+ ((50 & ISPCCDC_VDINT_1_MASK) <<
+ ISPCCDC_VDINT_1_SHIFT), ISPCCDC_VDINT);
+ }
} else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP_MEM) {
omap_writel((1 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
(ispccdc_obj.ccdcin_w <<
@@ -1356,6 +1424,40 @@ void ispccdc_enable(u8 enable)
EXPORT_SYMBOL(ispccdc_enable);
/**
+ * ispccdc_config_y8pos - Configures the location of Y color component
+ * @mode: Y8POS_EVEN Y pixel in even position, otherwise Y pixel in odd
+ *
+ * Configures the location of Y color componenent for YCbCr 8-bit data
+ */
+void ispccdc_config_y8pos(enum y8pos_mode mode)
+{
+ if (mode == Y8POS_EVEN)
+ omap_writel(omap_readl(ISPCCDC_CFG) & ~(ISPCCDC_CFG_Y8POS),
+ ISPCCDC_CFG);
+ else
+ omap_writel(omap_readl(ISPCCDC_CFG) | (ISPCCDC_CFG_Y8POS),
+ ISPCCDC_CFG);
+}
+EXPORT_SYMBOL(ispccdc_config_y8pos);
+
+/**
+ * ispccdc_config_byteswap - Configures byte swap data stored in memory
+ * @swap: 1 - swap bytes, 0 - normal
+ *
+ * Controls the order in which the Y and C pixels are stored in memory
+ */
+void ispccdc_config_byteswap(int swap)
+{
+ if (swap)
+ omap_writel(omap_readl(ISPCCDC_CFG) | (ISPCCDC_CFG_BSWD),
+ ISPCCDC_CFG);
+ else
+ omap_writel(omap_readl(ISPCCDC_CFG) & ~(ISPCCDC_CFG_BSWD),
+ ISPCCDC_CFG);
+}
+EXPORT_SYMBOL(ispccdc_config_byteswap);
+
+/**
* ispccdc_busy - Gets busy state of the CCDC.
**/
int ispccdc_busy(void)
@@ -60,6 +60,11 @@ enum datasize {
DAT12
};
+/* Enumeration constants for location of Y component in 8-bit YUV data */
+enum y8pos_mode {
+ Y8POS_EVEN = 0,
+ Y8POS_ODD = 1
+};
/**
* struct ispccdc_syncif - Structure for Sync Interface between sensor and CCDC
@@ -191,6 +196,10 @@ int ispccdc_set_outaddr(u32 addr);
void ispccdc_enable(u8 enable);
+void ispccdc_config_y8pos(enum y8pos_mode mode);
+
+void ispccdc_config_byteswap(int swap);
+
int ispccdc_busy(void);
void ispccdc_save_context(void);
old mode 100644
new mode 100755
@@ -56,6 +56,8 @@
#include "isp/isppreview.h"
#include "isp/ispresizer.h"
+#include <media/tvp514x.h>
+
#define OMAP34XXCAM_VERSION KERNEL_VERSION(0, 0, 0)
/* global variables */
@@ -262,7 +264,8 @@ static int omap34xxcam_vbq_prepare(struct videobuf_queue *vbq,
*/
if (vb->baddr) {
/* This is a userspace buffer. */
- if (fh->pix.sizeimage > vb->bsize)
+ if ((fh->pix.sizeimage > vb->bsize) ||
+ vb->baddr != (vb->baddr & ~0x1F))
/* The buffer isn't big enough. */
return -EINVAL;
} else {
@@ -379,7 +382,9 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
struct omap34xxcam_videodev *vdev = ofh->vdev;
int rval;
- if (vdev->vdev_sensor_config.sensor_isp)
+ if (vdev->vdev_sensor_mode)
+ rval = isp_enum_fmt_cap(f);
+ else if (vdev->vdev_sensor_config.sensor_isp)
rval = vidioc_int_enum_fmt_cap(vdev->vdev_sensor, f);
else
rval = isp_enum_fmt_cap(f);
@@ -403,7 +408,10 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
struct omap34xxcam_videodev *vdev = ofh->vdev;
mutex_lock(&vdev->mutex);
- f->fmt.pix = ofh->pix;
+ if (vdev->vdev_sensor_mode)
+ isp_g_fmt_cap(&f->fmt.pix);
+ else
+ f->fmt.pix = ofh->pix;
mutex_unlock(&vdev->mutex);
return 0;
@@ -607,20 +615,44 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
struct v4l2_pix_format pix_tmp;
struct v4l2_fract timeperframe;
int rval;
+ struct v4l2_format input_fmt = *f;
mutex_lock(&vdev->mutex);
if (vdev->streaming) {
rval = -EBUSY;
goto out;
}
+ if (vdev->vdev_sensor_mode) {
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ rval = isp_try_fmt_cap(pix, pix);
+ if (rval)
+ goto out;
- vdev->want_pix = f->fmt.pix;
+ /* Always negotiate with the sensor first */
+ rval = vidioc_int_s_fmt_cap(vdev->vdev_sensor, &input_fmt);
+ if (rval)
+ goto out;
- timeperframe = vdev->want_timeperframe;
+ pix->width = input_fmt.fmt.pix.width;
+ pix->height = input_fmt.fmt.pix.height;
+ pix->pixelformat = input_fmt.fmt.pix.pixelformat;
+ pix->field = input_fmt.fmt.pix.field;
+ pix->bytesperline = input_fmt.fmt.pix.bytesperline;
+ pix->colorspace = input_fmt.fmt.pix.colorspace;
+ pix->sizeimage = input_fmt.fmt.pix.sizeimage;
- rval = s_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
- pix_tmp = f->fmt.pix;
+ /* Negotiate with OMAP3 ISP */
+ rval = isp_s_fmt_cap(pix, pix);
+ if (!rval)
+ pix_tmp = f->fmt.pix;
+ } else {
+ vdev->want_pix = f->fmt.pix;
+ timeperframe = vdev->want_timeperframe;
+
+ rval = s_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
+ pix_tmp = f->fmt.pix;
+ }
out:
mutex_unlock(&vdev->mutex);
@@ -859,15 +891,28 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
static int vidioc_enum_input(struct file *file, void *fh,
struct v4l2_input *inp)
{
- if (inp->index > 0)
- return -EINVAL;
-
- strlcpy(inp->name, "camera", sizeof(inp->name));
- inp->type = V4L2_INPUT_TYPE_CAMERA;
-
+ struct omap34xxcam_videodev *vdev = ((struct omap34xxcam_fh *)fh)->vdev;
+
+ if (vdev->vdev_sensor_mode) {
+ if (vdev->slave_config[OMAP34XXCAM_SLAVE_SENSOR].cur_input
+ == INPUT_CVBS_VI4A) {
+ strlcpy(inp->name, "COMPOSITE", sizeof(inp->name));
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+ } else if (vdev->slave_config[OMAP34XXCAM_SLAVE_SENSOR]
+ .cur_input == INPUT_SVIDEO_VI2C_VI1C) {
+ strlcpy(inp->name, "S-VIDEO", sizeof(inp->name));
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+ }
+ } else {
+ if (inp->index > 0)
+ return -EINVAL;
+ strlcpy(inp->name, "camera", sizeof(inp->name));
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+ }
return 0;
}
+
/**
* vidioc_g_input - V4L2 get input IOCTL handler
* @file: ptr. to system file structure
@@ -878,9 +923,35 @@ static int vidioc_enum_input(struct file *file, void *fh,
*/
static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
{
- *i = 0;
+ struct omap34xxcam_videodev *vdev = ((struct omap34xxcam_fh *)fh)->vdev;
+ int rval = 0;
+
+ mutex_lock(&vdev->mutex);
+ if (vdev->vdev_sensor_mode) {
+ if (vdev->slave_config[OMAP34XXCAM_SLAVE_SENSOR].cur_input
+ == 0) {
+ struct v4l2_routing route;
+ route.input = INPUT_CVBS_VI4A;
+ route.output = 0;
+ rval = vidioc_int_s_video_routing(vdev->vdev_sensor,
+ &route);
+ if (!rval)
+ vdev->slave_config[OMAP34XXCAM_SLAVE_SENSOR]
+ .cur_input = route.input;
+ }
+ if (vdev->slave_config[OMAP34XXCAM_SLAVE_SENSOR].cur_input
+ == INPUT_CVBS_VI4A)
+ *i = 0;
+ else if (vdev->slave_config[OMAP34XXCAM_SLAVE_SENSOR].cur_input
+ == INPUT_SVIDEO_VI2C_VI1C)
+ *i = 1;
+ } else
+ *i = 0;
+
+ mutex_unlock(&vdev->mutex);
+
+ return rval;
- return 0;
}
/**
@@ -893,10 +964,30 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
*/
static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
{
- if (i > 0)
- return -EINVAL;
+ struct omap34xxcam_fh *ofh = fh;
+ struct omap34xxcam_videodev *vdev = ofh->vdev;
+ int rval = 0;
+ struct v4l2_routing route;
- return 0;
+ mutex_lock(&vdev->mutex);
+ if (vdev->vdev_sensor_mode) {
+ if (i == 0)
+ route.input = INPUT_CVBS_VI4A;
+ else
+ route.input = INPUT_SVIDEO_VI2C_VI1C;
+
+ route.output = 0;
+ rval = vidioc_int_s_video_routing(vdev->vdev_sensor, &route);
+ if (!rval)
+ vdev->slave_config[OMAP34XXCAM_SLAVE_SENSOR].cur_input
+ = route.input;
+ } else {
+ if (i > 0)
+ rval = -EINVAL;
+ }
+ mutex_unlock(&vdev->mutex);
+
+ return rval;
}
/**
@@ -1381,6 +1472,61 @@ out:
return rval;
}
+
+/**
+ * vidioc_querystd - V4L2 query current standard IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @std: standard V4L2 v4l2_std_id enum
+ *
+ * If using a "smart" sensor, just forwards request to the sensor driver,
+ * otherwise returns error
+ */
+static int vidioc_querystd(struct file *file, void *fh, v4l2_std_id *std)
+{
+ struct omap34xxcam_fh *ofh = fh;
+ struct omap34xxcam_videodev *vdev = ofh->vdev;
+ int rval = 0;
+
+ mutex_lock(&vdev->mutex);
+ if (vdev->vdev_sensor_mode) {
+ rval = vidioc_int_querystd(vdev->vdev_sensor, std);
+ if (rval == 0)
+ vdev->vfd->current_norm = *std;
+ } else
+ rval = -EINVAL;
+ mutex_unlock(&vdev->mutex);
+
+ return rval;
+}
+
+/**
+ * vidioc_s_std - V4L2 set standard IOCTL handler
+ * @file: ptr. to system file structure
+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
+ * @std: standard V4L2 v4l2_std_id enum
+ *
+ * If using a "smart" sensor, just forwards request to the sensor driver,
+ * otherwise returns error
+ */
+static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+ struct omap34xxcam_fh *ofh = fh;
+ struct omap34xxcam_videodev *vdev = ofh->vdev;
+ int rval = 0;
+
+ mutex_lock(&vdev->mutex);
+ if (vdev->vdev_sensor_mode) {
+ rval = vidioc_int_s_std(vdev->vdev_sensor, std);
+ if (rval == 0)
+ vdev->vfd->current_norm = *std;
+ } else
+ rval = -EINVAL;
+ mutex_unlock(&vdev->mutex);
+
+ return rval;
+}
+
/*
*
* File operations.
@@ -1683,6 +1829,8 @@ static const struct v4l2_ioctl_ops omap34xxcam_ioctl_ops = {
.vidioc_g_crop = vidioc_g_crop,
.vidioc_s_crop = vidioc_s_crop,
.vidioc_default = vidioc_default,
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_querystd = vidioc_querystd,
};
/**
@@ -1704,6 +1852,7 @@ static int omap34xxcam_device_register(struct v4l2_int_device *s)
struct omap34xxcam_hw_config hwc;
struct video_device *vfd;
int rval;
+ struct v4l2_ifparm ifparm;
/* We need to check rval just once. The place is here. */
if (vidioc_int_g_priv(s, &hwc))
@@ -1783,6 +1932,18 @@ static int omap34xxcam_device_register(struct v4l2_int_device *s)
} else {
vfd = vdev->vfd;
}
+ /*Determine whether the slave connected is BT656 decoder or a sensor*/
+ if (!vidioc_int_g_ifparm(s, &ifparm)) {
+ if (ifparm.if_type == V4L2_IF_TYPE_BT656) {
+ vfd->current_norm = V4L2_STD_NTSC;
+ vfd->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL;
+ if ((ifparm.u.bt656.mode ==
+ V4L2_IF_TYPE_BT656_MODE_BT_8BIT) ||
+ (ifparm.u.bt656.mode ==
+ V4L2_IF_TYPE_BT656_MODE_BT_10BIT))
+ vdev->slave_mode[hwc.dev_type] = 1;
+ }
+ }
omap34xxcam_vfd_name_update(vdev);
@@ -92,6 +92,7 @@ struct omap34xxcam_hw_config {
struct omap34xxcam_lens_config lens;
struct omap34xxcam_flash_config flash;
} u;
+ int cur_input;
};
/**
@@ -155,6 +156,10 @@ struct omap34xxcam_videodev {
#define vdev_lens_config slave_config[OMAP34XXCAM_SLAVE_LENS].u.lens
#define vdev_flash_config slave_config[OMAP34XXCAM_SLAVE_FLASH].u.flash
struct omap34xxcam_hw_config slave_config[OMAP34XXCAM_SLAVE_FLASH + 1];
+#define vdev_sensor_mode slave_mode[OMAP34XXCAM_SLAVE_SENSOR]
+#define vdev_lens_mode slave_mode[OMAP34XXCAM_SLAVE_LENS]
+#define vdev_flash_mode slave_mode[OMAP34XXCAM_SLAVE_FLASH]
+ int slave_mode[OMAP34XXCAM_SLAVE_FLASH + 1];
/*** capture data ***/
struct v4l2_fract want_timeperframe;