forked from linux-surface/kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
staging: Add WIP camera drivers for Surfae devices
- Loading branch information
Showing
8 changed files
with
2,673 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
config VIDEO_OV5693 | ||
tristate "Omnivision ov5693 sensor support" | ||
depends on I2C && VIDEO_V4L2 | ||
---help--- | ||
This is a Video4Linux2 sensor-level driver for the Micron | ||
ov5693 5 Mpixel camera. | ||
|
||
ov5693 is video camera sensor. | ||
|
||
It currently only works with the atomisp driver. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
obj-$(CONFIG_VIDEO_OV5693) += ov569x.o | ||
|
||
ov569x-objs := ov5693.o ad5823.o | ||
|
||
ccflags-y += -Werror |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
#include <asm/intel-mid.h> | ||
#include <linux/bitops.h> | ||
#include <linux/device.h> | ||
#include <linux/delay.h> | ||
#include <linux/errno.h> | ||
#include <linux/fs.h> | ||
#include <linux/gpio.h> | ||
#include <linux/init.h> | ||
#include <linux/i2c.h> | ||
#include <linux/io.h> | ||
#include <linux/kernel.h> | ||
#include <linux/kmod.h> | ||
#include <linux/mm.h> | ||
#include <linux/module.h> | ||
#include <linux/moduleparam.h> | ||
#include <linux/string.h> | ||
#include <linux/slab.h> | ||
#include <linux/types.h> | ||
#include <media/v4l2-chip-ident.h> | ||
#include <media/v4l2-device.h> | ||
|
||
#include "ad5823.h" | ||
|
||
static struct ad5823_device ad5823_dev; | ||
static int ad5823_i2c_write(struct i2c_client *client, u8 reg, u8 val) | ||
{ | ||
struct i2c_msg msg; | ||
u8 buf[2]; | ||
buf[0] = reg; | ||
buf[1] = val; | ||
msg.addr = AD5823_VCM_ADDR; | ||
msg.flags = 0; | ||
msg.len = AD5823_8BIT; | ||
msg.buf = &buf[0]; | ||
|
||
if (i2c_transfer(client->adapter, &msg, 1) != 1) | ||
return -EIO; | ||
return 0; | ||
} | ||
|
||
static int ad5823_i2c_read(struct i2c_client *client, u8 reg, u8 *val) | ||
{ | ||
struct i2c_msg msg[2]; | ||
u8 buf[2]; | ||
buf[0] = reg; | ||
buf[1] = 0; | ||
|
||
msg[0].addr = AD5823_VCM_ADDR; | ||
msg[0].flags = 0; | ||
msg[0].len = AD5823_8BIT; | ||
msg[0].buf = &buf[0]; | ||
|
||
msg[1].addr = AD5823_VCM_ADDR; | ||
msg[1].flags = I2C_M_RD; | ||
msg[1].len = AD5823_8BIT; | ||
msg[1].buf = &buf[1]; | ||
*val = 0; | ||
if (i2c_transfer(client->adapter, msg, 2) != 2) | ||
return -EIO; | ||
*val = buf[1]; | ||
return 0; | ||
} | ||
|
||
int ad5823_vcm_power_up(struct v4l2_subdev *sd) | ||
{ | ||
int ret = -ENODEV; | ||
|
||
/* Enable power */ | ||
if (ad5823_dev.platform_data) | ||
ret = ad5823_dev.platform_data->power_ctrl(sd, 1); | ||
/* | ||
* waiting time requested by AD5823(vcm) | ||
*/ | ||
usleep_range(1000, 2000); | ||
return ret; | ||
} | ||
|
||
int ad5823_vcm_power_down(struct v4l2_subdev *sd) | ||
{ | ||
int ret = -ENODEV; | ||
|
||
if (ad5823_dev.platform_data) | ||
ret = ad5823_dev.platform_data->power_ctrl(sd, 0); | ||
|
||
return ret; | ||
} | ||
|
||
|
||
int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val) | ||
{ | ||
struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
int ret = -EINVAL; | ||
u8 vcm_code; | ||
u8 vcm_mode_reg_val[4] = { | ||
AD5823_ARC_RES0, | ||
AD5823_ARC_RES1, | ||
AD5823_ARC_RES2, | ||
AD5823_ESRC | ||
}; | ||
|
||
if (ad5823_dev.vcm_mode != AD5823_DIRECT) { | ||
ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, | ||
AD5823_RING_CTRL_ENABLE); | ||
if (ret) | ||
return ret; | ||
|
||
ret = ad5823_i2c_write(client, AD5823_REG_MODE, | ||
vcm_mode_reg_val[ad5823_dev.vcm_mode]); | ||
if (ret) | ||
return ret; | ||
} else { | ||
ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, | ||
AD5823_RING_CTRL_DISABLE); | ||
if (ret) | ||
return ret; | ||
} | ||
|
||
ret = ad5823_i2c_read(client, AD5823_REG_VCM_CODE_MSB, &vcm_code); | ||
if (ret) | ||
return ret; | ||
|
||
/* set reg VCM_CODE_MSB Bit[1:0] */ | ||
vcm_code = (vcm_code & VCM_CODE_MSB_MASK) | ((val >> 8) & ~VCM_CODE_MSB_MASK); | ||
ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, vcm_code); | ||
if (ret) | ||
return ret; | ||
|
||
/* set reg VCM_CODE_LSB Bit[7:0] */ | ||
ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_LSB, | ||
(val & 0x0f)); | ||
if (ret) | ||
return ret; | ||
|
||
/* set required vcm move time */ | ||
vcm_code = AD5823_RESONANCE_PERIOD / AD5823_RESONANCE_COEF | ||
- AD5823_HIGH_FREQ_RANGE; | ||
ret = ad5823_i2c_write(client, AD5823_REG_VCM_MOVE_TIME, vcm_code); | ||
|
||
return ret; | ||
} | ||
|
||
int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value) | ||
{ | ||
int ret; | ||
|
||
value = min(value, AD5823_MAX_FOCUS_POS); | ||
ret = ad5823_t_focus_vcm(sd, AD5823_MAX_FOCUS_POS - value); | ||
if (ret == 0) { | ||
ad5823_dev.number_of_steps = value - ad5823_dev.focus; | ||
ad5823_dev.focus = value; | ||
ktime_get_ts(&ad5823_dev.timestamp_t_focus_abs); | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
int ad5823_t_focus_rel(struct v4l2_subdev *sd, s32 value) | ||
{ | ||
return ad5823_t_focus_abs(sd, ad5823_dev.focus + value); | ||
} | ||
|
||
int ad5823_q_focus_status(struct v4l2_subdev *sd, s32 *value) | ||
{ | ||
u32 status = 0; | ||
struct timespec temptime; | ||
const struct timespec timedelay = { | ||
0, | ||
min_t(u32, abs(ad5823_dev.number_of_steps)*DELAY_PER_STEP_NS, | ||
DELAY_MAX_PER_STEP_NS), | ||
}; | ||
|
||
ktime_get_ts(&temptime); | ||
|
||
temptime = timespec_sub(temptime, (ad5823_dev.timestamp_t_focus_abs)); | ||
|
||
if (timespec_compare(&temptime, &timedelay) <= 0) | ||
status = ATOMISP_FOCUS_STATUS_MOVING | ||
| ATOMISP_FOCUS_HP_IN_PROGRESS; | ||
else | ||
status = ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE | ||
| ATOMISP_FOCUS_HP_COMPLETE; | ||
|
||
*value = status; | ||
|
||
return 0; | ||
} | ||
|
||
int ad5823_q_focus_abs(struct v4l2_subdev *sd, s32 *value) | ||
{ | ||
s32 val; | ||
|
||
ad5823_q_focus_status(sd, &val); | ||
|
||
if (val & ATOMISP_FOCUS_STATUS_MOVING) | ||
*value = ad5823_dev.focus - ad5823_dev.number_of_steps; | ||
else | ||
*value = ad5823_dev.focus ; | ||
|
||
return 0; | ||
} | ||
|
||
int ad5823_t_vcm_slew(struct v4l2_subdev *sd, s32 value) | ||
{ | ||
return 0; | ||
} | ||
|
||
int ad5823_t_vcm_timing(struct v4l2_subdev *sd, s32 value) | ||
{ | ||
return 0; | ||
} | ||
|
||
int ad5823_vcm_init(struct v4l2_subdev *sd) | ||
{ | ||
/* set vcm mode to ARC RES0.5 */ | ||
ad5823_dev.vcm_mode = AD5823_ARC_RES1; | ||
ad5823_dev.platform_data = camera_get_af_platform_data(); | ||
return ad5823_dev.platform_data ? 0 : -ENODEV; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* Support for AD5823 VCM. | ||
* | ||
* Copyright (c) 2013 Intel Corporation. All Rights Reserved. | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License version | ||
* 2 as published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
* 02110-1301, USA. | ||
* | ||
*/ | ||
|
||
#ifndef __AD5823_H__ | ||
#define __AD5823_H__ | ||
|
||
#include <linux/atomisp_platform.h> | ||
#include <linux/types.h> | ||
|
||
|
||
#define AD5823_VCM_ADDR 0x0c | ||
|
||
#define AD5823_REG_RESET 0x01 | ||
#define AD5823_REG_MODE 0x02 | ||
#define AD5823_REG_VCM_MOVE_TIME 0x03 | ||
#define AD5823_REG_VCM_CODE_MSB 0x04 | ||
#define AD5823_REG_VCM_CODE_LSB 0x05 | ||
#define AD5823_REG_VCM_THRESHOLD_MSB 0x06 | ||
#define AD5823_REG_VCM_THRESHOLD_LSB 0x07 | ||
|
||
#define AD5823_RING_CTRL_ENABLE 0x04 | ||
#define AD5823_RING_CTRL_DISABLE 0x00 | ||
|
||
#define AD5823_RESONANCE_PERIOD 100000 | ||
#define AD5823_RESONANCE_COEF 512 | ||
#define AD5823_HIGH_FREQ_RANGE 0x80 | ||
|
||
#define VCM_CODE_MSB_MASK 0xfc | ||
|
||
enum ad5823_tok_type { | ||
AD5823_8BIT = 0x0001, | ||
AD5823_16BIT = 0x0002, | ||
}; | ||
|
||
enum ad5823_vcm_mode { | ||
AD5823_ARC_RES0 = 0x0, /* Actuator response control RES1 */ | ||
AD5823_ARC_RES1 = 0x1, /* Actuator response control RES0.5 */ | ||
AD5823_ARC_RES2 = 0x2, /* Actuator response control RES2 */ | ||
AD5823_ESRC = 0x3, /* Enhanced slew rate control */ | ||
AD5823_DIRECT = 0x4, /* Direct control */ | ||
}; | ||
|
||
/* ad5823 device structure */ | ||
struct ad5823_device { | ||
struct timespec timestamp_t_focus_abs; | ||
enum ad5823_vcm_mode vcm_mode; | ||
s16 number_of_steps; | ||
bool initialized; /* true if ad5823 is detected */ | ||
s32 focus; /* Current focus value */ | ||
struct timespec focus_time; /* Time when focus was last time set */ | ||
__u8 buffer[4]; /* Used for i2c transactions */ | ||
const struct camera_af_platform_data *platform_data; | ||
}; | ||
|
||
#define AD5823_INVALID_CONFIG 0xffffffff | ||
#define AD5823_MAX_FOCUS_POS 1023 | ||
|
||
|
||
#define DELAY_PER_STEP_NS 1000000 | ||
#define DELAY_MAX_PER_STEP_NS (1000000 * 1023) | ||
|
||
int ad5823_vcm_power_up(struct v4l2_subdev *sd); | ||
int ad5823_vcm_power_down(struct v4l2_subdev *sd); | ||
int ad5823_vcm_init(struct v4l2_subdev *sd); | ||
|
||
int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val); | ||
int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value); | ||
int ad5823_t_focus_rel(struct v4l2_subdev *sd, s32 value); | ||
int ad5823_q_focus_status(struct v4l2_subdev *sd, s32 *value); | ||
int ad5823_q_focus_abs(struct v4l2_subdev *sd, s32 *value); | ||
|
||
#endif |
Oops, something went wrong.