mirror of
https://github.com/hardkernel/linux.git
synced 2026-04-22 21:40:52 +09:00
camera: sync s5k6aa sensor driver for FIH project
This commit is contained in:
@@ -22,6 +22,16 @@
|
||||
#include <mach/rk29_camera.h>
|
||||
#include <linux/delay.h>
|
||||
#include "s5k6aa.h"
|
||||
static int debug;
|
||||
module_param(debug, int, S_IRUGO|S_IWUSR);
|
||||
|
||||
#define dprintk(level, fmt, arg...) do { \
|
||||
if (debug >= level) \
|
||||
printk(KERN_WARNING fmt , ## arg); } while (0)
|
||||
|
||||
#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
|
||||
#define SENSOR_DG(format, ...) dprintk(0, format, ## __VA_ARGS__)
|
||||
|
||||
|
||||
#define _CONS(a,b) a##b
|
||||
#define CONS(a,b) _CONS(a,b)
|
||||
@@ -30,10 +40,16 @@
|
||||
#define _STR(x) __STR(x)
|
||||
#define STR(x) _STR(x)
|
||||
|
||||
#define MIN(x,y) ((x<y) ? x: y)
|
||||
#define MAX(x,y) ((x>y) ? x: y)
|
||||
|
||||
/* Sensor Driver Configuration */
|
||||
#define SENSOR_NAME s5k6aa
|
||||
#define SENSOR_V4L2_IDENT V4L2_IDENT_S5K66A
|
||||
#define SENSOR_ID 0x06aa
|
||||
#define SENSOR_ID_REG 0x015a
|
||||
#define SENSOR_RESET_REG SEQUENCE_END
|
||||
#define SENSOR_RESET_VAL 0x00
|
||||
#define SENSOR_MIN_WIDTH 640
|
||||
#define SENSOR_MIN_HEIGHT 480
|
||||
#define SENSOR_MAX_WIDTH 1280
|
||||
@@ -55,29 +71,14 @@
|
||||
#define CONFIG_SENSOR_Flash 0
|
||||
#define CONFIG_SENSOR_Mirror 0
|
||||
#define CONFIG_SENSOR_Flip 0
|
||||
#define CONFIG_SENSOR_Focus 0
|
||||
|
||||
#define CONFIG_SENSOR_I2C_SPEED 100000 /* Hz */
|
||||
|
||||
#define CONFIG_SENSOR_TR 0
|
||||
#define CONFIG_SENSOR_DEBUG 0
|
||||
#define CONFIG_SENSOR_I2C_SPEED 250000 /* Hz */
|
||||
/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
|
||||
#define CONFIG_SENSOR_I2C_NOSCHED 0
|
||||
#define CONFIG_SENSOR_I2C_RDWRCHK 0
|
||||
|
||||
#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
|
||||
#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
|
||||
|
||||
#define MIN(x,y) ((x<y) ? x: y)
|
||||
#define MAX(x,y) ((x>y) ? x: y)
|
||||
|
||||
#if (CONFIG_SENSOR_TR)
|
||||
#define SENSOR_TR(format, ...) printk(format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define SENSOR_TR(format, ...)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_SENSOR_DEBUG)
|
||||
#define SENSOR_DG(format, ...) printk(format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define SENSOR_DG(format, ...)
|
||||
#endif
|
||||
|
||||
#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |\
|
||||
SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |\
|
||||
@@ -92,11 +93,20 @@
|
||||
#define COLOR_TEMPERATURE_HOME_DN 2500
|
||||
#define COLOR_TEMPERATURE_HOME_UP 3500
|
||||
|
||||
struct reginfo
|
||||
{
|
||||
u16 reg;
|
||||
u16 val;
|
||||
};
|
||||
#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
|
||||
#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
|
||||
|
||||
#define SENSOR_AF_IS_ERR (0x00<<0)
|
||||
#define SENSOR_AF_IS_OK (0x01<<0)
|
||||
|
||||
#if CONFIG_SENSOR_Focus
|
||||
#define SENSOR_AF_MODE_INFINITY 0
|
||||
#define SENSOR_AF_MODE_MACRO 1
|
||||
#define SENSOR_AF_MODE_FIXED 2
|
||||
#define SENSOR_AF_MODE_AUTO 3
|
||||
#define SENSOR_AF_MODE_CONTINUOUS 4
|
||||
#define SENSOR_AF_MODE_CLOSE 5
|
||||
#endif
|
||||
|
||||
/* init 640X480 SVGA */
|
||||
static struct reginfo sensor_init_data[] =
|
||||
@@ -5012,6 +5022,9 @@ static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg);
|
||||
static int sensor_resume(struct soc_camera_device *icd);
|
||||
static int sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);
|
||||
static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);
|
||||
static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
|
||||
static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
|
||||
static int sensor_deactivate(struct i2c_client *client);
|
||||
|
||||
static struct soc_camera_ops sensor_ops =
|
||||
{
|
||||
@@ -5035,6 +5048,17 @@ static struct soc_camera_ops sensor_ops =
|
||||
static const struct soc_camera_data_format sensor_colour_formats[] = {
|
||||
JPG_FMT(SENSOR_NAME_STRING(YUYV), 16, V4L2_PIX_FMT_YUYV),
|
||||
};
|
||||
enum sensor_work_state
|
||||
{
|
||||
sensor_work_ready = 0,
|
||||
sensor_working,
|
||||
};
|
||||
struct sensor_work
|
||||
{
|
||||
struct i2c_client *client;
|
||||
struct delayed_work dwork;
|
||||
enum sensor_work_state state;
|
||||
};
|
||||
|
||||
typedef struct sensor_info_priv_s
|
||||
{
|
||||
@@ -5046,21 +5070,51 @@ typedef struct sensor_info_priv_s
|
||||
int scene;
|
||||
int digitalzoom;
|
||||
int focus;
|
||||
int auto_focus;
|
||||
int affm_reinit;
|
||||
int flash;
|
||||
int exposure;
|
||||
unsigned char mirror; /* HFLIP */
|
||||
unsigned char flip; /* VFLIP */
|
||||
unsigned int winseqe_cur_addr;
|
||||
bool snap2preview;
|
||||
bool video2preview;
|
||||
int capture_w;
|
||||
int capture_h;
|
||||
int preview_w;
|
||||
int preview_h;
|
||||
struct reginfo *winseqe_cur_addr;
|
||||
unsigned int pixfmt;
|
||||
|
||||
unsigned int enable;
|
||||
unsigned int funmodule_state;
|
||||
} sensor_info_priv_t;
|
||||
|
||||
|
||||
|
||||
struct sensor_parameter
|
||||
{
|
||||
unsigned short int preview_maxlines;
|
||||
unsigned short int preview_exposure;
|
||||
unsigned short int preview_line_width;
|
||||
unsigned short int preview_gain;
|
||||
|
||||
unsigned short int capture_framerate;
|
||||
unsigned short int preview_framerate;
|
||||
};
|
||||
|
||||
struct sensor
|
||||
{
|
||||
struct v4l2_subdev subdev;
|
||||
struct i2c_client *client;
|
||||
sensor_info_priv_t info_priv;
|
||||
struct sensor_parameter parameter;
|
||||
struct workqueue_struct *sensor_wq;
|
||||
struct sensor_work sensor_wk;
|
||||
struct mutex wq_lock;
|
||||
int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
|
||||
#if CONFIG_SENSOR_I2C_NOSCHED
|
||||
atomic_t tasklock_cnt;
|
||||
#endif
|
||||
struct rk29camera_platform_data *sensor_io_request;
|
||||
};
|
||||
|
||||
static struct sensor* to_sensor(const struct i2c_client *client)
|
||||
@@ -5068,34 +5122,95 @@ static struct sensor* to_sensor(const struct i2c_client *client)
|
||||
return container_of(i2c_get_clientdata(client), struct sensor, subdev);
|
||||
}
|
||||
|
||||
static int sensor_task_lock(struct i2c_client *client, int lock)
|
||||
{
|
||||
#if CONFIG_SENSOR_I2C_NOSCHED
|
||||
int cnt = 3;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
|
||||
if (lock) {
|
||||
if (atomic_read(&sensor->tasklock_cnt) == 0) {
|
||||
while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) {
|
||||
SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING());
|
||||
msleep(35);
|
||||
cnt--;
|
||||
}
|
||||
if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) {
|
||||
SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING());
|
||||
goto sensor_task_lock_err;
|
||||
}
|
||||
preempt_disable();
|
||||
}
|
||||
|
||||
atomic_add(1, &sensor->tasklock_cnt);
|
||||
} else {
|
||||
if (atomic_read(&sensor->tasklock_cnt) > 0) {
|
||||
atomic_sub(1, &sensor->tasklock_cnt);
|
||||
|
||||
if (atomic_read(&sensor->tasklock_cnt) == 0)
|
||||
preempt_enable();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
sensor_task_lock_err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* sensor register write */
|
||||
static int sensor_write(struct i2c_client *client, u16 reg, u16 val)
|
||||
{
|
||||
int err=0,cnt;
|
||||
u8 buf[4];
|
||||
struct i2c_msg msg[1];
|
||||
int err = 0;
|
||||
|
||||
if(reg != SEQUENCE_WAIT_MS) {
|
||||
buf[0] = reg >> 8;
|
||||
buf[1] = reg & 0xFF;
|
||||
buf[2] = val>> 8;
|
||||
buf[3] = val & 0xFF;
|
||||
|
||||
msg->addr = client->addr;
|
||||
msg->flags = client->flags;
|
||||
msg->buf = buf;
|
||||
msg->len = sizeof(buf);
|
||||
msg->scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
|
||||
msg->read_type = 0; /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */
|
||||
|
||||
err = i2c_transfer(client->adapter, msg, 1);
|
||||
if (err < 0) {
|
||||
SENSOR_TR("%s write reg(0x%x val:0x%x) failed!",SENSOR_NAME_STRING(),reg,val);
|
||||
switch (reg)
|
||||
{
|
||||
case SEQUENCE_WAIT_MS:
|
||||
{
|
||||
msleep(val);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
msleep(val);
|
||||
}
|
||||
|
||||
case SEQUENCE_WAIT_US:
|
||||
{
|
||||
udelay(val);
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQUENCE_PROPERTY:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
buf[0] = reg >> 8;
|
||||
buf[1] = reg & 0xFF;
|
||||
buf[2] = val >> 8;
|
||||
buf[3] = val & 0xFF;
|
||||
|
||||
msg->addr = client->addr;
|
||||
msg->flags = client->flags;
|
||||
msg->buf = buf;
|
||||
msg->len = sizeof(buf);
|
||||
msg->scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
|
||||
msg->read_type = 0; /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */
|
||||
|
||||
cnt = 3;
|
||||
err = -EAGAIN;
|
||||
|
||||
while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
|
||||
err = i2c_transfer(client->adapter, msg, 1);
|
||||
|
||||
if (err >= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
|
||||
udelay(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -5139,34 +5254,146 @@ static int sensor_read(struct i2c_client *client, u16 reg, u16 *val)
|
||||
/* write a array of registers */
|
||||
static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
|
||||
{
|
||||
int err, cnt;
|
||||
int err = 0, cnt;
|
||||
int i = 0;
|
||||
u16 val00;
|
||||
#if CONFIG_SENSOR_I2C_RDWRCHK
|
||||
char valchk;
|
||||
#endif
|
||||
|
||||
cnt = 0;
|
||||
while (regarray[i].reg != SEQUENCE_END) {
|
||||
if (sensor_task_lock(client, 1) < 0)
|
||||
goto sensor_write_array_end;
|
||||
while (regarray[i].reg != SEQUENCE_END)
|
||||
{
|
||||
|
||||
err = sensor_write(client, regarray[i].reg, regarray[i].val);
|
||||
if (err < 0) {
|
||||
if (err < 0)
|
||||
{
|
||||
if (cnt-- > 0) {
|
||||
SENSOR_TR("%s..write failed current reg:0x%x, Write array again !\n", SENSOR_NAME_STRING(),regarray[i].reg);
|
||||
i = 0;
|
||||
continue;
|
||||
} else {
|
||||
SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
|
||||
return -EPERM;
|
||||
err = -EPERM;
|
||||
goto sensor_write_array_end;
|
||||
}
|
||||
} else {
|
||||
sensor_read(client, regarray[i].reg, &val00);
|
||||
if (val00 != regarray[i].val) {
|
||||
SENSOR_TR("%s write reg(0x%x val:0x%x) fail\n",SENSOR_NAME_STRING(),regarray[i].reg,val00);
|
||||
}
|
||||
#if CONFIG_SENSOR_I2C_RDWRCHK
|
||||
sensor_read(client, regarray[i].reg, &valchk);
|
||||
if (valchk != regarray[i].val)
|
||||
SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
sensor_write_array_end:
|
||||
sensor_task_lock(client,0);
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_SENSOR_I2C_RDWRCHK
|
||||
static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
|
||||
{
|
||||
int cnt;
|
||||
int i = 0;
|
||||
char valchk;
|
||||
|
||||
cnt = 0;
|
||||
valchk = 0;
|
||||
while (regarray[i].reg != SEQUENCE_END)
|
||||
{
|
||||
sensor_read(client, regarray[i].reg, &valchk);
|
||||
if (valchk != regarray[i].val)
|
||||
SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
|
||||
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_SENSOR_Focus
|
||||
|
||||
static int sensor_af_single(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
||||
sensor_af_single_end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_af_const(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
sensor_af_const_end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_af_zoneupdate(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
sensor_af_zoneupdate_end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_af_init(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
|
||||
{
|
||||
struct soc_camera_link *icl = to_soc_camera_link(icd);
|
||||
int ret = 0;
|
||||
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case Sensor_PowerDown:
|
||||
{
|
||||
if (icl->powerdown) {
|
||||
ret = icl->powerdown(icd->pdev, on);
|
||||
if (ret == RK29_CAM_IO_SUCCESS) {
|
||||
if (on == 0) {
|
||||
mdelay(2);
|
||||
if (icl->reset)
|
||||
icl->reset(icd->pdev);
|
||||
}
|
||||
} else if (ret == RK29_CAM_EIO_REQUESTFAIL) {
|
||||
ret = -ENODEV;
|
||||
goto sensor_power_end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Sensor_Flash:
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
|
||||
if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
|
||||
sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SENSOR_TR("%s power cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sensor_power_end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_init(struct v4l2_subdev *sd, u32 val)
|
||||
{
|
||||
@@ -5174,32 +5401,43 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
const struct v4l2_queryctrl *qctrl;
|
||||
u16 value;
|
||||
int ret,pid = 0;
|
||||
|
||||
SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
|
||||
#if 0
|
||||
|
||||
if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
|
||||
ret = -ENODEV;
|
||||
goto sensor_INIT_ERR;
|
||||
}
|
||||
|
||||
/* soft reset */
|
||||
ret = sensor_write(client, 0x001a, 0x0011);
|
||||
if (ret != 0)
|
||||
{
|
||||
if (sensor_task_lock(client,1)<0)
|
||||
goto sensor_INIT_ERR;
|
||||
|
||||
#if (SENSOR_RESET_REG != SEQUENCE_END)
|
||||
ret = sensor_write(client, SENSOR_RESET_REG, SENSOR_RESET_VAL);
|
||||
if (ret != 0) {
|
||||
SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING());
|
||||
ret = -ENODEV;
|
||||
goto sensor_INIT_ERR;
|
||||
}
|
||||
|
||||
mdelay(5); //delay 5 microseconds
|
||||
|
||||
#endif
|
||||
|
||||
/* check if it is an sensor sensor */
|
||||
ret = sensor_read(client, 0x015a, &value);
|
||||
#if (SENSOR_ID_REG != SEQUENCE_END)
|
||||
ret = sensor_read(client, SENSOR_ID_REG, &pid);
|
||||
if (ret != 0) {
|
||||
SENSOR_TR("read chip id high byte failed\n");
|
||||
SENSOR_TR("read chip id failed\n");
|
||||
ret = -ENODEV;
|
||||
goto sensor_INIT_ERR;
|
||||
}
|
||||
pid = value;
|
||||
SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
|
||||
|
||||
SENSOR_DG("\n %s pid = 0x%x \n", SENSOR_NAME_STRING(), pid);
|
||||
#else
|
||||
pid = SENSOR_ID;
|
||||
#endif
|
||||
if (pid == SENSOR_ID) {
|
||||
sensor->model = SENSOR_V4L2_IDENT;
|
||||
} else {
|
||||
@@ -5207,7 +5445,6 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
|
||||
ret = -ENODEV;
|
||||
goto sensor_INIT_ERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = sensor_write_array(client, sensor_init_data);
|
||||
if (ret != 0)
|
||||
@@ -5215,10 +5452,8 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
|
||||
SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
|
||||
goto sensor_INIT_ERR;
|
||||
}
|
||||
|
||||
icd->user_width = SENSOR_INIT_WIDTH;
|
||||
icd->user_height = SENSOR_INIT_HEIGHT;
|
||||
sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;
|
||||
sensor_task_lock(client,0);
|
||||
sensor->info_priv.winseqe_cur_addr = SENSOR_INIT_WINSEQADR;
|
||||
sensor->info_priv.pixfmt = SENSOR_INIT_PIXFMT;
|
||||
|
||||
/* sensor sensor information for initialization */
|
||||
@@ -5255,34 +5490,36 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
|
||||
sensor->info_priv.digitalzoom = qctrl->default_value;
|
||||
|
||||
/* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code */
|
||||
#if CONFIG_SENSOR_Focus
|
||||
sensor_set_focus();
|
||||
qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
|
||||
qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
|
||||
if (qctrl)
|
||||
sensor->info_priv.focus = qctrl->default_value;
|
||||
#endif
|
||||
|
||||
#if CONFIG_SENSOR_Flash
|
||||
sensor_set_flash();
|
||||
qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);
|
||||
if (qctrl)
|
||||
sensor->info_priv.flash = qctrl->default_value;
|
||||
#endif
|
||||
|
||||
SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,icd->user_width,icd->user_height);
|
||||
SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
|
||||
|
||||
return 0;
|
||||
sensor_INIT_ERR:
|
||||
sensor_task_lock(client,0);
|
||||
sensor_deactivate(client);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_deactivate(struct v4l2_subdev *sd)
|
||||
static int sensor_deactivate(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct soc_camera_device *icd = client->dev.platform_data;
|
||||
|
||||
SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
|
||||
SENSOR_DG("\n%s..%s.. Enter\n",SENSOR_NAME_STRING(),__FUNCTION__);
|
||||
|
||||
/* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
|
||||
sensor_task_lock(client, 1);
|
||||
|
||||
/* ddl@rock-chips.com : sensor config init width , because next open sensor quickly(soc_camera_open -> Try to configure with default parameters) */
|
||||
icd->user_width = SENSOR_INIT_WIDTH;
|
||||
icd->user_height = SENSOR_INIT_HEIGHT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5295,56 +5532,40 @@ static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
|
||||
struct soc_camera_link *icl;
|
||||
|
||||
|
||||
if (pm_msg.event == PM_EVENT_SUSPEND)
|
||||
{
|
||||
if (pm_msg.event == PM_EVENT_SUSPEND) {
|
||||
SENSOR_DG("\n %s Enter Suspend.. \n", SENSOR_NAME_STRING());
|
||||
ret = sensor_write_array(client, sensor_power_down_sequence) ;
|
||||
if (ret != 0)
|
||||
{
|
||||
if (ret != 0) {
|
||||
SENSOR_TR("\n %s..%s WriteReg Fail.. \n", SENSOR_NAME_STRING(),__FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
icl = to_soc_camera_link(icd);
|
||||
if (icl->power) {
|
||||
ret = icl->power(icd->pdev, 0);
|
||||
if (ret < 0) {
|
||||
SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
ret = sensor_ioctrl(icd, Sensor_PowerDown, 1);
|
||||
if (ret < 0) {
|
||||
SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
SENSOR_TR("\n %s cann't suppout Suspend..\n",SENSOR_NAME_STRING());
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sensor_resume(struct soc_camera_device *icd)
|
||||
{
|
||||
struct soc_camera_link *icl;
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
icl = to_soc_camera_link(icd);
|
||||
if (icl->power) {
|
||||
ret = icl->power(icd->pdev, 1);
|
||||
if (ret < 0) {
|
||||
SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = sensor_ioctrl(icd, Sensor_PowerDown, 0);
|
||||
if (ret < 0) {
|
||||
SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
SENSOR_DG("\n %s Enter Resume.. \n", SENSOR_NAME_STRING());
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sensor_set_bus_param(struct soc_camera_device *icd,
|
||||
@@ -5376,6 +5597,41 @@ static int sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
||||
|
||||
return 0;
|
||||
}
|
||||
static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_format *f)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
|
||||
ret = true;
|
||||
} else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
|
||||
ret = true;
|
||||
} else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
|
||||
ret = true;
|
||||
} else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
|
||||
ret = true;
|
||||
} else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (ret == true)
|
||||
SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_format *f)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 720)) {
|
||||
ret = true;
|
||||
} else if ((f->fmt.pix.width == 1920) && (f->fmt.pix.height == 1080)) {
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (ret == true)
|
||||
SENSOR_DG("%s %dx%d is video format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
|
||||
return ret;
|
||||
}
|
||||
static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
@@ -6175,13 +6431,25 @@ static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_control
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
|
||||
if (enable == 1) {
|
||||
sensor->info_priv.enable = 1;
|
||||
} else if (enable == 0) {
|
||||
sensor->info_priv.enable = 0;
|
||||
}
|
||||
|
||||
sensor_s_stream_end:
|
||||
return 0;
|
||||
}
|
||||
/* Interface active, can use i2c. If it fails, it can indeed mean, that
|
||||
* this wasn't our capture interface, so, we wait for the right one */
|
||||
static int sensor_video_probe(struct soc_camera_device *icd,
|
||||
struct i2c_client *client)
|
||||
{
|
||||
u16 value;
|
||||
int ret,pid = 0;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
|
||||
@@ -6190,28 +6458,38 @@ static int sensor_video_probe(struct soc_camera_device *icd,
|
||||
if (!icd->dev.parent ||
|
||||
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
|
||||
return -ENODEV;
|
||||
#if 0
|
||||
|
||||
if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
|
||||
ret = -ENODEV;
|
||||
goto sensor_video_probe_err;
|
||||
}
|
||||
|
||||
/* soft reset */
|
||||
ret = sensor_write(client, 0x001a, 0x0011);
|
||||
if (ret != 0)
|
||||
{
|
||||
#if (SENSOR_RESET_REG != SEQUENCE_END)
|
||||
ret = sensor_write(client, SENSOR_RESET_REG, SENSOR_RESET_VAL);
|
||||
if (ret != 0) {
|
||||
SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING());
|
||||
ret = -ENODEV;
|
||||
goto sensor_video_probe_err;
|
||||
goto sensor_INIT_ERR;
|
||||
}
|
||||
|
||||
mdelay(5); //delay 5 microseconds
|
||||
#endif
|
||||
|
||||
/* check if it is an sensor sensor */
|
||||
sensor_write(client, 0xFCFC, 0x7000);
|
||||
ret = sensor_read(client, 0x015a, &value);
|
||||
#if (SENSOR_ID_REG != SEQUENCE_END)
|
||||
ret = sensor_read(client, SENSOR_ID_REG, &pid);
|
||||
if (ret != 0) {
|
||||
SENSOR_TR("read chip id high byte failed\n");
|
||||
SENSOR_TR("read chip id failed\n");
|
||||
ret = -ENODEV;
|
||||
goto sensor_video_probe_err;
|
||||
}
|
||||
pid = value;
|
||||
SENSOR_DG("\n %s .. pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
|
||||
|
||||
SENSOR_DG("\n %s pid = 0x%x \n", SENSOR_NAME_STRING(), pid);
|
||||
#else
|
||||
pid = SENSOR_ID;
|
||||
#endif
|
||||
|
||||
if (pid == SENSOR_ID) {
|
||||
sensor->model = SENSOR_V4L2_IDENT;
|
||||
} else {
|
||||
@@ -6219,7 +6497,6 @@ static int sensor_video_probe(struct soc_camera_device *icd,
|
||||
ret = -ENODEV;
|
||||
goto sensor_video_probe_err;
|
||||
}
|
||||
#endif
|
||||
|
||||
icd->formats = sensor_colour_formats;
|
||||
icd->num_formats = ARRAY_SIZE(sensor_colour_formats);
|
||||
@@ -6227,21 +6504,31 @@ static int sensor_video_probe(struct soc_camera_device *icd,
|
||||
return 0;
|
||||
|
||||
sensor_video_probe_err:
|
||||
|
||||
return ret;
|
||||
}
|
||||
static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
{
|
||||
struct i2c_client *client = sd->priv;
|
||||
struct sensor *sensor = to_sensor(client);
|
||||
|
||||
SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
|
||||
switch (cmd)
|
||||
{
|
||||
case RK29_CAM_SUBDEV_DEACTIVATE:
|
||||
{
|
||||
sensor_deactivate(sd);
|
||||
sensor_deactivate(client);
|
||||
break;
|
||||
}
|
||||
case RK29_CAM_SUBDEV_IOREQUEST:
|
||||
{
|
||||
sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -6261,6 +6548,7 @@ static struct v4l2_subdev_video_ops sensor_subdev_video_ops = {
|
||||
.s_fmt = sensor_s_fmt,
|
||||
.g_fmt = sensor_g_fmt,
|
||||
.try_fmt = sensor_try_fmt,
|
||||
.s_stream = sensor_s_stream,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_ops sensor_subdev_ops = {
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
#ifndef __S5K6AA_H__
|
||||
#define __S5K6AA_H__
|
||||
|
||||
struct reginfo
|
||||
{
|
||||
u16 reg;
|
||||
u16 val;
|
||||
};
|
||||
|
||||
#define SEQUENCE_INIT 0x00
|
||||
#define SEQUENCE_NORMAL 0x01
|
||||
#define SEQUENCE_CAPTURE 0x02
|
||||
#define SEQUENCE_PREVIEW 0x03
|
||||
|
||||
#define SEQUENCE_PROPERTY 0xFFF9
|
||||
#define SEQUENCE_WAIT_MS 0xFFFA
|
||||
#define SEQUENCE_WAIT_US 0xFFFB
|
||||
#define SEQUENCE_WAIT_MS (0xFFFE)
|
||||
#define SEQUENCE_END (0xFFFF)
|
||||
#define SEQUENCE_FAST_SETMODE_START (0xFFFD)
|
||||
|
||||
Reference in New Issue
Block a user