Commit 40e2e092 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Mauro Carvalho Chehab

V4L/DVB (12506): soc-camera: convert to platform device

Convert soc-camera core and all drivers to platform device API. We already
converted platforms to register a platform device for each soc-camera client,
now we remove the compatibility code and switch completely to the new scheme.
This is a preparatory step for the v4l2-subdev conversion.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent bc1937b4
...@@ -69,8 +69,6 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { ...@@ -69,8 +69,6 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
}; };
struct mt9m001 { struct mt9m001 {
struct i2c_client *client;
struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
unsigned char autoexposure; unsigned char autoexposure;
}; };
...@@ -111,11 +109,11 @@ static int reg_clear(struct i2c_client *client, const u8 reg, ...@@ -111,11 +109,11 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
static int mt9m001_init(struct soc_camera_device *icd) static int mt9m001_init(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = client->dev.platform_data; struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret; int ret;
dev_dbg(icd->vdev->parent, "%s\n", __func__); dev_dbg(&icd->dev, "%s\n", __func__);
if (icl->power) { if (icl->power) {
ret = icl->power(&client->dev, 1); ret = icl->power(&client->dev, 1);
...@@ -147,8 +145,8 @@ static int mt9m001_init(struct soc_camera_device *icd) ...@@ -147,8 +145,8 @@ static int mt9m001_init(struct soc_camera_device *icd)
static int mt9m001_release(struct soc_camera_device *icd) static int mt9m001_release(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = client->dev.platform_data; struct soc_camera_link *icl = to_soc_camera_link(icd);
/* Disable the chip */ /* Disable the chip */
reg_write(client, MT9M001_OUTPUT_CONTROL, 0); reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
...@@ -161,7 +159,7 @@ static int mt9m001_release(struct soc_camera_device *icd) ...@@ -161,7 +159,7 @@ static int mt9m001_release(struct soc_camera_device *icd)
static int mt9m001_start_capture(struct soc_camera_device *icd) static int mt9m001_start_capture(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Switch to master "normal" mode */ /* Switch to master "normal" mode */
if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0) if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0)
...@@ -171,7 +169,7 @@ static int mt9m001_start_capture(struct soc_camera_device *icd) ...@@ -171,7 +169,7 @@ static int mt9m001_start_capture(struct soc_camera_device *icd)
static int mt9m001_stop_capture(struct soc_camera_device *icd) static int mt9m001_stop_capture(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Stop sensor readout */ /* Stop sensor readout */
if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0) if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0)
...@@ -182,8 +180,7 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd) ...@@ -182,8 +180,7 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd)
static int mt9m001_set_bus_param(struct soc_camera_device *icd, static int mt9m001_set_bus_param(struct soc_camera_device *icd,
unsigned long flags) unsigned long flags)
{ {
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK; unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
/* Only one width bit may be set */ /* Only one width bit may be set */
...@@ -205,8 +202,7 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd, ...@@ -205,8 +202,7 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd,
static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
{ {
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
/* MT9M001 has all capture_format parameters fixed */ /* MT9M001 has all capture_format parameters fixed */
unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING | unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING |
SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
...@@ -223,8 +219,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) ...@@ -223,8 +219,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
static int mt9m001_set_crop(struct soc_camera_device *icd, static int mt9m001_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect) struct v4l2_rect *rect)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
int ret; int ret;
const u16 hblank = 9, vblank = 25; const u16 hblank = 9, vblank = 25;
...@@ -290,12 +286,13 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd, ...@@ -290,12 +286,13 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd,
static int mt9m001_get_chip_id(struct soc_camera_device *icd, static int mt9m001_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id) struct v4l2_dbg_chip_ident *id)
{ {
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL; return -EINVAL;
if (id->match.addr != mt9m001->client->addr) if (id->match.addr != client->addr)
return -ENODEV; return -ENODEV;
id->ident = mt9m001->model; id->ident = mt9m001->model;
...@@ -308,7 +305,7 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd, ...@@ -308,7 +305,7 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
static int mt9m001_get_register(struct soc_camera_device *icd, static int mt9m001_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL; return -EINVAL;
...@@ -328,7 +325,7 @@ static int mt9m001_get_register(struct soc_camera_device *icd, ...@@ -328,7 +325,7 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
static int mt9m001_set_register(struct soc_camera_device *icd, static int mt9m001_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL; return -EINVAL;
...@@ -381,15 +378,11 @@ static const struct v4l2_queryctrl mt9m001_controls[] = { ...@@ -381,15 +378,11 @@ static const struct v4l2_queryctrl mt9m001_controls[] = {
} }
}; };
static int mt9m001_video_probe(struct soc_camera_device *);
static void mt9m001_video_remove(struct soc_camera_device *);
static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *); static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
static struct soc_camera_ops mt9m001_ops = { static struct soc_camera_ops mt9m001_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.probe = mt9m001_video_probe,
.remove = mt9m001_video_remove,
.init = mt9m001_init, .init = mt9m001_init,
.release = mt9m001_release, .release = mt9m001_release,
.start_capture = mt9m001_start_capture, .start_capture = mt9m001_start_capture,
...@@ -412,8 +405,8 @@ static struct soc_camera_ops mt9m001_ops = { ...@@ -412,8 +405,8 @@ static struct soc_camera_ops mt9m001_ops = {
static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
int data; int data;
switch (ctrl->id) { switch (ctrl->id) {
...@@ -432,8 +425,8 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro ...@@ -432,8 +425,8 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro
static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
const struct v4l2_queryctrl *qctrl; const struct v4l2_queryctrl *qctrl;
int data; int data;
...@@ -525,11 +518,11 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro ...@@ -525,11 +518,11 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
/* Interface active, can use i2c. If it fails, it can indeed mean, that /* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one */ * this wasn't our capture interface, so, we wait for the right one */
static int mt9m001_video_probe(struct soc_camera_device *icd) static int mt9m001_video_probe(struct soc_camera_device *icd,
struct i2c_client *client)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_link *icl = client->dev.platform_data;
s32 data; s32 data;
int ret; int ret;
unsigned long flags; unsigned long flags;
...@@ -540,6 +533,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) ...@@ -540,6 +533,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface) to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV; return -ENODEV;
/* Switch master clock on */
ret = soc_camera_video_start(icd, &client->dev);
if (ret)
return ret;
/* Enable the chip */ /* Enable the chip */
data = reg_write(client, MT9M001_CHIP_ENABLE, 1); data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
dev_dbg(&icd->dev, "write: %d\n", data); dev_dbg(&icd->dev, "write: %d\n", data);
...@@ -547,6 +545,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) ...@@ -547,6 +545,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
/* Read out the chip version register */ /* Read out the chip version register */
data = reg_read(client, MT9M001_CHIP_VERSION); data = reg_read(client, MT9M001_CHIP_VERSION);
soc_camera_video_stop(icd);
/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
switch (data) { switch (data) {
case 0x8411: case 0x8411:
...@@ -559,10 +559,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) ...@@ -559,10 +559,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
icd->formats = mt9m001_monochrome_formats; icd->formats = mt9m001_monochrome_formats;
break; break;
default: default:
ret = -ENODEV;
dev_err(&icd->dev, dev_err(&icd->dev,
"No MT9M001 chip detected, register read %x\n", data); "No MT9M001 chip detected, register read %x\n", data);
goto ei2c; return -ENODEV;
} }
icd->num_formats = 0; icd->num_formats = 0;
...@@ -588,26 +587,16 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) ...@@ -588,26 +587,16 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
data == 0x8431 ? "C12STM" : "C12ST"); data == 0x8431 ? "C12STM" : "C12ST");
/* Now that we know the model, we can start video */
ret = soc_camera_video_start(icd);
if (ret)
goto eisis;
return 0; return 0;
eisis:
ei2c:
return ret;
} }
static void mt9m001_video_remove(struct soc_camera_device *icd) static void mt9m001_video_remove(struct soc_camera_device *icd)
{ {
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = mt9m001->client->dev.platform_data; struct soc_camera_link *icl = to_soc_camera_link(icd);
dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
icd->dev.parent, icd->vdev); icd->dev.parent, icd->vdev);
soc_camera_video_stop(icd);
if (icl->free_bus) if (icl->free_bus)
icl->free_bus(icl); icl->free_bus(icl);
} }
...@@ -616,11 +605,17 @@ static int mt9m001_probe(struct i2c_client *client, ...@@ -616,11 +605,17 @@ static int mt9m001_probe(struct i2c_client *client,
const struct i2c_device_id *did) const struct i2c_device_id *did)
{ {
struct mt9m001 *mt9m001; struct mt9m001 *mt9m001;
struct soc_camera_device *icd; struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct soc_camera_link *icl = client->dev.platform_data; struct soc_camera_link *icl;
int ret; int ret;
if (!icd) {
dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
return -EINVAL;
}
icl = to_soc_camera_link(icd);
if (!icl) { if (!icl) {
dev_err(&client->dev, "MT9M001 driver needs platform data\n"); dev_err(&client->dev, "MT9M001 driver needs platform data\n");
return -EINVAL; return -EINVAL;
...@@ -636,13 +631,10 @@ static int mt9m001_probe(struct i2c_client *client, ...@@ -636,13 +631,10 @@ static int mt9m001_probe(struct i2c_client *client,
if (!mt9m001) if (!mt9m001)
return -ENOMEM; return -ENOMEM;
mt9m001->client = client;
i2c_set_clientdata(client, mt9m001); i2c_set_clientdata(client, mt9m001);
/* Second stage probe - when a capture adapter is there */ /* Second stage probe - when a capture adapter is there */
icd = &mt9m001->icd;
icd->ops = &mt9m001_ops; icd->ops = &mt9m001_ops;
icd->control = &client->dev;
icd->x_min = 20; icd->x_min = 20;
icd->y_min = 12; icd->y_min = 12;
icd->x_current = 20; icd->x_current = 20;
...@@ -652,27 +644,29 @@ static int mt9m001_probe(struct i2c_client *client, ...@@ -652,27 +644,29 @@ static int mt9m001_probe(struct i2c_client *client,
icd->height_min = 32; icd->height_min = 32;
icd->height_max = 1024; icd->height_max = 1024;
icd->y_skip_top = 1; icd->y_skip_top = 1;
icd->iface = icl->bus_id;
/* Simulated autoexposure. If enabled, we calculate shutter width /* Simulated autoexposure. If enabled, we calculate shutter width
* ourselves in the driver based on vertical blanking and frame width */ * ourselves in the driver based on vertical blanking and frame width */
mt9m001->autoexposure = 1; mt9m001->autoexposure = 1;
ret = soc_camera_device_register(icd); ret = mt9m001_video_probe(icd, client);
if (ret) if (ret) {
goto eisdr; icd->ops = NULL;
i2c_set_clientdata(client, NULL);
return 0;
eisdr:
kfree(mt9m001); kfree(mt9m001);
}
return ret; return ret;
} }
static int mt9m001_remove(struct i2c_client *client) static int mt9m001_remove(struct i2c_client *client)
{ {
struct mt9m001 *mt9m001 = i2c_get_clientdata(client); struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
struct soc_camera_device *icd = client->dev.platform_data;
soc_camera_device_unregister(&mt9m001->icd); icd->ops = NULL;
mt9m001_video_remove(icd);
i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(mt9m001); kfree(mt9m001);
return 0; return 0;
......
...@@ -148,8 +148,6 @@ enum mt9m111_context { ...@@ -148,8 +148,6 @@ enum mt9m111_context {
}; };
struct mt9m111 { struct mt9m111 {
struct i2c_client *client;
struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */
enum mt9m111_context context; enum mt9m111_context context;
struct v4l2_rect rect; struct v4l2_rect rect;
...@@ -203,7 +201,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg, ...@@ -203,7 +201,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
ret = reg_page_map_set(client, reg); ret = reg_page_map_set(client, reg);
if (!ret) if (!ret)
ret = i2c_smbus_write_word_data(client, (reg & 0xff), ret = i2c_smbus_write_word_data(client, reg & 0xff,
swab16(data)); swab16(data));
dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
return ret; return ret;
...@@ -232,7 +230,7 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg, ...@@ -232,7 +230,7 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
static int mt9m111_set_context(struct soc_camera_device *icd, static int mt9m111_set_context(struct soc_camera_device *icd,
enum mt9m111_context ctxt) enum mt9m111_context ctxt)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
| MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
| MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
...@@ -249,8 +247,8 @@ static int mt9m111_set_context(struct soc_camera_device *icd, ...@@ -249,8 +247,8 @@ static int mt9m111_set_context(struct soc_camera_device *icd,
static int mt9m111_setup_rect(struct soc_camera_device *icd, static int mt9m111_setup_rect(struct soc_camera_device *icd,
struct v4l2_rect *rect) struct v4l2_rect *rect)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret, is_raw_format; int ret, is_raw_format;
int width = rect->width; int width = rect->width;
int height = rect->height; int height = rect->height;
...@@ -294,7 +292,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd, ...@@ -294,7 +292,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd,
static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int ret; int ret;
ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
...@@ -315,7 +313,8 @@ static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) ...@@ -315,7 +313,8 @@ static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd)
static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int val = 0; int val = 0;
if (mt9m111->swap_rgb_red_blue) if (mt9m111->swap_rgb_red_blue)
...@@ -329,7 +328,8 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) ...@@ -329,7 +328,8 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int val = 0; int val = 0;
if (mt9m111->swap_rgb_red_blue) if (mt9m111->swap_rgb_red_blue)
...@@ -343,7 +343,8 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) ...@@ -343,7 +343,8 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int val = 0; int val = 0;
if (mt9m111->swap_yuv_cb_cr) if (mt9m111->swap_yuv_cb_cr)
...@@ -356,9 +357,9 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) ...@@ -356,9 +357,9 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
static int mt9m111_enable(struct soc_camera_device *icd) static int mt9m111_enable(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_link *icl = client->dev.platform_data; struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret; int ret;
if (icl->power) { if (icl->power) {
...@@ -378,9 +379,9 @@ static int mt9m111_enable(struct soc_camera_device *icd) ...@@ -378,9 +379,9 @@ static int mt9m111_enable(struct soc_camera_device *icd)
static int mt9m111_disable(struct soc_camera_device *icd) static int mt9m111_disable(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_link *icl = client->dev.platform_data; struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret; int ret;
ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
...@@ -395,8 +396,8 @@ static int mt9m111_disable(struct soc_camera_device *icd) ...@@ -395,8 +396,8 @@ static int mt9m111_disable(struct soc_camera_device *icd)
static int mt9m111_reset(struct soc_camera_device *icd) static int mt9m111_reset(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = client->dev.platform_data; struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret; int ret;
ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
...@@ -424,8 +425,7 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd) ...@@ -424,8 +425,7 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd)
static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
...@@ -441,7 +441,8 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) ...@@ -441,7 +441,8 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
static int mt9m111_set_crop(struct soc_camera_device *icd, static int mt9m111_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect) struct v4l2_rect *rect)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret; int ret;
dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
...@@ -456,7 +457,8 @@ static int mt9m111_set_crop(struct soc_camera_device *icd, ...@@ -456,7 +457,8 @@ static int mt9m111_set_crop(struct soc_camera_device *icd,
static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret; int ret;
switch (pixfmt) { switch (pixfmt) {
...@@ -506,7 +508,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) ...@@ -506,7 +508,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
static int mt9m111_set_fmt(struct soc_camera_device *icd, static int mt9m111_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_rect rect = { struct v4l2_rect rect = {
.left = mt9m111->rect.left, .left = mt9m111->rect.left,
...@@ -544,12 +547,13 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd, ...@@ -544,12 +547,13 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd,
static int mt9m111_get_chip_id(struct soc_camera_device *icd, static int mt9m111_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id) struct v4l2_dbg_chip_ident *id)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL; return -EINVAL;
if (id->match.addr != mt9m111->client->addr) if (id->match.addr != client->addr)
return -ENODEV; return -ENODEV;
id->ident = mt9m111->model; id->ident = mt9m111->model;
...@@ -562,8 +566,8 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd, ...@@ -562,8 +566,8 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd,
static int mt9m111_get_register(struct soc_camera_device *icd, static int mt9m111_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int val; int val;
struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL; return -EINVAL;
...@@ -583,7 +587,7 @@ static int mt9m111_get_register(struct soc_camera_device *icd, ...@@ -583,7 +587,7 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
static int mt9m111_set_register(struct soc_camera_device *icd, static int mt9m111_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL; return -EINVAL;
...@@ -635,8 +639,6 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { ...@@ -635,8 +639,6 @@ static const struct v4l2_queryctrl mt9m111_controls[] = {
} }
}; };
static int mt9m111_video_probe(struct soc_camera_device *);
static void mt9m111_video_remove(struct soc_camera_device *);
static int mt9m111_get_control(struct soc_camera_device *, static int mt9m111_get_control(struct soc_camera_device *,
struct v4l2_control *); struct v4l2_control *);
static int mt9m111_set_control(struct soc_camera_device *, static int mt9m111_set_control(struct soc_camera_device *,
...@@ -647,8 +649,6 @@ static int mt9m111_release(struct soc_camera_device *icd); ...@@ -647,8 +649,6 @@ static int mt9m111_release(struct soc_camera_device *icd);
static struct soc_camera_ops mt9m111_ops = { static struct soc_camera_ops mt9m111_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.probe = mt9m111_video_probe,
.remove = mt9m111_video_remove,
.init = mt9m111_init, .init = mt9m111_init,
.resume = mt9m111_resume, .resume = mt9m111_resume,
.release = mt9m111_release, .release = mt9m111_release,
...@@ -672,8 +672,8 @@ static struct soc_camera_ops mt9m111_ops = { ...@@ -672,8 +672,8 @@ static struct soc_camera_ops mt9m111_ops = {
static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret; int ret;
if (mt9m111->context == HIGHPOWER) { if (mt9m111->context == HIGHPOWER) {
...@@ -693,7 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) ...@@ -693,7 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
static int mt9m111_get_global_gain(struct soc_camera_device *icd) static int mt9m111_get_global_gain(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int data; int data;
data = reg_read(GLOBAL_GAIN); data = reg_read(GLOBAL_GAIN);
...@@ -705,7 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd) ...@@ -705,7 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd)
static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
u16 val; u16 val;
if (gain > 63 * 2 * 2) if (gain > 63 * 2 * 2)
...@@ -724,8 +724,8 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) ...@@ -724,8 +724,8 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret; int ret;
if (on) if (on)
...@@ -741,8 +741,8 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) ...@@ -741,8 +741,8 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret; int ret;
if (on) if (on)
...@@ -759,8 +759,8 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) ...@@ -759,8 +759,8 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
static int mt9m111_get_control(struct soc_camera_device *icd, static int mt9m111_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl) struct v4l2_control *ctrl)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int data; int data;
switch (ctrl->id) { switch (ctrl->id) {
...@@ -803,7 +803,8 @@ static int mt9m111_get_control(struct soc_camera_device *icd, ...@@ -803,7 +803,8 @@ static int mt9m111_get_control(struct soc_camera_device *icd,
static int mt9m111_set_control(struct soc_camera_device *icd, static int mt9m111_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl) struct v4l2_control *ctrl)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
const struct v4l2_queryctrl *qctrl; const struct v4l2_queryctrl *qctrl;
int ret; int ret;
...@@ -841,7 +842,8 @@ static int mt9m111_set_control(struct soc_camera_device *icd, ...@@ -841,7 +842,8 @@ static int mt9m111_set_control(struct soc_camera_device *icd,
static int mt9m111_restore_state(struct soc_camera_device *icd) static int mt9m111_restore_state(struct soc_camera_device *icd)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
mt9m111_set_context(icd, mt9m111->context); mt9m111_set_context(icd, mt9m111->context);
mt9m111_set_pixfmt(icd, mt9m111->pixfmt); mt9m111_set_pixfmt(icd, mt9m111->pixfmt);
...@@ -856,7 +858,8 @@ static int mt9m111_restore_state(struct soc_camera_device *icd) ...@@ -856,7 +858,8 @@ static int mt9m111_restore_state(struct soc_camera_device *icd)
static int mt9m111_resume(struct soc_camera_device *icd) static int mt9m111_resume(struct soc_camera_device *icd)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret = 0; int ret = 0;
if (mt9m111->powered) { if (mt9m111->powered) {
...@@ -871,7 +874,8 @@ static int mt9m111_resume(struct soc_camera_device *icd) ...@@ -871,7 +874,8 @@ static int mt9m111_resume(struct soc_camera_device *icd)
static int mt9m111_init(struct soc_camera_device *icd) static int mt9m111_init(struct soc_camera_device *icd)
{ {
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret; int ret;
mt9m111->context = HIGHPOWER; mt9m111->context = HIGHPOWER;
...@@ -902,10 +906,10 @@ static int mt9m111_release(struct soc_camera_device *icd) ...@@ -902,10 +906,10 @@ static int mt9m111_release(struct soc_camera_device *icd)
* Interface active, can use i2c. If it fails, it can indeed mean, that * Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one * this wasn't our capture interface, so, we wait for the right one
*/ */
static int mt9m111_video_probe(struct soc_camera_device *icd) static int mt9m111_video_probe(struct soc_camera_device *icd,
struct i2c_client *client)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
s32 data; s32 data;
int ret; int ret;
...@@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd) ...@@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface) to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV; return -ENODEV;
/* Switch master clock on */
ret = soc_camera_video_start(icd, &client->dev);
if (ret)
goto evstart;
ret = mt9m111_enable(icd); ret = mt9m111_enable(icd);
if (ret) if (ret)
goto ei2c; goto ei2c;
...@@ -945,40 +954,33 @@ static int mt9m111_video_probe(struct soc_camera_device *icd) ...@@ -945,40 +954,33 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data); dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data);
ret = soc_camera_video_start(icd);
if (ret)
goto eisis;
mt9m111->autoexposure = 1; mt9m111->autoexposure = 1;
mt9m111->autowhitebalance = 1; mt9m111->autowhitebalance = 1;
mt9m111->swap_rgb_even_odd = 1; mt9m111->swap_rgb_even_odd = 1;
mt9m111->swap_rgb_red_blue = 1; mt9m111->swap_rgb_red_blue = 1;
return 0;
eisis:
ei2c: ei2c:
soc_camera_video_stop(icd);
evstart:
return ret; return ret;
} }
static void mt9m111_video_remove(struct soc_camera_device *icd)
{
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr,
mt9m111->icd.dev.parent, mt9m111->icd.vdev);
soc_camera_video_stop(&mt9m111->icd);
}
static int mt9m111_probe(struct i2c_client *client, static int mt9m111_probe(struct i2c_client *client,
const struct i2c_device_id *did) const struct i2c_device_id *did)
{ {
struct mt9m111 *mt9m111; struct mt9m111 *mt9m111;
struct soc_camera_device *icd; struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct soc_camera_link *icl = client->dev.platform_data; struct soc_camera_link *icl;
int ret; int ret;
if (!icd) {
dev_err(&client->dev, "MT9M11x: missing soc-camera data!\n");
return -EINVAL;
}
icl = to_soc_camera_link(icd);
if (!icl) { if (!icl) {
dev_err(&client->dev, "MT9M11x driver needs platform data\n"); dev_err(&client->dev, "MT9M11x driver needs platform data\n");
return -EINVAL; return -EINVAL;
...@@ -994,13 +996,10 @@ static int mt9m111_probe(struct i2c_client *client, ...@@ -994,13 +996,10 @@ static int mt9m111_probe(struct i2c_client *client,
if (!mt9m111) if (!mt9m111)
return -ENOMEM; return -ENOMEM;
mt9m111->client = client;
i2c_set_clientdata(client, mt9m111); i2c_set_clientdata(client, mt9m111);
/* Second stage probe - when a capture adapter is there */ /* Second stage probe - when a capture adapter is there */
icd = &mt9m111->icd;
icd->ops = &mt9m111_ops; icd->ops = &mt9m111_ops;
icd->control = &client->dev;
icd->x_min = MT9M111_MIN_DARK_COLS; icd->x_min = MT9M111_MIN_DARK_COLS;
icd->y_min = MT9M111_MIN_DARK_ROWS; icd->y_min = MT9M111_MIN_DARK_ROWS;
icd->x_current = icd->x_min; icd->x_current = icd->x_min;
...@@ -1010,22 +1009,25 @@ static int mt9m111_probe(struct i2c_client *client, ...@@ -1010,22 +1009,25 @@ static int mt9m111_probe(struct i2c_client *client,
icd->height_min = MT9M111_MIN_DARK_COLS; icd->height_min = MT9M111_MIN_DARK_COLS;
icd->height_max = MT9M111_MAX_HEIGHT; icd->height_max = MT9M111_MAX_HEIGHT;
icd->y_skip_top = 0; icd->y_skip_top = 0;
icd->iface = icl->bus_id;
ret = soc_camera_device_register(icd); ret = mt9m111_video_probe(icd, client);
if (ret) if (ret) {
goto eisdr; icd->ops = NULL;
return 0; i2c_set_clientdata(client, NULL);
eisdr:
kfree(mt9m111); kfree(mt9m111);
}
return ret; return ret;
} }
static int mt9m111_remove(struct i2c_client *client) static int mt9m111_remove(struct i2c_client *client)
{ {
struct mt9m111 *mt9m111 = i2c_get_clientdata(client); struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
soc_camera_device_unregister(&mt9m111->icd); struct soc_camera_device *icd = client->dev.platform_data;
icd->ops = NULL;
i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(mt9m111); kfree(mt9m111);
return 0; return 0;
......
...@@ -68,8 +68,6 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = { ...@@ -68,8 +68,6 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = {
}; };
struct mt9t031 { struct mt9t031 {
struct i2c_client *client;
struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
unsigned char autoexposure; unsigned char autoexposure;
u16 xskip; u16 xskip;
...@@ -138,8 +136,8 @@ static int get_shutter(struct i2c_client *client, u32 *data) ...@@ -138,8 +136,8 @@ static int get_shutter(struct i2c_client *client, u32 *data)
static int mt9t031_init(struct soc_camera_device *icd) static int mt9t031_init(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = client->dev.platform_data; struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret; int ret;
if (icl->power) { if (icl->power) {
...@@ -166,8 +164,8 @@ static int mt9t031_init(struct soc_camera_device *icd) ...@@ -166,8 +164,8 @@ static int mt9t031_init(struct soc_camera_device *icd)
static int mt9t031_release(struct soc_camera_device *icd) static int mt9t031_release(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = client->dev.platform_data; struct soc_camera_link *icl = to_soc_camera_link(icd);
/* Disable the chip */ /* Disable the chip */
reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
...@@ -180,7 +178,7 @@ static int mt9t031_release(struct soc_camera_device *icd) ...@@ -180,7 +178,7 @@ static int mt9t031_release(struct soc_camera_device *icd)
static int mt9t031_start_capture(struct soc_camera_device *icd) static int mt9t031_start_capture(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Switch to master "normal" mode */ /* Switch to master "normal" mode */
if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0) if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
...@@ -190,7 +188,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd) ...@@ -190,7 +188,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd)
static int mt9t031_stop_capture(struct soc_camera_device *icd) static int mt9t031_stop_capture(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Stop sensor readout */ /* Stop sensor readout */
if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0) if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
...@@ -201,7 +199,7 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd) ...@@ -201,7 +199,7 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd)
static int mt9t031_set_bus_param(struct soc_camera_device *icd, static int mt9t031_set_bus_param(struct soc_camera_device *icd,
unsigned long flags) unsigned long flags)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* The caller should have queried our parameters, check anyway */ /* The caller should have queried our parameters, check anyway */
if (flags & ~MT9T031_BUS_PARAM) if (flags & ~MT9T031_BUS_PARAM)
...@@ -217,8 +215,7 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd, ...@@ -217,8 +215,7 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd,
static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd)
{ {
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
} }
...@@ -238,8 +235,8 @@ static void recalculate_limits(struct soc_camera_device *icd, ...@@ -238,8 +235,8 @@ static void recalculate_limits(struct soc_camera_device *icd,
static int mt9t031_set_params(struct soc_camera_device *icd, static int mt9t031_set_params(struct soc_camera_device *icd,
struct v4l2_rect *rect, u16 xskip, u16 yskip) struct v4l2_rect *rect, u16 xskip, u16 yskip)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
int ret; int ret;
u16 xbin, ybin, width, height, left, top; u16 xbin, ybin, width, height, left, top;
const u16 hblank = MT9T031_HORIZONTAL_BLANK, const u16 hblank = MT9T031_HORIZONTAL_BLANK,
...@@ -336,7 +333,8 @@ static int mt9t031_set_params(struct soc_camera_device *icd, ...@@ -336,7 +333,8 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
static int mt9t031_set_crop(struct soc_camera_device *icd, static int mt9t031_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect) struct v4l2_rect *rect)
{ {
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
/* CROP - no change in scaling, or in limits */ /* CROP - no change in scaling, or in limits */
return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip);
...@@ -345,7 +343,8 @@ static int mt9t031_set_crop(struct soc_camera_device *icd, ...@@ -345,7 +343,8 @@ static int mt9t031_set_crop(struct soc_camera_device *icd,
static int mt9t031_set_fmt(struct soc_camera_device *icd, static int mt9t031_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
int ret; int ret;
u16 xskip, yskip; u16 xskip, yskip;
struct v4l2_rect rect = { struct v4l2_rect rect = {
...@@ -395,12 +394,13 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, ...@@ -395,12 +394,13 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd,
static int mt9t031_get_chip_id(struct soc_camera_device *icd, static int mt9t031_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id) struct v4l2_dbg_chip_ident *id)
{ {
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL; return -EINVAL;
if (id->match.addr != mt9t031->client->addr) if (id->match.addr != client->addr)
return -ENODEV; return -ENODEV;
id->ident = mt9t031->model; id->ident = mt9t031->model;
...@@ -413,7 +413,7 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd, ...@@ -413,7 +413,7 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd,
static int mt9t031_get_register(struct soc_camera_device *icd, static int mt9t031_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL; return -EINVAL;
...@@ -432,7 +432,7 @@ static int mt9t031_get_register(struct soc_camera_device *icd, ...@@ -432,7 +432,7 @@ static int mt9t031_get_register(struct soc_camera_device *icd,
static int mt9t031_set_register(struct soc_camera_device *icd, static int mt9t031_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL; return -EINVAL;
...@@ -493,15 +493,11 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { ...@@ -493,15 +493,11 @@ static const struct v4l2_queryctrl mt9t031_controls[] = {
} }
}; };
static int mt9t031_video_probe(struct soc_camera_device *);
static void mt9t031_video_remove(struct soc_camera_device *);
static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *);
static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *); static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *);
static struct soc_camera_ops mt9t031_ops = { static struct soc_camera_ops mt9t031_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.probe = mt9t031_video_probe,
.remove = mt9t031_video_remove,
.init = mt9t031_init, .init = mt9t031_init,
.release = mt9t031_release, .release = mt9t031_release,
.start_capture = mt9t031_start_capture, .start_capture = mt9t031_start_capture,
...@@ -524,8 +520,8 @@ static struct soc_camera_ops mt9t031_ops = { ...@@ -524,8 +520,8 @@ static struct soc_camera_ops mt9t031_ops = {
static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
int data; int data;
switch (ctrl->id) { switch (ctrl->id) {
...@@ -550,8 +546,8 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro ...@@ -550,8 +546,8 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro
static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
const struct v4l2_queryctrl *qctrl; const struct v4l2_queryctrl *qctrl;
int data; int data;
...@@ -657,10 +653,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro ...@@ -657,10 +653,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
/* Interface active, can use i2c. If it fails, it can indeed mean, that /* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one */ * this wasn't our capture interface, so, we wait for the right one */
static int mt9t031_video_probe(struct soc_camera_device *icd) static int mt9t031_video_probe(struct soc_camera_device *icd,
struct i2c_client *client)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
s32 data; s32 data;
int ret; int ret;
...@@ -670,6 +666,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) ...@@ -670,6 +666,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface) to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV; return -ENODEV;
/* Switch master clock on */
ret = soc_camera_video_start(icd, &client->dev);
if (ret)
return ret;
/* Enable the chip */ /* Enable the chip */
data = reg_write(client, MT9T031_CHIP_ENABLE, 1); data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
dev_dbg(&icd->dev, "write: %d\n", data); dev_dbg(&icd->dev, "write: %d\n", data);
...@@ -677,6 +678,8 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) ...@@ -677,6 +678,8 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
/* Read out the chip version register */ /* Read out the chip version register */
data = reg_read(client, MT9T031_CHIP_VERSION); data = reg_read(client, MT9T031_CHIP_VERSION);
soc_camera_video_stop(icd);
switch (data) { switch (data) {
case 0x1621: case 0x1621:
mt9t031->model = V4L2_IDENT_MT9T031; mt9t031->model = V4L2_IDENT_MT9T031;
...@@ -684,44 +687,31 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) ...@@ -684,44 +687,31 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats); icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats);
break; break;
default: default:
ret = -ENODEV;
dev_err(&icd->dev, dev_err(&icd->dev,
"No MT9T031 chip detected, register read %x\n", data); "No MT9T031 chip detected, register read %x\n", data);
goto ei2c; return -ENODEV;
} }
dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data); dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data);
/* Now that we know the model, we can start video */
ret = soc_camera_video_start(icd);
if (ret)
goto evstart;
return 0; return 0;
evstart:
ei2c:
return ret;
}
static void mt9t031_video_remove(struct soc_camera_device *icd)
{
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr,
icd->dev.parent, icd->vdev);
soc_camera_video_stop(icd);
} }
static int mt9t031_probe(struct i2c_client *client, static int mt9t031_probe(struct i2c_client *client,
const struct i2c_device_id *did) const struct i2c_device_id *did)
{ {
struct mt9t031 *mt9t031; struct mt9t031 *mt9t031;
struct soc_camera_device *icd; struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct soc_camera_link *icl = client->dev.platform_data; struct soc_camera_link *icl;
int ret; int ret;
if (!icd) {
dev_err(&client->dev, "MT9T031: missing soc-camera data!\n");
return -EINVAL;
}
icl = to_soc_camera_link(icd);
if (!icl) { if (!icl) {
dev_err(&client->dev, "MT9T031 driver needs platform data\n"); dev_err(&client->dev, "MT9T031 driver needs platform data\n");
return -EINVAL; return -EINVAL;
...@@ -737,13 +727,10 @@ static int mt9t031_probe(struct i2c_client *client, ...@@ -737,13 +727,10 @@ static int mt9t031_probe(struct i2c_client *client,
if (!mt9t031) if (!mt9t031)
return -ENOMEM; return -ENOMEM;
mt9t031->client = client;
i2c_set_clientdata(client, mt9t031); i2c_set_clientdata(client, mt9t031);
/* Second stage probe - when a capture adapter is there */ /* Second stage probe - when a capture adapter is there */
icd = &mt9t031->icd;
icd->ops = &mt9t031_ops; icd->ops = &mt9t031_ops;
icd->control = &client->dev;
icd->x_min = MT9T031_COLUMN_SKIP; icd->x_min = MT9T031_COLUMN_SKIP;
icd->y_min = MT9T031_ROW_SKIP; icd->y_min = MT9T031_ROW_SKIP;
icd->x_current = icd->x_min; icd->x_current = icd->x_min;
...@@ -753,7 +740,6 @@ static int mt9t031_probe(struct i2c_client *client, ...@@ -753,7 +740,6 @@ static int mt9t031_probe(struct i2c_client *client,
icd->height_min = MT9T031_MIN_HEIGHT; icd->height_min = MT9T031_MIN_HEIGHT;
icd->height_max = MT9T031_MAX_HEIGHT; icd->height_max = MT9T031_MAX_HEIGHT;
icd->y_skip_top = 0; icd->y_skip_top = 0;
icd->iface = icl->bus_id;
/* Simulated autoexposure. If enabled, we calculate shutter width /* Simulated autoexposure. If enabled, we calculate shutter width
* ourselves in the driver based on vertical blanking and frame width */ * ourselves in the driver based on vertical blanking and frame width */
mt9t031->autoexposure = 1; mt9t031->autoexposure = 1;
...@@ -761,24 +747,24 @@ static int mt9t031_probe(struct i2c_client *client, ...@@ -761,24 +747,24 @@ static int mt9t031_probe(struct i2c_client *client,
mt9t031->xskip = 1; mt9t031->xskip = 1;
mt9t031->yskip = 1; mt9t031->yskip = 1;
ret = soc_camera_device_register(icd); ret = mt9t031_video_probe(icd, client);
if (ret) if (ret) {
goto eisdr; icd->ops = NULL;
return 0;
eisdr:
i2c_set_clientdata(client, NULL); i2c_set_clientdata(client, NULL);
kfree(mt9t031); kfree(mt9t031);
}
return ret; return ret;
} }
static int mt9t031_remove(struct i2c_client *client) static int mt9t031_remove(struct i2c_client *client)
{ {
struct mt9t031 *mt9t031 = i2c_get_clientdata(client); struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
struct soc_camera_device *icd = client->dev.platform_data;
soc_camera_device_unregister(&mt9t031->icd); icd->ops = NULL;
i2c_set_clientdata(client, NULL); i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(mt9t031); kfree(mt9t031);
return 0; return 0;
......
...@@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { ...@@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
}; };
struct mt9v022 { struct mt9v022 {
struct i2c_client *client;
struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
u16 chip_control; u16 chip_control;
}; };
...@@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg, ...@@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
static int mt9v022_init(struct soc_camera_device *icd) static int mt9v022_init(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_link *icl = client->dev.platform_data; struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
int ret; int ret;
if (icl->power) { if (icl->power) {
...@@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd) ...@@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd)
static int mt9v022_release(struct soc_camera_device *icd) static int mt9v022_release(struct soc_camera_device *icd)
{ {
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = mt9v022->client->dev.platform_data; struct soc_camera_link *icl = to_soc_camera_link(icd);
if (icl->power) if (icl->power)
icl->power(&mt9v022->client->dev, 0); icl->power(&client->dev, 0);
return 0; return 0;
} }
static int mt9v022_start_capture(struct soc_camera_device *icd) static int mt9v022_start_capture(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
/* Switch to master "normal" mode */ /* Switch to master "normal" mode */
mt9v022->chip_control &= ~0x10; mt9v022->chip_control &= ~0x10;
if (reg_write(client, MT9V022_CHIP_CONTROL, if (reg_write(client, MT9V022_CHIP_CONTROL,
...@@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd) ...@@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd)
static int mt9v022_stop_capture(struct soc_camera_device *icd) static int mt9v022_stop_capture(struct soc_camera_device *icd)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
/* Switch to snapshot mode */ /* Switch to snapshot mode */
mt9v022->chip_control |= 0x10; mt9v022->chip_control |= 0x10;
if (reg_write(client, MT9V022_CHIP_CONTROL, if (reg_write(client, MT9V022_CHIP_CONTROL,
...@@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd) ...@@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
static int mt9v022_set_bus_param(struct soc_camera_device *icd, static int mt9v022_set_bus_param(struct soc_camera_device *icd,
unsigned long flags) unsigned long flags)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
struct soc_camera_link *icl = client->dev.platform_data; struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
int ret; int ret;
u16 pixclk = 0; u16 pixclk = 0;
...@@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, ...@@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
{ {
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
unsigned int width_flag; unsigned int width_flag;
if (icl->query_bus_param) if (icl->query_bus_param)
...@@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) ...@@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
static int mt9v022_set_crop(struct soc_camera_device *icd, static int mt9v022_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect) struct v4l2_rect *rect)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int ret; int ret;
/* Like in example app. Contradicts the datasheet though */ /* Like in example app. Contradicts the datasheet though */
...@@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd, ...@@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd,
static int mt9v022_set_fmt(struct soc_camera_device *icd, static int mt9v022_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_rect rect = { struct v4l2_rect rect = {
.left = icd->x_current, .left = icd->x_current,
...@@ -374,12 +372,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd, ...@@ -374,12 +372,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd,
static int mt9v022_get_chip_id(struct soc_camera_device *icd, static int mt9v022_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id) struct v4l2_dbg_chip_ident *id)
{ {
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL; return -EINVAL;
if (id->match.addr != mt9v022->client->addr) if (id->match.addr != client->addr)
return -ENODEV; return -ENODEV;
id->ident = mt9v022->model; id->ident = mt9v022->model;
...@@ -392,7 +391,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd, ...@@ -392,7 +391,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
static int mt9v022_get_register(struct soc_camera_device *icd, static int mt9v022_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL; return -EINVAL;
...@@ -412,7 +411,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd, ...@@ -412,7 +411,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
static int mt9v022_set_register(struct soc_camera_device *icd, static int mt9v022_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL; return -EINVAL;
...@@ -481,15 +480,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { ...@@ -481,15 +480,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = {
} }
}; };
static int mt9v022_video_probe(struct soc_camera_device *);
static void mt9v022_video_remove(struct soc_camera_device *);
static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
static struct soc_camera_ops mt9v022_ops = { static struct soc_camera_ops mt9v022_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.probe = mt9v022_video_probe,
.remove = mt9v022_video_remove,
.init = mt9v022_init, .init = mt9v022_init,
.release = mt9v022_release, .release = mt9v022_release,
.start_capture = mt9v022_start_capture, .start_capture = mt9v022_start_capture,
...@@ -513,7 +508,7 @@ static struct soc_camera_ops mt9v022_ops = { ...@@ -513,7 +508,7 @@ static struct soc_camera_ops mt9v022_ops = {
static int mt9v022_get_control(struct soc_camera_device *icd, static int mt9v022_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl) struct v4l2_control *ctrl)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int data; int data;
switch (ctrl->id) { switch (ctrl->id) {
...@@ -549,7 +544,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd, ...@@ -549,7 +544,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl) struct v4l2_control *ctrl)
{ {
int data; int data;
struct i2c_client *client = to_i2c_client(icd->control); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
const struct v4l2_queryctrl *qctrl; const struct v4l2_queryctrl *qctrl;
qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
...@@ -646,11 +641,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd, ...@@ -646,11 +641,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
/* Interface active, can use i2c. If it fails, it can indeed mean, that /* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one */ * this wasn't our capture interface, so, we wait for the right one */
static int mt9v022_video_probe(struct soc_camera_device *icd) static int mt9v022_video_probe(struct soc_camera_device *icd,
struct i2c_client *client)
{ {
struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_link *icl = client->dev.platform_data;
s32 data; s32 data;
int ret; int ret;
unsigned long flags; unsigned long flags;
...@@ -659,6 +654,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) ...@@ -659,6 +654,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface) to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV; return -ENODEV;
/* Switch master clock on */
ret = soc_camera_video_start(icd, &client->dev);
if (ret)
return ret;
/* Read out the chip version register */ /* Read out the chip version register */
data = reg_read(client, MT9V022_CHIP_VERSION); data = reg_read(client, MT9V022_CHIP_VERSION);
...@@ -678,6 +678,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) ...@@ -678,6 +678,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
udelay(200); udelay(200);
if (reg_read(client, MT9V022_RESET)) { if (reg_read(client, MT9V022_RESET)) {
dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
if (ret > 0)
ret = -EIO;
goto ei2c; goto ei2c;
} }
...@@ -694,7 +696,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) ...@@ -694,7 +696,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
} }
if (ret < 0) if (ret < 0)
goto eisis; goto ei2c;
icd->num_formats = 0; icd->num_formats = 0;
...@@ -716,29 +718,23 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) ...@@ -716,29 +718,23 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
if (flags & SOCAM_DATAWIDTH_8) if (flags & SOCAM_DATAWIDTH_8)
icd->num_formats++; icd->num_formats++;
ret = soc_camera_video_start(icd);
if (ret < 0)
goto eisis;
dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
"monochrome" : "colour"); "monochrome" : "colour");
return 0;
eisis:
ei2c: ei2c:
soc_camera_video_stop(icd);
return ret; return ret;
} }
static void mt9v022_video_remove(struct soc_camera_device *icd) static void mt9v022_video_remove(struct soc_camera_device *icd)
{ {
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = mt9v022->client->dev.platform_data; struct soc_camera_link *icl = to_soc_camera_link(icd);
dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
icd->dev.parent, icd->vdev); icd->dev.parent, icd->vdev);
soc_camera_video_stop(icd);
if (icl->free_bus) if (icl->free_bus)
icl->free_bus(icl); icl->free_bus(icl);
} }
...@@ -747,11 +743,17 @@ static int mt9v022_probe(struct i2c_client *client, ...@@ -747,11 +743,17 @@ static int mt9v022_probe(struct i2c_client *client,
const struct i2c_device_id *did) const struct i2c_device_id *did)
{ {
struct mt9v022 *mt9v022; struct mt9v022 *mt9v022;
struct soc_camera_device *icd; struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct soc_camera_link *icl = client->dev.platform_data; struct soc_camera_link *icl;
int ret; int ret;
if (!icd) {
dev_err(&client->dev, "MT9V022: missing soc-camera data!\n");
return -EINVAL;
}
icl = to_soc_camera_link(icd);
if (!icl) { if (!icl) {
dev_err(&client->dev, "MT9V022 driver needs platform data\n"); dev_err(&client->dev, "MT9V022 driver needs platform data\n");
return -EINVAL; return -EINVAL;
...@@ -768,12 +770,9 @@ static int mt9v022_probe(struct i2c_client *client, ...@@ -768,12 +770,9 @@ static int mt9v022_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
mt9v022->client = client;
i2c_set_clientdata(client, mt9v022); i2c_set_clientdata(client, mt9v022);
icd = &mt9v022->icd;
icd->ops = &mt9v022_ops; icd->ops = &mt9v022_ops;
icd->control = &client->dev;
icd->x_min = 1; icd->x_min = 1;
icd->y_min = 4; icd->y_min = 4;
icd->x_current = 1; icd->x_current = 1;
...@@ -783,24 +782,26 @@ static int mt9v022_probe(struct i2c_client *client, ...@@ -783,24 +782,26 @@ static int mt9v022_probe(struct i2c_client *client,
icd->height_min = 32; icd->height_min = 32;
icd->height_max = 480; icd->height_max = 480;
icd->y_skip_top = 1; icd->y_skip_top = 1;
icd->iface = icl->bus_id;
ret = soc_camera_device_register(icd); ret = mt9v022_video_probe(icd, client);
if (ret) if (ret) {
goto eisdr; icd->ops = NULL;
i2c_set_clientdata(client, NULL);
return 0;
eisdr:
kfree(mt9v022); kfree(mt9v022);
}
return ret; return ret;
} }
static int mt9v022_remove(struct i2c_client *client) static int mt9v022_remove(struct i2c_client *client)
{ {
struct mt9v022 *mt9v022 = i2c_get_clientdata(client); struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
struct soc_camera_device *icd = client->dev.platform_data;
soc_camera_device_unregister(&mt9v022->icd); icd->ops = NULL;
mt9v022_video_remove(icd);
i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(mt9v022); kfree(mt9v022);
return 0; return 0;
......
...@@ -503,19 +503,20 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) ...@@ -503,19 +503,20 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
mx3_camera_activate(mx3_cam, icd); mx3_camera_activate(mx3_cam, icd);
ret = icd->ops->init(icd); ret = icd->ops->init(icd);
if (ret < 0) { if (ret < 0)
clk_disable(mx3_cam->clk);
goto einit; goto einit;
}
mx3_cam->icd = icd; mx3_cam->icd = icd;
einit:
ebusy:
if (!ret)
dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
icd->devnum); icd->devnum);
return 0;
einit:
clk_disable(mx3_cam->clk);
ebusy:
return ret; return ret;
} }
...@@ -947,9 +948,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) ...@@ -947,9 +948,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
camera_flags = icd->ops->query_bus_param(icd); camera_flags = icd->ops->query_bus_param(icd);
common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
camera_flags, bus_flags, common_flags);
if (!common_flags) { if (!common_flags) {
dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n", dev_dbg(ici->dev, "no common flags");
camera_flags, bus_flags);
return -EINVAL; return -EINVAL;
} }
...@@ -1002,8 +1004,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) ...@@ -1002,8 +1004,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
SOCAM_DATAWIDTH_4; SOCAM_DATAWIDTH_4;
ret = icd->ops->set_bus_param(icd, common_flags); ret = icd->ops->set_bus_param(icd, common_flags);
if (ret < 0) if (ret < 0) {
dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n",
common_flags, ret);
return ret; return ret;
}
/* /*
* So far only gated clock mode is supported. Add a line * So far only gated clock mode is supported. Add a line
...@@ -1127,8 +1132,9 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) ...@@ -1127,8 +1132,9 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&mx3_cam->capture); INIT_LIST_HEAD(&mx3_cam->capture);
spin_lock_init(&mx3_cam->lock); spin_lock_init(&mx3_cam->lock);
base = ioremap(res->start, res->end - res->start + 1); base = ioremap(res->start, resource_size(res));
if (!base) { if (!base) {
pr_err("Couldn't map %x@%x\n", resource_size(res), res->start);
err = -ENOMEM; err = -ENOMEM;
goto eioremap; goto eioremap;
} }
...@@ -1215,3 +1221,4 @@ module_exit(mx3_camera_exit); ...@@ -1215,3 +1221,4 @@ module_exit(mx3_camera_exit);
MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME);
...@@ -399,8 +399,6 @@ struct ov772x_win_size { ...@@ -399,8 +399,6 @@ struct ov772x_win_size {
struct ov772x_priv { struct ov772x_priv {
struct ov772x_camera_info *info; struct ov772x_camera_info *info;
struct i2c_client *client;
struct soc_camera_device icd;
const struct ov772x_color_format *fmt; const struct ov772x_color_format *fmt;
const struct ov772x_win_size *win; const struct ov772x_win_size *win;
int model; int model;
...@@ -619,42 +617,45 @@ static int ov772x_reset(struct i2c_client *client) ...@@ -619,42 +617,45 @@ static int ov772x_reset(struct i2c_client *client)
static int ov772x_init(struct soc_camera_device *icd) static int ov772x_init(struct soc_camera_device *icd)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret = 0; int ret = 0;
if (priv->info->link.power) { if (icl->power) {
ret = priv->info->link.power(&priv->client->dev, 1); ret = icl->power(&client->dev, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
if (priv->info->link.reset) if (icl->reset)
ret = priv->info->link.reset(&priv->client->dev); ret = icl->reset(&client->dev);
return ret; return ret;
} }
static int ov772x_release(struct soc_camera_device *icd) static int ov772x_release(struct soc_camera_device *icd)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret = 0; int ret = 0;
if (priv->info->link.power) if (icl->power)
ret = priv->info->link.power(&priv->client->dev, 0); ret = icl->power(&client->dev, 0);
return ret; return ret;
} }
static int ov772x_start_capture(struct soc_camera_device *icd) static int ov772x_start_capture(struct soc_camera_device *icd)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct ov772x_priv *priv = i2c_get_clientdata(client);
if (!priv->win || !priv->fmt) { if (!priv->win || !priv->fmt) {
dev_err(&icd->dev, "norm or win select error\n"); dev_err(&icd->dev, "norm or win select error\n");
return -EPERM; return -EPERM;
} }
ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0); ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0);
dev_dbg(&icd->dev, dev_dbg(&icd->dev,
"format %s, win %s\n", priv->fmt->name, priv->win->name); "format %s, win %s\n", priv->fmt->name, priv->win->name);
...@@ -664,8 +665,8 @@ static int ov772x_start_capture(struct soc_camera_device *icd) ...@@ -664,8 +665,8 @@ static int ov772x_start_capture(struct soc_camera_device *icd)
static int ov772x_stop_capture(struct soc_camera_device *icd) static int ov772x_stop_capture(struct soc_camera_device *icd)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
return 0; return 0;
} }
...@@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd, ...@@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd,
static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = &priv->info->link; struct ov772x_priv *priv = i2c_get_clientdata(client);
struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
...@@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) ...@@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
static int ov772x_get_control(struct soc_camera_device *icd, static int ov772x_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl) struct v4l2_control *ctrl)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct ov772x_priv *priv = i2c_get_clientdata(client);
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_VFLIP: case V4L2_CID_VFLIP:
...@@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd, ...@@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd,
static int ov772x_set_control(struct soc_camera_device *icd, static int ov772x_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl) struct v4l2_control *ctrl)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct ov772x_priv *priv = i2c_get_clientdata(client);
int ret = 0; int ret = 0;
u8 val; u8 val;
...@@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd, ...@@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd,
priv->flag_vflip = ctrl->value; priv->flag_vflip = ctrl->value;
if (priv->info->flags & OV772X_FLAG_VFLIP) if (priv->info->flags & OV772X_FLAG_VFLIP)
val ^= VFLIP_IMG; val ^= VFLIP_IMG;
ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val); ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val);
break; break;
case V4L2_CID_HFLIP: case V4L2_CID_HFLIP:
val = ctrl->value ? HFLIP_IMG : 0x00; val = ctrl->value ? HFLIP_IMG : 0x00;
priv->flag_hflip = ctrl->value; priv->flag_hflip = ctrl->value;
if (priv->info->flags & OV772X_FLAG_HFLIP) if (priv->info->flags & OV772X_FLAG_HFLIP)
val ^= HFLIP_IMG; val ^= HFLIP_IMG;
ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val); ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val);
break; break;
} }
...@@ -732,7 +736,8 @@ static int ov772x_set_control(struct soc_camera_device *icd, ...@@ -732,7 +736,8 @@ static int ov772x_set_control(struct soc_camera_device *icd,
static int ov772x_get_chip_id(struct soc_camera_device *icd, static int ov772x_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id) struct v4l2_dbg_chip_ident *id)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct ov772x_priv *priv = i2c_get_clientdata(client);
id->ident = priv->model; id->ident = priv->model;
id->revision = 0; id->revision = 0;
...@@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, ...@@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd,
static int ov772x_get_register(struct soc_camera_device *icd, static int ov772x_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int ret; int ret;
reg->size = 1; reg->size = 1;
if (reg->reg > 0xff) if (reg->reg > 0xff)
return -EINVAL; return -EINVAL;
ret = i2c_smbus_read_byte_data(priv->client, reg->reg); ret = i2c_smbus_read_byte_data(client, reg->reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd, ...@@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd,
static int ov772x_set_register(struct soc_camera_device *icd, static int ov772x_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->reg > 0xff || if (reg->reg > 0xff ||
reg->val > 0xff) reg->val > 0xff)
return -EINVAL; return -EINVAL;
return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
} }
#endif #endif
...@@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height) ...@@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height)
return win; return win;
} }
static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, static int ov772x_set_params(struct soc_camera_device *icd,
u32 pixfmt) u32 width, u32 height, u32 pixfmt)
{ {
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct ov772x_priv *priv = i2c_get_clientdata(client);
int ret = -EINVAL; int ret = -EINVAL;
u8 val; u8 val;
int i; int i;
...@@ -810,6 +817,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ...@@ -810,6 +817,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
break; break;
} }
} }
dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i);
if (!priv->fmt) if (!priv->fmt)
goto ov772x_set_fmt_error; goto ov772x_set_fmt_error;
...@@ -821,7 +829,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ...@@ -821,7 +829,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
/* /*
* reset hardware * reset hardware
*/ */
ov772x_reset(priv->client); ov772x_reset(client);
/* /*
* Edge Ctrl * Edge Ctrl
...@@ -835,17 +843,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ...@@ -835,17 +843,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
* Remove it when manual mode. * Remove it when manual mode.
*/ */
ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00); ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00);
if (ret < 0) if (ret < 0)
goto ov772x_set_fmt_error; goto ov772x_set_fmt_error;
ret = ov772x_mask_set(priv->client, ret = ov772x_mask_set(client,
EDGE_TRSHLD, EDGE_THRESHOLD_MASK, EDGE_TRSHLD, EDGE_THRESHOLD_MASK,
priv->info->edgectrl.threshold); priv->info->edgectrl.threshold);
if (ret < 0) if (ret < 0)
goto ov772x_set_fmt_error; goto ov772x_set_fmt_error;
ret = ov772x_mask_set(priv->client, ret = ov772x_mask_set(client,
EDGE_STRNGT, EDGE_STRENGTH_MASK, EDGE_STRNGT, EDGE_STRENGTH_MASK,
priv->info->edgectrl.strength); priv->info->edgectrl.strength);
if (ret < 0) if (ret < 0)
...@@ -857,13 +865,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ...@@ -857,13 +865,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
* *
* set upper and lower limit * set upper and lower limit
*/ */
ret = ov772x_mask_set(priv->client, ret = ov772x_mask_set(client,
EDGE_UPPER, EDGE_UPPER_MASK, EDGE_UPPER, EDGE_UPPER_MASK,
priv->info->edgectrl.upper); priv->info->edgectrl.upper);
if (ret < 0) if (ret < 0)
goto ov772x_set_fmt_error; goto ov772x_set_fmt_error;
ret = ov772x_mask_set(priv->client, ret = ov772x_mask_set(client,
EDGE_LOWER, EDGE_LOWER_MASK, EDGE_LOWER, EDGE_LOWER_MASK,
priv->info->edgectrl.lower); priv->info->edgectrl.lower);
if (ret < 0) if (ret < 0)
...@@ -873,7 +881,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ...@@ -873,7 +881,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
/* /*
* set size format * set size format
*/ */
ret = ov772x_write_array(priv->client, priv->win->regs); ret = ov772x_write_array(client, priv->win->regs);
if (ret < 0) if (ret < 0)
goto ov772x_set_fmt_error; goto ov772x_set_fmt_error;
...@@ -882,7 +890,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ...@@ -882,7 +890,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
*/ */
val = priv->fmt->dsp3; val = priv->fmt->dsp3;
if (val) { if (val) {
ret = ov772x_mask_set(priv->client, ret = ov772x_mask_set(client,
DSP_CTRL3, UV_MASK, val); DSP_CTRL3, UV_MASK, val);
if (ret < 0) if (ret < 0)
goto ov772x_set_fmt_error; goto ov772x_set_fmt_error;
...@@ -901,7 +909,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ...@@ -901,7 +909,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
if (priv->flag_hflip) if (priv->flag_hflip)
val ^= HFLIP_IMG; val ^= HFLIP_IMG;
ret = ov772x_mask_set(priv->client, ret = ov772x_mask_set(client,
COM3, SWAP_MASK | IMG_MASK, val); COM3, SWAP_MASK | IMG_MASK, val);
if (ret < 0) if (ret < 0)
goto ov772x_set_fmt_error; goto ov772x_set_fmt_error;
...@@ -910,7 +918,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ...@@ -910,7 +918,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
* set COM7 * set COM7
*/ */
val = priv->win->com7_bit | priv->fmt->com7; val = priv->win->com7_bit | priv->fmt->com7;
ret = ov772x_mask_set(priv->client, ret = ov772x_mask_set(client,
COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK),
val); val);
if (ret < 0) if (ret < 0)
...@@ -920,7 +928,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ...@@ -920,7 +928,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
ov772x_set_fmt_error: ov772x_set_fmt_error:
ov772x_reset(priv->client); ov772x_reset(client);
priv->win = NULL; priv->win = NULL;
priv->fmt = NULL; priv->fmt = NULL;
...@@ -930,22 +938,22 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ...@@ -930,22 +938,22 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
static int ov772x_set_crop(struct soc_camera_device *icd, static int ov772x_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect) struct v4l2_rect *rect)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct ov772x_priv *priv = i2c_get_clientdata(client);
if (!priv->fmt) if (!priv->fmt)
return -EINVAL; return -EINVAL;
return ov772x_set_params(priv, rect->width, rect->height, return ov772x_set_params(icd, rect->width, rect->height,
priv->fmt->fourcc); priv->fmt->fourcc);
} }
static int ov772x_set_fmt(struct soc_camera_device *icd, static int ov772x_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_pix_format *pix = &f->fmt.pix;
return ov772x_set_params(priv, pix->width, pix->height, return ov772x_set_params(icd, pix->width, pix->height,
pix->pixelformat); pix->pixelformat);
} }
...@@ -967,11 +975,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd, ...@@ -967,11 +975,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd,
return 0; return 0;
} }
static int ov772x_video_probe(struct soc_camera_device *icd) static int ov772x_video_probe(struct soc_camera_device *icd,
struct i2c_client *client)
{ {
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct ov772x_priv *priv = i2c_get_clientdata(client);
u8 pid, ver; u8 pid, ver;
const char *devname; const char *devname;
int ret;
/* /*
* We must have a parent by now. And it cannot be a wrong one. * We must have a parent by now. And it cannot be a wrong one.
...@@ -993,11 +1003,16 @@ static int ov772x_video_probe(struct soc_camera_device *icd) ...@@ -993,11 +1003,16 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
icd->formats = ov772x_fmt_lists; icd->formats = ov772x_fmt_lists;
icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists);
/* Switch master clock on */
ret = soc_camera_video_start(icd, &client->dev);
if (ret)
return ret;
/* /*
* check and show product ID and manufacturer ID * check and show product ID and manufacturer ID
*/ */
pid = i2c_smbus_read_byte_data(priv->client, PID); pid = i2c_smbus_read_byte_data(client, PID);
ver = i2c_smbus_read_byte_data(priv->client, VER); ver = i2c_smbus_read_byte_data(client, VER);
switch (VERSION(pid, ver)) { switch (VERSION(pid, ver)) {
case OV7720: case OV7720:
...@@ -1011,7 +1026,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd) ...@@ -1011,7 +1026,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
default: default:
dev_err(&icd->dev, dev_err(&icd->dev,
"Product ID error %x:%x\n", pid, ver); "Product ID error %x:%x\n", pid, ver);
return -ENODEV; ret = -ENODEV;
goto ever;
} }
dev_info(&icd->dev, dev_info(&icd->dev,
...@@ -1019,21 +1035,17 @@ static int ov772x_video_probe(struct soc_camera_device *icd) ...@@ -1019,21 +1035,17 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
devname, devname,
pid, pid,
ver, ver,
i2c_smbus_read_byte_data(priv->client, MIDH), i2c_smbus_read_byte_data(client, MIDH),
i2c_smbus_read_byte_data(priv->client, MIDL)); i2c_smbus_read_byte_data(client, MIDL));
return soc_camera_video_start(icd);
}
static void ov772x_video_remove(struct soc_camera_device *icd)
{
soc_camera_video_stop(icd); soc_camera_video_stop(icd);
ever:
return ret;
} }
static struct soc_camera_ops ov772x_ops = { static struct soc_camera_ops ov772x_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.probe = ov772x_video_probe,
.remove = ov772x_video_remove,
.init = ov772x_init, .init = ov772x_init,
.release = ov772x_release, .release = ov772x_release,
.start_capture = ov772x_start_capture, .start_capture = ov772x_start_capture,
...@@ -1063,15 +1075,21 @@ static int ov772x_probe(struct i2c_client *client, ...@@ -1063,15 +1075,21 @@ static int ov772x_probe(struct i2c_client *client,
{ {
struct ov772x_priv *priv; struct ov772x_priv *priv;
struct ov772x_camera_info *info; struct ov772x_camera_info *info;
struct soc_camera_device *icd; struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct soc_camera_link *icl;
int ret; int ret;
if (!client->dev.platform_data) if (!icd) {
dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
return -EINVAL; return -EINVAL;
}
info = container_of(client->dev.platform_data, icl = to_soc_camera_link(icd);
struct ov772x_camera_info, link); if (!icl)
return -EINVAL;
info = container_of(icl, struct ov772x_camera_info, link);
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_err(&adapter->dev, dev_err(&adapter->dev,
...@@ -1085,19 +1103,15 @@ static int ov772x_probe(struct i2c_client *client, ...@@ -1085,19 +1103,15 @@ static int ov772x_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
priv->info = info; priv->info = info;
priv->client = client;
i2c_set_clientdata(client, priv); i2c_set_clientdata(client, priv);
icd = &priv->icd;
icd->ops = &ov772x_ops; icd->ops = &ov772x_ops;
icd->control = &client->dev;
icd->width_max = MAX_WIDTH; icd->width_max = MAX_WIDTH;
icd->height_max = MAX_HEIGHT; icd->height_max = MAX_HEIGHT;
icd->iface = priv->info->link.bus_id;
ret = soc_camera_device_register(icd);
ret = ov772x_video_probe(icd, client);
if (ret) { if (ret) {
icd->ops = NULL;
i2c_set_clientdata(client, NULL); i2c_set_clientdata(client, NULL);
kfree(priv); kfree(priv);
} }
...@@ -1108,8 +1122,9 @@ static int ov772x_probe(struct i2c_client *client, ...@@ -1108,8 +1122,9 @@ static int ov772x_probe(struct i2c_client *client,
static int ov772x_remove(struct i2c_client *client) static int ov772x_remove(struct i2c_client *client)
{ {
struct ov772x_priv *priv = i2c_get_clientdata(client); struct ov772x_priv *priv = i2c_get_clientdata(client);
struct soc_camera_device *icd = client->dev.platform_data;
soc_camera_device_unregister(&priv->icd); icd->ops = NULL;
i2c_set_clientdata(client, NULL); i2c_set_clientdata(client, NULL);
kfree(priv); kfree(priv);
return 0; return 0;
......
...@@ -830,7 +830,8 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q, ...@@ -830,7 +830,8 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q,
sizeof(struct pxa_buffer), icd); sizeof(struct pxa_buffer), icd);
} }
static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) static u32 mclk_get_divisor(struct platform_device *pdev,
struct pxa_camera_dev *pcdev)
{ {
unsigned long mclk = pcdev->mclk; unsigned long mclk = pcdev->mclk;
u32 div; u32 div;
...@@ -842,7 +843,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) ...@@ -842,7 +843,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
/* mclk <= ciclk / 4 (27.4.2) */ /* mclk <= ciclk / 4 (27.4.2) */
if (mclk > lcdclk / 4) { if (mclk > lcdclk / 4) {
mclk = lcdclk / 4; mclk = lcdclk / 4;
dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk); dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk);
} }
/* We verify mclk != 0, so if anyone breaks it, here comes their Oops */ /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
...@@ -852,8 +853,8 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) ...@@ -852,8 +853,8 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
pcdev->mclk = lcdclk / (2 * (div + 1)); pcdev->mclk = lcdclk / (2 * (div + 1));
dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, " dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n",
"divisor %u\n", lcdclk, mclk, div); lcdclk, mclk, div);
return div; return div;
} }
...@@ -958,15 +959,20 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) ...@@ -958,15 +959,20 @@ static int pxa_camera_add_device(struct soc_camera_device *icd)
goto ebusy; goto ebusy;
} }
dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
icd->devnum);
pxa_camera_activate(pcdev); pxa_camera_activate(pcdev);
ret = icd->ops->init(icd); ret = icd->ops->init(icd);
if (ret < 0)
goto einit;
if (!ret)
pcdev->icd = icd; pcdev->icd = icd;
dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
icd->devnum);
return 0;
einit:
pxa_camera_deactivate(pcdev);
ebusy: ebusy:
return ret; return ret;
} }
...@@ -1575,8 +1581,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) ...@@ -1575,8 +1581,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev)
pcdev->mclk = 20000000; pcdev->mclk = 20000000;
} }
pcdev->soc_host.dev = &pdev->dev; pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev);
pcdev->mclk_divisor = mclk_get_divisor(pcdev);
INIT_LIST_HEAD(&pcdev->capture); INIT_LIST_HEAD(&pcdev->capture);
spin_lock_init(&pcdev->lock); spin_lock_init(&pcdev->lock);
...@@ -1641,6 +1646,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) ...@@ -1641,6 +1646,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev)
pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME;
pcdev->soc_host.ops = &pxa_soc_camera_host_ops; pcdev->soc_host.ops = &pxa_soc_camera_host_ops;
pcdev->soc_host.priv = pcdev; pcdev->soc_host.priv = pcdev;
pcdev->soc_host.dev = &pdev->dev;
pcdev->soc_host.nr = pdev->id; pcdev->soc_host.nr = pdev->id;
err = soc_camera_host_register(&pcdev->soc_host); err = soc_camera_host_register(&pcdev->soc_host);
...@@ -1722,3 +1728,4 @@ module_exit(pxa_camera_exit); ...@@ -1722,3 +1728,4 @@ module_exit(pxa_camera_exit);
MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" PXA_CAM_DRV_NAME);
...@@ -356,11 +356,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) ...@@ -356,11 +356,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
"SuperH Mobile CEU driver attached to camera %d\n", "SuperH Mobile CEU driver attached to camera %d\n",
icd->devnum); icd->devnum);
clk_enable(pcdev->clk);
ret = icd->ops->init(icd); ret = icd->ops->init(icd);
if (ret) if (ret) {
clk_disable(pcdev->clk);
goto err; goto err;
}
pm_runtime_get_sync(ici->dev);
ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
while (ceu_read(pcdev, CSTSR) & 1) while (ceu_read(pcdev, CSTSR) & 1)
...@@ -394,10 +396,10 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) ...@@ -394,10 +396,10 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
} }
spin_unlock_irqrestore(&pcdev->lock, flags); spin_unlock_irqrestore(&pcdev->lock, flags);
pm_runtime_put_sync(ici->dev);
icd->ops->release(icd); icd->ops->release(icd);
clk_disable(pcdev->clk);
dev_info(&icd->dev, dev_info(&icd->dev,
"SuperH Mobile CEU driver detached from camera %d\n", "SuperH Mobile CEU driver detached from camera %d\n",
icd->devnum); icd->devnum);
...@@ -946,3 +948,4 @@ module_exit(sh_mobile_ceu_exit); ...@@ -946,3 +948,4 @@ module_exit(sh_mobile_ceu_exit);
MODULE_DESCRIPTION("SuperH Mobile CEU driver"); MODULE_DESCRIPTION("SuperH Mobile CEU driver");
MODULE_AUTHOR("Magnus Damm"); MODULE_AUTHOR("Magnus Damm");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:sh_mobile_ceu");
...@@ -21,15 +21,15 @@ ...@@ -21,15 +21,15 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include <media/v4l2-dev.h>
#include <media/videobuf-core.h> #include <media/videobuf-core.h>
/* Default to VGA resolution */ /* Default to VGA resolution */
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
static LIST_HEAD(hosts); static LIST_HEAD(hosts);
static LIST_HEAD(devices); static LIST_HEAD(devices);
static DEFINE_MUTEX(list_lock); static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */
const struct soc_camera_data_format *soc_camera_format_by_fourcc( const struct soc_camera_data_format *soc_camera_format_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc) struct soc_camera_device *icd, unsigned int fourcc)
...@@ -209,6 +209,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv, ...@@ -209,6 +209,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
} }
/* Always entered with .video_lock held */
static int soc_camera_init_user_formats(struct soc_camera_device *icd) static int soc_camera_init_user_formats(struct soc_camera_device *icd)
{ {
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
...@@ -257,9 +258,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) ...@@ -257,9 +258,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
return 0; return 0;
} }
/* Always entered with .video_lock held */
static void soc_camera_free_user_formats(struct soc_camera_device *icd) static void soc_camera_free_user_formats(struct soc_camera_device *icd)
{ {
icd->current_fmt = NULL;
vfree(icd->user_formats); vfree(icd->user_formats);
icd->user_formats = NULL;
} }
/* Called with .vb_lock held */ /* Called with .vb_lock held */
...@@ -310,10 +314,6 @@ static int soc_camera_open(struct file *file) ...@@ -310,10 +314,6 @@ static int soc_camera_open(struct file *file)
struct soc_camera_file *icf; struct soc_camera_file *icf;
int ret; int ret;
icf = vmalloc(sizeof(*icf));
if (!icf)
return -ENOMEM;
/* /*
* It is safe to dereference these pointers now as long as a user has * It is safe to dereference these pointers now as long as a user has
* the video device open - we are protected by the held cdev reference. * the video device open - we are protected by the held cdev reference.
...@@ -321,8 +321,17 @@ static int soc_camera_open(struct file *file) ...@@ -321,8 +321,17 @@ static int soc_camera_open(struct file *file)
vdev = video_devdata(file); vdev = video_devdata(file);
icd = container_of(vdev->parent, struct soc_camera_device, dev); icd = container_of(vdev->parent, struct soc_camera_device, dev);
if (!icd->ops)
/* No device driver attached */
return -ENODEV;
ici = to_soc_camera_host(icd->dev.parent); ici = to_soc_camera_host(icd->dev.parent);
icf = vmalloc(sizeof(*icf));
if (!icf)
return -ENOMEM;
if (!try_module_get(icd->ops->owner)) { if (!try_module_get(icd->ops->owner)) {
dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
ret = -EINVAL; ret = -EINVAL;
...@@ -335,7 +344,7 @@ static int soc_camera_open(struct file *file) ...@@ -335,7 +344,7 @@ static int soc_camera_open(struct file *file)
goto emgi; goto emgi;
} }
/* Protect against icd->remove() until we module_get() both drivers. */ /* Protect against icd->ops->remove() until we module_get() both drivers. */
mutex_lock(&icd->video_lock); mutex_lock(&icd->video_lock);
icf->icd = icd; icf->icd = icd;
...@@ -350,11 +359,18 @@ static int soc_camera_open(struct file *file) ...@@ -350,11 +359,18 @@ static int soc_camera_open(struct file *file)
.width = icd->width, .width = icd->width,
.height = icd->height, .height = icd->height,
.field = icd->field, .field = icd->field,
.pixelformat = icd->current_fmt->fourcc,
.colorspace = icd->current_fmt->colorspace,
}, },
}; };
ret = soc_camera_init_user_formats(icd);
if (ret < 0)
goto eiufmt;
dev_dbg(&icd->dev, "Using fmt %x\n", icd->current_fmt->fourcc);
f.fmt.pix.pixelformat = icd->current_fmt->fourcc;
f.fmt.pix.colorspace = icd->current_fmt->colorspace;
ret = ici->ops->add(icd); ret = ici->ops->add(icd);
if (ret < 0) { if (ret < 0) {
dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
...@@ -383,6 +399,8 @@ static int soc_camera_open(struct file *file) ...@@ -383,6 +399,8 @@ static int soc_camera_open(struct file *file)
esfmt: esfmt:
ici->ops->remove(icd); ici->ops->remove(icd);
eiciadd: eiciadd:
soc_camera_free_user_formats(icd);
eiufmt:
icd->use_count--; icd->use_count--;
mutex_unlock(&icd->video_lock); mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner); module_put(ici->ops->owner);
...@@ -402,8 +420,10 @@ static int soc_camera_close(struct file *file) ...@@ -402,8 +420,10 @@ static int soc_camera_close(struct file *file)
mutex_lock(&icd->video_lock); mutex_lock(&icd->video_lock);
icd->use_count--; icd->use_count--;
if (!icd->use_count) if (!icd->use_count) {
ici->ops->remove(icd); ici->ops->remove(icd);
soc_camera_free_user_formats(icd);
}
mutex_unlock(&icd->video_lock); mutex_unlock(&icd->video_lock);
...@@ -764,29 +784,6 @@ static int soc_camera_s_register(struct file *file, void *fh, ...@@ -764,29 +784,6 @@ static int soc_camera_s_register(struct file *file, void *fh,
} }
#endif #endif
static int device_register_link(struct soc_camera_device *icd)
{
int ret = dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum);
if (!ret)
ret = device_register(&icd->dev);
if (ret < 0) {
/* Prevent calling device_unregister() */
icd->dev.parent = NULL;
dev_err(&icd->dev, "Cannot register device: %d\n", ret);
/* Even if probe() was unsuccessful for all registered drivers,
* device_register() returns 0, and we add the link, just to
* document this camera's control device */
} else if (icd->control)
/* Have to sysfs_remove_link() before device_unregister()? */
if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj,
"control"))
dev_warn(&icd->dev,
"Failed creating the control symlink\n");
return ret;
}
/* So far this function cannot fail */ /* So far this function cannot fail */
static void scan_add_host(struct soc_camera_host *ici) static void scan_add_host(struct soc_camera_host *ici)
{ {
...@@ -796,106 +793,124 @@ static void scan_add_host(struct soc_camera_host *ici) ...@@ -796,106 +793,124 @@ static void scan_add_host(struct soc_camera_host *ici)
list_for_each_entry(icd, &devices, list) { list_for_each_entry(icd, &devices, list) {
if (icd->iface == ici->nr) { if (icd->iface == ici->nr) {
int ret;
icd->dev.parent = ici->dev; icd->dev.parent = ici->dev;
device_register_link(icd); dev_set_name(&icd->dev, "%u-%u", icd->iface,
icd->devnum);
ret = device_register(&icd->dev);
if (ret < 0) {
icd->dev.parent = NULL;
dev_err(&icd->dev,
"Cannot register device: %d\n", ret);
}
} }
} }
mutex_unlock(&list_lock); mutex_unlock(&list_lock);
} }
/* return: 0 if no match found or a match found and #ifdef CONFIG_I2C_BOARDINFO
* device_register() successful, error code otherwise */ static int soc_camera_init_i2c(struct soc_camera_device *icd,
static int scan_add_device(struct soc_camera_device *icd) struct soc_camera_link *icl)
{ {
struct soc_camera_host *ici; struct i2c_client *client;
int ret = 0; struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id);
int ret;
mutex_lock(&list_lock); if (!adap) {
ret = -ENODEV;
dev_err(&icd->dev, "Cannot get I2C adapter #%d. No driver?\n",
icl->i2c_adapter_id);
goto ei2cga;
}
list_add_tail(&icd->list, &devices); icl->board_info->platform_data = icd;
/* Watch out for class_for_each_device / class_find_device API by client = i2c_new_device(adap, icl->board_info);
* Dave Young <hidave.darkstar@gmail.com> */ if (!client) {
list_for_each_entry(ici, &hosts, list) { ret = -ENOMEM;
if (icd->iface == ici->nr) { goto ei2cnd;
ret = 1;
icd->dev.parent = ici->dev;
break;
}
} }
mutex_unlock(&list_lock); /*
* We set icd drvdata at two locations - here and in
if (ret) * soc_camera_video_start(). Depending on the module loading /
ret = device_register_link(icd); * initialisation order one of these locations will be entered first
*/
/* Use to_i2c_client(dev) to recover the i2c client */
dev_set_drvdata(&icd->dev, &client->dev);
return 0;
ei2cnd:
i2c_put_adapter(adap);
ei2cga:
return ret; return ret;
} }
static void soc_camera_free_i2c(struct soc_camera_device *icd)
{
struct i2c_client *client =
to_i2c_client(to_soc_camera_control(icd));
dev_set_drvdata(&icd->dev, NULL);
i2c_unregister_device(client);
i2c_put_adapter(client->adapter);
}
#else
#define soc_camera_init_i2c(icd, icl) (-ENODEV)
#define soc_camera_free_i2c(icd) do {} while (0)
#endif
static int video_dev_create(struct soc_camera_device *icd);
/* Called during host-driver probe */
static int soc_camera_probe(struct device *dev) static int soc_camera_probe(struct device *dev)
{ {
struct soc_camera_device *icd = to_soc_camera_dev(dev); struct soc_camera_device *icd = to_soc_camera_dev(dev);
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret; int ret;
/* dev_info(dev, "Probing %s\n", dev_name(dev));
* Possible race scenario:
* modprobe <camera-host-driver> triggers __func__
* at this moment respective <camera-sensor-driver> gets rmmod'ed
* to protect take module references.
*/
if (!try_module_get(icd->ops->owner)) { ret = video_dev_create(icd);
dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); if (ret < 0)
ret = -EINVAL; goto evdc;
goto emgd;
}
if (!try_module_get(ici->ops->owner)) { /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */
dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); if (icl->board_info) {
ret = soc_camera_init_i2c(icd, icl);
if (ret < 0)
goto eadddev;
} else if (!icl->add_device || !icl->del_device) {
ret = -EINVAL; ret = -EINVAL;
goto emgi; goto eadddev;
} } else {
ret = icl->add_device(icl, &icd->dev);
mutex_lock(&icd->video_lock);
/* We only call ->add() here to activate and probe the camera.
* We shall ->remove() and deactivate it immediately afterwards. */
ret = ici->ops->add(icd);
if (ret < 0) if (ret < 0)
goto eiadd; goto eadddev;
}
ret = icd->ops->probe(icd);
if (ret >= 0) {
const struct v4l2_queryctrl *qctrl;
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
icd->exposure = qctrl ? qctrl->default_value :
(unsigned short)~0;
ret = soc_camera_init_user_formats(icd); ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, icd->vdev->minor);
if (ret < 0) { if (ret < 0) {
if (icd->ops->remove) dev_err(&icd->dev, "video_register_device failed: %d\n", ret);
icd->ops->remove(icd); goto evidregd;
goto eiufmt;
} }
icd->height = DEFAULT_HEIGHT; /* Do we have to sysfs_remove_link() before device_unregister()? */
icd->width = DEFAULT_WIDTH; if (to_soc_camera_control(icd) &&
icd->field = V4L2_FIELD_ANY; sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj,
} "control"))
dev_warn(&icd->dev, "Failed creating the control symlink\n");
eiufmt:
ici->ops->remove(icd); return 0;
eiadd:
mutex_unlock(&icd->video_lock); evidregd:
module_put(ici->ops->owner); if (icl->board_info)
emgi: soc_camera_free_i2c(icd);
module_put(icd->ops->owner); else
emgd: icl->del_device(icl);
eadddev:
video_device_release(icd->vdev);
evdc:
return ret; return ret;
} }
...@@ -904,13 +919,22 @@ static int soc_camera_probe(struct device *dev) ...@@ -904,13 +919,22 @@ static int soc_camera_probe(struct device *dev)
static int soc_camera_remove(struct device *dev) static int soc_camera_remove(struct device *dev)
{ {
struct soc_camera_device *icd = to_soc_camera_dev(dev); struct soc_camera_device *icd = to_soc_camera_dev(dev);
struct soc_camera_link *icl = to_soc_camera_link(icd);
struct video_device *vdev = icd->vdev;
BUG_ON(!dev->parent);
if (vdev) {
mutex_lock(&icd->video_lock); mutex_lock(&icd->video_lock);
if (icd->ops->remove) video_unregister_device(vdev);
icd->ops->remove(icd); icd->vdev = NULL;
mutex_unlock(&icd->video_lock); mutex_unlock(&icd->video_lock);
}
soc_camera_free_user_formats(icd); if (icl->board_info)
soc_camera_free_i2c(icd);
else
icl->del_device(icl);
return 0; return 0;
} }
...@@ -1005,10 +1029,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) ...@@ -1005,10 +1029,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
list_for_each_entry(icd, &devices, list) { list_for_each_entry(icd, &devices, list) {
if (icd->dev.parent == ici->dev) { if (icd->dev.parent == ici->dev) {
/* The bus->remove will be called */
device_unregister(&icd->dev); device_unregister(&icd->dev);
/* Not before device_unregister(), .remove /* Not before device_unregister(), .remove
* needs parent to call ici->ops->remove() */ * needs parent to call ici->ops->remove() */
icd->dev.parent = NULL; icd->dev.parent = NULL;
/* If the host module is loaded again, device_register()
* would complain "already initialised" */
memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
} }
} }
...@@ -1020,26 +1048,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) ...@@ -1020,26 +1048,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
EXPORT_SYMBOL(soc_camera_host_unregister); EXPORT_SYMBOL(soc_camera_host_unregister);
/* Image capture device */ /* Image capture device */
int soc_camera_device_register(struct soc_camera_device *icd) static int soc_camera_device_register(struct soc_camera_device *icd)
{ {
struct soc_camera_device *ix; struct soc_camera_device *ix;
int num = -1, i; int num = -1, i;
if (!icd || !icd->ops ||
!icd->ops->probe ||
!icd->ops->init ||
!icd->ops->release ||
!icd->ops->start_capture ||
!icd->ops->stop_capture ||
!icd->ops->set_crop ||
!icd->ops->set_fmt ||
!icd->ops->try_fmt ||
!icd->ops->query_bus_param ||
!icd->ops->set_bus_param)
return -EINVAL;
for (i = 0; i < 256 && num < 0; i++) { for (i = 0; i < 256 && num < 0; i++) {
num = i; num = i;
/* Check if this index is available on this interface */
list_for_each_entry(ix, &devices, list) { list_for_each_entry(ix, &devices, list) {
if (ix->iface == icd->iface && ix->devnum == i) { if (ix->iface == icd->iface && ix->devnum == i) {
num = -1; num = -1;
...@@ -1061,21 +1077,15 @@ int soc_camera_device_register(struct soc_camera_device *icd) ...@@ -1061,21 +1077,15 @@ int soc_camera_device_register(struct soc_camera_device *icd)
icd->host_priv = NULL; icd->host_priv = NULL;
mutex_init(&icd->video_lock); mutex_init(&icd->video_lock);
return scan_add_device(icd); list_add_tail(&icd->list, &devices);
return 0;
} }
EXPORT_SYMBOL(soc_camera_device_register);
void soc_camera_device_unregister(struct soc_camera_device *icd) static void soc_camera_device_unregister(struct soc_camera_device *icd)
{ {
mutex_lock(&list_lock);
list_del(&icd->list); list_del(&icd->list);
/* The bus->remove will be eventually called */
if (icd->dev.parent)
device_unregister(&icd->dev);
mutex_unlock(&list_lock);
} }
EXPORT_SYMBOL(soc_camera_device_unregister);
static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
.vidioc_querycap = soc_camera_querycap, .vidioc_querycap = soc_camera_querycap,
...@@ -1106,22 +1116,13 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { ...@@ -1106,22 +1116,13 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
#endif #endif
}; };
/* static int video_dev_create(struct soc_camera_device *icd)
* Usually called from the struct soc_camera_ops .probe() method, i.e., from
* soc_camera_probe() above with .video_lock held
*/
int soc_camera_video_start(struct soc_camera_device *icd)
{ {
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
int err = -ENOMEM; struct video_device *vdev = video_device_alloc();
struct video_device *vdev;
if (!icd->dev.parent)
return -ENODEV;
vdev = video_device_alloc();
if (!vdev) if (!vdev)
goto evidallocd; return -ENOMEM;
dev_dbg(ici->dev, "Allocated video_device %p\n", vdev); dev_dbg(ici->dev, "Allocated video_device %p\n", vdev);
strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
...@@ -1132,114 +1133,106 @@ int soc_camera_video_start(struct soc_camera_device *icd) ...@@ -1132,114 +1133,106 @@ int soc_camera_video_start(struct soc_camera_device *icd)
vdev->ioctl_ops = &soc_camera_ioctl_ops; vdev->ioctl_ops = &soc_camera_ioctl_ops;
vdev->release = video_device_release; vdev->release = video_device_release;
vdev->minor = -1; vdev->minor = -1;
vdev->tvnorms = V4L2_STD_UNKNOWN, vdev->tvnorms = V4L2_STD_UNKNOWN;
err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
if (err < 0) {
dev_err(vdev->parent, "video_register_device failed\n");
goto evidregd;
}
icd->vdev = vdev; icd->vdev = vdev;
return 0; return 0;
}
evidregd: /*
video_device_release(vdev); * Usually called from the struct soc_camera_ops .probe() method, i.e., from
evidallocd: * soc_camera_probe() above with .video_lock held
return err; */
int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
const struct v4l2_queryctrl *qctrl;
if (!icd->dev.parent)
return -ENODEV;
if (!icd->ops ||
!icd->ops->init ||
!icd->ops->release ||
!icd->ops->start_capture ||
!icd->ops->stop_capture ||
!icd->ops->set_fmt ||
!icd->ops->try_fmt ||
!icd->ops->query_bus_param ||
!icd->ops->set_bus_param)
return -EINVAL;
/* See comment in soc_camera_probe() */
dev_set_drvdata(&icd->dev, dev);
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0;
return ici->ops->add(icd);
} }
EXPORT_SYMBOL(soc_camera_video_start); EXPORT_SYMBOL(soc_camera_video_start);
/* Called from client .remove() methods with .video_lock held */ /* Called from client .remove() methods with .video_lock held */
void soc_camera_video_stop(struct soc_camera_device *icd) void soc_camera_video_stop(struct soc_camera_device *icd)
{ {
struct video_device *vdev = icd->vdev; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
dev_dbg(&icd->dev, "%s\n", __func__); dev_dbg(&icd->dev, "%s\n", __func__);
if (!icd->dev.parent || !vdev) ici->ops->remove(icd);
return;
video_unregister_device(vdev);
icd->vdev = NULL;
} }
EXPORT_SYMBOL(soc_camera_video_stop); EXPORT_SYMBOL(soc_camera_video_stop);
#ifdef CONFIG_I2C_BOARDINFO static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
static int soc_camera_init_i2c(struct platform_device *pdev,
struct soc_camera_link *icl)
{ {
struct i2c_client *client; struct soc_camera_link *icl = pdev->dev.platform_data;
struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); struct soc_camera_device *icd;
int ret; int ret;
if (!adap) { if (!icl)
ret = -ENODEV; return -EINVAL;
dev_err(&pdev->dev, "Cannot get adapter #%d. No driver?\n",
icl->i2c_adapter_id);
goto ei2cga;
}
icl->board_info->platform_data = icl; icd = kzalloc(sizeof(*icd), GFP_KERNEL);
client = i2c_new_device(adap, icl->board_info); if (!icd)
if (!client) { return -ENOMEM;
ret = -ENOMEM;
goto ei2cnd;
}
platform_set_drvdata(pdev, client); icd->iface = icl->bus_id;
platform_set_drvdata(pdev, icd);
icd->dev.platform_data = icl;
return 0; ret = soc_camera_device_register(icd);
ei2cnd: if (ret < 0)
i2c_put_adapter(adap); goto escdevreg;
ei2cga:
return ret;
}
static void soc_camera_free_i2c(struct platform_device *pdev) return 0;
{
struct i2c_client *client = platform_get_drvdata(pdev);
if (!client) escdevreg:
return; kfree(icd);
i2c_unregister_device(client); return ret;
i2c_put_adapter(client->adapter);
} }
#else
#define soc_camera_init_i2c(d, icl) (-ENODEV)
#define soc_camera_free_i2c(d) do {} while (0)
#endif
static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) /* Only called on rmmod for each platform device, since they are not
* hot-pluggable. Now we know, that all our users - hosts and devices have
* been unloaded already */
static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
{ {
struct soc_camera_link *icl = pdev->dev.platform_data; struct soc_camera_device *icd = platform_get_drvdata(pdev);
if (!icl) if (!icd)
return -EINVAL; return -EINVAL;
if (icl->board_info) soc_camera_device_unregister(icd);
return soc_camera_init_i2c(pdev, icl);
else if (!icl->add_device || !icl->del_device)
return -EINVAL;
/* &pdev->dev will become &icd->dev */ kfree(icd);
return icl->add_device(icl, &pdev->dev);
}
static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
{
struct soc_camera_link *icl = pdev->dev.platform_data;
if (icl->board_info)
soc_camera_free_i2c(pdev);
else
icl->del_device(icl);
return 0; return 0;
} }
static struct platform_driver __refdata soc_camera_pdrv = { static struct platform_driver __refdata soc_camera_pdrv = {
.probe = soc_camera_pdrv_probe,
.remove = __devexit_p(soc_camera_pdrv_remove), .remove = __devexit_p(soc_camera_pdrv_remove),
.driver = { .driver = {
.name = "soc-camera-pdrv", .name = "soc-camera-pdrv",
...@@ -1256,7 +1249,7 @@ static int __init soc_camera_init(void) ...@@ -1256,7 +1249,7 @@ static int __init soc_camera_init(void)
if (ret) if (ret)
goto edrvr; goto edrvr;
ret = platform_driver_register(&soc_camera_pdrv); ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe);
if (ret) if (ret)
goto epdr; goto epdr;
......
...@@ -21,35 +21,32 @@ ...@@ -21,35 +21,32 @@
#include <media/soc_camera_platform.h> #include <media/soc_camera_platform.h>
struct soc_camera_platform_priv { struct soc_camera_platform_priv {
struct soc_camera_platform_info *info;
struct soc_camera_device icd;
struct soc_camera_data_format format; struct soc_camera_data_format format;
}; };
static struct soc_camera_platform_info * static struct soc_camera_platform_info *
soc_camera_platform_get_info(struct soc_camera_device *icd) soc_camera_platform_get_info(struct soc_camera_device *icd)
{ {
struct soc_camera_platform_priv *priv; struct platform_device *pdev = to_platform_device(dev_get_drvdata(&icd->dev));
priv = container_of(icd, struct soc_camera_platform_priv, icd); return pdev->dev.platform_data;
return priv->info;
} }
static int soc_camera_platform_init(struct soc_camera_device *icd) static int soc_camera_platform_init(struct soc_camera_device *icd)
{ {
struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
if (p->power) if (icl->power)
p->power(1); icl->power(dev_get_drvdata(&icd->dev), 1);
return 0; return 0;
} }
static int soc_camera_platform_release(struct soc_camera_device *icd) static int soc_camera_platform_release(struct soc_camera_device *icd)
{ {
struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
if (p->power) if (icl->power)
p->power(0); icl->power(dev_get_drvdata(&icd->dev), 0);
return 0; return 0;
} }
...@@ -102,31 +99,29 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd, ...@@ -102,31 +99,29 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd,
return 0; return 0;
} }
static int soc_camera_platform_video_probe(struct soc_camera_device *icd) static int soc_camera_platform_video_probe(struct soc_camera_device *icd,
struct platform_device *pdev)
{ {
struct soc_camera_platform_priv *priv; struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev);
priv = container_of(icd, struct soc_camera_platform_priv, icd); struct soc_camera_platform_info *p = pdev->dev.platform_data;
int ret;
priv->format.name = priv->info->format_name; priv->format.name = p->format_name;
priv->format.depth = priv->info->format_depth; priv->format.depth = p->format_depth;
priv->format.fourcc = priv->info->format.pixelformat; priv->format.fourcc = p->format.pixelformat;
priv->format.colorspace = priv->info->format.colorspace; priv->format.colorspace = p->format.colorspace;
icd->formats = &priv->format; icd->formats = &priv->format;
icd->num_formats = 1; icd->num_formats = 1;
return soc_camera_video_start(icd); /* ..._video_start() does dev_set_drvdata(&icd->dev, &pdev->dev) */
} ret = soc_camera_video_start(icd, &pdev->dev);
static void soc_camera_platform_video_remove(struct soc_camera_device *icd)
{
soc_camera_video_stop(icd); soc_camera_video_stop(icd);
return ret;
} }
static struct soc_camera_ops soc_camera_platform_ops = { static struct soc_camera_ops soc_camera_platform_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.probe = soc_camera_platform_video_probe,
.remove = soc_camera_platform_video_remove,
.init = soc_camera_platform_init, .init = soc_camera_platform_init,
.release = soc_camera_platform_release, .release = soc_camera_platform_release,
.start_capture = soc_camera_platform_start_capture, .start_capture = soc_camera_platform_start_capture,
...@@ -141,11 +136,10 @@ static struct soc_camera_ops soc_camera_platform_ops = { ...@@ -141,11 +136,10 @@ static struct soc_camera_ops soc_camera_platform_ops = {
static int soc_camera_platform_probe(struct platform_device *pdev) static int soc_camera_platform_probe(struct platform_device *pdev)
{ {
struct soc_camera_platform_priv *priv; struct soc_camera_platform_priv *priv;
struct soc_camera_platform_info *p; struct soc_camera_platform_info *p = pdev->dev.platform_data;
struct soc_camera_device *icd; struct soc_camera_device *icd;
int ret; int ret;
p = pdev->dev.platform_data;
if (!p) if (!p)
return -EINVAL; return -EINVAL;
...@@ -153,31 +147,40 @@ static int soc_camera_platform_probe(struct platform_device *pdev) ...@@ -153,31 +147,40 @@ static int soc_camera_platform_probe(struct platform_device *pdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
priv->info = p;
platform_set_drvdata(pdev, priv); platform_set_drvdata(pdev, priv);
icd = &priv->icd; icd = to_soc_camera_dev(p->dev);
if (!icd)
goto enoicd;
icd->ops = &soc_camera_platform_ops; icd->ops = &soc_camera_platform_ops;
icd->control = &pdev->dev; dev_set_drvdata(&icd->dev, &pdev->dev);
icd->width_min = 0; icd->width_min = 0;
icd->width_max = priv->info->format.width; icd->width_max = p->format.width;
icd->height_min = 0; icd->height_min = 0;
icd->height_max = priv->info->format.height; icd->height_max = p->format.height;
icd->y_skip_top = 0; icd->y_skip_top = 0;
icd->iface = priv->info->iface;
ret = soc_camera_device_register(icd); ret = soc_camera_platform_video_probe(icd, pdev);
if (ret) if (ret) {
icd->ops = NULL;
kfree(priv); kfree(priv);
}
return ret; return ret;
enoicd:
kfree(priv);
return -EINVAL;
} }
static int soc_camera_platform_remove(struct platform_device *pdev) static int soc_camera_platform_remove(struct platform_device *pdev)
{ {
struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev);
struct soc_camera_platform_info *p = pdev->dev.platform_data;
struct soc_camera_device *icd = to_soc_camera_dev(p->dev);
soc_camera_device_unregister(&priv->icd); icd->ops = NULL;
kfree(priv); kfree(priv);
return 0; return 0;
} }
...@@ -206,3 +209,4 @@ module_exit(soc_camera_platform_module_exit); ...@@ -206,3 +209,4 @@ module_exit(soc_camera_platform_module_exit);
MODULE_DESCRIPTION("SoC Camera Platform driver"); MODULE_DESCRIPTION("SoC Camera Platform driver");
MODULE_AUTHOR("Magnus Damm"); MODULE_AUTHOR("Magnus Damm");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:soc_camera_platform");
...@@ -224,8 +224,6 @@ struct tw9910_hsync_ctrl { ...@@ -224,8 +224,6 @@ struct tw9910_hsync_ctrl {
struct tw9910_priv { struct tw9910_priv {
struct tw9910_video_info *info; struct tw9910_video_info *info;
struct i2c_client *client;
struct soc_camera_device icd;
const struct tw9910_scale_ctrl *scale; const struct tw9910_scale_ctrl *scale;
}; };
...@@ -511,35 +509,38 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height) ...@@ -511,35 +509,38 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height)
*/ */
static int tw9910_init(struct soc_camera_device *icd) static int tw9910_init(struct soc_camera_device *icd)
{ {
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret = 0; int ret = 0;
if (priv->info->link.power) { if (icl->power) {
ret = priv->info->link.power(&priv->client->dev, 1); ret = icl->power(&client->dev, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
if (priv->info->link.reset) if (icl->reset)
ret = priv->info->link.reset(&priv->client->dev); ret = icl->reset(&client->dev);
return ret; return ret;
} }
static int tw9910_release(struct soc_camera_device *icd) static int tw9910_release(struct soc_camera_device *icd)
{ {
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret = 0; int ret = 0;
if (priv->info->link.power) if (icl->power)
ret = priv->info->link.power(&priv->client->dev, 0); ret = icl->power(&client->dev, 0);
return ret; return ret;
} }
static int tw9910_start_capture(struct soc_camera_device *icd) static int tw9910_start_capture(struct soc_camera_device *icd)
{ {
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct tw9910_priv *priv = i2c_get_clientdata(client);
if (!priv->scale) { if (!priv->scale) {
dev_err(&icd->dev, "norm select error\n"); dev_err(&icd->dev, "norm select error\n");
...@@ -567,8 +568,9 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd, ...@@ -567,8 +568,9 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd,
static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
{ {
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct soc_camera_link *icl = priv->client->dev.platform_data; struct tw9910_priv *priv = i2c_get_clientdata(client);
struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
...@@ -610,13 +612,13 @@ static int tw9910_enum_input(struct soc_camera_device *icd, ...@@ -610,13 +612,13 @@ static int tw9910_enum_input(struct soc_camera_device *icd,
static int tw9910_get_register(struct soc_camera_device *icd, static int tw9910_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int ret; int ret;
if (reg->reg > 0xff) if (reg->reg > 0xff)
return -EINVAL; return -EINVAL;
ret = i2c_smbus_read_byte_data(priv->client, reg->reg); ret = i2c_smbus_read_byte_data(client, reg->reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -631,20 +633,21 @@ static int tw9910_get_register(struct soc_camera_device *icd, ...@@ -631,20 +633,21 @@ static int tw9910_get_register(struct soc_camera_device *icd,
static int tw9910_set_register(struct soc_camera_device *icd, static int tw9910_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->reg > 0xff || if (reg->reg > 0xff ||
reg->val > 0xff) reg->val > 0xff)
return -EINVAL; return -EINVAL;
return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
} }
#endif #endif
static int tw9910_set_crop(struct soc_camera_device *icd, static int tw9910_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect) struct v4l2_rect *rect)
{ {
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct tw9910_priv *priv = i2c_get_clientdata(client);
int ret = -EINVAL; int ret = -EINVAL;
u8 val; u8 val;
...@@ -658,8 +661,8 @@ static int tw9910_set_crop(struct soc_camera_device *icd, ...@@ -658,8 +661,8 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
/* /*
* reset hardware * reset hardware
*/ */
tw9910_reset(priv->client); tw9910_reset(client);
ret = tw9910_write_array(priv->client, tw9910_default_regs); ret = tw9910_write_array(client, tw9910_default_regs);
if (ret < 0) if (ret < 0)
goto tw9910_set_fmt_error; goto tw9910_set_fmt_error;
...@@ -670,7 +673,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, ...@@ -670,7 +673,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
if (SOCAM_DATAWIDTH_16 == priv->info->buswidth) if (SOCAM_DATAWIDTH_16 == priv->info->buswidth)
val = LEN; val = LEN;
ret = tw9910_mask_set(priv->client, OPFORM, LEN, val); ret = tw9910_mask_set(client, OPFORM, LEN, val);
if (ret < 0) if (ret < 0)
goto tw9910_set_fmt_error; goto tw9910_set_fmt_error;
...@@ -698,28 +701,28 @@ static int tw9910_set_crop(struct soc_camera_device *icd, ...@@ -698,28 +701,28 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
val = 0; val = 0;
} }
ret = tw9910_mask_set(priv->client, VBICNTL, RTSEL_MASK, val); ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val);
if (ret < 0) if (ret < 0)
goto tw9910_set_fmt_error; goto tw9910_set_fmt_error;
/* /*
* set scale * set scale
*/ */
ret = tw9910_set_scale(priv->client, priv->scale); ret = tw9910_set_scale(client, priv->scale);
if (ret < 0) if (ret < 0)
goto tw9910_set_fmt_error; goto tw9910_set_fmt_error;
/* /*
* set cropping * set cropping
*/ */
ret = tw9910_set_cropping(priv->client, &tw9910_cropping_ctrl); ret = tw9910_set_cropping(client, &tw9910_cropping_ctrl);
if (ret < 0) if (ret < 0)
goto tw9910_set_fmt_error; goto tw9910_set_fmt_error;
/* /*
* set hsync * set hsync
*/ */
ret = tw9910_set_hsync(priv->client, &tw9910_hsync_ctrl); ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl);
if (ret < 0) if (ret < 0)
goto tw9910_set_fmt_error; goto tw9910_set_fmt_error;
...@@ -727,7 +730,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, ...@@ -727,7 +730,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
tw9910_set_fmt_error: tw9910_set_fmt_error:
tw9910_reset(priv->client); tw9910_reset(client);
priv->scale = NULL; priv->scale = NULL;
return ret; return ret;
...@@ -784,9 +787,10 @@ static int tw9910_try_fmt(struct soc_camera_device *icd, ...@@ -784,9 +787,10 @@ static int tw9910_try_fmt(struct soc_camera_device *icd,
return 0; return 0;
} }
static int tw9910_video_probe(struct soc_camera_device *icd) static int tw9910_video_probe(struct soc_camera_device *icd,
struct i2c_client *client)
{ {
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); struct tw9910_priv *priv = i2c_get_clientdata(client);
s32 val; s32 val;
int ret; int ret;
...@@ -810,10 +814,18 @@ static int tw9910_video_probe(struct soc_camera_device *icd) ...@@ -810,10 +814,18 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
icd->formats = tw9910_color_fmt; icd->formats = tw9910_color_fmt;
icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); icd->num_formats = ARRAY_SIZE(tw9910_color_fmt);
/* Switch master clock on */
ret = soc_camera_video_start(icd, &client->dev);
if (ret)
return ret;
/* /*
* check and show Product ID * check and show Product ID
*/ */
val = i2c_smbus_read_byte_data(priv->client, ID); val = i2c_smbus_read_byte_data(client, ID);
soc_camera_video_stop(icd);
if (0x0B != GET_ID(val) || if (0x0B != GET_ID(val) ||
0x00 != GET_ReV(val)) { 0x00 != GET_ReV(val)) {
dev_err(&icd->dev, dev_err(&icd->dev,
...@@ -824,25 +836,14 @@ static int tw9910_video_probe(struct soc_camera_device *icd) ...@@ -824,25 +836,14 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
dev_info(&icd->dev, dev_info(&icd->dev,
"tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val)); "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val));
ret = soc_camera_video_start(icd);
if (ret < 0)
return ret;
icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL;
icd->vdev->current_norm = V4L2_STD_NTSC; icd->vdev->current_norm = V4L2_STD_NTSC;
return ret; return ret;
} }
static void tw9910_video_remove(struct soc_camera_device *icd)
{
soc_camera_video_stop(icd);
}
static struct soc_camera_ops tw9910_ops = { static struct soc_camera_ops tw9910_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.probe = tw9910_video_probe,
.remove = tw9910_video_remove,
.init = tw9910_init, .init = tw9910_init,
.release = tw9910_release, .release = tw9910_release,
.start_capture = tw9910_start_capture, .start_capture = tw9910_start_capture,
...@@ -871,18 +872,25 @@ static int tw9910_probe(struct i2c_client *client, ...@@ -871,18 +872,25 @@ static int tw9910_probe(struct i2c_client *client,
{ {
struct tw9910_priv *priv; struct tw9910_priv *priv;
struct tw9910_video_info *info; struct tw9910_video_info *info;
struct soc_camera_device *icd; struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter =
to_i2c_adapter(client->dev.parent);
struct soc_camera_link *icl;
const struct tw9910_scale_ctrl *scale; const struct tw9910_scale_ctrl *scale;
int i, ret; int i, ret;
if (!client->dev.platform_data) if (!icd) {
dev_err(&client->dev, "TW9910: missing soc-camera data!\n");
return -EINVAL; return -EINVAL;
}
info = container_of(client->dev.platform_data, icl = to_soc_camera_link(icd);
struct tw9910_video_info, link); if (!icl)
return -EINVAL;
if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent), info = container_of(icl, struct tw9910_video_info, link);
I2C_FUNC_SMBUS_BYTE_DATA)) {
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_err(&client->dev, dev_err(&client->dev,
"I2C-Adapter doesn't support " "I2C-Adapter doesn't support "
"I2C_FUNC_SMBUS_BYTE_DATA\n"); "I2C_FUNC_SMBUS_BYTE_DATA\n");
...@@ -894,12 +902,9 @@ static int tw9910_probe(struct i2c_client *client, ...@@ -894,12 +902,9 @@ static int tw9910_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
priv->info = info; priv->info = info;
priv->client = client;
i2c_set_clientdata(client, priv); i2c_set_clientdata(client, priv);
icd = &priv->icd;
icd->ops = &tw9910_ops; icd->ops = &tw9910_ops;
icd->control = &client->dev;
icd->iface = info->link.bus_id; icd->iface = info->link.bus_id;
/* /*
...@@ -925,9 +930,9 @@ static int tw9910_probe(struct i2c_client *client, ...@@ -925,9 +930,9 @@ static int tw9910_probe(struct i2c_client *client,
icd->height_min = min(scale[i].height, icd->height_min); icd->height_min = min(scale[i].height, icd->height_min);
} }
ret = soc_camera_device_register(icd); ret = tw9910_video_probe(icd, client);
if (ret) { if (ret) {
icd->ops = NULL;
i2c_set_clientdata(client, NULL); i2c_set_clientdata(client, NULL);
kfree(priv); kfree(priv);
} }
...@@ -938,8 +943,9 @@ static int tw9910_probe(struct i2c_client *client, ...@@ -938,8 +943,9 @@ static int tw9910_probe(struct i2c_client *client,
static int tw9910_remove(struct i2c_client *client) static int tw9910_remove(struct i2c_client *client)
{ {
struct tw9910_priv *priv = i2c_get_clientdata(client); struct tw9910_priv *priv = i2c_get_clientdata(client);
struct soc_camera_device *icd = client->dev.platform_data;
soc_camera_device_unregister(&priv->icd); icd->ops = NULL;
i2c_set_clientdata(client, NULL); i2c_set_clientdata(client, NULL);
kfree(priv); kfree(priv);
return 0; return 0;
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
struct soc_camera_device { struct soc_camera_device {
struct list_head list; struct list_head list;
struct device dev; struct device dev;
struct device *control;
unsigned short width; /* Current window */ unsigned short width; /* Current window */
unsigned short height; /* sizes */ unsigned short height; /* sizes */
unsigned short x_min; /* Camera capabilities */ unsigned short x_min; /* Camera capabilities */
...@@ -131,17 +130,25 @@ static inline struct soc_camera_host *to_soc_camera_host(struct device *dev) ...@@ -131,17 +130,25 @@ static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
return dev_get_drvdata(dev); return dev_get_drvdata(dev);
} }
extern int soc_camera_host_register(struct soc_camera_host *ici); static inline struct soc_camera_link *to_soc_camera_link(struct soc_camera_device *icd)
extern void soc_camera_host_unregister(struct soc_camera_host *ici); {
extern int soc_camera_device_register(struct soc_camera_device *icd); return icd->dev.platform_data;
extern void soc_camera_device_unregister(struct soc_camera_device *icd); }
extern int soc_camera_video_start(struct soc_camera_device *icd); static inline struct device *to_soc_camera_control(struct soc_camera_device *icd)
extern void soc_camera_video_stop(struct soc_camera_device *icd); {
return dev_get_drvdata(&icd->dev);
}
extern const struct soc_camera_data_format *soc_camera_format_by_fourcc( int soc_camera_host_register(struct soc_camera_host *ici);
void soc_camera_host_unregister(struct soc_camera_host *ici);
int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev);
void soc_camera_video_stop(struct soc_camera_device *icd);
const struct soc_camera_data_format *soc_camera_format_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc); struct soc_camera_device *icd, unsigned int fourcc);
extern const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc); struct soc_camera_device *icd, unsigned int fourcc);
struct soc_camera_data_format { struct soc_camera_data_format {
...@@ -170,8 +177,6 @@ struct soc_camera_format_xlate { ...@@ -170,8 +177,6 @@ struct soc_camera_format_xlate {
struct soc_camera_ops { struct soc_camera_ops {
struct module *owner; struct module *owner;
int (*probe)(struct soc_camera_device *);
void (*remove)(struct soc_camera_device *);
int (*suspend)(struct soc_camera_device *, pm_message_t state); int (*suspend)(struct soc_camera_device *, pm_message_t state);
int (*resume)(struct soc_camera_device *); int (*resume)(struct soc_camera_device *);
int (*init)(struct soc_camera_device *); int (*init)(struct soc_camera_device *);
......
...@@ -18,11 +18,10 @@ struct device; ...@@ -18,11 +18,10 @@ struct device;
struct soc_camera_platform_info { struct soc_camera_platform_info {
int iface; int iface;
char *format_name; const char *format_name;
unsigned long format_depth; unsigned long format_depth;
struct v4l2_pix_format format; struct v4l2_pix_format format;
unsigned long bus_param; unsigned long bus_param;
void (*power)(int);
struct device *dev; struct device *dev;
int (*set_capture)(struct soc_camera_platform_info *info, int enable); int (*set_capture)(struct soc_camera_platform_info *info, int enable);
struct soc_camera_link link; struct soc_camera_link link;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment