summaryrefslogtreecommitdiff
path: root/drivers/media/video/mxc/capture
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mxc/capture')
-rw-r--r--drivers/media/video/mxc/capture/Kconfig18
-rw-r--r--drivers/media/video/mxc/capture/Makefile2
-rw-r--r--drivers/media/video/mxc/capture/adv7180.c67
-rw-r--r--drivers/media/video/mxc/capture/csi_v4l2_capture.c12
-rw-r--r--drivers/media/video/mxc/capture/emma_v4l2_capture.c17
-rw-r--r--drivers/media/video/mxc/capture/ipu_csi_enc.c69
-rw-r--r--drivers/media/video/mxc/capture/ipu_prp_enc.c11
-rw-r--r--drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c2
-rw-r--r--drivers/media/video/mxc/capture/ipu_still.c65
-rw-r--r--drivers/media/video/mxc/capture/mt9v111.c1085
-rw-r--r--drivers/media/video/mxc/capture/mt9v111.h8
-rw-r--r--drivers/media/video/mxc/capture/mx27_prpsw.c4
-rw-r--r--drivers/media/video/mxc/capture/mxc_v4l2_capture.c565
-rw-r--r--drivers/media/video/mxc/capture/mxc_v4l2_capture.h6
-rw-r--r--drivers/media/video/mxc/capture/ov3640.c87
15 files changed, 1379 insertions, 639 deletions
diff --git a/drivers/media/video/mxc/capture/Kconfig b/drivers/media/video/mxc/capture/Kconfig
index adab0a886f36..276dfa424feb 100644
--- a/drivers/media/video/mxc/capture/Kconfig
+++ b/drivers/media/video/mxc/capture/Kconfig
@@ -58,6 +58,22 @@ config MXC_CAMERA_MICRON111
---help---
If you plan to use the mt9v111 Camera with your MXC system, say Y here.
+config MXC_CAMERA_MICRON111_1
+ tristate "Micron mt9v111 camera 1 support"
+ select I2C_MXC
+ depends on ! VIDEO_MXC_EMMA_CAMERA
+ depends on MXC_CAMERA_MICRON111
+ ---help---
+ If you plan to use the mt9v111 Camera 1 with your MXC system, say Y here.
+
+config MXC_CAMERA_MICRON111_2
+ tristate "Micron mt9v111 camera 2 support"
+ select I2C_MXC
+ depends on ! VIDEO_MXC_EMMA_CAMERA
+ depends on MXC_CAMERA_MICRON111
+ ---help---
+ If you plan to use the mt9v111 Camera 2 with your MXC system, say Y here.
+
config MXC_CAMERA_OV2640
tristate "OmniVision ov2640 camera support"
depends on !VIDEO_MXC_EMMA_CAMERA
@@ -72,7 +88,7 @@ config MXC_CAMERA_OV3640
config MXC_TVIN_ADV7180
tristate "Analog Device adv7180 TV Decoder Input support"
- depends on MACH_MX35_3DS
+ depends on (MACH_MX35_3DS || MACH_MX51_3DS)
---help---
If you plan to use the adv7180 video decoder with your MXC system, say Y here.
diff --git a/drivers/media/video/mxc/capture/Makefile b/drivers/media/video/mxc/capture/Makefile
index 112923c8fc8f..03ff094171bf 100644
--- a/drivers/media/video/mxc/capture/Makefile
+++ b/drivers/media/video/mxc/capture/Makefile
@@ -35,5 +35,5 @@ obj-$(CONFIG_MXC_CAMERA_OV2640) += ov2640_camera.o
ov3640_camera-objs := ov3640.o sensor_clock.o
obj-$(CONFIG_MXC_CAMERA_OV3640) += ov3640_camera.o
-adv7180_tvin-objs := adv7180.o sensor_clock.o
+adv7180_tvin-objs := adv7180.o
obj-$(CONFIG_MXC_TVIN_ADV7180) += adv7180_tvin.o
diff --git a/drivers/media/video/mxc/capture/adv7180.c b/drivers/media/video/mxc/capture/adv7180.c
index 1edee763bebc..527a0d1ad9fa 100644
--- a/drivers/media/video/mxc/capture/adv7180.c
+++ b/drivers/media/video/mxc/capture/adv7180.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2005-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -39,6 +39,7 @@ static struct regulator *dvddio_regulator;
static struct regulator *dvdd_regulator;
static struct regulator *avdd_regulator;
static struct regulator *pvdd_regulator;
+static struct mxc_tvin_platform_data *tvin_plat;
extern void gpio_sensor_active(void);
extern void gpio_sensor_inactive(void);
@@ -118,26 +119,26 @@ static video_fmt_t video_fmts[] = {
{ /*! NTSC */
.v4l2_id = V4L2_STD_NTSC,
.name = "NTSC",
- .raw_width = 720 - 1, /* SENS_FRM_WIDTH */
- .raw_height = 288 - 1, /* SENS_FRM_HEIGHT */
+ .raw_width = 720, /* SENS_FRM_WIDTH */
+ .raw_height = 525, /* SENS_FRM_HEIGHT */
.active_width = 720, /* ACT_FRM_WIDTH plus 1 */
- .active_height = (480 / 2), /* ACT_FRM_WIDTH plus 1 */
+ .active_height = 480, /* ACT_FRM_WIDTH plus 1 */
},
{ /*! (B, G, H, I, N) PAL */
.v4l2_id = V4L2_STD_PAL,
.name = "PAL",
- .raw_width = 720 - 1,
- .raw_height = (576 / 2) + 24 * 2 - 1,
+ .raw_width = 720,
+ .raw_height = 625,
.active_width = 720,
- .active_height = (576 / 2),
+ .active_height = 576,
},
{ /*! Unlocked standard */
.v4l2_id = V4L2_STD_ALL,
.name = "Autodetect",
- .raw_width = 720 - 1,
- .raw_height = (576 / 2) + 24 * 2 - 1,
+ .raw_width = 720,
+ .raw_height = 625,
.active_width = 720,
- .active_height = (576 / 2),
+ .active_height = 576,
},
};
@@ -246,6 +247,10 @@ static void adv7180_get_std(v4l2_std_id *std)
dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180_get_std\n");
+ /* Make sure power on */
+ if (tvin_plat->pwdn)
+ tvin_plat->pwdn(0);
+
/* Read the AD_RESULT to get the detect output video standard */
tmp = adv7180_read(ADV7180_STATUS_1) & 0x70;
@@ -335,6 +340,11 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on)
if (on && !sensor->on) {
gpio_sensor_active();
+
+ /* Make sure pwoer on */
+ if (tvin_plat->pwdn)
+ tvin_plat->pwdn(0);
+
if (adv7180_write_reg(ADV7180_PWR_MNG, 0) != 0)
return -EIO;
} else if (!on && sensor->on) {
@@ -500,6 +510,10 @@ static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_g_ctrl\n");
+ /* Make sure power on */
+ if (tvin_plat->pwdn)
+ tvin_plat->pwdn(0);
+
switch (vc->id) {
case V4L2_CID_BRIGHTNESS:
dev_dbg(&adv7180_data.i2c_client->dev,
@@ -593,6 +607,10 @@ static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_s_ctrl\n");
+ /* Make sure power on */
+ if (tvin_plat->pwdn)
+ tvin_plat->pwdn(0);
+
switch (vc->id) {
case V4L2_CID_BRIGHTNESS:
dev_dbg(&adv7180_data.i2c_client->dev,
@@ -803,13 +821,13 @@ static int adv7180_probe(struct i2c_client *client,
{
int rev_id;
int ret = 0;
- struct mxc_tvin_platform_data *plat_data = client->dev.platform_data;
+ tvin_plat = client->dev.platform_data;
dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180_probe\n");
- if (plat_data->dvddio_reg) {
+ if (tvin_plat->dvddio_reg) {
dvddio_regulator =
- regulator_get(&client->dev, plat_data->dvddio_reg);
+ regulator_get(&client->dev, tvin_plat->dvddio_reg);
if (!IS_ERR_VALUE((unsigned long)dvddio_regulator)) {
regulator_set_voltage(dvddio_regulator, 3300000, 3300000);
if (regulator_enable(dvddio_regulator) != 0)
@@ -817,9 +835,9 @@ static int adv7180_probe(struct i2c_client *client,
}
}
- if (plat_data->dvdd_reg) {
+ if (tvin_plat->dvdd_reg) {
dvdd_regulator =
- regulator_get(&client->dev, plat_data->dvdd_reg);
+ regulator_get(&client->dev, tvin_plat->dvdd_reg);
if (!IS_ERR_VALUE((unsigned long)dvdd_regulator)) {
regulator_set_voltage(dvdd_regulator, 1800000, 1800000);
if (regulator_enable(dvdd_regulator) != 0)
@@ -827,9 +845,9 @@ static int adv7180_probe(struct i2c_client *client,
}
}
- if (plat_data->avdd_reg) {
+ if (tvin_plat->avdd_reg) {
avdd_regulator =
- regulator_get(&client->dev, plat_data->avdd_reg);
+ regulator_get(&client->dev, tvin_plat->avdd_reg);
if (!IS_ERR_VALUE((unsigned long)avdd_regulator)) {
regulator_set_voltage(avdd_regulator, 1800000, 1800000);
if (regulator_enable(avdd_regulator) != 0)
@@ -837,9 +855,9 @@ static int adv7180_probe(struct i2c_client *client,
}
}
- if (plat_data->pvdd_reg) {
+ if (tvin_plat->pvdd_reg) {
pvdd_regulator =
- regulator_get(&client->dev, plat_data->pvdd_reg);
+ regulator_get(&client->dev, tvin_plat->pvdd_reg);
if (!IS_ERR_VALUE((unsigned long)pvdd_regulator)) {
regulator_set_voltage(pvdd_regulator, 1800000, 1800000);
if (regulator_enable(pvdd_regulator) != 0)
@@ -847,11 +865,12 @@ static int adv7180_probe(struct i2c_client *client,
}
}
- if (plat_data->reset)
- plat_data->reset();
- if (plat_data->pwdn)
- plat_data->pwdn(1);
+ if (tvin_plat->reset)
+ tvin_plat->reset();
+
+ if (tvin_plat->pwdn)
+ tvin_plat->pwdn(0);
msleep(1);
@@ -913,7 +932,7 @@ static int adv7180_detach(struct i2c_client *client)
__func__, IF_NAME, client->addr << 1, client->adapter->name);
if (plat_data->pwdn)
- plat_data->pwdn(0);
+ plat_data->pwdn(1);
if (dvddio_regulator) {
regulator_disable(dvddio_regulator);
diff --git a/drivers/media/video/mxc/capture/csi_v4l2_capture.c b/drivers/media/video/mxc/capture/csi_v4l2_capture.c
index 9bddc3692996..cf224e0673f0 100644
--- a/drivers/media/video/mxc/capture/csi_v4l2_capture.c
+++ b/drivers/media/video/mxc/capture/csi_v4l2_capture.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -789,15 +789,15 @@ static ssize_t csi_v4l_read(struct file *file, char *buf, size_t count,
(cam->v2f.fmt.
pix.sizeimage),
&cam->
- still_buf,
+ still_buf[0],
GFP_DMA | GFP_KERNEL);
if (cam->still_buf_vaddr == NULL) {
pr_err("alloc dma memory failed\n");
return -ENOMEM;
}
cam->still_counter = 0;
- __raw_writel(cam->still_buf, CSI_CSIDMASA_FB2);
- __raw_writel(cam->still_buf, CSI_CSIDMASA_FB1);
+ __raw_writel(cam->still_buf[0], CSI_CSIDMASA_FB2);
+ __raw_writel(cam->still_buf[0], CSI_CSIDMASA_FB1);
__raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF,
CSI_CSICR3);
__raw_writel(__raw_readl(CSI_CSISR), CSI_CSISR);
@@ -813,8 +813,8 @@ static ssize_t csi_v4l_read(struct file *file, char *buf, size_t count,
if (cam->still_buf_vaddr != NULL) {
dma_free_coherent(0, PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
- cam->still_buf_vaddr, cam->still_buf);
- cam->still_buf = 0;
+ cam->still_buf_vaddr, cam->still_buf[0]);
+ cam->still_buf[0] = 0;
cam->still_buf_vaddr = NULL;
}
diff --git a/drivers/media/video/mxc/capture/emma_v4l2_capture.c b/drivers/media/video/mxc/capture/emma_v4l2_capture.c
index 9cb08b26f1cd..170807716ec6 100644
--- a/drivers/media/video/mxc/capture/emma_v4l2_capture.c
+++ b/drivers/media/video/mxc/capture/emma_v4l2_capture.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -858,7 +858,7 @@ static void mxc_csi_dma_chaining(void *data)
/* Config DMA */
memset(&dma_request, 0, sizeof(mxc_dma_requestbuf_t));
- dma_request.dst_addr = cam->still_buf
+ dma_request.dst_addr = cam->still_buf[0]
+ (chained % max_dma) * CSI_DMA_LENGTH;
dma_request.src_addr = (dma_addr_t) CSI_CSIRXFIFO_PHYADDR;
dma_request.num_of_bytes = count;
@@ -1040,7 +1040,7 @@ mxc_v4l_read(struct file *file, char *buf, size_t count, loff_t *ppos)
cam->still_buf_vaddr = dma_alloc_coherent(0,
PAGE_ALIGN(CSI_MEM_SIZE),
- &cam->still_buf,
+ &cam->still_buf[0],
GFP_DMA | GFP_KERNEL);
if (!cam->still_buf_vaddr) {
@@ -1120,8 +1120,8 @@ mxc_v4l_read(struct file *file, char *buf, size_t count, loff_t *ppos)
exit1:
dma_free_coherent(0, PAGE_ALIGN(CSI_MEM_SIZE),
- cam->still_buf_vaddr, cam->still_buf);
- cam->still_buf = 0;
+ cam->still_buf_vaddr, cam->still_buf[0]);
+ cam->still_buf[0] = 0;
exit0:
up(&cam->busy_lock);
@@ -1160,7 +1160,8 @@ mxc_v4l_read(struct file *file, char *buf, size_t count, loff_t *ppos)
v_address = dma_alloc_coherent(0,
PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
- &cam->still_buf, GFP_DMA | GFP_KERNEL);
+ &cam->still_buf[0],
+ GFP_DMA | GFP_KERNEL);
if (!v_address) {
pr_info("mxc_v4l_read failed at allocate still_buf\n");
@@ -1194,8 +1195,8 @@ mxc_v4l_read(struct file *file, char *buf, size_t count, loff_t *ppos)
exit1:
dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address,
- cam->still_buf);
- cam->still_buf = 0;
+ cam->still_buf[0]);
+ cam->still_buf[0] = 0;
exit0:
up(&cam->busy_lock);
diff --git a/drivers/media/video/mxc/capture/ipu_csi_enc.c b/drivers/media/video/mxc/capture/ipu_csi_enc.c
index fd3f0c132c14..0b87282551ff 100644
--- a/drivers/media/video/mxc/capture/ipu_csi_enc.c
+++ b/drivers/media/video/mxc/capture/ipu_csi_enc.c
@@ -25,6 +25,7 @@
#include "ipu_prp_sw.h"
#ifdef CAMERA_DBG
+ extern void ipu_dump_registers(void);
#define CAMERA_TRACE(x) (printk)x
#else
#define CAMERA_TRACE(x)
@@ -66,6 +67,7 @@ static int csi_enc_setup(cam_data *cam)
u32 pixel_fmt;
int err = 0;
dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;
+ ipu_channel_t channel;
CAMERA_TRACE("In csi_enc_setup\n");
if (!cam) {
@@ -101,13 +103,18 @@ static int csi_enc_setup(cam_data *cam)
ipu_csi_enable_mclk_if(CSI_MCLK_ENC, cam->csi, true, true);
- err = ipu_init_channel(CSI_MEM, &params);
+ if (cam->csi == 0)
+ channel = CSI_MEM0;
+ else
+ channel = CSI_MEM1;
+
+ err = ipu_init_channel(channel, &params);
if (err != 0) {
printk(KERN_ERR "ipu_init_channel %d\n", err);
return err;
}
- err = ipu_init_channel_buffer(CSI_MEM, IPU_OUTPUT_BUFFER,
+ err = ipu_init_channel_buffer(channel, IPU_OUTPUT_BUFFER,
pixel_fmt, cam->v2f.fmt.pix.width,
cam->v2f.fmt.pix.height,
cam->v2f.fmt.pix.width, IPU_ROTATE_NONE,
@@ -115,12 +122,12 @@ static int csi_enc_setup(cam_data *cam)
cam->offset.u_offset,
cam->offset.v_offset);
if (err != 0) {
- printk(KERN_ERR "CSI_MEM output buffer\n");
+ printk(KERN_ERR "CSI_MEM%d output buffer\n",cam->csi);
return err;
}
- err = ipu_enable_channel(CSI_MEM);
+ err = ipu_enable_channel(channel);
if (err < 0) {
- printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
+ printk(KERN_ERR "ipu_enable_channel CSI_MEM%d\n",cam->csi);
return err;
}
@@ -135,24 +142,34 @@ static int csi_enc_setup(cam_data *cam)
*
* @return status
*/
-static int csi_enc_eba_update(dma_addr_t eba, int *buffer_num)
+static int csi_enc_eba_update(int csi, dma_addr_t eba, int *buffer_num)
{
int err = 0;
+ ipu_channel_t channel;
+
+ if (csi == 0)
+ channel = CSI_MEM0;
+ else
+ channel = CSI_MEM1;
- pr_debug("eba %x\n", eba);
- err = ipu_update_channel_buffer(CSI_MEM, IPU_OUTPUT_BUFFER,
+ err = ipu_update_channel_buffer(channel, IPU_OUTPUT_BUFFER,
*buffer_num, eba);
+
if (err != 0) {
- ipu_clear_buffer_ready(CSI_MEM, IPU_OUTPUT_BUFFER,
+ ipu_clear_buffer_ready(channel, IPU_OUTPUT_BUFFER,
*buffer_num);
printk(KERN_ERR "err %d buffer_num %d\n", err, *buffer_num);
return err;
}
- ipu_select_buffer(CSI_MEM, IPU_OUTPUT_BUFFER, *buffer_num);
+ ipu_select_buffer(channel, IPU_OUTPUT_BUFFER, *buffer_num);
*buffer_num = (*buffer_num == 0) ? 1 : 0;
+#ifdef CAMERA_DBG
+ ipu_dump_registers ();
+#endif
+
return 0;
}
@@ -166,6 +183,7 @@ static int csi_enc_enabling_tasks(void *private)
{
cam_data *cam = (cam_data *) private;
int err = 0;
+ int ipu_irq_csi_out_eof;
CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n");
cam->dummy_frame.vaddress = dma_alloc_coherent(0,
@@ -182,11 +200,16 @@ static int csi_enc_enabling_tasks(void *private)
PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;
- ipu_clear_irq(IPU_IRQ_CSI0_OUT_EOF);
- err = ipu_request_irq(IPU_IRQ_CSI0_OUT_EOF,
- csi_enc_callback, 0, "Mxc Camera", cam);
+ if (cam->csi == 0)
+ ipu_irq_csi_out_eof = IPU_IRQ_CSI0_OUT_EOF;
+ else
+ ipu_irq_csi_out_eof = IPU_IRQ_CSI1_OUT_EOF;
+ ipu_clear_irq(ipu_irq_csi_out_eof);
+ err = ipu_request_irq(ipu_irq_csi_out_eof,
+ csi_enc_callback, 0, "Mxc Camera", cam);
+
if (err != 0) {
- printk(KERN_ERR "Error registering rot irq\n");
+ printk(KERN_ERR "Error registering eot irq for csi %d\n",cam->csi);
return err;
}
@@ -209,12 +232,24 @@ static int csi_enc_disabling_tasks(void *private)
{
cam_data *cam = (cam_data *) private;
int err = 0;
+ ipu_channel_t channel;
+ int ipu_irq_csi_out_eof;
- ipu_free_irq(IPU_IRQ_CSI0_OUT_EOF, cam);
+ if (cam->csi == 0)
+ {
+ channel = CSI_MEM0;
+ ipu_irq_csi_out_eof = IPU_IRQ_CSI0_OUT_EOF;
+ }
+ else
+ {
+ channel = CSI_MEM1;
+ ipu_irq_csi_out_eof = IPU_IRQ_CSI1_OUT_EOF;
+ }
- err = ipu_disable_channel(CSI_MEM, true);
+ ipu_free_irq(ipu_irq_csi_out_eof, cam);
+ err = ipu_disable_channel(channel, true);
- ipu_uninit_channel(CSI_MEM);
+ ipu_uninit_channel(channel);
if (cam->dummy_frame.vaddress != 0) {
dma_free_coherent(0, cam->dummy_frame.buffer.length,
diff --git a/drivers/media/video/mxc/capture/ipu_prp_enc.c b/drivers/media/video/mxc/capture/ipu_prp_enc.c
index 4b5426cb887d..0df8050ad7de 100644
--- a/drivers/media/video/mxc/capture/ipu_prp_enc.c
+++ b/drivers/media/video/mxc/capture/ipu_prp_enc.c
@@ -19,12 +19,14 @@
* @ingroup IPU
*/
+#include <linux/types.h>
#include <linux/dma-mapping.h>
#include <linux/ipu.h>
#include "mxc_v4l2_capture.h"
#include "ipu_prp_sw.h"
#ifdef CAMERA_DBG
+ extern void ipu_dump_registers(void);
#define CAMERA_TRACE(x) (printk)x
#else
#define CAMERA_TRACE(x)
@@ -266,11 +268,10 @@ static int prp_enc_setup(cam_data * cam)
*
* @return status
*/
-static int prp_enc_eba_update(dma_addr_t eba, int *buffer_num)
+static int prp_enc_eba_update(int csi, dma_addr_t eba, int *buffer_num)
{
int err = 0;
- pr_debug("eba %x\n", eba);
if (grotation >= IPU_ROTATE_90_RIGHT) {
err = ipu_update_channel_buffer(MEM_ROT_ENC_MEM,
IPU_OUTPUT_BUFFER, *buffer_num,
@@ -294,6 +295,11 @@ static int prp_enc_eba_update(dma_addr_t eba, int *buffer_num)
}
*buffer_num = (*buffer_num == 0) ? 1 : 0;
+
+#ifdef CAMERA_DBG
+ ipu_dump_registers ();
+#endif
+
return 0;
}
@@ -350,7 +356,6 @@ static int prp_enc_disabling_tasks(void *private)
if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
ipu_unlink_channels(CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);
}
-
err = ipu_disable_channel(CSI_PRP_ENC_MEM, true);
if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
err |= ipu_disable_channel(MEM_ROT_ENC_MEM, true);
diff --git a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c
index 7f0984c42950..9f8078d558b0 100644
--- a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c
+++ b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c
@@ -182,6 +182,7 @@ static int prpvf_start(void *private)
printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n");
goto out_3;
}
+
err = ipu_init_channel(MEM_ROT_VF_MEM, NULL);
if (err != 0) {
printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n");
@@ -200,6 +201,7 @@ static int prpvf_start(void *private)
}
if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) {
+
err = ipu_init_channel_buffer(MEM_ROT_VF_MEM, IPU_OUTPUT_BUFFER,
format,
vf.csi_prp_vf_mem.out_height,
diff --git a/drivers/media/video/mxc/capture/ipu_still.c b/drivers/media/video/mxc/capture/ipu_still.c
index 348bf2b9b564..22cf3f51e1cb 100644
--- a/drivers/media/video/mxc/capture/ipu_still.c
+++ b/drivers/media/video/mxc/capture/ipu_still.c
@@ -26,6 +26,9 @@
#include "ipu_prp_sw.h"
static int callback_eof_flag;
+#ifndef CONFIG_MXC_IPU_V1
+static int buffer_num;
+#endif
#ifdef CONFIG_MXC_IPU_V1
static int callback_flag;
@@ -42,10 +45,10 @@ static int callback_flag;
*/
static irqreturn_t prp_csi_eof_callback(int irq, void *dev_id)
{
- if (callback_flag == 2) {
- ipu_select_buffer(CSI_MEM, IPU_OUTPUT_BUFFER, 0);
+ ipu_select_buffer(CSI_MEM, IPU_OUTPUT_BUFFER,
+ callback_flag%2 ? 1 : 0);
+ if (callback_flag == 0)
ipu_enable_channel(CSI_MEM);
- }
callback_flag++;
return IRQ_HANDLED;
@@ -65,9 +68,12 @@ static irqreturn_t prp_still_callback(int irq, void *dev_id)
cam_data *cam = (cam_data *) dev_id;
callback_eof_flag++;
- if (callback_eof_flag < 5)
- ipu_select_buffer(CSI_MEM, IPU_OUTPUT_BUFFER, 0);
- else {
+ if (callback_eof_flag < 5) {
+#ifndef CONFIG_MXC_IPU_V1
+ buffer_num = (buffer_num == 0) ? 1 : 0;
+ ipu_select_buffer(CSI_MEM, IPU_OUTPUT_BUFFER, buffer_num);
+#endif
+ } else {
cam->still_counter++;
wake_up_interruptible(&cam->still_queue);
}
@@ -87,6 +93,8 @@ static int prp_still_start(void *private)
u32 pixel_fmt;
int err;
ipu_channel_params_t params;
+ ipu_channel_t channel;
+ int ipu_irq_csi_out_eof;
if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
pixel_fmt = IPU_PIX_FMT_YUV420P;
@@ -113,20 +121,32 @@ static int prp_still_start(void *private)
ipu_csi_enable_mclk_if(CSI_MCLK_RAW, cam->csi, true, true);
+ if (cam->csi == 0) {
+ channel = CSI_MEM0;
+ ipu_irq_csi_out_eof = IPU_IRQ_CSI0_OUT_EOF;
+ }
+ else {
+ channel = CSI_MEM1;
+ ipu_irq_csi_out_eof = IPU_IRQ_CSI1_OUT_EOF;
+ }
+
memset(&params, 0, sizeof(params));
- err = ipu_init_channel(CSI_MEM, &params);
+ params.csi_mem.csi = cam->csi;
+ err = ipu_init_channel(channel, &params);
if (err != 0)
return err;
- err = ipu_init_channel_buffer(CSI_MEM, IPU_OUTPUT_BUFFER,
+ err = ipu_init_channel_buffer(channel, IPU_OUTPUT_BUFFER,
pixel_fmt, cam->v2f.fmt.pix.width,
cam->v2f.fmt.pix.height,
cam->v2f.fmt.pix.width, IPU_ROTATE_NONE,
- cam->still_buf, 0, 0, 0);
+ cam->still_buf[0], cam->still_buf[1],
+ 0, 0);
if (err != 0)
return err;
#ifdef CONFIG_MXC_IPU_V1
+ ipu_clear_irq(IPU_IRQ_SENSOR_OUT_EOF);
err = ipu_request_irq(IPU_IRQ_SENSOR_OUT_EOF, prp_still_callback,
0, "Mxc Camera", cam);
if (err != 0) {
@@ -135,6 +155,7 @@ static int prp_still_start(void *private)
}
callback_flag = 0;
callback_eof_flag = 0;
+ ipu_clear_irq(IPU_IRQ_SENSOR_EOF);
err = ipu_request_irq(IPU_IRQ_SENSOR_EOF, prp_csi_eof_callback,
0, "Mxc Camera", NULL);
if (err != 0) {
@@ -142,8 +163,9 @@ static int prp_still_start(void *private)
return err;
}
#else
- ipu_clear_irq(IPU_IRQ_CSI0_OUT_EOF);
- err = ipu_request_irq(IPU_IRQ_CSI0_OUT_EOF, prp_still_callback,
+
+ ipu_clear_irq(ipu_irq_csi_out_eof);
+ err = ipu_request_irq(ipu_irq_csi_out_eof, prp_still_callback,
0, "Mxc Camera", cam);
if (err != 0) {
printk(KERN_ERR "Error registering irq.\n");
@@ -151,9 +173,9 @@ static int prp_still_start(void *private)
}
callback_eof_flag = 0;
+ ipu_select_buffer(channel, IPU_OUTPUT_BUFFER, 0);
+ ipu_enable_channel(channel);
- ipu_select_buffer(CSI_MEM, IPU_OUTPUT_BUFFER, 0);
- ipu_enable_channel(CSI_MEM);
ipu_enable_csi(cam->csi);
#endif
@@ -170,17 +192,28 @@ static int prp_still_stop(void *private)
{
cam_data *cam = (cam_data *) private;
int err = 0;
+ ipu_channel_t channel;
+ int ipu_irq_csi_out_eof;
+
+ if (cam->csi == 0) {
+ channel = CSI_MEM0;
+ ipu_irq_csi_out_eof = IPU_IRQ_CSI0_OUT_EOF;
+ }
+ else {
+ channel = CSI_MEM1;
+ ipu_irq_csi_out_eof = IPU_IRQ_CSI1_OUT_EOF;
+ }
#ifdef CONFIG_MXC_IPU_V1
ipu_free_irq(IPU_IRQ_SENSOR_EOF, NULL);
ipu_free_irq(IPU_IRQ_SENSOR_OUT_EOF, cam);
#else
- ipu_free_irq(IPU_IRQ_CSI0_OUT_EOF, cam);
+ ipu_free_irq(ipu_irq_csi_out_eof, cam);
#endif
ipu_disable_csi(cam->csi);
- ipu_disable_channel(CSI_MEM, true);
- ipu_uninit_channel(CSI_MEM);
+ ipu_disable_channel(channel, true);
+ ipu_uninit_channel(channel);
ipu_csi_enable_mclk_if(CSI_MCLK_RAW, cam->csi, false, false);
return err;
diff --git a/drivers/media/video/mxc/capture/mt9v111.c b/drivers/media/video/mxc/capture/mt9v111.c
index c95a20683924..dfdd455db3dd 100644
--- a/drivers/media/video/mxc/capture/mt9v111.c
+++ b/drivers/media/video/mxc/capture/mt9v111.c
@@ -18,6 +18,9 @@
*
* @ingroup Camera
*/
+
+//#define MT9V111_DEBUG
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -40,7 +43,6 @@ static mt9v111_conf mt9v111_device;
/*!
* Holds the current frame rate.
*/
-static int reset_frame_rate = MT9V111_FRAME_RATE;
struct sensor {
const struct mt9v111_platform_data *platform_data;
@@ -49,33 +51,45 @@ struct sensor {
struct v4l2_pix_format pix;
struct v4l2_captureparm streamcap;
bool on;
+ bool used;
/* control settings */
int brightness;
- int hue;
- int contrast;
int saturation;
- int red;
- int green;
- int blue;
+ int sharpness;
+ int gain;
int ae_mode;
-} mt9v111_data;
-
-extern void gpio_sensor_active(void);
-extern void gpio_sensor_inactive(void);
+};
static int mt9v111_probe(struct i2c_client *client,
const struct i2c_device_id *id);
static int mt9v111_remove(struct i2c_client *client);
static const struct i2c_device_id mt9v111_id[] = {
- {"mt9v111", 0},
+ {"mt9v111_1", 2},
+ {"mt9v111_2", 3},
{},
};
+struct sensor mt9v111_data[ARRAY_SIZE(mt9v111_id)-1];
+
MODULE_DEVICE_TABLE(i2c, mt9v111_id);
+static int mt9v111_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ pr_debug("In mt9v111_suspend\n");
+
+ return 0;
+}
+
+static int mt9v111_resume(struct i2c_client *client)
+{
+ pr_debug("In mt9v111_resume\n");
+
+ return 0;
+}
+
static struct i2c_driver mt9v111_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
@@ -84,37 +98,52 @@ static struct i2c_driver mt9v111_i2c_driver = {
.probe = mt9v111_probe,
.remove = mt9v111_remove,
.id_table = mt9v111_id,
-/* To add power management add .suspend and .resume functions */
+ .suspend = mt9v111_suspend,
+ .resume = mt9v111_resume,
};
/*
* Function definitions
*/
-#ifdef MT9V111_DEBUG
-static inline int mt9v111_read_reg(u8 reg)
+static int mt9v111_id_from_name ( const char * name )
+{
+ int id = -1;
+
+ if( name == NULL || ( strlen(name) < strlen("mt9v111_n") ) )
+ return -1;
+
+ id = (int)simple_strtol(name+strlen("mt9v111_"),NULL,0) - 1;
+ if( id >= ARRAY_SIZE(mt9v111_id) ) {
+ printk("Invalid sensor index %d for %s\n",id,name);
+ return -1;
+ }
+
+ return id;
+}
+
+static inline int mt9v111_read_reg(int sensorid , u8 reg)
{
- int val = i2c_smbus_read_word_data(mt9v111_data.i2c_client, reg);
+ int val = i2c_smbus_read_word_data(mt9v111_data[sensorid].i2c_client, reg);
if (val != -1)
val = cpu_to_be16(val);
return val;
}
-#endif
/*!
* Writes to the register via I2C.
*/
-static inline int mt9v111_write_reg(u8 reg, u16 val)
+static inline int mt9v111_write_reg(int sensorid , u8 reg, u16 val)
{
- pr_debug("In mt9v111_write_reg (0x%x, 0x%x)\n", reg, val);
+ pr_debug("[%d] In mt9v111_write_reg (0x%x, 0x%x)\n", sensorid , reg, val);
pr_debug(" write reg %x val %x.\n", reg, val);
- return i2c_smbus_write_word_data(mt9v111_data.i2c_client,
+ return i2c_smbus_write_word_data(mt9v111_data[sensorid].i2c_client,
reg, cpu_to_be16(val));
}
/*!
- * Initialize mt9v111_sensor_lib
+ * Initialize mt9v111_sensor_lib_datasheet
* Libarary for Sensor configuration through I2C
*
* @param coreReg Core Registers
@@ -122,7 +151,7 @@ static inline int mt9v111_write_reg(u8 reg, u16 val)
*
* @return status
*/
-static u8 mt9v111_sensor_lib(mt9v111_coreReg * coreReg, mt9v111_IFPReg * ifpReg)
+static u8 mt9v111_sensor_lib_datasheet(int sensorid , mt9v111_coreReg * coreReg, mt9v111_IFPReg * ifpReg)
{
u8 reg;
u16 data;
@@ -130,200 +159,103 @@ static u8 mt9v111_sensor_lib(mt9v111_coreReg * coreReg, mt9v111_IFPReg * ifpReg)
pr_debug("In mt9v111_sensor_lib\n");
+ /* IFP R51(0x33)=5137,R57(0x39)=290,R59(0x3B)=1068,R62(0x3E)=4095,R89(0x59)=504,R90(0x5A)=605,R92(0x5C)=8222,R93(0x5D)=10021,R100(0x64)=4477 */
+
/*
* setup to IFP registers
*/
reg = MT9V111I_ADDR_SPACE_SEL;
data = ifpReg->addrSpaceSel;
- mt9v111_write_reg(reg, data);
-
- /* Operation Mode Control */
- reg = MT9V111I_MODE_CONTROL;
- data = ifpReg->modeControl;
- mt9v111_write_reg(reg, data);
-
- /* Output format */
- reg = MT9V111I_FORMAT_CONTROL;
- data = ifpReg->formatControl; /* Set bit 12 */
- mt9v111_write_reg(reg, data);
-
- /* AE limit 4 */
- reg = MT9V111I_SHUTTER_WIDTH_LIMIT_AE;
- data = ifpReg->gainLimitAE;
- mt9v111_write_reg(reg, data);
-
- reg = MT9V111I_OUTPUT_FORMAT_CTRL2;
- data = ifpReg->outputFormatCtrl2;
- mt9v111_write_reg(reg, data);
-
- reg = MT9V111I_AE_SPEED;
- data = ifpReg->AESpeed;
- mt9v111_write_reg(reg, data);
-
- /* output image size */
- reg = MT9V111i_H_PAN;
- data = 0x8000 | ifpReg->HPan;
- mt9v111_write_reg(reg, data);
-
- reg = MT9V111i_H_ZOOM;
- data = 0x8000 | ifpReg->HZoom;
- mt9v111_write_reg(reg, data);
-
- reg = MT9V111i_H_SIZE;
- data = 0x8000 | ifpReg->HSize;
- mt9v111_write_reg(reg, data);
-
- reg = MT9V111i_V_PAN;
- data = 0x8000 | ifpReg->VPan;
- mt9v111_write_reg(reg, data);
+ mt9v111_write_reg(sensorid,reg, data);
- reg = MT9V111i_V_ZOOM;
- data = 0x8000 | ifpReg->VZoom;
- mt9v111_write_reg(reg, data);
+ reg = MT9V111I_LIMIT_SHARP_SATU_CTRL;
+ data = ifpReg->limitSharpSatuCtrl;
+ mt9v111_write_reg(sensorid,reg, data);
- reg = MT9V111i_V_SIZE;
- data = 0x8000 | ifpReg->VSize;
- mt9v111_write_reg(reg, data);
-
- reg = MT9V111i_H_PAN;
- data = ~0x8000 & ifpReg->HPan;
- mt9v111_write_reg(reg, data);
-#if 0
reg = MT9V111I_UPPER_SHUTTER_DELAY_LIM;
data = ifpReg->upperShutterDelayLi;
- mt9v111_write_reg(reg, data);
+ mt9v111_write_reg(sensorid,reg, data);
+
+ reg = MT9V111I_IPF_BLACK_LEVEL_SUB;
+ data = ifpReg->ipfBlackLevelSub;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ reg = MT9V111I_GAIN_THRE_CCAM_ADJ;
+ data = ifpReg->agimnThreCamAdj;
+ mt9v111_write_reg(sensorid,reg, data);
reg = MT9V111I_SHUTTER_60;
data = ifpReg->shutter_width_60;
- mt9v111_write_reg(reg, data);
+ mt9v111_write_reg(sensorid,reg, data);
+
+ reg = MT9V111I_AUTO_EXPOSURE_17;
+ data = ifpReg->auto_exposure_17;
+ mt9v111_write_reg(sensorid,reg, data);
reg = MT9V111I_SEARCH_FLICK_60;
data = ifpReg->search_flicker_60;
- mt9v111_write_reg(reg, data);
-#endif
+ mt9v111_write_reg(sensorid,reg, data);
+
+ reg = MT9V111I_RESERVED93;
+ data = ifpReg->reserved93;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ reg = MT9V111I_RESERVED100;
+ data = ifpReg->reserved100;
+ mt9v111_write_reg(sensorid,reg, data);
/*
* setup to sensor core registers
*/
reg = MT9V111I_ADDR_SPACE_SEL;
data = coreReg->addressSelect;
- mt9v111_write_reg(reg, data);
-
- /* enable changes and put the Sync bit on */
- reg = MT9V111S_OUTPUT_CTRL;
- data = MT9V111S_OUTCTRL_SYNC | MT9V111S_OUTCTRL_CHIP_ENABLE | 0x3000;
- mt9v111_write_reg(reg, data);
+ mt9v111_write_reg(sensorid,reg, data);
- /* min PIXCLK - Default */
- reg = MT9V111S_PIXEL_CLOCK_SPEED;
- data = coreReg->pixelClockSpeed;
- mt9v111_write_reg(reg, data);
+ /* Core R5=46, R7[4]=0 (DEFAULT) ,R33=58369*/
- /* Setup image flipping / Dark rows / row/column skip */
- reg = MT9V111S_READ_MODE;
- data = coreReg->readMode;
- mt9v111_write_reg(reg, data);
-
- /* zoom 0 */
- reg = MT9V111S_DIGITAL_ZOOM;
- data = coreReg->digitalZoom;
- mt9v111_write_reg(reg, data);
-
- /* min H-blank */
reg = MT9V111S_HOR_BLANKING;
data = coreReg->horizontalBlanking;
- mt9v111_write_reg(reg, data);
-
- /* min V-blank */
- reg = MT9V111S_VER_BLANKING;
- data = coreReg->verticalBlanking;
- mt9v111_write_reg(reg, data);
-
- reg = MT9V111S_SHUTTER_WIDTH;
- data = coreReg->shutterWidth;
- mt9v111_write_reg(reg, data);
+ mt9v111_write_reg(sensorid,reg, data);
- reg = MT9V111S_SHUTTER_DELAY;
- data = ifpReg->upperShutterDelayLi;
- mt9v111_write_reg(reg, data);
-
- /* changes become effective */
- reg = MT9V111S_OUTPUT_CTRL;
- data = MT9V111S_OUTCTRL_CHIP_ENABLE | 0x3000;
- mt9v111_write_reg(reg, data);
+ reg = MT9V111S_RESERVED33;
+ data = coreReg->reserved33;
+ mt9v111_write_reg(sensorid,reg, data);
return error;
}
-/*!
- * MT9V111 frame rate calculate
- *
- * @param frame_rate int *
- * @param mclk int
- * @return None
- */
-static void mt9v111_rate_cal(int *frame_rate, int mclk)
+void mt9v111_config_datasheet(void)
{
- int num_clock_per_row;
- int max_rate = 0;
+ pr_debug("In mt9v111_config_datasheet\n");
- pr_debug("In mt9v111_rate_cal\n");
+ mt9v111_device.coreReg->addressSelect = MT9V111I_SEL_SCA;
- num_clock_per_row = (MT9V111_MAX_WIDTH + 114 + MT9V111_HORZBLANK_MIN)
- * 2;
- max_rate = mclk / (num_clock_per_row *
- (MT9V111_MAX_HEIGHT + MT9V111_VERTBLANK_DEFAULT));
+ /* MT9V111I_ADDR_SPACE_SEL */
+ mt9v111_device.ifpReg->addrSpaceSel = MT9V111I_SEL_IFP;
- if ((*frame_rate > max_rate) || (*frame_rate == 0)) {
- *frame_rate = max_rate;
- }
+ /* Recommended values for 30fps @ 27MHz from datasheet*/
- mt9v111_device.coreReg->verticalBlanking
- = mclk / (*frame_rate * num_clock_per_row) - MT9V111_MAX_HEIGHT;
+ /* Core R5=132, R6=10 , R7[4]=0 (DEFAULT) ,R33=58369*/
- reset_frame_rate = *frame_rate;
-}
+ mt9v111_device.coreReg->horizontalBlanking = 132;
+ mt9v111_device.coreReg->verticalBlanking = 10;
+ mt9v111_device.coreReg->reserved33 = 58369;
-/*!
- * MT9V111 sensor configuration
- */
-void mt9v111_config(void)
-{
- pr_debug("In mt9v111_config\n");
+ /* IFP R51(0x33)=5137,R57(0x39)=290,R59(0x3B)=1068,R62(0x3E)=4095,R89(0x59)=504,R90(0x5A)=605,R92(0x5C)=8222,R93(0x5D)=10021,R100(0x64)=4477 */
- mt9v111_device.coreReg->addressSelect = MT9V111I_SEL_SCA;
- mt9v111_device.ifpReg->addrSpaceSel = MT9V111I_SEL_IFP;
+ mt9v111_device.ifpReg->limitSharpSatuCtrl = 5137;
+ mt9v111_device.ifpReg->upperShutterDelayLi = 290;
+ mt9v111_device.ifpReg->ipfBlackLevelSub = 1068;
+ mt9v111_device.ifpReg->agimnThreCamAdj = 4095;
- mt9v111_device.coreReg->windowHeight = MT9V111_WINHEIGHT;
- mt9v111_device.coreReg->windowWidth = MT9V111_WINWIDTH;
- mt9v111_device.coreReg->zoomColStart = 0;
- mt9v111_device.coreReg->zomRowStart = 0;
- mt9v111_device.coreReg->digitalZoom = 0x0;
-
- mt9v111_device.coreReg->verticalBlanking = MT9V111_VERTBLANK_DEFAULT;
- mt9v111_device.coreReg->horizontalBlanking = MT9V111_HORZBLANK_MIN;
- mt9v111_device.coreReg->pixelClockSpeed = 0;
- mt9v111_device.coreReg->readMode = 0xd0a1;
-
- mt9v111_device.ifpReg->outputFormatCtrl2 = 0;
- mt9v111_device.ifpReg->gainLimitAE = 0x300;
- mt9v111_device.ifpReg->AESpeed = 0x80;
-
- /* here is the default value */
- mt9v111_device.ifpReg->formatControl = 0xc800;
- mt9v111_device.ifpReg->modeControl = 0x708e;
- mt9v111_device.ifpReg->awbSpeed = 0x4514;
- mt9v111_device.coreReg->shutterWidth = 0xf8;
-
- /* output size */
- mt9v111_device.ifpReg->HPan = 0;
- mt9v111_device.ifpReg->HZoom = MT9V111_MAX_WIDTH;
- mt9v111_device.ifpReg->HSize = MT9V111_MAX_WIDTH;
- mt9v111_device.ifpReg->VPan = 0;
- mt9v111_device.ifpReg->VZoom = MT9V111_MAX_HEIGHT;
- mt9v111_device.ifpReg->VSize = MT9V111_MAX_HEIGHT;
+ mt9v111_device.ifpReg->shutter_width_60 = 504;
+ mt9v111_device.ifpReg->auto_exposure_17 = 605;
+ mt9v111_device.ifpReg->search_flicker_60 = 8222;
+ mt9v111_device.ifpReg->reserved93 = 10021;
+ mt9v111_device.ifpReg->reserved100 = 4477;
}
+
/*!
* mt9v111 sensor set saturtionn
*
@@ -331,7 +263,7 @@ void mt9v111_config(void)
* @return Error code of 0.
*/
-static int mt9v111_set_saturation(int saturation)
+static int mt9v111_set_saturation(int sensorid , int saturation)
{
u8 reg;
u16 data;
@@ -357,6 +289,9 @@ static int mt9v111_set_saturation(int saturation)
case 25:
mt9v111_device.ifpReg->awbSpeed = 0x6514;
break;
+ case 0:
+ mt9v111_device.ifpReg->awbSpeed = 0x7514;
+ break;
default:
mt9v111_device.ifpReg->awbSpeed = 0x4514;
break;
@@ -364,12 +299,348 @@ static int mt9v111_set_saturation(int saturation)
reg = MT9V111I_ADDR_SPACE_SEL;
data = mt9v111_device.ifpReg->addrSpaceSel;
- mt9v111_write_reg(reg, data);
+ mt9v111_write_reg(sensorid,reg, data);
/* Operation Mode Control */
reg = MT9V111I_AWB_SPEED;
data = mt9v111_device.ifpReg->awbSpeed;
- mt9v111_write_reg(reg, data);
+ mt9v111_write_reg(sensorid,reg, data);
+
+ return 0;
+}
+
+#if 0
+/*!
+ * mt9v111 sensor set digital zoom
+ *
+ * @param on/off int
+
+ * @return 0 on success, -1 on error.
+ */
+static int mt9v111_set_digitalzoom(int sensorid , unsigned int on)
+{
+ u8 reg;
+ u16 data;
+ pr_debug("In mt9v111_set_digitalzoom(%d)\n",on);
+
+ if( on > 1 )
+ return -1;
+
+ mt9v111_device.coreReg->digitalZoom = on;
+
+ reg = MT9V111I_ADDR_SPACE_SEL;
+ data = mt9v111_device.coreReg->addressSelect;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ /* Operation Mode Control */
+ reg = MT9V111S_DIGITAL_ZOOM;
+ data = mt9v111_device.coreReg->digitalZoom;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ return 0;
+}
+
+/*!
+ * mt9v111 sensor set digital pan
+ *
+ * @param pan_level int
+
+ * @return 0 on success, -1 on error.
+ */
+static int mt9v111_set_digitalpan (int sensorid , int pan_level)
+{
+ u8 reg;
+ u16 data;
+ pr_debug("In mt9v111_set_digitalpan(%d)\n",
+ pan_level);
+
+ mt9v111_device.ifpReg->HPan = 8;
+ if (pan_level & 0xFFFF0000) {
+ pan_level = (0xFFFFFFFF - pan_level);
+ pan_level = pan_level / 0x14;
+ mt9v111_device.ifpReg->HPan =
+ mt9v111_device.ifpReg->HPan - (pan_level & 0x3FF);
+ } else {
+ pan_level = pan_level / 0x14;
+ mt9v111_device.ifpReg->HPan =
+ mt9v111_device.ifpReg->HPan + (pan_level - 1);
+ }
+
+ reg = MT9V111I_ADDR_SPACE_SEL;
+ data = mt9v111_device.ifpReg->addrSpaceSel;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ /* Operation Mode Control */
+ reg = MT9V111i_H_PAN;
+ data = mt9v111_device.ifpReg->HPan;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ return 0;
+}
+
+/*!
+ * mt9v111 sensor set digital tilt
+ *
+ * @param tilt_level int
+
+ * @return 0 on success, -1 on error.
+ */
+static int mt9v111_set_digitaltilt (int sensorid , int tilt_level)
+{
+ u8 reg;
+ u16 data;
+ pr_debug("In mt9v111_set_digitaltilt(%d)\n",
+ tilt_level);
+
+ mt9v111_device.ifpReg->VPan = 8;
+ if( tilt_level & 0xFFFF0000 ) {
+ tilt_level = (0xFFFFFFFF - tilt_level);
+ tilt_level = tilt_level / 0x14;
+ mt9v111_device.ifpReg->VPan = mt9v111_device.ifpReg->VPan - (tilt_level & 0x3FF);
+ }
+ else {
+ tilt_level = tilt_level / 0x14;
+ mt9v111_device.ifpReg->VPan = mt9v111_device.ifpReg->VPan + (tilt_level - 1);
+ }
+
+ reg = MT9V111I_ADDR_SPACE_SEL;
+ data = mt9v111_device.ifpReg->addrSpaceSel;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ /* Operation Mode Control */
+ reg = MT9V111i_V_PAN;
+ data = mt9v111_device.ifpReg->VPan;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ return 0;
+}
+
+/*!
+ * mt9v111 sensor set output resolution
+ *
+ * @param resolution res
+
+ * @return 0 on success, -1 on error.
+ */
+static int mt9v111_set_outputresolution(int sensorid , MT9V111_OutputResolution res)
+{
+ u8 reg;
+ u16 data;
+ int zoom = 0;
+
+ pr_debug("In mt9v111_set_outputresolution(%d)\n",res);
+
+ switch (res) {
+ case MT9V111_OutputResolution_VGA:
+ /* 640x480 */
+ mt9v111_device.ifpReg->HSize = 0x0280;
+ mt9v111_device.ifpReg->VSize = 0x01E0;
+ break;
+
+ case MT9V111_OutputResolution_QVGA:
+ /* 320x240 */
+ mt9v111_device.ifpReg->HSize = 0x0140;
+ mt9v111_device.ifpReg->VSize = 0x00F0;
+ break;
+
+ case MT9V111_OutputResolution_CIF:
+ /* 352x288 */
+ mt9v111_device.ifpReg->HSize = 0x0160;
+ mt9v111_device.ifpReg->VSize = 0x0120;
+ mt9v111_device.ifpReg->HZoom = 0x0160;
+ mt9v111_device.ifpReg->VZoom = 0x0120;
+ zoom = 1;
+ break;
+
+ case MT9V111_OutputResolution_QCIF:
+ /* 176X220 */
+ mt9v111_device.ifpReg->HSize = 0x00B0;
+ mt9v111_device.ifpReg->VSize = 0x0090;
+ mt9v111_device.ifpReg->HZoom = 0x00B0;
+ mt9v111_device.ifpReg->VZoom = 0x0090;
+ zoom = 1;
+ break;
+
+ case MT9V111_OutputResolution_QQVGA:
+ /* 2048*1536 */
+ mt9v111_device.ifpReg->HSize = 0x00A0;
+ mt9v111_device.ifpReg->VSize = 0x0078;
+ mt9v111_device.ifpReg->HZoom = 0x00A0;
+ mt9v111_device.ifpReg->VZoom = 0x0078;
+ zoom = 1;
+ break;
+
+ case MT9V111_OutputResolution_SXGA:
+ /* 1280x1024 */
+ break;
+
+ default:
+ break;
+ }
+
+ reg = MT9V111I_ADDR_SPACE_SEL;
+ data = mt9v111_device.ifpReg->addrSpaceSel;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ reg = MT9V111i_V_SIZE;
+ data = mt9v111_device.ifpReg->VSize;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ reg = MT9V111i_H_SIZE;
+ data = mt9v111_device.ifpReg->HSize;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ if ( zoom ) {
+ reg = MT9V111i_V_ZOOM;
+ data = mt9v111_device.ifpReg->VZoom;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ reg = MT9V111i_H_ZOOM;
+ data = mt9v111_device.ifpReg->HZoom;
+ mt9v111_write_reg(sensorid,reg, data);
+ }
+
+ return 0;
+}
+
+/*!
+ * mt9v111 sensor set digital flash
+ *
+ * @param flash_level int
+
+ * @return 0 on success, -1 on error.
+ */
+static int mt9v111_set_digitalflash (int sensorid , int flash_level)
+{
+ u8 reg;
+ u16 data = mt9v111_read_reg(sensorid,MT9V111i_FLASH_CTRL);
+ pr_debug("In mt9v111_set_digitalflash(%d)\n",
+ flash_level);
+
+ if(flash_level) {
+ data &= (0xFF00);
+ data |= ((flash_level & 0x00FF) | (1<<13));
+ }
+ else {
+ data &= ~(1<<13);
+ }
+
+ reg = MT9V111I_ADDR_SPACE_SEL;
+ data = mt9v111_device.ifpReg->addrSpaceSel;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ /* Operation Mode Control */
+ reg = MT9V111i_FLASH_CTRL;
+ mt9v111_device.ifpReg->flashCtrl = data;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ return 0;
+}
+
+/*!
+ * mt9v111 sensor set digital monochrome
+ *
+ * @param on int
+
+ * @return 0 on success, -1 on error.
+ */
+static int mt9v111_set_digitalmonochrome (int sensorid , int on)
+{
+ u8 reg;
+ u16 data = mt9v111_read_reg(sensorid,MT9V111I_FORMAT_CONTROL);
+ pr_debug("In mt9v111_set_digitalmonochrome(%d)\n",
+ on);
+
+ /* clear the monochrome bit field */
+ data &= ~(1<<5);
+
+ /* enable or disable monochrome mode */
+ if( on )
+ data |= (0<<5);
+ else
+ data |= (1<<5);
+
+ reg = MT9V111I_ADDR_SPACE_SEL;
+ data = mt9v111_device.ifpReg->addrSpaceSel;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ /* Operation Mode Control */
+ reg = MT9V111I_FORMAT_CONTROL;
+ mt9v111_device.ifpReg->formatControl = data;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ return 0;
+}
+#endif
+
+/*!
+ * mt9v111 sensor set digital sharpness
+ *
+ * @param value int
+
+ * @return 0 on success, -1 on error.
+ */
+static int mt9v111_set_digitalsharpness (int sensorid , int value)
+{
+ u8 reg;
+ u16 data ;
+
+ pr_debug("In mt9v111_set_digitalsharpness(%d)\n",value);
+
+ reg = MT9V111I_ADDR_SPACE_SEL;
+ data = mt9v111_device.ifpReg->addrSpaceSel;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ data = mt9v111_read_reg(sensorid,MT9V111I_APERTURE_GAIN);
+
+ /* erase current and remove auto reduce sharpness in low light */
+ data &= ~(0x000F);
+ data |= (value & (0x000F));
+ if( data > (0x000F) )
+ return -1;
+
+ /* Operation Mode Control */
+ reg = MT9V111I_APERTURE_GAIN;
+ mt9v111_device.ifpReg->apertureGain = data;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ return 0;
+}
+
+/*!
+ * mt9v111 sensor set digital brightness
+ *
+ * @param value int
+
+ * @return 0 on success, -1 on error.
+ */
+static int mt9v111_set_digitalbrightness (int sensorid , int value)
+{
+ u8 reg;
+ u16 data;
+ u32 max_brightness, min_brightness;
+
+ data = mt9v111_read_reg(sensorid,MT9V111I_CLIP_LIMIT_OUTPUT_LUMI);
+ max_brightness = data >> 8;
+ min_brightness = (u8)data;
+
+ if( value > max_brightness )
+ value = max_brightness;
+ else if( value < min_brightness )
+ value = min_brightness;
+
+ reg = MT9V111I_ADDR_SPACE_SEL;
+ data = mt9v111_device.ifpReg->addrSpaceSel;
+ mt9v111_write_reg(sensorid,reg, data);
+
+ data = mt9v111_read_reg(sensorid,MT9V111I_AE_PRECISION_TARGET);
+ data &= 0xFF00; /* Clear target luminance */
+ data |= ((u8)value );
+
+ /* Operation Mode Control */
+ reg = MT9V111I_AE_PRECISION_TARGET;
+ mt9v111_device.ifpReg->AEPrecisionTarget = data;
+ mt9v111_write_reg(sensorid,reg, data);
return 0;
}
@@ -380,7 +651,7 @@ static int mt9v111_set_saturation(int saturation)
* @param ae_mode int
* @return Error code of 0 (no Error)
*/
-static int mt9v111_set_ae_mode(int ae_mode)
+static int mt9v111_set_ae_mode(int sensorid , int ae_mode)
{
u8 reg;
u16 data;
@@ -408,19 +679,20 @@ static int mt9v111_set_ae_mode(int ae_mode)
/* V4L2_EXPOSURE_MANUAL = 1 needs register setting of 0x308E */
mt9v111_device.ifpReg->modeControl &= 0x3fff;
mt9v111_device.ifpReg->modeControl |= (ae_mode & 0x03) << 14;
- mt9v111_data.ae_mode = ae_mode;
+ mt9v111_data[sensorid].ae_mode = ae_mode;
reg = MT9V111I_ADDR_SPACE_SEL;
data = mt9v111_device.ifpReg->addrSpaceSel;
- mt9v111_write_reg(reg, data);
+ mt9v111_write_reg(sensorid,reg, data);
reg = MT9V111I_MODE_CONTROL;
data = mt9v111_device.ifpReg->modeControl;
- mt9v111_write_reg(reg, data);
+ mt9v111_write_reg(sensorid,reg, data);
return 0;
}
+#if 0
/*!
* mt9v111 sensor get AE measurement window mode configuration
*
@@ -435,6 +707,7 @@ static void mt9v111_get_ae_mode(int *ae_mode)
*ae_mode = (mt9v111_device.ifpReg->modeControl & 0xc) >> 2;
}
}
+#endif
#ifdef MT9V111_DEBUG
/*!
@@ -442,33 +715,33 @@ static void mt9v111_get_ae_mode(int *ae_mode)
*
* @return none
*/
-static void mt9v111_test_pattern(bool flag)
+static void mt9v111_test_pattern(int sensorid , bool flag)
{
u16 data;
/* switch to sensor registers */
- mt9v111_write_reg(MT9V111I_ADDR_SPACE_SEL, MT9V111I_SEL_SCA);
+ mt9v111_write_reg(sensorid,MT9V111I_ADDR_SPACE_SEL, MT9V111I_SEL_SCA);
if (flag == true) {
testpattern = MT9V111S_OUTCTRL_TEST_MODE;
- data = mt9v111_read_reg(MT9V111S_ROW_NOISE_CTRL) & 0xBF;
- mt9v111_write_reg(MT9V111S_ROW_NOISE_CTRL, data);
+ data = mt9v111_read_reg(sensorid,MT9V111S_ROW_NOISE_CTRL) & 0xBF;
+ mt9v111_write_reg(sensorid,MT9V111S_ROW_NOISE_CTRL, data);
- mt9v111_write_reg(MT9V111S_TEST_DATA, 0);
+ mt9v111_write_reg(sensorid,MT9V111S_TEST_DATA, 0);
/* changes take effect */
data = MT9V111S_OUTCTRL_CHIP_ENABLE | testpattern | 0x3000;
- mt9v111_write_reg(MT9V111S_OUTPUT_CTRL, data);
+ mt9v111_write_reg(sensorid,MT9V111S_OUTPUT_CTRL, data);
} else {
testpattern = 0;
- data = mt9v111_read_reg(MT9V111S_ROW_NOISE_CTRL) | 0x40;
+ data = mt9v111_read_reg(sensorid,MT9V111S_ROW_NOISE_CTRL) | 0x40;
mt9v111_write_reg(MT9V111S_ROW_NOISE_CTRL, data);
/* changes take effect */
data = MT9V111S_OUTCTRL_CHIP_ENABLE | testpattern | 0x3000;
- mt9v111_write_reg(MT9V111S_OUTPUT_CTRL, data);
+ mt9v111_write_reg(sensorid,MT9V111S_OUTPUT_CTRL, data);
}
}
#endif
@@ -507,6 +780,7 @@ static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
p->u.bt656.clock_curr = MT9V111_MCLK;
p->if_type = V4L2_IF_TYPE_BT656;
p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.bt_sync_correct = 1; // translates to CSI ext vsync
p->u.bt656.clock_min = MT9V111_CLK_MIN;
p->u.bt656.clock_max = MT9V111_CLK_MAX;
@@ -534,10 +808,12 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on)
sensor->on = on;
- if (on)
- gpio_sensor_active();
- else
- gpio_sensor_inactive();
+ if(on) {
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, 0 /* cam->csi */, true, true);
+ }
+ else {
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, 0 /* cam->csi */, false, false);
+ }
return 0;
}
@@ -554,19 +830,23 @@ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
int ret = 0;
struct v4l2_captureparm *cparm = &a->parm.capture;
/* s->priv points to mt9v111_data */
+ int sensorid = mt9v111_id_from_name(((struct sensor *)s->priv)->v4l2_int_device->name);
pr_debug("In mt9v111:ioctl_g_parm\n");
+ if( sensorid < 0 )
+ return ret;
+
switch (a->type) {
/* This is the only case currently handled. */
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
memset(a, 0, sizeof(*a));
a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- cparm->capability = mt9v111_data.streamcap.capability;
+ cparm->capability = mt9v111_data[sensorid].streamcap.capability;
cparm->timeperframe =
- mt9v111_data.streamcap.timeperframe;
- cparm->capturemode = mt9v111_data.streamcap.capturemode;
+ mt9v111_data[sensorid].streamcap.timeperframe;
+ cparm->capturemode = mt9v111_data[sensorid].streamcap.capturemode;
ret = 0;
break;
@@ -605,9 +885,13 @@ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
int ret = 0;
struct v4l2_captureparm *cparm = &a->parm.capture;
/* s->priv points to mt9v111_data */
+ int sensorid = mt9v111_id_from_name(((struct sensor *)s->priv)->v4l2_int_device->name);
pr_debug("In mt9v111:ioctl_s_parm\n");
+ if( sensorid < 0 )
+ return ret;
+
switch (a->type) {
/* This is the only case currently handled. */
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -617,13 +901,13 @@ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
* Changing the frame rate is not allowed on this
*camera. */
if (cparm->timeperframe.denominator !=
- mt9v111_data.streamcap.timeperframe.denominator) {
+ mt9v111_data[sensorid].streamcap.timeperframe.denominator) {
pr_err("ERROR: mt9v111: ioctl_s_parm: " \
"This camera does not allow frame rate "
"changes.\n");
ret = -EINVAL;
} else {
- mt9v111_data.streamcap.timeperframe =
+ mt9v111_data[sensorid].streamcap.timeperframe =
cparm->timeperframe;
/* Call any camera functions to match settings. */
}
@@ -635,7 +919,7 @@ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
"unsupported capture mode\n");
ret = -EINVAL;
} else {
- mt9v111_data.streamcap.capturemode =
+ mt9v111_data[sensorid].streamcap.capturemode =
cparm->capturemode;
/* Call any camera functions to match settings. */
/* Right now this camera only supports 1 mode. */
@@ -685,6 +969,7 @@ static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
return 0;
}
+#if 0
/*!
* ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl
* @s: pointer to standard V4L2 device structure
@@ -700,6 +985,7 @@ static int ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qc)
return 0;
}
+#endif
/*!
* ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
@@ -712,66 +998,29 @@ static int ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qc)
*/
static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
{
+ int sensorid = mt9v111_id_from_name(((struct sensor *)s->priv)->v4l2_int_device->name);
+
pr_debug("In mt9v111:ioctl_g_ctrl\n");
+ if( sensorid < 0 )
+ return 0;
+
switch (vc->id) {
case V4L2_CID_BRIGHTNESS:
pr_debug(" V4L2_CID_BRIGHTNESS\n");
- vc->value = mt9v111_data.brightness;
- break;
- case V4L2_CID_CONTRAST:
- pr_debug(" V4L2_CID_CONTRAST\n");
- vc->value = mt9v111_data.contrast;
+ vc->value = mt9v111_data[sensorid].brightness;
break;
case V4L2_CID_SATURATION:
pr_debug(" V4L2_CID_SATURATION\n");
- vc->value = mt9v111_data.saturation;
- break;
- case V4L2_CID_HUE:
- pr_debug(" V4L2_CID_HUE\n");
- vc->value = mt9v111_data.hue;
- break;
- case V4L2_CID_AUTO_WHITE_BALANCE:
- pr_debug(
- " V4L2_CID_AUTO_WHITE_BALANCE\n");
- vc->value = 0;
- break;
- case V4L2_CID_DO_WHITE_BALANCE:
- pr_debug(
- " V4L2_CID_DO_WHITE_BALANCE\n");
- vc->value = 0;
- break;
- case V4L2_CID_RED_BALANCE:
- pr_debug(" V4L2_CID_RED_BALANCE\n");
- vc->value = mt9v111_data.red;
- break;
- case V4L2_CID_BLUE_BALANCE:
- pr_debug(" V4L2_CID_BLUE_BALANCE\n");
- vc->value = mt9v111_data.blue;
- break;
- case V4L2_CID_GAMMA:
- pr_debug(" V4L2_CID_GAMMA\n");
- vc->value = 0;
+ vc->value = mt9v111_data[sensorid].saturation;
break;
case V4L2_CID_EXPOSURE:
pr_debug(" V4L2_CID_EXPOSURE\n");
- vc->value = mt9v111_data.ae_mode;
- break;
- case V4L2_CID_AUTOGAIN:
- pr_debug(" V4L2_CID_AUTOGAIN\n");
- vc->value = 0;
+ vc->value = mt9v111_data[sensorid].ae_mode;
break;
case V4L2_CID_GAIN:
pr_debug(" V4L2_CID_GAIN\n");
- vc->value = 0;
- break;
- case V4L2_CID_HFLIP:
- pr_debug(" V4L2_CID_HFLIP\n");
- vc->value = 0;
- break;
- case V4L2_CID_VFLIP:
- pr_debug(" V4L2_CID_VFLIP\n");
- vc->value = 0;
+ vc->value = mt9v111_data[sensorid].gain;
break;
default:
pr_debug(" Default case\n");
@@ -794,56 +1043,34 @@ static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
{
int retval = 0;
+ int sensorid = mt9v111_id_from_name(((struct sensor *)s->priv)->v4l2_int_device->name);
pr_debug("In mt9v111:ioctl_s_ctrl %d\n",
vc->id);
+ if( sensorid < 0 )
+ return retval;
+
switch (vc->id) {
case V4L2_CID_BRIGHTNESS:
pr_debug(" V4L2_CID_BRIGHTNESS\n");
- break;
- case V4L2_CID_CONTRAST:
- pr_debug(" V4L2_CID_CONTRAST\n");
+ mt9v111_set_digitalbrightness(sensorid,vc->value);
+ mt9v111_data[sensorid].brightness = vc->value;
break;
case V4L2_CID_SATURATION:
pr_debug(" V4L2_CID_SATURATION\n");
- retval = mt9v111_set_saturation(vc->value);
- break;
- case V4L2_CID_HUE:
- pr_debug(" V4L2_CID_HUE\n");
- break;
- case V4L2_CID_AUTO_WHITE_BALANCE:
- pr_debug(
- " V4L2_CID_AUTO_WHITE_BALANCE\n");
- break;
- case V4L2_CID_DO_WHITE_BALANCE:
- pr_debug(
- " V4L2_CID_DO_WHITE_BALANCE\n");
- break;
- case V4L2_CID_RED_BALANCE:
- pr_debug(" V4L2_CID_RED_BALANCE\n");
- break;
- case V4L2_CID_BLUE_BALANCE:
- pr_debug(" V4L2_CID_BLUE_BALANCE\n");
- break;
- case V4L2_CID_GAMMA:
- pr_debug(" V4L2_CID_GAMMA\n");
+ retval = mt9v111_set_saturation(sensorid,vc->value);
+ mt9v111_data[sensorid].saturation = vc->value;
break;
case V4L2_CID_EXPOSURE:
pr_debug(" V4L2_CID_EXPOSURE\n");
- retval = mt9v111_set_ae_mode(vc->value);
- break;
- case V4L2_CID_AUTOGAIN:
- pr_debug(" V4L2_CID_AUTOGAIN\n");
+ retval = mt9v111_set_ae_mode(sensorid,vc->value);
+ mt9v111_data[sensorid].ae_mode = vc->value;
break;
case V4L2_CID_GAIN:
pr_debug(" V4L2_CID_GAIN\n");
- break;
- case V4L2_CID_HFLIP:
- pr_debug(" V4L2_CID_HFLIP\n");
- break;
- case V4L2_CID_VFLIP:
- pr_debug(" V4L2_CID_VFLIP\n");
+ mt9v111_set_digitalsharpness(sensorid,vc->value);
+ mt9v111_data[sensorid].gain = vc->value;
break;
default:
pr_debug(" Default case\n");
@@ -854,13 +1081,41 @@ static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
return retval;
}
+static void mt9v111_ifp_reset ( int sensorid )
+{
+ mt9v111_write_reg(sensorid,MT9V111S_ADDR_SPACE_SEL, 0x0001);
+ mt9v111_write_reg(sensorid,MT9V111I_SOFT_RESET, 0x0001);
+ msleep(100);
+ mt9v111_write_reg(sensorid,MT9V111I_SOFT_RESET, 0x0000);
+ msleep(100);
+}
+
+static void mt9v111_sensor_reset ( int sensorid )
+{
+ mt9v111_write_reg(sensorid,MT9V111S_ADDR_SPACE_SEL, 0x0004);
+ mt9v111_write_reg(sensorid,MT9V111S_RESET, 0x0001);
+ msleep(100);
+ mt9v111_write_reg(sensorid,MT9V111S_RESET, 0x0000);
+ msleep(100);
+}
+
/*!
* ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
* @s: pointer to standard V4L2 device structure
*/
static int ioctl_init(struct v4l2_int_device *s)
{
- pr_debug("In mt9v111:ioctl_init\n");
+ int sensorid = 0;
+
+ sensorid = mt9v111_id_from_name(((struct sensor *)s->priv)->v4l2_int_device->name);
+ if( sensorid < 0 )
+ return 0;
+
+ pr_debug("In mt9v111:ioctl_init for sensor %d\n",sensorid);
+
+ mt9v111_sensor_reset(sensorid);
+ mt9v111_ifp_reset(sensorid);
+ mt9v111_sensor_lib_datasheet(sensorid,mt9v111_device.coreReg, mt9v111_device.ifpReg);
return 0;
}
@@ -873,19 +1128,146 @@ static int ioctl_init(struct v4l2_int_device *s)
*/
static int ioctl_dev_init(struct v4l2_int_device *s)
{
+ int sensorid = 0;
uint32_t clock_rate = MT9V111_MCLK;
+ sensorid = mt9v111_id_from_name(((struct sensor *)s->priv)->v4l2_int_device->name);
+ if( sensorid < 0 )
+ return 0;
+
pr_debug("In mt9v111:ioctl_dev_init\n");
- gpio_sensor_active();
+ set_mclk_rate(&clock_rate, 0); // Both sensors use mclk0 on Digi ccwmx51
+
+ mt9v111_sensor_reset(sensorid);
+ mt9v111_ifp_reset(sensorid);
+ mt9v111_sensor_lib_datasheet(sensorid,mt9v111_device.coreReg, mt9v111_device.ifpReg);
- set_mclk_rate(&clock_rate);
- mt9v111_rate_cal(&reset_frame_rate, clock_rate);
- mt9v111_sensor_lib(mt9v111_device.coreReg, mt9v111_device.ifpReg);
+ return 0;
+}
+
+/* list of image formats supported by sensor */
+static const struct v4l2_fmtdesc mt9v111_formats[] = {
+ {
+ .description = "RGB565",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ },
+ {
+ .description = "YUV422 UYVY",
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ },
+};
+
+#define MT9V111_NUM_CAPTURE_FORMATS ARRAY_SIZE(mt9v111_formats)
+
+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_fmtdesc *fmt)
+{
+ int index = fmt->index;
+
+ switch (fmt->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (index >= MT9V111_NUM_CAPTURE_FORMATS)
+ return -EINVAL;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ fmt->flags = mt9v111_formats[index].flags;
+ strlcpy(fmt->description, mt9v111_formats[index].description,
+ sizeof(fmt->description));
+ fmt->pixelformat = mt9v111_formats[index].pixelformat;
return 0;
}
+static int ioctl_s_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_format *f)
+{
+ unsigned short reg;
+ int sensorid = mt9v111_id_from_name(((struct sensor *)s->priv)->v4l2_int_device->name);
+ struct sensor *sensor = s->priv;
+ /* s->priv points to mt9v111_data */
+
+ if( sensorid < 0 )
+ return -ENODEV;
+
+ /* Select IFP registers */
+ mt9v111_write_reg (sensorid,MT9V111S_ADDR_SPACE_SEL, 0x0001);
+
+ switch (f->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB565:
+ /*MT9V111I_OUTPUT_FORMAT_CTRL2*/
+ reg = mt9v111_read_reg (sensorid,MT9V111I_OUTPUT_FORMAT_CTRL2);
+ reg &= ~(0x3 << 6);
+ mt9v111_write_reg (sensorid,MT9V111I_OUTPUT_FORMAT_CTRL2, reg);
+
+ /* MT9V111I_FORMAT_CONTROL */
+ reg = mt9v111_read_reg(sensorid,MT9V111I_FORMAT_CONTROL);
+ reg |= 1 << 12;
+ mt9v111_write_reg(sensorid,MT9V111I_FORMAT_CONTROL, reg);
+ break;
+
+ case V4L2_PIX_FMT_YUV444:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_YUYV:
+ /* MT9V111I_FORMAT_CONTROL */
+ reg = mt9v111_read_reg(sensorid,MT9V111I_FORMAT_CONTROL);
+ reg &= ~(1 << 12);
+ mt9v111_write_reg(sensorid,MT9V111I_FORMAT_CONTROL, reg);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ sensor->pix.width = f->fmt.pix.width;
+ sensor->pix.height = f->fmt.pix.height;
+ sensor->pix.sizeimage = f->fmt.pix.sizeimage;
+ sensor->pix.pixelformat = f->fmt.pix.pixelformat;
+ return 0;
+}
+
+static int ioctl_try_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+ int i;
+
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ for( i=0 ; i < MT9V111_NUM_CAPTURE_FORMATS ; i++) {
+ if( f->fmt.pix.pixelformat == mt9v111_formats[i].pixelformat )
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ioctl_get_register(struct v4l2_int_device *s,struct v4l2_dbg_register * dreg)
+{
+ int sensorid = mt9v111_id_from_name(((struct sensor *)s->priv)->v4l2_int_device->name);
+
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, 0 /* cam->csi */ , true, true);
+ dreg->val = mt9v111_read_reg (sensorid,dreg->reg);
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, 0 /* cam->csi */ , false, false);
+ return 0;
+}
+
+static int ioctl_set_register(struct v4l2_int_device *s,struct v4l2_dbg_register * dreg)
+{
+ int sensorid = mt9v111_id_from_name(((struct sensor *)s->priv)->v4l2_int_device->name);
+
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, 0 /* cam->csi */ , true, true);
+ mt9v111_write_reg (sensorid,dreg->reg, dreg->val);
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, 0 /* cam->csi */ , false, false);
+ return 0;
+}
+#endif
+
/*!
* This structure defines all the ioctls for this module and links them to the
* enumeration.
@@ -910,16 +1292,23 @@ static struct v4l2_int_ioctl_desc mt9v111_ioctl_desc[] = {
/*!
* VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type.
*/
-/* {vidioc_int_enum_fmt_cap_num,
- (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap}, */
+ {vidioc_int_enum_fmt_cap_num,
+ (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap},
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ {vidioc_int_g_register_num,
+ (v4l2_int_ioctl_func *) ioctl_get_register},
+ {vidioc_int_s_register_num,
+ (v4l2_int_ioctl_func *) ioctl_set_register},
+#endif
/*!
* VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type.
* This ioctl is used to negotiate the image capture size and
* pixel format without actually making it take effect.
*/
-/* {vidioc_int_try_fmt_cap_num,
- (v4l2_int_ioctl_func *) ioctl_try_fmt_cap}, */
+ {vidioc_int_try_fmt_cap_num,
+ (v4l2_int_ioctl_func *) ioctl_try_fmt_cap},
{vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_g_fmt_cap},
@@ -928,7 +1317,7 @@ static struct v4l2_int_ioctl_desc mt9v111_ioctl_desc[] = {
* format, returns error code if format not supported or HW can't be
* correctly configured.
*/
-/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */
+ {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap},
{vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm},
{vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm},
@@ -937,20 +1326,56 @@ static struct v4l2_int_ioctl_desc mt9v111_ioctl_desc[] = {
{vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl},
};
-static struct v4l2_int_slave mt9v111_slave = {
- .ioctls = mt9v111_ioctl_desc,
- .num_ioctls = ARRAY_SIZE(mt9v111_ioctl_desc),
+static struct v4l2_int_slave mt9v111_slave[] = {
+ {
+ .ioctls = mt9v111_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(mt9v111_ioctl_desc),
+ .attach_to = "mxc_v4l2_cap_1",
+ },
+ {
+ .ioctls = mt9v111_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(mt9v111_ioctl_desc),
+ .attach_to = "mxc_v4l2_cap_2",
+ },
};
-static struct v4l2_int_device mt9v111_int_device = {
- .module = THIS_MODULE,
- .name = "mt9v111",
- .type = v4l2_int_type_slave,
- .u = {
- .slave = &mt9v111_slave,
+static struct v4l2_int_device mt9v111_int_device [] = {
+ {
+ .module = THIS_MODULE,
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &mt9v111_slave[0],
+ },
+ },
+ {
+ .module = THIS_MODULE,
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &mt9v111_slave[1],
+ },
},
};
+static int mt9v111_read_id( int sensoridx )
+{
+ int sensorid = 0;
+ int ret = 0;
+
+ mt9v111_write_reg (sensoridx,MT9V111S_ADDR_SPACE_SEL, 0x0004);
+
+ sensorid = mt9v111_read_reg (sensoridx,MT9V111S_CHIP_VERSION);
+ if( sensorid == 0x823a )
+ {
+ printk(KERN_INFO" MT9V111 ID %x\n",sensorid);
+ }
+ else
+ {
+ printk(KERN_ERR" MT9V111 Could not detect sensor (read %x)\n",sensorid);
+ ret = -ENODEV;
+ }
+ return ret;
+}
+
/*!
* mt9v111 I2C probe function
* Function set in i2c_driver struct.
@@ -962,32 +1387,56 @@ static int mt9v111_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int retval;
+ int sensorid;
pr_debug("In mt9v111_probe device id is %s\n", id->name);
+ sensorid = mt9v111_id_from_name(id->name);
+
+ if( sensorid < 0 )
+ return -ENODEV;
+
/* Set initial values for the sensor struct. */
- memset(&mt9v111_data, 0, sizeof(mt9v111_data));
- mt9v111_data.i2c_client = client;
+ memset(&mt9v111_data[sensorid], 0, sizeof(struct sensor));
+ mt9v111_data[sensorid].i2c_client = client;
pr_debug(" client name is %s\n", client->name);
- mt9v111_data.pix.pixelformat = V4L2_PIX_FMT_UYVY;
- mt9v111_data.pix.width = MT9V111_MAX_WIDTH;
- mt9v111_data.pix.height = MT9V111_MAX_HEIGHT;
- mt9v111_data.streamcap.capability = 0; /* No higher resolution or frame
- * frame rate changes supported.
- */
- mt9v111_data.streamcap.timeperframe.denominator = MT9V111_FRAME_RATE;
- mt9v111_data.streamcap.timeperframe.numerator = 1;
+ mt9v111_data[sensorid].pix.pixelformat = V4L2_PIX_FMT_UYVY;
+ mt9v111_data[sensorid].pix.width = MT9V111_MAX_WIDTH;
+ mt9v111_data[sensorid].pix.height = MT9V111_MAX_HEIGHT;
+ mt9v111_data[sensorid].streamcap.capability = 0; /* No higher resolution or frame
+ * frame rate changes supported.*/
+ mt9v111_data[sensorid].streamcap.timeperframe.denominator = MT9V111_FRAME_RATE;
+ mt9v111_data[sensorid].streamcap.timeperframe.numerator = 1;
+
+ strcpy(mt9v111_int_device[sensorid].name,id->name);
+ pr_debug(" video device name is %s\n", mt9v111_data[sensorid].v4l2_int_device->name);
+ mt9v111_data[sensorid].v4l2_int_device = &mt9v111_int_device[sensorid];
+ mt9v111_int_device[sensorid].priv = &mt9v111_data[sensorid];
+
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, sensorid , true, true);
+
+ if( mt9v111_read_id(sensorid) != 0) {
+ printk(KERN_ERR"mt9v111_probe: No sensor found\n");
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, sensorid , false, false);
+ return -ENXIO;
+ }
- mt9v111_int_device.priv = &mt9v111_data;
+#ifdef MT9V111_DEBUG
+ mt9v111_test_pattern(1);
+#endif
+
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, sensorid , false, false);
pr_debug(" type is %d (expect %d)\n",
- mt9v111_int_device.type, v4l2_int_type_slave);
+ mt9v111_int_device[sensorid].type, v4l2_int_type_slave);
pr_debug(" num ioctls is %d\n",
- mt9v111_int_device.u.slave->num_ioctls);
+ mt9v111_int_device[sensorid].u.slave->num_ioctls);
/* This function attaches this structure to the /dev/video0 device.
* The pointer in priv points to the mt9v111_data structure here.*/
- retval = v4l2_int_device_register(&mt9v111_int_device);
+ retval = v4l2_int_device_register(&mt9v111_int_device[sensorid]);
+ if( retval == 0 )
+ mt9v111_data[sensorid].used = 1;
return retval;
}
@@ -998,9 +1447,14 @@ static int mt9v111_probe(struct i2c_client *client,
*/
static int mt9v111_remove(struct i2c_client *client)
{
+ int i;
+
pr_debug("In mt9v111_remove\n");
- v4l2_int_device_unregister(&mt9v111_int_device);
+ for ( i=0 ; i < ARRAY_SIZE(mt9v111_int_device) ; i++ ) {
+ if( mt9v111_data[i].used )
+ v4l2_int_device_unregister(&mt9v111_int_device[i]);
+ }
return 0;
}
@@ -1033,13 +1487,13 @@ static __init int mt9v111_init(void)
memset(mt9v111_device.ifpReg, 0, sizeof(mt9v111_IFPReg));
/* Set contents of the just created structures. */
- mt9v111_config();
+ mt9v111_config_datasheet();
/* Tells the i2c driver what functions to call for this driver. */
err = i2c_add_driver(&mt9v111_i2c_driver);
if (err != 0)
pr_err("%s:driver registration failed, error=%d \n",
- __func__, err);
+ __func__, err);
return err;
}
@@ -1055,7 +1509,6 @@ static void __exit mt9v111_clean(void)
pr_debug("In mt9v111_clean()\n");
i2c_del_driver(&mt9v111_i2c_driver);
- gpio_sensor_inactive();
if (mt9v111_device.coreReg) {
kfree(mt9v111_device.coreReg);
diff --git a/drivers/media/video/mxc/capture/mt9v111.h b/drivers/media/video/mxc/capture/mt9v111.h
index cf38cec4757c..ba91a722a076 100644
--- a/drivers/media/video/mxc/capture/mt9v111.h
+++ b/drivers/media/video/mxc/capture/mt9v111.h
@@ -111,11 +111,14 @@
#define MT9V111I_GAMMA_KNEE_Y90 0x57
#define MT9V111I_GAMMA_VALUE_Y0 0x58
#define MT9V111I_SHUTTER_60 0x59
+#define MT9V111I_AUTO_EXPOSURE_17 0x5A
#define MT9V111I_SEARCH_FLICK_60 0x5c
+#define MT9V111I_RESERVED93 0x5d
#define MT9V111I_RATIO_IMAGE_GAIN_BASE 0x5e
#define MT9V111I_RATIO_IMAGE_GAIN_DELTA 0x5f
#define MT9V111I_SIGN_VALUE_REG5F 0x60
#define MT9V111I_AE_GAIN 0x62
+#define MT9V111I_RESERVED100 0x64
#define MT9V111I_MAX_GAIN_AE 0x67
#define MT9V111I_LENS_CORRECT_CTRL 0x80
#define MT9V111I_SHADING_PARAMETER1 0x81
@@ -173,6 +176,7 @@
#define MT9V111S_ROW_START_IN_ZOOM 0x13
#define MT9V111S_DIGITAL_ZOOM 0x1e
#define MT9V111S_READ_MODE 0x20
+#define MT9V111S_RESERVED33 0x21
#define MT9V111S_DAC_CTRL 0x27
#define MT9V111S_GREEN1_GAIN 0x2b
#define MT9V111S_BLUE_GAIN 0x2c
@@ -278,6 +282,7 @@ typedef struct {
u32 rowNoiseControl;
u32 darkTargetwNC;
u32 testData; /*!< test mode */
+ u32 reserved33;
u32 globalGain;
u32 chipVersion;
u32 darkTargetwoNC;
@@ -375,11 +380,14 @@ typedef struct {
u32 gammaKneeY90; /*!< Gamma knee points Y9 and Y10 */
u32 gammaKneeY0; /*!< Gamma knee point Y0 */
u32 shutter_width_60;
+ u32 auto_exposure_17;
u32 search_flicker_60;
+ u32 reserved93;
u32 ratioImageGainBase;
u32 ratioImageGainDelta;
u32 signValueReg5F;
u32 aeGain;
+ u32 reserved100;
u32 maxGainAE;
u32 lensCorrectCtrl;
u32 shadingParameter1; /*!< Shade Parameters */
diff --git a/drivers/media/video/mxc/capture/mx27_prpsw.c b/drivers/media/video/mxc/capture/mx27_prpsw.c
index ce7db16913ec..eca200a580f2 100644
--- a/drivers/media/video/mxc/capture/mx27_prpsw.c
+++ b/drivers/media/video/mxc/capture/mx27_prpsw.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -702,7 +702,7 @@ static int prp_still_start(void *private)
cam_data *cam = (cam_data *) private;
g_still_on = 1;
- g_prp_cfg.ch2_ptr = (unsigned int)cam->still_buf;
+ g_prp_cfg.ch2_ptr = (unsigned int)cam->still_buf[0];
g_prp_cfg.ch2_ptr2 = 0;
if (prp_v4l2_cfg(&g_prp_cfg, cam))
diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c
index 30ad533b0ebd..be9a988aff2f 100644
--- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c
+++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c
@@ -18,6 +18,8 @@
*
* @ingroup MXC_V4L2_CAPTURE
*/
+
+
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -37,9 +39,9 @@
#include <media/v4l2-int-device.h>
#include "mxc_v4l2_capture.h"
#include "ipu_prp_sw.h"
+#include "asm/delay.h"
static int video_nr = -1;
-static cam_data *g_cam;
/*! This data is used for the output to the display. */
#define MXC_V4L2_CAPTURE_NUM_OUTPUTS 3
@@ -74,21 +76,23 @@ static struct v4l2_output mxc_capture_outputs[MXC_V4L2_CAPTURE_NUM_OUTPUTS] = {
static struct v4l2_input mxc_capture_inputs[MXC_V4L2_CAPTURE_NUM_INPUTS] = {
{
.index = 0,
- .name = "CSI IC MEM",
+ .name = "CSI MEM",
.type = V4L2_INPUT_TYPE_CAMERA,
.audioset = 0,
.tuner = 0,
.std = V4L2_STD_UNKNOWN,
- .status = 0,
+ .status = V4L2_IN_ST_NO_POWER,
},
{
.index = 1,
+// AG: CSI IC MEM works but has problems
+// .name = "CSI IC MEM",
.name = "CSI MEM",
.type = V4L2_INPUT_TYPE_CAMERA,
.audioset = 0,
.tuner = 0,
.std = V4L2_STD_UNKNOWN,
- .status = V4L2_IN_ST_NO_POWER,
+ .status = 0,
},
};
@@ -118,6 +122,7 @@ typedef struct {
u16 active_left; /*!< Active left. */
} video_fmt_t;
+#if 0
/*!
* Description of video formats supported.
*
@@ -128,37 +133,39 @@ static video_fmt_t video_fmts[] = {
{ /*! NTSC */
.v4l2_id = V4L2_STD_NTSC,
.name = "NTSC",
- .raw_width = 720 - 1, /* SENS_FRM_WIDTH */
- .raw_height = 288 - 1, /* SENS_FRM_HEIGHT */
- .active_width = 720, /* ACT_FRM_WIDTH plus 1 */
- .active_height = (480 / 2), /* ACT_FRM_HEIGHT plus 1 */
- .active_top = 12,
+ .raw_width = 720, /* SENS_FRM_WIDTH */
+ .raw_height = 525, /* SENS_FRM_HEIGHT */
+ .active_width = 720, /* ACT_FRM_WIDTH */
+ .active_height = 240, /* ACT_FRM_HEIGHT */
+ .active_top = 0,
.active_left = 0,
},
{ /*! (B, G, H, I, N) PAL */
.v4l2_id = V4L2_STD_PAL,
.name = "PAL",
- .raw_width = 720 - 1,
- .raw_height = (576 / 2) + 24 * 2 - 1,
+ .raw_width = 720,
+ .raw_height = 625,
.active_width = 720,
- .active_height = (576 / 2),
+ .active_height = 288,
.active_top = 0,
.active_left = 0,
},
{ /*! Unlocked standard */
.v4l2_id = V4L2_STD_ALL,
.name = "Autodetect",
- .raw_width = 720 - 1,
- .raw_height = (576 / 2) + 24 * 2 - 1,
+ .raw_width = 720,
+ .raw_height = 625,
.active_width = 720,
- .active_height = (576 / 2),
+ .active_height = 288,
.active_top = 0,
.active_left = 0,
},
};
+
/*!* Standard index of TV. */
static video_fmt_idx video_index = TV_NOT_LOCKED;
+#endif
static int mxc_v4l2_master_attach(struct v4l2_int_device *slave);
static void mxc_v4l2_master_detach(struct v4l2_int_device *slave);
@@ -172,15 +179,27 @@ static struct v4l2_int_master mxc_v4l2_master = {
.detach = mxc_v4l2_master_detach,
};
-static struct v4l2_int_device mxc_v4l2_int_device = {
+static struct v4l2_int_device mxc_v4l2_int_device [] = {
+ {
+ .module = THIS_MODULE,
+ .name = "mxc_v4l2_cap_1",
+ .type = v4l2_int_type_master,
+ .u = {
+ .master = &mxc_v4l2_master,
+ },
+ },
+ {
.module = THIS_MODULE,
- .name = "mxc_v4l2_cap",
+ .name = "mxc_v4l2_cap_2",
.type = v4l2_int_type_master,
.u = {
.master = &mxc_v4l2_master,
},
+ },
};
+static cam_data *g_cam[ARRAY_SIZE(mxc_v4l2_int_device)];
+
/***************************************************************************
* Functions for handling Frame buffers.
**************************************************************************/
@@ -260,6 +279,7 @@ static int mxc_allocate_frame_buf(cam_data *cam, int count)
static void mxc_free_frames(cam_data *cam)
{
int i;
+ unsigned long lock_flags;
pr_debug("In MVC:mxc_free_frames\n");
@@ -269,9 +289,11 @@ static void mxc_free_frames(cam_data *cam)
cam->enc_counter = 0;
cam->skip_frame = 0;
+ spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags);
INIT_LIST_HEAD(&cam->ready_q);
INIT_LIST_HEAD(&cam->working_q);
INIT_LIST_HEAD(&cam->done_q);
+ spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags);
}
/*!
@@ -331,8 +353,7 @@ static int mxc_streamon(cam_data *cam)
{
struct mxc_v4l_frame *frame;
int err = 0;
-
- pr_debug("In MVC:mxc_streamon\n");
+ unsigned long lock_flags;
if (NULL == cam) {
pr_err("ERROR! cam parameter is NULL\n");
@@ -363,23 +384,27 @@ static int mxc_streamon(cam_data *cam)
}
}
+ spin_lock_irqsave(&cam->queue_int_lock, lock_flags);
cam->ping_pong_csi = 0;
if (cam->enc_update_eba) {
- frame =
- list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
- list_del(cam->ready_q.next);
- list_add_tail(&frame->queue, &cam->working_q);
- err = cam->enc_update_eba(frame->buffer.m.offset,
- &cam->ping_pong_csi);
frame =
list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
list_del(cam->ready_q.next);
list_add_tail(&frame->queue, &cam->working_q);
- err |= cam->enc_update_eba(frame->buffer.m.offset,
- &cam->ping_pong_csi);
+ err = cam->enc_update_eba(cam->csi,frame->buffer.m.offset,
+ &cam->ping_pong_csi);
+ if (!list_empty(&cam->ready_q)) {
+ frame =
+ list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
+ list_del(cam->ready_q.next);
+ list_add_tail(&frame->queue, &cam->working_q);
+ err |= cam->enc_update_eba(cam->csi,frame->buffer.m.offset,
+ &cam->ping_pong_csi);
+ }
+ cam->capture_on = true;
} else {
- return -EINVAL;
+ err = -EINVAL;
}
if (cam->overlay_on == true)
@@ -387,11 +412,9 @@ static int mxc_streamon(cam_data *cam)
if (cam->enc_enable_csi) {
err = cam->enc_enable_csi(cam);
- if (err != 0)
- return err;
}
- cam->capture_on = true;
+ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
return err;
}
@@ -543,8 +566,6 @@ static int start_preview(cam_data *cam)
{
int err = 0;
- pr_debug("MVC: start_preview\n");
-
#if defined(CONFIG_MXC_IPU_PRP_VF_SDC) || defined(CONFIG_MXC_IPU_PRP_VF_SDC_MODULE)
pr_debug(" This is an SDC display\n");
if (cam->output == 0 || cam->output == 2) {
@@ -602,8 +623,6 @@ static int stop_preview(cam_data *cam)
{
int err = 0;
- pr_debug("MVC: stop preview\n");
-
#if defined(CONFIG_MXC_IPU_PRP_VF_ADC) || defined(CONFIG_MXC_IPU_PRP_VF_ADC_MODULE)
if (cam->output == 1) {
err = prp_vf_adc_deselect(cam);
@@ -674,6 +693,29 @@ static int mxc_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f)
__func__,
cam->crop_current.width, cam->crop_current.height);
+ retval = vidioc_int_g_fmt_cap(cam->sensor,f);
+ return retval;
+}
+
+/*!
+ * V4L2 - mxc_v4l2_enum_fmt function
+ *
+ * @param cam structure cam_data *
+ *
+ * @param f structure v4l2_fmtdesc *
+ *
+ * @return status 0 success, EINVAL failed
+ */
+static int mxc_v4l2_enum_fmt(cam_data *cam, struct v4l2_fmtdesc *f)
+{
+ int retval = 0;
+
+ pr_debug("In MVC: mxc_v4l2_enum_fmt\n");
+
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, true, true);
+ retval = vidioc_int_enum_fmt_cap(cam->sensor,f);
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, false, false);
+
return retval;
}
@@ -709,10 +751,14 @@ static int mxc_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
* for CSI MEM input mode.
*/
if (strcmp(mxc_capture_inputs[cam->current_input].name,
- "CSI MEM") == 0) {
+ "CSI MEM") == 0 || strcmp(mxc_capture_inputs[cam->current_input].name,
+ "CSI IC MEM") == 0) {
f->fmt.pix.width = cam->crop_current.width;
f->fmt.pix.height = cam->crop_current.height;
}
+ else {
+ printk("Error no match %s\n",mxc_capture_inputs[cam->current_input].name);
+ }
if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
height = &f->fmt.pix.width;
@@ -811,6 +857,13 @@ static int mxc_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
break;
}
}
+
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
+ true, true);
+ vidioc_int_s_fmt_cap(cam->sensor, f);
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
+ false, false);
+
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
@@ -1057,63 +1110,10 @@ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c)
return ret;
}
-/*!
- * V4L2 - mxc_v4l2_s_param function
- * Allows setting of capturemode and frame rate.
- *
- * @param cam structure cam_data *
- * @param parm structure v4l2_streamparm *
- *
- * @return status 0 success, EINVAL failed
- */
-static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
-{
- struct v4l2_ifparm ifparm;
+static int mxc_v4l2_init_csi( cam_data *cam ) {
struct v4l2_format cam_fmt;
- struct v4l2_streamparm currentparm;
ipu_csi_signal_cfg_t csi_param;
- int err = 0;
-
- pr_debug("In mxc_v4l2_s_param\n");
-
- if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- pr_err(KERN_ERR "mxc_v4l2_s_param invalid type\n");
- return -EINVAL;
- }
-
- /* Stop the viewfinder */
- if (cam->overlay_on == true) {
- stop_preview(cam);
- }
-
- currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- /* First check that this device can support the changes requested. */
- err = vidioc_int_g_parm(cam->sensor, &currentparm);
- if (err) {
- pr_err("%s: vidioc_int_g_parm returned an error %d\n",
- __func__, err);
- goto exit;
- }
-
- pr_debug(" Current capabilities are %x\n",
- currentparm.parm.capture.capability);
- pr_debug(" Current capturemode is %d change to %d\n",
- currentparm.parm.capture.capturemode,
- parm->parm.capture.capturemode);
- pr_debug(" Current framerate is %d change to %d\n",
- currentparm.parm.capture.timeperframe.denominator,
- parm->parm.capture.timeperframe.denominator);
-
- /* This will change any camera settings needed. */
- ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, true, true);
- err = vidioc_int_s_parm(cam->sensor, parm);
- ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, false, false);
- if (err) {
- pr_err("%s: vidioc_int_s_parm returned an error %d\n",
- __func__, err);
- goto exit;
- }
+ struct v4l2_ifparm ifparm;
/* If resolution changed, need to re-program the CSI */
/* Get new values. */
@@ -1131,13 +1131,13 @@ static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
csi_param.force_eof = 0;
csi_param.data_en_pol = 0;
csi_param.data_fmt = 0;
- csi_param.csi = 0;
+ csi_param.csi = cam->csi;
csi_param.mclk = 0;
/* This may not work on other platforms. Check when adding a new one.*/
pr_debug(" clock_curr=mclk=%d\n", ifparm.u.bt656.clock_curr);
if (ifparm.u.bt656.clock_curr == 0) {
- csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
+ csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
} else {
csi_param.clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
}
@@ -1189,7 +1189,63 @@ static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
ipu_csi_init_interface(cam->crop_bounds.width,
cam->crop_bounds.height,
cam_fmt.fmt.pix.pixelformat, csi_param);
+ return 0;
+}
+/*!
+ * V4L2 - mxc_v4l2_s_param function
+ * Allows setting of capturemode and frame rate.
+ *
+ * @param cam structure cam_data *
+ * @param parm structure v4l2_streamparm *
+ *
+ * @return status 0 success, EINVAL failed
+ */
+static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
+{
+ struct v4l2_streamparm currentparm;
+ int err = 0;
+
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ pr_err(KERN_ERR "mxc_v4l2_s_param invalid type\n");
+ return -EINVAL;
+ }
+
+ /* Stop the viewfinder */
+ if (cam->overlay_on == true) {
+ stop_preview(cam);
+ }
+
+ currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ /* First check that this device can support the changes requested. */
+ err = vidioc_int_g_parm(cam->sensor, &currentparm);
+ if (err) {
+ pr_err("%s: vidioc_int_g_parm returned an error %d\n",
+ __func__, err);
+ goto exit;
+ }
+
+ pr_debug(" Current capabilities are %x\n",
+ currentparm.parm.capture.capability);
+ pr_debug(" Current capturemode is %d change to %d\n",
+ currentparm.parm.capture.capturemode,
+ parm->parm.capture.capturemode);
+ pr_debug(" Current framerate is %d change to %d\n",
+ currentparm.parm.capture.timeperframe.denominator,
+ parm->parm.capture.timeperframe.denominator);
+
+ /* This will change any camera settings needed. */
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, true, true);
+ err = vidioc_int_s_parm(cam->sensor, parm);
+ ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, false, false);
+ if (err) {
+ pr_err("%s: vidioc_int_s_parm returned an error %d\n",
+ __func__, err);
+ goto exit;
+ }
+
+ err = mxc_v4l2_init_csi(cam);
exit:
if (cam->overlay_on == true)
@@ -1198,6 +1254,7 @@ exit:
return err;
}
+#if 0
/*!
* V4L2 - mxc_v4l2_s_std function
*
@@ -1287,6 +1344,7 @@ static int mxc_v4l2_g_std(cam_data *cam, v4l2_std_id *e)
return 0;
}
+#endif
/*!
* Dequeue one V4L capture buffer
@@ -1372,6 +1430,11 @@ static int mxc_v4l_open(struct file *file)
return -EBADF;
}
+ if(!cam->sensor) {
+ pr_err("ERROR: v4l2 capture: Unattached sensor!\n");
+ return -EBADF;
+ }
+
down(&cam->busy_lock);
err = 0;
if (signal_pending(current))
@@ -1411,12 +1474,9 @@ static int mxc_v4l_open(struct file *file)
csi_param.force_eof = 0;
csi_param.data_en_pol = 0;
csi_param.mclk = ifparm.u.bt656.clock_curr;
-
+ csi_param.ext_vsync = ifparm.u.bt656.bt_sync_correct;
csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv;
- /* Once we handle multiple inputs this will need to change. */
- csi_param.csi = 0;
-
if (ifparm.u.bt656.mode
== V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT)
csi_param.data_width = IPU_CSI_DATA_WIDTH_8;
@@ -1464,11 +1524,13 @@ static int mxc_v4l_open(struct file *file)
__func__,
cam->crop_current.width, cam->crop_current.height);
+ udelay(100);
+
csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat;
pr_debug("On Open: Input to ipu size is %d x %d\n",
cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height);
ipu_csi_set_window_size(cam->crop_current.width,
- cam->crop_current.width,
+ cam->crop_current.height,
cam->csi);
ipu_csi_set_window_pos(cam->crop_current.left,
cam->crop_current.top,
@@ -1478,12 +1540,16 @@ static int mxc_v4l_open(struct file *file)
cam_fmt.fmt.pix.pixelformat,
csi_param);
+ udelay(100);
+
ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
true, true);
vidioc_int_init(cam->sensor);
ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi,
false, false);
+
+ udelay(100);
}
file->private_data = dev;
@@ -1519,7 +1585,7 @@ static int mxc_v4l_close(struct file *file)
err = stop_preview(cam);
cam->overlay_on = false;
}
- if (cam->capture_pid == current->pid) {
+ if (cam->capture_pid == current->tgid) {
err |= mxc_streamoff(cam);
wake_up_interruptible(&cam->enc_queue);
}
@@ -1570,7 +1636,7 @@ static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count,
loff_t *ppos)
{
int err = 0;
- u8 *v_address;
+ u8 *v_address[2];
struct video_device *dev = video_devdata(file);
cam_data *cam = video_get_drvdata(dev);
@@ -1581,11 +1647,17 @@ static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count,
if (cam->overlay_on == true)
stop_preview(cam);
- v_address = dma_alloc_coherent(0,
+ v_address[0] = dma_alloc_coherent(0,
PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
- &cam->still_buf, GFP_DMA | GFP_KERNEL);
+ &cam->still_buf[0],
+ GFP_DMA | GFP_KERNEL);
+
+ v_address[1] = dma_alloc_coherent(0,
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
+ &cam->still_buf[1],
+ GFP_DMA | GFP_KERNEL);
- if (!v_address) {
+ if (!v_address[0] || !v_address[1]) {
err = -ENOBUFS;
goto exit0;
}
@@ -1593,14 +1665,14 @@ static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count,
err = prp_still_select(cam);
if (err != 0) {
err = -EIO;
- goto exit1;
+ goto exit0;
}
cam->still_counter = 0;
err = cam->csi_start(cam);
if (err != 0) {
err = -EIO;
- goto exit2;
+ goto exit1;
}
if (!wait_event_interruptible_timeout(cam->still_queue,
@@ -1609,19 +1681,23 @@ static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count,
pr_err("ERROR: v4l2 capture: mxc_v4l_read timeout counter %x\n",
cam->still_counter);
err = -ETIME;
- goto exit2;
+ goto exit1;
}
- err = copy_to_user(buf, v_address, cam->v2f.fmt.pix.sizeimage);
-
- exit2:
- prp_still_deselect(cam);
+ err = copy_to_user(buf, v_address[1], cam->v2f.fmt.pix.sizeimage);
exit1:
- dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address,
- cam->still_buf);
- cam->still_buf = 0;
+ prp_still_deselect(cam);
exit0:
+ if (v_address[0] != 0)
+ dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[0],
+ cam->still_buf[0]);
+ if (v_address[1] != 0)
+ dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[1],
+ cam->still_buf[1]);
+
+ cam->still_buf[0] = cam->still_buf[1] = 0;
+
if (cam->overlay_on == true) {
start_preview(cam);
}
@@ -1661,6 +1737,21 @@ static long mxc_v4l_do_ioctl(struct file *file,
return -EBUSY;
switch (ioctlnr) {
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_DBG_S_REGISTER: {
+ struct v4l2_dbg_register * dreg = arg;
+ vidioc_int_s_register(cam->sensor,dreg);
+ break;
+ }
+
+ case VIDIOC_DBG_G_REGISTER: {
+ struct v4l2_dbg_register * dreg = arg;
+ vidioc_int_g_register(cam->sensor,dreg);
+ break;
+ }
+#endif
+
/*!
* V4l2 VIDIOC_QUERYCAP ioctl
*/
@@ -1695,6 +1786,14 @@ static long mxc_v4l_do_ioctl(struct file *file,
struct v4l2_format *sf = arg;
pr_debug(" case VIDIOC_S_FMT\n");
retval = mxc_v4l2_s_fmt(cam, sf);
+ mxc_v4l2_init_csi(cam);
+ break;
+ }
+
+ case VIDIOC_ENUM_FMT: {
+ struct v4l2_fmtdesc *fd = arg;
+ pr_debug(" case VIDIOC_ENUM_FMT\n");
+ retval = mxc_v4l2_enum_fmt(cam, fd);
break;
}
@@ -1775,9 +1874,8 @@ static long mxc_v4l_do_ioctl(struct file *file,
if (cam->skip_frame > 0) {
list_add_tail(&cam->frame[index].queue,
&cam->working_q);
-
retval =
- cam->enc_update_eba(cam->
+ cam->enc_update_eba(cam->csi,cam->
frame[index].
buffer.m.offset,
&cam->
@@ -1999,28 +2097,6 @@ static long mxc_v4l_do_ioctl(struct file *file,
break;
}
- /* linux v4l2 bug, kernel c0485619 user c0405619 */
- case VIDIOC_ENUMSTD: {
- struct v4l2_standard *e = arg;
- pr_debug(" case VIDIOC_ENUMSTD\n");
- *e = cam->standard;
- break;
- }
-
- case VIDIOC_G_STD: {
- v4l2_std_id *e = arg;
- pr_debug(" case VIDIOC_G_STD\n");
- retval = mxc_v4l2_g_std(cam, e);
- break;
- }
-
- case VIDIOC_S_STD: {
- v4l2_std_id *e = arg;
- pr_debug(" case VIDIOC_S_STD\n");
- retval = mxc_v4l2_s_std(cam, *e);
-
- break;
- }
case VIDIOC_ENUMOUTPUT: {
struct v4l2_output *output = arg;
@@ -2109,8 +2185,13 @@ static long mxc_v4l_do_ioctl(struct file *file,
break;
}
- case VIDIOC_ENUM_FMT:
- case VIDIOC_TRY_FMT:
+ case VIDIOC_TRY_FMT: {
+ struct v4l2_format * f = arg;
+ pr_debug(" case VIDIOC_TRY_FMT\n");
+ retval = vidioc_int_try_fmt_cap(cam->sensor,f);
+ break;
+ }
+
case VIDIOC_QUERYCTRL:
case VIDIOC_G_TUNER:
case VIDIOC_S_TUNER:
@@ -2163,7 +2244,7 @@ static int mxc_mmap(struct file *file, struct vm_area_struct *vma)
return -EINTR;
size = vma->vm_end - vma->vm_start;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
if (remap_pfn_range(vma, vma->vm_start,
vma->vm_pgoff, size, vma->vm_page_prot)) {
@@ -2236,12 +2317,21 @@ static void camera_platform_release(struct device *device)
}
/*! Device Definition for Mt9v111 devices */
-static struct platform_device mxc_v4l2_devices = {
- .name = "mxc_v4l2",
- .dev = {
- .release = camera_platform_release,
- },
- .id = 0,
+static struct platform_device mxc_v4l2_devices[] = {
+ {
+ .name = "mxc_v4l2_1",
+ .dev = {
+ .release = camera_platform_release,
+ },
+ .id = 0,
+ },
+ {
+ .name = "mxc_v4l2_2",
+ .dev = {
+ .release = camera_platform_release,
+ },
+ .id = 1,
+ }
};
/*!
@@ -2302,7 +2392,7 @@ static void camera_callback(u32 mask, void *dev)
struct mxc_v4l_frame,
queue);
- if (cam->enc_update_eba(
+ if (cam->enc_update_eba(cam->csi,
ready_frame->buffer.m.offset,
&cam->ping_pong_csi) == 0) {
list_del(cam->ready_q.next);
@@ -2354,7 +2444,7 @@ static void camera_callback(u32 mask, void *dev)
ready_frame = list_entry(cam->ready_q.next,
struct mxc_v4l_frame,
queue);
- if (cam->enc_update_eba(ready_frame->buffer.m.offset,
+ if (cam->enc_update_eba(cam->csi,ready_frame->buffer.m.offset,
&cam->ping_pong_csi) == 0) {
list_del(cam->ready_q.next);
list_add_tail(&ready_frame->queue,
@@ -2362,7 +2452,7 @@ static void camera_callback(u32 mask, void *dev)
} else
return;
} else {
- if (cam->enc_update_eba(
+ if (cam->enc_update_eba(cam->csi,
cam->dummy_frame.buffer.m.offset,
&cam->ping_pong_csi) == -EACCES)
return;
@@ -2379,13 +2469,15 @@ static void camera_callback(u32 mask, void *dev)
*
* @return status 0 Success
*/
-static void init_camera_struct(cam_data *cam)
+static void init_camera_struct(cam_data *cam,unsigned int csi)
{
- pr_debug("In MVC: init_camera_struct\n");
+ pr_debug("In MVC: init_camera_struct for csi %d\n",csi);
/* Default everything to 0 */
memset(cam, 0, sizeof(cam_data));
+ cam->csi = csi;
+
init_MUTEX(&cam->param_lock);
init_MUTEX(&cam->busy_lock);
@@ -2396,7 +2488,7 @@ static void init_camera_struct(cam_data *cam)
*(cam->video_dev) = mxc_v4l_template;
video_set_drvdata(cam->video_dev, cam);
- dev_set_drvdata(&mxc_v4l2_devices.dev, (void *)cam);
+ dev_set_drvdata(&mxc_v4l2_devices[csi].dev, (void *)cam);
cam->video_dev->minor = -1;
init_waitqueue_head(&cam->enc_queue);
@@ -2428,6 +2520,8 @@ static void init_camera_struct(cam_data *cam)
cam->skip_frame = 0;
cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY;
+ cam->current_input = cam->csi;
+
cam->v2f.fmt.pix.sizeimage = 352 * 288 * 3 / 2;
cam->v2f.fmt.pix.bytesperline = 288 * 3 / 2;
cam->v2f.fmt.pix.width = 288;
@@ -2438,9 +2532,6 @@ static void init_camera_struct(cam_data *cam)
cam->win.w.left = 0;
cam->win.w.top = 0;
- cam->csi = 0; /* Need to determine how to set this correctly with
- * multiple video input devices. */
-
cam->enc_callback = camera_callback;
init_waitqueue_head(&cam->power_queue);
spin_lock_init(&cam->queue_int_lock);
@@ -2460,11 +2551,12 @@ static u8 camera_power(cam_data *cam, bool cameraOn)
{
pr_debug("In MVC:camera_power on=%d\n", cameraOn);
+ if( !cam->open_count )
+ return 0;
+
if (cameraOn == true) {
- ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, true, true);
vidioc_int_s_power(cam->sensor, 1);
} else {
- ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, false, false);
vidioc_int_s_power(cam->sensor, 0);
}
return 0;
@@ -2491,15 +2583,15 @@ static int mxc_v4l2_suspend(struct platform_device *pdev, pm_message_t state)
return -1;
}
+ if (!cam->open_count) {
+ return 0;
+ }
+
cam->low_power = true;
if (cam->overlay_on == true)
stop_preview(cam);
- if ((cam->capture_on == true) && cam->enc_disable) {
- cam->enc_disable(cam);
- }
camera_power(cam, false);
-
return 0;
}
@@ -2522,14 +2614,19 @@ static int mxc_v4l2_resume(struct platform_device *pdev)
return -1;
}
+ if( !cam->open_count )
+ return 0;
+
cam->low_power = false;
wake_up_interruptible(&cam->power_queue);
+
camera_power(cam, true);
if (cam->overlay_on == true)
start_preview(cam);
+
if (cam->capture_on == true)
- mxc_streamon(cam);
+ mxc_streamon(cam);
return 0;
}
@@ -2537,15 +2634,27 @@ static int mxc_v4l2_resume(struct platform_device *pdev)
/*!
* This structure contains pointers to the power management callback functions.
*/
-static struct platform_driver mxc_v4l2_driver = {
- .driver = {
- .name = "mxc_v4l2",
- },
- .probe = NULL,
- .remove = NULL,
- .suspend = mxc_v4l2_suspend,
- .resume = mxc_v4l2_resume,
- .shutdown = NULL,
+static struct platform_driver mxc_v4l2_driver[] = {
+ {
+ .driver = {
+ .name = "mxc_v4l2_1",
+ },
+ .probe = NULL,
+ .remove = NULL,
+ .suspend = mxc_v4l2_suspend,
+ .resume = mxc_v4l2_resume,
+ .shutdown = NULL,
+ },
+ {
+ .driver = {
+ .name = "mxc_v4l2_2",
+ },
+ .probe = NULL,
+ .remove = NULL,
+ .suspend = mxc_v4l2_suspend,
+ .resume = mxc_v4l2_resume,
+ .shutdown = NULL,
+ },
};
/*!
@@ -2567,6 +2676,7 @@ static int mxc_v4l2_master_attach(struct v4l2_int_device *slave)
}
ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, true, true);
+ vidioc_int_s_power(cam->sensor, 1);
vidioc_int_dev_init(slave);
ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, false, false);
cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -2623,53 +2733,55 @@ static void mxc_v4l2_master_detach(struct v4l2_int_device *slave)
static __init int camera_init(void)
{
u8 err = 0;
+ int i;
pr_debug("In MVC:camera_init\n");
- /* Register the device driver structure. */
- err = platform_driver_register(&mxc_v4l2_driver);
- if (err != 0) {
- pr_err("ERROR: v4l2 capture:camera_init: "
- "platform_driver_register failed.\n");
- return err;
- }
+ for (i = 0; i < ARRAY_SIZE(mxc_v4l2_int_device); i++) {
+ /* Register the device driver structure. */
+ err = platform_driver_register(&mxc_v4l2_driver[i]);
+ if (err != 0) {
+ pr_err("ERROR: v4l2 capture:camera_init: "
+ "platform_driver_register failed.\n");
+ return err;
+ }
- /* Create g_cam and initialize it. */
- if ((g_cam = kmalloc(sizeof(cam_data), GFP_KERNEL)) == NULL) {
- pr_err("ERROR: v4l2 capture: failed to register camera\n");
- platform_driver_unregister(&mxc_v4l2_driver);
- return -1;
- }
- init_camera_struct(g_cam);
+ /* Create g_cam and initialize it. */
+ if ((g_cam [i] = kmalloc(sizeof(cam_data), GFP_KERNEL)) == NULL) {
+ pr_err("ERROR: v4l2 capture: failed to register camera\n");
+ platform_driver_unregister(&mxc_v4l2_driver[i]);
+ return -1;
+ }
+ init_camera_struct(g_cam [i], i);
- /* Set up the v4l2 device and register it*/
- mxc_v4l2_int_device.priv = g_cam;
- /* This function contains a bug that won't let this be rmmod'd. */
- v4l2_int_device_register(&mxc_v4l2_int_device);
+ /* Set up the v4l2 device and register it*/
+ mxc_v4l2_int_device[i].priv = g_cam [i];
+ /* This function contains a bug that won't let this be rmmod'd. */
+ v4l2_int_device_register(&mxc_v4l2_int_device[i]);
- /* Register the I2C device */
- err = platform_device_register(&mxc_v4l2_devices);
- if (err != 0) {
- pr_err("ERROR: v4l2 capture: camera_init: "
- "platform_device_register failed.\n");
- platform_driver_unregister(&mxc_v4l2_driver);
- kfree(g_cam);
- g_cam = NULL;
- return err;
- }
+ /* Register the I2C device */
+ err = platform_device_register(&mxc_v4l2_devices[i]);
+ if (err != 0) {
+ pr_err("ERROR: v4l2 capture: camera_init: "
+ "platform_device_register failed.\n");
+ platform_driver_unregister(&mxc_v4l2_driver[i]);
+ kfree(g_cam [i]);
+ g_cam [i] = NULL;
+ return err;
+ }
- /* register v4l video device */
- if (video_register_device(g_cam->video_dev, VFL_TYPE_GRABBER, video_nr)
- == -1) {
- platform_device_unregister(&mxc_v4l2_devices);
- platform_driver_unregister(&mxc_v4l2_driver);
- kfree(g_cam);
- g_cam = NULL;
- pr_err("ERROR: v4l2 capture: video_register_device failed\n");
- return -1;
+ /* register v4l video device */
+ if (video_register_device(g_cam[i]->video_dev, VFL_TYPE_GRABBER, video_nr)== -1) {
+ platform_device_unregister(&mxc_v4l2_devices[i]);
+ platform_driver_unregister(&mxc_v4l2_driver[i]);
+ kfree(g_cam[i]);
+ g_cam [i] = NULL;
+ pr_err("ERROR: v4l2 capture: video_register_device failed\n");
+ return -1;
+ }
+ pr_debug(" Video device registered: %s #%d\n",
+ g_cam[i]->video_dev->name, g_cam[i]->video_dev->minor);
}
- pr_debug(" Video device registered: %s #%d\n",
- g_cam->video_dev->name, g_cam->video_dev->minor);
return err;
}
@@ -2683,19 +2795,34 @@ static void __exit camera_exit(void)
pr_info("V4L2 unregistering video\n");
- if (g_cam->open_count) {
+ if (g_cam[0]->open_count) {
+ pr_err("ERROR: v4l2 capture:camera open "
+ "-- setting ops to NULL\n");
+ } else {
+ pr_info("V4L2 freeing image input device\n");
+ v4l2_int_device_unregister(&mxc_v4l2_int_device[0]);
+ video_unregister_device(g_cam[0]->video_dev);
+ platform_driver_unregister(&mxc_v4l2_driver[0]);
+ platform_device_unregister(&mxc_v4l2_devices[0]);
+
+ mxc_free_frame_buf(g_cam[0]);
+ kfree(g_cam[0]);
+ g_cam[0] = NULL;
+ }
+
+ if (g_cam[1]->open_count) {
pr_err("ERROR: v4l2 capture:camera open "
"-- setting ops to NULL\n");
} else {
pr_info("V4L2 freeing image input device\n");
- v4l2_int_device_unregister(&mxc_v4l2_int_device);
- video_unregister_device(g_cam->video_dev);
- platform_driver_unregister(&mxc_v4l2_driver);
- platform_device_unregister(&mxc_v4l2_devices);
-
- mxc_free_frame_buf(g_cam);
- kfree(g_cam);
- g_cam = NULL;
+ v4l2_int_device_unregister(&mxc_v4l2_int_device[1]);
+ video_unregister_device(g_cam[1]->video_dev);
+ platform_driver_unregister(&mxc_v4l2_driver[1]);
+ platform_device_unregister(&mxc_v4l2_devices[1]);
+
+ mxc_free_frame_buf(g_cam[1]);
+ kfree(g_cam[1]);
+ g_cam[1] = NULL;
}
}
diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h
index 45a211a80a38..abaaaea48447 100644
--- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h
+++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h
@@ -36,6 +36,7 @@
#include <media/v4l2-dev.h>
#define FRAME_NUM 3
+//#define FRAME_NUM 4
/*!
* v4l2 frame structure.
@@ -123,7 +124,7 @@ typedef struct _cam_data {
/* still image capture */
wait_queue_head_t still_queue;
int still_counter;
- dma_addr_t still_buf;
+ dma_addr_t still_buf[2];
void *still_buf_vaddr;
/* overlay */
@@ -166,7 +167,7 @@ typedef struct _cam_data {
struct v4l2_rect crop_defrect;
struct v4l2_rect crop_current;
- int (*enc_update_eba) (dma_addr_t eba, int *bufferNum);
+ int (*enc_update_eba) (int csi,dma_addr_t eba, int *bufferNum);
int (*enc_enable) (void *private);
int (*enc_disable) (void *private);
int (*enc_enable_csi) (void *private);
@@ -194,6 +195,7 @@ typedef struct _cam_data {
/* camera sensor interface */
struct camera_sensor *cam_sensor; /* old version */
struct v4l2_int_device *sensor;
+ struct timeval tv_wakeup; // TODO - for testing. Remove later
} cam_data;
#if defined(CONFIG_MXC_IPU_V1) || defined(CONFIG_VIDEO_MXC_EMMA_CAMERA) \
diff --git a/drivers/media/video/mxc/capture/ov3640.c b/drivers/media/video/mxc/capture/ov3640.c
index 29e61234e7f8..899945b7d071 100644
--- a/drivers/media/video/mxc/capture/ov3640.c
+++ b/drivers/media/video/mxc/capture/ov3640.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2005-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -26,7 +26,7 @@
#define OV3640_VOLTAGE_ANALOG 2800000
#define OV3640_VOLTAGE_DIGITAL_CORE 1500000
#define OV3640_VOLTAGE_DIGITAL_IO 1800000
-
+#define OV3640_VOLTAGE_DIGITAL_GPO 2800000
/* Check these values! */
#define MIN_FPS 15
@@ -40,8 +40,8 @@ enum ov3640_mode {
ov3640_mode_MIN = 0,
ov3640_mode_VGA_640_480 = 0,
ov3640_mode_QVGA_320_240 = 1,
- ov3640_mode_QXGA_2048_1536 = 2,
- ov3640_mode_XGA_1024_768 = 3,
+ ov3640_mode_XGA_1024_768 = 2,
+ ov3640_mode_QXGA_2048_1536 = 3,
ov3640_mode_NTSC_720_480 = 4,
ov3640_mode_PAL_720_576 = 5,
ov3640_mode_MAX = 5
@@ -93,6 +93,44 @@ struct sensor {
} ov3640_data;
static struct reg_value ov3640_setting_15fps_QXGA_2048_1536[] = {
+#if 0
+ /* The true 15fps QXGA setting. */
+ {0x3012, 0x80, 0, 0}, {0x304d, 0x41, 0, 0}, {0x3087, 0x16, 0, 0},
+ {0x30aa, 0x45, 0, 0}, {0x30b0, 0xff, 0, 0}, {0x30b1, 0xff, 0, 0},
+ {0x30b2, 0x13, 0, 0}, {0x30d7, 0x10, 0, 0}, {0x309e, 0x00, 0, 0},
+ {0x3602, 0x26, 0, 0}, {0x3603, 0x4D, 0, 0}, {0x364c, 0x04, 0, 0},
+ {0x360c, 0x12, 0, 0}, {0x361e, 0x00, 0, 0}, {0x361f, 0x11, 0, 0},
+ {0x3633, 0x03, 0, 0}, {0x3629, 0x3c, 0, 0}, {0x300e, 0x33, 0, 0},
+ {0x300f, 0x21, 0, 0}, {0x3010, 0x20, 0, 0}, {0x3011, 0x00, 0, 0},
+ {0x304c, 0x81, 0, 0}, {0x3029, 0x47, 0, 0}, {0x3070, 0x00, 0, 0},
+ {0x3071, 0xEC, 0, 0}, {0x301C, 0x06, 0, 0}, {0x3072, 0x00, 0, 0},
+ {0x3073, 0xC5, 0, 0}, {0x301D, 0x07, 0, 0}, {0x3018, 0x38, 0, 0},
+ {0x3019, 0x30, 0, 0}, {0x301a, 0x61, 0, 0}, {0x307d, 0x00, 0, 0},
+ {0x3087, 0x02, 0, 0}, {0x3082, 0x20, 0, 0}, {0x303c, 0x08, 0, 0},
+ {0x303d, 0x18, 0, 0}, {0x303e, 0x06, 0, 0}, {0x303F, 0x0c, 0, 0},
+ {0x3030, 0x62, 0, 0}, {0x3031, 0x26, 0, 0}, {0x3032, 0xe6, 0, 0},
+ {0x3033, 0x6e, 0, 0}, {0x3034, 0xea, 0, 0}, {0x3035, 0xae, 0, 0},
+ {0x3036, 0xa6, 0, 0}, {0x3037, 0x6a, 0, 0}, {0x3015, 0x12, 0, 0},
+ {0x3014, 0x04, 0, 0}, {0x3013, 0xf7, 0, 0}, {0x3104, 0x02, 0, 0},
+ {0x3105, 0xfd, 0, 0}, {0x3106, 0x00, 0, 0}, {0x3107, 0xff, 0, 0},
+ {0x3308, 0xa5, 0, 0}, {0x3316, 0xff, 0, 0}, {0x3317, 0x00, 0, 0},
+ {0x3087, 0x02, 0, 0}, {0x3082, 0x20, 0, 0}, {0x3300, 0x13, 0, 0},
+ {0x3301, 0xd6, 0, 0}, {0x3302, 0xef, 0, 0}, {0x30b8, 0x20, 0, 0},
+ {0x30b9, 0x17, 0, 0}, {0x30ba, 0x04, 0, 0}, {0x30bb, 0x08, 0, 0},
+ {0x3100, 0x02, 0, 0}, {0x3304, 0x00, 0, 0}, {0x3400, 0x00, 0, 0},
+ {0x3404, 0x02, 0, 0}, {0x3020, 0x01, 0, 0}, {0x3021, 0x1d, 0, 0},
+ {0x3022, 0x00, 0, 0}, {0x3023, 0x0a, 0, 0}, {0x3024, 0x08, 0, 0},
+ {0x3025, 0x18, 0, 0}, {0x3026, 0x06, 0, 0}, {0x3027, 0x0c, 0, 0},
+ {0x335f, 0x68, 0, 0}, {0x3360, 0x18, 0, 0}, {0x3361, 0x0c, 0, 0},
+ {0x3362, 0x68, 0, 0}, {0x3363, 0x08, 0, 0}, {0x3364, 0x04, 0, 0},
+ {0x3403, 0x42, 0, 0}, {0x3088, 0x08, 0, 0}, {0x3089, 0x00, 0, 0},
+ {0x308a, 0x06, 0, 0}, {0x308b, 0x00, 0, 0}, {0x3507, 0x06, 0, 0},
+ {0x350a, 0x4f, 0, 0}, {0x3600, 0xc4, 0, 0},
+#endif
+ /*
+ * Only support 7.5fps for QXGA to workaround screen tearing issue
+ * for 15fps when capturing still image.
+ */
{0x3012, 0x80, 0, 0}, {0x304d, 0x45, 0, 0}, {0x30a7, 0x5e, 0, 0},
{0x3087, 0x16, 0, 0}, {0x309c, 0x1a, 0, 0}, {0x30a2, 0xe4, 0, 0},
{0x30aa, 0x42, 0, 0}, {0x30b0, 0xff, 0, 0}, {0x30b1, 0xff, 0, 0},
@@ -118,25 +156,9 @@ static struct reg_value ov3640_setting_15fps_QXGA_2048_1536[] = {
{0x30bb, 0x08, 0, 0}, {0x3507, 0x06, 0, 0}, {0x350a, 0x4f, 0, 0},
{0x3100, 0x02, 0, 0}, {0x3301, 0xde, 0, 0}, {0x3304, 0x00, 0, 0},
{0x3400, 0x00, 0, 0}, {0x3404, 0x02, 0, 0}, {0x3600, 0xc4, 0, 0},
- {0x3302, 0xef, 0, 0}, {0x3020, 0x01, 0, 0}, {0x3021, 0x1d, 0, 0},
- {0x3022, 0x00, 0, 0}, {0x3023, 0x0a, 0, 0}, {0x3024, 0x08, 0, 0},
- {0x3025, 0x00, 0, 0}, {0x3026, 0x06, 0, 0}, {0x3027, 0x00, 0, 0},
- {0x335f, 0x68, 0, 0}, {0x3360, 0x00, 0, 0}, {0x3361, 0x00, 0, 0},
- {0x3362, 0x68, 0, 0}, {0x3363, 0x00, 0, 0}, {0x3364, 0x00, 0, 0},
- {0x3403, 0x00, 0, 0}, {0x3088, 0x08, 0, 0}, {0x3089, 0x00, 0, 0},
- {0x308a, 0x06, 0, 0}, {0x308b, 0x00, 0, 0}, {0x307c, 0x10, 0, 0},
- {0x3090, 0xc0, 0, 0}, {0x304c, 0x84, 0, 0}, {0x308d, 0x04, 0, 0},
- {0x3086, 0x03, 0, 0}, {0x3086, 0x00, 0, 0}, {0x3012, 0x00, 0, 0},
- {0x3020, 0x01, 0, 0}, {0x3021, 0x1d, 0, 0}, {0x3022, 0x00, 0, 0},
- {0x3023, 0x0a, 0, 0}, {0x3024, 0x08, 0, 0}, {0x3025, 0x18, 0, 0},
- {0x3026, 0x06, 0, 0}, {0x3027, 0x0c, 0, 0}, {0x302a, 0x06, 0, 0},
- {0x302b, 0x20, 0, 0}, {0x3075, 0x44, 0, 0}, {0x300d, 0x00, 0, 0},
- {0x30d7, 0x00, 0, 0}, {0x3069, 0x40, 0, 0}, {0x303e, 0x01, 0, 0},
- {0x303f, 0x80, 0, 0}, {0x3302, 0x20, 0, 0}, {0x335f, 0x68, 0, 0},
- {0x3360, 0x18, 0, 0}, {0x3361, 0x0c, 0, 0}, {0x3362, 0x68, 0, 0},
- {0x3363, 0x08, 0, 0}, {0x3364, 0x04, 0, 0}, {0x3403, 0x42, 0, 0},
{0x3088, 0x08, 0, 0}, {0x3089, 0x00, 0, 0}, {0x308a, 0x06, 0, 0},
- {0x308b, 0x00, 0, 0},
+ {0x308b, 0x00, 0, 0}, {0x308d, 0x04, 0, 0}, {0x3086, 0x03, 0, 0},
+ {0x3086, 0x00, 0, 0}, {0x3011, 0x01, 0, 0},
};
static struct reg_value ov3640_setting_15fps_XGA_1024_768[] = {
@@ -674,6 +696,7 @@ static struct regulator *io_regulator;
static struct regulator *core_regulator;
static struct regulator *analog_regulator;
static struct regulator *gpo_regulator;
+static struct mxc_camera_platform_data *camera_plat;
static int ov3640_probe(struct i2c_client *adapter,
const struct i2c_device_id *device_id);
@@ -843,6 +866,10 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on)
if (analog_regulator)
if (regulator_enable(analog_regulator) != 0)
return -EIO;
+ /* Make sure power on */
+ if (camera_plat->pwdn)
+ camera_plat->pwdn(0);
+
} else if (!on && sensor->on) {
if (analog_regulator)
regulator_disable(analog_regulator);
@@ -920,6 +947,10 @@ static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
enum ov3640_frame_rate frame_rate;
int ret = 0;
+ /* Make sure power on */
+ if (camera_plat->pwdn)
+ camera_plat->pwdn(0);
+
switch (a->type) {
/* This is the only case currently handled. */
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -1286,17 +1317,25 @@ static int ov3640_probe(struct i2c_client *client,
gpo_regulator = regulator_get(&client->dev,
plat_data->gpo_regulator);
if (!IS_ERR(gpo_regulator)) {
+ regulator_set_voltage(gpo_regulator,
+ OV3640_VOLTAGE_DIGITAL_GPO,
+ OV3640_VOLTAGE_DIGITAL_GPO);
if (regulator_enable(gpo_regulator) != 0) {
- pr_err("%s:gpo3 enable error\n", __func__);
+ pr_err("%s:gpo enable error\n", __func__);
goto err4;
} else {
dev_dbg(&client->dev,
- "%s:gpo3 enable ok\n", __func__);
+ "%s:gpo enable ok\n", __func__);
}
} else
gpo_regulator = NULL;
}
+ if (plat_data->pwdn)
+ plat_data->pwdn(0);
+
+ camera_plat = plat_data;
+
ov3640_int_device.priv = &ov3640_data;
retval = v4l2_int_device_register(&ov3640_int_device);