Skip to content

Commit

Permalink
staging: Add WIP camera drivers for Surfae devices
Browse files Browse the repository at this point in the history
  • Loading branch information
qzed committed Sep 28, 2019
1 parent d13cc15 commit 36f3225
Show file tree
Hide file tree
Showing 8 changed files with 2,673 additions and 0 deletions.
40 changes: 40 additions & 0 deletions drivers/media/usb/uvc/uvc_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -2365,6 +2365,46 @@ static const struct uvc_device_info uvc_quirk_force_y8 = {
* though they are compliant.
*/
static const struct usb_device_id uvc_ids[] = {
/* Microsoft Surface Pro 3 Front */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x045e,
.idProduct = 0x07be,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 1 },
/* Microsoft Surface Pro 3 Rear */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x045e,
.idProduct = 0x07bf,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 1 },
/* Microsoft Surface Pro 4 Cam */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x045e,
.idProduct = 0x090c,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 1 },
/* Microsoft Surface Book Cam 1 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x045e,
.idProduct = 0x090b,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 1 },
/* Microsoft Surface Book Cam 2 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x045e,
.idProduct = 0x091a,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 1 },
/* LogiLink Wireless Webcam */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
Expand Down
1 change: 1 addition & 0 deletions drivers/staging/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/
obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/
obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
obj-$(CONFIG_EROFS_FS) += erofs/
obj-$(CONFIG_VIDEO_OV5693) += ov5693/
10 changes: 10 additions & 0 deletions drivers/staging/ov5693/Kconfig
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.
5 changes: 5 additions & 0 deletions drivers/staging/ov5693/Makefile
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
218 changes: 218 additions & 0 deletions drivers/staging/ov5693/ad5823.c
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;
}
90 changes: 90 additions & 0 deletions drivers/staging/ov5693/ad5823.h
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
Loading

0 comments on commit 36f3225

Please sign in to comment.