On Fri, 10 Jun 2011 16:38:10 +0800 "He, Yong M" <yong.m...@intel.com> wrote:
> > From: Yong He <yong.m...@intel.com> > Subject: [PATCH] MRST Tablet camera driver ver-0.952, fix 8917 and 9552 > > =====This patch is going to fix these bugs === > > Bug 8112<https://bugzilla.otcshare.org/show_bug.cgi?id=8112> - ISP driver > doesn't support AF (auto-focus) controlling function for 5M camera sensor > (OV5640). > Bug_8917<https://bugzilla.otcshare.org/show_bug.cgi?id=8917> -[MM-camera]: a > cropped line appears on both camera previewing. > Bug 9552<https://bugzilla.otcshare.org/show_bug.cgi?id=9552> - Back camera > doesn't support advanced ioctl Hi, First of all, this patch is applied against a patch that was rejected, so it doesn't apply. Secondly, I need you to break down your patch into smaller functional patches. We don't want a single patch which addresses multiple issues, because then when we have regressions (like with the power) it winds up being an all or nothing accept/reject. Not to mention a large patch like this is really hard for me to review. So, you need to do the following: 1. refresh your patches against the current kernel source (which does not include your previous patches) 2. break patch into smaller patch sets which address a single bug. These instructions apply to the second patch you sent as well, and all future patches. Thanks, Kristen > > =====solution === > > Bug 8112<https://bugzilla.otcshare.org/show_bug.cgi?id=8112> change default > mode to reduce initial time. > > Bug_8917<https://bugzilla.otcshare.org/show_bug.cgi?id=8917> solution is to > add a empty frame buffer space. If the in-queue is empty, all dropped frames > goes to this empty buffer. > > Bug 9552<https://bugzilla.otcshare.org/show_bug.cgi?id=9552> solution is to > add new sensor driver Control IDs to support focus operations: > Auto Exposure Mode > Auto Exposure Position/Window Size > Exposure Level Detect (for auto-flash) > Flash Manual ON/OFF > Scene Mode (AWB / Gamma) > SPE Mode > Exposure Compensation > color tuning (contrast, brightness, saturation, hues) (-2 ~ +2) > Sharpness > > Signed-off-by: He, Yong <yong.m...@intel.com<mailto:yong.m...@intel.com>> > --- > Index: a/drivers/staging/mrstci/mrstisp/mrstisp_main.c > =================================================================== > --- a/drivers/staging/mrstci/mrstisp/mrstisp_main.c (revision 80) > +++ a/drivers/staging/mrstci/mrstisp/mrstisp_main.c (revision 87) > @@ -19,6 +19,7 @@ > * > * > * Xiaolin Zhang <xiaolin.zh...@intel.com> > + * Yong He <yong.m...@intel.com> > */ > #include <linux/pm_runtime.h> > @@ -61,6 +62,8 @@ > static struct timer_list prevent_sleep_timer = > TIMER_INITIALIZER(prevent_sleep_func, 0, 0); > #endif > +static void * addr_for_skipped_frame; > +static dma_addr_t dma_addr_for_skipped_frame; > void intel_timer_start(void) > { > @@ -1258,7 +1261,9 @@ > bufbase = videobuf_to_dma_contig(vb); > mrst_isp_update_marvinvfaddr(isp, bufbase, 0); > /* mrst_isp_enable_interrupt(isp); */ > + dprintk(1, "ISP set to write to buffer %d > <---------", vb->i); > } else { > + dprintk(1, "no active queue stopflag=1"); > isp->active = vb; > mrst_isp_enable_interrupt(isp); > /* > @@ -2463,10 +2468,10 @@ > WARN_ON(priv != file->private_data); > DBG_entering; > + dprintk(1, "q-ed index = %d <-----------------------------", buf->index); > + isp = fh->dev; > ret = videobuf_qbuf(&fh->vb_q, buf); > - isp = fh->dev; > - > /* call the mrst_ci_capture() in process context without > * the protection of spinlock. > */ > @@ -2476,8 +2481,13 @@ > } > /* identify which video buffer was q-ed */ > if (ret == 0) > + { > fh->qbuf_flag |= (1<<buf->index); > - dprintk(1, "q-ed index = %d", buf->index); > + } > + else > + { > + dprintk(1, "q-ed index = %d <---- Failed, this buffer is NOT > available!", buf->index); > + } > DBG_leaving; > @@ -2518,8 +2528,13 @@ > ret = videobuf_dqbuf(&fh->vb_q, b, 0); > /* identify which video buffer was dq-ed */ > if (ret == 0) > + { > fh->qbuf_flag &= ~(1<<b->index); > - > + } > + else > + { > + dprintk(1, "dqbuf Failed!\n"); > + } > /*XXX zheng*/ > ++frame_cnt; > /* > @@ -2529,7 +2544,7 @@ > frame_cnt * 1000 / intel_get_micro_sec()); > */ > - dprintk(1, "dq-ed index = %d", b->index); > + dprintk(1, "dq-ed index = %d ============================>", b->index); > DBG_leaving; > return ret; > } > @@ -2988,10 +3003,15 @@ > bufbase = videobuf_to_dma_contig(isp->next); > mrst_isp_update_marvinvfaddr(isp, bufbase, > > CI_ISP_CFG_UPDATE_FRAME_SYNC); > - dprintk(1, "updating new addr, next = %d", > - isp->next->i); > + dprintk(1, "updating new addr, next = %d", > + isp->next->i); > + dprintk(1, "ISP set to write to buffer %d <---------", > isp->next->i); > } else { > isp->stopflag = 1; > + mrst_isp_update_marvinvfaddr(isp, dma_addr_for_skipped_frame, > + CI_ISP_CFG_UPDATE_FRAME_SYNC); > + dprintk(1, "ISP set to write to a skipped buffer (0x%08x) > <---------", > + dma_addr_for_skipped_frame); > dprintk(0, "stop isp"); > } > @@ -3024,7 +3044,7 @@ > vb->field_count++; > isp->active = NULL; > - dprintk(1, "buf %d size = %lx", vb->i, vb->size); > + dprintk(1, "buf %d completed, size = %lx =======> ", vb->i, > vb->size); > do_gettimeofday(&vb->ts); > wake_up(&vb->done); > @@ -3034,7 +3054,7 @@ > struct > videobuf_buffer, queue); > list_del_init(&isp->active->queue); > isp->active->state = VIDEOBUF_ACTIVE; > - dprintk(3, "start next frame %d", > + dprintk(3, "got a buf in isp->capture > queue, start next frame %d", > isp->active->i); > mrst_isp_to_do_mblk_line = 1; > REG_SET_SLICE(mrv_reg->mi_imsc, > @@ -3044,7 +3064,7 @@ > REG_SET_SLICE(mrv_reg->mi_imsc, > MRV_MI_MBLK_LINE, ON); > mrst_isp_disable_interrupt(isp); > - dprintk(3, "no frame right now"); > + dprintk(3, "no frame right now, waiting > for mrst_isp_to_do_mblk_line"); > } > } else { > isp->active = isp->next; > @@ -3197,6 +3217,16 @@ > dprintk(1, "isp mb1 = %lx, mb1_size = %lx", isp->mb1, isp->mb1_size); > + addr_for_skipped_frame = dma_alloc_coherent(&pdev->dev, isp->mb1_size, > + &dma_addr_for_skipped_frame, > + GFP_KERNEL); > + > + if (!addr_for_skipped_frame) { > + dprintk(0, "failed to declare dma memory for skipped frame"); > + ret = -ENXIO; > + goto exit_iounmap; > + } > + > ret = dma_declare_coherent_memory(&pdev->dev, start, > /* start, len - 640 * 480 * 2, > */ > start, len, > @@ -3208,7 +3238,7 @@ > if (!ret) { > dprintk(0, "failed to declare dma memory"); > ret = -ENXIO; > - goto exit_iounmap; > + goto exit_dma_skipframe_release; > } > /* init device struct */ > @@ -3267,7 +3297,7 @@ > mrst_isp_to_do_mblk_line = 0; > isp->need_to_capture = 0; > - dprintk(0, "mrstisp driver module successfully loaded"); > + dprintk(0, "mrstisp driver module successfully loaded. > (Version-0.951)"); > pm_runtime_put_noidle(&pdev->dev); > pm_runtime_allow(&pdev->dev); > return 0; > @@ -3276,6 +3306,9 @@ > video_unregister_device(isp->vdev); > exit_dma_release: > dma_release_declared_memory(&pdev->dev); > +exit_dma_skipframe_release: > + dma_free_coherent(&pdev->dev,isp->mb1_size, > + addr_for_skipped_frame,dma_addr_for_skipped_frame); > exit_iounmap: > iounmap(isp->regs); > exit_release_regions: > Index: a/drivers/staging/mrstci/mrstov5640/mrstov5640.c > =================================================================== > --- a/drivers/staging/mrstci/mrstov5640/mrstov5640.c (revision 80) > +++ a/drivers/staging/mrstci/mrstov5640/mrstov5640.c (revision 87) > @@ -44,11 +44,12 @@ > #include <media/v4l2-device.h> > #include <media/v4l2-chip-ident.h> > #include <asm/div64.h> > +#include <asm/mrst.h> > #include "ci_sensor_common.h" > #include "ov5640.h" > -#define DRIVER_VERSION "0.95" > +#define DRIVER_VERSION "0.952" > static int mrstov5640_debug=5; > module_param(mrstov5640_debug, int, 0644); > @@ -218,7 +219,16 @@ > int anti_banding; > int iso_mode; > int iso_val; > + int brightness_val; > + int contrast_val; > + int hue_val; > + int sharpness_val; > + int saturation_val; > + int scene_val; > + int spe_val; > + int exp_comp_val; > int af_x, af_y, af_mode; > + int ae_x, ae_y, ae_w, ae_h,ae_mode; > // hw status > u8 REG20; > @@ -369,15 +379,31 @@ > return ret; > } > +#define OV5640_AF_TO_MS 100 > + > static int ov5640_af_center(struct i2c_client *c) > { > int ret = 0; > + u8 val = 1; > + int af_time_out = OV5640_AF_TO_MS; > DBG_entering; > ret += ov5640_write(c, 0x3023, 0x01); > ret += ov5640_write(c, 0x3022, 0x80); > - udelay(100); > + while (val != 0) > + { > + if (af_time_out-- <= 0) > + { > + dprintk(3, "%s() Time out.\n",__FUNCTION__); > + return 1; > + } > + > + udelay(1000); > + ret += ov5640_read(c, 0x3023, &val); > + } > + > + > DBG_leaving; > return ret; > } > @@ -385,12 +411,25 @@ > static int ov5640_af_change_res(struct i2c_client *c) > { > int ret = 0; > + u8 val = 1; > + int af_time_out = 3*OV5640_AF_TO_MS; > DBG_entering; > ret += ov5640_write(c, 0x3023, 0x01); > ret += ov5640_write(c, 0x3022, 0x12); > - udelay(100); > + while (val != 0) > + { > + if (af_time_out-- <= 0) > + { > + dprintk(3, "%s() Time out.\n",__FUNCTION__); > + return 1; > + } > + > + udelay(1000); > + ret += ov5640_read(c, 0x3023, &val); > + } > + > DBG_leaving; > return ret; > } > @@ -400,6 +439,8 @@ > static int ov5640_af_change_pos(struct i2c_client *c, unsigned int x, > unsigned int y) > { > int ret = 0; > + u8 val = 1; > + int af_time_out = OV5640_AF_TO_MS; > DBG_entering; > if (x > OV5640_FOCUS_NORMALIZED_W) > @@ -420,8 +461,19 @@ > ret += ov5640_write(c, 0x3025, y); > ret += ov5640_write(c, 0x3023, 0x01); > ret += ov5640_write(c, 0x3022, 0x81); > - udelay(100); > + while (val != 0) > + { > + if (af_time_out-- <= 0) > + { > + dprintk(3, "%s() Time out.\n",__FUNCTION__); > + return 1; > + } > + > + udelay(1000); > + ret += ov5640_read(c, 0x3023, &val); > + } > + > DBG_leaving; > return ret; > } > @@ -429,12 +481,25 @@ > static int ov5640_af_do_focus(struct i2c_client *c) > { > int ret = 0; > + u8 val = 1; > + int af_time_out = 3*OV5640_AF_TO_MS; > DBG_entering; > ret += ov5640_write(c, 0x3023, 0x01); > ret += ov5640_write(c, 0x3022, 0x03); > - udelay(100); > + while (val != 0) > + { > + if (af_time_out-- <= 0) > + { > + dprintk(3, "%s() Time out.\n",__FUNCTION__); > + return 1; > + } > + > + udelay(1000); > + ret += ov5640_read(c, 0x3023, &val); > + } > + > DBG_leaving; > return ret; > } > @@ -467,12 +532,25 @@ > static int ov5640_af_release(struct i2c_client *c) > { > int ret = 0; > + u8 val = 1; > + int af_time_out = 3*OV5640_AF_TO_MS; > DBG_entering; > ret += ov5640_write(c, 0x3023, 0x01); > ret += ov5640_write(c, 0x3022, 0x08); > - udelay(100); > + while (val != 0) > + { > + if (af_time_out-- <= 0) > + { > + dprintk(3, "%s() Time out.\n",__FUNCTION__); > + return 1; > + } > + > + udelay(1000); > + ret += ov5640_read(c, 0x3023, &val); > + } > + > DBG_leaving; > return ret; > } > @@ -490,7 +568,6 @@ > msleep(100); > ret += ov5640_af_center(c); > ov5640_status.fw_inited = OV5640_FW_INITED; > - ov5640_af_do_focus(c); > DBG_leaving; > return ret; > @@ -498,7 +575,7 @@ > static int ov5640_hw_init (struct i2c_client *c) > { > - int ret, af_fw_status; > + int ret; > DBG_entering; > if (ov5640_status.reg_inited != OV5640_REG_RESET) { > @@ -529,6 +606,7 @@ > if (ov5640_status.reg_inited == OV5640_REG_INITED) > { > struct i2c_client *c = v4l2_get_subdevdata(sd); > + ov5640_save_hw_status(c); > ov5640_af_release(c); > ov5640_status.reg_inited = OV5640_REG_RESET; > } > @@ -555,7 +633,6 @@ > if (hw_reinit) > { > struct i2c_client *c = v4l2_get_subdevdata(sd); > - ov5640_save_hw_status(c); > ov5640_hw_init(c); > ov5640_restore_hw_status(c); > } > @@ -1178,26 +1255,34 @@ > return err; > } > -static int ov5640_t_flash(struct i2c_client *c, int value) > +static int ov5640_t_flash(struct v4l2_subdev *sd, int value) > { > int ret; > - if(value!=0&&value!=1) > - return -EINVAL; > - if(ret == 0) > - { > - ret = gpio_direction_output(GPIO_FLASH,value); > - if(ret == 0) > - ov5640_flash = value; > - gpio_free(GPIO_FLASH); > - } > + > + if((value!=0) && (value!=1)) > + { > + return -EINVAL; > + } > + > + ret = gpio_direction_output(GPIO_FLASH,value); > + > + if(ret == 0) > + { > + ov5640_flash = value; > + } > + > + gpio_free(GPIO_FLASH); > + > return ret; > - > } > -static int ov5640_q_flash(struct i2c_client *c, int *value) > +static int ov5640_q_flash(struct v4l2_subdev *sd, int *value) > { > if(!value) > + { > return -EINVAL; > + } > + > *value=ov5640_flash; > return 0; > } > @@ -1307,7 +1392,7 @@ > gain = ov5640_iso_gain_tbl[index]; > ret += ov5640_read(c, 0x3518, &v); > ret += ov5640_write(c, 0x3518, ((gain>>8)&0x3) | (v & 0xfc)); > - ret += ov5640_write(c, 0x3519, gain | 0xff); > + ret += ov5640_write(c, 0x3519, gain & 0xff); > ov5640_status.iso_val = value; > return ret; > @@ -1320,7 +1405,7 @@ > *value = ov5640_status.iso_val; > return ret; > } > - > +/* > #define ISO_MODE_AUTO 0 > #define ISO_MODE_MANUAL 1 > static int ov5640_t_iso_mode(struct v4l2_subdev *sd, int value) > @@ -1363,75 +1448,293 @@ > dprintk( 3, "ov5640_q_iso_mode (%d)",*value); > return ret; > } > +*/ > static int ov5640_t_brightness(struct v4l2_subdev *sd, int value) > { > + struct i2c_client *c = v4l2_get_subdevdata(sd); > int ret=0; > - // TODO: will be added soon > + u8 v,reg_5587,reg_5588; > + dprintk( 3, "%s (%d)",__FUNCTION__,value); > + > + switch (value) > + { > + case -2: > + reg_5587 = 0x20; > + reg_5588 = 0x8; > + break; > + case -1: > + reg_5587 = 0x10; > + reg_5588 = 0x8; > + break; > + case 0: > + reg_5587 = 0x0; > + reg_5588 = 0x0; > + break; > + case 1: > + reg_5587 = 0x10; > + reg_5588 = 0x0; > + break; > + case 2: > + reg_5587 = 0x20; > + reg_5588 = 0x0; > + break; > + default: > + return 1; > + } > + > + ret += ov5640_read(c, 0x5001, &v); > + ret += ov5640_write(c, 0x5001, (v | 0x80)); > + > + ret += ov5640_write(c, 0x5587, reg_5587); > + > + ret += ov5640_read(c, 0x5580, &v); > + ret += ov5640_write(c, 0x5580, (v | 0x4)); > + > + ret += ov5640_read(c, 0x5588, &v); > + v = v & 0xf7; > + ret += ov5640_write(c, 0x5588, (v | reg_5588)); > + > + > + ov5640_status.brightness_val = value; > return ret; > } > + > static int ov5640_q_brightness(struct v4l2_subdev *sd, int *value) > { > int ret=0; > - // TODO: will be added soon > + *value = ov5640_status.brightness_val; > return ret; > } > + > static int ov5640_t_contrast(struct v4l2_subdev *sd, int value) > { > + struct i2c_client *c = v4l2_get_subdevdata(sd); > int ret=0; > - // TODO: will be added soon > + u8 v,reg_5585,reg_5586; > + dprintk( 3, "%s (%d)",__FUNCTION__,value); > + > + switch (value) > + { > + case -2: > + reg_5585 = 0x18; > + reg_5586 = 0x18; > + break; > + case -1: > + reg_5585 = 0x1c; > + reg_5586 = 0x1c; > + break; > + case 0: > + reg_5585 = 0x0; > + reg_5586 = 0x20; > + break; > + case 1: > + reg_5585 = 0x10; > + reg_5586 = 0x24; > + break; > + case 2: > + reg_5585 = 0x18; > + reg_5586 = 0x28; > + break; > + default: > + return 1; > + } > + > + ret += ov5640_read(c, 0x5001, &v); > + ret += ov5640_write(c, 0x5001, (v | 0x80)); > + ret += ov5640_read(c, 0x5580, &v); > + ret += ov5640_write(c, 0x5580, (v | 0x4)); > + > + ret += ov5640_write(c, 0x5586, reg_5586); > + ret += ov5640_write(c, 0x5585, reg_5585); > + > + ret += ov5640_read(c, 0x5588, &v); > + ret += ov5640_write(c, 0x5588, (v & 0xbf)); > + > + ov5640_status.contrast_val = value; > + > return ret; > } > static int ov5640_q_contrast(struct v4l2_subdev *sd, int *value) > { > int ret=0; > - // TODO: will be added soon > + *value = ov5640_status.contrast_val; > return ret; > } > + > static int ov5640_t_saturation(struct v4l2_subdev *sd, int value) > { > + struct i2c_client *c = v4l2_get_subdevdata(sd); > int ret=0; > - // TODO: will be added soon > + u8 v,reg_5583; > + dprintk( 3, "%s (%d)",__FUNCTION__,value); > + > + switch (value) > + { > + case -2: > + reg_5583 = 0x20; > + break; > + case -1: > + reg_5583 = 0x30; > + break; > + case 0: > + reg_5583 = 0x40; > + break; > + case 1: > + reg_5583 = 0x50; > + break; > + case 2: > + reg_5583 = 0x60; > + break; > + default: > + return 1; > + } > + > + ret += ov5640_read(c, 0x5001, &v); > + ret += ov5640_write(c, 0x5001, (v | 0x80)); > + > + ret += ov5640_write(c, 0x5583, reg_5583); > + ret += ov5640_write(c, 0x5584, reg_5583); > + > + ret += ov5640_read(c, 0x5580, &v); > + ret += ov5640_write(c, 0x5580, (v | 0x2)); > + > + ret += ov5640_read(c, 0x5588, &v); > + ret += ov5640_write(c, 0x5588, (v | 0x40)); > + > + ov5640_status.saturation_val = value; > + > return ret; > } > static int ov5640_q_saturation(struct v4l2_subdev *sd, int *value) > { > int ret=0; > - // TODO: will be added soon > + *value = ov5640_status.saturation_val; > return ret; > } > static int ov5640_t_hue(struct v4l2_subdev *sd, int value) > { > + struct i2c_client *c = v4l2_get_subdevdata(sd); > int ret=0; > - // TODO: will be added soon > + u8 v,reg_1,reg_2,reg_3; > + dprintk( 3, "%s (%d)",__FUNCTION__,value); > + > + switch (value) > + { > + case -2: > + reg_1 = 0x40; > + reg_2 = 0x6f; > + reg_3 = 2; > + break; > + case -1: > + reg_1 = 0x6f; > + reg_2 = 0x40; > + reg_3 = 2; > + break; > + case 0: > + reg_1 = 0x80; > + reg_2 = 0x0; > + reg_3 = 1; > + break; > + case 1: > + reg_1 = 0x6f; > + reg_2 = 0x40; > + reg_3 = 1; > + break; > + case 2: > + reg_1 = 0x40; > + reg_2 = 0x6f; > + reg_3 = 1; > + break; > + default: > + return 1; > + } > + > + ret += ov5640_read(c, 0x5001, &v); > + ret += ov5640_write(c, 0x5001, (v | 0x80)); > + ret += ov5640_read(c, 0x5580, &v); > + ret += ov5640_write(c, 0x5580, (v | 0x1)); > + > + ret += ov5640_write(c, 0x5581, reg_1); > + ret += ov5640_write(c, 0x5582, reg_2); > + > + ret += ov5640_read(c, 0x5588, &v); > + v = v & 0xcc; > + ret += ov5640_write(c, 0x5588, (v | reg_3)); > + > + ov5640_status.hue_val = value; > return ret; > } > static int ov5640_q_hue(struct v4l2_subdev *sd, int *value) > { > int ret=0; > - // TODO: will be added soon > + *value = ov5640_status.hue_val; > return ret; > } > + > static int ov5640_t_sharpness(struct v4l2_subdev *sd, int value) > { > + struct i2c_client *c = v4l2_get_subdevdata(sd); > int ret=0; > - // TODO: will be added soon > + u8 v,reg_1; > + dprintk( 3, "%s (%d)",__FUNCTION__,value); > + > + switch (value) > + { > + case 99: > + ret += ov5640_read(c, 0x5308, &v); > + ret += ov5640_write(c, 0x5308, (v & 0xbf)); > + ret += ov5640_write(c, 0x5300, 0x08); > + ret += ov5640_write(c, 0x5301, 0x30); > + ret += ov5640_write(c, 0x5302, 0x10); > + ret += ov5640_write(c, 0x5303, 0x00); > + ret += ov5640_write(c, 0x5309, 0x08); > + ret += ov5640_write(c, 0x530a, 0x30); > + ret += ov5640_write(c, 0x530b, 0x04); > + ret += ov5640_write(c, 0x530c, 0x06); > + ov5640_status.sharpness_val = value; > + return ret; > + case 1: > + reg_1 = 0x2; > + break; > + case 2: > + reg_1 = 0x4; > + break; > + case 3: > + reg_1 = 0x8; > + break; > + case 4: > + reg_1 = 0xc; > + break; > + case 5: > + reg_1 = 0x10; > + break; > + case 0: > + default: > + reg_1 = 0; > + break; > + } > + ret += ov5640_read(c, 0x5308, &v); > + ret += ov5640_write(c, 0x5308, (v | 0x40)); > + ret += ov5640_write(c, 0x5302, reg_1); > + > + ov5640_status.sharpness_val = value; > return ret; > } > static int ov5640_q_sharpness(struct v4l2_subdev *sd, int *value) > { > int ret=0; > - // TODO: will be added soon > + *value = ov5640_status.sharpness_val; > return ret; > } > @@ -1484,15 +1787,15 @@ > ret += ov5640_af_release(c); > break; > case OV5640_FOCUS_MODE_WINDOW: > - break; > + ret += ov5640_af_do_focus(c); > + break; > case OV5640_FOCUS_MODE_CENTERED: > default: > ret += ov5640_af_center(c); > - break; > + ret += ov5640_af_do_focus(c); > + break; > }; > - ret += ov5640_af_do_focus(c); > - > return ret; > } > @@ -1504,32 +1807,379 @@ > return ret; > } > +#define OV5640_AE_MODE_AUTO 0 > +#define OV5640_AE_MODE_WINDOW_AVG 1 > +#define OV5640_AE_MODE_WINDOW_CENTERED 2 > +#define OV5640_AE_MODE_WINDOW_LANDSCAPE 3 > + > static int ov5640_t_exposure(struct v4l2_subdev *sd, int value) > { > + struct i2c_client *c = v4l2_get_subdevdata(sd); > int ret=0; > - // TODO: will be added soon > + u8 reg_1,reg_2,reg_3,reg_4,reg_5,reg_6,reg_7,reg_8; > + dprintk( 3, "%s Mode (%d) - X = %d, Y = %d, W = %d, H = %d", > + __FUNCTION__,value, ov5640_status.ae_x,ov5640_status.ae_y, > + ov5640_status.ae_w, ov5640_status.ae_h); > + > + ov5640_status.ae_mode = value; > + > + switch (value) > + { > + case OV5640_AE_MODE_WINDOW_AVG: > + reg_1 = 0x11; > + reg_2 = 0x11; > + reg_3 = 0x11; > + reg_4 = 0x11; > + reg_5 = 0x11; > + reg_6 = 0x11; > + reg_7 = 0x11; > + reg_8 = 0x11; > + break; > + case OV5640_AE_MODE_WINDOW_CENTERED: > + reg_1 = 0; > + reg_2 = 0; > + reg_3 = 0x10; > + reg_4 = 0x01; > + reg_5 = 0x10; > + reg_6 = 0x01; > + reg_7 = 0; > + reg_8 = 0; > + break; > + case OV5640_AE_MODE_WINDOW_LANDSCAPE: > + reg_1 = 0x62; > + reg_2 = 0x26; > + reg_3 = 0xe6; > + reg_4 = 0x6e; > + reg_5 = 0xea; > + reg_6 = 0xae; > + reg_7 = 0xa6; > + reg_8 = 0x6a; > + break; > + case OV5640_AE_MODE_AUTO: > + default: > + ret += ov5640_write(c, 0x501d, 0); > + return ret; > + } > + > + ret += ov5640_write(c, 0x5688, reg_1); > + ret += ov5640_write(c, 0x5689, reg_2); > + ret += ov5640_write(c, 0x568a, reg_3); > + ret += ov5640_write(c, 0x568b, reg_4); > + ret += ov5640_write(c, 0x568c, reg_5); > + ret += ov5640_write(c, 0x568d, reg_6); > + ret += ov5640_write(c, 0x568e, reg_7); > + ret += ov5640_write(c, 0x568f, reg_8); > + > + reg_1 = (ov5640_status.ae_x >> 8); > + reg_2 = ov5640_status.ae_x & 0xff; > + reg_3 = (ov5640_status.ae_y >> 8); > + reg_4 = ov5640_status.ae_y & 0xff; > + reg_5 = ((ov5640_status.ae_x + ov5640_status.ae_w) >> 8); > + reg_6 = (ov5640_status.ae_x + ov5640_status.ae_w) & 0xff; > + reg_7 = ((ov5640_status.ae_y + ov5640_status.ae_h) >> 8); > + reg_8 = (ov5640_status.ae_y + ov5640_status.ae_h) & 0xff; > + > + ret += ov5640_write(c, 0x5680, reg_1); > + ret += ov5640_write(c, 0x5681, reg_2); > + ret += ov5640_write(c, 0x5682, reg_3); > + ret += ov5640_write(c, 0x5683, reg_4); > + ret += ov5640_write(c, 0x5684, reg_5); > + ret += ov5640_write(c, 0x5685, reg_6); > + ret += ov5640_write(c, 0x5686, reg_7); > + ret += ov5640_write(c, 0x5687, reg_8); > + > + ret += ov5640_write(c, 0x501d, 0x10); > + > return ret; > } > static int ov5640_q_exposure(struct v4l2_subdev *sd, int *value) > { > int ret=0; > - // TODO: will be added soon > + *value = ov5640_status.ae_mode; > return ret; > } > -static int ov5640_t_flash_detect(struct v4l2_subdev *sd, int value) > + > +#define OV5640_EXPOSURE_NORMALIZED_W 800 > +#define OV5640_EXPOSURE_NORMALIZED_H 384 > + > +static int ov5640_t_exposure_window(struct v4l2_subdev *sd, int value) > { > + unsigned int tmp_y,tmp_x; > int ret=0; > - // TODO: will be added soon > + u32 v = (u32)value; > + dprintk( 3, "%s (0x%08x)", __FUNCTION__,v); > + > + if (v & (1UL<<30)) > + { > + tmp_y = v & 0xffff; > + tmp_x = (v>>16) & 0x3fff; > + ov5640_status.ae_x = (tmp_x * OV5640_EXPOSURE_NORMALIZED_W) / > ov5640_res[ov5640_status.current_res_i].width; > + ov5640_status.ae_y = (tmp_y * OV5640_EXPOSURE_NORMALIZED_H) / > ov5640_res[ov5640_status.current_res_i].height; > + } else { > + tmp_y = v & 0xffff; > + tmp_x = (v>>16) & 0x3fff; > + ov5640_status.ae_w = (tmp_x * OV5640_EXPOSURE_NORMALIZED_W) / > ov5640_res[ov5640_status.current_res_i].width; > + ov5640_status.ae_h = (tmp_y * OV5640_EXPOSURE_NORMALIZED_H) / > ov5640_res[ov5640_status.current_res_i].height; > + } > + > return ret; > } > +static int ov5640_q_exposure_window(struct v4l2_subdev *sd, int *value) > +{ > + int ret=0; > + if ((u32)(*value) & (1UL<<31)) > + { > + *value = ((ov5640_status.ae_x << 16) | ov5640_status.ae_y); > + } else { > + *value = ((ov5640_status.ae_w << 16) | ov5640_status.ae_h); > + } > -static int ov5640_q_flash_detect(struct v4l2_subdev *sd, int *value) > + return ret; > +} > + > +#define OV5640_WB_AUTO 0 > +#define OV5640_WB_CLOUD 1 > +#define OV5640_WB_DAYLIGHT 2 > +#define OV5640_WB_INCANDESCENT 3 > +#define OV5640_WB_FLUORESCENT 4 > +#define OV5640_WB_TUNGSTEN 5 > + > +static int ov5640_t_scene_mode(struct v4l2_subdev *sd, int value) > { > + struct i2c_client *c = v4l2_get_subdevdata(sd); > int ret=0; > + u8 v,reg_1,reg_2,reg_3,reg_4,reg_5,reg_6; > + > + dprintk( 3, "%s (%d)",__FUNCTION__,value); > + ov5640_status.scene_val = value; > + > + switch (value) > + { > + case OV5640_WB_CLOUD: > + reg_1 = 0x7; > + reg_2 = 0x88; > + reg_3 = 0x4; > + reg_4 = 0x0; > + reg_5 = 0x5; > + reg_6 = 0x0; > + break; > + case OV5640_WB_DAYLIGHT: > + reg_1 = 0x7; > + reg_2 = 0x2; > + reg_3 = 0x4; > + reg_4 = 0x0; > + reg_5 = 0x5; > + reg_6 = 0x15; > + break; > + case OV5640_WB_INCANDESCENT: > + reg_1 = 0x4; > + reg_2 = 0x88; > + reg_3 = 4; > + reg_4 = 0x0; > + reg_5 = 0x8; > + reg_6 = 0xb6; > + break; > + case OV5640_WB_FLUORESCENT: > + reg_1 = 0x6; > + reg_2 = 0x2a; > + reg_3 = 4; > + reg_4 = 0x0; > + reg_5 = 0x7; > + reg_6 = 0x24; > + break; > + case OV5640_WB_TUNGSTEN: > + reg_1 = 0x4; > + reg_2 = 0x58; > + reg_3 = 4; > + reg_4 = 0x0; > + reg_5 = 0x8; > + reg_6 = 0x40; > + break; > + case OV5640_WB_AUTO: > + default: > + ret += ov5640_read(c, 0x3406, &v); > + ret += ov5640_write(c, 0x3406, v & 0xfe); > + return ret; > + } > + > + ret += ov5640_read(c, 0x3406, &v); > + ret += ov5640_write(c, 0x3406, v | 1); > + > + ret += ov5640_write(c, 0x3400, reg_1); > + ret += ov5640_write(c, 0x3401, reg_2); > + ret += ov5640_write(c, 0x3402, reg_3); > + ret += ov5640_write(c, 0x3403, reg_4); > + ret += ov5640_write(c, 0x3404, reg_5); > + ret += ov5640_write(c, 0x3405, reg_6); > + > + return ret; > +} > +static int ov5640_q_scene_mode(struct v4l2_subdev *sd, int *value) > +{ > + int ret=0; > + > + *value = ov5640_status.scene_val; > + return ret; > +} > + > +#define OV5640_SPE_NORMAL 0 > +#define OV5640_SPE_BLACKWHITE 1 > +#define OV5640_SPE_BLUISH 2 > +#define OV5640_SPE_SEPIA 3 > +#define OV5640_SPE_REDDISH 4 > +#define OV5640_SPE_GREENISH 5 > +#define OV5640_SPE_NEGATIVE 6 > + > +static int ov5640_t_spe_mode(struct v4l2_subdev *sd, int value) > +{ > struct i2c_client *c = v4l2_get_subdevdata(sd); > + int ret=0; > + u8 v,reg_1,reg_2; > + > + dprintk( 3, "%s (%d)",__FUNCTION__,value); > + ov5640_status.spe_val = value; > + > + switch (value) > + { > + case OV5640_SPE_BLACKWHITE: > + reg_1 = 0x80; > + reg_2 = 0x80; > + break; > + case OV5640_SPE_BLUISH: > + reg_1 = 0xa0; > + reg_2 = 0x40; > + break; > + case OV5640_SPE_SEPIA: > + reg_1 = 0x40; > + reg_2 = 0xa0; > + break; > + case OV5640_SPE_REDDISH: > + reg_1 = 0x80; > + reg_2 = 0xc0; > + break; > + case OV5640_SPE_GREENISH: > + reg_1 = 0x60; > + reg_2 = 0x60; > + break; > + case OV5640_SPE_NEGATIVE: > + ret += ov5640_read(c, 0x5001, &v); > + ret += ov5640_write(c, 0x5001, v | 0x80); > + ret += ov5640_read(c, 0x5580, &v); > + ret += ov5640_write(c, 0x5580, (v & 0xa7)|0x40); > + return ret; > + case OV5640_SPE_NORMAL: > + default: > + ret += ov5640_read(c, 0x5001, &v); > + ret += ov5640_write(c, 0x5001, v & 0x7f); > + ret += ov5640_read(c, 0x5580, &v); > + ret += ov5640_write(c, 0x5580, v & 0xa7); > + return ret; > + } > + > + ret += ov5640_read(c, 0x5001, &v); > + ret += ov5640_write(c, 0x5001, v | 0x80); > + ret += ov5640_read(c, 0x5580, &v); > + ret += ov5640_write(c, 0x5580, (v & 0xa7)|0x18); > + > + ret += ov5640_write(c, 0x5583, reg_1); > + ret += ov5640_write(c, 0x5584, reg_2); > + > + return ret; > +} > +static int ov5640_q_spe_mode(struct v4l2_subdev *sd, int *value) > +{ > + int ret=0; > + > + *value = ov5640_status.spe_val; > + return ret; > +} > + > +static int ov5640_t_exp_comp(struct v4l2_subdev *sd, int value) > +{ > + struct i2c_client *c = v4l2_get_subdevdata(sd); > + int ret=0; > + u8 reg_1,reg_2,reg_3,reg_4,reg_5,reg_6; > + > + dprintk( 3, "%s (%d)",__FUNCTION__,value); > + ov5640_status.exp_comp_val = value; > + > + switch (value) > + { > + case -2: > + reg_1 = 0x28; > + reg_2 = 0x20; > + reg_3 = 0x51; > + reg_4 = 0x28; > + reg_5 = 0x20; > + reg_6 = 0x10; > + break; > + case -1: > + reg_1 = 0x30; > + reg_2 = 0x28; > + reg_3 = 0x61; > + reg_4 = 0x30; > + reg_5 = 0x28; > + reg_6 = 0x10; > + break; > + case 1: > + reg_1 = 0x40; > + reg_2 = 0x38; > + reg_3 = 0x71; > + reg_4 = 0x40; > + reg_5 = 0x38; > + reg_6 = 0x10; > + break; > + case 2: > + reg_1 = 0x48; > + reg_2 = 0x40; > + reg_3 = 0x80; > + reg_4 = 0x48; > + reg_5 = 0x40; > + reg_6 = 0x20; > + break; > + case 0: > + default: > + reg_1 = 0x38; > + reg_2 = 0x30; > + reg_3 = 0x61; > + reg_4 = 0x38; > + reg_5 = 0x30; > + reg_6 = 0x10; > + break; > + } > + > + ret += ov5640_write(c, 0x3a0f, reg_1); > + ret += ov5640_write(c, 0x3a10, reg_2); > + ret += ov5640_write(c, 0x3a11, reg_3); > + ret += ov5640_write(c, 0x3a1b, reg_4); > + ret += ov5640_write(c, 0x3a1e, reg_5); > + ret += ov5640_write(c, 0x3a1f, reg_6); > + > + return ret; > +} > +static int ov5640_q_exp_comp(struct v4l2_subdev *sd, int *value) > +{ > + int ret=0; > + > + *value = ov5640_status.exp_comp_val; > + return ret; > +} > + > +static int ov5640_t_exposure_level_detect(struct v4l2_subdev *sd, int value) > +{ > + int ret=0; > + // this CID is RO > + > + return ret; > +} > + > +static int ov5640_q_exposure_level_detect(struct v4l2_subdev *sd, int *value) > +{ > + int ret=0; > + struct i2c_client *c = v4l2_get_subdevdata(sd); > int exposure,gain; > u8 v; > @@ -1690,15 +2340,16 @@ > .qc = { > .id = V4L2_CID_GAIN, > .type = V4L2_CTRL_TYPE_INTEGER, > - .name = "ISO Manual Val", > - .minimum = 100, > + .name = "ISO", > + .minimum = 0, > .maximum = 1600, > .step = 100, > - .default_value = 100, > + .default_value = 0, > }, > .tweak = ov5640_t_iso_val, > .query = ov5640_q_iso_val, > }, > + /* > { > .qc = { > .id = V4L2_CID_AUTOGAIN, > @@ -1711,7 +2362,7 @@ > }, > .tweak = ov5640_t_iso_mode, > .query = ov5640_q_iso_mode, > - }, > + },*/ > { > .qc = { > .id = V4L2_CID_BRIGHTNESS, > @@ -1769,8 +2420,8 @@ > .id = V4L2_CID_SHARPNESS, > .type = V4L2_CTRL_TYPE_INTEGER, > .name = "Sharpness", > - .minimum = -2, > - .maximum = 2, > + .minimum = 0, > + .maximum = 99, > .step = 1, > .default_value = 0, > }, > @@ -1782,7 +2433,13 @@ > #define CID_FOCUS_POSITION (V4L2_CID_PRIVATE_BASE + 0) > #define CID_FOCUS_MODE_STATUS (V4L2_CID_PRIVATE_BASE + 1) > #define CID_EXPOSURE_MODE_STATUS (V4L2_CID_PRIVATE_BASE + 2) > -#define CID_AUTO_FLASH_DETECT (V4L2_CID_PRIVATE_BASE + 3) > +#define CID_EXPOSURE_WINDOW (V4L2_CID_PRIVATE_BASE + 3) > +#define CID_EXPOSURE_LEVEL_DETECT (V4L2_CID_PRIVATE_BASE + 4) > +#define CID_FLASH_SWITCH (V4L2_CID_PRIVATE_BASE + 5) > +#define CID_SCENE_MODE (V4L2_CID_PRIVATE_BASE + 6) > +#define CID_SPE_MODE (V4L2_CID_PRIVATE_BASE + 7) > +#define CID_EXPOSURE_COMPENSATION (V4L2_CID_PRIVATE_BASE + 8) > + > { > .qc = { > .id = CID_FOCUS_POSITION, > @@ -1824,17 +2481,84 @@ > }, > { > .qc = { > - .id = CID_AUTO_FLASH_DETECT , > + .id = CID_EXPOSURE_WINDOW, > .type = V4L2_CTRL_TYPE_INTEGER, > - .name = "Auto Flash Detect", > + .name = "Exposure Window", > .minimum = 0, > .maximum = 0x7fffffff, > .step = 1, > + // default window, 320x240 of a total 1280x720 prevew screen > + .default_value = 0x014000f0, > + }, > + .tweak = ov5640_t_exposure_window, > + .query = ov5640_q_exposure_window, > + }, > + { > + .qc = { > + .id = CID_EXPOSURE_LEVEL_DETECT, > + .type = V4L2_CTRL_TYPE_INTEGER, > + .name = "Exposure Level Detect", > + .minimum = 0, > + .maximum = 0x7fffffff, > + .step = 1, > .default_value = 0, > }, > - .tweak = ov5640_t_flash_detect, > - .query = ov5640_q_flash_detect, > + .tweak = ov5640_t_exposure_level_detect, > + .query = ov5640_q_exposure_level_detect, > }, > + { > + .qc = { > + .id = CID_FLASH_SWITCH , > + .type = V4L2_CTRL_TYPE_BOOLEAN, > + .name = "Flash Switch", > + .minimum = 0, > + .maximum = 1, > + .step = 1, > + .default_value = 0, > + }, > + .tweak = ov5640_t_flash, > + .query = ov5640_q_flash, > + }, > + { > + .qc = { > + .id = CID_SCENE_MODE, > + .type = V4L2_CTRL_TYPE_INTEGER, > + .name = "Scene Mode", > + .minimum = 0, > + .maximum = 5, > + .step = 1, > + .default_value = 0, > + }, > + .tweak = ov5640_t_scene_mode, > + .query = ov5640_q_scene_mode, > + }, > + { > + .qc = { > + .id = CID_SPE_MODE , > + .type = V4L2_CTRL_TYPE_INTEGER, > + .name = "SPE Mode", > + .minimum = 0, > + .maximum = 6, > + .step = 1, > + .default_value = 0, > + }, > + .tweak = ov5640_t_spe_mode, > + .query = ov5640_q_spe_mode, > + }, > + { > + .qc = { > + .id = CID_EXPOSURE_COMPENSATION, > + .type = V4L2_CTRL_TYPE_INTEGER, > + .name = "Exposure Compensation", > + .minimum = -2, > + .maximum = 2, > + .step = 1, > + .default_value = 0, > + }, > + > + .tweak = ov5640_t_exp_comp, > + .query = ov5640_q_exp_comp, > + }, > #if 0 //BUGBUG > { > .qc = { > @@ -2217,6 +2941,8 @@ > struct ci_sensor_config *info; > struct v4l2_subdev *sd; > int ret = -1; > +#define LANGWELL_GPIO_BASE_ADDR 0xff12c000 > + u32 __iomem *mem = ioremap_nocache(LANGWELL_GPIO_BASE_ADDR, 64); > DBG_entering; > @@ -2240,11 +2966,14 @@ > sd = &info->sd; > v4l2_i2c_subdev_init(sd, client, &ov5640_ops); > + // change LANGWELL GPIO-45 mux to GPIO Funtion > + gpio_direction_output(GPIO_FLASH,0); > + *(mem + 16) &= 0xf3ffffff; > + > /* > * TODO: Need to check if this can be here. > * Turn into standby mode > */ > - /* ov5640_standby(); */ > ret += ov5640_init(client); > ov5640_standby(sd); > > > Best Regards, > > Yong He > Software Engineer, PCSD SW Solutions, > Intel Asia-Pacific R&D Ltd. > Phone (+86) 21-61166334 > Lab (+86) 21-61167881 > _______________________________________________ MeeGo-kernel mailing list MeeGo-kernel@lists.meego.com http://lists.meego.com/listinfo/meego-kernel