diff options
author | Wojciech Bieganski <wbieganski@antmicro.com> | 2015-08-26 15:26:19 +0200 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2016-11-21 15:05:08 +0100 |
commit | 017168237562b4d3af7d0aa5da9bca3a00b9a1d6 (patch) | |
tree | 868dbf9f15a118cc1fddc3cf085e9871b4414db9 | |
parent | d6ab5bcf5f16ba7dcecbd54de4304cc977cba456 (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.c | 44 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov5640.c | 29 |
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); |