From 0bee410db5fdb5a97578b6dc002b7d54fedbfe64 Mon Sep 17 00:00:00 2001 From: Andrew Chew Date: Wed, 1 Aug 2012 16:39:32 -0700 Subject: tegra: Make tegra_vi01_device accessible Make it accessible outside of drivers/video/tegra. V4L2 driver needs to set some platform_data. Add suport for T20. Change-Id: I98353c2874ea28cfa0a7a5dd8a1dc4c586af4dd7 Signed-off-by: Andrew Chew Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/200220 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- drivers/video/tegra/host/t20/t20.c | 6 ++++++ drivers/video/tegra/host/t30/t30.c | 6 ++++++ include/linux/nvhost.h | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/drivers/video/tegra/host/t20/t20.c b/drivers/video/tegra/host/t20/t20.c index 71ed7334e714..e6840ae7ba1c 100644 --- a/drivers/video/tegra/host/t20/t20.c +++ b/drivers/video/tegra/host/t20/t20.c @@ -286,3 +286,9 @@ int nvhost_init_t20_support(struct nvhost_master *host, return 0; } + +/* Hacky way to get access to struct nvhost_device tegra_vi01_device. */ +struct nvhost_device *t20_get_tegra_vi01_device(void) +{ + return &tegra_vi01_device; +} diff --git a/drivers/video/tegra/host/t30/t30.c b/drivers/video/tegra/host/t30/t30.c index 334d598d5c0b..6c3a7f925177 100644 --- a/drivers/video/tegra/host/t30/t30.c +++ b/drivers/video/tegra/host/t30/t30.c @@ -301,3 +301,9 @@ int nvhost_init_t30_support(struct nvhost_master *host, return 0; } + +/* Hacky way to get access to struct nvhost_device tegra_vi01_device. */ +struct nvhost_device *t30_get_tegra_vi01_device(void) +{ + return &tegra_vi01_device; +} diff --git a/include/linux/nvhost.h b/include/linux/nvhost.h index d7d8ad04653d..add4aeab377d 100644 --- a/include/linux/nvhost.h +++ b/include/linux/nvhost.h @@ -215,4 +215,8 @@ int nvhost_syncpt_wait_timeout_ext(struct nvhost_device *dev, u32 id, u32 thresh void nvhost_scale3d_set_throughput_hint(int hint); +/* Hacky way to get access to struct nvhost_device tegra_vi01_device. */ +struct nvhost_device *t20_get_tegra_vi01_device(void); +struct nvhost_device *t30_get_tegra_vi01_device(void); + #endif -- cgit v1.2.3 From cf430cbe6d219edf9da694697a5406bf27ed39a0 Mon Sep 17 00:00:00 2001 From: Andrew Chew Date: Wed, 1 Aug 2012 12:57:12 -0700 Subject: tegra: When using V4L2, don't use vi client. The VI client within drivers/video/tegra is mutually exclusive with the Tegra V4L2 framework, since they both want to own the camera hardware. Change-Id: Idebd0f619f5fc7eb6323b2e08c29c9692c8887a0 Signed-off-by: Andrew Chew Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/200221 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- drivers/video/tegra/host/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/tegra/host/Makefile b/drivers/video/tegra/host/Makefile index 6e5e469897b3..c2608218c811 100644 --- a/drivers/video/tegra/host/Makefile +++ b/drivers/video/tegra/host/Makefile @@ -22,7 +22,9 @@ obj-$(CONFIG_TEGRA_GRHOST) += t20/ obj-$(CONFIG_TEGRA_GRHOST) += t30/ obj-$(CONFIG_TEGRA_GRHOST) += gr2d/ obj-$(CONFIG_TEGRA_GRHOST) += isp/ +ifeq ($(CONFIG_TEGRA_CAMERA),y) obj-$(CONFIG_TEGRA_GRHOST) += vi/ +endif obj-$(CONFIG_TEGRA_GRHOST) += nvhost.o obj-$(CONFIG_TEGRA_GRHOST_USE_NVMAP) += nvmap.o -- cgit v1.2.3 From 58d8e724d2241b63870ff771dd6962ce9dc5e10c Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Wed, 16 Jan 2013 17:27:29 -0800 Subject: media: soc_camera: add OV5650 SoC camera I2C device driver OV5650 is a RAW sensor outputing Bayer RAW 8 or RAW 10 data. This driver uses SoC camera interface and supports several different resolution. Change-Id: I8075b63b42f7949a264bdef446f5ed8bdc0a9eee Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/200223 GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- drivers/media/video/Kconfig | 6 + drivers/media/video/Makefile | 1 + drivers/media/video/ov5650.c | 1382 +++++++++++++++++++++++++++++++++++++++ include/media/v4l2-chip-ident.h | 1 + 4 files changed, 1390 insertions(+) create mode 100644 drivers/media/video/ov5650.c diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 651a17e04fd0..dfff30255a92 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -867,6 +867,12 @@ config SOC_CAMERA_OV5642 help This is a V4L2 camera driver for the OmniVision OV5642 sensor +config SOC_CAMERA_OV5650 + tristate "ov5650 sensor support" + depends on SOC_CAMERA && I2C + help + This is a V4L2 camera driver for the OmniVision OV5650 sensor + config SOC_CAMERA_OV6650 tristate "ov6650 sensor support" depends on SOC_CAMERA && I2C diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index f63ad7e88fda..ce79916258ef 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o obj-$(CONFIG_SOC_CAMERA_OV5640) += ov5640.o obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o +obj-$(CONFIG_SOC_CAMERA_OV5650) += ov5650.o obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o diff --git a/drivers/media/video/ov5650.c b/drivers/media/video/ov5650.c new file mode 100644 index 000000000000..e721065c222b --- /dev/null +++ b/drivers/media/video/ov5650.c @@ -0,0 +1,1382 @@ +/* + * OmniVision OV5650 sensor driver + * + * Copyright (c) 2013, NVIDIA 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 as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define SIZEOF_I2C_TRANSBUF 32 + +struct ov5650_priv { + struct v4l2_subdev subdev; + struct v4l2_mbus_framefmt mf; + const struct ov5650_platform_data *pdata; + + int ident; + u16 chip_id; + u8 revision; + + int mode; + + struct i2c_client *client; + u8 i2c_trans_buf[SIZEOF_I2C_TRANSBUF]; +}; + +static struct ov5650_priv *to_ov5650(const struct v4l2_subdev *sd) +{ + return container_of(sd, struct ov5650_priv, subdev); +} + +/** + * struct ov5650_reg - ov5650 register format + * @addr: 16-bit offset to register + * @val: 8/16/32-bit register value + * + * Define a structure for OV5650 register initialization values + */ +struct ov5650_reg { + u16 addr; + u16 val; +}; + +#define OV5650_TABLE_WAIT_MS 0 +#define OV5650_TABLE_END 1 +#define OV5650_MAX_RETRIES 3 + +static struct ov5650_reg tp_none_seq[] = { + {0x5046, 0x00}, + {OV5650_TABLE_END, 0x0000} +}; + +static struct ov5650_reg tp_cbars_seq[] = { + {0x503D, 0xC0}, + {0x503E, 0x00}, + {0x5046, 0x01}, + {OV5650_TABLE_END, 0x0000} +}; + +static struct ov5650_reg tp_checker_seq[] = { + {0x503D, 0xC0}, + {0x503E, 0x0A}, + {0x5046, 0x01}, + {OV5650_TABLE_END, 0x0000} +}; + +static struct ov5650_reg *test_pattern_modes[] = { + tp_none_seq, + tp_cbars_seq, + tp_checker_seq, +}; + +static struct ov5650_reg reset_seq[] = { + {0x3008, 0x82}, + {OV5650_TABLE_WAIT_MS, 5}, + {0x3008, 0x42}, + {OV5650_TABLE_WAIT_MS, 5}, + {OV5650_TABLE_END, 0x0000}, +}; + +static struct ov5650_reg mode_start[] = { + {0x3103, 0x93}, + {0x3017, 0xff}, + {0x3018, 0xfc}, + + {0x3600, 0x50}, + {0x3601, 0x0d}, + {0x3604, 0x50}, + {0x3605, 0x04}, + {0x3606, 0x3f}, + {0x3612, 0x1a}, + {0x3630, 0x22}, + {0x3631, 0x22}, + {0x3702, 0x3a}, + {0x3704, 0x18}, + {0x3705, 0xda}, + {0x3706, 0x41}, + {0x370a, 0x80}, + {0x370b, 0x40}, + {0x370e, 0x00}, + {0x3710, 0x28}, + {0x3712, 0x13}, + {0x3830, 0x50}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3a00, 0x38}, + + + {0x3603, 0xa7}, + {0x3615, 0x50}, + {0x3620, 0x56}, + {0x3810, 0x00}, + {0x3836, 0x00}, + {0x3a1a, 0x06}, + {0x4000, 0x01}, + {0x401c, 0x48}, + {0x401d, 0x08}, + {0x5000, 0x06}, + {0x5001, 0x00}, + {0x5002, 0x00}, + {0x503d, 0x00}, + {0x5046, 0x00}, + + {0x300f, 0x8f}, + + {0x3010, 0x10}, + {0x3011, 0x14}, + {0x3012, 0x02}, + {0x3815, 0x82}, + {0x3503, 0x00}, + {0x3613, 0x44}, + {OV5650_TABLE_END, 0x0}, +}; + +static struct ov5650_reg mode_2592x1944[] = { + {0x3621, 0x2f}, + + {0x3632, 0x55}, + {0x3703, 0xe6}, + {0x370c, 0xa0}, + {0x370d, 0x04}, + {0x3713, 0x2f}, + {0x3800, 0x02}, + {0x3801, 0x58}, + {0x3802, 0x00}, + {0x3803, 0x0c}, + {0x3804, 0x0a}, + {0x3805, 0x20}, + {0x3806, 0x07}, + {0x3807, 0xa0}, + {0x3808, 0x0a}, + + {0x3809, 0x20}, + + {0x380a, 0x07}, + + {0x380b, 0xa0}, + + {0x380c, 0x0c}, + + {0x380d, 0xb4}, + + {0x380e, 0x07}, + + {0x380f, 0xb0}, + + {0x3818, 0xc0}, + {0x381a, 0x3c}, + {0x3a0d, 0x06}, + {0x3c01, 0x00}, + {0x3007, 0x3f}, + {0x5059, 0x80}, + {0x3003, 0x03}, + {0x3500, 0x00}, + {0x3501, 0x7a}, + + {0x3502, 0xd0}, + + {0x350a, 0x00}, + {0x350b, 0x00}, + {0x401d, 0x08}, + {0x4801, 0x0f}, + {0x300e, 0x0c}, + {0x4803, 0x50}, + {0x4800, 0x34}, + {OV5650_TABLE_END, 0x0000} +}; + +static struct ov5650_reg mode_1296x972[] = { + {0x3621, 0xaf}, + + {0x3632, 0x5a}, + {0x3703, 0xb0}, + {0x370c, 0xc5}, + {0x370d, 0x42}, + {0x3713, 0x2f}, + {0x3800, 0x03}, + {0x3801, 0x3c}, + {0x3802, 0x00}, + {0x3803, 0x06}, + {0x3804, 0x05}, + {0x3805, 0x10}, + {0x3806, 0x03}, + {0x3807, 0xd0}, + {0x3808, 0x05}, + + {0x3809, 0x10}, + + {0x380a, 0x03}, + + {0x380b, 0xd0}, + + {0x380c, 0x08}, + + {0x380d, 0xa8}, + + {0x380e, 0x05}, + + {0x380f, 0xa4}, + + {0x3818, 0xc1}, + {0x381a, 0x00}, + {0x3a0d, 0x08}, + {0x3c01, 0x00}, + {0x3007, 0x3b}, + {0x5059, 0x80}, + {0x3003, 0x03}, + {0x3500, 0x00}, + + {0x3501, 0x5a}, + {0x3502, 0x10}, + {0x350a, 0x00}, + {0x350b, 0x10}, + {0x401d, 0x08}, + {0x4801, 0x0f}, + {0x300e, 0x0c}, + {0x4803, 0x50}, + {0x4800, 0x34}, + {OV5650_TABLE_END, 0x0000} +}; + +static struct ov5650_reg mode_2080x1164[] = { + {0x3103, 0x93}, + {0x3007, 0x3b}, + {0x3017, 0xff}, + {0x3018, 0xfc}, + + {0x3600, 0x54}, + {0x3601, 0x05}, + {0x3603, 0xa7}, + {0x3604, 0x40}, + {0x3605, 0x04}, + {0x3606, 0x3f}, + {0x3612, 0x1a}, + {0x3613, 0x44}, + {0x3615, 0x52}, + {0x3620, 0x56}, + {0x3623, 0x01}, + {0x3630, 0x22}, + {0x3631, 0x36}, + {0x3632, 0x5f}, + {0x3633, 0x24}, + + {0x3702, 0x3a}, + {0x3704, 0x18}, + {0x3706, 0x41}, + {0x370b, 0x40}, + {0x370e, 0x00}, + {0x3710, 0x28}, + {0x3711, 0x24}, + {0x3712, 0x13}, + + {0x3810, 0x00}, + {0x3815, 0x82}, + {0x3830, 0x50}, + {0x3836, 0x00}, + + {0x3a1a, 0x06}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3a00, 0x38}, + + {0x3a0d, 0x06}, + {0x3c01, 0x34}, + + {0x401f, 0x03}, + {0x4000, 0x05}, + {0x401d, 0x08}, + {0x4001, 0x02}, + + {0x5001, 0x00}, + {0x5002, 0x00}, + {0x503d, 0x00}, + {0x5046, 0x00}, + + {0x300f, 0x8f}, + + {0x3010, 0x10}, + {0x3011, 0x14}, + {0x3012, 0x02}, + {0x3503, 0x00}, + + + {0x3621, 0x2f}, + + {0x3703, 0xe6}, + {0x370c, 0x00}, + {0x370d, 0x04}, + {0x3713, 0x22}, + {0x3714, 0x27}, + {0x3705, 0xda}, + {0x370a, 0x80}, + + {0x3800, 0x02}, + {0x3801, 0x12}, + {0x3802, 0x00}, + {0x3803, 0x0a}, + {0x3804, 0x08}, + {0x3805, 0x20}, + {0x3806, 0x04}, + {0x3807, 0x92}, + {0x3808, 0x08}, + + {0x3809, 0x20}, + + {0x380a, 0x04}, + + {0x380b, 0x92}, + + {0x380c, 0x0a}, + + {0x380d, 0x96}, + + {0x380e, 0x04}, + + {0x380f, 0x9e}, + + {0x3818, 0xc0}, + {0x381a, 0x3c}, + {0x381c, 0x31}, + {0x381d, 0x8e}, + {0x381e, 0x04}, + {0x381f, 0x92}, + {0x3820, 0x04}, + {0x3821, 0x19}, + {0x3824, 0x01}, + {0x3827, 0x0a}, + {0x401c, 0x46}, + + {0x3003, 0x03}, + {0x3500, 0x00}, + {0x3501, 0x49}, + {0x3502, 0xa0}, + {0x350a, 0x00}, + {0x350b, 0x00}, + {0x4801, 0x0f}, + {0x300e, 0x0c}, + {0x4803, 0x50}, + {0x4800, 0x34}, + + {OV5650_TABLE_END, 0x0000} +}; + +static struct ov5650_reg mode_1920x1080[] = { + {0x3103, 0x93}, + {0x3007, 0x3b}, + {0x3017, 0xff}, + {0x3018, 0xfc}, + + {0x3600, 0x54}, + {0x3601, 0x05}, + {0x3603, 0xa7}, + {0x3604, 0x40}, + {0x3605, 0x04}, + {0x3606, 0x3f}, + {0x3612, 0x1a}, + {0x3613, 0x44}, + {0x3615, 0x52}, + {0x3620, 0x56}, + {0x3623, 0x01}, + {0x3630, 0x22}, + {0x3631, 0x36}, + {0x3632, 0x5f}, + {0x3633, 0x24}, + + {0x3702, 0x3a}, + {0x3704, 0x18}, + {0x3706, 0x41}, + {0x370b, 0x40}, + {0x370e, 0x00}, + {0x3710, 0x28}, + {0x3711, 0x24}, + {0x3712, 0x13}, + + {0x3810, 0x00}, + {0x3815, 0x82}, + + {0x3830, 0x50}, + {0x3836, 0x00}, + + {0x3a1a, 0x06}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3a00, 0x38}, + {0x3a0d, 0x06}, + {0x3c01, 0x34}, + + {0x401f, 0x03}, + {0x4000, 0x05}, + {0x401d, 0x08}, + {0x4001, 0x02}, + + {0x5001, 0x00}, + {0x5002, 0x00}, + {0x503d, 0x00}, + {0x5046, 0x00}, + + {0x300f, 0x8f}, + {0x3010, 0x10}, + {0x3011, 0x14}, + {0x3012, 0x02}, + {0x3503, 0x00}, + + {0x3621, 0x2f}, + {0x3703, 0xe6}, + {0x370c, 0x00}, + {0x370d, 0x04}, + {0x3713, 0x22}, + {0x3714, 0x27}, + {0x3705, 0xda}, + {0x370a, 0x80}, + + {0x3800, 0x02}, + {0x3801, 0x94}, + {0x3802, 0x00}, + {0x3803, 0x0c}, + {0x3804, 0x07}, + {0x3805, 0x80}, + {0x3806, 0x04}, + {0x3807, 0x40}, + {0x3808, 0x07}, + {0x3809, 0x80}, + {0x380a, 0x04}, + {0x380b, 0x40}, + {0x380c, 0x0a}, + {0x380d, 0x84}, + {0x380e, 0x04}, + {0x380f, 0xa4}, + {0x3818, 0xc0}, + {0x381a, 0x3c}, + {0x381c, 0x31}, + {0x381d, 0xa4}, + {0x381e, 0x04}, + {0x381f, 0x60}, + {0x3820, 0x03}, + {0x3821, 0x1a}, + {0x3824, 0x01}, + {0x3827, 0x0a}, + {0x401c, 0x46}, + + {0x3003, 0x03}, + {0x3500, 0x00}, + {0x3501, 0x49}, + {0x3502, 0xa0}, + {0x350a, 0x00}, + {0x350b, 0x00}, + {0x4801, 0x0f}, + {0x300e, 0x0c}, + {0x4803, 0x50}, + {0x4800, 0x34}, + + {OV5650_TABLE_END, 0x0000} +}; + +static struct ov5650_reg mode_1280x720[] = { + {0x3103, 0x93}, + {0x3b07, 0x0c}, + {0x3017, 0xff}, + {0x3018, 0xfc}, + {0x3706, 0x41}, + {0x3613, 0xc4}, + {0x370d, 0x42}, + {0x3703, 0x9a}, + {0x3630, 0x22}, + {0x3605, 0x04}, + {0x3606, 0x3f}, + {0x3712, 0x13}, + {0x370e, 0x00}, + {0x370b, 0x40}, + {0x3600, 0x54}, + {0x3601, 0x05}, + {0x3713, 0x22}, + {0x3714, 0x27}, + {0x3631, 0x22}, + {0x3612, 0x1a}, + {0x3604, 0x40}, + {0x3705, 0xdb}, + {0x370a, 0x81}, + {0x370c, 0x00}, + {0x3710, 0x28}, + {0x3702, 0x3a}, + {0x3704, 0x18}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3a00, 0x38}, + {0x3800, 0x02}, + {0x3801, 0x54}, + {0x3803, 0x0c}, + {0x380c, 0x0c}, + {0x380d, 0xb4}, + {0x380e, 0x07}, + {0x380f, 0xb0}, + {0x3830, 0x50}, + {0x3a08, 0x12}, + {0x3a09, 0x70}, + {0x3a0a, 0x0f}, + {0x3a0b, 0x60}, + {0x3a0d, 0x06}, + {0x3a0e, 0x06}, + {0x3a13, 0x54}, + {0x3815, 0x82}, + {0x5059, 0x80}, + {0x3615, 0x52}, + {0x505a, 0x0a}, + {0x505b, 0x2e}, + {0x3713, 0x92}, + {0x3714, 0x17}, + {0x3804, 0x05}, + {0x3805, 0x00}, + {0x3806, 0x02}, + {0x3807, 0xd0}, + {0x3808, 0x05}, + {0x3809, 0x00}, + {0x380a, 0x02}, + {0x380b, 0xd0}, + {0x380c, 0x08}, + {0x380d, 0x72}, + {0x380e, 0x02}, + {0x380f, 0xe4}, + {0x3815, 0x81}, + {0x381c, 0x10}, + {0x381d, 0x82}, + {0x381e, 0x05}, + {0x381f, 0xc0}, + {0x3821, 0x20}, + {0x3824, 0x23}, + {0x3825, 0x2c}, + {0x3826, 0x00}, + {0x3827, 0x0c}, + {0x3a08, 0x1b}, + {0x3a09, 0xc0}, + {0x3a0a, 0x17}, + {0x3a0b, 0x20}, + {0x3a0d, 0x01}, + {0x3a0e, 0x01}, + {0x3a1a, 0x06}, + {0x3503, 0x00}, + {0x3623, 0x01}, + {0x3633, 0x24}, + {0x3c01, 0x34}, + {0x3c04, 0x28}, + {0x3c05, 0x98}, + {0x3c07, 0x07}, + {0x3c09, 0xc2}, + {0x4000, 0x05}, + {0x401d, 0x28}, + {0x4001, 0x02}, + {0x401c, 0x42}, + {0x5046, 0x09}, + {0x3810, 0x40}, + {0x3836, 0x41}, + {0x505f, 0x04}, + {0x5000, 0xfe}, + {0x5001, 0x01}, + {0x5002, 0x00}, + {0x503d, 0x00}, /* bit[7]=1 enable test_pattern */ + {0x5901, 0x00}, + {0x585a, 0x01}, + {0x585b, 0x2c}, + {0x585c, 0x01}, + {0x585d, 0x93}, + {0x585e, 0x01}, + {0x585f, 0x90}, + {0x5860, 0x01}, + {0x5861, 0x0d}, + {0x5180, 0xc0}, + {0x5184, 0x00}, + {0x470a, 0x00}, + {0x470b, 0x00}, + {0x470c, 0x00}, + {0x300f, 0x8e}, + {0x3603, 0xa7}, + {0x3632, 0x55}, + {0x3620, 0x56}, + {0x3621, 0xaf}, + {0x3818, 0xc1}, + {0x3631, 0x36}, + {0x3632, 0x5f}, + {0x3711, 0x24}, + {0x401f, 0x03}, + {0x3008, 0x02}, + + {0x3011, 0x14}, + {0x3007, 0x3B}, + {0x4801, 0x0f}, + {0x3003, 0x03}, + {0x300e, 0x0c}, + {0x4803, 0x50}, + {0x4800, 0x04}, /* bit[5]=0 as CSI continuous clock */ + {0x300f, 0x8f}, + {0x3010, 0x10}, + {0x3815, 0x82}, + {0x3003, 0x01}, + + {OV5650_TABLE_END, 0x0000} +}; + +static struct ov5650_reg mode_1264x704[] = { + {0x3600, 0x54}, + {0x3601, 0x05}, + {0x3604, 0x40}, + {0x3705, 0xdb}, + {0x370a, 0x81}, + {0x3615, 0x52}, + {0x3810, 0x40}, + {0x3836, 0x41}, + {0x4000, 0x05}, + {0x401c, 0x42}, + {0x401d, 0x08}, + {0x5046, 0x09}, + {0x3010, 0x00}, + {0x3503, 0x00}, + {0x3613, 0xc4}, + + {0x3621, 0xaf}, + + {0x3632, 0x55}, + {0x3703, 0x9a}, + {0x370c, 0x00}, + {0x370d, 0x42}, + {0x3713, 0x22}, + {0x3800, 0x02}, + {0x3801, 0x54}, + {0x3802, 0x00}, + {0x3803, 0x0c}, + {0x3804, 0x05}, + {0x3805, 0x00}, + {0x3806, 0x02}, + {0x3807, 0xd0}, + {0x3808, 0x05}, + + {0x3809, 0x00}, + + {0x380a, 0x02}, + + {0x380b, 0xd0}, + + {0x380c, 0x08}, + + {0x380d, 0x72}, + + {0x380e, 0x02}, + + {0x380f, 0xe4}, + + {0x3818, 0xc1}, + {0x381a, 0x3c}, + {0x3a0d, 0x06}, + {0x3c01, 0x34}, + {0x3007, 0x3b}, + {0x5059, 0x80}, + {0x3003, 0x03}, + {0x3500, 0x04}, + {0x3501, 0xa5}, + + {0x3502, 0x10}, + + {0x350a, 0x00}, + {0x350b, 0x00}, + {0x4801, 0x0f}, + {0x300e, 0x0c}, + {0x4803, 0x50}, + {0x4800, 0x24}, + {0x300f, 0x8b}, + + {0x3711, 0x24}, + {0x3713, 0x92}, + {0x3714, 0x17}, + {0x381c, 0x10}, + {0x381d, 0x82}, + {0x381e, 0x05}, + {0x381f, 0xc0}, + {0x3821, 0x20}, + {0x3824, 0x23}, + {0x3825, 0x2c}, + {0x3826, 0x00}, + {0x3827, 0x0c}, + {0x3623, 0x01}, + {0x3633, 0x24}, + {0x3632, 0x5f}, + {0x401f, 0x03}, + + {OV5650_TABLE_END, 0x0000} +}; + +static struct ov5650_reg mode_320x240[] = { + {0x3103, 0x93}, + {0x3b07, 0x0c}, + {0x3017, 0xff}, + {0x3018, 0xfc}, + {0x3706, 0x41}, + {0x3613, 0xc4}, + {0x370d, 0x42}, + {0x3703, 0x9a}, + {0x3630, 0x22}, + {0x3605, 0x04}, + {0x3606, 0x3f}, + {0x3712, 0x13}, + {0x370e, 0x00}, + {0x370b, 0x40}, + {0x3600, 0x54}, + {0x3601, 0x05}, + {0x3713, 0x22}, + {0x3714, 0x27}, + {0x3631, 0x22}, + {0x3612, 0x1a}, + {0x3604, 0x40}, + {0x3705, 0xdc}, + {0x370a, 0x83}, + {0x370c, 0xc8}, + {0x3710, 0x28}, + {0x3702, 0x3a}, + {0x3704, 0x18}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3a00, 0x38}, + {0x3800, 0x02}, + {0x3801, 0x54}, + {0x3803, 0x0c}, + {0x380c, 0x0c}, + {0x380d, 0xb4}, + {0x380e, 0x07}, + {0x380f, 0xb0}, + {0x3830, 0x50}, + {0x3a08, 0x12}, + {0x3a09, 0x70}, + {0x3a0a, 0x0f}, + {0x3a0b, 0x60}, + {0x3a0d, 0x06}, + {0x3a0e, 0x06}, + {0x3a13, 0x54}, + {0x3815, 0x82}, + {0x5059, 0x80}, + {0x3615, 0x52}, + {0x505a, 0x0a}, + {0x505b, 0x2e}, + {0x3713, 0x92}, + {0x3714, 0x17}, + {0x3803, 0x0a}, + {0x3804, 0x05}, + {0x3805, 0x00}, + {0x3806, 0x01}, + {0x3807, 0x00}, + {0x3808, 0x01}, + {0x3809, 0x40}, + {0x380a, 0x01}, + {0x380b, 0x00}, + {0x380c, 0x0a}, + + {0x380d, 0x04}, + + {0x380e, 0x01}, + + {0x380f, 0x38}, + + {0x3500, 0x00}, + {0x3501, 0x13}, + {0x3502, 0x80}, + {0x350b, 0x7f}, + + {0x3815, 0x81}, + {0x3824, 0x23}, + {0x3825, 0x20}, + {0x3826, 0x00}, + {0x3827, 0x08}, + {0x370d, 0xc2}, + {0x3a08, 0x17}, + {0x3a09, 0x64}, + {0x3a0a, 0x13}, + {0x3a0b, 0x80}, + {0x3a00, 0x58}, + {0x3a1a, 0x06}, + {0x3503, 0x00}, + {0x3623, 0x01}, + {0x3633, 0x24}, + {0x3c01, 0x34}, + {0x3c04, 0x28}, + {0x3c05, 0x98}, + {0x3c07, 0x07}, + {0x3c09, 0xc2}, + {0x4000, 0x05}, + {0x401d, 0x08}, + {0x4001, 0x02}, + {0x401c, 0x42}, + {0x5046, 0x09}, + {0x3810, 0x40}, + {0x3836, 0x41}, + {0x505f, 0x04}, + {0x5001, 0x00}, + {0x5002, 0x02}, + {0x503d, 0x00}, + {0x5901, 0x08}, + {0x585a, 0x01}, + {0x585b, 0x2c}, + {0x585c, 0x01}, + {0x585d, 0x93}, + {0x585e, 0x01}, + {0x585f, 0x90}, + {0x5860, 0x01}, + {0x5861, 0x0d}, + {0x5180, 0xc0}, + {0x5184, 0x00}, + {0x470a, 0x00}, + {0x470b, 0x00}, + {0x470c, 0x00}, + {0x300f, 0x8e}, + {0x3603, 0xa7}, + {0x3632, 0x55}, + {0x3620, 0x56}, + {0x3621, 0xaf}, + {0x3818, 0xc3}, + {0x3631, 0x36}, + {0x3632, 0x5f}, + {0x3711, 0x24}, + {0x401f, 0x03}, + + {0x3011, 0x14}, + {0x3007, 0x3B}, + {0x300f, 0x8f}, + {0x4801, 0x0f}, + {0x3003, 0x03}, + {0x300e, 0x0c}, + {0x3010, 0x15}, + {0x4803, 0x50}, + {0x4800, 0x24}, + {0x4837, 0x40}, + {0x3815, 0x82}, + + {OV5650_TABLE_END, 0x0000} +}; + +static struct ov5650_reg mode_end[] = { + {0x3212, 0x00}, + {0x3003, 0x01}, + {0x3212, 0x10}, + {0x3212, 0xa0}, + {0x3008, 0x02}, + + {OV5650_TABLE_END, 0x0000} +}; + +enum { + OV5650_MODE_2592x1944, + OV5650_MODE_2080x1164, + OV5650_MODE_1920x1080, + OV5650_MODE_1296x972, + OV5650_MODE_1280x720, + OV5650_MODE_1264x704, + OV5650_MODE_320x240, + OV5650_MODE_INVALID +}; + +static struct ov5650_reg *mode_table[] = { + [OV5650_MODE_2592x1944] = mode_2592x1944, + [OV5650_MODE_2080x1164] = mode_2080x1164, + [OV5650_MODE_1920x1080] = mode_1920x1080, + [OV5650_MODE_1296x972] = mode_1296x972, + [OV5650_MODE_1280x720] = mode_1280x720, + [OV5650_MODE_1264x704] = mode_1264x704, + [OV5650_MODE_320x240] = mode_320x240 +}; + +static const struct v4l2_frmsize_discrete ov5650_frmsizes[] = { + {2592, 1944}, + {2080, 1164}, + {1920, 1080}, + {1296, 972}, + {1280, 720}, + {1264, 704}, + {320, 240}, +}; + +static int ov5650_find_mode(u32 width, u32 height) +{ + if (width == 2592 && height == 1944) + return OV5650_MODE_2592x1944; + else if (width == 2080 && height == 1164) + return OV5650_MODE_2080x1164; + else if (width == 1920 && height == 1080) + return OV5650_MODE_1920x1080; + else if (width == 1296 && height == 972) + return OV5650_MODE_1296x972; + else if (width == 1280 && height == 720) + return OV5650_MODE_1280x720; + else if (width == 1264 && height == 704) + return OV5650_MODE_1264x704; + else if (width == 320 && height == 240) + return OV5650_MODE_320x240; + else { + pr_err("ov5650: %dx%d is not supported\n", width, height); + return OV5650_MODE_2592x1944; + } +} + +/** + * ov5650_reg_read - Read a value from a register in an ov5650 sensor device + * @client: i2c driver client structure + * @reg: register address / offset + * @val: stores the value that gets read + * + * Read a value from a register in an ov5650 sensor device. + * The value is returned in 'val'. + * Returns zero if successful, or non-zero otherwise. + */ +static int ov5650_reg_read(struct i2c_client *client, u16 reg, u8 *val) +{ + int ret; + u8 data[2] = {0}; + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = data, + }; + + data[0] = (u8)(reg >> 8); + data[1] = (u8)(reg & 0xff); + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) + goto err; + + msg.flags = I2C_M_RD; + msg.len = 1; + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) + goto err; + + *val = data[0]; + return 0; + +err: + dev_err(&client->dev, "Failed reading register 0x%02x!\n", reg); + return ret; +} + +/** + * Write a value to a register in ov5650 sensor device. + * @client: i2c driver client structure. + * @reg: Address of the register to read value from. + * @val: Value to be written to a specific register. + * Returns zero if successful, or non-zero otherwise. + */ +static int ov5650_reg_write(struct i2c_client *client, u16 reg, u8 val) +{ + int ret; + unsigned char data[3] = { (u8)(reg >> 8), (u8)(reg & 0xff), val }; + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .len = 3, + .buf = data, + }; + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) { + dev_err(&client->dev, "Failed writing register 0x%02x!\n", reg); + return ret; + } + + return 0; +} + +static int ov5650_write_bulk_reg(struct ov5650_priv *priv, int len) +{ + struct i2c_client *client = priv->client; + u8 *data = priv->i2c_trans_buf; + int err; + struct i2c_msg msg; + + if (!client->adapter) + return -ENODEV; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = len; + msg.buf = data; + + err = i2c_transfer(client->adapter, &msg, 1); + if (err != 1) { + dev_err(&client->dev, "I2C bulk transfer failed at %x\n", + (int)data[0] << 8 | data[1]); + return err; + } + + return 0; +} +static int ov5650_write_table(struct ov5650_priv *priv, + const struct ov5650_reg table[], + const struct ov5650_reg override_list[], + int num_override_regs) +{ + int err; + const struct ov5650_reg *next, *n_next; + u8 *b_ptr = priv->i2c_trans_buf; + unsigned int buf_filled = 0; + unsigned int i; + u16 val; + + for (next = table; next->addr != OV5650_TABLE_END; next++) { + if (next->addr == OV5650_TABLE_WAIT_MS) { + msleep(next->val); + continue; + } + + val = next->val; + /* When an override list is passed in, replace the reg */ + /* value to write if the reg is in the list */ + if (override_list) { + for (i = 0; i < num_override_regs; i++) { + if (next->addr == override_list[i].addr) { + val = override_list[i].val; + break; + } + } + } + + if (!buf_filled) { + b_ptr = priv->i2c_trans_buf; + *b_ptr++ = next->addr >> 8; + *b_ptr++ = next->addr & 0xff; + buf_filled = 2; + } + *b_ptr++ = val; + buf_filled++; + + n_next = next + 1; + if (n_next->addr != OV5650_TABLE_END && + n_next->addr != OV5650_TABLE_WAIT_MS && + buf_filled < SIZEOF_I2C_TRANSBUF && + n_next->addr == next->addr + 1) { + continue; + } + + err = ov5650_write_bulk_reg(priv, buf_filled); + if (err) + return err; + + buf_filled = 0; + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * V4L2 subdev internal operations + */ + +static void ov5650_set_default_fmt(struct ov5650_priv *priv) +{ + struct v4l2_mbus_framefmt *mf = &priv->mf; + + mf->width = ov5650_frmsizes[OV5650_MODE_2592x1944].width; + mf->height = ov5650_frmsizes[OV5650_MODE_2592x1944].height; + mf->code = V4L2_MBUS_FMT_SGRBG10_1X10; + mf->field = V4L2_FIELD_NONE; + mf->colorspace = V4L2_COLORSPACE_SRGB; +} + +static int ov5650_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct ov5650_priv *priv = to_ov5650(sd); + struct ov5650_reg reg_list[6]; + int ret = 0; + + if (enable) { + ret = ov5650_write_table(priv, reset_seq, NULL, 0); + if (ret) + return ret; + + ret = ov5650_write_table(priv, mode_start, NULL, 0); + if (ret) + return ret; + + ret = ov5650_write_table(priv, mode_table[priv->mode], + reg_list, 6); + if (ret) + return ret; + + ret = ov5650_write_table(priv, mode_end, NULL, 0); + if (ret) + return ret; + } else + ov5650_set_default_fmt(priv); + + return ret; +} + +/* Alter bus settings on camera side */ +static int ov5650_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) +{ + return 0; +} + +/* Request bus settings on camera side */ +static unsigned long ov5650_query_bus_param(struct soc_camera_device *icd) +{ + struct soc_camera_link *icl = to_soc_camera_link(icd); + + unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_10; + + return soc_camera_apply_sensor_flags(icl, flags); +} + +static int ov5650_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + struct ov5650_priv *priv = to_ov5650(sd); + + priv->mode = ov5650_find_mode(mf->width, mf->height); + memcpy(&priv->mf, mf, sizeof(struct v4l2_mbus_framefmt)); + + return 0; +} + +static int ov5650_s_power(struct v4l2_subdev *sd, int on) +{ + struct ov5650_priv *priv = to_ov5650(sd); + + if (on) { + ov5650_s_fmt(sd, &priv->mf); + ov5650_s_stream(sd, 1); + } else + ov5650_s_stream(sd, 0); + + return 0; +} + +static int ov5650_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + int mode; + + mode = ov5650_find_mode(mf->width, mf->height); + mf->width = ov5650_frmsizes[mode].width; + mf->height = ov5650_frmsizes[mode].height; + + if (mf->code != V4L2_MBUS_FMT_SGRBG8_1X8 && + mf->code != V4L2_MBUS_FMT_SGRBG10_1X10) + mf->code = V4L2_MBUS_FMT_SGRBG10_1X10; + + mf->field = V4L2_FIELD_NONE; + mf->colorspace = V4L2_COLORSPACE_SRGB; + + ov5650_s_fmt(sd, mf); + + return 0; +} + +static int ov5650_enum_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index >= 2) + return -EINVAL; + + switch (index) { + case 0: + *code = V4L2_MBUS_FMT_SGRBG10_1X10; + break; + case 1: + *code = V4L2_MBUS_FMT_SGRBG8_1X8; + break; + } + + return 0; +} + +static int ov5650_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = ov5650_frmsizes[OV5650_MODE_2592x1944].width; + a->bounds.height = ov5650_frmsizes[OV5650_MODE_2592x1944].height; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int ov5650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + a->c.left = 0; + a->c.top = 0; + a->c.width = ov5650_frmsizes[OV5650_MODE_2592x1944].width; + a->c.height = ov5650_frmsizes[OV5650_MODE_2592x1944].height; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +/* Get chip identification */ +static int ov5650_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) +{ + struct ov5650_priv *priv = to_ov5650(sd); + + id->ident = priv->ident; + id->revision = priv->revision; + + return 0; +} + +static struct soc_camera_ops ov5650_ops = { + .set_bus_param = ov5650_set_bus_param, + .query_bus_param = ov5650_query_bus_param, +}; + +static struct v4l2_subdev_video_ops ov5650_video_ops = { + .s_stream = ov5650_s_stream, + .s_mbus_fmt = ov5650_s_fmt, + .try_mbus_fmt = ov5650_try_fmt, + .enum_mbus_fmt = ov5650_enum_fmt, + .cropcap = ov5650_cropcap, + .g_crop = ov5650_g_crop, +}; + +static struct v4l2_subdev_core_ops ov5650_core_ops = { + .g_chip_ident = ov5650_g_chip_ident, + .s_power = ov5650_s_power, +}; + +static struct v4l2_subdev_ops ov5650_subdev_ops = { + .core = &ov5650_core_ops, + .video = &ov5650_video_ops, +}; + +static int ov5650_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct ov5650_priv *priv; + struct soc_camera_device *icd = client->dev.platform_data; + struct soc_camera_link *icl; + u8 chipid[2]; + int ret; + + /* Checking soc-camera interface */ + if (!icd) { + dev_err(&client->dev, "Missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); + if (!icl) { + dev_err(&client->dev, "Missing platform_data for driver\n"); + return -EINVAL; + } + + /* Register OV5650 soc_camera device interface */ + priv = kzalloc(sizeof(struct ov5650_priv), GFP_KERNEL); + if (!priv) { + dev_err(&client->dev, "Failed to allocate private data!\n"); + return -ENOMEM; + } + + v4l2_i2c_subdev_init(&priv->subdev, client, &ov5650_subdev_ops); + icd->ops = &ov5650_ops; + + priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + priv->ident = V4L2_IDENT_OV5650; + + ret = ov5650_reg_read(client, 0x300A, &chipid[0]); + if (ret) { + dev_err(&client->dev, "Failure to read Chip ID (high byte)\n"); + goto err; + } + + ret = ov5650_reg_read(client, 0x300B, &chipid[1]); + if (ret) { + dev_err(&client->dev, "Failure to read Chip ID (low byte)\n"); + goto err; + } + + if ((chipid[0] != 0x56) || ((chipid[1] & 0x51) != chipid[1])) { + dev_err(&client->dev, "Chip ID: %x%x not supported!\n", + chipid[0], chipid[1]); + ret = -ENODEV; + goto err; + } + + priv->chip_id = (chipid[0] << 8) | chipid[1]; + priv->revision = (chipid[1] == 0x50) ? 0x1A : 0x1B; + + priv->client = client; + + ov5650_set_default_fmt(priv); + + dev_info(&client->dev, "Detected a OV%x chip, revision %x\n", + priv->chip_id, priv->revision); + + return 0; + +err: + kfree(priv); + + return ret; +} + +static int ov5650_remove(struct i2c_client *client) +{ + struct ov5650_priv *priv = i2c_get_clientdata(client); + + kfree(priv); + return 0; +} + +static const struct i2c_device_id ov5650_id[] = { + { "ov5650", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ov5650_id); + +static struct i2c_driver ov5650_i2c_driver = { + .driver = { + .name = "ov5650", + }, + .probe = ov5650_probe, + .remove = ov5650_remove, + .id_table = ov5650_id, +}; + +static int __init ov5650_module_init(void) +{ + return i2c_add_driver(&ov5650_i2c_driver); +} + +static void __exit ov5650_module_exit(void) +{ + i2c_del_driver(&ov5650_i2c_driver); +} + +module_init(ov5650_module_init); +module_exit(ov5650_module_exit); + +MODULE_DESCRIPTION("OmniVision OV5650 Camera driver"); +MODULE_AUTHOR("Bryan Wu "); +MODULE_LICENSE("GPL v2"); diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index fb929eacd2e6..a0d15e57cc6f 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -78,6 +78,7 @@ enum { V4L2_IDENT_OV9740 = 260, V4L2_IDENT_OV5642 = 261, V4L2_IDENT_OV5640 = 262, + V4L2_IDENT_OV5650 = 263, /* module saa7146: reserved range 300-309 */ V4L2_IDENT_SAA7146 = 300, -- cgit v1.2.3 From 510e933eceda96651d5e79d1a56d964431c2f60c Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Wed, 16 Jan 2013 17:29:03 -0800 Subject: media: soc_camera: tegra: fix one building warning Change-Id: Ie685ad11a0847be5b51c752ec593aec857e2f0e2 Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/200224 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- drivers/media/video/tegra_v4l2_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c index 644d0be53803..d8db97e34742 100644 --- a/drivers/media/video/tegra_v4l2_camera.c +++ b/drivers/media/video/tegra_v4l2_camera.c @@ -1085,7 +1085,7 @@ static int tegra_camera_videobuf_setup(struct vb2_queue *vq, if (!*num_buffers) *num_buffers = 2; - dev_dbg(icd->parent, "num_buffers=%u, size=%u\n", + dev_dbg(icd->parent, "num_buffers=%u, size=%lu\n", *num_buffers, sizes[0]); tegra_camera_capture_setup(pcdev); -- cgit v1.2.3 From 59aa0b2d54eb2ee6f4fd4bf252632cbd5ee81e6f Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Tue, 12 Feb 2013 10:49:23 -0800 Subject: media: tegra: add supporting for RAW8/RAW10 input and output CSI host controller of Tegra can support Bayer Raw8 and Raw 10 data input, it also output data as extended 16-bit data format in memory directly. Raw data output should be handled by the second output channel. This patch add supporting for Raw data input/output and the second output channel. All were tested on Cardhu board. Change-Id: Ifd1d8c94671a1d4571dcf176774e2d3cffafc399 Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/200225 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- drivers/media/video/tegra_v4l2_camera.c | 419 +++++++++++++++++++++----------- 1 file changed, 275 insertions(+), 144 deletions(-) diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c index d8db97e34742..a5caef5a1da0 100644 --- a/drivers/media/video/tegra_v4l2_camera.c +++ b/drivers/media/video/tegra_v4l2_camera.c @@ -293,6 +293,8 @@ struct tegra_camera_dev { /* Debug */ int num_frames; + + int output_channel; }; static const struct soc_mbus_pixelfmt tegra_camera_formats[] = { @@ -338,6 +340,23 @@ static const struct soc_mbus_pixelfmt tegra_camera_formats[] = { .packing = SOC_MBUS_PACKING_NONE, .order = SOC_MBUS_ORDER_LE, }, + + /* For RAW8 and RAW10 output, we always output 16-bit (2 bytes). */ + { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .name = "Bayer 8 GRGR.. BGBG..", + .bits_per_sample = 16, + .packing = SOC_MBUS_PACKING_EXTEND16, + .order = SOC_MBUS_ORDER_LE, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG10, + .name = "Bayer 10 GRGR.. BGBG..", + .bits_per_sample = 16, + .packing = SOC_MBUS_PACKING_EXTEND16, + .order = SOC_MBUS_ORDER_LE, + }, + }; static struct tegra_buffer *to_tegra_vb(struct vb2_buffer *vb) @@ -365,29 +384,8 @@ static void tegra_camera_incr_syncpts(struct tegra_camera_dev *pcdev) TEGRA_VI_SYNCPT_VI); } -static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, - int input_format, - int yuv_input_format) +static void tegra_camera_capture_clean(struct tegra_camera_dev *pcdev) { - struct soc_camera_device *icd = pcdev->icd; - int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, - icd->current_fmt->host_fmt); - - TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x02000000); - - TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL, - (yuv_input_format << 8) | - (input_format << 2)); - - TC_VI_REG_WT(pcdev, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000004); - TC_VI_REG_WT(pcdev, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000004); - - /* CSI-A H_ACTIVE and V_ACTIVE */ - TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_H_ACTIVE, - (icd->user_width << 16)); - TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_V_ACTIVE, - (icd->user_height << 16)); - /* CSI A */ TC_VI_REG_WT(pcdev, TEGRA_CSI_VI_INPUT_STREAM_CONTROL, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_HOST_INPUT_STREAM_CONTROL, 0x00000000); @@ -397,22 +395,90 @@ static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_WORD_COUNT, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_GAP, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_B_CONTROL, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL1, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_GAP, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0x00000000); + + TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILA_CONTROL0, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILB_CONTROL0, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_CIL_STATUS, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_CIL_INTERRUPT_MASK, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_READONLY_STATUS, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_ESCAPE_MODE_COMMAND, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_ESCAPE_MODE_DATA, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_PAD_CONFIG0, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_PAD_CONFIG1, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG0, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG1, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_CIL_PAD_CONFIG, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_MIPI_CAL_CONFIG, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_CIL_MIPI_CAL_STATUS, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_CLKEN_OVERRIDE, 0x00000000); - /* pad1s enabled, virtual channel ID 00 */ - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_CONTROL0, - (0x1 << 16) | /* Output 1 pixel per clock */ - (0x1e << 8) | /* If hdr shows wrong fmt, use YUV422 */ - (0x1 << 7) | /* Check header CRC */ - (0x1 << 6) | /* Use word count field in the header */ - (0x1 << 5) | /* Look at data identifier byte in hdr */ - (0x1 << 4)); /* Expect packet header */ + TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_CONTROL, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_COUNTER_0, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_COUNTER_1, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_COUNTER_2, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME, 0x0); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME, 0x0); +} + +static u32 tegra_camera_header_for_wrong_fmt(struct tegra_camera_dev *pcdev) +{ + struct soc_camera_device *icd = pcdev->icd; + const struct soc_camera_format_xlate *current_fmt = icd->current_fmt; + enum v4l2_mbus_pixelcode input_code = current_fmt->code; + u32 hdr; + + switch (input_code) { + case V4L2_MBUS_FMT_UYVY8_2X8: + case V4L2_MBUS_FMT_VYUY8_2X8: + case V4L2_MBUS_FMT_YUYV8_2X8: + case V4L2_MBUS_FMT_YVYU8_2X8: + hdr = 30; + break; + case V4L2_MBUS_FMT_SGRBG8_1X8: + hdr = 42; + break; + case V4L2_MBUS_FMT_SGRBG10_1X10: + hdr = 43; + break; + default: + BUG_ON(1); + } + + return hdr; +} + +static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, + u32 input_control) +{ + struct soc_camera_device *icd = pcdev->icd; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + u32 hdr = tegra_camera_header_for_wrong_fmt(pcdev); + + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x02000000); + + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL, input_control); + + TC_VI_REG_WT(pcdev, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000004); + TC_VI_REG_WT(pcdev, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000004); + + /* CSI-A H_ACTIVE and V_ACTIVE */ + TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_H_ACTIVE, + (icd->user_width << 16)); + TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_V_ACTIVE, + (icd->user_height << 16)); TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_CONTROL1, 0x1); /* Frame # for top field detect for interlaced */ @@ -426,6 +492,15 @@ static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, (0x100 << 4) | /* Wait 0x100 vi clks for timeout */ 0x1); /* Enable line timeout */ + /* pad 0s enabled, virtual channel ID 00 */ + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_CONTROL0, + (0x1 << 16) | /* Output 1 pixel per clock */ + (hdr << 8) | /* If hdr shows wrong fmt, use right value */ + (0x1 << 7) | /* Check header CRC */ + (0x1 << 6) | /* Use word count field in the header */ + (0x1 << 5) | /* Look at data identifier byte in hdr */ + (0x1 << 4)); /* Expect packet header */ + TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_A_CONTROL, (0x3f << 16) | /* Skip packet threshold */ (pcdev->pdata->lanes - 1)); @@ -439,28 +514,22 @@ static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, (0x1 << 8) | /* Enable continuous syncpt */ TEGRA_VI_SYNCPT_CSI); - TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_OUT_1, - (0x1 << 8) | /* Enable continuous syncpt */ - TEGRA_VI_SYNCPT_VI); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00020001); TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0x0000f002); } static void tegra_camera_capture_setup_csi_b(struct tegra_camera_dev *pcdev, - int input_format, - int yuv_input_format) + u32 input_control) { struct soc_camera_device *icd = pcdev->icd; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); + u32 hdr = tegra_camera_header_for_wrong_fmt(pcdev); TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x04000000); - TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL, - (yuv_input_format << 8) | - (input_format << 2)); + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL, input_control); TC_VI_REG_WT(pcdev, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000008); TC_VI_REG_WT(pcdev, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000008); @@ -471,27 +540,10 @@ static void tegra_camera_capture_setup_csi_b(struct tegra_camera_dev *pcdev, TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPB_V_ACTIVE, (icd->user_height << 16)); - /* CSI B */ - TC_VI_REG_WT(pcdev, TEGRA_CSI_VI_INPUT_STREAM_CONTROL, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_HOST_INPUT_STREAM_CONTROL, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_B_CONTROL, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL1, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_GAP, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0x00000000); - - TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG0, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG1, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_CIL_PAD_CONFIG, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_CIL_MIPI_CAL_STATUS, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_CLKEN_OVERRIDE, 0x00000000); - - /* pad1s enabled, virtual channel ID 00 */ + /* pad 0s enabled, virtual channel ID 00 */ TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, (0x1 << 16) | /* Output 1 pixel per clock */ - (0x1e << 8) | /* If hdr shows wrong fmt, use YUV422 */ + (hdr << 8) | /* If hdr shows wrong fmt, use right value */ (0x1 << 7) | /* Check header CRC */ (0x1 << 6) | /* Use word count field in the header */ (0x1 << 5) | /* Look at data identifier byte in hdr */ @@ -523,18 +575,13 @@ static void tegra_camera_capture_setup_csi_b(struct tegra_camera_dev *pcdev, (0x1 << 8) | /* Enable continuous syncpt */ TEGRA_VI_SYNCPT_CSI); - TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_OUT_1, - (0x1 << 8) | /* Enable continuous syncpt */ - TEGRA_VI_SYNCPT_VI); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00010002); TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0x0000f002); } static void tegra_camera_capture_setup_vip(struct tegra_camera_dev *pcdev, - int input_format, - int yuv_input_format) + u32 input_control) { struct soc_camera_device *icd = pcdev->icd; @@ -543,9 +590,8 @@ static void tegra_camera_capture_setup_vip(struct tegra_camera_dev *pcdev, TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL, (1 << 27) | /* field detect */ (1 << 25) | /* hsync/vsync decoded from data (BT.656) */ - (yuv_input_format << 8) | (1 << 1) | /* VIP_INPUT_ENABLE */ - (input_format << 2)); + input_control); TC_VI_REG_WT(pcdev, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000000); @@ -573,60 +619,142 @@ static void tegra_camera_capture_setup_vip(struct tegra_camera_dev *pcdev, TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL, 0x00000004); } -static void tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) +static void tegra_camera_capture_output_channel_setup( + struct tegra_camera_dev *pcdev) { struct soc_camera_device *icd = pcdev->icd; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); const struct soc_camera_format_xlate *current_fmt = icd->current_fmt; - enum v4l2_mbus_pixelcode input_code = current_fmt->code; u32 output_fourcc = current_fmt->host_fmt->fourcc; - int yuv_input_format = 0x0; - int input_format = 0x0; /* Default to YUV422 */ - int yuv_output_format = 0x0; - int output_format = 0x3; /* Default to YUV422 */ + u32 output_format, output_control; int port = pcdev->pdata->port; - int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, - icd->current_fmt->host_fmt); - - switch (input_code) { - case V4L2_MBUS_FMT_UYVY8_2X8: - yuv_input_format = 0x2; - break; - case V4L2_MBUS_FMT_VYUY8_2X8: - yuv_input_format = 0x3; - break; - case V4L2_MBUS_FMT_YUYV8_2X8: - yuv_input_format = 0x0; - break; - case V4L2_MBUS_FMT_YVYU8_2X8: - yuv_input_format = 0x1; - break; - default: - BUG_ON(1); - } switch (output_fourcc) { case V4L2_PIX_FMT_UYVY: - yuv_output_format = 0x0; + output_format = 0x3; /* Default to YUV422 */ break; case V4L2_PIX_FMT_VYUY: - yuv_output_format = 0x1; + output_format = (0x1 << 17) | 0x3; break; case V4L2_PIX_FMT_YUYV: - yuv_output_format = 0x2; + output_format = (0x2 << 17) | 0x3; break; case V4L2_PIX_FMT_YVYU: - yuv_output_format = 0x3; + output_format = (0x3 << 17) | 0x3; break; case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: output_format = 0x6; /* YUV420 planar */ break; + case V4L2_PIX_FMT_SGRBG8: + case V4L2_PIX_FMT_SGRBG10: + /* Use second output channel for RAW8/RAW10 */ + pcdev->output_channel = 1; + + if (port == TEGRA_CAMERA_PORT_CSI_A) + output_format = 0x7; + else if (port == TEGRA_CAMERA_PORT_CSI_B) + output_format = 0x8; + else + output_format = 0x9; + break; default: BUG_ON(1); } + output_control = (pcdev->pdata->flip_v ? (0x1 << 20) : 0) | + (pcdev->pdata->flip_h ? (0x1 << 19) : 0) | + output_format; + + if (pcdev->output_channel == 0) { + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL, + output_control); + + /* + * Set up frame size. Bits 31:16 are the number of lines, and + * bits 15:0 are the number of pixels per line. + */ + TC_VI_REG_WT(pcdev, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE, + (icd->user_height << 16) | icd->user_width); + + /* First output memory enabled */ + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE, 0x00000000); + + /* Set the number of frames in the buffer. */ + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_COUNT_FIRST, 0x00000001); + + /* Set up buffer frame size. */ + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_SIZE_FIRST, + (icd->user_height << 16) | icd->user_width); + + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST, + (icd->user_height * bytes_per_line)); + + TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_OUT_1, + (0x1 << 8) | /* Enable continuous syncpt */ + TEGRA_VI_SYNCPT_VI); + + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE, 0x00000000); + + } else if (pcdev->output_channel == 1) { + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_SECOND_OUTPUT_CONTROL, + output_control); + + TC_VI_REG_WT(pcdev, TEGRA_VI_SECOND_OUTPUT_FRAME_SIZE, + (icd->user_height << 16) | icd->user_width); + + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE_2, 0x00000000); + + /* Set the number of frames in the buffer. */ + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_COUNT_SECOND, 0x00000001); + + /* Set up buffer frame size. */ + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_SIZE_SECOND, + (icd->user_height << 16) | icd->user_width); + + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BUFFER_STRIDE_SECOND, + (icd->user_height * bytes_per_line)); + + TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_OUT_2, + (0x1 << 8) | /* Enable continuous syncpt */ + TEGRA_VI_SYNCPT_VI); + + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE_2, 0x00000000); + } +} + +static void tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) +{ + struct soc_camera_device *icd = pcdev->icd; + const struct soc_camera_format_xlate *current_fmt = icd->current_fmt; + enum v4l2_mbus_pixelcode input_code = current_fmt->code; + u32 input_control = 0x0; + int port = pcdev->pdata->port; + BUG_ON(!tegra_camera_port_is_valid(port)); + switch (input_code) { + case V4L2_MBUS_FMT_UYVY8_2X8: + input_control |= 0x2 << 8; + break; + case V4L2_MBUS_FMT_VYUY8_2X8: + input_control |= 0x3 << 8; + break; + case V4L2_MBUS_FMT_YUYV8_2X8: + input_control |= 0x0; + break; + case V4L2_MBUS_FMT_YVYU8_2X8: + input_control |= 0x1 << 8; + break; + case V4L2_MBUS_FMT_SGRBG8_1X8: + case V4L2_MBUS_FMT_SGRBG10_1X10: + input_control |= 0x2 << 2; /* Input Format = Bayer */ + break; + default: + BUG_ON(1); + } + /* * Set up low pass filter. Use 0x240 for chromaticity and 0x240 * for luminance, which is the default and means not to touch @@ -637,54 +765,25 @@ static void tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) /* Set up raise-on-edge, so we get an interrupt on end of frame. */ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_RAISE, 0x00000001); + /* Cleanup registers */ + tegra_camera_capture_clean(pcdev); + + /* Setup registers for CSI-A, CSI-B and VIP inputs */ if (port == TEGRA_CAMERA_PORT_CSI_A) - tegra_camera_capture_setup_csi_a(pcdev, input_format, - yuv_input_format); + tegra_camera_capture_setup_csi_a(pcdev, input_control); else if (port == TEGRA_CAMERA_PORT_CSI_B) - tegra_camera_capture_setup_csi_b(pcdev, input_format, - yuv_input_format); + tegra_camera_capture_setup_csi_b(pcdev, input_control); else - tegra_camera_capture_setup_vip(pcdev, input_format, - yuv_input_format); - - TC_VI_REG_WT(pcdev, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL, - (pcdev->pdata->flip_v ? (0x1 << 20) : 0) | - (pcdev->pdata->flip_h ? (0x1 << 19) : 0) | - (yuv_output_format << 17) | - output_format); - - /* - * Set up frame size. Bits 31:16 are the number of lines, and - * bits 15:0 are the number of pixels per line. - */ - TC_VI_REG_WT(pcdev, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE, - (icd->user_height << 16) | icd->user_width); - - /* First output memory enabled */ - TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE, 0x00000000); + tegra_camera_capture_setup_vip(pcdev, input_control); - /* Set the number of frames in the buffer. */ - TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_COUNT_FIRST, 0x00000001); - - /* Set up buffer frame size. */ - TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_SIZE_FIRST, - (icd->user_height << 16) | icd->user_width); - - TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST, - (icd->user_height * bytes_per_line)); - - TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE, 0x00000000); + /* Setup registers for output channels */ + tegra_camera_capture_output_channel_setup(pcdev); } -static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, - struct tegra_buffer *buf) +static void tegra_camera_capture_buffer_setup(struct tegra_camera_dev *pcdev, + struct tegra_buffer *buf) { struct soc_camera_device *icd = pcdev->icd; - int port = pcdev->pdata->port; - int err; - - pcdev->syncpt_csi++; - pcdev->syncpt_vi++; switch (icd->current_fmt->host_fmt->fourcc) { case V4L2_PIX_FMT_YUV420: @@ -703,19 +802,41 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_YVYU: - TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_FIRST, - buf->buffer_addr); - TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_FIRST, - buf->start_addr); - - break; + case V4L2_PIX_FMT_SGRBG8: + case V4L2_PIX_FMT_SGRBG10: + /* output 1 */ + if (!pcdev->output_channel) { + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_FIRST, + buf->buffer_addr); + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_FIRST, + buf->start_addr); + /* output 2 */ + } else if (pcdev->output_channel == 1) { + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_SECOND, + buf->buffer_addr); + TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_SECOND, + buf->start_addr); + } + break; default: BUG_ON(1); } +} + +static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, + struct tegra_buffer *buf) +{ + int port = pcdev->pdata->port; + int err; BUG_ON(!tegra_camera_port_is_valid(port)); + pcdev->syncpt_csi++; + pcdev->syncpt_vi++; + + tegra_camera_capture_buffer_setup(pcdev, buf); + if (port == TEGRA_CAMERA_PORT_CSI_A) TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0x0000f005); @@ -817,8 +938,13 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev) u32 cilstatus; dev_err(&pcdev->ndev->dev, "Timeout on VI syncpt\n"); - buffer_addr = TC_VI_REG_RD(pcdev, + + if (!pcdev->output_channel) + buffer_addr = TC_VI_REG_RD(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_FIRST); + else + buffer_addr = TC_VI_REG_RD(pcdev, + TEGRA_VI_VB0_BASE_ADDRESS_SECOND); dev_err(&pcdev->ndev->dev, "buffer_addr = 0x%08x\n", buffer_addr); @@ -997,6 +1123,8 @@ static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev, case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_SGRBG8: + case V4L2_PIX_FMT_SGRBG10: buf->buffer_addr = vb2_dma_nvmap_plane_paddr(&buf->vb, 0); buf->start_addr = buf->buffer_addr; @@ -1292,6 +1420,7 @@ static int tegra_camera_add_device(struct soc_camera_device *icd) pcdev->icd = icd; pcdev->num_frames = 0; + pcdev->output_channel = 0; dev_dbg(icd->parent, "TEGRA Camera host attached to camera %d\n", icd->devnum); @@ -1354,6 +1483,8 @@ static int tegra_camera_get_formats(struct soc_camera_device *icd, case V4L2_MBUS_FMT_VYUY8_2X8: case V4L2_MBUS_FMT_YUYV8_2X8: case V4L2_MBUS_FMT_YVYU8_2X8: + case V4L2_MBUS_FMT_SGRBG8_1X8: + case V4L2_MBUS_FMT_SGRBG10_1X10: formats += ARRAY_SIZE(tegra_camera_formats); for (k = 0; xlate && (k < ARRAY_SIZE(tegra_camera_formats)); @@ -1628,7 +1759,7 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev, return err; exit_cleanup_alloc_ctx: - vb2_dma_nvmap_cleanup_ctx(&ndev->dev); + vb2_dma_nvmap_cleanup_ctx(pcdev->alloc_ctx); exit_put_resources: pm_runtime_disable(&ndev->dev); nvhost_client_device_put_resources(ndev); @@ -1661,7 +1792,7 @@ static int __devexit tegra_camera_remove(struct nvhost_device *ndev) soc_camera_host_unregister(ici); - vb2_dma_nvmap_cleanup_ctx(&ndev->dev); + vb2_dma_nvmap_cleanup_ctx(pcdev->alloc_ctx); pm_runtime_disable(&ndev->dev); -- cgit v1.2.3 From 0ffe70443b9bb259f9ea36a7e29c02c0d9643b07 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Tue, 12 Feb 2013 10:53:29 -0800 Subject: ARM: tegra: cardhu: enable OV5650 sensor Enable OV5650 sensor in Cardhu board file with the help of Tegra V4L2 SoC camera interface. Change-Id: I6ff8456941267c05986760f46f658962a940d07e Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/200226 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- arch/arm/mach-tegra/board-cardhu-sensors.c | 95 ++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c index 08ad0d5fb0fc..83ec4fc2f9cb 100644 --- a/arch/arm/mach-tegra/board-cardhu-sensors.c +++ b/arch/arm/mach-tegra/board-cardhu-sensors.c @@ -44,6 +44,8 @@ #include #include #include +#include +#include #include #include "gpio-names.h" #include "board.h" @@ -60,12 +62,13 @@ #include "board-cardhu.h" #include "cpu-tegra.h" -static struct regulator *cardhu_1v8_cam1 = NULL; -static struct regulator *cardhu_1v8_cam2 = NULL; -static struct regulator *cardhu_1v8_cam3 = NULL; -static struct regulator *cardhu_vdd_2v8_cam1 = NULL; -static struct regulator *cardhu_vdd_2v8_cam2 = NULL; -static struct regulator *cardhu_vdd_cam3 = NULL; +static struct regulator *cardhu_supply_csi; +static struct regulator *cardhu_1v8_cam1; +static struct regulator *cardhu_1v8_cam2; +static struct regulator *cardhu_1v8_cam3; +static struct regulator *cardhu_vdd_2v8_cam1; +static struct regulator *cardhu_vdd_2v8_cam2; +static struct regulator *cardhu_vdd_cam3; static struct board_info board_info; @@ -81,6 +84,51 @@ static struct pca954x_platform_data cardhu_pca954x_data = { .num_modes = ARRAY_SIZE(cardhu_pca954x_modes), }; +/* OV5650 V4L2 device */ +#ifdef CONFIG_SOC_CAMERA_OV5650 +static int cardhu_left_ov5650_power_on(void); +static int cardhu_left_ov5650_power_off(void); + +static int cardhu_ov5650_camera_power_enable(struct nvhost_device *ndev) +{ + return cardhu_left_ov5650_power_on(); +} + +static void cardhu_ov5650_camera_power_disable(struct nvhost_device *ndev) +{ + cardhu_left_ov5650_power_off(); +} + +static struct i2c_board_info cardhu_ov5650_camera_i2c_device = { + I2C_BOARD_INFO("ov5650", 0x36), +}; + +static struct soc_camera_link ov5650_iclink = { + .bus_id = -1, /* This must match the .id of tegra_vi01_device */ + .board_info = &cardhu_ov5650_camera_i2c_device, + .module_name = "ov5650", + .i2c_adapter_id = PCA954x_I2C_BUS0, +}; + +static struct platform_device cardhu_ov5650_soc_camera_device = { + .name = "soc-camera-pdrv", + .id = 0, + .dev = { + .platform_data = &ov5650_iclink, + }, +}; + +static struct tegra_camera_platform_data cardhu_ov5650_camera_platform_data = { + .enable_camera = cardhu_ov5650_camera_power_enable, + .disable_camera = cardhu_ov5650_camera_power_disable, + .flip_v = 0, + .flip_h = 0, + .port = TEGRA_CAMERA_PORT_CSI_A, + .lanes = 2, + .continuous_clk = 1, +}; +#endif + static int cardhu_camera_init(void) { int ret; @@ -135,6 +183,17 @@ static int cardhu_camera_init(void) static int cardhu_left_ov5650_power_on(void) { + + if (cardhu_supply_csi == NULL) { + cardhu_supply_csi = regulator_get(NULL, "avdd_dsi_csi"); + if (WARN_ON(IS_ERR(cardhu_supply_csi))) { + pr_err("%s: couldn't get regulator avdd_dsi_csi: %ld\n", + __func__, PTR_ERR(cardhu_supply_csi)); + goto reg_alloc_fail; + } + } + regulator_enable(cardhu_supply_csi); + /* Boards E1198 and E1291 are of Cardhu personality * and donot have TCA6416 exp for camera */ if ((board_info.board_id == BOARD_E1198) || @@ -192,6 +251,10 @@ reg_alloc_fail: regulator_put(cardhu_vdd_2v8_cam1); cardhu_vdd_2v8_cam1 = NULL; } + if (cardhu_supply_csi) { + regulator_put(cardhu_supply_csi); + cardhu_supply_csi = NULL; + } return -ENODEV; @@ -212,14 +275,18 @@ static int cardhu_left_ov5650_power_off(void) regulator_disable(cardhu_1v8_cam1); if (cardhu_vdd_2v8_cam1) regulator_disable(cardhu_vdd_2v8_cam1); + if (cardhu_supply_csi) + regulator_disable(cardhu_supply_csi); return 0; } +#if defined(CONFIG_VIDEO_OV5650) || defined(CONFIG_VIDEO_OV5650_MODULE) struct ov5650_platform_data cardhu_left_ov5650_data = { .power_on = cardhu_left_ov5650_power_on, .power_off = cardhu_left_ov5650_power_off, }; +#endif #ifdef CONFIG_VIDEO_OV14810 static int cardhu_ov14810_power_on(void) @@ -678,10 +745,12 @@ static const struct i2c_board_info cardhu_i2c_board_info_tps61050[] = { }; static struct i2c_board_info cardhu_i2c6_board_info[] = { +#if defined(CONFIG_VIDEO_OV5650) || defined(CONFIG_VIDEO_OV5650_MODULE) { I2C_BOARD_INFO("ov5650L", 0x36), .platform_data = &cardhu_left_ov5650_data, }, +#endif { I2C_BOARD_INFO("sh532u", 0x72), .platform_data = &sh532u_left_pdata, @@ -693,10 +762,12 @@ static struct i2c_board_info cardhu_i2c6_board_info[] = { }; static struct i2c_board_info cardhu_i2c7_board_info[] = { +#if defined(CONFIG_VIDEO_OV5650) || defined(CONFIG_VIDEO_OV5650_MODULE) { I2C_BOARD_INFO("ov5650R", 0x36), .platform_data = &cardhu_right_ov5650_data, }, +#endif { I2C_BOARD_INFO("sh532u", 0x72), .platform_data = &sh532u_right_pdata, @@ -708,10 +779,12 @@ static struct i2c_board_info cardhu_i2c7_board_info[] = { }; static struct i2c_board_info pm269_i2c6_board_info[] = { +#if defined(CONFIG_VIDEO_OV5650) || defined(CONFIG_VIDEO_OV5650_MODULE) { I2C_BOARD_INFO("ov5650L", 0x36), .platform_data = &cardhu_left_ov5650_data, }, +#endif { I2C_BOARD_INFO("sh532u", 0x72), .platform_data = &pm269_sh532u_left_pdata, @@ -723,10 +796,12 @@ static struct i2c_board_info pm269_i2c6_board_info[] = { }; static struct i2c_board_info pm269_i2c7_board_info[] = { +#if defined(CONFIG_VIDEO_OV5650) || defined(CONFIG_VIDEO_OV5650_MODULE) { I2C_BOARD_INFO("ov5650R", 0x36), .platform_data = &cardhu_right_ov5650_data, }, +#endif { I2C_BOARD_INFO("sh532u", 0x72), .platform_data = &pm269_sh532u_right_pdata, @@ -1133,10 +1208,17 @@ int __init cardhu_sensors_init(void) if (board_info.board_id != BOARD_PM315) mpuirq_init(); + +#ifdef CONFIG_SOC_CAMERA_OV5650 + t30_get_tegra_vi01_device()->dev.platform_data = + &cardhu_ov5650_camera_platform_data; + platform_device_register(&cardhu_ov5650_soc_camera_device); +#endif return 0; } #if defined(CONFIG_GPIO_PCA953X) +#if defined(CONFIG_VIDEO_OV5650) || defined(CONFIG_VIDEO_OV5650_MODULE) struct ov5650_gpios { const char *name; int gpio; @@ -1206,3 +1288,4 @@ fail: late_initcall(cardhu_ov5650_late_init); #endif +#endif -- cgit v1.2.3 From 25b80bc8abcc36fc4053534749faf9d9221a4ebf Mon Sep 17 00:00:00 2001 From: Naveen Kumar S Date: Mon, 31 Dec 2012 20:21:33 +0530 Subject: ARM: Config: Tegra2: Disabled CONFIG_INPUT_MOUSEDEV Disabled CONFIG_INPUT_MOUSEDEV to avoid kernel registering PS/2 mouse devices, which are mostly not in use now. Bug 1162832 Change-Id: If47e654063934d3b60d033a0d2523b8caf97825b Signed-off-by: Naveen Kumar S Reviewed-on: http://git-master/r/187808 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Winnie Hsu Reviewed-by: Laxman Dewangan GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- arch/arm/configs/tegra_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index e7b72881f054..6878abd433f6 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -399,3 +399,4 @@ CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_DEV_TEGRA_AES=y +# CONFIG_INPUT_MOUSEDEV is not set -- cgit v1.2.3 From 00d87897aab16dc387bfbb21f53e8db391e78a78 Mon Sep 17 00:00:00 2001 From: Naveen Kumar S Date: Thu, 7 Mar 2013 12:41:22 +0530 Subject: ARM: Config: Tegra3:Disabled CONFIG_INPUT_MOUSEDEV Disabled CONFIG_INPUT_MOUSEDEV to avoid kernel registering PS/2 mouse devices, which are mostly not in use now. Bug 1162832 Change-Id: I0b44af668fa94ffc589e646a842259afa837731e Signed-off-by: Naveen Kumar S Reviewed-on: http://git-master/r/187807 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- arch/arm/configs/tegra3_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/tegra3_defconfig b/arch/arm/configs/tegra3_defconfig index d8ba44fc373e..2fce137fc291 100644 --- a/arch/arm/configs/tegra3_defconfig +++ b/arch/arm/configs/tegra3_defconfig @@ -467,3 +467,4 @@ CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_DEV_TEGRA_SE=y +# CONFIG_INPUT_MOUSEDEV is not set -- cgit v1.2.3 From f07c2859fab5ca4dc1f833b3879cbbae32ce13fb Mon Sep 17 00:00:00 2001 From: Darbha Sriharsha Date: Thu, 24 Jan 2013 13:04:32 +0530 Subject: arm: tegra: cardhu: additions to cardhu board file This change is intended to add modifications to cardhu board file (which is also used for beaver) to get rid of NACK errors occuring due to the absence of certain hardware components on beaver Bug 1217572 Change-Id: I36dfcda1b133c983ce25d56729505bce8b99fdf1 Signed-off-by: Darbha Sriharsha Reviewed-on: http://git-master/r/193667 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- arch/arm/mach-tegra/board-cardhu-sensors.c | 14 +++++++++----- arch/arm/mach-tegra/board-cardhu.c | 9 +++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c index 83ec4fc2f9cb..59e1fa392801 100644 --- a/arch/arm/mach-tegra/board-cardhu-sensors.c +++ b/arch/arm/mach-tegra/board-cardhu-sensors.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-cardhu-sensors.c * - * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -995,7 +995,8 @@ static const struct i2c_board_info cardhu_i2c2_board_info_tca6416[] = { static int __init pmu_tca6416_init(void) { if ((board_info.board_id == BOARD_E1198) || - (board_info.board_id == BOARD_E1291)) + (board_info.board_id == BOARD_E1291) || + (board_info.board_id == BOARD_PM315)) return 0; pr_info("Registering pmu pca6416\n"); @@ -1009,7 +1010,8 @@ static int __init cam_tca6416_init(void) /* Boards E1198 and E1291 are of Cardhu personality * and donot have TCA6416 exp for camera */ if ((board_info.board_id == BOARD_E1198) || - (board_info.board_id == BOARD_E1291)) + (board_info.board_id == BOARD_E1291) || + (board_info.board_id == BOARD_PM315)) return 0; pr_info("Registering cam pca6416\n"); @@ -1148,8 +1150,10 @@ int __init cardhu_sensors_init(void) cardhu_camera_init(); cam_tca6416_init(); - i2c_register_board_info(2, cardhu_i2c3_board_info, - ARRAY_SIZE(cardhu_i2c3_board_info)); + if (board_info.board_id != BOARD_PM315) { + i2c_register_board_info(2, cardhu_i2c3_board_info, + ARRAY_SIZE(cardhu_i2c3_board_info)); + } i2c_register_board_info(2, cardhu_i2c_board_info_tps61050, ARRAY_SIZE(cardhu_i2c_board_info_tps61050)); diff --git a/arch/arm/mach-tegra/board-cardhu.c b/arch/arm/mach-tegra/board-cardhu.c index 4b03ddc03b7b..b6799dc5bc91 100644 --- a/arch/arm/mach-tegra/board-cardhu.c +++ b/arch/arm/mach-tegra/board-cardhu.c @@ -1,8 +1,8 @@ /* * arch/arm/mach-tegra/board-cardhu.c * - * Copyright (c) 2011-2012, NVIDIA Corporation. All rights reserved. - * Copyright (c) 2011-2012, NVIDIA Corporation. + * Copyright (c) 2011-2013, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2011-2013, NVIDIA Corporation. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1057,6 +1057,11 @@ static int __init cardhu_touch_init(void) struct board_info BoardInfo, DisplayBoardInfo; tegra_get_board_info(&BoardInfo); + + /* Beaver board does not have any touch hardware*/ + if (BoardInfo.board_id == BOARD_PM315) + return 0; + tegra_get_display_board_info(&DisplayBoardInfo); if (DisplayBoardInfo.board_id == BOARD_DISPLAY_PM313) { tegra_clk_init_from_table(spi_clk_init_table); -- cgit v1.2.3 From 0358875560c6a93898708e341461ae62b687d80a Mon Sep 17 00:00:00 2001 From: Ramalingam C Date: Mon, 18 Mar 2013 12:13:00 +0530 Subject: arch: tegra: Ventana: vdd_ldo4 regulator handling Cleaning up of the vdd_ldo4 regulator handling and also control the multiple calls for regulator_get call for vdd_ldo4 Bug 1241274 Change-Id: I0f62d5059212302956bfe7e48d24eb7f45ff2dda Signed-off-by: Ramalingam C Reviewed-on: http://git-master/r/207516 GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- arch/arm/mach-tegra/board-ventana-panel.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-tegra/board-ventana-panel.c b/arch/arm/mach-tegra/board-ventana-panel.c index d2d89392e1c5..d507dea88813 100644 --- a/arch/arm/mach-tegra/board-ventana-panel.c +++ b/arch/arm/mach-tegra/board-ventana-panel.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-ventana-panel.c * - * Copyright (c) 2010-2012 NVIDIA Corporation. + * Copyright (c) 2010-2013 NVIDIA Corporation. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -48,6 +48,7 @@ #define ventana_lvds_to_bl_ms 200 static struct regulator *pnl_pwr; +static struct regulator *vdd_ldo4; #ifdef CONFIG_TEGRA_DC static struct regulator *ventana_hdmi_reg = NULL; @@ -104,11 +105,17 @@ static struct platform_device ventana_backlight_device = { #ifdef CONFIG_TEGRA_DC static int ventana_panel_enable(void) { - struct regulator *reg = regulator_get(NULL, "vdd_ldo4"); - - if (!reg) { - regulator_enable(reg); - regulator_put(reg); + if (vdd_ldo4 == NULL) { + vdd_ldo4 = regulator_get(NULL, "vdd_ldo4"); + + if (IS_ERR(vdd_ldo4)) { + pr_err("%s: couldn't get regulator vdd_ldo4: %ld\n", + __func__, PTR_ERR(vdd_ldo4)); + } else { + regulator_enable(vdd_ldo4); + regulator_disable(vdd_ldo4); + regulator_put(vdd_ldo4); + } } if (pnl_pwr == NULL) { -- cgit v1.2.3 From 32ef1c46e812807ff555b9a8bcf362fc814e14fc Mon Sep 17 00:00:00 2001 From: Darbha Sriharsha Date: Wed, 3 Apr 2013 10:01:59 +0530 Subject: arm: tegra: cardhu: modify cardhu board files This change is intended to add a few modifications to cardhu board file (which is also used for beaver) to get rid of NACK errors occuring due to the absence of certain hardware components on beaver Bug 1217572 Change-Id: I1df7b7f777014610e4d64695d89324808ea4f266 Signed-off-by: Darbha Sriharsha Reviewed-on: http://git-master/r/215983 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro Reviewed-by: Ramalingam C Reviewed-by: Laxman Dewangan --- arch/arm/mach-tegra/board-cardhu-powermon.c | 4 ++-- arch/arm/mach-tegra/board-cardhu-sensors.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-powermon.c b/arch/arm/mach-tegra/board-cardhu-powermon.c index 823cddbabeb3..bffd51b1ea84 100644 --- a/arch/arm/mach-tegra/board-cardhu-powermon.c +++ b/arch/arm/mach-tegra/board-cardhu-powermon.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-cardhu-powermon.c * - * Copyright (c) 2011, NVIDIA, All Rights Reserved. + * Copyright (c) 2011-2013, NVIDIA, 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 as published by @@ -249,7 +249,7 @@ int __init cardhu_pmon_init(void) &power_mon_info[VDD_CORE_IN]; } - if (bi.board_id != BOARD_PM269) { + if (bi.board_id != BOARD_PM269 && bi.board_id != BOARD_PM315) { i2c_register_board_info(0, cardhu_i2c0_ina219_board_info, ARRAY_SIZE(cardhu_i2c0_ina219_board_info)); } diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c index 59e1fa392801..d9c569bf3104 100644 --- a/arch/arm/mach-tegra/board-cardhu-sensors.c +++ b/arch/arm/mach-tegra/board-cardhu-sensors.c @@ -1153,10 +1153,10 @@ int __init cardhu_sensors_init(void) if (board_info.board_id != BOARD_PM315) { i2c_register_board_info(2, cardhu_i2c3_board_info, ARRAY_SIZE(cardhu_i2c3_board_info)); - } - i2c_register_board_info(2, cardhu_i2c_board_info_tps61050, - ARRAY_SIZE(cardhu_i2c_board_info_tps61050)); + i2c_register_board_info(2, cardhu_i2c_board_info_tps61050, + ARRAY_SIZE(cardhu_i2c_board_info_tps61050)); + } #ifdef CONFIG_VIDEO_OV14810 /* This is disabled by default; To enable this change Kconfig; -- cgit v1.2.3 From c75951a17ef41e0cc108f1ced0213bc2620f6534 Mon Sep 17 00:00:00 2001 From: Preetham Chandru R Date: Wed, 15 May 2013 17:01:46 +0530 Subject: perf: Treat attr.config as u64 in perf_swevent_init() Trinity discovered that we fail to check all 64 bits of attr.config passed by user space, resulting to out-of-bounds access of the perf_swevent_enabled array in sw_perf_event_destroy(). Introduced in commit b0a873ebb ("perf: Register PMU implementations"). Bug 1289245 Signed-off-by: Tommi Rantala Signed-off-by: Preetham Chandru R (cherry picked from commit 8176cced706b5e5d15887584150764894e94e02f) Change-Id: Idde0330d7430f2ba1645f4dfed063c5df9bbb44a Reviewed-on: http://git-master/r/228851 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Kiran Adduri Reviewed-by: Bo Yan --- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 0f857782d06f..25a977abe7dd 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5072,7 +5072,7 @@ static void sw_perf_event_destroy(struct perf_event *event) static int perf_swevent_init(struct perf_event *event) { - int event_id = event->attr.config; + u64 event_id = event->attr.config; if (event->attr.type != PERF_TYPE_SOFTWARE) return -ENOENT; -- cgit v1.2.3 From fc90609debf45e79712caabb7668e6f32eb02b69 Mon Sep 17 00:00:00 2001 From: Mursalin Akon Date: Mon, 5 Aug 2013 14:59:38 -0700 Subject: Make firmware loading of R8169 optional According to Realtek, the firmware provides power optimizations. The driver works without the firmware. Plus, there are scenarios where the firmware is not available, which makes the driver wait at request_firmware call (i.e., 60 sec wait). Bug 1236060 Bug 991551 Change-Id: Ifcaa4b2dd48c4111ded33cf2bade7dc1f6422821 Signed-off-by: Mursalin Akon Reviewed-on: http://git-master/r/258353 GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- drivers/net/Kconfig | 27 ++++++++++++++++++--------- drivers/net/r8169.c | 4 ++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 41b279abbd5c..1c3fac524474 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2237,18 +2237,27 @@ config R8169 To compile this driver as a module, choose M here: the module will be called r8169. This is recommended. -config SB1250_MAC - tristate "SB1250 Gigabit Ethernet support" - depends on SIBYTE_SB1xxx_SOC - select PHYLIB +config R8169 + tristate "Realtek 8169 gigabit ethernet support" + depends on PCI + select CRC32 + select MII ---help--- - This driver supports Gigabit Ethernet interfaces based on the - Broadcom SiByte family of System-On-a-Chip parts. They include - the BCM1120, BCM1125, BCM1125H, BCM1250, BCM1255, BCM1280, BCM1455 - and BCM1480 chips. + Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter. To compile this driver as a module, choose M here: the module - will be called sb1250-mac. + will be called r8169. This is recommended. + +config R8169_FW_LOAD + bool "Load firmware for Realtek 8169" + depends on R8169 + select FW_LOADER + default y + ---help--- + This enables runtime loading of optional firmware by the Realtek 8169 + driver. Some environments do not require firmware, or prefer not to delay + the boot process when firmware is not available. Say N here to disable + firmware loading. If unsure, say Y. config SIS190 tristate "SiS190/SiS191 gigabit ethernet support" diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 6d657cabb951..a7ff1005ea64 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1327,7 +1327,11 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp) { +#ifdef CONFIG_R8169_FW_LOAD return rtl_chip_infos[tp->mac_version].fw_name; +#else + return NULL; +#endif } static void rtl8169_get_drvinfo(struct net_device *dev, -- cgit v1.2.3 From 7892df38fdc1c535e625f93c1fef47709e735c68 Mon Sep 17 00:00:00 2001 From: Mursalin Akon Date: Thu, 11 Apr 2013 11:00:35 -0700 Subject: config: tegra3: Turn off R8169 firmware loading The firmware is not being in use currently. So, turn the loading code off. Bug 1236060 Bug 991551 Change-Id: Id41cf762b59502d0ece470e315ac75d93e3b6b39 Signed-off-by: Mursalin Akon Reviewed-on: http://git-master/r/218613 (cherry picked from commit f15976bdfb32d6c5e20057f6d4d57646c15a5591) Reviewed-on: http://git-master/r/258354 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro --- arch/arm/configs/tegra3_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/tegra3_defconfig b/arch/arm/configs/tegra3_defconfig index 2fce137fc291..9f212bbad50b 100644 --- a/arch/arm/configs/tegra3_defconfig +++ b/arch/arm/configs/tegra3_defconfig @@ -226,6 +226,7 @@ CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_R8169=y +# CONFIG_R8169_FW_LOAD is not set # CONFIG_NETDEV_10000 is not set CONFIG_BCM4329=m CONFIG_BCM4329_FIRST_SCAN=y -- cgit v1.2.3 From 6b1f8183c6652ad9f93b4cd5dae1d08fbdac50bc Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Fri, 23 Nov 2012 13:51:59 +0530 Subject: media: video: tegra: sh532u: fix out-of-bounds read fix Coverity issue Coverity id : 13692 Bug 1046331 Bug 1049868 Change-Id: Iefa6d076d4622368534710630b89b9a15d166378 Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/165864 (cherry picked from commit db33c3f3f2447a52a40f4fd001fec9a2932ee4c8) Reviewed-on: http://git-master/r/244637 Reviewed-by: Shreshtha Sahu Tested-by: Shreshtha Sahu Reviewed-by: Kiran Adduri Reviewed-by: Erik Lilliebjerg GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/media/video/tegra/sh532u.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/tegra/sh532u.c b/drivers/media/video/tegra/sh532u.c index e41dd1f4afb1..b9f9b91d5a45 100644 --- a/drivers/media/video/tegra/sh532u.c +++ b/drivers/media/video/tegra/sh532u.c @@ -1,7 +1,7 @@ /* * SH532U focuser driver. * - * Copyright (C) 2011-2012 NVIDIA Corporation. + * Copyright (C) 2011-2013 NVIDIA Corporation. * * 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 @@ -386,7 +386,7 @@ static void sh532u_gpio_exit(struct sh532u_info *info) { unsigned i; - for (i = 0; i <= ARRAY_SIZE(sh532u_gpios); i++) { + for (i = 0; i < ARRAY_SIZE(sh532u_gpios); i++) { if (info->gpio[i].flag && info->gpio[i].own) { gpio_free(info->gpio[i].gpio); info->gpio[i].own = false; -- cgit v1.2.3 From e8b20893e1f9641f5bb3e8e215f84b93420a4a6d Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Tue, 19 Mar 2013 14:13:34 +0530 Subject: ARM: tegra: beaver: updated DVFS table DVFS entry is fixed for Hynix_2GB_H5TC4G83MFR-PBA to support all emc frequencies. Bug 1218885 Change-Id: Id9d578499e495f43db1a072cbcee25a353fa78f5 Signed-off-by: Bibek Basu Reviewed-on: http://git-master/r/210653 (cherry picked from commit 688bf04ff67e2c1ff22762f4f578b925ff3b9f3c) Reviewed-on: http://git-master/r/273530 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Kiran Adduri GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- arch/arm/mach-tegra/board-cardhu-memory.c | 68 +++++++++++++++---------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-memory.c b/arch/arm/mach-tegra/board-cardhu-memory.c index 1ea30fe74a6d..535f9ef75b5a 100644 --- a/arch/arm/mach-tegra/board-cardhu-memory.c +++ b/arch/arm/mach-tegra/board-cardhu-memory.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2011-2013, NVIDIA 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 @@ -30,12 +30,12 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 51000, /* SDRAM frequency */ { 0x00000002, /* EMC_RC */ - 0x0000000d, /* EMC_RFC */ + 0x0000000f, /* EMC_RFC */ 0x00000001, /* EMC_RAS */ 0x00000000, /* EMC_RP */ 0x00000002, /* EMC_R2W */ 0x0000000a, /* EMC_W2R */ - 0x00000003, /* EMC_R2P */ + 0x00000005, /* EMC_R2P */ 0x0000000b, /* EMC_W2P */ 0x00000000, /* EMC_RD_RCD */ 0x00000000, /* EMC_WR_RCD */ @@ -56,8 +56,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x00000000, /* EMC_ACT2PDEN */ 0x00000007, /* EMC_AR2PDEN */ 0x0000000f, /* EMC_RW2PDEN */ - 0x0000000e, /* EMC_TXSR */ - 0x0000000e, /* EMC_TXSRDLL */ + 0x00000010, /* EMC_TXSR */ + 0x00000010, /* EMC_TXSRDLL */ 0x00000004, /* EMC_TCKE */ 0x00000002, /* EMC_TFAW */ 0x00000000, /* EMC_TRPAB */ @@ -117,22 +117,22 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ 0x00010003, /* MC_EMEM_ARB_CFG */ - 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ 0x00000002, /* MC_EMEM_ARB_TIMING_RC */ 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */ 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ - 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */ 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ 0x06020102, /* MC_EMEM_ARB_DA_TURNS */ - 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */ - 0x74630303, /* MC_EMEM_ARB_MISC0 */ + 0x000a0502, /* MC_EMEM_ARB_DA_COVERS */ + 0x74e30303, /* MC_EMEM_ARB_MISC0 */ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ 0xe8000000, /* EMC_FBIO_SPARE */ 0xff00ff00, /* EMC_CFG_RSV */ @@ -150,12 +150,12 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 102000, /* SDRAM frequency */ { 0x00000004, /* EMC_RC */ - 0x0000001a, /* EMC_RFC */ + 0x0000001e, /* EMC_RFC */ 0x00000003, /* EMC_RAS */ 0x00000001, /* EMC_RP */ 0x00000002, /* EMC_R2W */ 0x0000000a, /* EMC_W2R */ - 0x00000003, /* EMC_R2P */ + 0x00000005, /* EMC_R2P */ 0x0000000b, /* EMC_W2P */ 0x00000001, /* EMC_RD_RCD */ 0x00000001, /* EMC_WR_RCD */ @@ -176,8 +176,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x00000000, /* EMC_ACT2PDEN */ 0x00000007, /* EMC_AR2PDEN */ 0x0000000f, /* EMC_RW2PDEN */ - 0x0000001c, /* EMC_TXSR */ - 0x0000001c, /* EMC_TXSRDLL */ + 0x00000020, /* EMC_TXSR */ + 0x00000020, /* EMC_TXSRDLL */ 0x00000004, /* EMC_TCKE */ 0x00000004, /* EMC_TFAW */ 0x00000000, /* EMC_TRPAB */ @@ -236,23 +236,23 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ - 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000003, /* MC_EMEM_ARB_CFG */ + 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ 0x00000003, /* MC_EMEM_ARB_TIMING_RC */ 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */ 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ - 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */ 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ 0x06020102, /* MC_EMEM_ARB_DA_TURNS */ - 0x000a0403, /* MC_EMEM_ARB_DA_COVERS */ - 0x73c30504, /* MC_EMEM_ARB_MISC0 */ + 0x000a0503, /* MC_EMEM_ARB_DA_COVERS */ + 0x74430504, /* MC_EMEM_ARB_MISC0 */ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ 0xe8000000, /* EMC_FBIO_SPARE */ 0xff00ff00, /* EMC_CFG_RSV */ @@ -270,12 +270,12 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 204000, /* SDRAM frequency */ { 0x00000009, /* EMC_RC */ - 0x00000035, /* EMC_RFC */ + 0x0000003d, /* EMC_RFC */ 0x00000007, /* EMC_RAS */ 0x00000002, /* EMC_RP */ 0x00000002, /* EMC_R2W */ 0x0000000a, /* EMC_W2R */ - 0x00000003, /* EMC_R2P */ + 0x00000005, /* EMC_R2P */ 0x0000000b, /* EMC_W2P */ 0x00000002, /* EMC_RD_RCD */ 0x00000002, /* EMC_WR_RCD */ @@ -296,8 +296,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x00000000, /* EMC_ACT2PDEN */ 0x00000007, /* EMC_AR2PDEN */ 0x0000000f, /* EMC_RW2PDEN */ - 0x00000038, /* EMC_TXSR */ - 0x00000038, /* EMC_TXSRDLL */ + 0x00000040, /* EMC_TXSR */ + 0x00000040, /* EMC_TXSRDLL */ 0x00000004, /* EMC_TCKE */ 0x00000007, /* EMC_TFAW */ 0x00000000, /* EMC_TRPAB */ @@ -356,7 +356,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -364,15 +364,15 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x00000002, /* MC_EMEM_ARB_TIMING_RAS */ 0x00000003, /* MC_EMEM_ARB_TIMING_FAW */ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ - 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */ 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ 0x06020102, /* MC_EMEM_ARB_DA_TURNS */ - 0x000a0405, /* MC_EMEM_ARB_DA_COVERS */ - 0x73840a06, /* MC_EMEM_ARB_MISC0 */ + 0x000a0505, /* MC_EMEM_ARB_DA_COVERS */ + 0x74040a06, /* MC_EMEM_ARB_MISC0 */ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ 0xe8000000, /* EMC_FBIO_SPARE */ 0xff00ff00, /* EMC_CFG_RSV */ @@ -390,7 +390,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 400000, /* SDRAM frequency */ { 0x00000012, /* EMC_RC */ - 0x00000066, /* EMC_RFC */ + 0x00000076, /* EMC_RFC */ 0x0000000c, /* EMC_RAS */ 0x00000004, /* EMC_RP */ 0x00000003, /* EMC_R2W */ @@ -416,7 +416,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x00000000, /* EMC_ACT2PDEN */ 0x00000008, /* EMC_AR2PDEN */ 0x0000000f, /* EMC_RW2PDEN */ - 0x0000006c, /* EMC_TXSR */ + 0x0000007c, /* EMC_TXSR */ 0x00000200, /* EMC_TXSRDLL */ 0x00000004, /* EMC_TCKE */ 0x0000000c, /* EMC_TFAW */ @@ -471,13 +471,13 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x00000802, /* EMC_CTT_TERM_CTRL */ 0x00020000, /* EMC_ZCAL_INTERVAL */ 0x00000100, /* EMC_ZCAL_WAIT_CNT */ - 0x0158000c, /* EMC_MRS_WAIT_CNT */ + 0x0148000c, /* EMC_MRS_WAIT_CNT */ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800018c8, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ - 0x80000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000c, /* MC_EMEM_ARB_CFG */ + 0xc0000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -596,8 +596,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000c, /* MC_EMEM_ARB_CFG */ - 0x80000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000018, /* MC_EMEM_ARB_CFG */ + 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */ @@ -624,7 +624,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc4g83mfr[] = { 0x80100002, /* Mode Register 1 */ 0x80200018, /* Mode Register 2 */ 0x00000000, /* EMC_CFG.DYN_SELF_REF */ - } + }, }; static const struct tegra_emc_table cardhu_emc_tables_h5tc2g[] = { -- cgit v1.2.3 From 02f9e545e98b68c134de8a0040130fe9aa8fdd72 Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Fri, 30 Aug 2013 12:20:05 +0530 Subject: ARM: tegra3: initialize pll_a during boot Configure pll_a during boot so that locking to pll_a does not fail Bug 1330751 Change-Id: I188f0be211379f43770b24c5b382dec2788aefda Signed-off-by: Bibek Basu Reviewed-on: http://git-master/r/269469 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Kiran Adduri GVS: Gerrit_Virtual_Submit Reviewed-by: Jong Kim Reviewed-by: Winnie Hsu --- arch/arm/mach-tegra/board-cardhu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-tegra/board-cardhu.c b/arch/arm/mach-tegra/board-cardhu.c index b6799dc5bc91..809dfd2b4970 100644 --- a/arch/arm/mach-tegra/board-cardhu.c +++ b/arch/arm/mach-tegra/board-cardhu.c @@ -218,6 +218,7 @@ static noinline void __init cardhu_setup_bluesleep(void) static __initdata struct tegra_clk_init_table cardhu_clk_init_table[] = { /* name parent rate enabled */ { "pll_m", NULL, 0, false}, + { "pll_a", NULL, 564480000, true}, { "hda", "pll_p", 108000000, false}, { "hda2codec_2x","pll_p", 48000000, false}, { "pwm", "pll_p", 3187500, false}, -- cgit v1.2.3 From 6ff867b97f89fa562ab419a4afd2076d8eaf8a13 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Tue, 23 Apr 2013 15:26:19 -0700 Subject: media: OV5650: tweak registers and add test mode - tweak offset registers - add test mode to output color bars - use BGGR RAW format Bug 1369083 Change-Id: I61352c018f8ca099ff3d39158a67052a1e185eec Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/279983 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Allen Martin Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/media/video/ov5650.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/ov5650.c b/drivers/media/video/ov5650.c index e721065c222b..9b47d66536ef 100644 --- a/drivers/media/video/ov5650.c +++ b/drivers/media/video/ov5650.c @@ -91,6 +91,15 @@ static struct ov5650_reg *test_pattern_modes[] = { tp_checker_seq, }; +enum { + TP_NONE = 1, + TP_COLORBARS = 2, + TP_CHECKER = 3, +}; + +static int test_mode = 2; +module_param(test_mode, int, 0644); + static struct ov5650_reg reset_seq[] = { {0x3008, 0x82}, {OV5650_TABLE_WAIT_MS, 5}, @@ -218,7 +227,7 @@ static struct ov5650_reg mode_1296x972[] = { {0x3800, 0x03}, {0x3801, 0x3c}, {0x3802, 0x00}, - {0x3803, 0x06}, + {0x3803, 0x62}, {0x3804, 0x05}, {0x3805, 0x10}, {0x3806, 0x03}, @@ -454,7 +463,7 @@ static struct ov5650_reg mode_1920x1080[] = { {0x3800, 0x02}, {0x3801, 0x94}, {0x3802, 0x00}, - {0x3803, 0x0c}, + {0x3803, 0x00}, {0x3804, 0x07}, {0x3805, 0x80}, {0x3806, 0x04}, @@ -1092,7 +1101,7 @@ static void ov5650_set_default_fmt(struct ov5650_priv *priv) mf->width = ov5650_frmsizes[OV5650_MODE_2592x1944].width; mf->height = ov5650_frmsizes[OV5650_MODE_2592x1944].height; - mf->code = V4L2_MBUS_FMT_SGRBG10_1X10; + mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; mf->field = V4L2_FIELD_NONE; mf->colorspace = V4L2_COLORSPACE_SRGB; } @@ -1120,6 +1129,21 @@ static int ov5650_s_stream(struct v4l2_subdev *sd, int enable) ret = ov5650_write_table(priv, mode_end, NULL, 0); if (ret) return ret; + + switch (test_mode) { + case TP_NONE: + ret = ov5650_write_table(priv, tp_none_seq, NULL, 0); + break; + case TP_COLORBARS: + ret = ov5650_write_table(priv, tp_cbars_seq, NULL, 0); + break; + case TP_CHECKER: + ret = ov5650_write_table(priv, tp_checker_seq, NULL, 0); + break; + } + if (ret) + return ret; + } else ov5650_set_default_fmt(priv); @@ -1178,9 +1202,9 @@ static int ov5650_try_fmt(struct v4l2_subdev *sd, mf->width = ov5650_frmsizes[mode].width; mf->height = ov5650_frmsizes[mode].height; - if (mf->code != V4L2_MBUS_FMT_SGRBG8_1X8 && - mf->code != V4L2_MBUS_FMT_SGRBG10_1X10) - mf->code = V4L2_MBUS_FMT_SGRBG10_1X10; + if (mf->code != V4L2_MBUS_FMT_SBGGR8_1X8 && + mf->code != V4L2_MBUS_FMT_SBGGR10_1X10) + mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; mf->field = V4L2_FIELD_NONE; mf->colorspace = V4L2_COLORSPACE_SRGB; @@ -1198,10 +1222,10 @@ static int ov5650_enum_fmt(struct v4l2_subdev *sd, unsigned int index, switch (index) { case 0: - *code = V4L2_MBUS_FMT_SGRBG10_1X10; + *code = V4L2_MBUS_FMT_SBGGR10_1X10; break; case 1: - *code = V4L2_MBUS_FMT_SGRBG8_1X8; + *code = V4L2_MBUS_FMT_SBGGR8_1X8; break; } -- cgit v1.2.3 From 15814ccc8a511c57182ba3396a1b16af2c648b14 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Tue, 23 Apr 2013 15:27:40 -0700 Subject: media: videobuf2: fix buffer management issues Use right buffer flag NVMAP_HANDLE_WRITE_COMBINE to allocate buffer, which can be shared by VI/CSI and CPU. Don't use NVMAP_HEAP_SYSMEM. It is validated to old T20 silicon and can't support big buffers. By default, our nvmap_alloc() will use IOVMM to allocate buffers. nvmap_pin() gives us IOVA for hardware engines like VI/CSI module with IOMMU enabled in kernel. nvmap_mmap() gives us VA for CPU read/write operations. So we need to convert VA address to physical address of the buffer and map that buffer to user space processor's memory space "page by page". Bug 1369083 Change-Id: I4629eebe206c7640adf63551968fd89260dd0082 Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/279984 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Allen Martin Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/media/video/videobuf2-dma-nvmap.c | 42 +++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/videobuf2-dma-nvmap.c b/drivers/media/video/videobuf2-dma-nvmap.c index 27f43e5a3a57..5ab3c62ac05b 100644 --- a/drivers/media/video/videobuf2-dma-nvmap.c +++ b/drivers/media/video/videobuf2-dma-nvmap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -54,7 +54,7 @@ static void *vb2_dma_nvmap_alloc(void *alloc_ctx, unsigned long size) } buf->nvmap_ref = nvmap_alloc(conf->nvmap_client, size, 32, - NVMAP_HANDLE_CACHEABLE, NVMAP_HEAP_SYSMEM); + NVMAP_HANDLE_UNCACHEABLE, 0); if (IS_ERR(buf->nvmap_ref)) { dev_err(conf->dev, "nvmap_alloc failed\n"); ret = -ENOMEM; @@ -134,14 +134,42 @@ static unsigned int vb2_dma_nvmap_num_users(void *buf_priv) static int vb2_dma_nvmap_mmap(void *buf_priv, struct vm_area_struct *vma) { struct vb2_dc_buf *buf = buf_priv; + unsigned long vm_start, paddr; + void *vaddr; + int size; + int ret; if (!buf) { - printk(KERN_ERR "No buffer to map\n"); + pr_err("No buffer to map\n"); return -EINVAL; } - return vb2_mmap_pfn_range(vma, buf->paddr, buf->size, - &vb2_common_vm_ops, &buf->handler); + size = min_t(unsigned long, vma->vm_end - vma->vm_start, buf->size); + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + for (vaddr = buf->vaddr; vaddr < buf->vaddr + size; + vaddr += PAGE_SIZE) { + paddr = page_to_phys(vmalloc_to_page(vaddr)); + vm_start = vma->vm_start + (unsigned long) (vaddr - buf->vaddr); + ret = remap_pfn_range(vma, vm_start, paddr >> PAGE_SHIFT, + PAGE_SIZE, vma->vm_page_prot); + if (ret) { + pr_err("Remapping memory failed, error: %d\n", + ret); + return ret; + } + pr_debug("%s: mapped paddr 0x%08lx at 0x%08lx, size %ld\n", + __func__, paddr, vm_start, PAGE_SIZE); + } + + vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; + vma->vm_private_data = &buf->handler; + vma->vm_ops = &vb2_common_vm_ops; + + vma->vm_ops->open(vma); + + return 0; } static void *vb2_dma_nvmap_get_userptr(void *alloc_ctx, unsigned long vaddr, @@ -158,8 +186,8 @@ static void *vb2_dma_nvmap_get_userptr(void *alloc_ctx, unsigned long vaddr, ret = vb2_get_contig_userptr(vaddr, size, &vma, &paddr); if (ret) { - printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n", - vaddr); + pr_err("Failed acquiring VMA for vaddr 0x%08lx\n", + vaddr); kfree(buf); return ERR_PTR(ret); } -- cgit v1.2.3 From 38b37d811fc6f0c705b36b51d74f62673b6c915e Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Tue, 23 Apr 2013 15:28:46 -0700 Subject: media: tegra: use BGGR raw ouput format Bug 1369083 Change-Id: I43acb0d1dd6ca182291895d294a8458bfc99da05 Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/279985 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Allen Martin Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/media/video/tegra_v4l2_camera.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c index a5caef5a1da0..739a56b85f3a 100644 --- a/drivers/media/video/tegra_v4l2_camera.c +++ b/drivers/media/video/tegra_v4l2_camera.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -343,14 +343,14 @@ static const struct soc_mbus_pixelfmt tegra_camera_formats[] = { /* For RAW8 and RAW10 output, we always output 16-bit (2 bytes). */ { - .fourcc = V4L2_PIX_FMT_SGRBG8, + .fourcc = V4L2_PIX_FMT_SBGGR8, .name = "Bayer 8 GRGR.. BGBG..", .bits_per_sample = 16, .packing = SOC_MBUS_PACKING_EXTEND16, .order = SOC_MBUS_ORDER_LE, }, { - .fourcc = V4L2_PIX_FMT_SGRBG10, + .fourcc = V4L2_PIX_FMT_SBGGR10, .name = "Bayer 10 GRGR.. BGBG..", .bits_per_sample = 16, .packing = SOC_MBUS_PACKING_EXTEND16, @@ -446,10 +446,10 @@ static u32 tegra_camera_header_for_wrong_fmt(struct tegra_camera_dev *pcdev) case V4L2_MBUS_FMT_YVYU8_2X8: hdr = 30; break; - case V4L2_MBUS_FMT_SGRBG8_1X8: + case V4L2_MBUS_FMT_SBGGR8_1X8: hdr = 42; break; - case V4L2_MBUS_FMT_SGRBG10_1X10: + case V4L2_MBUS_FMT_SBGGR10_1X10: hdr = 43; break; default: @@ -647,8 +647,8 @@ static void tegra_camera_capture_output_channel_setup( case V4L2_PIX_FMT_YVU420: output_format = 0x6; /* YUV420 planar */ break; - case V4L2_PIX_FMT_SGRBG8: - case V4L2_PIX_FMT_SGRBG10: + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SBGGR10: /* Use second output channel for RAW8/RAW10 */ pcdev->output_channel = 1; @@ -747,8 +747,8 @@ static void tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) case V4L2_MBUS_FMT_YVYU8_2X8: input_control |= 0x1 << 8; break; - case V4L2_MBUS_FMT_SGRBG8_1X8: - case V4L2_MBUS_FMT_SGRBG10_1X10: + case V4L2_MBUS_FMT_SBGGR8_1X8: + case V4L2_MBUS_FMT_SBGGR10_1X10: input_control |= 0x2 << 2; /* Input Format = Bayer */ break; default: @@ -802,8 +802,8 @@ static void tegra_camera_capture_buffer_setup(struct tegra_camera_dev *pcdev, case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_YVYU: - case V4L2_PIX_FMT_SGRBG8: - case V4L2_PIX_FMT_SGRBG10: + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SBGGR10: /* output 1 */ if (!pcdev->output_channel) { TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_FIRST, @@ -1123,8 +1123,8 @@ static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev, case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_YVYU: - case V4L2_PIX_FMT_SGRBG8: - case V4L2_PIX_FMT_SGRBG10: + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SBGGR10: buf->buffer_addr = vb2_dma_nvmap_plane_paddr(&buf->vb, 0); buf->start_addr = buf->buffer_addr; @@ -1483,8 +1483,8 @@ static int tegra_camera_get_formats(struct soc_camera_device *icd, case V4L2_MBUS_FMT_VYUY8_2X8: case V4L2_MBUS_FMT_YUYV8_2X8: case V4L2_MBUS_FMT_YVYU8_2X8: - case V4L2_MBUS_FMT_SGRBG8_1X8: - case V4L2_MBUS_FMT_SGRBG10_1X10: + case V4L2_MBUS_FMT_SBGGR8_1X8: + case V4L2_MBUS_FMT_SBGGR10_1X10: formats += ARRAY_SIZE(tegra_camera_formats); for (k = 0; xlate && (k < ARRAY_SIZE(tegra_camera_formats)); -- cgit v1.2.3 From f2054ae01c96275abdc7c323c8adb03795e11c7d Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Mon, 3 Jun 2013 14:40:25 -0700 Subject: media: tegra_v4l2: pass platform_data via soc_camera_link soc_camera_link supports passing power on/off control callback to soc_camera stack. So the power control can be handled by soc_camera stack instead of our Tegra V4L2 host driver. Also pass other platform_data fields via soc_camera_link instead of a hacking nvhost_device_data struct. Bug 1240806 Bug 1369083 Change-Id: I443a7d28196cc8292805da70d2d5ff1c3cd50a5d Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/246267 (cherry picked from commit 9083d270bf93b583cd5bf5151a52ea250f8541a3) Reviewed-on: http://git-master/r/279986 Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/media/video/tegra_v4l2_camera.c | 84 ++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 18 deletions(-) diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c index 739a56b85f3a..678e765512d4 100644 --- a/drivers/media/video/tegra_v4l2_camera.c +++ b/drivers/media/video/tegra_v4l2_camera.c @@ -960,6 +960,60 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev) return err; } +static void tegra_camera_activate(struct tegra_camera_dev *pcdev) +{ + nvhost_module_busy_ext(pcdev->ndev); + + /* Enable external power */ + regulator_enable(pcdev->reg); + + /* + * Powergating DIS must powergate VE partition. Camera + * module needs to increase the ref-count of disa to + * avoid itself powergated by DIS inadvertently. + */ + tegra_unpowergate_partition(TEGRA_POWERGATE_DISA); + /* Unpowergate VE */ + tegra_unpowergate_partition(TEGRA_POWERGATE_VENC); + + /* Turn on relevant clocks. */ + clk_set_rate(pcdev->clk_vi, 150000000); + clk_prepare_enable(pcdev->clk_vi); + clk_set_rate(pcdev->clk_vi_sensor, 24000000); + clk_prepare_enable(pcdev->clk_vi_sensor); + clk_prepare_enable(pcdev->clk_csi); + clk_prepare_enable(pcdev->clk_isp); + clk_prepare_enable(pcdev->clk_csus); + clk_set_rate(pcdev->clk_sclk, 80000000); + clk_prepare_enable(pcdev->clk_sclk); + clk_set_rate(pcdev->clk_sclk, 375000000); + clk_prepare_enable(pcdev->clk_emc); + + /* Save current syncpt values. */ + tegra_camera_save_syncpts(pcdev); +} + +static void tegra_camera_deactivate(struct tegra_camera_dev *pcdev) +{ + /* Turn off relevant clocks. */ + clk_disable_unprepare(pcdev->clk_vi); + clk_disable_unprepare(pcdev->clk_vi_sensor); + clk_disable_unprepare(pcdev->clk_csi); + clk_disable_unprepare(pcdev->clk_isp); + clk_disable_unprepare(pcdev->clk_csus); + clk_disable_unprepare(pcdev->clk_sclk); + clk_disable_unprepare(pcdev->clk_emc); + + /* Powergate VE */ + tegra_powergate_partition(TEGRA_POWERGATE_VENC); + tegra_powergate_partition(TEGRA_POWERGATE_DISA); + + /* Disable external power */ + regulator_disable(pcdev->reg); + + nvhost_module_idle_ext(pcdev->ndev); +} + static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev) { struct vb2_buffer *vb; @@ -1404,8 +1458,18 @@ static int tegra_camera_add_device(struct soc_camera_device *icd) struct tegra_camera_dev *pcdev = ici->priv; int err; - if (pcdev->icd) - return -EBUSY; + pcdev->pdata = icd->link->priv; + if (!pcdev->pdata) { + dev_err(icd->parent, "No platform data!\n"); + return -EINVAL; + } + + if (!tegra_camera_port_is_valid(pcdev->pdata->port)) { + dev_err(icd->parent, + "Invalid camera port %d in platform data\n", + pcdev->pdata->port); + return -EINVAL; + } pm_runtime_get_sync(ici->v4l2_dev.dev); @@ -1693,12 +1757,6 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev, nvhost_set_drvdata(ndev, pcdev); - if (!tegra_camera_port_is_valid(pcdev->pdata->port)) { - dev_err(&ndev->dev, "Invalid camera port %d in platform data\n", - pcdev->pdata->port); - goto exit_free_pcdev; - } - pcdev->clk_vi = clk_get_sys("tegra_camera", "vi"); if (IS_ERR_OR_NULL(pcdev->clk_vi)) { dev_err(&ndev->dev, "Failed to get vi clock.\n"); @@ -1825,11 +1883,6 @@ static int tegra_camera_suspend(struct nvhost_device *ndev, pm_message_t state) /* Suspend the camera sensor. */ WARN_ON(!pcdev->icd->ops->suspend); pcdev->icd->ops->suspend(pcdev->icd, state); - - /* Power off the camera subsystem. */ - pcdev->pdata->disable_camera(pcdev->ndev); - - nvhost_module_idle_ext(nvhost_get_parent(ndev)); } return 0; @@ -1843,11 +1896,6 @@ static int tegra_camera_resume(struct nvhost_device *ndev) /* We only need to do something if a camera sensor is attached. */ if (pcdev->icd) { - nvhost_module_busy_ext(nvhost_get_parent(ndev)); - - /* Power on the camera subsystem. */ - pcdev->pdata->enable_camera(pcdev->ndev); - /* Resume the camera host. */ tegra_camera_save_syncpts(pcdev); tegra_camera_capture_setup(pcdev); -- cgit v1.2.3 From 83b4fb0e77eb8950e225e62d0193a26af03e307e Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Mon, 24 Jun 2013 14:32:10 -0700 Subject: media: tegra_v4l2: add dual camera support Add support for dual cameras from both CSI-A and CSI-B: - move all the CSI settings into video buffer struct - queue the video buffer struct to a dedicated queue - process one video buffer struct from the queue at one time Bug 1369083 Change-Id: Ie64d69282ab991b66e97327e288a2bacde088bd6 Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/246269 (cherry picked from commit 228b0c2d9ae3fa1121f88836626d654ae0fc4ff0) Reviewed-on: http://git-master/r/279987 Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/media/video/tegra_v4l2_camera.c | 681 ++++++++++++++++---------------- 1 file changed, 338 insertions(+), 343 deletions(-) diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c index 678e765512d4..c96dae1389ff 100644 --- a/drivers/media/video/tegra_v4l2_camera.c +++ b/drivers/media/video/tegra_v4l2_camera.c @@ -14,6 +14,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -22,6 +23,7 @@ #include #include +#include #include #include @@ -45,7 +47,8 @@ /* SYNCPTs 12-17 are reserved for VI. */ #define TEGRA_VI_SYNCPT_VI NVSYNCPT_VI_ISP_2 -#define TEGRA_VI_SYNCPT_CSI NVSYNCPT_VI_ISP_3 +#define TEGRA_VI_SYNCPT_CSI_A NVSYNCPT_VI_ISP_3 +#define TEGRA_VI_SYNCPT_CSI_B NVSYNCPT_VI_ISP_4 /* Tegra CSI-MIPI registers. */ #define TEGRA_VI_OUT_1_INCR_SYNCPT 0x0000 @@ -252,6 +255,8 @@ struct tegra_buffer { struct vb2_buffer vb; /* v4l buffer must be first */ struct list_head queue; + struct soc_camera_device *icd; + int output_channel; /* * Various buffer addresses shadowed so we don't have to recalculate @@ -267,15 +272,17 @@ struct tegra_buffer { struct tegra_camera_dev { struct soc_camera_host ici; - struct soc_camera_device *icd; struct nvhost_device *ndev; - struct tegra_camera_platform_data *pdata; struct clk *clk_vi; struct clk *clk_vi_sensor; struct clk *clk_csi; struct clk *clk_isp; struct clk *clk_csus; + struct clk *clk_sclk; + struct clk *clk_emc; + + struct regulator *reg; void __iomem *vi_base; spinlock_t videobuf_queue_lock; @@ -283,18 +290,19 @@ struct tegra_camera_dev { struct vb2_buffer *active; struct vb2_alloc_ctx *alloc_ctx; enum v4l2_field field; - int sequence; + int sequence_a; + int sequence_b; struct work_struct work; struct mutex work_mutex; u32 syncpt_vi; - u32 syncpt_csi; + u32 syncpt_csi_a; + u32 syncpt_csi_b; /* Debug */ int num_frames; - - int output_channel; + int enable_refcnt; }; static const struct soc_mbus_pixelfmt tegra_camera_formats[] = { @@ -344,14 +352,14 @@ static const struct soc_mbus_pixelfmt tegra_camera_formats[] = { /* For RAW8 and RAW10 output, we always output 16-bit (2 bytes). */ { .fourcc = V4L2_PIX_FMT_SBGGR8, - .name = "Bayer 8 GRGR.. BGBG..", + .name = "Bayer 8 BGBG.. GRGR..", .bits_per_sample = 16, .packing = SOC_MBUS_PACKING_EXTEND16, .order = SOC_MBUS_ORDER_LE, }, { .fourcc = V4L2_PIX_FMT_SBGGR10, - .name = "Bayer 10 GRGR.. BGBG..", + .name = "Bayer 10 BGBG.. GRGR..", .bits_per_sample = 16, .packing = SOC_MBUS_PACKING_EXTEND16, .order = SOC_MBUS_ORDER_LE, @@ -366,9 +374,13 @@ static struct tegra_buffer *to_tegra_vb(struct vb2_buffer *vb) static void tegra_camera_save_syncpts(struct tegra_camera_dev *pcdev) { - pcdev->syncpt_csi = + pcdev->syncpt_csi_a = nvhost_syncpt_read_ext(pcdev->ndev, - TEGRA_VI_SYNCPT_CSI); + TEGRA_VI_SYNCPT_CSI_A); + + pcdev->syncpt_csi_b = + nvhost_syncpt_read_ext(pcdev->ndev, + TEGRA_VI_SYNCPT_CSI_B); pcdev->syncpt_vi = nvhost_syncpt_read_ext(pcdev->ndev, @@ -378,7 +390,10 @@ static void tegra_camera_save_syncpts(struct tegra_camera_dev *pcdev) static void tegra_camera_incr_syncpts(struct tegra_camera_dev *pcdev) { nvhost_syncpt_cpu_incr_ext(pcdev->ndev, - TEGRA_VI_SYNCPT_CSI); + TEGRA_VI_SYNCPT_CSI_A); + + nvhost_syncpt_cpu_incr_ext(pcdev->ndev, + TEGRA_VI_SYNCPT_CSI_B); nvhost_syncpt_cpu_incr_ext(pcdev->ndev, TEGRA_VI_SYNCPT_VI); @@ -386,25 +401,9 @@ static void tegra_camera_incr_syncpts(struct tegra_camera_dev *pcdev) static void tegra_camera_capture_clean(struct tegra_camera_dev *pcdev) { - /* CSI A */ TC_VI_REG_WT(pcdev, TEGRA_CSI_VI_INPUT_STREAM_CONTROL, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_HOST_INPUT_STREAM_CONTROL, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_A_CONTROL, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_CONTROL0, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_CONTROL1, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_WORD_COUNT, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_GAP, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_B_CONTROL, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL1, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_GAP, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILA_CONTROL0, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILB_CONTROL0, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS, 0x0); TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_CIL_STATUS, 0x0); TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK, 0x0); @@ -413,14 +412,7 @@ static void tegra_camera_capture_clean(struct tegra_camera_dev *pcdev) TC_VI_REG_WT(pcdev, TEGRA_CSI_ESCAPE_MODE_COMMAND, 0x0); TC_VI_REG_WT(pcdev, TEGRA_CSI_ESCAPE_MODE_DATA, 0x0); - - TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_PAD_CONFIG0, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_PAD_CONFIG1, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG0, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG1, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_CIL_PAD_CONFIG, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_MIPI_CAL_CONFIG, 0x00000000); - TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_CIL_MIPI_CAL_STATUS, 0x00000000); TC_VI_REG_WT(pcdev, TEGRA_CSI_CLKEN_OVERRIDE, 0x00000000); @@ -428,51 +420,29 @@ static void tegra_camera_capture_clean(struct tegra_camera_dev *pcdev) TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_COUNTER_0, 0x0); TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_COUNTER_1, 0x0); TC_VI_REG_WT(pcdev, TEGRA_CSI_DEBUG_COUNTER_2, 0x0); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME, 0x0); - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME, 0x0); -} - -static u32 tegra_camera_header_for_wrong_fmt(struct tegra_camera_dev *pcdev) -{ - struct soc_camera_device *icd = pcdev->icd; - const struct soc_camera_format_xlate *current_fmt = icd->current_fmt; - enum v4l2_mbus_pixelcode input_code = current_fmt->code; - u32 hdr; - - switch (input_code) { - case V4L2_MBUS_FMT_UYVY8_2X8: - case V4L2_MBUS_FMT_VYUY8_2X8: - case V4L2_MBUS_FMT_YUYV8_2X8: - case V4L2_MBUS_FMT_YVYU8_2X8: - hdr = 30; - break; - case V4L2_MBUS_FMT_SBGGR8_1X8: - hdr = 42; - break; - case V4L2_MBUS_FMT_SBGGR10_1X10: - hdr = 43; - break; - default: - BUG_ON(1); - } - - return hdr; } static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, - u32 input_control) + struct soc_camera_device *icd, + u32 hdr) { - struct soc_camera_device *icd = pcdev->icd; + struct tegra_camera_platform_data *pdata = icd->link->priv; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); - u32 hdr = tegra_camera_header_for_wrong_fmt(pcdev); - TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x02000000); - - TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL, input_control); + TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_A_CONTROL, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_CONTROL0, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_CONTROL1, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_WORD_COUNT, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_GAP, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILA_CONTROL0, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_PAD_CONFIG0, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_PAD_CONFIG1, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_MIPI_CAL_CONFIG, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME, 0x0); - TC_VI_REG_WT(pcdev, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000004); - TC_VI_REG_WT(pcdev, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000004); + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x02000000); /* CSI-A H_ACTIVE and V_ACTIVE */ TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPA_H_ACTIVE, @@ -503,16 +473,16 @@ static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_A_CONTROL, (0x3f << 16) | /* Skip packet threshold */ - (pcdev->pdata->lanes - 1)); + (pdata->lanes - 1)); /* Use 0x00000022 for continuous clock mode. */ TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILA_CONTROL0, - (pcdev->pdata->continuous_clk << 5) | + (pdata->continuous_clk << 5) | 0x5); /* Clock settle time */ TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_END, (0x1 << 8) | /* Enable continuous syncpt */ - TEGRA_VI_SYNCPT_CSI); + TEGRA_VI_SYNCPT_CSI_A); TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00020001); @@ -520,19 +490,26 @@ static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, } static void tegra_camera_capture_setup_csi_b(struct tegra_camera_dev *pcdev, - u32 input_control) + struct soc_camera_device *icd, + u32 hdr) { - struct soc_camera_device *icd = pcdev->icd; + struct tegra_camera_platform_data *pdata = icd->link->priv; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); - u32 hdr = tegra_camera_header_for_wrong_fmt(pcdev); - - TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x04000000); - TC_VI_REG_WT(pcdev, TEGRA_VI_VI_INPUT_CONTROL, input_control); + TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_B_CONTROL, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_CONTROL1, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_GAP, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILB_CONTROL0, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG0, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_PAD_CONFIG1, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, 0x00000000); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME, 0x0); - TC_VI_REG_WT(pcdev, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000008); - TC_VI_REG_WT(pcdev, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000008); + TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x04000000); /* CSI-B H_ACTIVE and V_ACTIVE */ TC_VI_REG_WT(pcdev, TEGRA_VI_CSI_PPB_H_ACTIVE, @@ -564,16 +541,16 @@ static void tegra_camera_capture_setup_csi_b(struct tegra_camera_dev *pcdev, TC_VI_REG_WT(pcdev, TEGRA_CSI_INPUT_STREAM_B_CONTROL, (0x3f << 16) | /* Skip packet threshold */ - (pcdev->pdata->lanes - 1)); + (pdata->lanes - 1)); /* Use 0x00000022 for continuous clock mode. */ TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CILB_CONTROL0, - (pcdev->pdata->continuous_clk << 5) | + (pdata->continuous_clk << 5) | 0x5); /* Clock settle time */ TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_END, (0x1 << 8) | /* Enable continuous syncpt */ - TEGRA_VI_SYNCPT_CSI); + TEGRA_VI_SYNCPT_CSI_B); TC_VI_REG_WT(pcdev, TEGRA_CSI_PHY_CIL_COMMAND, 0x00010002); @@ -581,9 +558,9 @@ static void tegra_camera_capture_setup_csi_b(struct tegra_camera_dev *pcdev, } static void tegra_camera_capture_setup_vip(struct tegra_camera_dev *pcdev, - u32 input_control) + struct soc_camera_device *icd, + u32 input_control) { - struct soc_camera_device *icd = pcdev->icd; TC_VI_REG_WT(pcdev, TEGRA_VI_VI_CORE_CONTROL, 0x00000000); @@ -619,16 +596,18 @@ static void tegra_camera_capture_setup_vip(struct tegra_camera_dev *pcdev, TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL, 0x00000004); } -static void tegra_camera_capture_output_channel_setup( - struct tegra_camera_dev *pcdev) +static int tegra_camera_capture_output_channel_setup( + struct tegra_camera_dev *pcdev, + struct soc_camera_device *icd) { - struct soc_camera_device *icd = pcdev->icd; + struct tegra_camera_platform_data *pdata = icd->link->priv; + int port = pdata->port; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); const struct soc_camera_format_xlate *current_fmt = icd->current_fmt; u32 output_fourcc = current_fmt->host_fmt->fourcc; u32 output_format, output_control; - int port = pcdev->pdata->port; + struct tegra_buffer *buf = to_tegra_vb(pcdev->active); switch (output_fourcc) { case V4L2_PIX_FMT_UYVY: @@ -650,7 +629,7 @@ static void tegra_camera_capture_output_channel_setup( case V4L2_PIX_FMT_SBGGR8: case V4L2_PIX_FMT_SBGGR10: /* Use second output channel for RAW8/RAW10 */ - pcdev->output_channel = 1; + buf->output_channel = 1; if (port == TEGRA_CAMERA_PORT_CSI_A) output_format = 0x7; @@ -660,17 +639,18 @@ static void tegra_camera_capture_output_channel_setup( output_format = 0x9; break; default: - BUG_ON(1); + dev_err(&pcdev->ndev->dev, "Wrong output format %d\n", + output_fourcc); + return -EINVAL; } - output_control = (pcdev->pdata->flip_v ? (0x1 << 20) : 0) | - (pcdev->pdata->flip_h ? (0x1 << 19) : 0) | + output_control = (pdata->flip_v ? (0x1 << 20) : 0) | + (pdata->flip_h ? (0x1 << 19) : 0) | output_format; - if (pcdev->output_channel == 0) { + if (buf->output_channel == 0) { TC_VI_REG_WT(pcdev, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL, output_control); - /* * Set up frame size. Bits 31:16 are the number of lines, and * bits 15:0 are the number of pixels per line. @@ -696,8 +676,7 @@ static void tegra_camera_capture_output_channel_setup( TEGRA_VI_SYNCPT_VI); TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE, 0x00000000); - - } else if (pcdev->output_channel == 1) { + } else if (buf->output_channel == 1) { TC_VI_REG_WT(pcdev, TEGRA_VI_VI_SECOND_OUTPUT_CONTROL, output_control); @@ -721,38 +700,55 @@ static void tegra_camera_capture_output_channel_setup( TEGRA_VI_SYNCPT_VI); TC_VI_REG_WT(pcdev, TEGRA_VI_VI_ENABLE_2, 0x00000000); + } else { + dev_err(&pcdev->ndev->dev, "Wrong output channel %d\n", + buf->output_channel); + return -EINVAL; } + + return 0; } -static void tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) +static int tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) { - struct soc_camera_device *icd = pcdev->icd; + struct vb2_buffer *vb = pcdev->active; + struct tegra_buffer *buf = to_tegra_vb(vb); + struct soc_camera_device *icd = buf->icd; + struct tegra_camera_platform_data *pdata = icd->link->priv; + int port = pdata->port; const struct soc_camera_format_xlate *current_fmt = icd->current_fmt; enum v4l2_mbus_pixelcode input_code = current_fmt->code; - u32 input_control = 0x0; - int port = pcdev->pdata->port; - - BUG_ON(!tegra_camera_port_is_valid(port)); + u32 hdr, input_control = 0x0; switch (input_code) { case V4L2_MBUS_FMT_UYVY8_2X8: input_control |= 0x2 << 8; + hdr = 30; break; case V4L2_MBUS_FMT_VYUY8_2X8: input_control |= 0x3 << 8; + hdr = 30; break; case V4L2_MBUS_FMT_YUYV8_2X8: input_control |= 0x0; + hdr = 30; break; case V4L2_MBUS_FMT_YVYU8_2X8: input_control |= 0x1 << 8; + hdr = 30; break; case V4L2_MBUS_FMT_SBGGR8_1X8: + input_control |= 0x2 << 2; /* Input Format = Bayer */ + hdr = 42; + break; case V4L2_MBUS_FMT_SBGGR10_1X10: input_control |= 0x2 << 2; /* Input Format = Bayer */ + hdr = 43; break; default: - BUG_ON(1); + dev_err(&pcdev->ndev->dev, "Input format %d is not supported\n", + input_code); + return -EINVAL; } /* @@ -770,20 +766,20 @@ static void tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) /* Setup registers for CSI-A, CSI-B and VIP inputs */ if (port == TEGRA_CAMERA_PORT_CSI_A) - tegra_camera_capture_setup_csi_a(pcdev, input_control); + tegra_camera_capture_setup_csi_a(pcdev, icd, hdr); else if (port == TEGRA_CAMERA_PORT_CSI_B) - tegra_camera_capture_setup_csi_b(pcdev, input_control); + tegra_camera_capture_setup_csi_b(pcdev, icd, hdr); else - tegra_camera_capture_setup_vip(pcdev, input_control); + tegra_camera_capture_setup_vip(pcdev, icd, input_control); /* Setup registers for output channels */ - tegra_camera_capture_output_channel_setup(pcdev); + return tegra_camera_capture_output_channel_setup(pcdev, icd); } -static void tegra_camera_capture_buffer_setup(struct tegra_camera_dev *pcdev, +static int tegra_camera_capture_buffer_setup(struct tegra_camera_dev *pcdev, struct tegra_buffer *buf) { - struct soc_camera_device *icd = pcdev->icd; + struct soc_camera_device *icd = buf->icd; switch (icd->current_fmt->host_fmt->fourcc) { case V4L2_PIX_FMT_YUV420: @@ -805,64 +801,76 @@ static void tegra_camera_capture_buffer_setup(struct tegra_camera_dev *pcdev, case V4L2_PIX_FMT_SBGGR8: case V4L2_PIX_FMT_SBGGR10: /* output 1 */ - if (!pcdev->output_channel) { + if (buf->output_channel == 0) { TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_FIRST, buf->buffer_addr); TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_FIRST, buf->start_addr); /* output 2 */ - } else if (pcdev->output_channel == 1) { + } else if (buf->output_channel == 1) { TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_SECOND, buf->buffer_addr); TC_VI_REG_WT(pcdev, TEGRA_VI_VB0_START_ADDRESS_SECOND, buf->start_addr); + } else { + dev_err(&pcdev->ndev->dev, "Wrong output channel %d\n", + buf->output_channel); + return -EINVAL; } break; default: - BUG_ON(1); + dev_err(&pcdev->ndev->dev, "Wrong host format %d\n", + icd->current_fmt->host_fmt->fourcc); + return -EINVAL; } + + return 0; } static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, struct tegra_buffer *buf) { - int port = pcdev->pdata->port; + struct soc_camera_device *icd = buf->icd; + struct tegra_camera_platform_data *pdata = icd->link->priv; + int port = pdata->port; int err; - BUG_ON(!tegra_camera_port_is_valid(port)); - - pcdev->syncpt_csi++; - pcdev->syncpt_vi++; - - tegra_camera_capture_buffer_setup(pcdev, buf); - - if (port == TEGRA_CAMERA_PORT_CSI_A) - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, - 0x0000f005); - else if (port == TEGRA_CAMERA_PORT_CSI_B) - TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, - 0x0000f005); - else - TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL, - 0x00000001); - + err = tegra_camera_capture_buffer_setup(pcdev, buf); + if (err < 0) + return err; /* * Only wait on CSI frame end syncpt if we're using CSI. Otherwise, * wait on VIP VSYNC syncpt. */ - if (tegra_camera_port_is_csi(port)) + if (port == TEGRA_CAMERA_PORT_CSI_A) { + pcdev->syncpt_csi_a++; + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, + 0x0000f005); err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev, - TEGRA_VI_SYNCPT_CSI, - pcdev->syncpt_csi, - TEGRA_SYNCPT_CSI_WAIT_TIMEOUT, - NULL); - else + TEGRA_VI_SYNCPT_CSI_A, + pcdev->syncpt_csi_a, + TEGRA_SYNCPT_CSI_WAIT_TIMEOUT, + NULL); + } else if (port == TEGRA_CAMERA_PORT_CSI_B) { + pcdev->syncpt_csi_b++; + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, + 0x0000f005); err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev, - TEGRA_VI_SYNCPT_VI, - pcdev->syncpt_csi, - TEGRA_SYNCPT_VI_WAIT_TIMEOUT, - NULL); + TEGRA_VI_SYNCPT_CSI_B, + pcdev->syncpt_csi_b, + TEGRA_SYNCPT_CSI_WAIT_TIMEOUT, + NULL); + } else { + pcdev->syncpt_vi++; + TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL, + 0x00000001); + err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev, + TEGRA_VI_SYNCPT_VI, + pcdev->syncpt_csi_a, + TEGRA_SYNCPT_VI_WAIT_TIMEOUT, + NULL); + } if (!err) return 0; @@ -872,8 +880,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, u32 cilstatus; u32 rostatus; - dev_err(&pcdev->ndev->dev, "Timeout on CSI syncpt\n"); - dev_err(&pcdev->ndev->dev, "buffer_addr = 0x%08x\n", + dev_warn(&icd->vdev->dev, "Timeout on CSI syncpt\n"); + dev_warn(&icd->vdev->dev, "buffer_addr = 0x%08x\n", buf->buffer_addr); ppstatus = TC_VI_REG_RD(pcdev, @@ -883,7 +891,7 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, rostatus = TC_VI_REG_RD(pcdev, TEGRA_CSI_CSI_READONLY_STATUS); - dev_err(&pcdev->ndev->dev, + dev_warn(&icd->vdev->dev, "PPSTATUS = 0x%08x, " "CILSTATUS = 0x%08x, " "ROSTATUS = 0x%08x\n", @@ -891,14 +899,14 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, } else { u32 vip_input_status; - dev_err(&pcdev->ndev->dev, "Timeout on VI syncpt\n"); - dev_err(&pcdev->ndev->dev, "buffer_addr = 0x%08x\n", + dev_warn(&pcdev->ndev->dev, "Timeout on VI syncpt\n"); + dev_warn(&pcdev->ndev->dev, "buffer_addr = 0x%08x\n", buf->buffer_addr); vip_input_status = TC_VI_REG_RD(pcdev, TEGRA_VI_VIP_INPUT_STATUS); - dev_err(&pcdev->ndev->dev, + dev_warn(&pcdev->ndev->dev, "VIP_INPUT_STATUS = 0x%08x\n", vip_input_status); } @@ -906,12 +914,10 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, return err; } -static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev) +static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev, int port) { - int port = pcdev->pdata->port; int err; - - BUG_ON(!tegra_camera_port_is_valid(port)); + struct tegra_buffer *buf = to_tegra_vb(pcdev->active); if (port == TEGRA_CAMERA_PORT_CSI_A) TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, @@ -937,22 +943,28 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev) u32 ppstatus; u32 cilstatus; - dev_err(&pcdev->ndev->dev, "Timeout on VI syncpt\n"); + dev_warn(&pcdev->ndev->dev, "Timeout on VI syncpt\n"); - if (!pcdev->output_channel) + if (buf->output_channel == 0) buffer_addr = TC_VI_REG_RD(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_FIRST); - else + else if (buf->output_channel == 1) buffer_addr = TC_VI_REG_RD(pcdev, TEGRA_VI_VB0_BASE_ADDRESS_SECOND); - dev_err(&pcdev->ndev->dev, "buffer_addr = 0x%08x\n", + else { + dev_err(&pcdev->ndev->dev, "Wrong output channel %d\n", + buf->output_channel); + return -EINVAL; + } + + dev_warn(&pcdev->ndev->dev, "buffer_addr = 0x%08x\n", buffer_addr); ppstatus = TC_VI_REG_RD(pcdev, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS); cilstatus = TC_VI_REG_RD(pcdev, TEGRA_CSI_CSI_CIL_STATUS); - dev_err(&pcdev->ndev->dev, + dev_warn(&pcdev->ndev->dev, "PPSTATUS = 0x%08x, CILSTATUS = 0x%08x\n", ppstatus, cilstatus); } @@ -962,32 +974,26 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev) static void tegra_camera_activate(struct tegra_camera_dev *pcdev) { - nvhost_module_busy_ext(pcdev->ndev); + nvhost_module_busy_ext(pcdev->ndev); /* Enable external power */ regulator_enable(pcdev->reg); - /* - * Powergating DIS must powergate VE partition. Camera - * module needs to increase the ref-count of disa to - * avoid itself powergated by DIS inadvertently. - */ - tegra_unpowergate_partition(TEGRA_POWERGATE_DISA); /* Unpowergate VE */ tegra_unpowergate_partition(TEGRA_POWERGATE_VENC); /* Turn on relevant clocks. */ clk_set_rate(pcdev->clk_vi, 150000000); - clk_prepare_enable(pcdev->clk_vi); + clk_enable(pcdev->clk_vi); clk_set_rate(pcdev->clk_vi_sensor, 24000000); - clk_prepare_enable(pcdev->clk_vi_sensor); - clk_prepare_enable(pcdev->clk_csi); - clk_prepare_enable(pcdev->clk_isp); - clk_prepare_enable(pcdev->clk_csus); + clk_enable(pcdev->clk_vi_sensor); + clk_enable(pcdev->clk_csi); + clk_enable(pcdev->clk_isp); + clk_enable(pcdev->clk_csus); clk_set_rate(pcdev->clk_sclk, 80000000); - clk_prepare_enable(pcdev->clk_sclk); + clk_enable(pcdev->clk_sclk); clk_set_rate(pcdev->clk_sclk, 375000000); - clk_prepare_enable(pcdev->clk_emc); + clk_enable(pcdev->clk_emc); /* Save current syncpt values. */ tegra_camera_save_syncpts(pcdev); @@ -996,17 +1002,16 @@ static void tegra_camera_activate(struct tegra_camera_dev *pcdev) static void tegra_camera_deactivate(struct tegra_camera_dev *pcdev) { /* Turn off relevant clocks. */ - clk_disable_unprepare(pcdev->clk_vi); - clk_disable_unprepare(pcdev->clk_vi_sensor); - clk_disable_unprepare(pcdev->clk_csi); - clk_disable_unprepare(pcdev->clk_isp); - clk_disable_unprepare(pcdev->clk_csus); - clk_disable_unprepare(pcdev->clk_sclk); - clk_disable_unprepare(pcdev->clk_emc); + clk_disable(pcdev->clk_vi); + clk_disable(pcdev->clk_vi_sensor); + clk_disable(pcdev->clk_csi); + clk_disable(pcdev->clk_isp); + clk_disable(pcdev->clk_csus); + clk_disable(pcdev->clk_sclk); + clk_disable(pcdev->clk_emc); /* Powergate VE */ tegra_powergate_partition(TEGRA_POWERGATE_VENC); - tegra_powergate_partition(TEGRA_POWERGATE_DISA); /* Disable external power */ regulator_disable(pcdev->reg); @@ -1016,24 +1021,21 @@ static void tegra_camera_deactivate(struct tegra_camera_dev *pcdev) static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev) { - struct vb2_buffer *vb; - struct tegra_buffer *buf; + struct vb2_buffer *vb = pcdev->active; + struct tegra_buffer *buf = to_tegra_vb(vb); + struct soc_camera_device *icd = buf->icd; + struct tegra_camera_platform_data *pdata = icd->link->priv; + int port = pdata->port; int retry = TEGRA_SYNCPT_RETRY_COUNT; - int port = pcdev->pdata->port; int err; - if (!pcdev->active) - return 0; - - vb = pcdev->active; - buf = to_tegra_vb(vb); - while (retry) { err = tegra_camera_capture_start(pcdev, buf); + /* Capturing succeed, stop capturing */ if (!err) - err = tegra_camera_capture_stop(pcdev); - - if (err != 0) { + err = tegra_camera_capture_stop(pcdev, port); + /* Capturing failed, stop and retry */ + else { retry--; /* Stop streaming. */ @@ -1065,7 +1067,6 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev) 0x00000005); } - tegra_camera_incr_syncpts(pcdev); tegra_camera_save_syncpts(pcdev); @@ -1075,26 +1076,26 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev) break; } - spin_lock_irq(&pcdev->videobuf_queue_lock); - - /* - * If vb->state is VB2_BUF_STATE_ERROR, then the vb has already been - * removed, so we shouldn't remove it again. - */ - if (vb->state != VB2_BUF_STATE_ERROR) - list_del_init(&buf->queue); + /* Reset hardware for too many errors */ + if (!retry) { + tegra_camera_deactivate(pcdev); + mdelay(5); + tegra_camera_activate(pcdev); + if (pcdev->active) + tegra_camera_capture_setup(pcdev); + } - if (!list_empty(&pcdev->capture)) - pcdev->active = &list_entry(pcdev->capture.next, - struct tegra_buffer, queue)->vb; - else - pcdev->active = NULL; + spin_lock_irq(&pcdev->videobuf_queue_lock); do_gettimeofday(&vb->v4l2_buf.timestamp); vb->v4l2_buf.field = pcdev->field; - vb->v4l2_buf.sequence = pcdev->sequence++; + if (port == TEGRA_CAMERA_PORT_CSI_A) + vb->v4l2_buf.sequence = pcdev->sequence_a++; + else if (port == TEGRA_CAMERA_PORT_CSI_B) + vb->v4l2_buf.sequence = pcdev->sequence_b++; vb2_buffer_done(vb, err < 0 ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); + list_del_init(&buf->queue); pcdev->num_frames++; @@ -1107,70 +1108,37 @@ static void tegra_camera_work(struct work_struct *work) { struct tegra_camera_dev *pcdev = container_of(work, struct tegra_camera_dev, work); + struct tegra_buffer *buf; - mutex_lock(&pcdev->work_mutex); - - while (pcdev->active) - tegra_camera_capture_frame(pcdev); - - mutex_unlock(&pcdev->work_mutex); -} - -static void tegra_camera_activate(struct tegra_camera_dev *pcdev) -{ -#ifdef CONFIG_ARCH_TEGRA_2x_SOC - u32 val; - void __iomem *apb_misc; -#endif - - nvhost_module_busy_ext(pcdev->ndev); + while (1) { + mutex_lock(&pcdev->work_mutex); - /* Turn on relevant clocks. */ - clk_enable(pcdev->clk_vi); - clk_enable(pcdev->clk_vi_sensor); - clk_enable(pcdev->clk_csi); - clk_enable(pcdev->clk_isp); - clk_enable(pcdev->clk_csus); - -#ifdef CONFIG_ARCH_TEGRA_2x_SOC - apb_misc = IO_ADDRESS(TEGRA_APB_MISC_BASE); - val = readl(apb_misc + 0x42c); - writel(val | 0x1, apb_misc + 0x42c); -#endif + spin_lock_irq(&pcdev->videobuf_queue_lock); + if (list_empty(&pcdev->capture)) { + pcdev->active = NULL; + spin_unlock_irq(&pcdev->videobuf_queue_lock); + mutex_unlock(&pcdev->work_mutex); + return; + } - /* Save current syncpt values. */ - tegra_camera_save_syncpts(pcdev); -} + buf = list_entry(pcdev->capture.next, struct tegra_buffer, + queue); + pcdev->active = &buf->vb; + spin_unlock_irq(&pcdev->videobuf_queue_lock); -static void tegra_camera_deactivate(struct tegra_camera_dev *pcdev) -{ - mutex_lock(&pcdev->work_mutex); + tegra_camera_capture_setup(pcdev); + tegra_camera_capture_frame(pcdev); - /* Cancel active buffer. */ - if (pcdev->active) { - list_del_init(&to_tegra_vb(pcdev->active)->queue); - vb2_buffer_done(pcdev->active, VB2_BUF_STATE_ERROR); - pcdev->active = NULL; + mutex_unlock(&pcdev->work_mutex); } - - mutex_unlock(&pcdev->work_mutex); - - /* Turn off relevant clocks. */ - clk_disable(pcdev->clk_vi); - clk_disable(pcdev->clk_vi_sensor); - clk_disable(pcdev->clk_csi); - clk_disable(pcdev->clk_isp); - clk_disable(pcdev->clk_csus); - - nvhost_module_idle_ext(pcdev->ndev); } -static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev, - struct tegra_buffer *buf) +static int tegra_camera_init_buffer(struct tegra_buffer *buf) { - struct soc_camera_device *icd = pcdev->icd; + struct soc_camera_device *icd = buf->icd; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); + struct tegra_camera_platform_data *pdata = icd->link->priv; switch (icd->current_fmt->host_fmt->fourcc) { case V4L2_PIX_FMT_UYVY: @@ -1182,11 +1150,11 @@ static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev, buf->buffer_addr = vb2_dma_nvmap_plane_paddr(&buf->vb, 0); buf->start_addr = buf->buffer_addr; - if (pcdev->pdata->flip_v) + if (pdata->flip_v) buf->start_addr += bytes_per_line * (icd->user_height-1); - if (pcdev->pdata->flip_h) + if (pdata->flip_h) buf->start_addr += bytes_per_line - 1; break; @@ -1210,7 +1178,7 @@ static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev, buf->start_addr_u = buf->buffer_addr_u; buf->start_addr_v = buf->buffer_addr_v; - if (pcdev->pdata->flip_v) { + if (pdata->flip_v) { buf->start_addr += icd->user_width * (icd->user_height - 1); @@ -1221,7 +1189,7 @@ static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev, ((icd->user_height/2) - 1)); } - if (pcdev->pdata->flip_h) { + if (pdata->flip_h) { buf->start_addr += icd->user_width - 1; buf->start_addr_u += (icd->user_width/2) - 1; @@ -1232,8 +1200,12 @@ static void tegra_camera_init_buffer(struct tegra_camera_dev *pcdev, break; default: - BUG_ON(1); + dev_err(icd->parent, "Wrong host format %d\n", + icd->current_fmt->host_fmt->fourcc); + return -EINVAL; } + + return 0; } /* @@ -1248,6 +1220,7 @@ static int tegra_camera_videobuf_setup(struct vb2_queue *vq, struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq); + struct tegra_camera_platform_data *pdata = icd->link->priv; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct tegra_camera_dev *pcdev = ici->priv; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, @@ -1260,20 +1233,16 @@ static int tegra_camera_videobuf_setup(struct vb2_queue *vq, *num_planes = 1; - pcdev->sequence = 0; + if (pdata->port == TEGRA_CAMERA_PORT_CSI_A) + pcdev->sequence_a = 0; + else if (pdata->port == TEGRA_CAMERA_PORT_CSI_B) + pcdev->sequence_b = 0; sizes[0] = bytes_per_line * icd->user_height; alloc_ctxs[0] = pcdev->alloc_ctx; if (!*num_buffers) *num_buffers = 2; - dev_dbg(icd->parent, "num_buffers=%u, size=%lu\n", - *num_buffers, sizes[0]); - - tegra_camera_capture_setup(pcdev); - - dev_dbg(icd->parent, "Finished tegra_camera_videobuf_setup()\n"); - return 0; } @@ -1282,9 +1251,8 @@ static int tegra_camera_videobuf_prepare(struct vb2_buffer *vb) struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct tegra_camera_dev *pcdev = ici->priv; - struct tegra_buffer *buf; + struct tegra_buffer *buf = to_tegra_vb(vb); + struct tegra_camera_platform_data *pdata = icd->link->priv; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); unsigned long size; @@ -1294,7 +1262,19 @@ static int tegra_camera_videobuf_prepare(struct vb2_buffer *vb) if (bytes_per_line < 0) return bytes_per_line; - buf = to_tegra_vb(vb); + buf->icd = icd; + + if (!pdata) { + dev_err(icd->parent, "No platform data for this device!\n"); + return -EINVAL; + } + + if (!tegra_camera_port_is_valid(pdata->port)) { + dev_err(icd->parent, + "Invalid camera port %d in platform data\n", + pdata->port); + return -EINVAL; + } dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb, vb2_plane_vaddr(vb, 0), vb2_plane_size(vb, 0)); @@ -1308,7 +1288,10 @@ static int tegra_camera_videobuf_prepare(struct vb2_buffer *vb) memset(vb2_plane_vaddr(vb, 0), 0xbd, vb2_plane_size(vb, 0)); #endif - BUG_ON(NULL == icd->current_fmt); + if (!icd->current_fmt) { + dev_err(icd->parent, "%s NULL format point\n", __func__); + return -EINVAL; + } size = icd->user_height * bytes_per_line; @@ -1320,11 +1303,7 @@ static int tegra_camera_videobuf_prepare(struct vb2_buffer *vb) vb2_set_plane_payload(vb, 0, size); - tegra_camera_init_buffer(pcdev, buf); - - dev_dbg(icd->parent, "Finished tegra_camera_videobuf_prepare()\n"); - - return 0; + return tegra_camera_init_buffer(buf); } static void tegra_camera_videobuf_queue(struct vb2_buffer *vb) @@ -1336,18 +1315,12 @@ static void tegra_camera_videobuf_queue(struct vb2_buffer *vb) struct tegra_camera_dev *pcdev = ici->priv; struct tegra_buffer *buf = to_tegra_vb(vb); - dev_dbg(icd->parent, "In tegra_camera_videobuf_queue()\n"); - dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); spin_lock_irq(&pcdev->videobuf_queue_lock); list_add_tail(&buf->queue, &pcdev->capture); - - if (!pcdev->active) { - pcdev->active = vb; - schedule_work(&pcdev->work); - } + schedule_work(&pcdev->work); spin_unlock_irq(&pcdev->videobuf_queue_lock); dev_dbg(icd->parent, "Finished tegra_camera_videobuf_queue()\n"); @@ -1402,17 +1375,25 @@ static int tegra_camera_stop_streaming(struct vb2_queue *q) struct tegra_camera_dev *pcdev = ici->priv; struct list_head *buf_head, *tmp; + mutex_lock(&pcdev->work_mutex); spin_lock_irq(&pcdev->videobuf_queue_lock); - - pcdev->active = NULL; - - list_for_each_safe(buf_head, tmp, &pcdev->capture) - list_del_init(buf_head); - + list_for_each_safe(buf_head, tmp, &pcdev->capture) { + struct tegra_buffer *buf = container_of(buf_head, + struct tegra_buffer, + queue); + if (buf->icd == icd) + list_del_init(buf_head); + } spin_unlock_irq(&pcdev->videobuf_queue_lock); + if (pcdev->active) { + struct tegra_buffer *buf = to_tegra_vb(pcdev->active); + if (buf->icd == icd) + pcdev->active = NULL; + } + mutex_unlock(&pcdev->work_mutex); return 0; @@ -1456,35 +1437,13 @@ static int tegra_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct tegra_camera_dev *pcdev = ici->priv; - int err; - pcdev->pdata = icd->link->priv; - if (!pcdev->pdata) { - dev_err(icd->parent, "No platform data!\n"); - return -EINVAL; + if (!pcdev->enable_refcnt) { + pm_runtime_get_sync(ici->v4l2_dev.dev); + tegra_camera_activate(pcdev); + pcdev->num_frames = 0; } - - if (!tegra_camera_port_is_valid(pcdev->pdata->port)) { - dev_err(icd->parent, - "Invalid camera port %d in platform data\n", - pcdev->pdata->port); - return -EINVAL; - } - - pm_runtime_get_sync(ici->v4l2_dev.dev); - - if (pcdev->pdata->enable_camera) { - err = pcdev->pdata->enable_camera(pcdev->ndev); - if (IS_ERR_VALUE(err)) - return err; - } - - tegra_camera_activate(pcdev); - - pcdev->icd = icd; - - pcdev->num_frames = 0; - pcdev->output_channel = 0; + pcdev->enable_refcnt++; dev_dbg(icd->parent, "TEGRA Camera host attached to camera %d\n", icd->devnum); @@ -1498,14 +1457,12 @@ static void tegra_camera_remove_device(struct soc_camera_device *icd) struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct tegra_camera_dev *pcdev = ici->priv; - tegra_camera_deactivate(pcdev); - - pcdev->icd = NULL; - - if (pcdev->pdata->disable_camera) - pcdev->pdata->disable_camera(pcdev->ndev); - - pm_runtime_put_sync(ici->v4l2_dev.dev); + pcdev->enable_refcnt--; + if (!pcdev->enable_refcnt) { + cancel_work_sync(&pcdev->work); + tegra_camera_deactivate(pcdev); + pm_runtime_put_sync(ici->v4l2_dev.dev); + } dev_dbg(icd->parent, "Frames captured: %d\n", pcdev->num_frames); @@ -1741,8 +1698,7 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev, goto exit; } - pcdev->pdata = ndev->dev.platform_data; - pcdev->ndev = ndev; + pcdev->ndev = ndev; pcdev->ici.priv = pcdev; pcdev->ici.v4l2_dev.dev = &ndev->dev; @@ -1755,8 +1711,6 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev, spin_lock_init(&pcdev->videobuf_queue_lock); mutex_init(&pcdev->work_mutex); - nvhost_set_drvdata(ndev, pcdev); - pcdev->clk_vi = clk_get_sys("tegra_camera", "vi"); if (IS_ERR_OR_NULL(pcdev->clk_vi)) { dev_err(&ndev->dev, "Failed to get vi clock.\n"); @@ -1787,14 +1741,47 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev, goto exit_put_clk_isp; } + pcdev->clk_sclk = clk_get_sys("tegra_camera", "sclk"); + if (IS_ERR_OR_NULL(pcdev->clk_sclk)) { + dev_err(&ndev->dev, "Failed to get sclk clock.\n"); + goto exit_put_clk_csus; + } + + pcdev->clk_emc = clk_get_sys("tegra_camera", "emc"); + if (IS_ERR_OR_NULL(pcdev->clk_emc)) { + dev_err(&ndev->dev, "Failed to get emc clock.\n"); + goto exit_put_clk_sclk; + } + clk_set_rate(pcdev->clk_vi, 150000000); clk_set_rate(pcdev->clk_vi_sensor, 24000000); + /* Get regulator pointer */ +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + pcdev->reg = regulator_get(&ndev->dev, "vcsi"); +#else + pcdev->reg = regulator_get(&ndev->dev, "avdd_dsi_csi"); +#endif + if (IS_ERR_OR_NULL(pcdev->reg)) { + dev_err(&ndev->dev, "%s: couldn't get regulator\n", + __func__); + goto exit_put_clk_emc; + } + + nvhost_set_drvdata(ndev, pcdev); err = nvhost_client_device_get_resources(ndev); - if (err) - goto exit_put_clk_csus; + if (err) { + dev_err(&ndev->dev, "%s: nvhost get resources failed %d\n", + __func__, err); + goto exit_put_regulator; + } - nvhost_client_device_init(ndev); + err = nvhost_client_device_init(ndev); + if (err) { + dev_err(&ndev->dev, "%s: nvhost init failed %d\n", + __func__, err); + goto exit_put_regulator; + } pcdev->vi_base = ndev->aperture; @@ -1802,10 +1789,10 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev, pm_runtime_enable(&ndev->dev); pm_runtime_resume(&ndev->dev); - pcdev->alloc_ctx = vb2_dma_nvmap_init_ctx(NULL); + pcdev->alloc_ctx = vb2_dma_nvmap_init_ctx(&ndev->dev); if (IS_ERR(pcdev->alloc_ctx)) { err = PTR_ERR(pcdev->alloc_ctx); - goto exit_put_resources; + goto exit_pm_disable; } err = soc_camera_host_register(&pcdev->ici); @@ -1818,9 +1805,15 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev, exit_cleanup_alloc_ctx: vb2_dma_nvmap_cleanup_ctx(pcdev->alloc_ctx); -exit_put_resources: +exit_pm_disable: pm_runtime_disable(&ndev->dev); nvhost_client_device_put_resources(ndev); +exit_put_regulator: + regulator_put(pcdev->reg); +exit_put_clk_emc: + clk_put(pcdev->clk_emc); +exit_put_clk_sclk: + clk_put(pcdev->clk_sclk); exit_put_clk_csus: clk_put(pcdev->clk_csus); exit_put_clk_isp: @@ -1898,7 +1891,8 @@ static int tegra_camera_resume(struct nvhost_device *ndev) if (pcdev->icd) { /* Resume the camera host. */ tegra_camera_save_syncpts(pcdev); - tegra_camera_capture_setup(pcdev); + if (pcdev->active) + tegra_camera_capture_setup(pcdev); /* Resume the camera sensor. */ WARN_ON(!pcdev->icd->ops->resume); @@ -1940,5 +1934,6 @@ module_exit(tegra_camera_exit); MODULE_DESCRIPTION("TEGRA SoC Camera Host driver"); MODULE_AUTHOR("Andrew Chew "); +MODULE_AUTHOR("Bryan Wu "); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("nvhost:" TEGRA_CAM_DRV_NAME); -- cgit v1.2.3 From 936120ccdc70b17fe1e58fa26081b0862cce16f2 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Fri, 27 Sep 2013 14:00:02 -0700 Subject: ARM: tegra: cardhu: enable OV5650/OV5640 sensor Enable OV5650 and OV5640 sensor in Cardhu board file with the help of Tegra V4L2 SoC camera interface. To use V4L2 driver, we need to disable old camera HAL driver. Bug 1240806 Bug 1369083 Change-Id: I0dc529d44fba4d80b45690e384e8bf81b29f69e5 Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/246266 (cherry picked from commit 6b2f7cc4117208dc992478f27d5873ea38071fdc) Reviewed-on: http://git-master/r/279988 Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- arch/arm/mach-tegra/board-cardhu-sensors.c | 126 +++++++++++++++++++---------- 1 file changed, 85 insertions(+), 41 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c index d9c569bf3104..af66e1f571c6 100644 --- a/arch/arm/mach-tegra/board-cardhu-sensors.c +++ b/arch/arm/mach-tegra/board-cardhu-sensors.c @@ -37,6 +37,8 @@ #include #include #include +#include + #include #include #include @@ -62,11 +64,15 @@ #include "board-cardhu.h" #include "cpu-tegra.h" -static struct regulator *cardhu_supply_csi; +#if defined(CONFIG_VIDEO_OV5650) || \ + defined(CONFIG_VIDEO_OV5650_MODULE) || \ + defined(CONFIG_SOC_CAMERA_OV5650) || \ + defined(CONFIG_SOC_CAMERA_OV5650_MODULE) static struct regulator *cardhu_1v8_cam1; +static struct regulator *cardhu_vdd_2v8_cam1; +#endif static struct regulator *cardhu_1v8_cam2; static struct regulator *cardhu_1v8_cam3; -static struct regulator *cardhu_vdd_2v8_cam1; static struct regulator *cardhu_vdd_2v8_cam2; static struct regulator *cardhu_vdd_cam3; @@ -84,30 +90,86 @@ static struct pca954x_platform_data cardhu_pca954x_data = { .num_modes = ARRAY_SIZE(cardhu_pca954x_modes), }; +#if defined(CONFIG_SOC_CAMERA_OV5640) \ + || defined(CONFIG_SOC_CAMERA_OV5640_MODULE) +static int cardhu_ov5640_power_on(void); +static int cardhu_ov5640_power_off(void); + +static int cardhu_ov5640_power(struct device *dev, int enable) +{ + if (enable) + return cardhu_ov5640_power_on(); + else + cardhu_ov5640_power_off(); + + return 0; +} + +static struct i2c_board_info cardhu_ov5640_camera_i2c_device = { + I2C_BOARD_INFO("ov5640", 0x3C), +}; + +static struct tegra_camera_platform_data cardhu_ov5640_camera_platform_data = { + .flip_v = 0, + .flip_h = 0, + .port = TEGRA_CAMERA_PORT_CSI_B, + .lanes = 2, + .continuous_clk = 0, +}; + +static struct soc_camera_link ov5640_iclink = { + .bus_id = -1, /* This must match the .id of tegra_vi01_device */ + .board_info = &cardhu_ov5640_camera_i2c_device, + .module_name = "ov5640", + .i2c_adapter_id = PCA954x_I2C_BUS2, + .power = cardhu_ov5640_power, + .priv = &cardhu_ov5640_camera_platform_data, +}; + +static struct platform_device cardhu_ov5640_soc_camera_device = { + .name = "soc-camera-pdrv", + .id = 1, + .dev = { + .platform_data = &ov5640_iclink, + }, +}; +#endif + /* OV5650 V4L2 device */ -#ifdef CONFIG_SOC_CAMERA_OV5650 +#if defined(CONFIG_SOC_CAMERA_OV5650) \ + || defined(CONFIG_SOC_CAMERA_OV5650_MODULE) static int cardhu_left_ov5650_power_on(void); static int cardhu_left_ov5650_power_off(void); -static int cardhu_ov5650_camera_power_enable(struct nvhost_device *ndev) +static int cardhu_ov5650_power(struct device *dev, int enable) { - return cardhu_left_ov5650_power_on(); -} + if (enable) + return cardhu_left_ov5650_power_on(); + else + cardhu_left_ov5650_power_off(); -static void cardhu_ov5650_camera_power_disable(struct nvhost_device *ndev) -{ - cardhu_left_ov5650_power_off(); + return 0; } static struct i2c_board_info cardhu_ov5650_camera_i2c_device = { I2C_BOARD_INFO("ov5650", 0x36), }; +static struct tegra_camera_platform_data cardhu_ov5650_camera_platform_data = { + .flip_v = 0, + .flip_h = 0, + .port = TEGRA_CAMERA_PORT_CSI_A, + .lanes = 2, + .continuous_clk = 1, +}; + static struct soc_camera_link ov5650_iclink = { .bus_id = -1, /* This must match the .id of tegra_vi01_device */ .board_info = &cardhu_ov5650_camera_i2c_device, .module_name = "ov5650", .i2c_adapter_id = PCA954x_I2C_BUS0, + .power = cardhu_ov5650_power, + .priv = &cardhu_ov5650_camera_platform_data, }; static struct platform_device cardhu_ov5650_soc_camera_device = { @@ -117,16 +179,6 @@ static struct platform_device cardhu_ov5650_soc_camera_device = { .platform_data = &ov5650_iclink, }, }; - -static struct tegra_camera_platform_data cardhu_ov5650_camera_platform_data = { - .enable_camera = cardhu_ov5650_camera_power_enable, - .disable_camera = cardhu_ov5650_camera_power_disable, - .flip_v = 0, - .flip_h = 0, - .port = TEGRA_CAMERA_PORT_CSI_A, - .lanes = 2, - .continuous_clk = 1, -}; #endif static int cardhu_camera_init(void) @@ -181,19 +233,12 @@ static int cardhu_camera_init(void) return 0; } +#if defined(CONFIG_VIDEO_OV5650) || \ + defined(CONFIG_VIDEO_OV5650_MODULE) || \ + defined(CONFIG_SOC_CAMERA_OV5650) || \ + defined(CONFIG_SOC_CAMERA_OV5650_MODULE) static int cardhu_left_ov5650_power_on(void) { - - if (cardhu_supply_csi == NULL) { - cardhu_supply_csi = regulator_get(NULL, "avdd_dsi_csi"); - if (WARN_ON(IS_ERR(cardhu_supply_csi))) { - pr_err("%s: couldn't get regulator avdd_dsi_csi: %ld\n", - __func__, PTR_ERR(cardhu_supply_csi)); - goto reg_alloc_fail; - } - } - regulator_enable(cardhu_supply_csi); - /* Boards E1198 and E1291 are of Cardhu personality * and donot have TCA6416 exp for camera */ if ((board_info.board_id == BOARD_E1198) || @@ -251,10 +296,6 @@ reg_alloc_fail: regulator_put(cardhu_vdd_2v8_cam1); cardhu_vdd_2v8_cam1 = NULL; } - if (cardhu_supply_csi) { - regulator_put(cardhu_supply_csi); - cardhu_supply_csi = NULL; - } return -ENODEV; @@ -275,11 +316,10 @@ static int cardhu_left_ov5650_power_off(void) regulator_disable(cardhu_1v8_cam1); if (cardhu_vdd_2v8_cam1) regulator_disable(cardhu_vdd_2v8_cam1); - if (cardhu_supply_csi) - regulator_disable(cardhu_supply_csi); return 0; } +#endif #if defined(CONFIG_VIDEO_OV5650) || defined(CONFIG_VIDEO_OV5650_MODULE) struct ov5650_platform_data cardhu_left_ov5650_data = { @@ -551,7 +591,6 @@ static int cardhu_ov5640_power_on(void) (board_info.board_id == BOARD_E1291) || (board_info.board_id == BOARD_PM315)) { - gpio_direction_output(CAM1_POWER_DWN_GPIO, 0); gpio_direction_output(CAM2_POWER_DWN_GPIO, 0); gpio_direction_output(CAM3_POWER_DWN_GPIO, 0); mdelay(10); @@ -604,7 +643,6 @@ static int cardhu_ov5640_power_off(void) if ((board_info.board_id == BOARD_E1198) || (board_info.board_id == BOARD_E1291) || (board_info.board_id == BOARD_PM315)) { - gpio_direction_output(CAM1_POWER_DWN_GPIO, 1); gpio_direction_output(CAM2_POWER_DWN_GPIO, 1); gpio_direction_output(CAM3_POWER_DWN_GPIO, 1); } @@ -817,10 +855,12 @@ static struct i2c_board_info cardhu_i2c8_board_info[] = { I2C_BOARD_INFO("ov2710", 0x36), .platform_data = &cardhu_ov2710_data, }, +#if defined(CONFIG_VIDEO_OV5640) || defined(CONFIG_VIDEO_OV5640_MODULE) { I2C_BOARD_INFO("ov5640", 0x3C), .platform_data = &cardhu_ov5640_data, }, +#endif }; static int nct_get_temp(void *_data, long *temp) @@ -1213,11 +1253,15 @@ int __init cardhu_sensors_init(void) if (board_info.board_id != BOARD_PM315) mpuirq_init(); -#ifdef CONFIG_SOC_CAMERA_OV5650 - t30_get_tegra_vi01_device()->dev.platform_data = - &cardhu_ov5650_camera_platform_data; +#if defined(CONFIG_SOC_CAMERA_OV5650) \ + || defined(CONFIG_SOC_CAMERA_OV5650_MODULE) platform_device_register(&cardhu_ov5650_soc_camera_device); #endif +#if defined(CONFIG_SOC_CAMERA_OV5640) \ + || defined(CONFIG_SOC_CAMERA_OV5640_MODULE) + platform_device_register(&cardhu_ov5640_soc_camera_device); +#endif + return 0; } -- cgit v1.2.3 From dae2101b35e9050bbfd02f6cd084e76d005de061 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Tue, 25 Jun 2013 17:30:57 -0700 Subject: media: ov5640: update OV5640 sensor driver Bug 1369083 Change-Id: I1522b688e0681e52592c0f26a8e335937372836a Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/279989 Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/media/video/ov5640.c | 2135 +++++++++++++++++++++++++----------------- 1 file changed, 1289 insertions(+), 846 deletions(-) diff --git a/drivers/media/video/ov5640.c b/drivers/media/video/ov5640.c index 8e45fa3de5d2..795d9bd541b3 100644 --- a/drivers/media/video/ov5640.c +++ b/drivers/media/video/ov5640.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -14,6 +14,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -21,793 +22,1324 @@ #include #include -#define to_ov5640(sd) container_of(sd, struct ov5640_priv, subdev) - -#define OV5640_SYSTEM_CTRL 0x3008 -#define OV5640_CHIP_ID_HI 0x300a -#define OV5640_CHIP_ID_LO 0x300b -#define OV5640_PAD_OUTPUT_ENABLE00 0x3016 -#define OV5640_PAD_OUTPUT_ENABLE01 0x3017 -#define OV5640_PAD_OUTPUT_ENABLE02 0x3018 -#define OV5640_SC_PLL_CTRL0 0x3034 -#define OV5640_SC_PLL_CTRL1 0x3035 -#define OV5640_SC_PLL_CTRL2 0x3036 -#define OV5640_SC_PLL_CTRL3 0x3037 - -/* SCCB Control */ -#define OV5640_SCCB_SYSTEM_CTRL1 0x3103 -#define OV5640_SYSTEM_ROOT_DIVIDER 0x3108 - -/* Timing Control */ -#define OV5640_TIMING_HS_HI 0x3800 -#define OV5640_TIMING_HS_LO 0x3801 -#define OV5640_TIMING_VS_HI 0x3802 -#define OV5640_TIMING_VS_LO 0x3803 -#define OV5640_TIMING_HW_HI 0x3804 -#define OV5640_TIMING_HW_LO 0x3805 -#define OV5640_TIMING_VH_HI 0x3806 -#define OV5640_TIMING_VH_LO 0x3807 -#define OV5640_TIMING_DVPHO_HI 0x3808 -#define OV5640_TIMING_DVPHO_LO 0x3809 -#define OV5640_TIMING_DVPVO_HI 0x380a -#define OV5640_TIMING_DVPVO_LO 0x380b -#define OV5640_TIMING_HTS_HI 0x380c -#define OV5640_TIMING_HTS_LO 0x380d -#define OV5640_TIMING_VTS_HI 0x380e -#define OV5640_TIMING_VTS_LO 0x380f -#define OV5640_TIMING_HOFFSET_HI 0x3810 -#define OV5640_TIMING_HOFFSET_LO 0x3811 -#define OV5640_TIMING_VOFFSET_HI 0x3812 -#define OV5640_TIMING_VOFFSET_LO 0x3813 -#define OV5640_TIMING_X_INC 0x3814 -#define OV5640_TIMING_Y_INC 0x3815 -#define OV5640_TIMING_TC_REG20 0x3820 -#define OV5640_TIMING_TC_REG21 0x3821 - -/* AEC/AGC Power Down Domain Control */ -#define OV5640_AEC_MAX_EXPO_60HZ_HI 0x3a02 -#define OV5640_AEC_MAX_EXPO_60HZ_LO 0x3a03 -#define OV5640_AEC_B50_STEP_HI 0x3a08 -#define OV5640_AEC_B50_STEP_LO 0x3a09 -#define OV5640_AEC_B60_STEP_HI 0x3a0a -#define OV5640_AEC_B60_STEP_LO 0x3a0b -#define OV5640_AEC_CTRL0C 0x3a0c -#define OV5640_AEC_CTRL0D 0x3a0d -#define OV5640_AEC_CTRL0E 0x3a0e -#define OV5640_AEC_CTRL0F 0x3a0f -#define OV5640_AEC_CTRL10 0x3a10 -#define OV5640_AEC_CTRL11 0x3a11 -#define OV5640_AEC_CTRL12 0x3a12 -#define OV5640_AEC_CTRL13 0x3a13 -#define OV5640_AEC_MAX_EXPO_50HZ_HI 0x3a14 -#define OV5640_AEC_MAX_EXPO_50HZ_LO 0x3a15 -#define OV5640_AEC_GAIN_CEILING_HI 0x3a18 -#define OV5640_AEC_GAIN_CEILING_LO 0x3a19 -#define OV5640_AEC_CTRL1B 0x3a1b -#define OV5640_AEC_CTRL1E 0x3a1e -#define OV5640_AEC_CTRL1F 0x3a1f - -/* 50/60Hz Detector Control */ -#define OV5640_5060HZ_CTRL00 0x3c00 -#define OV5640_5060HZ_CTRL01 0x3c01 -#define OV5640_5060HZ_CTRL02 0x3c02 -#define OV5640_5060HZ_CTRL03 0x3c03 -#define OV5640_5060HZ_CTRL04 0x3c04 -#define OV5640_5060HZ_CTRL05 0x3c05 -#define OV5640_LIGHT_METER1_THRESHOLD_HI 0x3c06 -#define OV5640_LIGHT_METER1_THRESHOLD_LO 0x3c07 -#define OV5640_LIGHT_METER2_THRESHOLD_HI 0x3c08 -#define OV5640_LIGHT_METER2_THRESHOLD_LO 0x3c09 -#define OV5640_SAMPLE_NUMBER_HI 0x3c0a -#define OV5640_SAMPLE_NUMBER_LO 0x3c0b - -/* ISP General Controls */ -#define OV5640_ISP_CTRL00 0x5000 -#define OV5640_ISP_CTRL01 0x5001 -#define OV5640_ISP_CTRL37 0x5025 - -/* AWB Control */ -#define OV5640_AWB_CTRL00 0x5180 -#define OV5640_AWB_CTRL01 0x5181 -#define OV5640_AWB_CTRL02 0x5182 -#define OV5640_AWB_CTRL03 0x5183 -#define OV5640_AWB_CTRL04 0x5184 -#define OV5640_AWB_CTRL05 0x5185 -#define OV5640_AWB_CTRL06 0x5186 -#define OV5640_AWB_CTRL07 0x5187 -#define OV5640_AWB_CTRL08 0x5188 -#define OV5640_AWB_CTRL09 0x5189 -#define OV5640_AWB_CTRL10 0x518a -#define OV5640_AWB_CTRL11 0x518b -#define OV5640_AWB_CTRL12 0x518c -#define OV5640_AWB_CTRL13 0x518d -#define OV5640_AWB_CTRL14 0x518e -#define OV5640_AWB_CTRL15 0x518f -#define OV5640_AWB_CTRL16 0x5190 -#define OV5640_AWB_CTRL17 0x5191 -#define OV5640_AWB_CTRL18 0x5192 -#define OV5640_AWB_CTRL19 0x5193 -#define OV5640_AWB_CTRL20 0x5194 -#define OV5640_AWB_CTRL21 0x5195 -#define OV5640_AWB_CTRL22 0x5196 -#define OV5640_AWB_CTRL23 0x5197 -#define OV5640_AWB_CTRL24 0x5198 -#define OV5640_AWB_CTRL25 0x5199 -#define OV5640_AWB_CTRL26 0x519a -#define OV5640_AWB_CTRL27 0x519b -#define OV5640_AWB_CTRL28 0x519c -#define OV5640_AWB_CTRL29 0x519d -#define OV5640_AWB_CTRL30 0x519e - -/* CIP Control */ -#define OV5640_CIP_SHARPENMT_THRESHOLD_1 0x5300 -#define OV5640_CIP_SHARPENMT_THRESHOLD_2 0x5301 -#define OV5640_CIP_SHARPENMT_OFFSET_1 0x5302 -#define OV5640_CIP_SHARPENMT_OFFSET_2 0x5303 -#define OV5640_CIP_DNS_THRESHOLD_1 0x5304 -#define OV5640_CIP_DNS_THRESHOLD_2 0x5305 -#define OV5640_CIP_DNS_OFFSET_1 0x5306 -#define OV5640_CIP_DNS_OFFSET_2 0x5307 -#define OV5640_CIP_CTRL 0x5308 -#define OV5640_CIP_SHARPENTH_THRESHOLD_1 0x5309 -#define OV5640_CIP_SHARPENTH_THRESHOLD_2 0x530a -#define OV5640_CIP_SHARPENTH_OFFSET_1 0x530b -#define OV5640_CIP_SHARPENTH_OFFSET_2 0x530c -#define OV5640_CIP_EDGE_MT_AUTO 0x530d -#define OV5640_CIP_DNS_THRESHOLD_AUTO 0x530e -#define OF5640_CIP_SHARPEN_THRESHOLD_AUTO 0x530f - -/* CMX Control */ -#define OV5640_CMX_CTRL 0x5380 -#define OV5640_CMX1 0x5381 -#define OV5640_CMX2 0x5382 -#define OV5640_CMX3 0x5383 -#define OV5640_CMX4 0x5384 -#define OV5640_CMX5 0x5385 -#define OV5640_CMX6 0x5386 -#define OV5640_CMX7 0x5387 -#define OV5640_CMX8 0x5388 -#define OV5640_CMX9 0x5389 -#define OV5640_CMXSIGN_HI 0x538a -#define OV5640_CMXSIGN_LO 0x538b - -/* Gamma Control */ -#define OV5640_GAMMA_CTRL00 0x5480 -#define OV5640_YST00 0x5481 -#define OV5640_YST01 0x5482 -#define OV5640_YST02 0x5483 -#define OV5640_YST03 0x5484 -#define OV5640_YST04 0x5485 -#define OV5640_YST05 0x5486 -#define OV5640_YST06 0x5487 -#define OV5640_YST07 0x5488 -#define OV5640_YST08 0x5489 -#define OV5640_YST09 0x548a -#define OV5640_YST0A 0x548b -#define OV5640_YST0B 0x548c -#define OV5640_YST0C 0x548d -#define OV5640_YST0D 0x548e -#define OV5640_YST0E 0x548f -#define OV5640_YST0F 0x5490 - -/* SDE Control */ -#define OV5640_SDE_CTRL_0 0x5580 -#define OV5640_SDE_CTRL_1 0x5581 -#define OV5640_SDE_CTRL_2 0x5582 -#define OV5640_SDE_CTRL_3 0x5583 -#define OV5640_SDE_CTRL_4 0x5584 -#define OV5640_SDE_CTRL_5 0x5585 -#define OV5640_SDE_CTRL_6 0x5586 -#define OV5640_SDE_CTRL_7 0x5587 -#define OV5640_SDE_CTRL_8 0x5588 -#define OV5640_SDE_CTRL_9 0x5589 -#define OV5640_SDE_CTRL_10 0x558a -#define OV5640_SDE_CTRL_11 0x558b -#define OV5640_SDE_CTRL_12 0x558c - -/* LENC Control */ -#define OV5640_GMTRX00 0x5800 -#define OV5640_GMTRX01 0x5801 -#define OV5640_GMTRX02 0x5802 -#define OV5640_GMTRX03 0x5803 -#define OV5640_GMTRX04 0x5804 -#define OV5640_GMTRX05 0x5805 -#define OV5640_GMTRX10 0x5806 -#define OV5640_GMTRX11 0x5807 -#define OV5640_GMTRX12 0x5808 -#define OV5640_GMTRX13 0x5809 -#define OV5640_GMTRX14 0x580a -#define OV5640_GMTRX15 0x580b -#define OV5640_GMTRX20 0x580c -#define OV5640_GMTRX21 0x580d -#define OV5640_GMTRX22 0x580e -#define OV5640_GMTRX23 0x580f -#define OV5640_GMTRX24 0x5810 -#define OV5640_GMTRX25 0x5811 -#define OV5640_GMTRX30 0x5812 -#define OV5640_GMTRX31 0x5813 -#define OV5640_GMTRX32 0x5814 -#define OV5640_GMTRX33 0x5815 -#define OV5640_GMTRX34 0x5816 -#define OV5640_GMTRX35 0x5817 -#define OV5640_GMTRX40 0x5818 -#define OV5640_GMTRX41 0x5819 -#define OV5640_GMTRX42 0x581a -#define OV5640_GMTRX43 0x581b -#define OV5640_GMTRX44 0x581c -#define OV5640_GMTRX45 0x581d -#define OV5640_GMTRX50 0x581e -#define OV5640_GMTRX51 0x581f -#define OV5640_GMTRX52 0x5820 -#define OV5640_GMTRX53 0x5821 -#define OV5640_GMTRX54 0x5822 -#define OV5640_GMTRX55 0x5823 -#define OV5640_BRMATRX00 0x5824 -#define OV5640_BRMATRX01 0x5825 -#define OV5640_BRMATRX02 0x5826 -#define OV5640_BRMATRX03 0x5827 -#define OV5640_BRMATRX04 0x5828 -#define OV5640_BRMATRX05 0x5829 -#define OV5640_BRMATRX06 0x582a -#define OV5640_BRMATRX07 0x582b -#define OV5640_BRMATRX08 0x582c -#define OV5640_BRMATRX09 0x582d -#define OV5640_BRMATRX20 0x582e -#define OV5640_BRMATRX21 0x582f -#define OV5640_BRMATRX22 0x5830 -#define OV5640_BRMATRX23 0x5831 -#define OV5640_BRMATRX24 0x5832 -#define OV5640_BRMATRX30 0x5833 -#define OV5640_BRMATRX31 0x5834 -#define OV5640_BRMATRX32 0x5835 -#define OV5640_BRMATRX33 0x5836 -#define OV5640_BRMATRX34 0x5837 -#define OV5640_BRMATRX40 0x5838 -#define OV5640_BRMATRX41 0x5839 -#define OV5640_BRMATRX42 0x583a -#define OV5640_BRMATRX43 0x583b -#define OV5640_BRMATRX44 0x583c -#define OV5640_LENC_BR_OFFSET 0x583d - -#define OV5640_MAX_WIDTH 640 -#define OV5640_MAX_HEIGHT 480 - -/* Misc. structures */ struct ov5640_reg { - u16 reg; - u8 val; + u16 addr; + u16 val; }; -struct ov5640_priv { - struct v4l2_subdev subdev; +#define OV5640_TABLE_WAIT_MS 0 +#define OV5640_TABLE_END 1 - int ident; - u16 chip_id; - u8 revision; - u8 manid; - u8 smiaver; +static struct ov5640_reg mode_2592x1944[] = { + /* PLL Control MIPI bit rate/lane = 672MHz, 16-bit mode. + * Output size: 2608x1948 (0, 0) - (2623, 1951), + * Line Length = 2844, Frame Length = 1968 + */ + {0x3103, 0x11}, + {0x3008, 0x82}, + {OV5640_TABLE_WAIT_MS, 5}, + {0x3008, 0x42}, + {0x3103, 0x03}, + {0x3017, 0x00}, + {0x3018, 0x00}, + {0x3034, 0x18}, + {0x3035, 0x11}, + {0x3036, 0x7d}, + {0x3037, 0x13}, + {0x3108, 0x01}, + {0x3630, 0x36}, + {0x3631, 0x0e}, + {0x3632, 0xe2}, + {0x3633, 0x12}, + {0x3621, 0xe0}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3905, 0x02}, + {0x3906, 0x10}, + {0x3901, 0x0a}, + {0x3731, 0x12}, + {0x3600, 0x08}, + {0x3601, 0x33}, + {0x302d, 0x60}, + {0x3620, 0x52}, + {0x371b, 0x20}, + {0x471c, 0x50}, + {0x3a13, 0x43}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3635, 0x13}, + {0x3636, 0x03}, + {0x3634, 0x40}, + {0x3622, 0x01}, + {0x3c01, 0x34}, + {0x3c04, 0x28}, + {0x3c05, 0x98}, + {0x3c06, 0x00}, + {0x3c07, 0x07}, + {0x3c08, 0x00}, + {0x3c09, 0x1c}, + {0x3c0a, 0x9c}, + {0x3c0b, 0x40}, + {0x3820, 0x40}, + {0x3821, 0x06}, + {0x3814, 0x11}, + {0x3815, 0x11}, + {0x3800, 0x00}, + {0x3801, 0x00}, + {0x3802, 0x00}, + {0x3803, 0x00}, + {0x3804, 0x0a}, + {0x3805, 0x3f}, + {0x3806, 0x07}, + {0x3807, 0x9f}, + {0x3808, 0x0a}, + {0x3809, 0x30}, + {0x380a, 0x07}, + {0x380b, 0x9c}, + {0x380c, 0x0b}, + {0x380d, 0x1c}, + {0x380e, 0x07}, + {0x380f, 0xb0}, + {0x3810, 0x00}, + {0x3811, 0x08}, + {0x3812, 0x00}, + {0x3813, 0x02}, + {0x3618, 0x04}, + {0x3612, 0x2b}, + {0x3708, 0x64}, + {0x3709, 0x12}, + {0x370c, 0x00}, + {0x3a02, 0x07}, + {0x3a03, 0xb0}, + {0x3a08, 0x01}, + {0x3a09, 0x27}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0e, 0x06}, + {0x3a0d, 0x08}, + {0x3a14, 0x07}, + {0x3a15, 0xb0}, + {0x4001, 0x02}, + {0x4004, 0x06}, + {0x3000, 0x00}, + {0x3002, 0x1c}, + {0x3004, 0xff}, + {0x3006, 0xc3}, + {0x300e, 0x45}, + {0x302e, 0x08}, + {0x4300, 0x32}, + {0x4800, 0x24}, + {0x4837, 0x0a}, + {0x501f, 0x00}, + {0x440e, 0x00}, + {0x5000, 0xa7}, + {0x5001, 0x83}, + {0x5180, 0xff}, + {0x5181, 0xf2}, + {0x5182, 0x00}, + {0x5183, 0x14}, + {0x5184, 0x25}, + {0x5185, 0x24}, + {0x5186, 0x09}, + {0x5187, 0x09}, + {0x5188, 0x09}, + {0x5189, 0x75}, + {0x518a, 0x54}, + {0x518b, 0xe0}, + {0x518c, 0xb2}, + {0x518d, 0x42}, + {0x518e, 0x3d}, + {0x518f, 0x56}, + {0x5190, 0x46}, + {0x5191, 0xf8}, + {0x5192, 0x04}, + {0x5193, 0x70}, + {0x5194, 0xf0}, + {0x5195, 0xf0}, + {0x5196, 0x03}, + {0x5197, 0x01}, + {0x5198, 0x04}, + {0x5199, 0x12}, + {0x519a, 0x04}, + {0x519b, 0x00}, + {0x519c, 0x06}, + {0x519d, 0x82}, + {0x519e, 0x38}, + {0x5381, 0x1e}, + {0x5382, 0x5b}, + {0x5383, 0x08}, + {0x5384, 0x0a}, + {0x5385, 0x7e}, + {0x5386, 0x88}, + {0x5387, 0x7c}, + {0x5388, 0x6c}, + {0x5389, 0x10}, + {0x538a, 0x01}, + {0x538b, 0x98}, + {0x5300, 0x08}, + {0x5301, 0x30}, + {0x5302, 0x10}, + {0x5303, 0x00}, + {0x5304, 0x08}, + {0x5305, 0x30}, + {0x5306, 0x08}, + {0x5307, 0x16}, + {0x5309, 0x08}, + {0x530a, 0x30}, + {0x530b, 0x04}, + {0x530c, 0x06}, + {0x5480, 0x01}, + {0x5481, 0x08}, + {0x5482, 0x14}, + {0x5483, 0x28}, + {0x5484, 0x51}, + {0x5485, 0x65}, + {0x5486, 0x71}, + {0x5487, 0x7d}, + {0x5488, 0x87}, + {0x5489, 0x91}, + {0x548a, 0x9a}, + {0x548b, 0xaa}, + {0x548c, 0xb8}, + {0x548d, 0xcd}, + {0x548e, 0xdd}, + {0x548f, 0xea}, + {0x5490, 0x1d}, + {0x5580, 0x02}, + {0x5583, 0x40}, + {0x5584, 0x10}, + {0x5589, 0x10}, + {0x558a, 0x00}, + {0x558b, 0xf8}, + {0x5800, 0x23}, + {0x5801, 0x14}, + {0x5802, 0x0f}, + {0x5803, 0x0f}, + {0x5804, 0x12}, + {0x5805, 0x26}, + {0x5806, 0x0c}, + {0x5807, 0x08}, + {0x5808, 0x05}, + {0x5809, 0x05}, + {0x580a, 0x08}, + {0x580b, 0x0d}, + {0x580c, 0x08}, + {0x580d, 0x03}, + {0x580e, 0x00}, + {0x580f, 0x00}, + {0x5810, 0x03}, + {0x5811, 0x09}, + {0x5812, 0x07}, + {0x5813, 0x03}, + {0x5814, 0x00}, + {0x5815, 0x01}, + {0x5816, 0x03}, + {0x5817, 0x08}, + {0x5818, 0x0d}, + {0x5819, 0x08}, + {0x581a, 0x05}, + {0x581b, 0x06}, + {0x581c, 0x08}, + {0x581d, 0x0e}, + {0x581e, 0x29}, + {0x581f, 0x17}, + {0x5820, 0x11}, + {0x5821, 0x11}, + {0x5822, 0x15}, + {0x5823, 0x28}, + {0x5824, 0x46}, + {0x5825, 0x26}, + {0x5826, 0x08}, + {0x5827, 0x26}, + {0x5828, 0x64}, + {0x5829, 0x26}, + {0x582a, 0x24}, + {0x582b, 0x22}, + {0x582c, 0x24}, + {0x582d, 0x24}, + {0x582e, 0x06}, + {0x582f, 0x22}, + {0x5830, 0x40}, + {0x5831, 0x42}, + {0x5832, 0x24}, + {0x5833, 0x26}, + {0x5834, 0x24}, + {0x5835, 0x22}, + {0x5836, 0x22}, + {0x5837, 0x26}, + {0x5838, 0x44}, + {0x5839, 0x24}, + {0x583a, 0x26}, + {0x583b, 0x28}, + {0x583c, 0x42}, + {0x583d, 0xce}, + {0x5025, 0x00}, + {0x3a0f, 0x30}, + {0x3a10, 0x28}, + {0x3a1b, 0x30}, + {0x3a1e, 0x26}, + {0x3a11, 0x60}, + {0x3a1f, 0x14}, + {0x3008, 0x02}, + {OV5640_TABLE_END, 0x0000} +}; - bool flag_vflip; - bool flag_hflip; +static struct ov5640_reg mode_1920x1080[] = { + /* PLL Control MIPI bit rate/lane = 672MHz, 16-bit mode. + * Output size: 1936x1096 (336, 426) - (2287, 1529), + * Line Length = 2500, Frame Length = 1120. + */ + {0x3103, 0x11}, + {0x3008, 0x82}, + {OV5640_TABLE_WAIT_MS, 5}, + {0x3008, 0x42}, + {0x3103, 0x03}, + {0x3017, 0x00}, + {0x3018, 0x00}, + {0x3034, 0x18}, + {0x3035, 0x11}, + {0x3036, 0x54}, + {0x3037, 0x13}, + {0x3108, 0x01}, + {0x3630, 0x36}, + {0x3631, 0x0e}, + {0x3632, 0xe2}, + {0x3633, 0x12}, + {0x3621, 0xe0}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3905, 0x02}, + {0x3906, 0x10}, + {0x3901, 0x0a}, + {0x3731, 0x12}, + {0x3600, 0x08}, + {0x3601, 0x33}, + {0x302d, 0x60}, + {0x3620, 0x52}, + {0x371b, 0x20}, + {0x471c, 0x50}, + {0x3a13, 0x43}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3635, 0x13}, + {0x3636, 0x03}, + {0x3634, 0x40}, + {0x3622, 0x01}, + {0x3c01, 0x34}, + {0x3c04, 0x28}, + {0x3c05, 0x98}, + {0x3c06, 0x00}, + {0x3c07, 0x07}, + {0x3c08, 0x00}, + {0x3c09, 0x1c}, + {0x3c0a, 0x9c}, + {0x3c0b, 0x40}, + {0x3820, 0x40}, + {0x3821, 0x06}, + {0x3814, 0x11}, + {0x3815, 0x11}, + {0x3800, 0x01}, + {0x3801, 0x50}, + {0x3802, 0x01}, + {0x3803, 0xaa}, + {0x3804, 0x08}, + {0x3805, 0xef}, + {0x3806, 0x05}, + {0x3807, 0xf9}, + {0x3808, 0x07}, + {0x3809, 0x90}, + {0x380a, 0x04}, + {0x380b, 0x48}, + {0x380c, 0x09}, + {0x380d, 0xc4}, + {0x380e, 0x04}, + {0x380f, 0x60}, + {0x3810, 0x00}, + {0x3811, 0x08}, + {0x3812, 0x00}, + {0x3813, 0x04}, + {0x3618, 0x04}, + {0x3612, 0x2b}, + {0x3708, 0x64}, + {0x3709, 0x12}, + {0x370c, 0x00}, + {0x3a02, 0x04}, + {0x3a03, 0x60}, + {0x3a08, 0x01}, + {0x3a09, 0x50}, + {0x3a0a, 0x01}, + {0x3a0b, 0x18}, + {0x3a0e, 0x03}, + {0x3a0d, 0x04}, + {0x3a14, 0x04}, + {0x3a15, 0x60}, + {0x4001, 0x02}, + {0x4004, 0x06}, + {0x3000, 0x00}, + {0x3002, 0x1c}, + {0x3004, 0xff}, + {0x3006, 0xc3}, + {0x300e, 0x45}, + {0x302e, 0x08}, + {0x4300, 0x32}, + {0x501f, 0x00}, + {0x4713, 0x02}, + {0x4407, 0x04}, + {0x440e, 0x00}, + {0x460b, 0x37}, + {0x460c, 0x20}, + {0x4800, 0x24}, + {0x4837, 0x0a}, + {0x3824, 0x04}, + {0x5000, 0xa7}, + {0x5001, 0x83}, + {0x5180, 0xff}, + {0x5181, 0xf2}, + {0x5182, 0x00}, + {0x5183, 0x14}, + {0x5184, 0x25}, + {0x5185, 0x24}, + {0x5186, 0x09}, + {0x5187, 0x09}, + {0x5188, 0x09}, + {0x5189, 0x75}, + {0x518a, 0x54}, + {0x518b, 0xe0}, + {0x518c, 0xb2}, + {0x518d, 0x42}, + {0x518e, 0x3d}, + {0x518f, 0x56}, + {0x5190, 0x46}, + {0x5191, 0xf8}, + {0x5192, 0x04}, + {0x5193, 0x70}, + {0x5194, 0xf0}, + {0x5195, 0xf0}, + {0x5196, 0x03}, + {0x5197, 0x01}, + {0x5198, 0x04}, + {0x5199, 0x12}, + {0x519a, 0x04}, + {0x519b, 0x00}, + {0x519c, 0x06}, + {0x519d, 0x82}, + {0x519e, 0x38}, + {0x5381, 0x1e}, + {0x5382, 0x5b}, + {0x5383, 0x08}, + {0x5384, 0x0a}, + {0x5385, 0x7e}, + {0x5386, 0x88}, + {0x5387, 0x7c}, + {0x5388, 0x6c}, + {0x5389, 0x10}, + {0x538a, 0x01}, + {0x538b, 0x98}, + {0x5300, 0x08}, + {0x5301, 0x30}, + {0x5302, 0x10}, + {0x5303, 0x00}, + {0x5304, 0x08}, + {0x5305, 0x30}, + {0x5306, 0x08}, + {0x5307, 0x16}, + {0x5309, 0x08}, + {0x530a, 0x30}, + {0x530b, 0x04}, + {0x530c, 0x06}, + {0x5480, 0x01}, + {0x5481, 0x08}, + {0x5482, 0x14}, + {0x5483, 0x28}, + {0x5484, 0x51}, + {0x5485, 0x65}, + {0x5486, 0x71}, + {0x5487, 0x7d}, + + {0x5488, 0x87}, + {0x5489, 0x91}, + {0x548a, 0x9a}, + {0x548b, 0xaa}, + {0x548c, 0xb8}, + {0x548d, 0xcd}, + {0x548e, 0xdd}, + {0x548f, 0xea}, + {0x5490, 0x1d}, + {0x5580, 0x02}, + {0x5583, 0x40}, + {0x5584, 0x10}, + {0x5589, 0x10}, + {0x558a, 0x00}, + {0x558b, 0xf8}, + {0x5800, 0x23}, + {0x5801, 0x14}, + {0x5802, 0x0f}, + {0x5803, 0x0f}, + {0x5804, 0x12}, + {0x5805, 0x26}, + {0x5806, 0x0c}, + {0x5807, 0x08}, + {0x5808, 0x05}, + {0x5809, 0x05}, + {0x580a, 0x08}, + {0x580b, 0x0d}, + {0x580c, 0x08}, + {0x580d, 0x03}, + {0x580e, 0x00}, + {0x580f, 0x00}, + {0x5810, 0x03}, + {0x5811, 0x09}, + {0x5812, 0x07}, + {0x5813, 0x03}, + {0x5814, 0x00}, + {0x5815, 0x01}, + {0x5816, 0x03}, + {0x5817, 0x08}, + {0x5818, 0x0d}, + {0x5819, 0x08}, + {0x581a, 0x05}, + {0x581b, 0x06}, + {0x581c, 0x08}, + {0x581d, 0x0e}, + {0x581e, 0x29}, + {0x581f, 0x17}, + {0x5820, 0x11}, + {0x5821, 0x11}, + {0x5822, 0x15}, + {0x5823, 0x28}, + {0x5824, 0x46}, + {0x5825, 0x26}, + {0x5826, 0x08}, + {0x5827, 0x26}, + {0x5828, 0x64}, + {0x5829, 0x26}, + {0x582a, 0x24}, + {0x582b, 0x22}, + {0x582c, 0x24}, + {0x582d, 0x24}, + {0x582e, 0x06}, + {0x582f, 0x22}, + {0x5830, 0x40}, + {0x5831, 0x42}, + {0x5832, 0x24}, + {0x5833, 0x26}, + {0x5834, 0x24}, + {0x5835, 0x22}, + {0x5836, 0x22}, + {0x5837, 0x26}, + {0x5838, 0x44}, + {0x5839, 0x24}, + {0x583a, 0x26}, + {0x583b, 0x28}, + {0x583c, 0x42}, + {0x583d, 0xce}, + {0x5025, 0x00}, + {0x3a0f, 0x30}, + {0x3a10, 0x28}, + {0x3a1b, 0x30}, + {0x3a1e, 0x26}, + {0x3a11, 0x60}, + {0x3a1f, 0x14}, + {0x3008, 0x02}, + {OV5640_TABLE_END, 0x0000} +}; - /* For suspend/resume. */ - struct v4l2_mbus_framefmt current_mf; - bool current_enable; +static struct ov5640_reg mode_1296x972[] = { + /* PLL Control MIPI bit rate/lane = 448MHz, 16-bit mode. + * Output size: 1304x972 (0, 0) - (2623, 1951), + * Line Length = 1886, Frame Length = 990. + */ + {0x3103, 0x11}, + {0x3008, 0x82}, + {OV5640_TABLE_WAIT_MS, 5}, + {0x3008, 0x42}, + {0x3103, 0x03}, + {0x3017, 0x00}, + {0x3018, 0x00}, + {0x3034, 0x18}, + {0x3035, 0x21}, + {0x3036, 0x70}, + {0x3037, 0x13}, + {0x3108, 0x01}, + {0x3630, 0x36}, + {0x3631, 0x0e}, + {0x3632, 0xe2}, + {0x3633, 0x12}, + {0x3621, 0xe0}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3905, 0x02}, + {0x3906, 0x10}, + {0x3901, 0x0a}, + {0x3731, 0x12}, + {0x3600, 0x08}, + {0x3601, 0x33}, + {0x302d, 0x60}, + {0x3620, 0x52}, + {0x371b, 0x20}, + {0x471c, 0x50}, + {0x3a13, 0x43}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3635, 0x13}, + {0x3636, 0x03}, + {0x3634, 0x40}, + {0x3622, 0x01}, + {0x3c01, 0x34}, + {0x3c04, 0x28}, + {0x3c05, 0x98}, + {0x3c06, 0x00}, + {0x3c07, 0x07}, + {0x3c08, 0x00}, + {0x3c09, 0x1c}, + {0x3c0a, 0x9c}, + {0x3c0b, 0x40}, + {0x3820, 0x41}, + {0x3821, 0x07}, + {0x3814, 0x31}, + {0x3815, 0x31}, + {0x3800, 0x00}, + {0x3801, 0x00}, + {0x3802, 0x00}, + {0x3803, 0x00}, + {0x3804, 0x0a}, + {0x3805, 0x3f}, + {0x3806, 0x07}, + {0x3807, 0x9f}, + {0x3808, 0x05}, + {0x3809, 0x18}, + {0x380a, 0x03}, + {0x380b, 0xcc}, + {0x380c, 0x07}, + {0x380d, 0x5e}, + {0x380e, 0x03}, + {0x380f, 0xde}, + {0x3810, 0x00}, + {0x3811, 0x06}, + {0x3812, 0x00}, + {0x3813, 0x02}, + {0x3618, 0x00}, + {0x3612, 0x29}, + {0x3708, 0x62}, + {0x3709, 0x52}, + {0x370c, 0x03}, + {0x3a02, 0x03}, + {0x3a03, 0xd8}, + {0x3a08, 0x01}, + {0x3a09, 0x27}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0e, 0x03}, + {0x3a0d, 0x04}, + {0x3a14, 0x03}, + {0x3a15, 0xd8}, + {0x4001, 0x02}, + {0x4004, 0x02}, + {0x3000, 0x00}, + {0x3002, 0x1c}, + {0x3004, 0xff}, + {0x3006, 0xc3}, + {0x300e, 0x45}, + {0x302e, 0x08}, + {0x4300, 0x32}, + {0x501f, 0x00}, + {0x4713, 0x02}, + {0x4407, 0x04}, + {0x440e, 0x00}, + {0x460b, 0x37}, + {0x460c, 0x20}, + {0x4800, 0x24}, + {0x4837, 0x10}, + {0x3824, 0x04}, + {0x5000, 0xa7}, + {0x5001, 0x83}, + {0x5180, 0xff}, + {0x5181, 0xf2}, + {0x5182, 0x00}, + {0x5183, 0x14}, + {0x5184, 0x25}, + {0x5185, 0x24}, + {0x5186, 0x09}, + {0x5187, 0x09}, + {0x5188, 0x09}, + {0x5189, 0x75}, + {0x518a, 0x54}, + {0x518b, 0xe0}, + {0x518c, 0xb2}, + {0x518d, 0x42}, + {0x518e, 0x3d}, + {0x518f, 0x56}, + {0x5190, 0x46}, + {0x5191, 0xf8}, + {0x5192, 0x04}, + {0x5193, 0x70}, + {0x5194, 0xf0}, + {0x5195, 0xf0}, + {0x5196, 0x03}, + {0x5197, 0x01}, + {0x5198, 0x04}, + {0x5199, 0x12}, + {0x519a, 0x04}, + {0x519b, 0x00}, + {0x519c, 0x06}, + {0x519d, 0x82}, + {0x519e, 0x38}, + {0x5381, 0x1e}, + {0x5382, 0x5b}, + {0x5383, 0x08}, + {0x5384, 0x0a}, + {0x5385, 0x7e}, + {0x5386, 0x88}, + {0x5387, 0x7c}, + {0x5388, 0x6c}, + {0x5389, 0x10}, + {0x538a, 0x01}, + {0x538b, 0x98}, + {0x5300, 0x08}, + {0x5301, 0x30}, + {0x5302, 0x10}, + {0x5303, 0x00}, + {0x5304, 0x08}, + {0x5305, 0x30}, + {0x5306, 0x08}, + {0x5307, 0x16}, + {0x5309, 0x08}, + {0x530a, 0x30}, + {0x530b, 0x04}, + {0x530c, 0x06}, + {0x5480, 0x01}, + {0x5481, 0x08}, + {0x5482, 0x14}, + {0x5483, 0x28}, + {0x5484, 0x51}, + {0x5485, 0x65}, + {0x5486, 0x71}, + {0x5487, 0x7d}, + {0x5488, 0x87}, + {0x5489, 0x91}, + {0x548a, 0x9a}, + {0x548b, 0xaa}, + {0x548c, 0xb8}, + {0x548d, 0xcd}, + {0x548e, 0xdd}, + {0x548f, 0xea}, + {0x5490, 0x1d}, + {0x5580, 0x02}, + {0x5583, 0x40}, + {0x5584, 0x10}, + {0x5589, 0x10}, + {0x558a, 0x00}, + {0x558b, 0xf8}, + {0x5800, 0x23}, + {0x5801, 0x14}, + {0x5802, 0x0f}, + {0x5803, 0x0f}, + {0x5804, 0x12}, + {0x5805, 0x26}, + {0x5806, 0x0c}, + {0x5807, 0x08}, + {0x5808, 0x05}, + {0x5809, 0x05}, + {0x580a, 0x08}, + {0x580b, 0x0d}, + {0x580c, 0x08}, + {0x580d, 0x03}, + {0x580e, 0x00}, + {0x580f, 0x00}, + {0x5810, 0x03}, + {0x5811, 0x09}, + {0x5812, 0x07}, + {0x5813, 0x03}, + {0x5814, 0x00}, + {0x5815, 0x01}, + {0x5816, 0x03}, + {0x5817, 0x08}, + {0x5818, 0x0d}, + {0x5819, 0x08}, + {0x581a, 0x05}, + {0x581b, 0x06}, + {0x581c, 0x08}, + {0x581d, 0x0e}, + {0x581e, 0x29}, + {0x581f, 0x17}, + {0x5820, 0x11}, + {0x5821, 0x11}, + {0x5822, 0x15}, + {0x5823, 0x28}, + {0x5824, 0x46}, + {0x5825, 0x26}, + {0x5826, 0x08}, + {0x5827, 0x26}, + {0x5828, 0x64}, + {0x5829, 0x26}, + {0x582a, 0x24}, + {0x582b, 0x22}, + {0x582c, 0x24}, + {0x582d, 0x24}, + {0x582e, 0x06}, + {0x582f, 0x22}, + {0x5830, 0x40}, + {0x5831, 0x42}, + {0x5832, 0x24}, + {0x5833, 0x26}, + {0x5834, 0x24}, + {0x5835, 0x22}, + {0x5836, 0x22}, + {0x5837, 0x26}, + {0x5838, 0x44}, + {0x5839, 0x24}, + {0x583a, 0x26}, + {0x583b, 0x28}, + {0x583c, 0x42}, + {0x583d, 0xce}, + {0x5025, 0x00}, + {0x3a0f, 0x30}, + {0x3a10, 0x28}, + {0x3a1b, 0x30}, + {0x3a1e, 0x26}, + {0x3a11, 0x60}, + {0x3a1f, 0x14}, + {0x3008, 0x02}, + {OV5640_TABLE_END, 0x0000} }; -static const struct ov5640_reg ov5640_defaults[] = { - { OV5640_SCCB_SYSTEM_CTRL1, 0x11}, - { OV5640_SYSTEM_CTRL, 0x82}, - { OV5640_SYSTEM_CTRL, 0x42}, - { OV5640_SCCB_SYSTEM_CTRL1, 0x03}, - { OV5640_PAD_OUTPUT_ENABLE01, 0x00}, - { OV5640_PAD_OUTPUT_ENABLE02, 0x00}, - { OV5640_SC_PLL_CTRL0, 0x18}, - { OV5640_SC_PLL_CTRL1, 0x14}, - { OV5640_SC_PLL_CTRL2, 0x38}, - { OV5640_SC_PLL_CTRL3, 0x13}, - { 0x4800, 0x24}, /* noncontinuous clock */ - { OV5640_SYSTEM_ROOT_DIVIDER, 0x01}, - { 0x3630, 0x36}, - { 0x3631, 0x0e}, - { 0x3632, 0xe2}, - { 0x3633, 0x12}, - { 0x3621, 0xe0}, - { 0x3704, 0xa0}, - { 0x3703, 0x5a}, - { 0x3715, 0x78}, - { 0x3717, 0x01}, - { 0x370b, 0x60}, - { 0x3705, 0x1a}, - { 0x3905, 0x02}, - { 0x3906, 0x10}, - { 0x3901, 0x0a}, - { 0x3731, 0x12}, - { 0x3600, 0x08}, - { 0x3601, 0x33}, - { 0x302d, 0x60}, - { 0x3620, 0x52}, - { 0x371b, 0x20}, - { 0x471c, 0x50}, - { 0x3a13, 0x43}, - { 0x3a18, 0x00}, - { 0x3a19, 0xf8}, - { 0x3635, 0x13}, - { 0x3636, 0x03}, - { 0x3634, 0x40}, - { 0x3622, 0x01}, - { 0x3c01, 0x34}, - { 0x3c04, 0x28}, - { 0x3c05, 0x98}, - { 0x3c06, 0x00}, - { 0x3c07, 0x08}, - { 0x3c08, 0x00}, - { 0x3c09, 0x1c}, - { 0x3c0a, 0x9c}, - { 0x3c0b, 0x40}, - { OV5640_TIMING_TC_REG20, 0x41}, - { OV5640_TIMING_TC_REG21, 0x01}, - { 0x3814, 0x31}, - { 0x3815, 0x31}, - { 0x3800, 0x00}, - { 0x3801, 0x00}, - { 0x3802, 0x00}, - { 0x3803, 0x04}, - { 0x3804, 0x0a}, - { 0x3805, 0x3f}, - { 0x3806, 0x07}, - { 0x3807, 0x9b}, - { 0x3808, 0x02}, - { 0x3809, 0x80}, - { 0x380a, 0x01}, - { 0x380b, 0xe0}, - { 0x380c, 0x07}, - { 0x380d, 0x68}, - { 0x380e, 0x03}, - { 0x380f, 0xd8}, - { 0x3810, 0x00}, - { 0x3811, 0x10}, - { 0x3812, 0x00}, - { 0x3813, 0x06}, - { 0x3618, 0x00}, - { 0x3612, 0x29}, - { 0x3708, 0x64}, - { 0x3709, 0x52}, - { 0x370c, 0x03}, +static struct ov5640_reg mode_640x480[] = { + {0x3103, 0x11}, + {0x3008, 0x82}, + {OV5640_TABLE_WAIT_MS, 5}, + {0x3008, 0x42}, + {0x3103, 0x03}, + {0x3017, 0x00}, + {0x3018, 0x00}, + {0x3034, 0x18}, + {0x3035, 0x14}, + {0x3036, 0x70}, + {0x3037, 0x13}, + {0x4800, 0x24}, /* noncontinuous clock */ + {0x3108, 0x01}, + {0x3630, 0x36}, + {0x3631, 0x0e}, + {0x3632, 0xe2}, + {0x3633, 0x12}, + {0x3621, 0xe0}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3905, 0x02}, + {0x3906, 0x10}, + {0x3901, 0x0a}, + {0x3731, 0x12}, + {0x3600, 0x08}, + {0x3601, 0x33}, + {0x302d, 0x60}, + {0x3620, 0x52}, + {0x371b, 0x20}, + {0x471c, 0x50}, + {0x3a13, 0x43}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3635, 0x13}, + {0x3636, 0x03}, + {0x3634, 0x40}, + {0x3622, 0x01}, + {0x3c01, 0x34}, + {0x3c04, 0x28}, + {0x3c05, 0x98}, + {0x3c06, 0x00}, + {0x3c07, 0x08}, + {0x3c08, 0x00}, + {0x3c09, 0x1c}, + {0x3c0a, 0x9c}, + {0x3c0b, 0x40}, + {0x3820, 0x41}, + {0x3821, 0x07}, + {0x3814, 0x31}, + {0x3815, 0x31}, + {0x3800, 0x00}, + {0x3801, 0x00}, + {0x3802, 0x00}, + {0x3803, 0x04}, + {0x3804, 0x0a}, + {0x3805, 0x3f}, + {0x3806, 0x07}, + {0x3807, 0x9b}, + {0x3808, 0x02}, + {0x3809, 0x80}, + {0x380a, 0x01}, + {0x380b, 0xe0}, + {0x380c, 0x07}, + {0x380d, 0x68}, + {0x380e, 0x03}, + {0x380f, 0xd8}, + {0x3810, 0x00}, + {0x3811, 0x10}, + {0x3812, 0x00}, + {0x3813, 0x06}, + {0x3618, 0x00}, + {0x3612, 0x29}, + {0x3708, 0x64}, + {0x3709, 0x52}, + {0x370c, 0x03}, /* AEC/AGC Power Down Domain Control */ - { OV5640_AEC_MAX_EXPO_60HZ_HI, 0x03}, - { OV5640_AEC_MAX_EXPO_60HZ_LO, 0xd8}, - { OV5640_AEC_B50_STEP_HI, 0x01}, - { OV5640_AEC_B50_STEP_LO, 0x27}, - { OV5640_AEC_B60_STEP_HI, 0x00}, - { OV5640_AEC_B60_STEP_LO, 0xf6}, - { OV5640_AEC_CTRL0E, 0x03}, - { OV5640_AEC_CTRL0D, 0x04}, - { OV5640_AEC_MAX_EXPO_50HZ_HI, 0x03}, - { OV5640_AEC_MAX_EXPO_50HZ_LO, 0xd8}, - - { 0x4001, 0x02}, - { 0x4004, 0x02}, - { 0x3000, 0x00}, - { 0x3002, 0x1c}, - { 0x3004, 0xff}, - { 0x3006, 0xc3}, - { 0x300e, 0x45}, - { 0x302e, 0x08}, + {0x3a02, 0x03}, + {0x3a03, 0xd8}, + {0x3a08, 0x01}, + {0x3a09, 0x27}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0e, 0x03}, + {0x3a0d, 0x04}, + {0x3a14, 0x03}, + {0x3a15, 0xd8}, + + {0x4001, 0x02}, + {0x4004, 0x02}, + {0x3000, 0x00}, + {0x3002, 0x1c}, + {0x3004, 0xff}, + {0x3006, 0xc3}, + {0x300e, 0x45}, + {0x302e, 0x08}, /* org:30 bit[3:0] 0x0:YUYV 0x1:YVYU 0x2:UYVY 0x3:VYUY 0xF:UYVY 0x4~0xE:Not-allowed */ - { 0x4300, 0x32}, - { 0x501f, 0x00}, - { 0x4713, 0x03}, - { 0x4407, 0x04}, - { 0x440e, 0x00}, - { 0x460b, 0x35}, - { 0x460c, 0x22}, - { 0x4837, 0x44}, - { 0x3824, 0x02}, - { 0x5000, 0xa7}, - { 0x5001, 0xa3}, + {0x4300, 0x32}, + {0x501f, 0x00}, + {0x4713, 0x03}, + {0x4407, 0x04}, + {0x440e, 0x00}, + {0x460b, 0x35}, + {0x460c, 0x22}, + {0x4837, 0x44}, + {0x3824, 0x02}, + {0x5000, 0xa7}, + {0x5001, 0xa3}, /* AWB Control */ - { OV5640_AWB_CTRL00, 0xff}, { OV5640_AWB_CTRL01, 0xf2}, - { OV5640_AWB_CTRL02, 0x00}, { OV5640_AWB_CTRL03, 0x14}, - { OV5640_AWB_CTRL04, 0x25}, { OV5640_AWB_CTRL05, 0x24}, - { OV5640_AWB_CTRL06, 0x09}, { OV5640_AWB_CTRL07, 0x09}, - { OV5640_AWB_CTRL08, 0x09}, { OV5640_AWB_CTRL09, 0x75}, - { OV5640_AWB_CTRL10, 0x54}, { OV5640_AWB_CTRL11, 0xe0}, - { OV5640_AWB_CTRL12, 0xb2}, { OV5640_AWB_CTRL13, 0x42}, - { OV5640_AWB_CTRL14, 0x3d}, { OV5640_AWB_CTRL15, 0x56}, - { OV5640_AWB_CTRL16, 0x46}, { OV5640_AWB_CTRL17, 0xf8}, - { OV5640_AWB_CTRL18, 0x04}, { OV5640_AWB_CTRL19, 0x70}, - { OV5640_AWB_CTRL20, 0xf0}, { OV5640_AWB_CTRL21, 0xf0}, - { OV5640_AWB_CTRL22, 0x03}, { OV5640_AWB_CTRL23, 0x01}, - { OV5640_AWB_CTRL24, 0x04}, { OV5640_AWB_CTRL25, 0x12}, - { OV5640_AWB_CTRL26, 0x04}, { OV5640_AWB_CTRL27, 0x00}, - { OV5640_AWB_CTRL28, 0x06}, { OV5640_AWB_CTRL29, 0x82}, - { OV5640_AWB_CTRL30, 0x38}, + {0x5180, 0xff}, + {0x5181, 0xf2}, + {0x5182, 0x00}, + {0x5183, 0x14}, + {0x5184, 0x25}, + {0x5185, 0x24}, + {0x5186, 0x09}, + {0x5187, 0x09}, + {0x5188, 0x09}, + {0x5189, 0x75}, + {0x518a, 0x54}, + {0x518b, 0xe0}, + {0x518c, 0xb2}, + {0x518d, 0x42}, + {0x518e, 0x3d}, + {0x518d, 0x56}, + {0x5190, 0x46}, + {0x5191, 0xf8}, + {0x5192, 0x04}, + {0x5193, 0x70}, + {0x5194, 0xf0}, + {0x5195, 0xf0}, + {0x5196, 0x03}, + {0x5197, 0x01}, + {0x5198, 0x04}, + {0x5199, 0x12}, + {0x519a, 0x04}, + {0x519b, 0x00}, + {0x519c, 0x06}, + {0x519d, 0x82}, + {0x519e, 0x38}, /* CMX Control */ - { OV5640_CMX1, 0x1e}, - { OV5640_CMX2, 0x5b}, - { OV5640_CMX3, 0x08}, - { OV5640_CMX4, 0x0a}, - { OV5640_CMX5, 0x7e}, - { OV5640_CMX6, 0x88}, - { OV5640_CMX7, 0x7c}, - { OV5640_CMX8, 0x6c}, - { OV5640_CMX9, 0x10}, - { OV5640_CMXSIGN_HI, 0x01}, - { OV5640_CMXSIGN_LO, 0x98}, + {0x5381, 0x1e}, + {0x5382, 0x5b}, + {0x5383, 0x08}, + {0x5384, 0x0a}, + {0x5385, 0x7e}, + {0x5386, 0x88}, + {0x5387, 0x7c}, + {0x5388, 0x6c}, + {0x5389, 0x10}, + {0x538a, 0x01}, + {0x538b, 0x98}, /* CIP Control */ - { OV5640_CIP_SHARPENMT_THRESHOLD_1, 0x08}, - { OV5640_CIP_SHARPENMT_THRESHOLD_2, 0x30}, - { OV5640_CIP_SHARPENMT_OFFSET_1, 0x10}, - { OV5640_CIP_SHARPENMT_OFFSET_2, 0x00}, - { OV5640_CIP_DNS_THRESHOLD_1, 0x08}, - { OV5640_CIP_DNS_THRESHOLD_2, 0x30}, - { OV5640_CIP_DNS_OFFSET_1, 0x08}, - { OV5640_CIP_DNS_OFFSET_2, 0x16}, - { OV5640_CIP_SHARPENTH_THRESHOLD_1, 0x08}, - { OV5640_CIP_SHARPENTH_THRESHOLD_2, 0x30}, - { OV5640_CIP_SHARPENTH_OFFSET_1, 0x04}, - { OV5640_CIP_SHARPENTH_OFFSET_2, 0x06}, + {0x5300, 0x08}, + {0x5301, 0x30}, + {0x5302, 0x10}, + {0x5303, 0x00}, + {0x5304, 0x08}, + {0x5305, 0x30}, + {0x5306, 0x08}, + {0x5307, 0x16}, + {0x5309, 0x08}, + {0x530a, 0x30}, + {0x530b, 0x04}, + {0x530c, 0x06}, /* Gamma Control */ - { OV5640_GAMMA_CTRL00, 0x01}, - { OV5640_YST00, 0x08}, { OV5640_YST01, 0x14}, - { OV5640_YST02, 0x28}, { OV5640_YST03, 0x51}, - { OV5640_YST04, 0x65}, { OV5640_YST05, 0x71}, - { OV5640_YST06, 0x7d}, { OV5640_YST07, 0x87}, - { OV5640_YST08, 0x91}, { OV5640_YST09, 0x9a}, - { OV5640_YST0A, 0xaa}, { OV5640_YST0B, 0xb8}, - { OV5640_YST0C, 0xcd}, { OV5640_YST0D, 0xdd}, - { OV5640_YST0E, 0xea}, { OV5640_YST0F, 0x1d}, + {0x5480, 0x01}, + {0x5481, 0x08}, + {0x5482, 0x14}, + {0x5483, 0x28}, + {0x5484, 0x51}, + {0x5485, 0x65}, + {0x5486, 0x71}, + {0x5487, 0x7d}, + {0x5488, 0x87}, + {0x5489, 0x91}, + {0x548a, 0x9a}, + {0x548b, 0xaa}, + {0x548c, 0xb8}, + {0x548d, 0xcd}, + {0x548e, 0xdd}, + {0x548f, 0xea}, + {0x5490, 0x1d}, /* SDE Control */ - { OV5640_SDE_CTRL_0, 0x02}, - { OV5640_SDE_CTRL_3, 0x40}, - { OV5640_SDE_CTRL_4, 0x10}, - { OV5640_SDE_CTRL_9, 0x10}, - { OV5640_SDE_CTRL_10, 0x00}, - { OV5640_SDE_CTRL_11, 0xf8}, + {0x5580, 0x02}, + {0x5583, 0x40}, + {0x5584, 0x10}, + {0x5589, 0x10}, + {0x558a, 0x00}, + {0x558b, 0xf8}, /* LENC Control */ - { OV5640_GMTRX00, 0x23}, { OV5640_GMTRX01, 0x14}, - { OV5640_GMTRX02, 0x0f}, { OV5640_GMTRX03, 0x0f}, - { OV5640_GMTRX04, 0x12}, { OV5640_GMTRX05, 0x26}, - { OV5640_GMTRX10, 0x0c}, { OV5640_GMTRX11, 0x08}, - { OV5640_GMTRX12, 0x05}, { OV5640_GMTRX13, 0x05}, - { OV5640_GMTRX14, 0x08}, { OV5640_GMTRX15, 0x0d}, - { OV5640_GMTRX20, 0x08}, { OV5640_GMTRX21, 0x03}, - { OV5640_GMTRX22, 0x00}, { OV5640_GMTRX23, 0x00}, - { OV5640_GMTRX24, 0x03}, { OV5640_GMTRX25, 0x09}, - { OV5640_GMTRX30, 0x07}, { OV5640_GMTRX31, 0x03}, - { OV5640_GMTRX32, 0x00}, { OV5640_GMTRX33, 0x01}, - { OV5640_GMTRX34, 0x03}, { OV5640_GMTRX35, 0x08}, - { OV5640_GMTRX40, 0x0d}, { OV5640_GMTRX41, 0x08}, - { OV5640_GMTRX42, 0x05}, { OV5640_GMTRX43, 0x06}, - { OV5640_GMTRX44, 0x08}, { OV5640_GMTRX45, 0x0e}, - { OV5640_GMTRX50, 0x29}, { OV5640_GMTRX51, 0x17}, - { OV5640_GMTRX52, 0x11}, { OV5640_GMTRX53, 0x11}, - { OV5640_GMTRX54, 0x15}, { OV5640_GMTRX55, 0x28}, - { OV5640_BRMATRX00, 0x46}, { OV5640_BRMATRX01, 0x26}, - { OV5640_BRMATRX02, 0x08}, { OV5640_BRMATRX03, 0x26}, - { OV5640_BRMATRX04, 0x64}, { OV5640_BRMATRX05, 0x26}, - { OV5640_BRMATRX06, 0x24}, { OV5640_BRMATRX07, 0x22}, - { OV5640_BRMATRX08, 0x24}, { OV5640_BRMATRX09, 0x24}, - { OV5640_BRMATRX20, 0x06}, { OV5640_BRMATRX21, 0x22}, - { OV5640_BRMATRX22, 0x40}, { OV5640_BRMATRX23, 0x42}, - { OV5640_BRMATRX24, 0x24}, { OV5640_BRMATRX30, 0x26}, - { OV5640_BRMATRX31, 0x24}, { OV5640_BRMATRX32, 0x22}, - { OV5640_BRMATRX33, 0x22}, { OV5640_BRMATRX34, 0x26}, - { OV5640_BRMATRX40, 0x44}, { OV5640_BRMATRX41, 0x24}, - { OV5640_BRMATRX42, 0x26}, { OV5640_BRMATRX43, 0x28}, - { OV5640_BRMATRX44, 0x42}, { OV5640_LENC_BR_OFFSET, 0xce}, - - { OV5640_ISP_CTRL37, 0x00}, - { OV5640_AEC_CTRL0F, 0x30}, - { OV5640_AEC_CTRL10, 0x28}, - { OV5640_AEC_CTRL1B, 0x30}, - { OV5640_AEC_CTRL1E, 0x26}, - { OV5640_AEC_CTRL11, 0x60}, - { OV5640_AEC_CTRL1F, 0x14}, - { OV5640_SYSTEM_CTRL, 0x02}, + {0x5800, 0x23}, + {0x5801, 0x14}, + {0x5802, 0x0f}, + {0x5803, 0x0f}, + {0x5804, 0x12}, + {0x5805, 0x26}, + {0x5806, 0x0c}, + {0x5807, 0x08}, + {0x5808, 0x05}, + {0x5809, 0x05}, + {0x580a, 0x08}, + {0x580b, 0x0d}, + {0x580c, 0x08}, + {0x580d, 0x03}, + {0x580e, 0x00}, + {0x580f, 0x00}, + {0x5810, 0x03}, + {0x5811, 0x09}, + {0x5812, 0x07}, + {0x5813, 0x03}, + {0x5814, 0x00}, + {0x5815, 0x01}, + {0x5816, 0x03}, + {0x5817, 0x08}, + {0x5818, 0x0d}, + {0x5819, 0x08}, + {0x581a, 0x05}, + {0x581b, 0x06}, + {0x581c, 0x08}, + {0x581d, 0x0e}, + {0x581e, 0x29}, + {0x581f, 0x17}, + {0x5820, 0x11}, + {0x5821, 0x11}, + {0x5822, 0x15}, + {0x5823, 0x28}, + {0x5824, 0x46}, + {0x5825, 0x26}, + {0x5826, 0x08}, + {0x5827, 0x26}, + {0x5828, 0x64}, + {0x5829, 0x26}, + {0x582a, 0x24}, + {0x582b, 0x22}, + {0x582c, 0x24}, + {0x582d, 0x24}, + {0x582e, 0x06}, + {0x582f, 0x22}, + {0x5830, 0x40}, + {0x5831, 0x42}, + {0x5832, 0x24}, + {0x5833, 0x26}, + {0x5834, 0x24}, + {0x5835, 0x22}, + {0x5836, 0x22}, + {0x5837, 0x26}, + {0x5838, 0x44}, + {0x5839, 0x24}, + {0x583a, 0x26}, + {0x583b, 0x28}, + {0x583c, 0x42}, + {0x583d, 0xce}, + + {0x5025, 0x00}, + {0x3a0f, 0x30}, + {0x3a10, 0x28}, + {0x3a1b, 0x30}, + {0x3a1e, 0x26}, + {0x3a11, 0x60}, + {0x3a1f, 0x14}, + {0x3008, 0x02}, + {OV5640_TABLE_END, 0x0000}, +}; + +enum { + OV5640_MODE_640x480, + OV5640_MODE_1296x972, + OV5640_MODE_1920x1080, + OV5640_MODE_2592x1944, + OV5640_SIZE_LAST, +}; + +static struct ov5640_reg *mode_table[] = { + [OV5640_MODE_640x480] = mode_640x480, + [OV5640_MODE_1296x972] = mode_1296x972, + [OV5640_MODE_1920x1080] = mode_1920x1080, + [OV5640_MODE_2592x1944] = mode_2592x1944, +}; + +static int test_pattern; +module_param(test_pattern, int, 0644); + +static struct ov5640_reg tp_cbars[] = { + {0x503D, 0x80}, + {0x503E, 0x00}, + {0x5046, 0x01}, + {OV5640_TABLE_END, 0x0000} +}; + +#define to_ov5640(sd) container_of(sd, struct ov5640_priv, subdev) + +#define SIZEOF_I2C_TRANSBUF 32 + +struct ov5640_priv { + struct v4l2_subdev subdev; + struct v4l2_mbus_framefmt mf; + + int ident; + u16 chip_id; + u8 revision; + + int mode; + + struct i2c_client *client; + u8 i2c_trans_buf[SIZEOF_I2C_TRANSBUF]; }; static enum v4l2_mbus_pixelcode ov5640_codes[] = { - V4L2_MBUS_FMT_YUYV8_2X8, + V4L2_MBUS_FMT_UYVY8_2X8, }; -static const struct v4l2_queryctrl ov5640_controls[] = { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Flip Vertically", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Flip Horizontally", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, +static const struct v4l2_frmsize_discrete ov5640_frmsizes[OV5640_SIZE_LAST] = { + {640, 480}, + {1296, 972}, + {1920, 1080}, + {2592, 1944}, }; -/* read a register */ -static int ov5640_reg_read(struct i2c_client *client, u16 reg, u8 *val) +static int ov5640_find_mode(u32 width, u32 height) { - int ret; - unsigned char data[2] = { reg >> 8, reg & 0xff }; + int i; - ret = i2c_master_send(client, data, 2); - if (ret < 2) { - dev_err(&client->dev, "%s: i2c read error, reg: %x\n", - __func__, reg); - return ret < 0 ? ret : -EIO; + for (i = 0; i < OV5640_SIZE_LAST; i++) { + if ((ov5640_frmsizes[i].width >= width) && + (ov5640_frmsizes[i].height >= height)) + break; } - ret = i2c_master_recv(client, val, 1); - if (ret < 1) { - dev_err(&client->dev, "%s: i2c read error, reg: %x\n", - __func__, reg); - return ret < 0 ? ret : -EIO; - } + /* If not found, select biggest */ + if (i >= OV5640_SIZE_LAST) + i = OV5640_SIZE_LAST - 1; - return 0; + return i; } -/* write a register */ -static int ov5640_reg_write(struct i2c_client *client, u16 reg, u8 val) +static int ov5640_read_reg(struct i2c_client *client, u16 addr, u8 *val) { - int ret; - unsigned char data[3] = { reg >> 8, reg & 0xff, val }; + int err; + struct i2c_msg msg[2]; + unsigned char data[3]; - ret = i2c_master_send(client, data, 3); - if (ret < 3) { - dev_err(&client->dev, "%s: i2c write error, reg: %x\n", - __func__, reg); - return ret < 0 ? ret : -EIO; - } + if (!client->adapter) + return -ENODEV; - return 0; -} + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 2; + msg[0].buf = data; + /* high byte goes out first */ + data[0] = (u8) (addr >> 8); + data[1] = (u8) (addr & 0xff); -/* Read a register, alter its bits, write it back */ -static int ov5640_reg_rmw(struct i2c_client *client, u16 reg, u8 set, u8 unset) -{ - u8 val; - int ret; + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = 1; + msg[1].buf = data + 2; - ret = ov5640_reg_read(client, reg, &val); - if (ret < 0) { - dev_err(&client->dev, - "[Read]-Modify-Write of register 0x%04x failed!\n", - reg); - return ret; - } + err = i2c_transfer(client->adapter, msg, 2); - val |= set; - val &= ~unset; + if (err != 2) + return -EINVAL; - ret = ov5640_reg_write(client, reg, val); - if (ret < 0) { - dev_err(&client->dev, - "Read-Modify-[Write] of register 0x%04x failed!\n", - reg); - return ret; - } + *val = data[2]; return 0; } -static int ov5640_reg_write_array(struct i2c_client *client, - const struct ov5640_reg *regarray, - int regarraylen) +static int ov5640_write_reg(struct i2c_client *client, u16 addr, u8 value) { - int i; - int ret; + int count; + struct i2c_msg msg[1]; + unsigned char data[4]; - for (i = 0; i < regarraylen; i++) { - ret = ov5640_reg_write(client, - regarray[i].reg, regarray[i].val); - if (ret < 0) - return ret; - } + if (!client->adapter) + return -ENODEV; - return 0; + data[0] = addr; + data[1] = (u8) (addr & 0xff); + data[2] = value; + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 3; + msg[0].buf = data; + + count = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (count == ARRAY_SIZE(msg)) + return 0; + dev_err(&client->dev, + "ov5840: i2c transfer failed, addr: %x, value: %02x\n", + addr, (u32)value); + return -EIO; } -/* Start/Stop streaming from the device */ -static int ov5640_s_stream(struct v4l2_subdev *sd, int enable) +static int ov5640_write_bulk_reg(struct i2c_client *client, u8 *data, int len) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov5640_priv *priv = to_ov5640(sd); - int ret; + int err; + struct i2c_msg msg; - /* Program orientation register. */ - if (priv->flag_vflip) - ret = ov5640_reg_rmw(client, OV5640_TIMING_TC_REG20, 0x2, 0); - else - ret = ov5640_reg_rmw(client, OV5640_TIMING_TC_REG20, 0, 0x2); - if (ret < 0) - return ret; + if (!client->adapter) + return -ENODEV; - if (priv->flag_hflip) - ret = ov5640_reg_rmw(client, OV5640_TIMING_TC_REG21, 0x2, 0); - else - ret = ov5640_reg_rmw(client, OV5640_TIMING_TC_REG21, 0, 0x2); - if (ret < 0) - return ret; + msg.addr = client->addr; + msg.flags = 0; + msg.len = len; + msg.buf = data; - if (!enable) { - /* Software Reset */ - ret = ov5640_reg_write(client, OV5640_SYSTEM_CTRL, 0x82); - if (!ret) - /* Setting Streaming to Standby */ - ret = ov5640_reg_write(client, OV5640_SYSTEM_CTRL, - 0x42); - } + err = i2c_transfer(client->adapter, &msg, 1); + if (err == 1) + return 0; - priv->current_enable = enable; + dev_err(&client->dev, "ov5640: i2c transfer failed at %x\n", + (int)data[0] << 8 | data[1]); - return ret; + return err; } -/* Alter bus settings on camera side */ -static int ov5640_set_bus_param(struct soc_camera_device *icd, - unsigned long flags) +static int ov5640_write_table(struct ov5640_priv *priv, + struct ov5640_reg table[]) { + int err; + struct ov5640_reg *next, *n_next; + u8 *b_ptr = priv->i2c_trans_buf; + unsigned int buf_filled = 0; + u16 val; + + for (next = table; next->addr != OV5640_TABLE_END; next++) { + if (next->addr == OV5640_TABLE_WAIT_MS) { + msleep(next->val); + continue; + } + + val = next->val; + + if (!buf_filled) { + b_ptr = priv->i2c_trans_buf; + *b_ptr++ = next->addr >> 8; + *b_ptr++ = next->addr & 0xff; + buf_filled = 2; + } + *b_ptr++ = val; + buf_filled++; + + n_next = next + 1; + if (n_next->addr != OV5640_TABLE_END && + n_next->addr != OV5640_TABLE_WAIT_MS && + buf_filled < SIZEOF_I2C_TRANSBUF && + n_next->addr == next->addr + 1) { + continue; + } + + err = ov5640_write_bulk_reg(priv->client, + priv->i2c_trans_buf, buf_filled); + if (err) + return err; + + buf_filled = 0; + } return 0; } -/* Request bus settings on camera side */ -static unsigned long ov5640_query_bus_param(struct soc_camera_device *icd) -{ - struct soc_camera_link *icl = to_soc_camera_link(icd); - - unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | - SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | - SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; - - return soc_camera_apply_sensor_flags(icl, flags); -} - -/* select nearest higher resolution for capture */ -static void ov5640_res_roundup(u32 *width, u32 *height) +static void ov5640_set_default_fmt(struct ov5640_priv *priv) { - /* Width must be a multiple of 4 pixels. */ - *width = ALIGN(*width, 4); + struct v4l2_mbus_framefmt *mf = &priv->mf; - /* Max resolution is 1280x720 (720p). */ - if (*width > OV5640_MAX_WIDTH) - *width = OV5640_MAX_WIDTH; - - if (*height > OV5640_MAX_HEIGHT) - *height = OV5640_MAX_HEIGHT; + mf->width = ov5640_frmsizes[OV5640_MODE_2592x1944].width; + mf->height = ov5640_frmsizes[OV5640_MODE_2592x1944].height; + mf->code = V4L2_MBUS_FMT_UYVY8_2X8; + mf->field = V4L2_FIELD_NONE; + mf->colorspace = V4L2_COLORSPACE_SRGB; } -/* Setup registers according to resolution and color encoding */ -static int ov5640_set_res(struct i2c_client *client, u32 width, u32 height) +/* Start/Stop streaming from the device */ +static int ov5640_s_stream(struct v4l2_subdev *sd, int enable) { - /* Note, this stuff is bogus. It's just copied from ov9740.c. */ -#if 0 - u32 x_start; - u32 y_start; - u32 x_end; - u32 y_end; - bool scaling = 0; - u32 scale_input_x; - u32 scale_input_y; - int ret; - - if ((width != OV5640_MAX_WIDTH) || (height != OV5640_MAX_HEIGHT)) - scaling = 1; + struct ov5640_priv *priv = to_ov5640(sd); + int ret = 0; - /* - * Try to use as much of the sensor area as possible when supporting - * smaller resolutions. Depending on the aspect ratio of the - * chosen resolution, we can either use the full width of the sensor, - * or the full height of the sensor (or both if the aspect ratio is - * the same as 1280x720. - */ - if ((OV5640_MAX_WIDTH * height) > (OV5640_MAX_HEIGHT * width)) { - scale_input_x = (OV5640_MAX_HEIGHT * width) / height; - scale_input_y = OV5640_MAX_HEIGHT; - } else { - scale_input_x = OV5640_MAX_WIDTH; - scale_input_y = (OV5640_MAX_WIDTH * height) / width; + if (!enable) { + ov5640_set_default_fmt(priv); + return 0; } - /* These describe the area of the sensor to use. */ - x_start = (OV5640_MAX_WIDTH - scale_input_x) / 2; - y_start = (OV5640_MAX_HEIGHT - scale_input_y) / 2; - x_end = x_start + scale_input_x - 1; - y_end = y_start + scale_input_y - 1; - - ret = ov5640_reg_write(client, OV5640_X_ADDR_START_HI, x_start >> 8); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_X_ADDR_START_LO, x_start & 0xff); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_Y_ADDR_START_HI, y_start >> 8); + ret = ov5640_write_table(priv, mode_table[priv->mode]); if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_Y_ADDR_START_LO, y_start & 0xff); - if (ret) - goto done; + return ret; - ret = ov5640_reg_write(client, OV5640_X_ADDR_END_HI, x_end >> 8); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_X_ADDR_END_LO, x_end & 0xff); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_Y_ADDR_END_HI, y_end >> 8); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_Y_ADDR_END_LO, y_end & 0xff); - if (ret) - goto done; + if (test_pattern == 1) { + ret = ov5640_write_table(priv, tp_cbars); + if (ret) + return ret; + } - ret = ov5640_reg_write(client, OV5640_X_OUTPUT_SIZE_HI, width >> 8); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_X_OUTPUT_SIZE_LO, width & 0xff); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_Y_OUTPUT_SIZE_HI, height >> 8); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_Y_OUTPUT_SIZE_LO, height & 0xff); - if (ret) - goto done; + return ret; +} - ret = ov5640_reg_write(client, OV5640_ISP_CTRL1E, scale_input_x >> 8); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_ISP_CTRL1F, scale_input_x & 0xff); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_ISP_CTRL20, scale_input_y >> 8); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_ISP_CTRL21, scale_input_y & 0xff); - if (ret) - goto done; +static int ov5640_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + int mode; - ret = ov5640_reg_write(client, OV5640_VFIFO_READ_START_HI, - (scale_input_x - width) >> 8); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_VFIFO_READ_START_LO, - (scale_input_x - width) & 0xff); - if (ret) - goto done; + mode = ov5640_find_mode(mf->width, mf->height); + mf->width = ov5640_frmsizes[mode].width; + mf->height = ov5640_frmsizes[mode].height; - ret = ov5640_reg_write(client, OV5640_ISP_CTRL00, 0xff); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_ISP_CTRL01, 0xef | - (scaling << 4)); - if (ret) - goto done; - ret = ov5640_reg_write(client, OV5640_ISP_CTRL03, 0xff); + mf->field = V4L2_FIELD_NONE; + mf->code = V4L2_MBUS_FMT_UYVY8_2X8; + mf->colorspace = V4L2_COLORSPACE_SRGB; -done: - return ret; -#endif return 0; } @@ -815,47 +1347,16 @@ done: static int ov5640_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov5640_priv *priv = to_ov5640(sd); - enum v4l2_colorspace cspace; - enum v4l2_mbus_pixelcode code = mf->code; int ret; - ov5640_res_roundup(&mf->width, &mf->height); - - switch (code) { - case V4L2_MBUS_FMT_YUYV8_2X8: - cspace = V4L2_COLORSPACE_SRGB; - break; - default: - return -EINVAL; - } - - ret = ov5640_reg_write_array(client, ov5640_defaults, - ARRAY_SIZE(ov5640_defaults)); - if (ret < 0) - return ret; - - ret = ov5640_set_res(client, mf->width, mf->height); + ret = ov5640_try_fmt(sd, mf); if (ret < 0) return ret; - mf->code = code; - mf->colorspace = cspace; + priv->mode = ov5640_find_mode(mf->width, mf->height); - memcpy(&priv->current_mf, mf, sizeof(struct v4l2_mbus_framefmt)); - - return ret; -} - -static int ov5640_try_fmt(struct v4l2_subdev *sd, - struct v4l2_mbus_framefmt *mf) -{ - ov5640_res_roundup(&mf->width, &mf->height); - - mf->field = V4L2_FIELD_NONE; - mf->code = V4L2_MBUS_FMT_YUYV8_2X8; - mf->colorspace = V4L2_COLORSPACE_SRGB; + memcpy(&priv->mf, mf, sizeof(struct v4l2_mbus_framefmt)); return 0; } @@ -875,8 +1376,8 @@ static int ov5640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) { a->bounds.left = 0; a->bounds.top = 0; - a->bounds.width = OV5640_MAX_WIDTH; - a->bounds.height = OV5640_MAX_HEIGHT; + a->bounds.width = ov5640_frmsizes[OV5640_MODE_2592x1944].width; + a->bounds.height = ov5640_frmsizes[OV5640_MODE_2592x1944].height; a->defrect = a->bounds; a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; a->pixelaspect.numerator = 1; @@ -889,51 +1390,13 @@ static int ov5640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { a->c.left = 0; a->c.top = 0; - a->c.width = OV5640_MAX_WIDTH; - a->c.height = OV5640_MAX_HEIGHT; + a->c.width = ov5640_frmsizes[OV5640_MODE_2592x1944].width; + a->c.height = ov5640_frmsizes[OV5640_MODE_2592x1944].height; a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; return 0; } -/* Get status of additional camera capabilities */ -static int ov5640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct ov5640_priv *priv = to_ov5640(sd); - - switch (ctrl->id) { - case V4L2_CID_VFLIP: - ctrl->value = priv->flag_vflip; - break; - case V4L2_CID_HFLIP: - ctrl->value = priv->flag_hflip; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* Set status of additional camera capabilities */ -static int ov5640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct ov5640_priv *priv = to_ov5640(sd); - - switch (ctrl->id) { - case V4L2_CID_VFLIP: - priv->flag_vflip = ctrl->value; - break; - case V4L2_CID_HFLIP: - priv->flag_hflip = ctrl->value; - break; - default: - return -EINVAL; - } - - return 0; -} - /* Get chip identification */ static int ov5640_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id) @@ -946,24 +1409,6 @@ static int ov5640_g_chip_ident(struct v4l2_subdev *sd, return 0; } -static int ov5640_s_power(struct v4l2_subdev *sd, int on) -{ - struct ov5640_priv *priv = to_ov5640(sd); - - if (!priv->current_enable) - return 0; - - if (on) { - ov5640_s_fmt(sd, &priv->current_mf); - ov5640_s_stream(sd, priv->current_enable); - } else { - ov5640_s_stream(sd, 0); - priv->current_enable = true; - } - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov5640_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -977,7 +1422,7 @@ static int ov5640_get_register(struct v4l2_subdev *sd, reg->size = 2; - ret = ov5640_reg_read(client, reg->reg, &val); + ret = ov5640_read_reg(client, reg->reg, &val); if (ret) return ret; @@ -994,53 +1439,32 @@ static int ov5640_set_register(struct v4l2_subdev *sd, if (reg->reg & ~0xffff || reg->val & ~0xff) return -EINVAL; - return ov5640_reg_write(client, reg->reg, reg->val); + return ov5640_write_reg(client, reg->reg, reg->val); } #endif -static int ov5640_video_probe(struct soc_camera_device *icd, - struct i2c_client *client) +/* Alter bus settings on camera side */ +static int ov5640_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) { - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct ov5640_priv *priv = to_ov5640(sd); - u8 chip_id_hi, chip_id_lo; - int ret; - - /* We must have a parent by now. And it cannot be a wrong one. */ - BUG_ON(!icd->parent || - to_soc_camera_host(icd->parent)->nr != icd->iface); - - /* - * check and show product ID and manufacturer ID - */ - ret = ov5640_reg_read(client, OV5640_CHIP_ID_HI, &chip_id_hi); - if (ret < 0) - goto err; - - ret = ov5640_reg_read(client, OV5640_CHIP_ID_LO, &chip_id_lo); - if (ret < 0) - goto err; - - priv->chip_id = (chip_id_hi << 8) | chip_id_lo; - - if (priv->chip_id != 0x5640) { - ret = -ENODEV; - goto err; - } + return 0; +} - priv->ident = V4L2_IDENT_OV5640; +/* Request bus settings on camera side */ +static unsigned long ov5640_query_bus_param(struct soc_camera_device *icd) +{ + struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_info(&client->dev, "Chip ID 0x%04x\n", priv->chip_id); + unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; -err: - return ret; + return soc_camera_apply_sensor_flags(icl, flags); } static struct soc_camera_ops ov5640_ops = { .set_bus_param = ov5640_set_bus_param, .query_bus_param = ov5640_query_bus_param, - .controls = ov5640_controls, - .num_controls = ARRAY_SIZE(ov5640_controls), }; static struct v4l2_subdev_video_ops ov5640_video_ops = { @@ -1053,10 +1477,7 @@ static struct v4l2_subdev_video_ops ov5640_video_ops = { }; static struct v4l2_subdev_core_ops ov5640_core_ops = { - .g_ctrl = ov5640_g_ctrl, - .s_ctrl = ov5640_s_ctrl, .g_chip_ident = ov5640_g_chip_ident, - .s_power = ov5640_s_power, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov5640_get_register, .s_register = ov5640_set_register, @@ -1077,6 +1498,7 @@ static int ov5640_probe(struct i2c_client *client, struct ov5640_priv *priv; struct soc_camera_device *icd = client->dev.platform_data; struct soc_camera_link *icl; + u8 chip_id_hi, chip_id_lo; int ret; if (!icd) { @@ -1090,31 +1512,52 @@ static int ov5640_probe(struct i2c_client *client, return -EINVAL; } - priv = kzalloc(sizeof(struct ov5640_priv), GFP_KERNEL); + priv = devm_kzalloc(&client->dev, sizeof(struct ov5640_priv), + GFP_KERNEL); if (!priv) { dev_err(&client->dev, "Failed to allocate private data!\n"); return -ENOMEM; } v4l2_i2c_subdev_init(&priv->subdev, client, &ov5640_subdev_ops); - icd->ops = &ov5640_ops; - ret = ov5640_video_probe(icd, client); + priv->client = client; + + priv->ident = V4L2_IDENT_OV5640; + + /* + * check and show product ID and manufacturer ID + */ + ret = ov5640_read_reg(client, 0x300A, &chip_id_hi); if (ret < 0) { - icd->ops = NULL; - kfree(priv); + dev_err(&client->dev, "Failure to read Chip ID (high byte)\n"); + return ret; } + ret = ov5640_read_reg(client, 0x300B, &chip_id_lo); + if (ret < 0) { + dev_err(&client->dev, "Failure to read Chip ID (low byte)\n"); + return ret; + } + + priv->chip_id = (chip_id_hi << 8) | chip_id_lo; + + if (priv->chip_id != 0x5640) { + dev_err(&client->dev, "Chip ID: %x not supported!\n", + priv->chip_id); + ret = -ENODEV; + return ret; + } + + ov5640_set_default_fmt(priv); + + dev_info(&client->dev, "Chip ID 0x%04x\n", priv->chip_id); return ret; } static int ov5640_remove(struct i2c_client *client) { - struct ov5640_priv *priv = i2c_get_clientdata(client); - - kfree(priv); - return 0; } -- cgit v1.2.3 From dd9a841da571a41d43f1eeaac1785b2adb1d80f3 Mon Sep 17 00:00:00 2001 From: Vikram Fugro Date: Wed, 30 Oct 2013 13:23:40 +0530 Subject: media: camera config changes - Disables TEGRA_CAMERA - Enables SOC_CAMERA and OV5640 sensor support Bug 1369083 Change-Id: I073c226e9f04a6f4f4699051f624a755dceb36cb Signed-off-by: Vikram Fugro Reviewed-on: http://git-master/r/309491 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Matthew Pedro --- arch/arm/configs/tegra3_defconfig | 5 ++++- drivers/media/video/tegra/Kconfig | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/tegra3_defconfig b/arch/arm/configs/tegra3_defconfig index 9f212bbad50b..207c5e5771dc 100644 --- a/arch/arm/configs/tegra3_defconfig +++ b/arch/arm/configs/tegra3_defconfig @@ -324,7 +324,10 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y # CONFIG_TEGRA_AVP is not set # CONFIG_TEGRA_MEDIASERVER is not set CONFIG_TEGRA_NVAVP=y -CONFIG_VIDEO_OV5650=m +#CONFIG_VIDEO_OV5650 is not set +CONFIG_SOC_CAMERA=y +CONFIG_VIDEO_TEGRA=y +CONFIG_SOC_CAMERA_OV5640=y CONFIG_VIDEO_OV2710=m CONFIG_TORCH_SSL3250A=m CONFIG_TORCH_TPS61050=m diff --git a/drivers/media/video/tegra/Kconfig b/drivers/media/video/tegra/Kconfig index 5099fe12c3e2..571b49bfd699 100644 --- a/drivers/media/video/tegra/Kconfig +++ b/drivers/media/video/tegra/Kconfig @@ -5,7 +5,6 @@ source "drivers/media/video/tegra/nvavp/Kconfig" config TEGRA_CAMERA bool "Enable support for tegra camera/isp hardware" depends on ARCH_TEGRA - default y help Enables support for the Tegra camera interface -- cgit v1.2.3 From 2cfae82f4f11691c291c85f9d4ff2ec73ea74e57 Mon Sep 17 00:00:00 2001 From: Vikram Fugro Date: Thu, 7 Nov 2013 01:44:29 -0800 Subject: Revert "media: camera config changes" This reverts commit dd9a841da571a41d43f1eeaac1785b2adb1d80f3. The config changes (for V4L2) can be done manually as per need basis for V4L2, followed by compiling the kernel. Change-Id: I9174bce0f3da2974ab703b238dfb8fb3bbf607c5 Signed-off-by: Vikram Fugro Reviewed-on: http://git-master/r/327607 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Kaustubh Purandare Reviewed-by: Winnie Hsu Reviewed-by: Matthew Pedro --- arch/arm/configs/tegra3_defconfig | 5 +---- drivers/media/video/tegra/Kconfig | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/tegra3_defconfig b/arch/arm/configs/tegra3_defconfig index 207c5e5771dc..9f212bbad50b 100644 --- a/arch/arm/configs/tegra3_defconfig +++ b/arch/arm/configs/tegra3_defconfig @@ -324,10 +324,7 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y # CONFIG_TEGRA_AVP is not set # CONFIG_TEGRA_MEDIASERVER is not set CONFIG_TEGRA_NVAVP=y -#CONFIG_VIDEO_OV5650 is not set -CONFIG_SOC_CAMERA=y -CONFIG_VIDEO_TEGRA=y -CONFIG_SOC_CAMERA_OV5640=y +CONFIG_VIDEO_OV5650=m CONFIG_VIDEO_OV2710=m CONFIG_TORCH_SSL3250A=m CONFIG_TORCH_TPS61050=m diff --git a/drivers/media/video/tegra/Kconfig b/drivers/media/video/tegra/Kconfig index 571b49bfd699..5099fe12c3e2 100644 --- a/drivers/media/video/tegra/Kconfig +++ b/drivers/media/video/tegra/Kconfig @@ -5,6 +5,7 @@ source "drivers/media/video/tegra/nvavp/Kconfig" config TEGRA_CAMERA bool "Enable support for tegra camera/isp hardware" depends on ARCH_TEGRA + default y help Enables support for the Tegra camera interface -- cgit v1.2.3 From 2fb9cd0d92979598e3aa5319babdbe6be4c6df22 Mon Sep 17 00:00:00 2001 From: Vikram Fugro Date: Wed, 30 Oct 2013 13:40:20 +0530 Subject: media: nvmap: Few tweaks in nvmap The tweaks are only specific to r16-r2 branch and will not go into mainline. - Pass nvmap memory handle to the user through the mmap'd buffer allocated by videobuf2 client. - Allow the "user" nvmap client to access the nvmap memory handle of "videobuf2-dma-nvmap" client. Re-arranging the copyright message in nvmap_dev.c for Automatic validation to pass. Bug 1369083 Change-Id: Ia27d172253860e79557911c2e848bc9084d662d4 Signed-off-by: Vikram Fugro Reviewed-on: http://git-master/r/309494 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Krishna Reddy Reviewed-by: Kaustubh Purandare Reviewed-by: Winnie Hsu Reviewed-by: Matthew Pedro --- drivers/media/video/videobuf2-dma-nvmap.c | 2 ++ drivers/video/tegra/nvmap/nvmap_dev.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/videobuf2-dma-nvmap.c b/drivers/media/video/videobuf2-dma-nvmap.c index 5ab3c62ac05b..4ba8fed0cc02 100644 --- a/drivers/media/video/videobuf2-dma-nvmap.c +++ b/drivers/media/video/videobuf2-dma-nvmap.c @@ -82,6 +82,8 @@ static void *vb2_dma_nvmap_alloc(void *alloc_ctx, unsigned long size) buf->handler.put = vb2_dma_nvmap_put; buf->handler.arg = buf; + *((unsigned long *)buf->vaddr) = (unsigned long)buf->nvmap_ref->handle; + atomic_inc(&buf->refcount); return buf; diff --git a/drivers/video/tegra/nvmap/nvmap_dev.c b/drivers/video/tegra/nvmap/nvmap_dev.c index 0c12348db88e..3b0db14f16ca 100644 --- a/drivers/video/tegra/nvmap/nvmap_dev.c +++ b/drivers/video/tegra/nvmap/nvmap_dev.c @@ -1,10 +1,10 @@ /* + * Copyright (c) 2011-2013, NVIDIA CORPORATION. All rights reserved. + * * drivers/video/tegra/nvmap/nvmap_dev.c * * User-space interface to nvmap * - * Copyright (c) 2011-2012, NVIDIA Corporation. - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -231,6 +231,14 @@ struct nvmap_handle *nvmap_get_handle_id(struct nvmap_client *client, struct nvmap_handle_ref *ref; struct nvmap_handle *h = NULL; + /* Allow the handle to be accessed by other (non-owner) + clients only if the owner is "videobuf2-dma-nvmap", + which is a V4L2 capture kernel module. This handle can + be accessed by the "user" client for rendering */ + if (!strcmp(((struct nvmap_handle *)id)->owner->name, + "videobuf2-dma-nvmap")) + client = ((struct nvmap_handle *)id)->owner; + nvmap_ref_lock(client); ref = _nvmap_validate_id_locked(client, id); if (ref) -- cgit v1.2.3 From 3c3f3589ca261a1e8d5e9355d540585fe1a164dd Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Tue, 15 Oct 2013 18:25:30 -0700 Subject: media: tegra_v4l2: add CSI pad calibration Bug 1369083 Change-Id: I1a81bcb62e8f6bb654ffbebba09661187ab4b512 Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/309536 Tested-by: Vikram Fugro Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Kaustubh Purandare Reviewed-by: Winnie Hsu Reviewed-by: Matthew Pedro --- drivers/media/video/tegra_v4l2_camera.c | 89 ++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c index c96dae1389ff..8f71d1702537 100644 --- a/drivers/media/video/tegra_v4l2_camera.c +++ b/drivers/media/video/tegra_v4l2_camera.c @@ -235,6 +235,7 @@ #define TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME 0x08c8 #define TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME 0x08cc #define TEGRA_CSI_DSI_MIPI_CAL_CONFIG 0x08d0 +#define TEGRA_CSI_MIPIBIAS_PAD_CONFIG0 0x08d4 #define TC_VI_REG_RD(DEV, REG) readl(DEV->vi_base + REG) #define TC_VI_REG_WT(DEV, REG, VAL) writel(VAL, DEV->vi_base + REG) @@ -303,6 +304,9 @@ struct tegra_camera_dev { /* Debug */ int num_frames; int enable_refcnt; + + /* CSI pad calibration flag */ + int cal_done; }; static const struct soc_mbus_pixelfmt tegra_camera_formats[] = { @@ -974,7 +978,7 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev, int port) static void tegra_camera_activate(struct tegra_camera_dev *pcdev) { - nvhost_module_busy_ext(pcdev->ndev); + nvhost_module_busy_ext(pcdev->ndev); /* Enable external power */ regulator_enable(pcdev->reg); @@ -1017,6 +1021,8 @@ static void tegra_camera_deactivate(struct tegra_camera_dev *pcdev) regulator_disable(pcdev->reg); nvhost_module_idle_ext(pcdev->ndev); + + pcdev->cal_done = 0; } static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev) @@ -1104,6 +1110,83 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev) return err; } +static int tegra_camera_csi_pad_calibration(struct tegra_camera_dev *pcdev) +{ + struct vb2_buffer *vb = pcdev->active; + struct tegra_buffer *buf = to_tegra_vb(vb); + struct soc_camera_device *icd = buf->icd; + struct tegra_camera_platform_data *pdata = icd->link->priv; + int port = pdata->port; + int retry = 500; + u32 data; + int err = -EINVAL; + + TC_VI_REG_WT(pcdev, TEGRA_CSI_DSI_MIPI_CAL_CONFIG, 0x40300); + TC_VI_REG_WT(pcdev, TEGRA_CSI_MIPIBIAS_PAD_CONFIG0, 0x50700); + + if (port == TEGRA_CAMERA_PORT_CSI_B || pdata->lanes == 4) + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, 0x200004); + + data = 0x2a000004; + if (port == TEGRA_CAMERA_PORT_CSI_A) + data |= 0x200000; /* MIPI_CAL_SELA */ + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_MIPI_CAL_CONFIG, data); + + /* Start calibration */ + data |= 0x80000000; + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_MIPI_CAL_CONFIG, data); + + while (retry--) { + data = TC_VI_REG_RD(pcdev, TEGRA_CSI_CSI_CIL_STATUS); + if ((data & 0x8000) == 0x8000) + break; + udelay(20); + } + if (!retry) { + dev_warn(&pcdev->ndev->dev, "MIPI calibration timeout!\n"); + goto cal_out; + } + + /* Clear status */ + TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_CIL_STATUS, data); + retry = 500; + while (retry--) { + data = TC_VI_REG_RD(pcdev, TEGRA_CSI_CSI_CIL_STATUS); + if ((data & 0x8000) == 0x0) + break; + udelay(20); + } + + if (!retry) { + dev_warn(&pcdev->ndev->dev, + "Clear MIPI calibration status timeout!\n"); + goto cal_out; + } + + data = TC_VI_REG_RD(pcdev, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS); + err = TC_VI_REG_RD(pcdev, TEGRA_CSI_CSI_CIL_STATUS); + if (data | err) { + dev_warn(&pcdev->ndev->dev, + "Calibration status not be cleared!\n"); + err = -EINVAL; + goto cal_out; + } + + /* Calibration succeed */ + err = 0; + +cal_out: + TC_VI_REG_WT(pcdev, TEGRA_CSI_CSI_CIL_STATUS, data); + + /* un-select to avoid interference with DSI */ + if (port == TEGRA_CAMERA_PORT_CSI_B || pdata->lanes == 4) + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, 0x4); + + TC_VI_REG_WT(pcdev, TEGRA_CSI_CILA_MIPI_CAL_CONFIG, 0x2a000004); + + return err; +} + static void tegra_camera_work(struct work_struct *work) { struct tegra_camera_dev *pcdev = @@ -1127,6 +1210,10 @@ static void tegra_camera_work(struct work_struct *work) spin_unlock_irq(&pcdev->videobuf_queue_lock); tegra_camera_capture_setup(pcdev); + if (!pcdev->cal_done) { + tegra_camera_csi_pad_calibration(pcdev); + pcdev->cal_done = 1; + } tegra_camera_capture_frame(pcdev); mutex_unlock(&pcdev->work_mutex); -- cgit v1.2.3 From f6cd9007c40d2c9e8da0629b7afe8a77063e7aa9 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Wed, 16 Oct 2013 11:07:58 -0700 Subject: media: ov5640: change 1080p resolution to 1088p Setting the resolution to 1088p (as of now), since there are flickers observed for 1080p and also the encoder is not compatible with alignement of the RM surfaces of 1080p. 1088p is a stop-gap solution until the issues with 1080p are resolved. Bug 1369083 Change-Id: I3e73076451e7671d90603c6496ad14733591edeb Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/309543 Tested-by: Vikram Fugro Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Kaustubh Purandare Reviewed-by: Winnie Hsu Reviewed-by: Matthew Pedro --- drivers/media/video/ov5640.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/ov5640.c b/drivers/media/video/ov5640.c index 795d9bd541b3..04b0443a4d22 100644 --- a/drivers/media/video/ov5640.c +++ b/drivers/media/video/ov5640.c @@ -288,7 +288,7 @@ static struct ov5640_reg mode_2592x1944[] = { {OV5640_TABLE_END, 0x0000} }; -static struct ov5640_reg mode_1920x1080[] = { +static struct ov5640_reg mode_1920x1088[] = { /* PLL Control MIPI bit rate/lane = 672MHz, 16-bit mode. * Output size: 1936x1096 (336, 426) - (2287, 1529), * Line Length = 2500, Frame Length = 1120. @@ -1097,7 +1097,7 @@ static struct ov5640_reg mode_640x480[] = { enum { OV5640_MODE_640x480, OV5640_MODE_1296x972, - OV5640_MODE_1920x1080, + OV5640_MODE_1920x1088, OV5640_MODE_2592x1944, OV5640_SIZE_LAST, }; @@ -1105,7 +1105,7 @@ enum { static struct ov5640_reg *mode_table[] = { [OV5640_MODE_640x480] = mode_640x480, [OV5640_MODE_1296x972] = mode_1296x972, - [OV5640_MODE_1920x1080] = mode_1920x1080, + [OV5640_MODE_1920x1088] = mode_1920x1088, [OV5640_MODE_2592x1944] = mode_2592x1944, }; @@ -1144,7 +1144,7 @@ static enum v4l2_mbus_pixelcode ov5640_codes[] = { static const struct v4l2_frmsize_discrete ov5640_frmsizes[OV5640_SIZE_LAST] = { {640, 480}, {1296, 972}, - {1920, 1080}, + {1920, 1088}, {2592, 1944}, }; -- cgit v1.2.3 From 82685ba23c803d10f678f25e92ca62aa575d24d9 Mon Sep 17 00:00:00 2001 From: Shreshtha Sahu Date: Fri, 22 Nov 2013 12:11:10 +0530 Subject: ARM: tegra: make SKU 0x81 same as 0xB1 for tegra3 SKU 0x81 is identical to 0xB1 so same can be used for sku to speedo ID conversion. Bug 1313434 Change-Id: I63f08522878524a05c2a6fb0a82fee90a59a99bd Signed-off-by: Shreshtha Sahu Reviewed-on: http://git-master/r/334396 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Venkat Moganty Reviewed-by: Matthew Pedro --- arch/arm/mach-tegra/tegra3_speedo.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-tegra/tegra3_speedo.c b/arch/arm/mach-tegra/tegra3_speedo.c index 2889f656f47a..b91135c5634d 100644 --- a/arch/arm/mach-tegra/tegra3_speedo.c +++ b/arch/arm/mach-tegra/tegra3_speedo.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra3_speedo.c * - * Copyright (c) 2011-2012, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2011-2013, NVIDIA 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 as published by @@ -198,6 +198,7 @@ static void rev_sku_to_speedo_ids(int rev, int sku) break; case 0x81: /* T30 */ + case 0xb1: switch (package_id) { case 1: /* MID => T30 */ cpu_speedo_id = 2; @@ -303,7 +304,6 @@ static void rev_sku_to_speedo_ids(int rev, int sku) case 0x91: /* T30AGS-Ax */ case 0xb0: /* T30IQS-Ax */ - case 0xb1: /* T30MQS-Ax */ case 0x90: /* T30AQS-Ax */ soc_speedo_id = 3; threshold_index = 12; @@ -473,7 +473,6 @@ void tegra_init_speedo_data(void) if (cpu_process_id <= 2) { switch(fuse_sku) { case 0xb0: - case 0xb1: cpu_speedo_id = 9; break; case 0x90: @@ -485,7 +484,6 @@ void tegra_init_speedo_data(void) } else if (cpu_process_id >= 3 && cpu_process_id < 6) { switch(fuse_sku) { case 0xb0: - case 0xb1: cpu_speedo_id = 10; break; case 0x90: -- cgit v1.2.3