summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojciech Bieganski <wbieganski@antmicro.com>2015-08-26 15:26:19 +0200
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2016-11-21 15:05:08 +0100
commit017168237562b4d3af7d0aa5da9bca3a00b9a1d6 (patch)
tree868dbf9f15a118cc1fddc3cf085e9871b4414db9
parentd6ab5bcf5f16ba7dcecbd54de4304cc977cba456 (diff)
OV5640 camera support
known issues: - works only in 1080p mode, - vertical synchronisation glitches, - setting queue-size in gstreamer greater than 1 results in blinking image - every start of streaming requires reloading of the modules Acked-by: Marcel Ziswiler <marcel.ziswiler@toradex.com> Acked-by: Dominik Sliwa <dominik.sliwa@toradex.com>
-rw-r--r--arch/arm/mach-tegra/board-ardbeg-sensors.c44
-rw-r--r--drivers/media/i2c/soc_camera/ov5640.c29
2 files changed, 62 insertions, 11 deletions
diff --git a/arch/arm/mach-tegra/board-ardbeg-sensors.c b/arch/arm/mach-tegra/board-ardbeg-sensors.c
index 37ba9ab3326c..c57d94f329cb 100644
--- a/arch/arm/mach-tegra/board-ardbeg-sensors.c
+++ b/arch/arm/mach-tegra/board-ardbeg-sensors.c
@@ -403,6 +403,47 @@ static struct platform_device ardbeg_ap1302_soc_camera_device = {
};
#endif
+#if IS_ENABLED(CONFIG_SOC_CAMERA_OV5640)
+static int ardbeg_ov5640_power(struct device *dev, int enable)
+ {
+ if(enable) {
+ tegra_io_dpd_disable(&csia_io);
+ } else {
+ tegra_io_dpd_enable(&csia_io);
+ }
+ return 0;
+ }
+
+static struct i2c_board_info ardbeg_ov5640_camera_i2c_device = {
+ I2C_BOARD_INFO("ov5640", 0x3c),
+};
+
+static struct tegra_camera_platform_data ardbeg_ov5640_camera_platform_data = {
+ .flip_v = 0,
+ .flip_h = 0,
+ .port = TEGRA_CAMERA_PORT_CSI_A,
+ .lanes = 2,
+ .continuous_clk = 0,
+};
+
+static struct soc_camera_link ov5640_iclink = {
+ .bus_id = 0, /* This must match the .id of tegra_vi01_device */
+ .board_info = &ardbeg_ov5640_camera_i2c_device,
+ .module_name = "ov5640",
+ .i2c_adapter_id = 2,
+ .power = ardbeg_ov5640_power,
+ .priv = &ardbeg_ov5640_camera_platform_data,
+};
+
+static struct platform_device ardbeg_ov5640_soc_camera_device = {
+ .name = "soc-camera-pdrv",
+ .id = 3,
+ .dev = {
+ .platform_data = &ov5640_iclink,
+ },
+};
+#endif
+
static struct regulator *ardbeg_vcmvdd;
static int ardbeg_get_extra_regulators(void)
@@ -1608,6 +1649,9 @@ static int ardbeg_camera_init(void)
#if IS_ENABLED(CONFIG_SOC_CAMERA_AP1302)
platform_device_register(&ardbeg_ap1302_soc_camera_device);
#endif
+#if IS_ENABLED(CONFIG_SOC_CAMERA_OV5640)
+ platform_device_register(&ardbeg_ov5640_soc_camera_device);
+#endif
return 0;
}
diff --git a/drivers/media/i2c/soc_camera/ov5640.c b/drivers/media/i2c/soc_camera/ov5640.c
index 38315b514407..917c55efb075 100644
--- a/drivers/media/i2c/soc_camera/ov5640.c
+++ b/drivers/media/i2c/soc_camera/ov5640.c
@@ -132,7 +132,7 @@ static struct ov5640_reg mode_2592x1944[] = {
{0x300e, 0x45},
{0x302e, 0x08},
{0x4300, 0x32},
- {0x4800, 0x24},
+ {0x4800, 0x4},
{0x4837, 0x0a},
{0x501f, 0x00},
{0x440e, 0x00},
@@ -396,7 +396,7 @@ static struct ov5640_reg mode_1920x1080[] = {
{0x440e, 0x00},
{0x460b, 0x37},
{0x460c, 0x20},
- {0x4800, 0x24},
+ {0x4800, 0x4},
{0x4837, 0x0a},
{0x3824, 0x04},
{0x5000, 0xa7},
@@ -660,7 +660,7 @@ static struct ov5640_reg mode_1296x972[] = {
{0x440e, 0x00},
{0x460b, 0x37},
{0x460c, 0x20},
- {0x4800, 0x24},
+ {0x4800, 0x4},
{0x4837, 0x10},
{0x3824, 0x04},
{0x5000, 0xa7},
@@ -1217,8 +1217,9 @@ static int ov5640_write_reg(struct i2c_client *client, u16 addr, u8 value)
msg[0].buf = data;
count = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
- if (count == 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);
@@ -1365,12 +1366,12 @@ static int ov5640_s_power(struct v4l2_subdev *sd, int on)
{
struct ov5640_priv *priv = to_ov5640(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+ struct soc_camera_subdev_desc *scsd = soc_camera_i2c_to_desc(client);
if (on)
ov5640_s_fmt(sd, &priv->mf);
- return soc_camera_set_power(&client->dev, icl, on);
+ return soc_camera_set_power(&client->dev, scsd, on);
}
static int ov5640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
@@ -1409,6 +1410,11 @@ static int ov5640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
return 0;
}
+static int ov5640_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+ return 0;
+}
+
/* Get chip identification */
static int ov5640_g_chip_ident(struct v4l2_subdev *sd,
struct v4l2_dbg_chip_ident *id)
@@ -1462,6 +1468,7 @@ static struct v4l2_subdev_video_ops ov5640_video_ops = {
.enum_mbus_fmt = ov5640_enum_fmt,
.cropcap = ov5640_cropcap,
.g_crop = ov5640_g_crop,
+ .querystd = ov5640_querystd,
};
@@ -1486,13 +1493,13 @@ static int ov5640_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct ov5640_priv *priv;
- struct soc_camera_link *icl;
+ struct soc_camera_subdev_desc *scsd;
u8 chip_id_hi, chip_id_lo;
int ret;
/* Checking soc-camera interface */
- icl = soc_camera_i2c_to_link(client);
- if (!icl) {
+ scsd = soc_camera_i2c_to_desc(client);
+ if (!scsd) {
dev_err(&client->dev, "Missing soc_camera_link for driver\n");
return -EINVAL;
}
@@ -1513,7 +1520,7 @@ static int ov5640_probe(struct i2c_client *client,
/*
* check and show product ID and manufacturer ID
*/
- soc_camera_power_on(&client->dev, icl);
+ soc_camera_power_on(&client->dev, scsd);
ret = ov5640_read_reg(client, 0x300A, &chip_id_hi);
if (ret < 0) {
dev_err(&client->dev, "Failure to read Chip ID (high byte)\n");
@@ -1534,7 +1541,7 @@ static int ov5640_probe(struct i2c_client *client,
ret = -ENODEV;
return ret;
}
- soc_camera_power_off(&client->dev, icl);
+ soc_camera_power_off(&client->dev, scsd);
ov5640_set_default_fmt(priv);