diff options
author | garyz <garyz@nvidia.com> | 2011-06-14 13:21:03 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:48:01 -0800 |
commit | ed9ecc5b6025a16cf28ac5488be2683149c712ec (patch) | |
tree | ceb569b2bd567cc08d9d0e90958c04e66c61b4b3 | |
parent | 353a6106f0e3b9c8d7a8585495f3bb02c3974372 (diff) |
ARM: Tegra: Sh532u: enable focuser attached to right camera
The sh532u focuser is enabled to pair with the stereo right camera
with the required power control configurations.
Bug 827897
Original-Change-Id: Icc21bcd2327671da193a8b8f24c338b0b2f6729c
Reviewed-on: http://git-master/r/36571
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>
Rebase-Id: R5c6dcd9b9c2bc7ab89870ee13da408ee0a392276
-rw-r--r-- | drivers/media/video/tegra/ov5650.c | 350 | ||||
-rw-r--r-- | drivers/media/video/tegra/sh532u.c | 463 | ||||
-rw-r--r-- | include/media/ov5650.h | 1 | ||||
-rw-r--r-- | include/media/sh532u.h | 1 | ||||
-rw-r--r-- | include/media/tegra_camera.h | 14 |
5 files changed, 527 insertions, 302 deletions
diff --git a/drivers/media/video/tegra/ov5650.c b/drivers/media/video/tegra/ov5650.c index 9f329d375f26..e8d00a5f830a 100644 --- a/drivers/media/video/tegra/ov5650.c +++ b/drivers/media/video/tegra/ov5650.c @@ -20,25 +20,13 @@ #include <linux/slab.h> #include <linux/uaccess.h> #include <media/ov5650.h> +#include <media/tegra_camera.h> struct ov5650_reg { u16 addr; u16 val; }; -enum StereoCameraMode{ - /* Sets the default camera to Main */ - Main, - /* Sets the stereo camera to stereo mode. */ - Stereo, - /* Only the sensor on the left is on. */ - LeftOnly, - /* Only the sensor on the right is on. */ - RightOnly, - /* Ignore -- Forces compilers to make 32-bit enums. */ - StereoCameraMode_Force32 = 0x7FFFFFFF -}; - struct ov5650_sensor { struct i2c_client *i2c_client; struct ov5650_platform_data *pdata; @@ -51,7 +39,7 @@ struct ov5650_info { struct ov5650_sensor right; }; -static struct ov5650_info *info; +static struct ov5650_info *stereo_ov5650_info; #define OV5650_TABLE_WAIT_MS 0 #define OV5650_TABLE_END 1 @@ -253,92 +241,104 @@ static struct ov5650_reg mode_1296x972[] = { }; static struct ov5650_reg mode_2080x1164[] = { - {0x3103, 0x93}, // power up system clock from PLL page 77 - {0x3007, 0x3b}, // clock enable03 pg 98 - {0x3017, 0xff}, // PAD output enable page 100 - {0x3018, 0xfc}, // PAD output enable page 100 - - {0x3600, 0x54}, // analog pg 108 - {0x3601, 0x05}, // analog pg 108 - {0x3603, 0xa7}, // analog pg 108 - {0x3604, 0x40}, // analog pg 108 - {0x3605, 0x04}, // analog pg 108 - {0x3606, 0x3f}, // analog pg 108 - {0x3612, 0x1a}, // analog pg 108 - {0x3613, 0x44}, // analog pg 108 - {0x3615, 0x52}, // analog pg 108 - {0x3620, 0x56}, // analog pg 108 - {0x3623, 0x01}, // analog pg 108 - {0x3630, 0x22}, // analog pg 108 - {0x3631, 0x36}, // analog pg 108 - {0x3632, 0x5f}, // analog pg 108 - {0x3633, 0x24}, // analog pg 108 - - {0x3702, 0x3a}, // analog pg 108 - {0x3704, 0x18}, // analog pg 108 - {0x3706, 0x41}, // analog pg 108 - {0x370b, 0x40}, // analog pg 108 - {0x370e, 0x00}, // analog pg 108 - {0x3710, 0x28}, // analog pg 108 + {0x3103, 0x93}, /* power up system clock from PLL page 77 */ + {0x3007, 0x3b}, /* clock enable03 pg 98 */ + {0x3017, 0xff}, /* PAD output enable page 100 */ + {0x3018, 0xfc}, /* PAD output enable page 100 */ + + {0x3600, 0x54}, /* analog pg 108 */ + {0x3601, 0x05}, /* analog pg 108 */ + {0x3603, 0xa7}, /* analog pg 108 */ + {0x3604, 0x40}, /* analog pg 108 */ + {0x3605, 0x04}, /* analog pg 108 */ + {0x3606, 0x3f}, /* analog pg 108 */ + {0x3612, 0x1a}, /* analog pg 108 */ + {0x3613, 0x44}, /* analog pg 108 */ + {0x3615, 0x52}, /* analog pg 108 */ + {0x3620, 0x56}, /* analog pg 108 */ + {0x3623, 0x01}, /* analog pg 108 */ + {0x3630, 0x22}, /* analog pg 108 */ + {0x3631, 0x36}, /* analog pg 108 */ + {0x3632, 0x5f}, /* analog pg 108 */ + {0x3633, 0x24}, /* analog pg 108 */ + + {0x3702, 0x3a}, /* analog pg 108 */ + {0x3704, 0x18}, /* analog pg 108 */ + {0x3706, 0x41}, /* analog pg 108 */ + {0x370b, 0x40}, /* analog pg 108 */ + {0x370e, 0x00}, /* analog pg 108 */ + {0x3710, 0x28}, /* analog pg 108 */ {0x3711, 0x24}, - {0x3712, 0x13}, // analog pg 108 - - {0x3810, 0x00}, // TIMING HVOFFS both are zero pg 80 - {0x3815, 0x82}, // PCLK to SCLK ratio bit[4:0] is set to 2 pg 81 - {0x3830, 0x50}, // manual exposure gain bit [0] - {0x3836, 0x00}, // TIMING HVPAD both are zero pg 82 - - {0x3a1a, 0x06}, // DIFF MAX an AEC register??? pg 114 - {0x3a18, 0x00}, // AEC gain ceiling bit 8 pg 114 - {0x3a19, 0xf8}, // AEC gain ceiling pg 114 - {0x3a00, 0x38}, // AEC control 0 debug mode band low limit mode band func pg 112 - {0x3a0d, 0x06}, // b60 max pg 113 - {0x3c01, 0x34}, // 5060HZ_CTRL01 pg 116 - - {0x401f, 0x03}, // BLC enabled pg 120 - {0x4000, 0x05}, // BLC enabled pg 120 - {0x401d, 0x08}, // reserved pg 120 - {0x4001, 0x02}, // BLC control pg 120 - - {0x5000, 0x00}, // ISP control00 features are disabled. pg 132 - {0x5001, 0x00}, // ISP control01 awb disabled. pg 132 - {0x5002, 0x00}, // ISP control02 debug mode disabled pg 132 - {0x503d, 0x00}, // ISP control3D features disabled pg 133 - {0x5046, 0x00}, // ISP control isp disable awbg disable pg 133 - - {0x300f, 0x8f}, // PLL control00 R_SELD5 [7:6] div by 4 R_DIVL [2] two lane div 1 SELD2P5 [1:0] div 2.5 pg 99 - {0x3010, 0x10}, // PLL control01 DIVM [3:0] DIVS [7:4] div 1 pg 99 - {0x3011, 0x14}, // PLL control02 R_DIVP [5:0] div 20 pg 99 - {0x3012, 0x02}, // PLL CTR 03, default - {0x3503, 0x33}, // AEC auto AGC auto gain has delay of 2 frames. pg 38 - - {0x3621, 0x2f}, // analog horizontal binning/sampling not enabled. pg 108 - {0x3703, 0xe6}, // analog pg 108 - {0x370c, 0x00}, // analog pg 108 - {0x370d, 0x04}, // analog pg 108 - {0x3713, 0x22}, // analog pg 108 + {0x3712, 0x13}, /* analog pg 108 */ + + {0x3810, 0x00}, /* TIMING HVOFFS both are zero pg 80 */ + {0x3815, 0x82}, /* PCLK to SCLK ratio bit[4:0] is set to 2 pg 81 */ + {0x3830, 0x50}, /* manual exposure gain bit [0] */ + {0x3836, 0x00}, /* TIMING HVPAD both are zero pg 82 */ + + {0x3a1a, 0x06}, /* DIFF MAX an AEC register??? pg 114 */ + {0x3a18, 0x00}, /* AEC gain ceiling bit 8 pg 114 */ + {0x3a19, 0xf8}, /* AEC gain ceiling pg 114 */ + {0x3a00, 0x38}, /* AEC control 0 debug mode band + low limit mode band func pg 112 */ + {0x3a0d, 0x06}, /* b60 max pg 113 */ + {0x3c01, 0x34}, /* 5060HZ_CTRL01 pg 116 */ + + {0x401f, 0x03}, /* BLC enabled pg 120 */ + {0x4000, 0x05}, /* BLC enabled pg 120 */ + {0x401d, 0x08}, /* reserved pg 120 */ + {0x4001, 0x02}, /* BLC control pg 120 */ + + {0x5000, 0x00}, /* ISP control00 features are disabled. pg 132 */ + {0x5001, 0x00}, /* ISP control01 awb disabled. pg 132 */ + {0x5002, 0x00}, /* ISP control02 debug mode disabled pg 132 */ + {0x503d, 0x00}, /* ISP control3D features disabled pg 133 */ + {0x5046, 0x00}, /* ISP control isp disable awbg disable pg 133 */ + + {0x300f, 0x8f}, /* PLL control00 R_SELD5 [7:6] div by 4 R_DIVL [2] + two lane div 1 SELD2P5 [1:0] div 2.5 pg 99 */ + {0x3010, 0x10}, /* PLL control01 DIVM [3:0] DIVS [7:4] div 1 pg 99 */ + {0x3011, 0x14}, /* PLL control02 R_DIVP [5:0] div 20 pg 99 */ + {0x3012, 0x02}, /* PLL CTR 03, default */ + {0x3503, 0x33}, /* AEC auto AGC auto gain has delay of 2 frames. + pg 38 */ + + {0x3621, 0x2f}, /* analog horizontal binning/sampling not enabled. + pg 108 */ + {0x3703, 0xe6}, /* analog pg 108 */ + {0x370c, 0x00}, /* analog pg 108 */ + {0x370d, 0x04}, /* analog pg 108 */ + {0x3713, 0x22}, /* analog pg 108 */ {0x3714, 0x27}, {0x3705, 0xda}, {0x370a, 0x80}, - {0x3800, 0x02}, // HREF start point higher 4 bits [3:0] pg 108 - {0x3801, 0x12}, // HREF start point lower 8 bits [7:0] pg 108 - {0x3802, 0x00}, // VREF start point higher 4 bits [3:0] pg 108 - {0x3803, 0x0a}, // VREF start point [7:0] pg 108 - {0x3804, 0x08}, // HREF width higher 4 bits [3:0] pg 108 - {0x3805, 0x20}, // HREF width lower 8 bits [7:0] pg 108 - {0x3806, 0x04}, // VREF height higher 4 bits [3:0] pg 109 - {0x3807, 0x92}, // VREF height lower 8 bits [7:0] pg 109 - {0x3808, 0x08}, // DVP horizontal output size higher 4 bits [3:0] pg 109 - {0x3809, 0x20}, // DVP horizontal output size lower 8 bits [7:0] pg 109 - {0x380a, 0x04}, // DVP vertical output size higher 4 bits [3:0] pg 109 - {0x380b, 0x92}, // DVP vertical output size lower 8 bits [7:0] pg 109 - {0x380c, 0x0a}, // total horizontal size higher 5 bits [4:0] pg 109, line length - {0x380d, 0x96}, // total horizontal size lower 8 bits [7:0] pg 109, line length - {0x380e, 0x04}, // total vertical size higher 5 bits [4:0] pg 109, frame length - {0x380f, 0x9e}, // total vertical size lower 8 bits [7:0] pg 109, frame length - {0x3818, 0xc0}, // timing control reg18 mirror & dkhf pg 110 - {0x381a, 0x3c}, // HS mirror adjustment pg 110 + {0x3800, 0x02}, /* HREF start point higher 4 bits [3:0] pg 108 */ + {0x3801, 0x12}, /* HREF start point lower 8 bits [7:0] pg 108 */ + {0x3802, 0x00}, /* VREF start point higher 4 bits [3:0] pg 108 */ + {0x3803, 0x0a}, /* VREF start point [7:0] pg 108 */ + {0x3804, 0x08}, /* HREF width higher 4 bits [3:0] pg 108 */ + {0x3805, 0x20}, /* HREF width lower 8 bits [7:0] pg 108 */ + {0x3806, 0x04}, /* VREF height higher 4 bits [3:0] pg 109 */ + {0x3807, 0x92}, /* VREF height lower 8 bits [7:0] pg 109 */ + {0x3808, 0x08}, /* DVP horizontal output size higher 4 bits [3:0] + pg 109 */ + {0x3809, 0x20}, /* DVP horizontal output size lower 8 bits [7:0] + pg 109 */ + {0x380a, 0x04}, /* DVP vertical output size higher 4 bits [3:0] + pg 109 */ + {0x380b, 0x92}, /* DVP vertical output size lower 8 bits [7:0] + pg 109 */ + {0x380c, 0x0a}, /* total horizontal size higher 5 bits [4:0] pg 109, + line length */ + {0x380d, 0x96}, /* total horizontal size lower 8 bits [7:0] pg 109, + line length */ + {0x380e, 0x04}, /* total vertical size higher 5 bits [4:0] pg 109, + frame length */ + {0x380f, 0x9e}, /* total vertical size lower 8 bits [7:0] pg 109, + frame length */ + {0x3818, 0xc0}, /* timing control reg18 mirror & dkhf pg 110 */ + {0x381a, 0x3c}, /* HS mirror adjustment pg 110 */ {0x381c, 0x31}, {0x381d, 0x8e}, {0x381e, 0x04}, @@ -349,16 +349,16 @@ static struct ov5650_reg mode_2080x1164[] = { {0x3827, 0x0a}, {0x401c, 0x46}, - {0x3003, 0x03}, // reset MIPI and DVP pg 97 - {0x3500, 0x00}, // long exp 1/3 in unit of 1/16 line, pg 38 - {0x3501, 0x49}, // long exp 2/3 in unit of 1/16 line, pg 38 - {0x3502, 0xa0}, // long exp 3/3 in unit of 1/16 line, pg 38 - {0x350a, 0x00}, // gain output to sensor, pg 38 - {0x350b, 0x00}, // gain output to sensor, pg 38 - {0x4801, 0x0f}, // MIPI control01 pg 125 - {0x300e, 0x0c}, // SC_MIPI_SC_CTRL0 pg 73 - {0x4803, 0x50}, // MIPI CTRL3 pg 91 - {0x4800, 0x34}, // MIPI CTRl0 idle and short line pg 89 + {0x3003, 0x03}, /* reset MIPI and DVP pg 97 */ + {0x3500, 0x00}, /* long exp 1/3 in unit of 1/16 line, pg 38 */ + {0x3501, 0x49}, /* long exp 2/3 in unit of 1/16 line, pg 38 */ + {0x3502, 0xa0}, /* long exp 3/3 in unit of 1/16 line, pg 38 */ + {0x350a, 0x00}, /* gain output to sensor, pg 38 */ + {0x350b, 0x00}, /* gain output to sensor, pg 38 */ + {0x4801, 0x0f}, /* MIPI control01 pg 125 */ + {0x300e, 0x0c}, /* SC_MIPI_SC_CTRL0 pg 73 */ + {0x4803, 0x50}, /* MIPI CTRL3 pg 91 */ + {0x4800, 0x34}, /* MIPI CTRl0 idle and short line pg 89 */ {OV5650_TABLE_END, 0x0000} }; @@ -489,7 +489,7 @@ static inline void ov5650_get_frame_length_regs(struct ov5650_reg *regs, /* 3 regs to program coarse time */ static inline void ov5650_get_coarse_time_regs(struct ov5650_reg *regs, - u32 coarse_time) + u32 coarse_time) { regs->addr = 0x3500; regs->val = (coarse_time >> 12) & 0xff; @@ -544,16 +544,16 @@ static int ov5650_write_reg_helper(struct ov5650_info *info, int ret; switch (info->camera_mode) { case Main: - case LeftOnly: + case StereoCameraMode_Left: ret = ov5650_write_reg(info->left.i2c_client, addr, val); break; - case Stereo: + case StereoCameraMode_Stereo: ret = ov5650_write_reg(info->left.i2c_client, addr, val); if (ret) break; ret = ov5650_write_reg(info->right.i2c_client, addr, val); break; - case RightOnly: + case StereoCameraMode_Right: ret = ov5650_write_reg(info->right.i2c_client, addr, val); break; default: @@ -720,49 +720,29 @@ static int ov5650_test_pattern(struct ov5650_info *info, NULL, 0); } +static int set_power_helper(struct ov5650_platform_data *pdata, + int powerLevel) +{ + if (pdata) { + if (powerLevel && pdata->power_on) + pdata->power_on(); + else if (pdata->power_off) + pdata->power_off(); + } + return 0; +} + static int ov5650_set_power(int powerLevel) { pr_info("%s: powerLevel=%d camera mode=%d\n", __func__, powerLevel, - info->camera_mode); + stereo_ov5650_info->camera_mode); - switch (info->camera_mode) { - case Main: - case LeftOnly: - if (info->left.pdata) { - if (powerLevel && info->left.pdata->power_on) - info->left.pdata->power_on(); - else if (info->left.pdata->power_off) - info->left.pdata->power_off(); - } - break; - - case Stereo: - if (info->left.pdata) { - if (powerLevel && info->left.pdata->power_on) - info->left.pdata->power_on(); - else if (info->left.pdata->power_off) - info->left.pdata->power_off(); - } - if (info->right.pdata) { - if (powerLevel && info->right.pdata->power_on) - info->right.pdata->power_on(); - else if (info->right.pdata->power_off) - info->right.pdata->power_off(); - } - break; + if (StereoCameraMode_Left & stereo_ov5650_info->camera_mode) + set_power_helper(stereo_ov5650_info->left.pdata, powerLevel); - case RightOnly: - if (info->right.pdata) { - if (powerLevel && info->right.pdata->power_on) - info->right.pdata->power_on(); - else if (info->right.pdata->power_off) - info->right.pdata->power_off(); - } - break; + if (StereoCameraMode_Right & stereo_ov5650_info->camera_mode) + set_power_helper(stereo_ov5650_info->right.pdata, powerLevel); - default: - return -1; - } return 0; } @@ -836,7 +816,7 @@ static long ov5650_ioctl(struct file *file, static int ov5650_open(struct inode *inode, struct file *file) { pr_info("%s\n", __func__); - file->private_data = info; + file->private_data = stereo_ov5650_info; ov5650_set_power(1); return 0; } @@ -862,37 +842,63 @@ static struct miscdevice ov5650_device = { .fops = &ov5650_fileops, }; -static int left_ov5650_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ov5650_probe_common(void) { int err; - pr_info("%s: probing sensor.\n", __func__); - if (!info) { - info = kzalloc(sizeof(struct ov5650_info), GFP_KERNEL); - if (!info) { + if (!stereo_ov5650_info) { + stereo_ov5650_info = kzalloc(sizeof(struct ov5650_info), + GFP_KERNEL); + if (!stereo_ov5650_info) { pr_err("ov5650: Unable to allocate memory!\n"); return -ENOMEM; } + + err = misc_register(&ov5650_device); + if (err) { + pr_err("ov5650: Unable to register misc device!\n"); + kfree(stereo_ov5650_info); + return err; + } } + return 0; +} + +static int ov5650_remove_common(struct i2c_client *client) +{ + if (stereo_ov5650_info->left.i2c_client || + stereo_ov5650_info->right.i2c_client) + return 0; + + misc_deregister(&ov5650_device); + kfree(stereo_ov5650_info); + stereo_ov5650_info = NULL; + + return 0; +} + +static int left_ov5650_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err; + pr_info("%s: probing sensor.\n", __func__); - err = misc_register(&ov5650_device); - if (err) { - pr_err("ov5650: Unable to register misc device!\n"); - kfree(info); + err = ov5650_probe_common(); + if (err) return err; - } - info->left.pdata = client->dev.platform_data; - info->left.i2c_client = client; + stereo_ov5650_info->left.pdata = client->dev.platform_data; + stereo_ov5650_info->left.i2c_client = client; return 0; } static int left_ov5650_remove(struct i2c_client *client) { - misc_deregister(&ov5650_device); - kfree(info); + if (stereo_ov5650_info) { + stereo_ov5650_info->left.i2c_client = NULL; + ov5650_remove_common(client); + } return 0; } @@ -917,23 +923,25 @@ static struct i2c_driver left_ov5650_i2c_driver = { static int right_ov5650_probe(struct i2c_client *client, const struct i2c_device_id *id) { + int err; pr_info("%s: probing sensor.\n", __func__); - if (!info) { - info = kzalloc(sizeof(struct ov5650_info), GFP_KERNEL); - if (!info) { - pr_err("ov5650_right: Unable to allocate memory!\n"); - return -ENOMEM; - } - } - info->right.pdata = client->dev.platform_data; - info->right.i2c_client = client; + err = ov5650_probe_common(); + if (err) + return err; + + stereo_ov5650_info->right.pdata = client->dev.platform_data; + stereo_ov5650_info->right.i2c_client = client; return 0; } static int right_ov5650_remove(struct i2c_client *client) { + if (stereo_ov5650_info) { + stereo_ov5650_info->right.i2c_client = NULL; + ov5650_remove_common(client); + } return 0; } diff --git a/drivers/media/video/tegra/sh532u.c b/drivers/media/video/tegra/sh532u.c index 7a707dff21e8..1ee2832cc49e 100644 --- a/drivers/media/video/tegra/sh532u.c +++ b/drivers/media/video/tegra/sh532u.c @@ -24,7 +24,9 @@ #include <linux/miscdevice.h> #include <linux/slab.h> #include <linux/uaccess.h> +#include <media/ov5650.h> #include <media/sh532u.h> +#include <media/tegra_camera.h> #include <asm/traps.h> @@ -34,18 +36,22 @@ #define FOCAL_LENGTH 0x408d70a4 /* (4.42f) */ #define FNUMBER 0x40333333 /* (2.8f) */ - -struct sh532u_info { +struct sh532u_sensor { struct i2c_client *i2c_client; struct sh532u_config config; - struct sh532u_platform_data sh532u_pdata; + struct sh532u_platform_data pdata; +}; + +struct sh532u_info { + enum StereoCameraMode camera_mode; + struct sh532u_sensor *left; + struct sh532u_sensor *right; }; -static struct sh532u_info *info; +static struct sh532u_info *stereo_sh532u_info; /* set to NULL by compiler */ -static int sh532u_read_u8(u8 dev, u8 addr, u8 *val) +static int sh532u_read_u8(struct i2c_client *client, u8 dev, u8 addr, u8 *val) { - struct i2c_client *client = info->i2c_client; struct i2c_msg msg[2]; unsigned char data[3]; @@ -73,9 +79,8 @@ static int sh532u_read_u8(u8 dev, u8 addr, u8 *val) return 0; } -static int sh532u_read_u16(u8 addr, u16 *val) +static int sh532u_read_u16(struct i2c_client *client, u8 addr, u16 *val) { - struct i2c_client *client = info->i2c_client; struct i2c_msg msg[2]; u8 buf[4]; @@ -98,9 +103,8 @@ static int sh532u_read_u16(u8 addr, u16 *val) return 0; } -static int eeprom_read_u32(u8 addr, u32 *val) +static int eeprom_read_u32(struct i2c_client *client, u8 addr, u32 *val) { - struct i2c_client *client = info->i2c_client; struct i2c_msg msg[2]; union { u8 dataU8[8]; @@ -127,9 +131,8 @@ static int eeprom_read_u32(u8 addr, u32 *val) return 0; } -static int sh532u_write_u8(u16 addr, u8 val) +static int sh532u_write_u8(struct i2c_client *client, u16 addr, u8 val) { - struct i2c_client *client = info->i2c_client; struct i2c_msg msg; unsigned char data[2]; @@ -143,13 +146,12 @@ static int sh532u_write_u8(u16 addr, u8 val) if (i2c_transfer(client->adapter, &msg, 1) != 1) return -1; - - return 0; + else + return 0; } -static int sh532u_write_u16(u16 addr, u16 val) +static int sh532u_write_u16(struct i2c_client *client, u16 addr, u16 val) { - struct i2c_client *client = info->i2c_client; struct i2c_msg msg; unsigned char data[3]; @@ -167,14 +169,14 @@ static int sh532u_write_u16(u16 addr, u16 val) return 0; } -static void move_driver(s16 tarPos) +static void move_driver(struct i2c_client *client, s16 tarPos) { s16 curPos, moveStep; u16 moveDistance; int err; /* Read Current Position */ - err = sh532u_read_u16(RZ_211H, &curPos); + err = sh532u_read_u16(client, RZ_211H, &curPos); if (err) goto move_driver_error; /* Check move distance to Target Position */ @@ -182,8 +184,9 @@ static void move_driver(s16 tarPos) /* if move distance is shorter than MS1Z12(=Step width) */ if (moveDistance <= STMV_SIZE) { - err = sh532u_write_u8(MSSET_211, (INI_MSSET_211 | 0x01)); - err = err | sh532u_write_u16(MS1Z22_211H, tarPos); + err = sh532u_write_u8(client, MSSET_211, + (INI_MSSET_211 | 0x01)); + err = err | sh532u_write_u16(client, MS1Z22_211H, tarPos); if (err) goto move_driver_error; } else { @@ -193,12 +196,11 @@ static void move_driver(s16 tarPos) moveStep = -STMV_SIZE; /* Set StepMove Target Positon */ - err = sh532u_write_u16(MS1Z12_211H, moveStep); - err = err | sh532u_write_u16(STMVENDH_211, tarPos); + err = sh532u_write_u16(client, MS1Z12_211H, moveStep); + err = err | sh532u_write_u16(client, STMVENDH_211, tarPos); /* Start StepMove */ err = err | - sh532u_write_u8( - STMVEN_211, + sh532u_write_u8(client, STMVEN_211, (STMCHTG_ON | STMSV_ON | STMLFF_OFF | STMVEN_ON)); if (err) goto move_driver_error; @@ -206,10 +208,10 @@ static void move_driver(s16 tarPos) return; move_driver_error: - pr_err("Focuser: %s failed!\n", __func__); + pr_err("sh532u: %s failed!\n", __func__); } -static void wait_for_move(void) +static void wait_for_move(struct i2c_client *client) { u16 usSmvFin; u8 moveTime, ucParMod, tmp; @@ -218,14 +220,15 @@ static void wait_for_move(void) moveTime = 0; do { mdelay(1); - err = sh532u_read_u8(0, STMVEN_211, &ucParMod); - err = err | sh532u_read_u16(RZ_211H, &usSmvFin); + err = sh532u_read_u8(client, 0, STMVEN_211, &ucParMod); + err = err | sh532u_read_u16(client, RZ_211H, &usSmvFin); if (err) goto wait_for_move_error; /* StepMove Error Handling, Unexpected Position */ if ((usSmvFin == 0x7FFF) || (usSmvFin == 0x8001)) { /* Stop StepMove Operation */ - err = sh532u_write_u8(STMVEN_211, ucParMod & 0xFE); + err = sh532u_write_u8(client, STMVEN_211, + ucParMod & 0xFE); if (err) goto wait_for_move_error; } @@ -239,7 +242,7 @@ static void wait_for_move(void) do { mdelay(1); moveTime++; - err = sh532u_read_u8(0, MSSET_211, &tmp); + err = sh532u_read_u8(client, 0, MSSET_211, &tmp); if (err) goto wait_for_move_error; } while ((tmp & CHTGST_ON) && (moveTime < 15)); @@ -247,17 +250,18 @@ static void wait_for_move(void) return; wait_for_move_error: - pr_err("Focuser: %s failed!\n", __func__); + pr_err("sh532u: %s failed!\n", __func__); } -static void lens_move_pulse(s16 position) +static void lens_move_pulse(struct i2c_client *client, s16 position) { - move_driver(position); - wait_for_move(); + move_driver(client, position); + wait_for_move(client); } -static void get_rom_info(void) +static void get_rom_info(struct sh532u_sensor *info) { + struct i2c_client *client = info->i2c_client; u8 tmp; int err; @@ -265,11 +269,11 @@ static void get_rom_info(void) Inf1 and Mac1 are the mechanical limit position. Inf1 : Bottom limit. Mac1 : Top limit. */ - err = sh532u_read_u8(0x50, addrMac1, &tmp); + err = sh532u_read_u8(client, 0x50, addrMac1, &tmp); if (err) goto get_rom_info_error; info->config.limit_low = (tmp<<8) & 0xff00; - err = sh532u_read_u8(0x50, addrInf1, &tmp); + err = sh532u_read_u8(client, 0x50, addrInf1, &tmp); if (err) goto get_rom_info_error; info->config.limit_high = (tmp<<8) & 0xff00; @@ -278,34 +282,35 @@ static void get_rom_info(void) Inf2 and Mac2 are the calibration data for SEMCO AF lens. Inf2: Best focus (lens position) when object distance is 1.2M. Mac2: Best focus (lens position) when object distance is 10cm. */ - err = sh532u_read_u8(0x50, addrMac2, &tmp); + err = sh532u_read_u8(client, 0x50, addrMac2, &tmp); if (err) goto get_rom_info_error; info->config.pos_low = (tmp << 8) & 0xff00; - err = sh532u_read_u8(0x50, addrInf2, &tmp); + err = sh532u_read_u8(client, 0x50, addrInf2, &tmp); if (err) goto get_rom_info_error; info->config.pos_high = (tmp << 8) & 0xff00; return; get_rom_info_error: - pr_err("Focuser: %s failed!\n", __func__); + pr_err("sh532u: %s failed!\n", __func__); info->config.limit_high = POS_HIGH; info->config.limit_low = POS_LOW; info->config.pos_high = POS_HIGH; info->config.pos_low = POS_LOW; } -static void init_hvca_pos(void) +static void init_hvca_pos(struct sh532u_sensor *info) { + struct i2c_client *client = info->i2c_client; short sBottomLimit, sTopLimit; - get_rom_info(); + get_rom_info(info); sBottomLimit = (((int)info->config.limit_low * 5) >> 3) & 0xFFC0; - lens_move_pulse(sBottomLimit); + lens_move_pulse(client, sBottomLimit); sTopLimit = (((int)info->config.limit_high * 5) >> 3) & 0xFFC0; - lens_move_pulse(sTopLimit); - lens_move_pulse(info->config.pos_high); + lens_move_pulse(client, sTopLimit); + lens_move_pulse(client, info->config.pos_high); } static unsigned int a2buf[] = { @@ -328,8 +333,10 @@ static unsigned int a2buf[] = { }; /* Write 1 byte data to the HVCA Drive IC by data type */ -static void sh532u_hvca_wr1(u8 ep_type, u8 ep_data1, u8 ep_addr) +static void sh532u_hvca_wr1(struct sh532u_sensor *info, + u8 ep_type, u8 ep_data1, u8 ep_addr) { + struct i2c_client *client = info->i2c_client; int err = 0; u8 us_data; @@ -339,20 +346,20 @@ static void sh532u_hvca_wr1(u8 ep_type, u8 ep_data1, u8 ep_addr) break; case INDIRECT_EEPROM: - err = sh532u_read_u8(0x50, ep_data1, &us_data); + err = sh532u_read_u8(client, 0x50, ep_data1, &us_data); break; case INDIRECT_HVCA: - err = sh532u_read_u8(0, (u16)ep_data1, &us_data); + err = sh532u_read_u8(client, 0, (u16)ep_data1, &us_data); break; case MASK_AND: - err = sh532u_read_u8(0, (u16)ep_addr, &us_data); + err = sh532u_read_u8(client, 0, (u16)ep_addr, &us_data); us_data = us_data & ep_data1; break; case MASK_OR: - err = sh532u_read_u8(0, (u16)ep_addr, &us_data); + err = sh532u_read_u8(client, 0, (u16)ep_addr, &us_data); us_data = us_data | ep_data1; break; @@ -360,14 +367,20 @@ static void sh532u_hvca_wr1(u8 ep_type, u8 ep_data1, u8 ep_addr) err = 1; } if (!err) - err = sh532u_write_u8((u16)ep_addr, us_data); + err = sh532u_write_u8(client, (u16)ep_addr, us_data); + + /* we output error message when there is I2C error, but we can't do + * anything about it nor recover from it. */ if (err) - pr_err("Focuser: Failed to init!\n"); + pr_err("sh532u: %s: Failed to init!: client=0x%x, ep_addr=0x%2x, us_data=0x%x, ret=%d\n", + __func__, (u32)client, (u32)ep_addr, (u32)us_data, err); } /* Write 2 byte data to the HVCA Drive IC by data type */ -static void sh532u_hvca_wr2(u8 ep_type, u8 ep_data1, u8 ep_data2, u8 ep_addr) +static void sh532u_hvca_wr2(struct sh532u_sensor *info, u8 ep_type, + u8 ep_data1, u8 ep_data2, u8 ep_addr) { + struct i2c_client *client = info->i2c_client; int err = 0; u8 uc_data1; u8 uc_data2; @@ -380,27 +393,29 @@ static void sh532u_hvca_wr2(u8 ep_type, u8 ep_data1, u8 ep_data2, u8 ep_addr) break; case INDIRECT_EEPROM: - err = sh532u_read_u8(0x50, (u16)ep_data1, &uc_data1); - err = err | sh532u_read_u8(0x50, (u16)ep_data2, &uc_data2); + err = sh532u_read_u8(client, 0x50, (u16)ep_data1, + &uc_data1); + err = err | sh532u_read_u8(client, 0x50, (u16)ep_data2, + &uc_data2); us_data = (((u16)uc_data1 << 8) & 0xFF00) | ((u16)uc_data2 & 0x00FF); break; case INDIRECT_HVCA: - err = sh532u_read_u8(0, (u16)ep_data1, &uc_data1); - err = err | sh532u_read_u8(0, (u16)ep_data2, &uc_data2); + err = sh532u_read_u8(client, 0, (u16)ep_data1, &uc_data1); + err = err | sh532u_read_u8(client, 0, (u16)ep_data2, &uc_data2); us_data = (((u16)uc_data1 << 8) & 0xFF00) | ((u16)uc_data2 & 0x00FF); break; case MASK_AND: - err = sh532u_read_u16((u16)ep_addr, &us_data); + err = sh532u_read_u16(client, (u16)ep_addr, &us_data); us_data = us_data & ((((u16)ep_data1 << 8) & 0xFF00) | ((u16)ep_data2 & 0x00FF)); break; case MASK_OR: - err = sh532u_read_u16((u16)ep_addr, &us_data); + err = sh532u_read_u16(client, (u16)ep_addr, &us_data); us_data = us_data | ((((u16)ep_data1 << 8) & 0xFF00) | ((u16)ep_data2 & 0x00FF)); break; @@ -409,23 +424,31 @@ static void sh532u_hvca_wr2(u8 ep_type, u8 ep_data1, u8 ep_data2, u8 ep_addr) err = 1; } if (!err) - err = sh532u_write_u16((u16)ep_addr, us_data); + err = sh532u_write_u16(client, (u16)ep_addr, us_data); + + /* we output error message when there is I2C error, but we can't do + * anything about it nor recover from it. */ if (err) - pr_err("Focuser: Failed to init!\n"); + pr_err("sh532u: %s: Failed to init!: client=0x%x, ep_addr=0x%2x, us_data=0x%x, ret=%d\n", + __func__, (u32)client, (u32)ep_addr, (u32)us_data, err); } -static void init_driver(void) +static void init_driver(struct sh532u_sensor *info) { int eeprom_addr; unsigned int eeprom_data = 0; u8 ep_addr, ep_type, ep_data1, ep_data2; + pr_info("sh532u: init_driver: i2c_client = 0x%x\n", + (u32)info->i2c_client); + for (eeprom_addr = 0x30; eeprom_addr <= 0x013C; eeprom_addr += 4) { if (eeprom_addr > 0xff) { /* use hardcoded data instead */ eeprom_data = a2buf[(eeprom_addr & 0xFF) / 4]; } else { - if (eeprom_read_u32(eeprom_addr & 0xFF, &eeprom_data)) + if (eeprom_read_u32(info->i2c_client, + eeprom_addr & 0xFF, &eeprom_data)) pr_info("sh532u: cannot read eeprom\n"); } @@ -442,9 +465,11 @@ static void init_driver(void) mdelay((unsigned int)((ep_data1 << 8) | ep_data2)); } else { if ((ep_type & 0x0F) == DATA_1BYTE) { - sh532u_hvca_wr1(ep_type, ep_data1, ep_addr); + sh532u_hvca_wr1(info, ep_type, ep_data1, + ep_addr); } else { - sh532u_hvca_wr2(ep_type, + sh532u_hvca_wr2(info, + ep_type, ep_data1, ep_data2, ep_addr); @@ -453,39 +478,40 @@ static void init_driver(void) } msleep(300); - init_hvca_pos(); + init_hvca_pos(info); } -static int sh532u_set_position(struct sh532u_info *info, s16 position) +static int sh532u_set_position(struct sh532u_sensor *info, s16 position) { if (position > info->config.limit_high) return -1; /* Caller's responsibility to check motor status. */ - move_driver(position); + move_driver(info->i2c_client, position); return 0; } -static int sh532u_get_move_status(unsigned long arg) +static int sh532u_get_move_status(struct sh532u_sensor *info, unsigned long arg) { + struct i2c_client *client = info->i2c_client; enum sh532u_move_status status = SH532U_Forced32; u8 ucTmp; u16 usSmvFin; - int err = sh532u_read_u8(0, STMVEN_211, &ucTmp) | - sh532u_read_u16(RZ_211H, &usSmvFin); + int err = sh532u_read_u8(client, 0, STMVEN_211, &ucTmp) | + sh532u_read_u16(client, RZ_211H, &usSmvFin); if (err) return err; /* StepMove Error Handling, Unexpected Position */ if ((usSmvFin == 0x7FFF) || (usSmvFin == 0x8001)) { /* Stop StepMove Operation */ - err = sh532u_write_u8(STMVEN_211, ucTmp & 0xFE); + err = sh532u_write_u8(client, STMVEN_211, ucTmp & 0xFE); if (err) return err; } if (ucTmp & STMVEN_ON) { - err = sh532u_read_u8(0, MSSET_211, &ucTmp); + err = sh532u_read_u8(client, 0, MSSET_211, &ucTmp); if (err) return err; if (ucTmp & CHTGST_ON) @@ -497,24 +523,24 @@ static int sh532u_get_move_status(unsigned long arg) if (copy_to_user((void __user *) arg, &status, sizeof(enum sh532u_move_status))) { - pr_info("Error in copying move status: %s: %d\n", __func__, __LINE__); + pr_info("Error in copying move status: %s: %d\n", + __func__, __LINE__); return -EFAULT; } return 0; } -static long sh532u_ioctl( - struct file *file, +static long sh532u_ioctl_helper( + struct sh532u_sensor *info, unsigned int cmd, unsigned long arg) { - struct sh532u_info *info = file->private_data; - switch (cmd) { case SH532U_IOCTL_GET_CONFIG: if (copy_to_user((void __user *) arg, &info->config, sizeof(info->config))) { - pr_err("Error in copying config: %s: %d\n", __func__, __LINE__); + pr_err("Error in copying config: %s: %d\n", + __func__, __LINE__); return -EFAULT; } return 0; @@ -523,31 +549,89 @@ static long sh532u_ioctl( return sh532u_set_position(info, (s16)(arg & 0xffff)); case SH532U_IOCTL_GET_MOVE_STATUS: - return sh532u_get_move_status(arg); + return sh532u_get_move_status(info, arg); default: return -EINVAL; } } +static long sh532u_ioctl( + struct file *file, + unsigned int cmd, + unsigned long arg) +{ + struct sh532u_info *stereo_info = file->private_data; + int ret; + + /* select a camera */ + if (cmd == SH532U_IOCTL_SET_CAMERA_MODE) { + stereo_info->camera_mode = arg; + return 0; + } + + if (StereoCameraMode_Left & stereo_info->camera_mode) { + ret = sh532u_ioctl_helper(stereo_info->left, cmd, arg); + if (ret) + return ret; + + if (StereoCameraMode_Stereo & stereo_info->camera_mode) { + /* To be finalized for stereo */ + if (cmd != SH532U_IOCTL_GET_CONFIG) + ret = sh532u_ioctl_helper(stereo_info->right, + cmd, arg); + } + return ret; + } + + if (StereoCameraMode_Right & stereo_info->camera_mode) + return sh532u_ioctl_helper(stereo_info->right, cmd, arg); + + return 0; +} + +static void sh532u_open_helper(struct sh532u_sensor *info) +{ + if (info->pdata.board_init) + info->pdata.board_init(info->pdata.context_data); + init_driver(info); +} + +static void sh532u_release_helper(struct sh532u_sensor *info) +{ + if (info->pdata.board_deinit) + info->pdata.board_deinit(info->pdata.context_data); +} static int sh532u_open(struct inode *inode, struct file *file) { - pr_info("sh532 open\n"); - file->private_data = info; - if (info->sh532u_pdata.board_init) - info->sh532u_pdata.board_init( - info->sh532u_pdata.context_data); - init_driver(); + pr_info("sh532u open: camera_mode: %2d\n", + stereo_sh532u_info->camera_mode); + + file->private_data = stereo_sh532u_info; + + if (StereoCameraMode_Left & stereo_sh532u_info->camera_mode) + sh532u_open_helper(stereo_sh532u_info->left); + + if (StereoCameraMode_Right & stereo_sh532u_info->camera_mode) + sh532u_open_helper(stereo_sh532u_info->right); + return 0; } int sh532u_release(struct inode *inode, struct file *file) { - pr_info("sh532 release\n"); - if (info->sh532u_pdata.board_deinit) - info->sh532u_pdata.board_deinit( - info->sh532u_pdata.context_data); + struct sh532u_info *info = file->private_data; + + pr_info("sh532u release: camera_mode: %2d\n", + info->camera_mode); + + if (StereoCameraMode_Left & info->camera_mode) + sh532u_release_helper(info->left); + + if (StereoCameraMode_Right & info->camera_mode) + sh532u_release_helper(info->right); + file->private_data = NULL; return 0; } @@ -566,75 +650,194 @@ static struct miscdevice sh532u_device = { .fops = &sh532u_fileops, }; -static int sh532u_probe( - struct i2c_client *client, - const struct i2c_device_id *id) +static int sh532u_probe_init(struct i2c_client *client, + struct sh532u_sensor **info) { - int err; - struct sh532u_platform_data *sh532u_pdata = client->dev.platform_data; - - pr_info("sh532u: probing sensor.\n"); - info = kzalloc(sizeof(struct sh532u_info), GFP_KERNEL); - if (!info) { - pr_err("sh532u: Unable to allocate memory!\n"); + struct sh532u_platform_data *pdata = client->dev.platform_data; + struct sh532u_sensor *p_info = + kzalloc(sizeof(struct sh532u_sensor), GFP_KERNEL); + if (!p_info) { + pr_err("%s\n", "sh532u_sensor: Unable to allocate memory!\n"); return -ENOMEM; } - err = misc_register(&sh532u_device); - if (err) { - pr_err("sh532u: Unable to register misc device!\n"); - kfree(info); - return err; + + p_info->i2c_client = client; + p_info->config.settle_time = SETTLETIME_MS; + p_info->config.focal_length = FOCAL_LENGTH; + p_info->config.fnumber = FNUMBER; + p_info->config.pos_low = POS_LOW; + p_info->config.pos_high = POS_HIGH; + i2c_set_clientdata(client, p_info); + + if (pdata) { + p_info->pdata.context_data = pdata->context_data; + p_info->pdata.board_init = pdata->board_init; + p_info->pdata.board_deinit = pdata->board_deinit; } - info->i2c_client = client; - info->config.settle_time = SETTLETIME_MS; - info->config.focal_length = FOCAL_LENGTH; - info->config.fnumber = FNUMBER; - info->config.pos_low = POS_LOW; - info->config.pos_high = POS_HIGH; - i2c_set_clientdata(client, info); - if (sh532u_pdata) { - info->sh532u_pdata.context_data = sh532u_pdata->context_data; - info->sh532u_pdata.board_init = sh532u_pdata->board_init; - info->sh532u_pdata.board_deinit = sh532u_pdata->board_deinit; + *info = p_info; + return 0; +} + +static int sh532u_probe_helper(struct i2c_client *client) +{ + struct sh532u_platform_data *pdata = client->dev.platform_data; + int err; + + if (!stereo_sh532u_info) { + stereo_sh532u_info = kzalloc(sizeof(struct sh532u_info), + GFP_KERNEL); + if (!stereo_sh532u_info) { + pr_err("%s\n", + "sh532u_info: Unable to allocate memory!\n"); + return -ENOMEM; + } + + err = misc_register(&sh532u_device); + if (err) { + pr_err("sh532u: Unable to register sh532u device!\n"); + kfree(stereo_sh532u_info); + stereo_sh532u_info = NULL; + return err; + } + + err = sh532u_probe_init(client, &stereo_sh532u_info->left); + if (err) { + kfree(stereo_sh532u_info); + stereo_sh532u_info = NULL; + return -ENOMEM; + } + + err = sh532u_probe_init(client, &stereo_sh532u_info->right); + if (err) { + kfree(stereo_sh532u_info); + stereo_sh532u_info = NULL; + kfree(stereo_sh532u_info->left); + return -ENOMEM; + } + stereo_sh532u_info->camera_mode = StereoCameraMode_Left; } + return 0; } -static int sh532u_remove(struct i2c_client *client) +static int left_sh532u_probe( + struct i2c_client *client, + const struct i2c_device_id *id) { - struct sh532u_info *info; - info = i2c_get_clientdata(client); - misc_deregister(&sh532u_device); - kfree(info); + int err ; + + pr_info("left_sh532u: probing sensor: i2c_client=0x%x\n", (u32)client); + + err = sh532u_probe_helper(client); + + return err; +} + +static int left_sh532u_remove(struct i2c_client *client) +{ + pr_info("left_sh532u to be removed\n"); + if (!stereo_sh532u_info || !client) { + pr_info("left_sh532u_remove(): NULL pointers\n"); + return 0; + } + + kfree(stereo_sh532u_info->left); + stereo_sh532u_info->left = NULL; + + if (!stereo_sh532u_info->right) { + misc_deregister(&sh532u_device); + kfree(stereo_sh532u_info); + stereo_sh532u_info = NULL; + } + return 0; } -static const struct i2c_device_id sh532u_id[] = { +static const struct i2c_device_id left_sh532u_id[] = { { "sh532u", 0 }, + { "sh532uL", 0 }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, left_sh532u_id); + +static struct i2c_driver left_sh532u_i2c_driver = { + .driver = { + .name = "sh532uL", + .owner = THIS_MODULE, + }, + .probe = left_sh532u_probe, + .remove = left_sh532u_remove, + .id_table = left_sh532u_id, +}; + +static int right_sh532u_probe( + struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err ; + + pr_info("right_sh532u: probing sensor: i2c_client=0x%x\n", (u32)client); + + err = sh532u_probe_helper(client); + + return err; +} + +static int right_sh532u_remove(struct i2c_client *client) +{ + if (!stereo_sh532u_info || !client) { + pr_info("right_sh532u_remove(): NULL pointers\n"); + return 0; + } + + kfree(stereo_sh532u_info->right); + stereo_sh532u_info->right = NULL; + + if (!stereo_sh532u_info->left) { + misc_deregister(&sh532u_device); + kfree(stereo_sh532u_info); + stereo_sh532u_info = NULL; + } + + return 0; +} + +static const struct i2c_device_id right_sh532u_id[] = { + { "sh532uR", 0 }, { }, }; -MODULE_DEVICE_TABLE(i2c, sh532u_id); +MODULE_DEVICE_TABLE(i2c, right_sh532u_id); -static struct i2c_driver sh532u_i2c_driver = { +static struct i2c_driver right_sh532u_i2c_driver = { .driver = { - .name = "sh532u", + .name = "sh532uR", .owner = THIS_MODULE, }, - .probe = sh532u_probe, - .remove = sh532u_remove, - .id_table = sh532u_id, + .probe = right_sh532u_probe, + .remove = right_sh532u_remove, + .id_table = right_sh532u_id, }; static int __init sh532u_init(void) { - return i2c_add_driver(&sh532u_i2c_driver); + int ret; + pr_info("sh532u focuser driver loading\n"); + ret = i2c_add_driver(&left_sh532u_i2c_driver); + if (ret) + return ret; + + ret = i2c_add_driver(&right_sh532u_i2c_driver); + + return ret; } static void __exit sh532u_exit(void) { - i2c_del_driver(&sh532u_i2c_driver); + i2c_del_driver(&left_sh532u_i2c_driver); + i2c_del_driver(&right_sh532u_i2c_driver); } module_init(sh532u_init); diff --git a/include/media/ov5650.h b/include/media/ov5650.h index 4a5f5baa5b43..d45a952eecf2 100644 --- a/include/media/ov5650.h +++ b/include/media/ov5650.h @@ -44,6 +44,7 @@ struct ov5650_mode { __u32 coarse_time; __u16 gain; }; + #ifdef __KERNEL__ struct ov5650_platform_data { int (*power_on)(void); diff --git a/include/media/sh532u.h b/include/media/sh532u.h index 5c4ffd9d42f8..166caad65f88 100644 --- a/include/media/sh532u.h +++ b/include/media/sh532u.h @@ -24,6 +24,7 @@ #define SH532U_IOCTL_GET_CONFIG _IOR('o', 1, struct sh532u_config) #define SH532U_IOCTL_SET_POSITION _IOW('o', 2, u32) #define SH532U_IOCTL_GET_MOVE_STATUS _IOW('o', 3, unsigned char) +#define SH532U_IOCTL_SET_CAMERA_MODE _IOW('o', 4, unsigned char) enum sh532u_move_status { SH532U_STATE_UNKNOWN = 1, diff --git a/include/media/tegra_camera.h b/include/media/tegra_camera.h index 3c8ddcab26e3..f88d376e6769 100644 --- a/include/media/tegra_camera.h +++ b/include/media/tegra_camera.h @@ -13,7 +13,8 @@ * GNU General Public License for more details. * */ - +#ifndef TEGRA_CAMERA_H +#define TEGRA_CAMERA_H enum { TEGRA_CAMERA_MODULE_ISP = 0, TEGRA_CAMERA_MODULE_VI, @@ -31,8 +32,19 @@ struct tegra_camera_clk_info { unsigned long rate; }; +enum StereoCameraMode { + Main = 0x0, /* Sets the default camera to Main */ + StereoCameraMode_Left = 0x01, /* the left camera is on. */ + StereoCameraMode_Right = 0x02, /* the right camera is on. */ + StereoCameraMode_Stereo = 0x03, /* both cameras are on. */ + StereoCameraMode_Force32 = 0x7FFFFFFF +}; + + #define TEGRA_CAMERA_IOCTL_ENABLE _IOWR('i', 1, uint) #define TEGRA_CAMERA_IOCTL_DISABLE _IOWR('i', 2, uint) #define TEGRA_CAMERA_IOCTL_CLK_SET_RATE \ _IOWR('i', 3, struct tegra_camera_clk_info) #define TEGRA_CAMERA_IOCTL_RESET _IOWR('i', 4, uint) + +#endif |