aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/usb/em28xx/em28xx-camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-camera.c')
-rw-r--r--drivers/media/usb/em28xx/em28xx-camera.c84
1 files changed, 54 insertions, 30 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c
index 73cc50afa5e..12d4c0326e3 100644
--- a/drivers/media/usb/em28xx/em28xx-camera.c
+++ b/drivers/media/usb/em28xx/em28xx-camera.c
@@ -22,6 +22,7 @@
#include <linux/i2c.h>
#include <media/soc_camera.h>
#include <media/mt9v011.h>
+#include <media/v4l2-clk.h>
#include <media/v4l2-common.h>
#include "em28xx.h"
@@ -47,6 +48,7 @@ static struct soc_camera_link camlink = {
.bus_id = 0,
.flags = 0,
.module_name = "em28xx",
+ .unbalanced_power = true,
};
@@ -118,7 +120,7 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev)
reg = 0x00;
ret = i2c_master_send(&client, &reg, 1);
if (ret < 0) {
- if (ret != -ENODEV)
+ if (ret != -ENXIO)
em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
client.addr << 1, ret);
continue;
@@ -216,7 +218,7 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev)
reg = 0x1c;
ret = i2c_smbus_read_byte_data(&client, reg);
if (ret < 0) {
- if (ret != -ENODEV)
+ if (ret != -ENXIO)
em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
client.addr << 1, ret);
continue;
@@ -325,18 +327,30 @@ int em28xx_detect_sensor(struct em28xx *dev)
int em28xx_init_camera(struct em28xx *dev)
{
+ char clk_name[V4L2_SUBDEV_NAME_SIZE];
+ struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
+ struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus];
+ struct em28xx_v4l2 *v4l2 = dev->v4l2;
+ int ret = 0;
+
+ v4l2_clk_name_i2c(clk_name, sizeof(clk_name),
+ i2c_adapter_id(adap), client->addr);
+ v4l2->clk = v4l2_clk_register_fixed(clk_name, "mclk", -EINVAL);
+ if (IS_ERR(v4l2->clk))
+ return PTR_ERR(v4l2->clk);
+
switch (dev->em28xx_sensor) {
case EM28XX_MT9V011:
{
struct mt9v011_platform_data pdata;
struct i2c_board_info mt9v011_info = {
.type = "mt9v011",
- .addr = dev->i2c_client[dev->def_i2c_bus].addr,
+ .addr = client->addr,
.platform_data = &pdata,
};
- dev->sensor_xres = 640;
- dev->sensor_yres = 480;
+ v4l2->sensor_xres = 640;
+ v4l2->sensor_yres = 480;
/*
* FIXME: mt9v011 uses I2S speed as xtal clk - at least with
@@ -349,40 +363,41 @@ int em28xx_init_camera(struct em28xx *dev)
*/
dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
- dev->sensor_xtal = 4300000;
- pdata.xtal = dev->sensor_xtal;
+ v4l2->sensor_xtal = 4300000;
+ pdata.xtal = v4l2->sensor_xtal;
if (NULL ==
- v4l2_i2c_new_subdev_board(&dev->v4l2_dev,
- &dev->i2c_adap[dev->def_i2c_bus],
- &mt9v011_info, NULL))
- return -ENODEV;
+ v4l2_i2c_new_subdev_board(&dev->v4l2->v4l2_dev, adap,
+ &mt9v011_info, NULL)) {
+ ret = -ENODEV;
+ break;
+ }
/* probably means GRGB 16 bit bayer */
- dev->vinmode = 0x0d;
- dev->vinctl = 0x00;
+ v4l2->vinmode = 0x0d;
+ v4l2->vinctl = 0x00;
break;
}
case EM28XX_MT9M001:
- dev->sensor_xres = 1280;
- dev->sensor_yres = 1024;
+ v4l2->sensor_xres = 1280;
+ v4l2->sensor_yres = 1024;
em28xx_initialize_mt9m001(dev);
/* probably means BGGR 16 bit bayer */
- dev->vinmode = 0x0c;
- dev->vinctl = 0x00;
+ v4l2->vinmode = 0x0c;
+ v4l2->vinctl = 0x00;
break;
case EM28XX_MT9M111:
- dev->sensor_xres = 640;
- dev->sensor_yres = 512;
+ v4l2->sensor_xres = 640;
+ v4l2->sensor_yres = 512;
dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
em28xx_initialize_mt9m111(dev);
- dev->vinmode = 0x0a;
- dev->vinctl = 0x00;
+ v4l2->vinmode = 0x0a;
+ v4l2->vinctl = 0x00;
break;
case EM28XX_OV2640:
@@ -391,7 +406,7 @@ int em28xx_init_camera(struct em28xx *dev)
struct i2c_board_info ov2640_info = {
.type = "ov2640",
.flags = I2C_CLIENT_SCCB,
- .addr = dev->i2c_client[dev->def_i2c_bus].addr,
+ .addr = client->addr,
.platform_data = &camlink,
};
struct v4l2_mbus_framefmt fmt;
@@ -404,13 +419,16 @@ int em28xx_init_camera(struct em28xx *dev)
* - adjust bridge xclk
* - disable 16 bit (12 bit) output formats on high resolutions
*/
- dev->sensor_xres = 640;
- dev->sensor_yres = 480;
+ v4l2->sensor_xres = 640;
+ v4l2->sensor_yres = 480;
subdev =
- v4l2_i2c_new_subdev_board(&dev->v4l2_dev,
- &dev->i2c_adap[dev->def_i2c_bus],
+ v4l2_i2c_new_subdev_board(&dev->v4l2->v4l2_dev, adap,
&ov2640_info, NULL);
+ if (NULL == subdev) {
+ ret = -ENODEV;
+ break;
+ }
fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
fmt.width = 640;
@@ -420,15 +438,21 @@ int em28xx_init_camera(struct em28xx *dev)
/* NOTE: for UXGA=1600x1200 switch to 12MHz */
dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ;
em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
- dev->vinmode = 0x08;
- dev->vinctl = 0x00;
+ v4l2->vinmode = 0x08;
+ v4l2->vinctl = 0x00;
break;
}
case EM28XX_NOSENSOR:
default:
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+ if (ret < 0) {
+ v4l2_clk_unregister_fixed(v4l2->clk);
+ v4l2->clk = NULL;
+ }
+
+ return ret;
}
+EXPORT_SYMBOL_GPL(em28xx_init_camera);