diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2009-08-25 10:28:22 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-18 23:18:27 -0400 |
commit | 40e2e0927003424c25807b575dd40da2b8685857 (patch) | |
tree | 917ca8fd5f7598194d264ec92a08b312d4932b90 /drivers/media | |
parent | bc1937b41d8253e2b554da385023a92189d38917 (diff) |
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: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/mt9m001.c | 114 | ||||
-rw-r--r-- | drivers/media/video/mt9m111.c | 154 | ||||
-rw-r--r-- | drivers/media/video/mt9t031.c | 116 | ||||
-rw-r--r-- | drivers/media/video/mt9v022.c | 119 | ||||
-rw-r--r-- | drivers/media/video/mx3_camera.c | 27 | ||||
-rw-r--r-- | drivers/media/video/ov772x.c | 157 | ||||
-rw-r--r-- | drivers/media/video/pxa_camera.c | 29 | ||||
-rw-r--r-- | drivers/media/video/sh_mobile_ceu_camera.c | 13 | ||||
-rw-r--r-- | drivers/media/video/soc_camera.c | 431 | ||||
-rw-r--r-- | drivers/media/video/soc_camera_platform.c | 76 | ||||
-rw-r--r-- | drivers/media/video/tw9910.c | 110 |
11 files changed, 682 insertions, 664 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 4d794b42d6cd..1e4f269fc08b 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c | |||
@@ -69,8 +69,6 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | struct mt9m001 { | 71 | struct mt9m001 { |
72 | struct i2c_client *client; | ||
73 | struct soc_camera_device icd; | ||
74 | int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ | 72 | int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ |
75 | unsigned char autoexposure; | 73 | unsigned char autoexposure; |
76 | }; | 74 | }; |
@@ -111,11 +109,11 @@ static int reg_clear(struct i2c_client *client, const u8 reg, | |||
111 | 109 | ||
112 | static int mt9m001_init(struct soc_camera_device *icd) | 110 | static int mt9m001_init(struct soc_camera_device *icd) |
113 | { | 111 | { |
114 | struct i2c_client *client = to_i2c_client(icd->control); | 112 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
115 | struct soc_camera_link *icl = client->dev.platform_data; | 113 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
116 | int ret; | 114 | int ret; |
117 | 115 | ||
118 | dev_dbg(icd->vdev->parent, "%s\n", __func__); | 116 | dev_dbg(&icd->dev, "%s\n", __func__); |
119 | 117 | ||
120 | if (icl->power) { | 118 | if (icl->power) { |
121 | ret = icl->power(&client->dev, 1); | 119 | ret = icl->power(&client->dev, 1); |
@@ -147,8 +145,8 @@ static int mt9m001_init(struct soc_camera_device *icd) | |||
147 | 145 | ||
148 | static int mt9m001_release(struct soc_camera_device *icd) | 146 | static int mt9m001_release(struct soc_camera_device *icd) |
149 | { | 147 | { |
150 | struct i2c_client *client = to_i2c_client(icd->control); | 148 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
151 | struct soc_camera_link *icl = client->dev.platform_data; | 149 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
152 | 150 | ||
153 | /* Disable the chip */ | 151 | /* Disable the chip */ |
154 | reg_write(client, MT9M001_OUTPUT_CONTROL, 0); | 152 | reg_write(client, MT9M001_OUTPUT_CONTROL, 0); |
@@ -161,7 +159,7 @@ static int mt9m001_release(struct soc_camera_device *icd) | |||
161 | 159 | ||
162 | static int mt9m001_start_capture(struct soc_camera_device *icd) | 160 | static int mt9m001_start_capture(struct soc_camera_device *icd) |
163 | { | 161 | { |
164 | struct i2c_client *client = to_i2c_client(icd->control); | 162 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
165 | 163 | ||
166 | /* Switch to master "normal" mode */ | 164 | /* Switch to master "normal" mode */ |
167 | if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0) | 165 | if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0) |
@@ -171,7 +169,7 @@ static int mt9m001_start_capture(struct soc_camera_device *icd) | |||
171 | 169 | ||
172 | static int mt9m001_stop_capture(struct soc_camera_device *icd) | 170 | static int mt9m001_stop_capture(struct soc_camera_device *icd) |
173 | { | 171 | { |
174 | struct i2c_client *client = to_i2c_client(icd->control); | 172 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
175 | 173 | ||
176 | /* Stop sensor readout */ | 174 | /* Stop sensor readout */ |
177 | if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0) | 175 | if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0) |
@@ -182,8 +180,7 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd) | |||
182 | static int mt9m001_set_bus_param(struct soc_camera_device *icd, | 180 | static int mt9m001_set_bus_param(struct soc_camera_device *icd, |
183 | unsigned long flags) | 181 | unsigned long flags) |
184 | { | 182 | { |
185 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | 183 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
186 | struct soc_camera_link *icl = mt9m001->client->dev.platform_data; | ||
187 | unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK; | 184 | unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK; |
188 | 185 | ||
189 | /* Only one width bit may be set */ | 186 | /* Only one width bit may be set */ |
@@ -205,8 +202,7 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd, | |||
205 | 202 | ||
206 | static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) | 203 | static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) |
207 | { | 204 | { |
208 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | 205 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
209 | struct soc_camera_link *icl = mt9m001->client->dev.platform_data; | ||
210 | /* MT9M001 has all capture_format parameters fixed */ | 206 | /* MT9M001 has all capture_format parameters fixed */ |
211 | unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING | | 207 | unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING | |
212 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | | 208 | 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 | static int mt9m001_set_crop(struct soc_camera_device *icd, | 219 | static int mt9m001_set_crop(struct soc_camera_device *icd, |
224 | struct v4l2_rect *rect) | 220 | struct v4l2_rect *rect) |
225 | { | 221 | { |
226 | struct i2c_client *client = to_i2c_client(icd->control); | 222 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
227 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | 223 | struct mt9m001 *mt9m001 = i2c_get_clientdata(client); |
228 | int ret; | 224 | int ret; |
229 | const u16 hblank = 9, vblank = 25; | 225 | const u16 hblank = 9, vblank = 25; |
230 | 226 | ||
@@ -290,12 +286,13 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd, | |||
290 | static int mt9m001_get_chip_id(struct soc_camera_device *icd, | 286 | static int mt9m001_get_chip_id(struct soc_camera_device *icd, |
291 | struct v4l2_dbg_chip_ident *id) | 287 | struct v4l2_dbg_chip_ident *id) |
292 | { | 288 | { |
293 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | 289 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
290 | struct mt9m001 *mt9m001 = i2c_get_clientdata(client); | ||
294 | 291 | ||
295 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | 292 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) |
296 | return -EINVAL; | 293 | return -EINVAL; |
297 | 294 | ||
298 | if (id->match.addr != mt9m001->client->addr) | 295 | if (id->match.addr != client->addr) |
299 | return -ENODEV; | 296 | return -ENODEV; |
300 | 297 | ||
301 | id->ident = mt9m001->model; | 298 | id->ident = mt9m001->model; |
@@ -308,7 +305,7 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd, | |||
308 | static int mt9m001_get_register(struct soc_camera_device *icd, | 305 | static int mt9m001_get_register(struct soc_camera_device *icd, |
309 | struct v4l2_dbg_register *reg) | 306 | struct v4l2_dbg_register *reg) |
310 | { | 307 | { |
311 | struct i2c_client *client = to_i2c_client(icd->control); | 308 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
312 | 309 | ||
313 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) | 310 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) |
314 | return -EINVAL; | 311 | return -EINVAL; |
@@ -328,7 +325,7 @@ static int mt9m001_get_register(struct soc_camera_device *icd, | |||
328 | static int mt9m001_set_register(struct soc_camera_device *icd, | 325 | static int mt9m001_set_register(struct soc_camera_device *icd, |
329 | struct v4l2_dbg_register *reg) | 326 | struct v4l2_dbg_register *reg) |
330 | { | 327 | { |
331 | struct i2c_client *client = to_i2c_client(icd->control); | 328 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
332 | 329 | ||
333 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) | 330 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) |
334 | return -EINVAL; | 331 | return -EINVAL; |
@@ -381,15 +378,11 @@ static const struct v4l2_queryctrl mt9m001_controls[] = { | |||
381 | } | 378 | } |
382 | }; | 379 | }; |
383 | 380 | ||
384 | static int mt9m001_video_probe(struct soc_camera_device *); | ||
385 | static void mt9m001_video_remove(struct soc_camera_device *); | ||
386 | static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *); | 381 | static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *); |
387 | static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *); | 382 | static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *); |
388 | 383 | ||
389 | static struct soc_camera_ops mt9m001_ops = { | 384 | static struct soc_camera_ops mt9m001_ops = { |
390 | .owner = THIS_MODULE, | 385 | .owner = THIS_MODULE, |
391 | .probe = mt9m001_video_probe, | ||
392 | .remove = mt9m001_video_remove, | ||
393 | .init = mt9m001_init, | 386 | .init = mt9m001_init, |
394 | .release = mt9m001_release, | 387 | .release = mt9m001_release, |
395 | .start_capture = mt9m001_start_capture, | 388 | .start_capture = mt9m001_start_capture, |
@@ -412,8 +405,8 @@ static struct soc_camera_ops mt9m001_ops = { | |||
412 | 405 | ||
413 | static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) | 406 | static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) |
414 | { | 407 | { |
415 | struct i2c_client *client = to_i2c_client(icd->control); | 408 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
416 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | 409 | struct mt9m001 *mt9m001 = i2c_get_clientdata(client); |
417 | int data; | 410 | int data; |
418 | 411 | ||
419 | switch (ctrl->id) { | 412 | switch (ctrl->id) { |
@@ -432,8 +425,8 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro | |||
432 | 425 | ||
433 | static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) | 426 | static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) |
434 | { | 427 | { |
435 | struct i2c_client *client = to_i2c_client(icd->control); | 428 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
436 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | 429 | struct mt9m001 *mt9m001 = i2c_get_clientdata(client); |
437 | const struct v4l2_queryctrl *qctrl; | 430 | const struct v4l2_queryctrl *qctrl; |
438 | int data; | 431 | int data; |
439 | 432 | ||
@@ -525,11 +518,11 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro | |||
525 | 518 | ||
526 | /* Interface active, can use i2c. If it fails, it can indeed mean, that | 519 | /* Interface active, can use i2c. If it fails, it can indeed mean, that |
527 | * this wasn't our capture interface, so, we wait for the right one */ | 520 | * this wasn't our capture interface, so, we wait for the right one */ |
528 | static int mt9m001_video_probe(struct soc_camera_device *icd) | 521 | static int mt9m001_video_probe(struct soc_camera_device *icd, |
522 | struct i2c_client *client) | ||
529 | { | 523 | { |
530 | struct i2c_client *client = to_i2c_client(icd->control); | 524 | struct mt9m001 *mt9m001 = i2c_get_clientdata(client); |
531 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | 525 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
532 | struct soc_camera_link *icl = client->dev.platform_data; | ||
533 | s32 data; | 526 | s32 data; |
534 | int ret; | 527 | int ret; |
535 | unsigned long flags; | 528 | unsigned long flags; |
@@ -540,6 +533,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) | |||
540 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) | 533 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) |
541 | return -ENODEV; | 534 | return -ENODEV; |
542 | 535 | ||
536 | /* Switch master clock on */ | ||
537 | ret = soc_camera_video_start(icd, &client->dev); | ||
538 | if (ret) | ||
539 | return ret; | ||
540 | |||
543 | /* Enable the chip */ | 541 | /* Enable the chip */ |
544 | data = reg_write(client, MT9M001_CHIP_ENABLE, 1); | 542 | data = reg_write(client, MT9M001_CHIP_ENABLE, 1); |
545 | dev_dbg(&icd->dev, "write: %d\n", data); | 543 | dev_dbg(&icd->dev, "write: %d\n", data); |
@@ -547,6 +545,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) | |||
547 | /* Read out the chip version register */ | 545 | /* Read out the chip version register */ |
548 | data = reg_read(client, MT9M001_CHIP_VERSION); | 546 | data = reg_read(client, MT9M001_CHIP_VERSION); |
549 | 547 | ||
548 | soc_camera_video_stop(icd); | ||
549 | |||
550 | /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ | 550 | /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ |
551 | switch (data) { | 551 | switch (data) { |
552 | case 0x8411: | 552 | case 0x8411: |
@@ -559,10 +559,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) | |||
559 | icd->formats = mt9m001_monochrome_formats; | 559 | icd->formats = mt9m001_monochrome_formats; |
560 | break; | 560 | break; |
561 | default: | 561 | default: |
562 | ret = -ENODEV; | ||
563 | dev_err(&icd->dev, | 562 | dev_err(&icd->dev, |
564 | "No MT9M001 chip detected, register read %x\n", data); | 563 | "No MT9M001 chip detected, register read %x\n", data); |
565 | goto ei2c; | 564 | return -ENODEV; |
566 | } | 565 | } |
567 | 566 | ||
568 | icd->num_formats = 0; | 567 | icd->num_formats = 0; |
@@ -588,26 +587,16 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) | |||
588 | dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, | 587 | dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, |
589 | data == 0x8431 ? "C12STM" : "C12ST"); | 588 | data == 0x8431 ? "C12STM" : "C12ST"); |
590 | 589 | ||
591 | /* Now that we know the model, we can start video */ | ||
592 | ret = soc_camera_video_start(icd); | ||
593 | if (ret) | ||
594 | goto eisis; | ||
595 | |||
596 | return 0; | 590 | return 0; |
597 | |||
598 | eisis: | ||
599 | ei2c: | ||
600 | return ret; | ||
601 | } | 591 | } |
602 | 592 | ||
603 | static void mt9m001_video_remove(struct soc_camera_device *icd) | 593 | static void mt9m001_video_remove(struct soc_camera_device *icd) |
604 | { | 594 | { |
605 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | 595 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
606 | struct soc_camera_link *icl = mt9m001->client->dev.platform_data; | 596 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
607 | 597 | ||
608 | dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, | 598 | dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr, |
609 | icd->dev.parent, icd->vdev); | 599 | icd->dev.parent, icd->vdev); |
610 | soc_camera_video_stop(icd); | ||
611 | if (icl->free_bus) | 600 | if (icl->free_bus) |
612 | icl->free_bus(icl); | 601 | icl->free_bus(icl); |
613 | } | 602 | } |
@@ -616,11 +605,17 @@ static int mt9m001_probe(struct i2c_client *client, | |||
616 | const struct i2c_device_id *did) | 605 | const struct i2c_device_id *did) |
617 | { | 606 | { |
618 | struct mt9m001 *mt9m001; | 607 | struct mt9m001 *mt9m001; |
619 | struct soc_camera_device *icd; | 608 | struct soc_camera_device *icd = client->dev.platform_data; |
620 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 609 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
621 | struct soc_camera_link *icl = client->dev.platform_data; | 610 | struct soc_camera_link *icl; |
622 | int ret; | 611 | int ret; |
623 | 612 | ||
613 | if (!icd) { | ||
614 | dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); | ||
615 | return -EINVAL; | ||
616 | } | ||
617 | |||
618 | icl = to_soc_camera_link(icd); | ||
624 | if (!icl) { | 619 | if (!icl) { |
625 | dev_err(&client->dev, "MT9M001 driver needs platform data\n"); | 620 | dev_err(&client->dev, "MT9M001 driver needs platform data\n"); |
626 | return -EINVAL; | 621 | return -EINVAL; |
@@ -636,13 +631,10 @@ static int mt9m001_probe(struct i2c_client *client, | |||
636 | if (!mt9m001) | 631 | if (!mt9m001) |
637 | return -ENOMEM; | 632 | return -ENOMEM; |
638 | 633 | ||
639 | mt9m001->client = client; | ||
640 | i2c_set_clientdata(client, mt9m001); | 634 | i2c_set_clientdata(client, mt9m001); |
641 | 635 | ||
642 | /* Second stage probe - when a capture adapter is there */ | 636 | /* Second stage probe - when a capture adapter is there */ |
643 | icd = &mt9m001->icd; | ||
644 | icd->ops = &mt9m001_ops; | 637 | icd->ops = &mt9m001_ops; |
645 | icd->control = &client->dev; | ||
646 | icd->x_min = 20; | 638 | icd->x_min = 20; |
647 | icd->y_min = 12; | 639 | icd->y_min = 12; |
648 | icd->x_current = 20; | 640 | icd->x_current = 20; |
@@ -652,27 +644,29 @@ static int mt9m001_probe(struct i2c_client *client, | |||
652 | icd->height_min = 32; | 644 | icd->height_min = 32; |
653 | icd->height_max = 1024; | 645 | icd->height_max = 1024; |
654 | icd->y_skip_top = 1; | 646 | icd->y_skip_top = 1; |
655 | icd->iface = icl->bus_id; | ||
656 | /* Simulated autoexposure. If enabled, we calculate shutter width | 647 | /* Simulated autoexposure. If enabled, we calculate shutter width |
657 | * ourselves in the driver based on vertical blanking and frame width */ | 648 | * ourselves in the driver based on vertical blanking and frame width */ |
658 | mt9m001->autoexposure = 1; | 649 | mt9m001->autoexposure = 1; |
659 | 650 | ||
660 | ret = soc_camera_device_register(icd); | 651 | ret = mt9m001_video_probe(icd, client); |
661 | if (ret) | 652 | if (ret) { |
662 | goto eisdr; | 653 | icd->ops = NULL; |
663 | 654 | i2c_set_clientdata(client, NULL); | |
664 | return 0; | 655 | kfree(mt9m001); |
656 | } | ||
665 | 657 | ||
666 | eisdr: | ||
667 | kfree(mt9m001); | ||
668 | return ret; | 658 | return ret; |
669 | } | 659 | } |
670 | 660 | ||
671 | static int mt9m001_remove(struct i2c_client *client) | 661 | static int mt9m001_remove(struct i2c_client *client) |
672 | { | 662 | { |
673 | struct mt9m001 *mt9m001 = i2c_get_clientdata(client); | 663 | struct mt9m001 *mt9m001 = i2c_get_clientdata(client); |
664 | struct soc_camera_device *icd = client->dev.platform_data; | ||
674 | 665 | ||
675 | soc_camera_device_unregister(&mt9m001->icd); | 666 | icd->ops = NULL; |
667 | mt9m001_video_remove(icd); | ||
668 | i2c_set_clientdata(client, NULL); | ||
669 | client->driver = NULL; | ||
676 | kfree(mt9m001); | 670 | kfree(mt9m001); |
677 | 671 | ||
678 | return 0; | 672 | return 0; |
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index fc5e2de03766..95c2f089605f 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c | |||
@@ -148,8 +148,6 @@ enum mt9m111_context { | |||
148 | }; | 148 | }; |
149 | 149 | ||
150 | struct mt9m111 { | 150 | struct mt9m111 { |
151 | struct i2c_client *client; | ||
152 | struct soc_camera_device icd; | ||
153 | int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ | 151 | int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ |
154 | enum mt9m111_context context; | 152 | enum mt9m111_context context; |
155 | struct v4l2_rect rect; | 153 | struct v4l2_rect rect; |
@@ -203,7 +201,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg, | |||
203 | 201 | ||
204 | ret = reg_page_map_set(client, reg); | 202 | ret = reg_page_map_set(client, reg); |
205 | if (!ret) | 203 | if (!ret) |
206 | ret = i2c_smbus_write_word_data(client, (reg & 0xff), | 204 | ret = i2c_smbus_write_word_data(client, reg & 0xff, |
207 | swab16(data)); | 205 | swab16(data)); |
208 | dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); | 206 | dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); |
209 | return ret; | 207 | return ret; |
@@ -232,7 +230,7 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg, | |||
232 | static int mt9m111_set_context(struct soc_camera_device *icd, | 230 | static int mt9m111_set_context(struct soc_camera_device *icd, |
233 | enum mt9m111_context ctxt) | 231 | enum mt9m111_context ctxt) |
234 | { | 232 | { |
235 | struct i2c_client *client = to_i2c_client(icd->control); | 233 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
236 | int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | 234 | int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B |
237 | | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | 235 | | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B |
238 | | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B | 236 | | 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 | static int mt9m111_setup_rect(struct soc_camera_device *icd, | 247 | static int mt9m111_setup_rect(struct soc_camera_device *icd, |
250 | struct v4l2_rect *rect) | 248 | struct v4l2_rect *rect) |
251 | { | 249 | { |
252 | struct i2c_client *client = to_i2c_client(icd->control); | 250 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
253 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 251 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); |
254 | int ret, is_raw_format; | 252 | int ret, is_raw_format; |
255 | int width = rect->width; | 253 | int width = rect->width; |
256 | int height = rect->height; | 254 | int height = rect->height; |
@@ -294,7 +292,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd, | |||
294 | 292 | ||
295 | static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) | 293 | static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) |
296 | { | 294 | { |
297 | struct i2c_client *client = to_i2c_client(icd->control); | 295 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
298 | int ret; | 296 | int ret; |
299 | 297 | ||
300 | ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); | 298 | ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); |
@@ -315,7 +313,8 @@ static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) | |||
315 | 313 | ||
316 | static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) | 314 | static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) |
317 | { | 315 | { |
318 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 316 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
317 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
319 | int val = 0; | 318 | int val = 0; |
320 | 319 | ||
321 | if (mt9m111->swap_rgb_red_blue) | 320 | if (mt9m111->swap_rgb_red_blue) |
@@ -329,7 +328,8 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) | |||
329 | 328 | ||
330 | static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) | 329 | static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) |
331 | { | 330 | { |
332 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 331 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
332 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
333 | int val = 0; | 333 | int val = 0; |
334 | 334 | ||
335 | if (mt9m111->swap_rgb_red_blue) | 335 | if (mt9m111->swap_rgb_red_blue) |
@@ -343,7 +343,8 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) | |||
343 | 343 | ||
344 | static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) | 344 | static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) |
345 | { | 345 | { |
346 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 346 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
347 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
347 | int val = 0; | 348 | int val = 0; |
348 | 349 | ||
349 | if (mt9m111->swap_yuv_cb_cr) | 350 | if (mt9m111->swap_yuv_cb_cr) |
@@ -356,9 +357,9 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) | |||
356 | 357 | ||
357 | static int mt9m111_enable(struct soc_camera_device *icd) | 358 | static int mt9m111_enable(struct soc_camera_device *icd) |
358 | { | 359 | { |
359 | struct i2c_client *client = to_i2c_client(icd->control); | 360 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
360 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 361 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
361 | struct soc_camera_link *icl = client->dev.platform_data; | 362 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); |
362 | int ret; | 363 | int ret; |
363 | 364 | ||
364 | if (icl->power) { | 365 | if (icl->power) { |
@@ -378,9 +379,9 @@ static int mt9m111_enable(struct soc_camera_device *icd) | |||
378 | 379 | ||
379 | static int mt9m111_disable(struct soc_camera_device *icd) | 380 | static int mt9m111_disable(struct soc_camera_device *icd) |
380 | { | 381 | { |
381 | struct i2c_client *client = to_i2c_client(icd->control); | 382 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
382 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 383 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
383 | struct soc_camera_link *icl = client->dev.platform_data; | 384 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); |
384 | int ret; | 385 | int ret; |
385 | 386 | ||
386 | ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); | 387 | ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); |
@@ -395,8 +396,8 @@ static int mt9m111_disable(struct soc_camera_device *icd) | |||
395 | 396 | ||
396 | static int mt9m111_reset(struct soc_camera_device *icd) | 397 | static int mt9m111_reset(struct soc_camera_device *icd) |
397 | { | 398 | { |
398 | struct i2c_client *client = to_i2c_client(icd->control); | 399 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
399 | struct soc_camera_link *icl = client->dev.platform_data; | 400 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
400 | int ret; | 401 | int ret; |
401 | 402 | ||
402 | ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); | 403 | ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); |
@@ -424,8 +425,7 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd) | |||
424 | 425 | ||
425 | static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) | 426 | static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) |
426 | { | 427 | { |
427 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 428 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
428 | struct soc_camera_link *icl = mt9m111->client->dev.platform_data; | ||
429 | unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | | 429 | unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | |
430 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | | 430 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | |
431 | SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; | 431 | 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 | static int mt9m111_set_crop(struct soc_camera_device *icd, | 441 | static int mt9m111_set_crop(struct soc_camera_device *icd, |
442 | struct v4l2_rect *rect) | 442 | struct v4l2_rect *rect) |
443 | { | 443 | { |
444 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 444 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
445 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
445 | int ret; | 446 | int ret; |
446 | 447 | ||
447 | dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", | 448 | 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 | 457 | ||
457 | static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) | 458 | static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) |
458 | { | 459 | { |
459 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 460 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
461 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
460 | int ret; | 462 | int ret; |
461 | 463 | ||
462 | switch (pixfmt) { | 464 | switch (pixfmt) { |
@@ -506,7 +508,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) | |||
506 | static int mt9m111_set_fmt(struct soc_camera_device *icd, | 508 | static int mt9m111_set_fmt(struct soc_camera_device *icd, |
507 | struct v4l2_format *f) | 509 | struct v4l2_format *f) |
508 | { | 510 | { |
509 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 511 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
512 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
510 | struct v4l2_pix_format *pix = &f->fmt.pix; | 513 | struct v4l2_pix_format *pix = &f->fmt.pix; |
511 | struct v4l2_rect rect = { | 514 | struct v4l2_rect rect = { |
512 | .left = mt9m111->rect.left, | 515 | .left = mt9m111->rect.left, |
@@ -544,12 +547,13 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd, | |||
544 | static int mt9m111_get_chip_id(struct soc_camera_device *icd, | 547 | static int mt9m111_get_chip_id(struct soc_camera_device *icd, |
545 | struct v4l2_dbg_chip_ident *id) | 548 | struct v4l2_dbg_chip_ident *id) |
546 | { | 549 | { |
547 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 550 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
551 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
548 | 552 | ||
549 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | 553 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) |
550 | return -EINVAL; | 554 | return -EINVAL; |
551 | 555 | ||
552 | if (id->match.addr != mt9m111->client->addr) | 556 | if (id->match.addr != client->addr) |
553 | return -ENODEV; | 557 | return -ENODEV; |
554 | 558 | ||
555 | id->ident = mt9m111->model; | 559 | id->ident = mt9m111->model; |
@@ -562,8 +566,8 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd, | |||
562 | static int mt9m111_get_register(struct soc_camera_device *icd, | 566 | static int mt9m111_get_register(struct soc_camera_device *icd, |
563 | struct v4l2_dbg_register *reg) | 567 | struct v4l2_dbg_register *reg) |
564 | { | 568 | { |
569 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
565 | int val; | 570 | int val; |
566 | struct i2c_client *client = to_i2c_client(icd->control); | ||
567 | 571 | ||
568 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) | 572 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) |
569 | return -EINVAL; | 573 | return -EINVAL; |
@@ -583,7 +587,7 @@ static int mt9m111_get_register(struct soc_camera_device *icd, | |||
583 | static int mt9m111_set_register(struct soc_camera_device *icd, | 587 | static int mt9m111_set_register(struct soc_camera_device *icd, |
584 | struct v4l2_dbg_register *reg) | 588 | struct v4l2_dbg_register *reg) |
585 | { | 589 | { |
586 | struct i2c_client *client = to_i2c_client(icd->control); | 590 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
587 | 591 | ||
588 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) | 592 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) |
589 | return -EINVAL; | 593 | return -EINVAL; |
@@ -635,8 +639,6 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { | |||
635 | } | 639 | } |
636 | }; | 640 | }; |
637 | 641 | ||
638 | static int mt9m111_video_probe(struct soc_camera_device *); | ||
639 | static void mt9m111_video_remove(struct soc_camera_device *); | ||
640 | static int mt9m111_get_control(struct soc_camera_device *, | 642 | static int mt9m111_get_control(struct soc_camera_device *, |
641 | struct v4l2_control *); | 643 | struct v4l2_control *); |
642 | static int mt9m111_set_control(struct soc_camera_device *, | 644 | static int mt9m111_set_control(struct soc_camera_device *, |
@@ -647,8 +649,6 @@ static int mt9m111_release(struct soc_camera_device *icd); | |||
647 | 649 | ||
648 | static struct soc_camera_ops mt9m111_ops = { | 650 | static struct soc_camera_ops mt9m111_ops = { |
649 | .owner = THIS_MODULE, | 651 | .owner = THIS_MODULE, |
650 | .probe = mt9m111_video_probe, | ||
651 | .remove = mt9m111_video_remove, | ||
652 | .init = mt9m111_init, | 652 | .init = mt9m111_init, |
653 | .resume = mt9m111_resume, | 653 | .resume = mt9m111_resume, |
654 | .release = mt9m111_release, | 654 | .release = mt9m111_release, |
@@ -672,8 +672,8 @@ static struct soc_camera_ops mt9m111_ops = { | |||
672 | 672 | ||
673 | static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) | 673 | static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) |
674 | { | 674 | { |
675 | struct i2c_client *client = to_i2c_client(icd->control); | 675 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
676 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 676 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); |
677 | int ret; | 677 | int ret; |
678 | 678 | ||
679 | if (mt9m111->context == HIGHPOWER) { | 679 | if (mt9m111->context == HIGHPOWER) { |
@@ -693,7 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) | |||
693 | 693 | ||
694 | static int mt9m111_get_global_gain(struct soc_camera_device *icd) | 694 | static int mt9m111_get_global_gain(struct soc_camera_device *icd) |
695 | { | 695 | { |
696 | struct i2c_client *client = to_i2c_client(icd->control); | 696 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
697 | int data; | 697 | int data; |
698 | 698 | ||
699 | data = reg_read(GLOBAL_GAIN); | 699 | data = reg_read(GLOBAL_GAIN); |
@@ -705,7 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd) | |||
705 | 705 | ||
706 | static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) | 706 | static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) |
707 | { | 707 | { |
708 | struct i2c_client *client = to_i2c_client(icd->control); | 708 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
709 | u16 val; | 709 | u16 val; |
710 | 710 | ||
711 | if (gain > 63 * 2 * 2) | 711 | if (gain > 63 * 2 * 2) |
@@ -724,8 +724,8 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) | |||
724 | 724 | ||
725 | static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) | 725 | static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) |
726 | { | 726 | { |
727 | struct i2c_client *client = to_i2c_client(icd->control); | 727 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
728 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 728 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); |
729 | int ret; | 729 | int ret; |
730 | 730 | ||
731 | if (on) | 731 | if (on) |
@@ -741,8 +741,8 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) | |||
741 | 741 | ||
742 | static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) | 742 | static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) |
743 | { | 743 | { |
744 | struct i2c_client *client = to_i2c_client(icd->control); | 744 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
745 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 745 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); |
746 | int ret; | 746 | int ret; |
747 | 747 | ||
748 | if (on) | 748 | if (on) |
@@ -759,8 +759,8 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) | |||
759 | static int mt9m111_get_control(struct soc_camera_device *icd, | 759 | static int mt9m111_get_control(struct soc_camera_device *icd, |
760 | struct v4l2_control *ctrl) | 760 | struct v4l2_control *ctrl) |
761 | { | 761 | { |
762 | struct i2c_client *client = to_i2c_client(icd->control); | 762 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
763 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 763 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); |
764 | int data; | 764 | int data; |
765 | 765 | ||
766 | switch (ctrl->id) { | 766 | switch (ctrl->id) { |
@@ -803,7 +803,8 @@ static int mt9m111_get_control(struct soc_camera_device *icd, | |||
803 | static int mt9m111_set_control(struct soc_camera_device *icd, | 803 | static int mt9m111_set_control(struct soc_camera_device *icd, |
804 | struct v4l2_control *ctrl) | 804 | struct v4l2_control *ctrl) |
805 | { | 805 | { |
806 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 806 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
807 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
807 | const struct v4l2_queryctrl *qctrl; | 808 | const struct v4l2_queryctrl *qctrl; |
808 | int ret; | 809 | int ret; |
809 | 810 | ||
@@ -841,7 +842,8 @@ static int mt9m111_set_control(struct soc_camera_device *icd, | |||
841 | 842 | ||
842 | static int mt9m111_restore_state(struct soc_camera_device *icd) | 843 | static int mt9m111_restore_state(struct soc_camera_device *icd) |
843 | { | 844 | { |
844 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 845 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
846 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
845 | 847 | ||
846 | mt9m111_set_context(icd, mt9m111->context); | 848 | mt9m111_set_context(icd, mt9m111->context); |
847 | mt9m111_set_pixfmt(icd, mt9m111->pixfmt); | 849 | mt9m111_set_pixfmt(icd, mt9m111->pixfmt); |
@@ -856,7 +858,8 @@ static int mt9m111_restore_state(struct soc_camera_device *icd) | |||
856 | 858 | ||
857 | static int mt9m111_resume(struct soc_camera_device *icd) | 859 | static int mt9m111_resume(struct soc_camera_device *icd) |
858 | { | 860 | { |
859 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 861 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
862 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
860 | int ret = 0; | 863 | int ret = 0; |
861 | 864 | ||
862 | if (mt9m111->powered) { | 865 | if (mt9m111->powered) { |
@@ -871,7 +874,8 @@ static int mt9m111_resume(struct soc_camera_device *icd) | |||
871 | 874 | ||
872 | static int mt9m111_init(struct soc_camera_device *icd) | 875 | static int mt9m111_init(struct soc_camera_device *icd) |
873 | { | 876 | { |
874 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | 877 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
878 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
875 | int ret; | 879 | int ret; |
876 | 880 | ||
877 | mt9m111->context = HIGHPOWER; | 881 | mt9m111->context = HIGHPOWER; |
@@ -902,10 +906,10 @@ static int mt9m111_release(struct soc_camera_device *icd) | |||
902 | * Interface active, can use i2c. If it fails, it can indeed mean, that | 906 | * Interface active, can use i2c. If it fails, it can indeed mean, that |
903 | * this wasn't our capture interface, so, we wait for the right one | 907 | * this wasn't our capture interface, so, we wait for the right one |
904 | */ | 908 | */ |
905 | static int mt9m111_video_probe(struct soc_camera_device *icd) | 909 | static int mt9m111_video_probe(struct soc_camera_device *icd, |
910 | struct i2c_client *client) | ||
906 | { | 911 | { |
907 | struct i2c_client *client = to_i2c_client(icd->control); | 912 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); |
908 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
909 | s32 data; | 913 | s32 data; |
910 | int ret; | 914 | int ret; |
911 | 915 | ||
@@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd) | |||
917 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) | 921 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) |
918 | return -ENODEV; | 922 | return -ENODEV; |
919 | 923 | ||
924 | /* Switch master clock on */ | ||
925 | ret = soc_camera_video_start(icd, &client->dev); | ||
926 | if (ret) | ||
927 | goto evstart; | ||
928 | |||
920 | ret = mt9m111_enable(icd); | 929 | ret = mt9m111_enable(icd); |
921 | if (ret) | 930 | if (ret) |
922 | goto ei2c; | 931 | goto ei2c; |
@@ -945,40 +954,33 @@ static int mt9m111_video_probe(struct soc_camera_device *icd) | |||
945 | 954 | ||
946 | dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data); | 955 | dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data); |
947 | 956 | ||
948 | ret = soc_camera_video_start(icd); | ||
949 | if (ret) | ||
950 | goto eisis; | ||
951 | |||
952 | mt9m111->autoexposure = 1; | 957 | mt9m111->autoexposure = 1; |
953 | mt9m111->autowhitebalance = 1; | 958 | mt9m111->autowhitebalance = 1; |
954 | 959 | ||
955 | mt9m111->swap_rgb_even_odd = 1; | 960 | mt9m111->swap_rgb_even_odd = 1; |
956 | mt9m111->swap_rgb_red_blue = 1; | 961 | mt9m111->swap_rgb_red_blue = 1; |
957 | 962 | ||
958 | return 0; | ||
959 | eisis: | ||
960 | ei2c: | 963 | ei2c: |
964 | soc_camera_video_stop(icd); | ||
965 | evstart: | ||
961 | return ret; | 966 | return ret; |
962 | } | 967 | } |
963 | 968 | ||
964 | static void mt9m111_video_remove(struct soc_camera_device *icd) | ||
965 | { | ||
966 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
967 | |||
968 | dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr, | ||
969 | mt9m111->icd.dev.parent, mt9m111->icd.vdev); | ||
970 | soc_camera_video_stop(&mt9m111->icd); | ||
971 | } | ||
972 | |||
973 | static int mt9m111_probe(struct i2c_client *client, | 969 | static int mt9m111_probe(struct i2c_client *client, |
974 | const struct i2c_device_id *did) | 970 | const struct i2c_device_id *did) |
975 | { | 971 | { |
976 | struct mt9m111 *mt9m111; | 972 | struct mt9m111 *mt9m111; |
977 | struct soc_camera_device *icd; | 973 | struct soc_camera_device *icd = client->dev.platform_data; |
978 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 974 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
979 | struct soc_camera_link *icl = client->dev.platform_data; | 975 | struct soc_camera_link *icl; |
980 | int ret; | 976 | int ret; |
981 | 977 | ||
978 | if (!icd) { | ||
979 | dev_err(&client->dev, "MT9M11x: missing soc-camera data!\n"); | ||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
983 | icl = to_soc_camera_link(icd); | ||
982 | if (!icl) { | 984 | if (!icl) { |
983 | dev_err(&client->dev, "MT9M11x driver needs platform data\n"); | 985 | dev_err(&client->dev, "MT9M11x driver needs platform data\n"); |
984 | return -EINVAL; | 986 | return -EINVAL; |
@@ -994,13 +996,10 @@ static int mt9m111_probe(struct i2c_client *client, | |||
994 | if (!mt9m111) | 996 | if (!mt9m111) |
995 | return -ENOMEM; | 997 | return -ENOMEM; |
996 | 998 | ||
997 | mt9m111->client = client; | ||
998 | i2c_set_clientdata(client, mt9m111); | 999 | i2c_set_clientdata(client, mt9m111); |
999 | 1000 | ||
1000 | /* Second stage probe - when a capture adapter is there */ | 1001 | /* Second stage probe - when a capture adapter is there */ |
1001 | icd = &mt9m111->icd; | ||
1002 | icd->ops = &mt9m111_ops; | 1002 | icd->ops = &mt9m111_ops; |
1003 | icd->control = &client->dev; | ||
1004 | icd->x_min = MT9M111_MIN_DARK_COLS; | 1003 | icd->x_min = MT9M111_MIN_DARK_COLS; |
1005 | icd->y_min = MT9M111_MIN_DARK_ROWS; | 1004 | icd->y_min = MT9M111_MIN_DARK_ROWS; |
1006 | icd->x_current = icd->x_min; | 1005 | icd->x_current = icd->x_min; |
@@ -1010,22 +1009,25 @@ static int mt9m111_probe(struct i2c_client *client, | |||
1010 | icd->height_min = MT9M111_MIN_DARK_COLS; | 1009 | icd->height_min = MT9M111_MIN_DARK_COLS; |
1011 | icd->height_max = MT9M111_MAX_HEIGHT; | 1010 | icd->height_max = MT9M111_MAX_HEIGHT; |
1012 | icd->y_skip_top = 0; | 1011 | icd->y_skip_top = 0; |
1013 | icd->iface = icl->bus_id; | ||
1014 | 1012 | ||
1015 | ret = soc_camera_device_register(icd); | 1013 | ret = mt9m111_video_probe(icd, client); |
1016 | if (ret) | 1014 | if (ret) { |
1017 | goto eisdr; | 1015 | icd->ops = NULL; |
1018 | return 0; | 1016 | i2c_set_clientdata(client, NULL); |
1017 | kfree(mt9m111); | ||
1018 | } | ||
1019 | 1019 | ||
1020 | eisdr: | ||
1021 | kfree(mt9m111); | ||
1022 | return ret; | 1020 | return ret; |
1023 | } | 1021 | } |
1024 | 1022 | ||
1025 | static int mt9m111_remove(struct i2c_client *client) | 1023 | static int mt9m111_remove(struct i2c_client *client) |
1026 | { | 1024 | { |
1027 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 1025 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); |
1028 | soc_camera_device_unregister(&mt9m111->icd); | 1026 | struct soc_camera_device *icd = client->dev.platform_data; |
1027 | |||
1028 | icd->ops = NULL; | ||
1029 | i2c_set_clientdata(client, NULL); | ||
1030 | client->driver = NULL; | ||
1029 | kfree(mt9m111); | 1031 | kfree(mt9m111); |
1030 | 1032 | ||
1031 | return 0; | 1033 | return 0; |
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 4207fb342670..d9c7c2fd698a 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c | |||
@@ -68,8 +68,6 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = { | |||
68 | }; | 68 | }; |
69 | 69 | ||
70 | struct mt9t031 { | 70 | struct mt9t031 { |
71 | struct i2c_client *client; | ||
72 | struct soc_camera_device icd; | ||
73 | int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ | 71 | int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ |
74 | unsigned char autoexposure; | 72 | unsigned char autoexposure; |
75 | u16 xskip; | 73 | u16 xskip; |
@@ -138,8 +136,8 @@ static int get_shutter(struct i2c_client *client, u32 *data) | |||
138 | 136 | ||
139 | static int mt9t031_init(struct soc_camera_device *icd) | 137 | static int mt9t031_init(struct soc_camera_device *icd) |
140 | { | 138 | { |
141 | struct i2c_client *client = to_i2c_client(icd->control); | 139 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
142 | struct soc_camera_link *icl = client->dev.platform_data; | 140 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
143 | int ret; | 141 | int ret; |
144 | 142 | ||
145 | if (icl->power) { | 143 | if (icl->power) { |
@@ -166,8 +164,8 @@ static int mt9t031_init(struct soc_camera_device *icd) | |||
166 | 164 | ||
167 | static int mt9t031_release(struct soc_camera_device *icd) | 165 | static int mt9t031_release(struct soc_camera_device *icd) |
168 | { | 166 | { |
169 | struct i2c_client *client = to_i2c_client(icd->control); | 167 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
170 | struct soc_camera_link *icl = client->dev.platform_data; | 168 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
171 | 169 | ||
172 | /* Disable the chip */ | 170 | /* Disable the chip */ |
173 | reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); | 171 | reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); |
@@ -180,7 +178,7 @@ static int mt9t031_release(struct soc_camera_device *icd) | |||
180 | 178 | ||
181 | static int mt9t031_start_capture(struct soc_camera_device *icd) | 179 | static int mt9t031_start_capture(struct soc_camera_device *icd) |
182 | { | 180 | { |
183 | struct i2c_client *client = to_i2c_client(icd->control); | 181 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
184 | 182 | ||
185 | /* Switch to master "normal" mode */ | 183 | /* Switch to master "normal" mode */ |
186 | if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0) | 184 | if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0) |
@@ -190,7 +188,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd) | |||
190 | 188 | ||
191 | static int mt9t031_stop_capture(struct soc_camera_device *icd) | 189 | static int mt9t031_stop_capture(struct soc_camera_device *icd) |
192 | { | 190 | { |
193 | struct i2c_client *client = to_i2c_client(icd->control); | 191 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
194 | 192 | ||
195 | /* Stop sensor readout */ | 193 | /* Stop sensor readout */ |
196 | if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0) | 194 | if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0) |
@@ -201,7 +199,7 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd) | |||
201 | static int mt9t031_set_bus_param(struct soc_camera_device *icd, | 199 | static int mt9t031_set_bus_param(struct soc_camera_device *icd, |
202 | unsigned long flags) | 200 | unsigned long flags) |
203 | { | 201 | { |
204 | struct i2c_client *client = to_i2c_client(icd->control); | 202 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
205 | 203 | ||
206 | /* The caller should have queried our parameters, check anyway */ | 204 | /* The caller should have queried our parameters, check anyway */ |
207 | if (flags & ~MT9T031_BUS_PARAM) | 205 | if (flags & ~MT9T031_BUS_PARAM) |
@@ -217,8 +215,7 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd, | |||
217 | 215 | ||
218 | static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) | 216 | static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) |
219 | { | 217 | { |
220 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | 218 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
221 | struct soc_camera_link *icl = mt9t031->client->dev.platform_data; | ||
222 | 219 | ||
223 | return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); | 220 | return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); |
224 | } | 221 | } |
@@ -238,8 +235,8 @@ static void recalculate_limits(struct soc_camera_device *icd, | |||
238 | static int mt9t031_set_params(struct soc_camera_device *icd, | 235 | static int mt9t031_set_params(struct soc_camera_device *icd, |
239 | struct v4l2_rect *rect, u16 xskip, u16 yskip) | 236 | struct v4l2_rect *rect, u16 xskip, u16 yskip) |
240 | { | 237 | { |
241 | struct i2c_client *client = to_i2c_client(icd->control); | 238 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
242 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | 239 | struct mt9t031 *mt9t031 = i2c_get_clientdata(client); |
243 | int ret; | 240 | int ret; |
244 | u16 xbin, ybin, width, height, left, top; | 241 | u16 xbin, ybin, width, height, left, top; |
245 | const u16 hblank = MT9T031_HORIZONTAL_BLANK, | 242 | const u16 hblank = MT9T031_HORIZONTAL_BLANK, |
@@ -336,7 +333,8 @@ static int mt9t031_set_params(struct soc_camera_device *icd, | |||
336 | static int mt9t031_set_crop(struct soc_camera_device *icd, | 333 | static int mt9t031_set_crop(struct soc_camera_device *icd, |
337 | struct v4l2_rect *rect) | 334 | struct v4l2_rect *rect) |
338 | { | 335 | { |
339 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | 336 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
337 | struct mt9t031 *mt9t031 = i2c_get_clientdata(client); | ||
340 | 338 | ||
341 | /* CROP - no change in scaling, or in limits */ | 339 | /* CROP - no change in scaling, or in limits */ |
342 | return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); | 340 | 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 | static int mt9t031_set_fmt(struct soc_camera_device *icd, | 343 | static int mt9t031_set_fmt(struct soc_camera_device *icd, |
346 | struct v4l2_format *f) | 344 | struct v4l2_format *f) |
347 | { | 345 | { |
348 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | 346 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
347 | struct mt9t031 *mt9t031 = i2c_get_clientdata(client); | ||
349 | int ret; | 348 | int ret; |
350 | u16 xskip, yskip; | 349 | u16 xskip, yskip; |
351 | struct v4l2_rect rect = { | 350 | struct v4l2_rect rect = { |
@@ -395,12 +394,13 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, | |||
395 | static int mt9t031_get_chip_id(struct soc_camera_device *icd, | 394 | static int mt9t031_get_chip_id(struct soc_camera_device *icd, |
396 | struct v4l2_dbg_chip_ident *id) | 395 | struct v4l2_dbg_chip_ident *id) |
397 | { | 396 | { |
398 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | 397 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
398 | struct mt9t031 *mt9t031 = i2c_get_clientdata(client); | ||
399 | 399 | ||
400 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | 400 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) |
401 | return -EINVAL; | 401 | return -EINVAL; |
402 | 402 | ||
403 | if (id->match.addr != mt9t031->client->addr) | 403 | if (id->match.addr != client->addr) |
404 | return -ENODEV; | 404 | return -ENODEV; |
405 | 405 | ||
406 | id->ident = mt9t031->model; | 406 | id->ident = mt9t031->model; |
@@ -413,7 +413,7 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd, | |||
413 | static int mt9t031_get_register(struct soc_camera_device *icd, | 413 | static int mt9t031_get_register(struct soc_camera_device *icd, |
414 | struct v4l2_dbg_register *reg) | 414 | struct v4l2_dbg_register *reg) |
415 | { | 415 | { |
416 | struct i2c_client *client = to_i2c_client(icd->control); | 416 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
417 | 417 | ||
418 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) | 418 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) |
419 | return -EINVAL; | 419 | return -EINVAL; |
@@ -432,7 +432,7 @@ static int mt9t031_get_register(struct soc_camera_device *icd, | |||
432 | static int mt9t031_set_register(struct soc_camera_device *icd, | 432 | static int mt9t031_set_register(struct soc_camera_device *icd, |
433 | struct v4l2_dbg_register *reg) | 433 | struct v4l2_dbg_register *reg) |
434 | { | 434 | { |
435 | struct i2c_client *client = to_i2c_client(icd->control); | 435 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
436 | 436 | ||
437 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) | 437 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) |
438 | return -EINVAL; | 438 | return -EINVAL; |
@@ -493,15 +493,11 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { | |||
493 | } | 493 | } |
494 | }; | 494 | }; |
495 | 495 | ||
496 | static int mt9t031_video_probe(struct soc_camera_device *); | ||
497 | static void mt9t031_video_remove(struct soc_camera_device *); | ||
498 | static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *); | 496 | static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *); |
499 | static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *); | 497 | static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *); |
500 | 498 | ||
501 | static struct soc_camera_ops mt9t031_ops = { | 499 | static struct soc_camera_ops mt9t031_ops = { |
502 | .owner = THIS_MODULE, | 500 | .owner = THIS_MODULE, |
503 | .probe = mt9t031_video_probe, | ||
504 | .remove = mt9t031_video_remove, | ||
505 | .init = mt9t031_init, | 501 | .init = mt9t031_init, |
506 | .release = mt9t031_release, | 502 | .release = mt9t031_release, |
507 | .start_capture = mt9t031_start_capture, | 503 | .start_capture = mt9t031_start_capture, |
@@ -524,8 +520,8 @@ static struct soc_camera_ops mt9t031_ops = { | |||
524 | 520 | ||
525 | static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) | 521 | static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) |
526 | { | 522 | { |
527 | struct i2c_client *client = to_i2c_client(icd->control); | 523 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
528 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | 524 | struct mt9t031 *mt9t031 = i2c_get_clientdata(client); |
529 | int data; | 525 | int data; |
530 | 526 | ||
531 | switch (ctrl->id) { | 527 | switch (ctrl->id) { |
@@ -550,8 +546,8 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro | |||
550 | 546 | ||
551 | static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) | 547 | static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) |
552 | { | 548 | { |
553 | struct i2c_client *client = to_i2c_client(icd->control); | 549 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
554 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | 550 | struct mt9t031 *mt9t031 = i2c_get_clientdata(client); |
555 | const struct v4l2_queryctrl *qctrl; | 551 | const struct v4l2_queryctrl *qctrl; |
556 | int data; | 552 | int data; |
557 | 553 | ||
@@ -657,10 +653,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro | |||
657 | 653 | ||
658 | /* Interface active, can use i2c. If it fails, it can indeed mean, that | 654 | /* Interface active, can use i2c. If it fails, it can indeed mean, that |
659 | * this wasn't our capture interface, so, we wait for the right one */ | 655 | * this wasn't our capture interface, so, we wait for the right one */ |
660 | static int mt9t031_video_probe(struct soc_camera_device *icd) | 656 | static int mt9t031_video_probe(struct soc_camera_device *icd, |
657 | struct i2c_client *client) | ||
661 | { | 658 | { |
662 | struct i2c_client *client = to_i2c_client(icd->control); | 659 | struct mt9t031 *mt9t031 = i2c_get_clientdata(client); |
663 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | ||
664 | s32 data; | 660 | s32 data; |
665 | int ret; | 661 | int ret; |
666 | 662 | ||
@@ -670,6 +666,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) | |||
670 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) | 666 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) |
671 | return -ENODEV; | 667 | return -ENODEV; |
672 | 668 | ||
669 | /* Switch master clock on */ | ||
670 | ret = soc_camera_video_start(icd, &client->dev); | ||
671 | if (ret) | ||
672 | return ret; | ||
673 | |||
673 | /* Enable the chip */ | 674 | /* Enable the chip */ |
674 | data = reg_write(client, MT9T031_CHIP_ENABLE, 1); | 675 | data = reg_write(client, MT9T031_CHIP_ENABLE, 1); |
675 | dev_dbg(&icd->dev, "write: %d\n", data); | 676 | dev_dbg(&icd->dev, "write: %d\n", data); |
@@ -677,6 +678,8 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) | |||
677 | /* Read out the chip version register */ | 678 | /* Read out the chip version register */ |
678 | data = reg_read(client, MT9T031_CHIP_VERSION); | 679 | data = reg_read(client, MT9T031_CHIP_VERSION); |
679 | 680 | ||
681 | soc_camera_video_stop(icd); | ||
682 | |||
680 | switch (data) { | 683 | switch (data) { |
681 | case 0x1621: | 684 | case 0x1621: |
682 | mt9t031->model = V4L2_IDENT_MT9T031; | 685 | mt9t031->model = V4L2_IDENT_MT9T031; |
@@ -684,44 +687,31 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) | |||
684 | icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats); | 687 | icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats); |
685 | break; | 688 | break; |
686 | default: | 689 | default: |
687 | ret = -ENODEV; | ||
688 | dev_err(&icd->dev, | 690 | dev_err(&icd->dev, |
689 | "No MT9T031 chip detected, register read %x\n", data); | 691 | "No MT9T031 chip detected, register read %x\n", data); |
690 | goto ei2c; | 692 | return -ENODEV; |
691 | } | 693 | } |
692 | 694 | ||
693 | dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data); | 695 | dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data); |
694 | 696 | ||
695 | /* Now that we know the model, we can start video */ | ||
696 | ret = soc_camera_video_start(icd); | ||
697 | if (ret) | ||
698 | goto evstart; | ||
699 | |||
700 | return 0; | 697 | return 0; |
701 | |||
702 | evstart: | ||
703 | ei2c: | ||
704 | return ret; | ||
705 | } | ||
706 | |||
707 | static void mt9t031_video_remove(struct soc_camera_device *icd) | ||
708 | { | ||
709 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | ||
710 | |||
711 | dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr, | ||
712 | icd->dev.parent, icd->vdev); | ||
713 | soc_camera_video_stop(icd); | ||
714 | } | 698 | } |
715 | 699 | ||
716 | static int mt9t031_probe(struct i2c_client *client, | 700 | static int mt9t031_probe(struct i2c_client *client, |
717 | const struct i2c_device_id *did) | 701 | const struct i2c_device_id *did) |
718 | { | 702 | { |
719 | struct mt9t031 *mt9t031; | 703 | struct mt9t031 *mt9t031; |
720 | struct soc_camera_device *icd; | 704 | struct soc_camera_device *icd = client->dev.platform_data; |
721 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 705 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
722 | struct soc_camera_link *icl = client->dev.platform_data; | 706 | struct soc_camera_link *icl; |
723 | int ret; | 707 | int ret; |
724 | 708 | ||
709 | if (!icd) { | ||
710 | dev_err(&client->dev, "MT9T031: missing soc-camera data!\n"); | ||
711 | return -EINVAL; | ||
712 | } | ||
713 | |||
714 | icl = to_soc_camera_link(icd); | ||
725 | if (!icl) { | 715 | if (!icl) { |
726 | dev_err(&client->dev, "MT9T031 driver needs platform data\n"); | 716 | dev_err(&client->dev, "MT9T031 driver needs platform data\n"); |
727 | return -EINVAL; | 717 | return -EINVAL; |
@@ -737,13 +727,10 @@ static int mt9t031_probe(struct i2c_client *client, | |||
737 | if (!mt9t031) | 727 | if (!mt9t031) |
738 | return -ENOMEM; | 728 | return -ENOMEM; |
739 | 729 | ||
740 | mt9t031->client = client; | ||
741 | i2c_set_clientdata(client, mt9t031); | 730 | i2c_set_clientdata(client, mt9t031); |
742 | 731 | ||
743 | /* Second stage probe - when a capture adapter is there */ | 732 | /* Second stage probe - when a capture adapter is there */ |
744 | icd = &mt9t031->icd; | ||
745 | icd->ops = &mt9t031_ops; | 733 | icd->ops = &mt9t031_ops; |
746 | icd->control = &client->dev; | ||
747 | icd->x_min = MT9T031_COLUMN_SKIP; | 734 | icd->x_min = MT9T031_COLUMN_SKIP; |
748 | icd->y_min = MT9T031_ROW_SKIP; | 735 | icd->y_min = MT9T031_ROW_SKIP; |
749 | icd->x_current = icd->x_min; | 736 | icd->x_current = icd->x_min; |
@@ -753,7 +740,6 @@ static int mt9t031_probe(struct i2c_client *client, | |||
753 | icd->height_min = MT9T031_MIN_HEIGHT; | 740 | icd->height_min = MT9T031_MIN_HEIGHT; |
754 | icd->height_max = MT9T031_MAX_HEIGHT; | 741 | icd->height_max = MT9T031_MAX_HEIGHT; |
755 | icd->y_skip_top = 0; | 742 | icd->y_skip_top = 0; |
756 | icd->iface = icl->bus_id; | ||
757 | /* Simulated autoexposure. If enabled, we calculate shutter width | 743 | /* Simulated autoexposure. If enabled, we calculate shutter width |
758 | * ourselves in the driver based on vertical blanking and frame width */ | 744 | * ourselves in the driver based on vertical blanking and frame width */ |
759 | mt9t031->autoexposure = 1; | 745 | mt9t031->autoexposure = 1; |
@@ -761,24 +747,24 @@ static int mt9t031_probe(struct i2c_client *client, | |||
761 | mt9t031->xskip = 1; | 747 | mt9t031->xskip = 1; |
762 | mt9t031->yskip = 1; | 748 | mt9t031->yskip = 1; |
763 | 749 | ||
764 | ret = soc_camera_device_register(icd); | 750 | ret = mt9t031_video_probe(icd, client); |
765 | if (ret) | 751 | if (ret) { |
766 | goto eisdr; | 752 | icd->ops = NULL; |
767 | 753 | i2c_set_clientdata(client, NULL); | |
768 | return 0; | 754 | kfree(mt9t031); |
755 | } | ||
769 | 756 | ||
770 | eisdr: | ||
771 | i2c_set_clientdata(client, NULL); | ||
772 | kfree(mt9t031); | ||
773 | return ret; | 757 | return ret; |
774 | } | 758 | } |
775 | 759 | ||
776 | static int mt9t031_remove(struct i2c_client *client) | 760 | static int mt9t031_remove(struct i2c_client *client) |
777 | { | 761 | { |
778 | struct mt9t031 *mt9t031 = i2c_get_clientdata(client); | 762 | struct mt9t031 *mt9t031 = i2c_get_clientdata(client); |
763 | struct soc_camera_device *icd = client->dev.platform_data; | ||
779 | 764 | ||
780 | soc_camera_device_unregister(&mt9t031->icd); | 765 | icd->ops = NULL; |
781 | i2c_set_clientdata(client, NULL); | 766 | i2c_set_clientdata(client, NULL); |
767 | client->driver = NULL; | ||
782 | kfree(mt9t031); | 768 | kfree(mt9t031); |
783 | 769 | ||
784 | return 0; | 770 | return 0; |
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index dbdcc86ae50d..959cc299f1ae 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { | |||
85 | }; | 85 | }; |
86 | 86 | ||
87 | struct mt9v022 { | 87 | struct mt9v022 { |
88 | struct i2c_client *client; | ||
89 | struct soc_camera_device icd; | ||
90 | int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ | 88 | int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ |
91 | u16 chip_control; | 89 | u16 chip_control; |
92 | }; | 90 | }; |
@@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg, | |||
127 | 125 | ||
128 | static int mt9v022_init(struct soc_camera_device *icd) | 126 | static int mt9v022_init(struct soc_camera_device *icd) |
129 | { | 127 | { |
130 | struct i2c_client *client = to_i2c_client(icd->control); | 128 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
131 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 129 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
132 | struct soc_camera_link *icl = client->dev.platform_data; | 130 | struct mt9v022 *mt9v022 = i2c_get_clientdata(client); |
133 | int ret; | 131 | int ret; |
134 | 132 | ||
135 | if (icl->power) { | 133 | if (icl->power) { |
@@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd) | |||
173 | 171 | ||
174 | static int mt9v022_release(struct soc_camera_device *icd) | 172 | static int mt9v022_release(struct soc_camera_device *icd) |
175 | { | 173 | { |
176 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 174 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
177 | struct soc_camera_link *icl = mt9v022->client->dev.platform_data; | 175 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
178 | 176 | ||
179 | if (icl->power) | 177 | if (icl->power) |
180 | icl->power(&mt9v022->client->dev, 0); | 178 | icl->power(&client->dev, 0); |
181 | 179 | ||
182 | return 0; | 180 | return 0; |
183 | } | 181 | } |
184 | 182 | ||
185 | static int mt9v022_start_capture(struct soc_camera_device *icd) | 183 | static int mt9v022_start_capture(struct soc_camera_device *icd) |
186 | { | 184 | { |
187 | struct i2c_client *client = to_i2c_client(icd->control); | 185 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
188 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 186 | struct mt9v022 *mt9v022 = i2c_get_clientdata(client); |
189 | /* Switch to master "normal" mode */ | 187 | /* Switch to master "normal" mode */ |
190 | mt9v022->chip_control &= ~0x10; | 188 | mt9v022->chip_control &= ~0x10; |
191 | if (reg_write(client, MT9V022_CHIP_CONTROL, | 189 | if (reg_write(client, MT9V022_CHIP_CONTROL, |
@@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd) | |||
196 | 194 | ||
197 | static int mt9v022_stop_capture(struct soc_camera_device *icd) | 195 | static int mt9v022_stop_capture(struct soc_camera_device *icd) |
198 | { | 196 | { |
199 | struct i2c_client *client = to_i2c_client(icd->control); | 197 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
200 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 198 | struct mt9v022 *mt9v022 = i2c_get_clientdata(client); |
201 | /* Switch to snapshot mode */ | 199 | /* Switch to snapshot mode */ |
202 | mt9v022->chip_control |= 0x10; | 200 | mt9v022->chip_control |= 0x10; |
203 | if (reg_write(client, MT9V022_CHIP_CONTROL, | 201 | if (reg_write(client, MT9V022_CHIP_CONTROL, |
@@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd) | |||
209 | static int mt9v022_set_bus_param(struct soc_camera_device *icd, | 207 | static int mt9v022_set_bus_param(struct soc_camera_device *icd, |
210 | unsigned long flags) | 208 | unsigned long flags) |
211 | { | 209 | { |
212 | struct i2c_client *client = to_i2c_client(icd->control); | 210 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
213 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 211 | struct mt9v022 *mt9v022 = i2c_get_clientdata(client); |
214 | struct soc_camera_link *icl = client->dev.platform_data; | 212 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
215 | unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; | 213 | unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; |
216 | int ret; | 214 | int ret; |
217 | u16 pixclk = 0; | 215 | u16 pixclk = 0; |
@@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, | |||
263 | 261 | ||
264 | static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) | 262 | static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) |
265 | { | 263 | { |
266 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 264 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
267 | struct soc_camera_link *icl = mt9v022->client->dev.platform_data; | ||
268 | unsigned int width_flag; | 265 | unsigned int width_flag; |
269 | 266 | ||
270 | if (icl->query_bus_param) | 267 | if (icl->query_bus_param) |
@@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) | |||
283 | static int mt9v022_set_crop(struct soc_camera_device *icd, | 280 | static int mt9v022_set_crop(struct soc_camera_device *icd, |
284 | struct v4l2_rect *rect) | 281 | struct v4l2_rect *rect) |
285 | { | 282 | { |
286 | struct i2c_client *client = to_i2c_client(icd->control); | 283 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
287 | int ret; | 284 | int ret; |
288 | 285 | ||
289 | /* Like in example app. Contradicts the datasheet though */ | 286 | /* Like in example app. Contradicts the datasheet though */ |
@@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd, | |||
326 | static int mt9v022_set_fmt(struct soc_camera_device *icd, | 323 | static int mt9v022_set_fmt(struct soc_camera_device *icd, |
327 | struct v4l2_format *f) | 324 | struct v4l2_format *f) |
328 | { | 325 | { |
329 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 326 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
327 | struct mt9v022 *mt9v022 = i2c_get_clientdata(client); | ||
330 | struct v4l2_pix_format *pix = &f->fmt.pix; | 328 | struct v4l2_pix_format *pix = &f->fmt.pix; |
331 | struct v4l2_rect rect = { | 329 | struct v4l2_rect rect = { |
332 | .left = icd->x_current, | 330 | .left = icd->x_current, |
@@ -374,12 +372,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd, | |||
374 | static int mt9v022_get_chip_id(struct soc_camera_device *icd, | 372 | static int mt9v022_get_chip_id(struct soc_camera_device *icd, |
375 | struct v4l2_dbg_chip_ident *id) | 373 | struct v4l2_dbg_chip_ident *id) |
376 | { | 374 | { |
377 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 375 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
376 | struct mt9v022 *mt9v022 = i2c_get_clientdata(client); | ||
378 | 377 | ||
379 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | 378 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) |
380 | return -EINVAL; | 379 | return -EINVAL; |
381 | 380 | ||
382 | if (id->match.addr != mt9v022->client->addr) | 381 | if (id->match.addr != client->addr) |
383 | return -ENODEV; | 382 | return -ENODEV; |
384 | 383 | ||
385 | id->ident = mt9v022->model; | 384 | id->ident = mt9v022->model; |
@@ -392,7 +391,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd, | |||
392 | static int mt9v022_get_register(struct soc_camera_device *icd, | 391 | static int mt9v022_get_register(struct soc_camera_device *icd, |
393 | struct v4l2_dbg_register *reg) | 392 | struct v4l2_dbg_register *reg) |
394 | { | 393 | { |
395 | struct i2c_client *client = to_i2c_client(icd->control); | 394 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
396 | 395 | ||
397 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) | 396 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) |
398 | return -EINVAL; | 397 | return -EINVAL; |
@@ -412,7 +411,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd, | |||
412 | static int mt9v022_set_register(struct soc_camera_device *icd, | 411 | static int mt9v022_set_register(struct soc_camera_device *icd, |
413 | struct v4l2_dbg_register *reg) | 412 | struct v4l2_dbg_register *reg) |
414 | { | 413 | { |
415 | struct i2c_client *client = to_i2c_client(icd->control); | 414 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
416 | 415 | ||
417 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) | 416 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) |
418 | return -EINVAL; | 417 | return -EINVAL; |
@@ -481,15 +480,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { | |||
481 | } | 480 | } |
482 | }; | 481 | }; |
483 | 482 | ||
484 | static int mt9v022_video_probe(struct soc_camera_device *); | ||
485 | static void mt9v022_video_remove(struct soc_camera_device *); | ||
486 | static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); | 483 | static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); |
487 | static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); | 484 | static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); |
488 | 485 | ||
489 | static struct soc_camera_ops mt9v022_ops = { | 486 | static struct soc_camera_ops mt9v022_ops = { |
490 | .owner = THIS_MODULE, | 487 | .owner = THIS_MODULE, |
491 | .probe = mt9v022_video_probe, | ||
492 | .remove = mt9v022_video_remove, | ||
493 | .init = mt9v022_init, | 488 | .init = mt9v022_init, |
494 | .release = mt9v022_release, | 489 | .release = mt9v022_release, |
495 | .start_capture = mt9v022_start_capture, | 490 | .start_capture = mt9v022_start_capture, |
@@ -513,7 +508,7 @@ static struct soc_camera_ops mt9v022_ops = { | |||
513 | static int mt9v022_get_control(struct soc_camera_device *icd, | 508 | static int mt9v022_get_control(struct soc_camera_device *icd, |
514 | struct v4l2_control *ctrl) | 509 | struct v4l2_control *ctrl) |
515 | { | 510 | { |
516 | struct i2c_client *client = to_i2c_client(icd->control); | 511 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
517 | int data; | 512 | int data; |
518 | 513 | ||
519 | switch (ctrl->id) { | 514 | switch (ctrl->id) { |
@@ -549,7 +544,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd, | |||
549 | struct v4l2_control *ctrl) | 544 | struct v4l2_control *ctrl) |
550 | { | 545 | { |
551 | int data; | 546 | int data; |
552 | struct i2c_client *client = to_i2c_client(icd->control); | 547 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
553 | const struct v4l2_queryctrl *qctrl; | 548 | const struct v4l2_queryctrl *qctrl; |
554 | 549 | ||
555 | qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); | 550 | qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); |
@@ -646,11 +641,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd, | |||
646 | 641 | ||
647 | /* Interface active, can use i2c. If it fails, it can indeed mean, that | 642 | /* Interface active, can use i2c. If it fails, it can indeed mean, that |
648 | * this wasn't our capture interface, so, we wait for the right one */ | 643 | * this wasn't our capture interface, so, we wait for the right one */ |
649 | static int mt9v022_video_probe(struct soc_camera_device *icd) | 644 | static int mt9v022_video_probe(struct soc_camera_device *icd, |
645 | struct i2c_client *client) | ||
650 | { | 646 | { |
651 | struct i2c_client *client = to_i2c_client(icd->control); | 647 | struct mt9v022 *mt9v022 = i2c_get_clientdata(client); |
652 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 648 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
653 | struct soc_camera_link *icl = client->dev.platform_data; | ||
654 | s32 data; | 649 | s32 data; |
655 | int ret; | 650 | int ret; |
656 | unsigned long flags; | 651 | unsigned long flags; |
@@ -659,6 +654,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) | |||
659 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) | 654 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) |
660 | return -ENODEV; | 655 | return -ENODEV; |
661 | 656 | ||
657 | /* Switch master clock on */ | ||
658 | ret = soc_camera_video_start(icd, &client->dev); | ||
659 | if (ret) | ||
660 | return ret; | ||
661 | |||
662 | /* Read out the chip version register */ | 662 | /* Read out the chip version register */ |
663 | data = reg_read(client, MT9V022_CHIP_VERSION); | 663 | data = reg_read(client, MT9V022_CHIP_VERSION); |
664 | 664 | ||
@@ -678,6 +678,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) | |||
678 | udelay(200); | 678 | udelay(200); |
679 | if (reg_read(client, MT9V022_RESET)) { | 679 | if (reg_read(client, MT9V022_RESET)) { |
680 | dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); | 680 | dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); |
681 | if (ret > 0) | ||
682 | ret = -EIO; | ||
681 | goto ei2c; | 683 | goto ei2c; |
682 | } | 684 | } |
683 | 685 | ||
@@ -694,7 +696,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) | |||
694 | } | 696 | } |
695 | 697 | ||
696 | if (ret < 0) | 698 | if (ret < 0) |
697 | goto eisis; | 699 | goto ei2c; |
698 | 700 | ||
699 | icd->num_formats = 0; | 701 | icd->num_formats = 0; |
700 | 702 | ||
@@ -716,29 +718,23 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) | |||
716 | if (flags & SOCAM_DATAWIDTH_8) | 718 | if (flags & SOCAM_DATAWIDTH_8) |
717 | icd->num_formats++; | 719 | icd->num_formats++; |
718 | 720 | ||
719 | ret = soc_camera_video_start(icd); | ||
720 | if (ret < 0) | ||
721 | goto eisis; | ||
722 | |||
723 | dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", | 721 | dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", |
724 | data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? | 722 | data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? |
725 | "monochrome" : "colour"); | 723 | "monochrome" : "colour"); |
726 | 724 | ||
727 | return 0; | ||
728 | |||
729 | eisis: | ||
730 | ei2c: | 725 | ei2c: |
726 | soc_camera_video_stop(icd); | ||
727 | |||
731 | return ret; | 728 | return ret; |
732 | } | 729 | } |
733 | 730 | ||
734 | static void mt9v022_video_remove(struct soc_camera_device *icd) | 731 | static void mt9v022_video_remove(struct soc_camera_device *icd) |
735 | { | 732 | { |
736 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 733 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
737 | struct soc_camera_link *icl = mt9v022->client->dev.platform_data; | 734 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
738 | 735 | ||
739 | dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, | 736 | dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr, |
740 | icd->dev.parent, icd->vdev); | 737 | icd->dev.parent, icd->vdev); |
741 | soc_camera_video_stop(icd); | ||
742 | if (icl->free_bus) | 738 | if (icl->free_bus) |
743 | icl->free_bus(icl); | 739 | icl->free_bus(icl); |
744 | } | 740 | } |
@@ -747,11 +743,17 @@ static int mt9v022_probe(struct i2c_client *client, | |||
747 | const struct i2c_device_id *did) | 743 | const struct i2c_device_id *did) |
748 | { | 744 | { |
749 | struct mt9v022 *mt9v022; | 745 | struct mt9v022 *mt9v022; |
750 | struct soc_camera_device *icd; | 746 | struct soc_camera_device *icd = client->dev.platform_data; |
751 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 747 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
752 | struct soc_camera_link *icl = client->dev.platform_data; | 748 | struct soc_camera_link *icl; |
753 | int ret; | 749 | int ret; |
754 | 750 | ||
751 | if (!icd) { | ||
752 | dev_err(&client->dev, "MT9V022: missing soc-camera data!\n"); | ||
753 | return -EINVAL; | ||
754 | } | ||
755 | |||
756 | icl = to_soc_camera_link(icd); | ||
755 | if (!icl) { | 757 | if (!icl) { |
756 | dev_err(&client->dev, "MT9V022 driver needs platform data\n"); | 758 | dev_err(&client->dev, "MT9V022 driver needs platform data\n"); |
757 | return -EINVAL; | 759 | return -EINVAL; |
@@ -768,12 +770,9 @@ static int mt9v022_probe(struct i2c_client *client, | |||
768 | return -ENOMEM; | 770 | return -ENOMEM; |
769 | 771 | ||
770 | mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; | 772 | mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; |
771 | mt9v022->client = client; | ||
772 | i2c_set_clientdata(client, mt9v022); | 773 | i2c_set_clientdata(client, mt9v022); |
773 | 774 | ||
774 | icd = &mt9v022->icd; | ||
775 | icd->ops = &mt9v022_ops; | 775 | icd->ops = &mt9v022_ops; |
776 | icd->control = &client->dev; | ||
777 | icd->x_min = 1; | 776 | icd->x_min = 1; |
778 | icd->y_min = 4; | 777 | icd->y_min = 4; |
779 | icd->x_current = 1; | 778 | icd->x_current = 1; |
@@ -783,24 +782,26 @@ static int mt9v022_probe(struct i2c_client *client, | |||
783 | icd->height_min = 32; | 782 | icd->height_min = 32; |
784 | icd->height_max = 480; | 783 | icd->height_max = 480; |
785 | icd->y_skip_top = 1; | 784 | icd->y_skip_top = 1; |
786 | icd->iface = icl->bus_id; | ||
787 | |||
788 | ret = soc_camera_device_register(icd); | ||
789 | if (ret) | ||
790 | goto eisdr; | ||
791 | 785 | ||
792 | return 0; | 786 | ret = mt9v022_video_probe(icd, client); |
787 | if (ret) { | ||
788 | icd->ops = NULL; | ||
789 | i2c_set_clientdata(client, NULL); | ||
790 | kfree(mt9v022); | ||
791 | } | ||
793 | 792 | ||
794 | eisdr: | ||
795 | kfree(mt9v022); | ||
796 | return ret; | 793 | return ret; |
797 | } | 794 | } |
798 | 795 | ||
799 | static int mt9v022_remove(struct i2c_client *client) | 796 | static int mt9v022_remove(struct i2c_client *client) |
800 | { | 797 | { |
801 | struct mt9v022 *mt9v022 = i2c_get_clientdata(client); | 798 | struct mt9v022 *mt9v022 = i2c_get_clientdata(client); |
799 | struct soc_camera_device *icd = client->dev.platform_data; | ||
802 | 800 | ||
803 | soc_camera_device_unregister(&mt9v022->icd); | 801 | icd->ops = NULL; |
802 | mt9v022_video_remove(icd); | ||
803 | i2c_set_clientdata(client, NULL); | ||
804 | client->driver = NULL; | ||
804 | kfree(mt9v022); | 805 | kfree(mt9v022); |
805 | 806 | ||
806 | return 0; | 807 | return 0; |
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index 9770cb7932ca..2edf77a6256b 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c | |||
@@ -503,18 +503,19 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) | |||
503 | 503 | ||
504 | mx3_camera_activate(mx3_cam, icd); | 504 | mx3_camera_activate(mx3_cam, icd); |
505 | ret = icd->ops->init(icd); | 505 | ret = icd->ops->init(icd); |
506 | if (ret < 0) { | 506 | if (ret < 0) |
507 | clk_disable(mx3_cam->clk); | ||
508 | goto einit; | 507 | goto einit; |
509 | } | ||
510 | 508 | ||
511 | mx3_cam->icd = icd; | 509 | mx3_cam->icd = icd; |
512 | 510 | ||
511 | dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", | ||
512 | icd->devnum); | ||
513 | |||
514 | return 0; | ||
515 | |||
513 | einit: | 516 | einit: |
517 | clk_disable(mx3_cam->clk); | ||
514 | ebusy: | 518 | ebusy: |
515 | if (!ret) | ||
516 | dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", | ||
517 | icd->devnum); | ||
518 | 519 | ||
519 | return ret; | 520 | return ret; |
520 | } | 521 | } |
@@ -947,9 +948,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
947 | camera_flags = icd->ops->query_bus_param(icd); | 948 | camera_flags = icd->ops->query_bus_param(icd); |
948 | 949 | ||
949 | common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); | 950 | common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); |
951 | dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", | ||
952 | camera_flags, bus_flags, common_flags); | ||
950 | if (!common_flags) { | 953 | if (!common_flags) { |
951 | dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n", | 954 | dev_dbg(ici->dev, "no common flags"); |
952 | camera_flags, bus_flags); | ||
953 | return -EINVAL; | 955 | return -EINVAL; |
954 | } | 956 | } |
955 | 957 | ||
@@ -1002,8 +1004,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
1002 | SOCAM_DATAWIDTH_4; | 1004 | SOCAM_DATAWIDTH_4; |
1003 | 1005 | ||
1004 | ret = icd->ops->set_bus_param(icd, common_flags); | 1006 | ret = icd->ops->set_bus_param(icd, common_flags); |
1005 | if (ret < 0) | 1007 | if (ret < 0) { |
1008 | dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n", | ||
1009 | common_flags, ret); | ||
1006 | return ret; | 1010 | return ret; |
1011 | } | ||
1007 | 1012 | ||
1008 | /* | 1013 | /* |
1009 | * So far only gated clock mode is supported. Add a line | 1014 | * 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 | INIT_LIST_HEAD(&mx3_cam->capture); | 1132 | INIT_LIST_HEAD(&mx3_cam->capture); |
1128 | spin_lock_init(&mx3_cam->lock); | 1133 | spin_lock_init(&mx3_cam->lock); |
1129 | 1134 | ||
1130 | base = ioremap(res->start, res->end - res->start + 1); | 1135 | base = ioremap(res->start, resource_size(res)); |
1131 | if (!base) { | 1136 | if (!base) { |
1137 | pr_err("Couldn't map %x@%x\n", resource_size(res), res->start); | ||
1132 | err = -ENOMEM; | 1138 | err = -ENOMEM; |
1133 | goto eioremap; | 1139 | goto eioremap; |
1134 | } | 1140 | } |
@@ -1215,3 +1221,4 @@ module_exit(mx3_camera_exit); | |||
1215 | MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); | 1221 | MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); |
1216 | MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); | 1222 | MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); |
1217 | MODULE_LICENSE("GPL v2"); | 1223 | MODULE_LICENSE("GPL v2"); |
1224 | MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME); | ||
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 0bce255168bd..3ea650d55b17 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c | |||
@@ -399,8 +399,6 @@ struct ov772x_win_size { | |||
399 | 399 | ||
400 | struct ov772x_priv { | 400 | struct ov772x_priv { |
401 | struct ov772x_camera_info *info; | 401 | struct ov772x_camera_info *info; |
402 | struct i2c_client *client; | ||
403 | struct soc_camera_device icd; | ||
404 | const struct ov772x_color_format *fmt; | 402 | const struct ov772x_color_format *fmt; |
405 | const struct ov772x_win_size *win; | 403 | const struct ov772x_win_size *win; |
406 | int model; | 404 | int model; |
@@ -619,53 +617,56 @@ static int ov772x_reset(struct i2c_client *client) | |||
619 | 617 | ||
620 | static int ov772x_init(struct soc_camera_device *icd) | 618 | static int ov772x_init(struct soc_camera_device *icd) |
621 | { | 619 | { |
622 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 620 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
621 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
623 | int ret = 0; | 622 | int ret = 0; |
624 | 623 | ||
625 | if (priv->info->link.power) { | 624 | if (icl->power) { |
626 | ret = priv->info->link.power(&priv->client->dev, 1); | 625 | ret = icl->power(&client->dev, 1); |
627 | if (ret < 0) | 626 | if (ret < 0) |
628 | return ret; | 627 | return ret; |
629 | } | 628 | } |
630 | 629 | ||
631 | if (priv->info->link.reset) | 630 | if (icl->reset) |
632 | ret = priv->info->link.reset(&priv->client->dev); | 631 | ret = icl->reset(&client->dev); |
633 | 632 | ||
634 | return ret; | 633 | return ret; |
635 | } | 634 | } |
636 | 635 | ||
637 | static int ov772x_release(struct soc_camera_device *icd) | 636 | static int ov772x_release(struct soc_camera_device *icd) |
638 | { | 637 | { |
639 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 638 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
639 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
640 | int ret = 0; | 640 | int ret = 0; |
641 | 641 | ||
642 | if (priv->info->link.power) | 642 | if (icl->power) |
643 | ret = priv->info->link.power(&priv->client->dev, 0); | 643 | ret = icl->power(&client->dev, 0); |
644 | 644 | ||
645 | return ret; | 645 | return ret; |
646 | } | 646 | } |
647 | 647 | ||
648 | static int ov772x_start_capture(struct soc_camera_device *icd) | 648 | static int ov772x_start_capture(struct soc_camera_device *icd) |
649 | { | 649 | { |
650 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 650 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
651 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
651 | 652 | ||
652 | if (!priv->win || !priv->fmt) { | 653 | if (!priv->win || !priv->fmt) { |
653 | dev_err(&icd->dev, "norm or win select error\n"); | 654 | dev_err(&icd->dev, "norm or win select error\n"); |
654 | return -EPERM; | 655 | return -EPERM; |
655 | } | 656 | } |
656 | 657 | ||
657 | ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0); | 658 | ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); |
658 | 659 | ||
659 | dev_dbg(&icd->dev, | 660 | dev_dbg(&icd->dev, |
660 | "format %s, win %s\n", priv->fmt->name, priv->win->name); | 661 | "format %s, win %s\n", priv->fmt->name, priv->win->name); |
661 | 662 | ||
662 | return 0; | 663 | return 0; |
663 | } | 664 | } |
664 | 665 | ||
665 | static int ov772x_stop_capture(struct soc_camera_device *icd) | 666 | static int ov772x_stop_capture(struct soc_camera_device *icd) |
666 | { | 667 | { |
667 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 668 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
668 | ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); | 669 | ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); |
669 | return 0; | 670 | return 0; |
670 | } | 671 | } |
671 | 672 | ||
@@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd, | |||
677 | 678 | ||
678 | static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) | 679 | static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) |
679 | { | 680 | { |
680 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 681 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
681 | struct soc_camera_link *icl = &priv->info->link; | 682 | struct ov772x_priv *priv = i2c_get_clientdata(client); |
683 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
682 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | | 684 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | |
683 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | | 685 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | |
684 | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; | 686 | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; |
@@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) | |||
689 | static int ov772x_get_control(struct soc_camera_device *icd, | 691 | static int ov772x_get_control(struct soc_camera_device *icd, |
690 | struct v4l2_control *ctrl) | 692 | struct v4l2_control *ctrl) |
691 | { | 693 | { |
692 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 694 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
695 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
693 | 696 | ||
694 | switch (ctrl->id) { | 697 | switch (ctrl->id) { |
695 | case V4L2_CID_VFLIP: | 698 | case V4L2_CID_VFLIP: |
@@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd, | |||
705 | static int ov772x_set_control(struct soc_camera_device *icd, | 708 | static int ov772x_set_control(struct soc_camera_device *icd, |
706 | struct v4l2_control *ctrl) | 709 | struct v4l2_control *ctrl) |
707 | { | 710 | { |
708 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 711 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
712 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
709 | int ret = 0; | 713 | int ret = 0; |
710 | u8 val; | 714 | u8 val; |
711 | 715 | ||
@@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd, | |||
715 | priv->flag_vflip = ctrl->value; | 719 | priv->flag_vflip = ctrl->value; |
716 | if (priv->info->flags & OV772X_FLAG_VFLIP) | 720 | if (priv->info->flags & OV772X_FLAG_VFLIP) |
717 | val ^= VFLIP_IMG; | 721 | val ^= VFLIP_IMG; |
718 | ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val); | 722 | ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val); |
719 | break; | 723 | break; |
720 | case V4L2_CID_HFLIP: | 724 | case V4L2_CID_HFLIP: |
721 | val = ctrl->value ? HFLIP_IMG : 0x00; | 725 | val = ctrl->value ? HFLIP_IMG : 0x00; |
722 | priv->flag_hflip = ctrl->value; | 726 | priv->flag_hflip = ctrl->value; |
723 | if (priv->info->flags & OV772X_FLAG_HFLIP) | 727 | if (priv->info->flags & OV772X_FLAG_HFLIP) |
724 | val ^= HFLIP_IMG; | 728 | val ^= HFLIP_IMG; |
725 | ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val); | 729 | ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val); |
726 | break; | 730 | break; |
727 | } | 731 | } |
728 | 732 | ||
@@ -730,9 +734,10 @@ static int ov772x_set_control(struct soc_camera_device *icd, | |||
730 | } | 734 | } |
731 | 735 | ||
732 | static int ov772x_get_chip_id(struct soc_camera_device *icd, | 736 | static int ov772x_get_chip_id(struct soc_camera_device *icd, |
733 | struct v4l2_dbg_chip_ident *id) | 737 | struct v4l2_dbg_chip_ident *id) |
734 | { | 738 | { |
735 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 739 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
740 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
736 | 741 | ||
737 | id->ident = priv->model; | 742 | id->ident = priv->model; |
738 | id->revision = 0; | 743 | id->revision = 0; |
@@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, | |||
744 | static int ov772x_get_register(struct soc_camera_device *icd, | 749 | static int ov772x_get_register(struct soc_camera_device *icd, |
745 | struct v4l2_dbg_register *reg) | 750 | struct v4l2_dbg_register *reg) |
746 | { | 751 | { |
747 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 752 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
748 | int ret; | 753 | int ret; |
749 | 754 | ||
750 | reg->size = 1; | 755 | reg->size = 1; |
751 | if (reg->reg > 0xff) | 756 | if (reg->reg > 0xff) |
752 | return -EINVAL; | 757 | return -EINVAL; |
753 | 758 | ||
754 | ret = i2c_smbus_read_byte_data(priv->client, reg->reg); | 759 | ret = i2c_smbus_read_byte_data(client, reg->reg); |
755 | if (ret < 0) | 760 | if (ret < 0) |
756 | return ret; | 761 | return ret; |
757 | 762 | ||
@@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd, | |||
763 | static int ov772x_set_register(struct soc_camera_device *icd, | 768 | static int ov772x_set_register(struct soc_camera_device *icd, |
764 | struct v4l2_dbg_register *reg) | 769 | struct v4l2_dbg_register *reg) |
765 | { | 770 | { |
766 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 771 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
767 | 772 | ||
768 | if (reg->reg > 0xff || | 773 | if (reg->reg > 0xff || |
769 | reg->val > 0xff) | 774 | reg->val > 0xff) |
770 | return -EINVAL; | 775 | return -EINVAL; |
771 | 776 | ||
772 | return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); | 777 | return i2c_smbus_write_byte_data(client, reg->reg, reg->val); |
773 | } | 778 | } |
774 | #endif | 779 | #endif |
775 | 780 | ||
@@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height) | |||
793 | return win; | 798 | return win; |
794 | } | 799 | } |
795 | 800 | ||
796 | static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | 801 | static int ov772x_set_params(struct soc_camera_device *icd, |
797 | u32 pixfmt) | 802 | u32 width, u32 height, u32 pixfmt) |
798 | { | 803 | { |
804 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
805 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
799 | int ret = -EINVAL; | 806 | int ret = -EINVAL; |
800 | u8 val; | 807 | u8 val; |
801 | int i; | 808 | int i; |
@@ -810,6 +817,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
810 | break; | 817 | break; |
811 | } | 818 | } |
812 | } | 819 | } |
820 | dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i); | ||
813 | if (!priv->fmt) | 821 | if (!priv->fmt) |
814 | goto ov772x_set_fmt_error; | 822 | goto ov772x_set_fmt_error; |
815 | 823 | ||
@@ -821,7 +829,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
821 | /* | 829 | /* |
822 | * reset hardware | 830 | * reset hardware |
823 | */ | 831 | */ |
824 | ov772x_reset(priv->client); | 832 | ov772x_reset(client); |
825 | 833 | ||
826 | /* | 834 | /* |
827 | * Edge Ctrl | 835 | * Edge Ctrl |
@@ -835,17 +843,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
835 | * Remove it when manual mode. | 843 | * Remove it when manual mode. |
836 | */ | 844 | */ |
837 | 845 | ||
838 | ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00); | 846 | ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00); |
839 | if (ret < 0) | 847 | if (ret < 0) |
840 | goto ov772x_set_fmt_error; | 848 | goto ov772x_set_fmt_error; |
841 | 849 | ||
842 | ret = ov772x_mask_set(priv->client, | 850 | ret = ov772x_mask_set(client, |
843 | EDGE_TRSHLD, EDGE_THRESHOLD_MASK, | 851 | EDGE_TRSHLD, EDGE_THRESHOLD_MASK, |
844 | priv->info->edgectrl.threshold); | 852 | priv->info->edgectrl.threshold); |
845 | if (ret < 0) | 853 | if (ret < 0) |
846 | goto ov772x_set_fmt_error; | 854 | goto ov772x_set_fmt_error; |
847 | 855 | ||
848 | ret = ov772x_mask_set(priv->client, | 856 | ret = ov772x_mask_set(client, |
849 | EDGE_STRNGT, EDGE_STRENGTH_MASK, | 857 | EDGE_STRNGT, EDGE_STRENGTH_MASK, |
850 | priv->info->edgectrl.strength); | 858 | priv->info->edgectrl.strength); |
851 | if (ret < 0) | 859 | if (ret < 0) |
@@ -857,13 +865,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
857 | * | 865 | * |
858 | * set upper and lower limit | 866 | * set upper and lower limit |
859 | */ | 867 | */ |
860 | ret = ov772x_mask_set(priv->client, | 868 | ret = ov772x_mask_set(client, |
861 | EDGE_UPPER, EDGE_UPPER_MASK, | 869 | EDGE_UPPER, EDGE_UPPER_MASK, |
862 | priv->info->edgectrl.upper); | 870 | priv->info->edgectrl.upper); |
863 | if (ret < 0) | 871 | if (ret < 0) |
864 | goto ov772x_set_fmt_error; | 872 | goto ov772x_set_fmt_error; |
865 | 873 | ||
866 | ret = ov772x_mask_set(priv->client, | 874 | ret = ov772x_mask_set(client, |
867 | EDGE_LOWER, EDGE_LOWER_MASK, | 875 | EDGE_LOWER, EDGE_LOWER_MASK, |
868 | priv->info->edgectrl.lower); | 876 | priv->info->edgectrl.lower); |
869 | if (ret < 0) | 877 | if (ret < 0) |
@@ -873,7 +881,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
873 | /* | 881 | /* |
874 | * set size format | 882 | * set size format |
875 | */ | 883 | */ |
876 | ret = ov772x_write_array(priv->client, priv->win->regs); | 884 | ret = ov772x_write_array(client, priv->win->regs); |
877 | if (ret < 0) | 885 | if (ret < 0) |
878 | goto ov772x_set_fmt_error; | 886 | goto ov772x_set_fmt_error; |
879 | 887 | ||
@@ -882,7 +890,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
882 | */ | 890 | */ |
883 | val = priv->fmt->dsp3; | 891 | val = priv->fmt->dsp3; |
884 | if (val) { | 892 | if (val) { |
885 | ret = ov772x_mask_set(priv->client, | 893 | ret = ov772x_mask_set(client, |
886 | DSP_CTRL3, UV_MASK, val); | 894 | DSP_CTRL3, UV_MASK, val); |
887 | if (ret < 0) | 895 | if (ret < 0) |
888 | goto ov772x_set_fmt_error; | 896 | goto ov772x_set_fmt_error; |
@@ -901,7 +909,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
901 | if (priv->flag_hflip) | 909 | if (priv->flag_hflip) |
902 | val ^= HFLIP_IMG; | 910 | val ^= HFLIP_IMG; |
903 | 911 | ||
904 | ret = ov772x_mask_set(priv->client, | 912 | ret = ov772x_mask_set(client, |
905 | COM3, SWAP_MASK | IMG_MASK, val); | 913 | COM3, SWAP_MASK | IMG_MASK, val); |
906 | if (ret < 0) | 914 | if (ret < 0) |
907 | goto ov772x_set_fmt_error; | 915 | goto ov772x_set_fmt_error; |
@@ -910,7 +918,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
910 | * set COM7 | 918 | * set COM7 |
911 | */ | 919 | */ |
912 | val = priv->win->com7_bit | priv->fmt->com7; | 920 | val = priv->win->com7_bit | priv->fmt->com7; |
913 | ret = ov772x_mask_set(priv->client, | 921 | ret = ov772x_mask_set(client, |
914 | COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), | 922 | COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), |
915 | val); | 923 | val); |
916 | if (ret < 0) | 924 | if (ret < 0) |
@@ -920,7 +928,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
920 | 928 | ||
921 | ov772x_set_fmt_error: | 929 | ov772x_set_fmt_error: |
922 | 930 | ||
923 | ov772x_reset(priv->client); | 931 | ov772x_reset(client); |
924 | priv->win = NULL; | 932 | priv->win = NULL; |
925 | priv->fmt = NULL; | 933 | priv->fmt = NULL; |
926 | 934 | ||
@@ -930,22 +938,22 @@ ov772x_set_fmt_error: | |||
930 | static int ov772x_set_crop(struct soc_camera_device *icd, | 938 | static int ov772x_set_crop(struct soc_camera_device *icd, |
931 | struct v4l2_rect *rect) | 939 | struct v4l2_rect *rect) |
932 | { | 940 | { |
933 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 941 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
942 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
934 | 943 | ||
935 | if (!priv->fmt) | 944 | if (!priv->fmt) |
936 | return -EINVAL; | 945 | return -EINVAL; |
937 | 946 | ||
938 | return ov772x_set_params(priv, rect->width, rect->height, | 947 | return ov772x_set_params(icd, rect->width, rect->height, |
939 | priv->fmt->fourcc); | 948 | priv->fmt->fourcc); |
940 | } | 949 | } |
941 | 950 | ||
942 | static int ov772x_set_fmt(struct soc_camera_device *icd, | 951 | static int ov772x_set_fmt(struct soc_camera_device *icd, |
943 | struct v4l2_format *f) | 952 | struct v4l2_format *f) |
944 | { | 953 | { |
945 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | ||
946 | struct v4l2_pix_format *pix = &f->fmt.pix; | 954 | struct v4l2_pix_format *pix = &f->fmt.pix; |
947 | 955 | ||
948 | return ov772x_set_params(priv, pix->width, pix->height, | 956 | return ov772x_set_params(icd, pix->width, pix->height, |
949 | pix->pixelformat); | 957 | pix->pixelformat); |
950 | } | 958 | } |
951 | 959 | ||
@@ -967,11 +975,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd, | |||
967 | return 0; | 975 | return 0; |
968 | } | 976 | } |
969 | 977 | ||
970 | static int ov772x_video_probe(struct soc_camera_device *icd) | 978 | static int ov772x_video_probe(struct soc_camera_device *icd, |
979 | struct i2c_client *client) | ||
971 | { | 980 | { |
972 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 981 | struct ov772x_priv *priv = i2c_get_clientdata(client); |
973 | u8 pid, ver; | 982 | u8 pid, ver; |
974 | const char *devname; | 983 | const char *devname; |
984 | int ret; | ||
975 | 985 | ||
976 | /* | 986 | /* |
977 | * We must have a parent by now. And it cannot be a wrong one. | 987 | * 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 | icd->formats = ov772x_fmt_lists; | 1003 | icd->formats = ov772x_fmt_lists; |
994 | icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); | 1004 | icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); |
995 | 1005 | ||
1006 | /* Switch master clock on */ | ||
1007 | ret = soc_camera_video_start(icd, &client->dev); | ||
1008 | if (ret) | ||
1009 | return ret; | ||
1010 | |||
996 | /* | 1011 | /* |
997 | * check and show product ID and manufacturer ID | 1012 | * check and show product ID and manufacturer ID |
998 | */ | 1013 | */ |
999 | pid = i2c_smbus_read_byte_data(priv->client, PID); | 1014 | pid = i2c_smbus_read_byte_data(client, PID); |
1000 | ver = i2c_smbus_read_byte_data(priv->client, VER); | 1015 | ver = i2c_smbus_read_byte_data(client, VER); |
1001 | 1016 | ||
1002 | switch (VERSION(pid, ver)) { | 1017 | switch (VERSION(pid, ver)) { |
1003 | case OV7720: | 1018 | case OV7720: |
@@ -1011,7 +1026,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd) | |||
1011 | default: | 1026 | default: |
1012 | dev_err(&icd->dev, | 1027 | dev_err(&icd->dev, |
1013 | "Product ID error %x:%x\n", pid, ver); | 1028 | "Product ID error %x:%x\n", pid, ver); |
1014 | return -ENODEV; | 1029 | ret = -ENODEV; |
1030 | goto ever; | ||
1015 | } | 1031 | } |
1016 | 1032 | ||
1017 | dev_info(&icd->dev, | 1033 | dev_info(&icd->dev, |
@@ -1019,21 +1035,17 @@ static int ov772x_video_probe(struct soc_camera_device *icd) | |||
1019 | devname, | 1035 | devname, |
1020 | pid, | 1036 | pid, |
1021 | ver, | 1037 | ver, |
1022 | i2c_smbus_read_byte_data(priv->client, MIDH), | 1038 | i2c_smbus_read_byte_data(client, MIDH), |
1023 | i2c_smbus_read_byte_data(priv->client, MIDL)); | 1039 | i2c_smbus_read_byte_data(client, MIDL)); |
1024 | |||
1025 | return soc_camera_video_start(icd); | ||
1026 | } | ||
1027 | 1040 | ||
1028 | static void ov772x_video_remove(struct soc_camera_device *icd) | ||
1029 | { | ||
1030 | soc_camera_video_stop(icd); | 1041 | soc_camera_video_stop(icd); |
1042 | |||
1043 | ever: | ||
1044 | return ret; | ||
1031 | } | 1045 | } |
1032 | 1046 | ||
1033 | static struct soc_camera_ops ov772x_ops = { | 1047 | static struct soc_camera_ops ov772x_ops = { |
1034 | .owner = THIS_MODULE, | 1048 | .owner = THIS_MODULE, |
1035 | .probe = ov772x_video_probe, | ||
1036 | .remove = ov772x_video_remove, | ||
1037 | .init = ov772x_init, | 1049 | .init = ov772x_init, |
1038 | .release = ov772x_release, | 1050 | .release = ov772x_release, |
1039 | .start_capture = ov772x_start_capture, | 1051 | .start_capture = ov772x_start_capture, |
@@ -1059,19 +1071,25 @@ static struct soc_camera_ops ov772x_ops = { | |||
1059 | */ | 1071 | */ |
1060 | 1072 | ||
1061 | static int ov772x_probe(struct i2c_client *client, | 1073 | static int ov772x_probe(struct i2c_client *client, |
1062 | const struct i2c_device_id *did) | 1074 | const struct i2c_device_id *did) |
1063 | { | 1075 | { |
1064 | struct ov772x_priv *priv; | 1076 | struct ov772x_priv *priv; |
1065 | struct ov772x_camera_info *info; | 1077 | struct ov772x_camera_info *info; |
1066 | struct soc_camera_device *icd; | 1078 | struct soc_camera_device *icd = client->dev.platform_data; |
1067 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 1079 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
1080 | struct soc_camera_link *icl; | ||
1068 | int ret; | 1081 | int ret; |
1069 | 1082 | ||
1070 | if (!client->dev.platform_data) | 1083 | if (!icd) { |
1084 | dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); | ||
1071 | return -EINVAL; | 1085 | return -EINVAL; |
1086 | } | ||
1072 | 1087 | ||
1073 | info = container_of(client->dev.platform_data, | 1088 | icl = to_soc_camera_link(icd); |
1074 | struct ov772x_camera_info, link); | 1089 | if (!icl) |
1090 | return -EINVAL; | ||
1091 | |||
1092 | info = container_of(icl, struct ov772x_camera_info, link); | ||
1075 | 1093 | ||
1076 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 1094 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
1077 | dev_err(&adapter->dev, | 1095 | dev_err(&adapter->dev, |
@@ -1085,19 +1103,15 @@ static int ov772x_probe(struct i2c_client *client, | |||
1085 | return -ENOMEM; | 1103 | return -ENOMEM; |
1086 | 1104 | ||
1087 | priv->info = info; | 1105 | priv->info = info; |
1088 | priv->client = client; | ||
1089 | i2c_set_clientdata(client, priv); | 1106 | i2c_set_clientdata(client, priv); |
1090 | 1107 | ||
1091 | icd = &priv->icd; | ||
1092 | icd->ops = &ov772x_ops; | 1108 | icd->ops = &ov772x_ops; |
1093 | icd->control = &client->dev; | ||
1094 | icd->width_max = MAX_WIDTH; | 1109 | icd->width_max = MAX_WIDTH; |
1095 | icd->height_max = MAX_HEIGHT; | 1110 | icd->height_max = MAX_HEIGHT; |
1096 | icd->iface = priv->info->link.bus_id; | ||
1097 | |||
1098 | ret = soc_camera_device_register(icd); | ||
1099 | 1111 | ||
1112 | ret = ov772x_video_probe(icd, client); | ||
1100 | if (ret) { | 1113 | if (ret) { |
1114 | icd->ops = NULL; | ||
1101 | i2c_set_clientdata(client, NULL); | 1115 | i2c_set_clientdata(client, NULL); |
1102 | kfree(priv); | 1116 | kfree(priv); |
1103 | } | 1117 | } |
@@ -1108,8 +1122,9 @@ static int ov772x_probe(struct i2c_client *client, | |||
1108 | static int ov772x_remove(struct i2c_client *client) | 1122 | static int ov772x_remove(struct i2c_client *client) |
1109 | { | 1123 | { |
1110 | struct ov772x_priv *priv = i2c_get_clientdata(client); | 1124 | struct ov772x_priv *priv = i2c_get_clientdata(client); |
1125 | struct soc_camera_device *icd = client->dev.platform_data; | ||
1111 | 1126 | ||
1112 | soc_camera_device_unregister(&priv->icd); | 1127 | icd->ops = NULL; |
1113 | i2c_set_clientdata(client, NULL); | 1128 | i2c_set_clientdata(client, NULL); |
1114 | kfree(priv); | 1129 | kfree(priv); |
1115 | return 0; | 1130 | return 0; |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 016bb45ba0c3..8b9b44d86837 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -830,7 +830,8 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q, | |||
830 | sizeof(struct pxa_buffer), icd); | 830 | sizeof(struct pxa_buffer), icd); |
831 | } | 831 | } |
832 | 832 | ||
833 | static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) | 833 | static u32 mclk_get_divisor(struct platform_device *pdev, |
834 | struct pxa_camera_dev *pcdev) | ||
834 | { | 835 | { |
835 | unsigned long mclk = pcdev->mclk; | 836 | unsigned long mclk = pcdev->mclk; |
836 | u32 div; | 837 | u32 div; |
@@ -842,7 +843,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) | |||
842 | /* mclk <= ciclk / 4 (27.4.2) */ | 843 | /* mclk <= ciclk / 4 (27.4.2) */ |
843 | if (mclk > lcdclk / 4) { | 844 | if (mclk > lcdclk / 4) { |
844 | mclk = lcdclk / 4; | 845 | mclk = lcdclk / 4; |
845 | dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk); | 846 | dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk); |
846 | } | 847 | } |
847 | 848 | ||
848 | /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */ | 849 | /* 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 | if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) | 853 | if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) |
853 | pcdev->mclk = lcdclk / (2 * (div + 1)); | 854 | pcdev->mclk = lcdclk / (2 * (div + 1)); |
854 | 855 | ||
855 | dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, " | 856 | dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n", |
856 | "divisor %u\n", lcdclk, mclk, div); | 857 | lcdclk, mclk, div); |
857 | 858 | ||
858 | return div; | 859 | return div; |
859 | } | 860 | } |
@@ -958,15 +959,20 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) | |||
958 | goto ebusy; | 959 | goto ebusy; |
959 | } | 960 | } |
960 | 961 | ||
961 | dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", | ||
962 | icd->devnum); | ||
963 | |||
964 | pxa_camera_activate(pcdev); | 962 | pxa_camera_activate(pcdev); |
965 | ret = icd->ops->init(icd); | 963 | ret = icd->ops->init(icd); |
964 | if (ret < 0) | ||
965 | goto einit; | ||
966 | |||
967 | pcdev->icd = icd; | ||
966 | 968 | ||
967 | if (!ret) | 969 | dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", |
968 | pcdev->icd = icd; | 970 | icd->devnum); |
969 | 971 | ||
972 | return 0; | ||
973 | |||
974 | einit: | ||
975 | pxa_camera_deactivate(pcdev); | ||
970 | ebusy: | 976 | ebusy: |
971 | return ret; | 977 | return ret; |
972 | } | 978 | } |
@@ -1575,8 +1581,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) | |||
1575 | pcdev->mclk = 20000000; | 1581 | pcdev->mclk = 20000000; |
1576 | } | 1582 | } |
1577 | 1583 | ||
1578 | pcdev->soc_host.dev = &pdev->dev; | 1584 | pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev); |
1579 | pcdev->mclk_divisor = mclk_get_divisor(pcdev); | ||
1580 | 1585 | ||
1581 | INIT_LIST_HEAD(&pcdev->capture); | 1586 | INIT_LIST_HEAD(&pcdev->capture); |
1582 | spin_lock_init(&pcdev->lock); | 1587 | spin_lock_init(&pcdev->lock); |
@@ -1641,6 +1646,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) | |||
1641 | pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; | 1646 | pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; |
1642 | pcdev->soc_host.ops = &pxa_soc_camera_host_ops; | 1647 | pcdev->soc_host.ops = &pxa_soc_camera_host_ops; |
1643 | pcdev->soc_host.priv = pcdev; | 1648 | pcdev->soc_host.priv = pcdev; |
1649 | pcdev->soc_host.dev = &pdev->dev; | ||
1644 | pcdev->soc_host.nr = pdev->id; | 1650 | pcdev->soc_host.nr = pdev->id; |
1645 | 1651 | ||
1646 | err = soc_camera_host_register(&pcdev->soc_host); | 1652 | err = soc_camera_host_register(&pcdev->soc_host); |
@@ -1722,3 +1728,4 @@ module_exit(pxa_camera_exit); | |||
1722 | MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); | 1728 | MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); |
1723 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); | 1729 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); |
1724 | MODULE_LICENSE("GPL"); | 1730 | MODULE_LICENSE("GPL"); |
1731 | MODULE_ALIAS("platform:" PXA_CAM_DRV_NAME); | ||
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 61c47b824083..e7ac84daf670 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -356,11 +356,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
356 | "SuperH Mobile CEU driver attached to camera %d\n", | 356 | "SuperH Mobile CEU driver attached to camera %d\n", |
357 | icd->devnum); | 357 | icd->devnum); |
358 | 358 | ||
359 | clk_enable(pcdev->clk); | ||
360 | |||
359 | ret = icd->ops->init(icd); | 361 | ret = icd->ops->init(icd); |
360 | if (ret) | 362 | if (ret) { |
363 | clk_disable(pcdev->clk); | ||
361 | goto err; | 364 | goto err; |
362 | 365 | } | |
363 | pm_runtime_get_sync(ici->dev); | ||
364 | 366 | ||
365 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | 367 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ |
366 | while (ceu_read(pcdev, CSTSR) & 1) | 368 | while (ceu_read(pcdev, CSTSR) & 1) |
@@ -394,10 +396,10 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
394 | } | 396 | } |
395 | spin_unlock_irqrestore(&pcdev->lock, flags); | 397 | spin_unlock_irqrestore(&pcdev->lock, flags); |
396 | 398 | ||
397 | pm_runtime_put_sync(ici->dev); | ||
398 | |||
399 | icd->ops->release(icd); | 399 | icd->ops->release(icd); |
400 | 400 | ||
401 | clk_disable(pcdev->clk); | ||
402 | |||
401 | dev_info(&icd->dev, | 403 | dev_info(&icd->dev, |
402 | "SuperH Mobile CEU driver detached from camera %d\n", | 404 | "SuperH Mobile CEU driver detached from camera %d\n", |
403 | icd->devnum); | 405 | icd->devnum); |
@@ -946,3 +948,4 @@ module_exit(sh_mobile_ceu_exit); | |||
946 | MODULE_DESCRIPTION("SuperH Mobile CEU driver"); | 948 | MODULE_DESCRIPTION("SuperH Mobile CEU driver"); |
947 | MODULE_AUTHOR("Magnus Damm"); | 949 | MODULE_AUTHOR("Magnus Damm"); |
948 | MODULE_LICENSE("GPL"); | 950 | MODULE_LICENSE("GPL"); |
951 | MODULE_ALIAS("platform:sh_mobile_ceu"); | ||
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 0340754e5406..20ef5c773fae 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -21,15 +21,15 @@ | |||
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
24 | #include <linux/module.h> | ||
25 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
25 | #include <linux/module.h> | ||
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/vmalloc.h> | 27 | #include <linux/vmalloc.h> |
28 | 28 | ||
29 | #include <media/soc_camera.h> | 29 | #include <media/soc_camera.h> |
30 | #include <media/v4l2-common.h> | 30 | #include <media/v4l2-common.h> |
31 | #include <media/v4l2-dev.h> | ||
32 | #include <media/v4l2-ioctl.h> | 31 | #include <media/v4l2-ioctl.h> |
32 | #include <media/v4l2-dev.h> | ||
33 | #include <media/videobuf-core.h> | 33 | #include <media/videobuf-core.h> |
34 | 34 | ||
35 | /* Default to VGA resolution */ | 35 | /* Default to VGA resolution */ |
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | static LIST_HEAD(hosts); | 39 | static LIST_HEAD(hosts); |
40 | static LIST_HEAD(devices); | 40 | static LIST_HEAD(devices); |
41 | static DEFINE_MUTEX(list_lock); | 41 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ |
42 | 42 | ||
43 | const struct soc_camera_data_format *soc_camera_format_by_fourcc( | 43 | const struct soc_camera_data_format *soc_camera_format_by_fourcc( |
44 | struct soc_camera_device *icd, unsigned int fourcc) | 44 | struct soc_camera_device *icd, unsigned int fourcc) |
@@ -209,6 +209,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv, | |||
209 | return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); | 209 | return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); |
210 | } | 210 | } |
211 | 211 | ||
212 | /* Always entered with .video_lock held */ | ||
212 | static int soc_camera_init_user_formats(struct soc_camera_device *icd) | 213 | static int soc_camera_init_user_formats(struct soc_camera_device *icd) |
213 | { | 214 | { |
214 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 215 | 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 | return 0; | 258 | return 0; |
258 | } | 259 | } |
259 | 260 | ||
261 | /* Always entered with .video_lock held */ | ||
260 | static void soc_camera_free_user_formats(struct soc_camera_device *icd) | 262 | static void soc_camera_free_user_formats(struct soc_camera_device *icd) |
261 | { | 263 | { |
264 | icd->current_fmt = NULL; | ||
262 | vfree(icd->user_formats); | 265 | vfree(icd->user_formats); |
266 | icd->user_formats = NULL; | ||
263 | } | 267 | } |
264 | 268 | ||
265 | /* Called with .vb_lock held */ | 269 | /* Called with .vb_lock held */ |
@@ -310,10 +314,6 @@ static int soc_camera_open(struct file *file) | |||
310 | struct soc_camera_file *icf; | 314 | struct soc_camera_file *icf; |
311 | int ret; | 315 | int ret; |
312 | 316 | ||
313 | icf = vmalloc(sizeof(*icf)); | ||
314 | if (!icf) | ||
315 | return -ENOMEM; | ||
316 | |||
317 | /* | 317 | /* |
318 | * It is safe to dereference these pointers now as long as a user has | 318 | * It is safe to dereference these pointers now as long as a user has |
319 | * the video device open - we are protected by the held cdev reference. | 319 | * 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 | 321 | ||
322 | vdev = video_devdata(file); | 322 | vdev = video_devdata(file); |
323 | icd = container_of(vdev->parent, struct soc_camera_device, dev); | 323 | icd = container_of(vdev->parent, struct soc_camera_device, dev); |
324 | |||
325 | if (!icd->ops) | ||
326 | /* No device driver attached */ | ||
327 | return -ENODEV; | ||
328 | |||
324 | ici = to_soc_camera_host(icd->dev.parent); | 329 | ici = to_soc_camera_host(icd->dev.parent); |
325 | 330 | ||
331 | icf = vmalloc(sizeof(*icf)); | ||
332 | if (!icf) | ||
333 | return -ENOMEM; | ||
334 | |||
326 | if (!try_module_get(icd->ops->owner)) { | 335 | if (!try_module_get(icd->ops->owner)) { |
327 | dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); | 336 | dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); |
328 | ret = -EINVAL; | 337 | ret = -EINVAL; |
@@ -335,7 +344,7 @@ static int soc_camera_open(struct file *file) | |||
335 | goto emgi; | 344 | goto emgi; |
336 | } | 345 | } |
337 | 346 | ||
338 | /* Protect against icd->remove() until we module_get() both drivers. */ | 347 | /* Protect against icd->ops->remove() until we module_get() both drivers. */ |
339 | mutex_lock(&icd->video_lock); | 348 | mutex_lock(&icd->video_lock); |
340 | 349 | ||
341 | icf->icd = icd; | 350 | icf->icd = icd; |
@@ -350,11 +359,18 @@ static int soc_camera_open(struct file *file) | |||
350 | .width = icd->width, | 359 | .width = icd->width, |
351 | .height = icd->height, | 360 | .height = icd->height, |
352 | .field = icd->field, | 361 | .field = icd->field, |
353 | .pixelformat = icd->current_fmt->fourcc, | ||
354 | .colorspace = icd->current_fmt->colorspace, | ||
355 | }, | 362 | }, |
356 | }; | 363 | }; |
357 | 364 | ||
365 | ret = soc_camera_init_user_formats(icd); | ||
366 | if (ret < 0) | ||
367 | goto eiufmt; | ||
368 | |||
369 | dev_dbg(&icd->dev, "Using fmt %x\n", icd->current_fmt->fourcc); | ||
370 | |||
371 | f.fmt.pix.pixelformat = icd->current_fmt->fourcc; | ||
372 | f.fmt.pix.colorspace = icd->current_fmt->colorspace; | ||
373 | |||
358 | ret = ici->ops->add(icd); | 374 | ret = ici->ops->add(icd); |
359 | if (ret < 0) { | 375 | if (ret < 0) { |
360 | dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); | 376 | 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 | esfmt: | 399 | esfmt: |
384 | ici->ops->remove(icd); | 400 | ici->ops->remove(icd); |
385 | eiciadd: | 401 | eiciadd: |
402 | soc_camera_free_user_formats(icd); | ||
403 | eiufmt: | ||
386 | icd->use_count--; | 404 | icd->use_count--; |
387 | mutex_unlock(&icd->video_lock); | 405 | mutex_unlock(&icd->video_lock); |
388 | module_put(ici->ops->owner); | 406 | module_put(ici->ops->owner); |
@@ -402,8 +420,10 @@ static int soc_camera_close(struct file *file) | |||
402 | 420 | ||
403 | mutex_lock(&icd->video_lock); | 421 | mutex_lock(&icd->video_lock); |
404 | icd->use_count--; | 422 | icd->use_count--; |
405 | if (!icd->use_count) | 423 | if (!icd->use_count) { |
406 | ici->ops->remove(icd); | 424 | ici->ops->remove(icd); |
425 | soc_camera_free_user_formats(icd); | ||
426 | } | ||
407 | 427 | ||
408 | mutex_unlock(&icd->video_lock); | 428 | mutex_unlock(&icd->video_lock); |
409 | 429 | ||
@@ -764,29 +784,6 @@ static int soc_camera_s_register(struct file *file, void *fh, | |||
764 | } | 784 | } |
765 | #endif | 785 | #endif |
766 | 786 | ||
767 | static int device_register_link(struct soc_camera_device *icd) | ||
768 | { | ||
769 | int ret = dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum); | ||
770 | |||
771 | if (!ret) | ||
772 | ret = device_register(&icd->dev); | ||
773 | |||
774 | if (ret < 0) { | ||
775 | /* Prevent calling device_unregister() */ | ||
776 | icd->dev.parent = NULL; | ||
777 | dev_err(&icd->dev, "Cannot register device: %d\n", ret); | ||
778 | /* Even if probe() was unsuccessful for all registered drivers, | ||
779 | * device_register() returns 0, and we add the link, just to | ||
780 | * document this camera's control device */ | ||
781 | } else if (icd->control) | ||
782 | /* Have to sysfs_remove_link() before device_unregister()? */ | ||
783 | if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj, | ||
784 | "control")) | ||
785 | dev_warn(&icd->dev, | ||
786 | "Failed creating the control symlink\n"); | ||
787 | return ret; | ||
788 | } | ||
789 | |||
790 | /* So far this function cannot fail */ | 787 | /* So far this function cannot fail */ |
791 | static void scan_add_host(struct soc_camera_host *ici) | 788 | static void scan_add_host(struct soc_camera_host *ici) |
792 | { | 789 | { |
@@ -796,106 +793,124 @@ static void scan_add_host(struct soc_camera_host *ici) | |||
796 | 793 | ||
797 | list_for_each_entry(icd, &devices, list) { | 794 | list_for_each_entry(icd, &devices, list) { |
798 | if (icd->iface == ici->nr) { | 795 | if (icd->iface == ici->nr) { |
796 | int ret; | ||
799 | icd->dev.parent = ici->dev; | 797 | icd->dev.parent = ici->dev; |
800 | device_register_link(icd); | 798 | dev_set_name(&icd->dev, "%u-%u", icd->iface, |
799 | icd->devnum); | ||
800 | ret = device_register(&icd->dev); | ||
801 | if (ret < 0) { | ||
802 | icd->dev.parent = NULL; | ||
803 | dev_err(&icd->dev, | ||
804 | "Cannot register device: %d\n", ret); | ||
805 | } | ||
801 | } | 806 | } |
802 | } | 807 | } |
803 | 808 | ||
804 | mutex_unlock(&list_lock); | 809 | mutex_unlock(&list_lock); |
805 | } | 810 | } |
806 | 811 | ||
807 | /* return: 0 if no match found or a match found and | 812 | #ifdef CONFIG_I2C_BOARDINFO |
808 | * device_register() successful, error code otherwise */ | 813 | static int soc_camera_init_i2c(struct soc_camera_device *icd, |
809 | static int scan_add_device(struct soc_camera_device *icd) | 814 | struct soc_camera_link *icl) |
810 | { | 815 | { |
811 | struct soc_camera_host *ici; | 816 | struct i2c_client *client; |
812 | int ret = 0; | 817 | struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); |
818 | int ret; | ||
813 | 819 | ||
814 | mutex_lock(&list_lock); | 820 | if (!adap) { |
821 | ret = -ENODEV; | ||
822 | dev_err(&icd->dev, "Cannot get I2C adapter #%d. No driver?\n", | ||
823 | icl->i2c_adapter_id); | ||
824 | goto ei2cga; | ||
825 | } | ||
815 | 826 | ||
816 | list_add_tail(&icd->list, &devices); | 827 | icl->board_info->platform_data = icd; |
817 | 828 | ||
818 | /* Watch out for class_for_each_device / class_find_device API by | 829 | client = i2c_new_device(adap, icl->board_info); |
819 | * Dave Young <hidave.darkstar@gmail.com> */ | 830 | if (!client) { |
820 | list_for_each_entry(ici, &hosts, list) { | 831 | ret = -ENOMEM; |
821 | if (icd->iface == ici->nr) { | 832 | goto ei2cnd; |
822 | ret = 1; | ||
823 | icd->dev.parent = ici->dev; | ||
824 | break; | ||
825 | } | ||
826 | } | 833 | } |
827 | 834 | ||
828 | mutex_unlock(&list_lock); | 835 | /* |
829 | 836 | * We set icd drvdata at two locations - here and in | |
830 | if (ret) | 837 | * soc_camera_video_start(). Depending on the module loading / |
831 | ret = device_register_link(icd); | 838 | * initialisation order one of these locations will be entered first |
839 | */ | ||
840 | /* Use to_i2c_client(dev) to recover the i2c client */ | ||
841 | dev_set_drvdata(&icd->dev, &client->dev); | ||
832 | 842 | ||
843 | return 0; | ||
844 | ei2cnd: | ||
845 | i2c_put_adapter(adap); | ||
846 | ei2cga: | ||
833 | return ret; | 847 | return ret; |
834 | } | 848 | } |
835 | 849 | ||
850 | static void soc_camera_free_i2c(struct soc_camera_device *icd) | ||
851 | { | ||
852 | struct i2c_client *client = | ||
853 | to_i2c_client(to_soc_camera_control(icd)); | ||
854 | dev_set_drvdata(&icd->dev, NULL); | ||
855 | i2c_unregister_device(client); | ||
856 | i2c_put_adapter(client->adapter); | ||
857 | } | ||
858 | #else | ||
859 | #define soc_camera_init_i2c(icd, icl) (-ENODEV) | ||
860 | #define soc_camera_free_i2c(icd) do {} while (0) | ||
861 | #endif | ||
862 | |||
863 | static int video_dev_create(struct soc_camera_device *icd); | ||
864 | /* Called during host-driver probe */ | ||
836 | static int soc_camera_probe(struct device *dev) | 865 | static int soc_camera_probe(struct device *dev) |
837 | { | 866 | { |
838 | struct soc_camera_device *icd = to_soc_camera_dev(dev); | 867 | struct soc_camera_device *icd = to_soc_camera_dev(dev); |
839 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 868 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
840 | int ret; | 869 | int ret; |
841 | 870 | ||
842 | /* | 871 | dev_info(dev, "Probing %s\n", dev_name(dev)); |
843 | * Possible race scenario: | ||
844 | * modprobe <camera-host-driver> triggers __func__ | ||
845 | * at this moment respective <camera-sensor-driver> gets rmmod'ed | ||
846 | * to protect take module references. | ||
847 | */ | ||
848 | 872 | ||
849 | if (!try_module_get(icd->ops->owner)) { | 873 | ret = video_dev_create(icd); |
850 | dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); | 874 | if (ret < 0) |
851 | ret = -EINVAL; | 875 | goto evdc; |
852 | goto emgd; | ||
853 | } | ||
854 | 876 | ||
855 | if (!try_module_get(ici->ops->owner)) { | 877 | /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */ |
856 | dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); | 878 | if (icl->board_info) { |
879 | ret = soc_camera_init_i2c(icd, icl); | ||
880 | if (ret < 0) | ||
881 | goto eadddev; | ||
882 | } else if (!icl->add_device || !icl->del_device) { | ||
857 | ret = -EINVAL; | 883 | ret = -EINVAL; |
858 | goto emgi; | 884 | goto eadddev; |
885 | } else { | ||
886 | ret = icl->add_device(icl, &icd->dev); | ||
887 | if (ret < 0) | ||
888 | goto eadddev; | ||
859 | } | 889 | } |
860 | 890 | ||
861 | mutex_lock(&icd->video_lock); | 891 | ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, icd->vdev->minor); |
862 | 892 | if (ret < 0) { | |
863 | /* We only call ->add() here to activate and probe the camera. | 893 | dev_err(&icd->dev, "video_register_device failed: %d\n", ret); |
864 | * We shall ->remove() and deactivate it immediately afterwards. */ | 894 | goto evidregd; |
865 | ret = ici->ops->add(icd); | 895 | } |
866 | if (ret < 0) | ||
867 | goto eiadd; | ||
868 | |||
869 | ret = icd->ops->probe(icd); | ||
870 | if (ret >= 0) { | ||
871 | const struct v4l2_queryctrl *qctrl; | ||
872 | 896 | ||
873 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); | 897 | /* Do we have to sysfs_remove_link() before device_unregister()? */ |
874 | icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; | 898 | if (to_soc_camera_control(icd) && |
875 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); | 899 | sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, |
876 | icd->exposure = qctrl ? qctrl->default_value : | 900 | "control")) |
877 | (unsigned short)~0; | 901 | dev_warn(&icd->dev, "Failed creating the control symlink\n"); |
878 | 902 | ||
879 | ret = soc_camera_init_user_formats(icd); | ||
880 | if (ret < 0) { | ||
881 | if (icd->ops->remove) | ||
882 | icd->ops->remove(icd); | ||
883 | goto eiufmt; | ||
884 | } | ||
885 | 903 | ||
886 | icd->height = DEFAULT_HEIGHT; | 904 | return 0; |
887 | icd->width = DEFAULT_WIDTH; | ||
888 | icd->field = V4L2_FIELD_ANY; | ||
889 | } | ||
890 | 905 | ||
891 | eiufmt: | 906 | evidregd: |
892 | ici->ops->remove(icd); | 907 | if (icl->board_info) |
893 | eiadd: | 908 | soc_camera_free_i2c(icd); |
894 | mutex_unlock(&icd->video_lock); | 909 | else |
895 | module_put(ici->ops->owner); | 910 | icl->del_device(icl); |
896 | emgi: | 911 | eadddev: |
897 | module_put(icd->ops->owner); | 912 | video_device_release(icd->vdev); |
898 | emgd: | 913 | evdc: |
899 | return ret; | 914 | return ret; |
900 | } | 915 | } |
901 | 916 | ||
@@ -904,13 +919,22 @@ emgd: | |||
904 | static int soc_camera_remove(struct device *dev) | 919 | static int soc_camera_remove(struct device *dev) |
905 | { | 920 | { |
906 | struct soc_camera_device *icd = to_soc_camera_dev(dev); | 921 | struct soc_camera_device *icd = to_soc_camera_dev(dev); |
922 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
923 | struct video_device *vdev = icd->vdev; | ||
907 | 924 | ||
908 | mutex_lock(&icd->video_lock); | 925 | BUG_ON(!dev->parent); |
909 | if (icd->ops->remove) | ||
910 | icd->ops->remove(icd); | ||
911 | mutex_unlock(&icd->video_lock); | ||
912 | 926 | ||
913 | soc_camera_free_user_formats(icd); | 927 | if (vdev) { |
928 | mutex_lock(&icd->video_lock); | ||
929 | video_unregister_device(vdev); | ||
930 | icd->vdev = NULL; | ||
931 | mutex_unlock(&icd->video_lock); | ||
932 | } | ||
933 | |||
934 | if (icl->board_info) | ||
935 | soc_camera_free_i2c(icd); | ||
936 | else | ||
937 | icl->del_device(icl); | ||
914 | 938 | ||
915 | return 0; | 939 | return 0; |
916 | } | 940 | } |
@@ -1005,10 +1029,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) | |||
1005 | 1029 | ||
1006 | list_for_each_entry(icd, &devices, list) { | 1030 | list_for_each_entry(icd, &devices, list) { |
1007 | if (icd->dev.parent == ici->dev) { | 1031 | if (icd->dev.parent == ici->dev) { |
1032 | /* The bus->remove will be called */ | ||
1008 | device_unregister(&icd->dev); | 1033 | device_unregister(&icd->dev); |
1009 | /* Not before device_unregister(), .remove | 1034 | /* Not before device_unregister(), .remove |
1010 | * needs parent to call ici->ops->remove() */ | 1035 | * needs parent to call ici->ops->remove() */ |
1011 | icd->dev.parent = NULL; | 1036 | icd->dev.parent = NULL; |
1037 | |||
1038 | /* If the host module is loaded again, device_register() | ||
1039 | * would complain "already initialised" */ | ||
1012 | memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); | 1040 | memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); |
1013 | } | 1041 | } |
1014 | } | 1042 | } |
@@ -1020,26 +1048,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) | |||
1020 | EXPORT_SYMBOL(soc_camera_host_unregister); | 1048 | EXPORT_SYMBOL(soc_camera_host_unregister); |
1021 | 1049 | ||
1022 | /* Image capture device */ | 1050 | /* Image capture device */ |
1023 | int soc_camera_device_register(struct soc_camera_device *icd) | 1051 | static int soc_camera_device_register(struct soc_camera_device *icd) |
1024 | { | 1052 | { |
1025 | struct soc_camera_device *ix; | 1053 | struct soc_camera_device *ix; |
1026 | int num = -1, i; | 1054 | int num = -1, i; |
1027 | 1055 | ||
1028 | if (!icd || !icd->ops || | ||
1029 | !icd->ops->probe || | ||
1030 | !icd->ops->init || | ||
1031 | !icd->ops->release || | ||
1032 | !icd->ops->start_capture || | ||
1033 | !icd->ops->stop_capture || | ||
1034 | !icd->ops->set_crop || | ||
1035 | !icd->ops->set_fmt || | ||
1036 | !icd->ops->try_fmt || | ||
1037 | !icd->ops->query_bus_param || | ||
1038 | !icd->ops->set_bus_param) | ||
1039 | return -EINVAL; | ||
1040 | |||
1041 | for (i = 0; i < 256 && num < 0; i++) { | 1056 | for (i = 0; i < 256 && num < 0; i++) { |
1042 | num = i; | 1057 | num = i; |
1058 | /* Check if this index is available on this interface */ | ||
1043 | list_for_each_entry(ix, &devices, list) { | 1059 | list_for_each_entry(ix, &devices, list) { |
1044 | if (ix->iface == icd->iface && ix->devnum == i) { | 1060 | if (ix->iface == icd->iface && ix->devnum == i) { |
1045 | num = -1; | 1061 | num = -1; |
@@ -1061,21 +1077,15 @@ int soc_camera_device_register(struct soc_camera_device *icd) | |||
1061 | icd->host_priv = NULL; | 1077 | icd->host_priv = NULL; |
1062 | mutex_init(&icd->video_lock); | 1078 | mutex_init(&icd->video_lock); |
1063 | 1079 | ||
1064 | return scan_add_device(icd); | 1080 | list_add_tail(&icd->list, &devices); |
1081 | |||
1082 | return 0; | ||
1065 | } | 1083 | } |
1066 | EXPORT_SYMBOL(soc_camera_device_register); | ||
1067 | 1084 | ||
1068 | void soc_camera_device_unregister(struct soc_camera_device *icd) | 1085 | static void soc_camera_device_unregister(struct soc_camera_device *icd) |
1069 | { | 1086 | { |
1070 | mutex_lock(&list_lock); | ||
1071 | list_del(&icd->list); | 1087 | list_del(&icd->list); |
1072 | |||
1073 | /* The bus->remove will be eventually called */ | ||
1074 | if (icd->dev.parent) | ||
1075 | device_unregister(&icd->dev); | ||
1076 | mutex_unlock(&list_lock); | ||
1077 | } | 1088 | } |
1078 | EXPORT_SYMBOL(soc_camera_device_unregister); | ||
1079 | 1089 | ||
1080 | static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { | 1090 | static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { |
1081 | .vidioc_querycap = soc_camera_querycap, | 1091 | .vidioc_querycap = soc_camera_querycap, |
@@ -1106,22 +1116,13 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { | |||
1106 | #endif | 1116 | #endif |
1107 | }; | 1117 | }; |
1108 | 1118 | ||
1109 | /* | 1119 | static int video_dev_create(struct soc_camera_device *icd) |
1110 | * Usually called from the struct soc_camera_ops .probe() method, i.e., from | ||
1111 | * soc_camera_probe() above with .video_lock held | ||
1112 | */ | ||
1113 | int soc_camera_video_start(struct soc_camera_device *icd) | ||
1114 | { | 1120 | { |
1115 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1121 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
1116 | int err = -ENOMEM; | 1122 | struct video_device *vdev = video_device_alloc(); |
1117 | struct video_device *vdev; | ||
1118 | 1123 | ||
1119 | if (!icd->dev.parent) | ||
1120 | return -ENODEV; | ||
1121 | |||
1122 | vdev = video_device_alloc(); | ||
1123 | if (!vdev) | 1124 | if (!vdev) |
1124 | goto evidallocd; | 1125 | return -ENOMEM; |
1125 | dev_dbg(ici->dev, "Allocated video_device %p\n", vdev); | 1126 | dev_dbg(ici->dev, "Allocated video_device %p\n", vdev); |
1126 | 1127 | ||
1127 | strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); | 1128 | strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); |
@@ -1132,118 +1133,110 @@ int soc_camera_video_start(struct soc_camera_device *icd) | |||
1132 | vdev->ioctl_ops = &soc_camera_ioctl_ops; | 1133 | vdev->ioctl_ops = &soc_camera_ioctl_ops; |
1133 | vdev->release = video_device_release; | 1134 | vdev->release = video_device_release; |
1134 | vdev->minor = -1; | 1135 | vdev->minor = -1; |
1135 | vdev->tvnorms = V4L2_STD_UNKNOWN, | 1136 | vdev->tvnorms = V4L2_STD_UNKNOWN; |
1136 | 1137 | ||
1137 | err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); | ||
1138 | if (err < 0) { | ||
1139 | dev_err(vdev->parent, "video_register_device failed\n"); | ||
1140 | goto evidregd; | ||
1141 | } | ||
1142 | icd->vdev = vdev; | 1138 | icd->vdev = vdev; |
1143 | 1139 | ||
1144 | return 0; | 1140 | return 0; |
1141 | } | ||
1145 | 1142 | ||
1146 | evidregd: | 1143 | /* |
1147 | video_device_release(vdev); | 1144 | * Usually called from the struct soc_camera_ops .probe() method, i.e., from |
1148 | evidallocd: | 1145 | * soc_camera_probe() above with .video_lock held |
1149 | return err; | 1146 | */ |
1147 | int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev) | ||
1148 | { | ||
1149 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
1150 | const struct v4l2_queryctrl *qctrl; | ||
1151 | |||
1152 | if (!icd->dev.parent) | ||
1153 | return -ENODEV; | ||
1154 | |||
1155 | if (!icd->ops || | ||
1156 | !icd->ops->init || | ||
1157 | !icd->ops->release || | ||
1158 | !icd->ops->start_capture || | ||
1159 | !icd->ops->stop_capture || | ||
1160 | !icd->ops->set_fmt || | ||
1161 | !icd->ops->try_fmt || | ||
1162 | !icd->ops->query_bus_param || | ||
1163 | !icd->ops->set_bus_param) | ||
1164 | return -EINVAL; | ||
1165 | |||
1166 | /* See comment in soc_camera_probe() */ | ||
1167 | dev_set_drvdata(&icd->dev, dev); | ||
1168 | |||
1169 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); | ||
1170 | icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; | ||
1171 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); | ||
1172 | icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; | ||
1173 | |||
1174 | return ici->ops->add(icd); | ||
1150 | } | 1175 | } |
1151 | EXPORT_SYMBOL(soc_camera_video_start); | 1176 | EXPORT_SYMBOL(soc_camera_video_start); |
1152 | 1177 | ||
1153 | /* Called from client .remove() methods with .video_lock held */ | 1178 | /* Called from client .remove() methods with .video_lock held */ |
1154 | void soc_camera_video_stop(struct soc_camera_device *icd) | 1179 | void soc_camera_video_stop(struct soc_camera_device *icd) |
1155 | { | 1180 | { |
1156 | struct video_device *vdev = icd->vdev; | 1181 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
1157 | 1182 | ||
1158 | dev_dbg(&icd->dev, "%s\n", __func__); | 1183 | dev_dbg(&icd->dev, "%s\n", __func__); |
1159 | 1184 | ||
1160 | if (!icd->dev.parent || !vdev) | 1185 | ici->ops->remove(icd); |
1161 | return; | ||
1162 | |||
1163 | video_unregister_device(vdev); | ||
1164 | icd->vdev = NULL; | ||
1165 | } | 1186 | } |
1166 | EXPORT_SYMBOL(soc_camera_video_stop); | 1187 | EXPORT_SYMBOL(soc_camera_video_stop); |
1167 | 1188 | ||
1168 | #ifdef CONFIG_I2C_BOARDINFO | 1189 | static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) |
1169 | static int soc_camera_init_i2c(struct platform_device *pdev, | ||
1170 | struct soc_camera_link *icl) | ||
1171 | { | 1190 | { |
1172 | struct i2c_client *client; | 1191 | struct soc_camera_link *icl = pdev->dev.platform_data; |
1173 | struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); | 1192 | struct soc_camera_device *icd; |
1174 | int ret; | 1193 | int ret; |
1175 | 1194 | ||
1176 | if (!adap) { | 1195 | if (!icl) |
1177 | ret = -ENODEV; | 1196 | return -EINVAL; |
1178 | dev_err(&pdev->dev, "Cannot get adapter #%d. No driver?\n", | ||
1179 | icl->i2c_adapter_id); | ||
1180 | goto ei2cga; | ||
1181 | } | ||
1182 | 1197 | ||
1183 | icl->board_info->platform_data = icl; | 1198 | icd = kzalloc(sizeof(*icd), GFP_KERNEL); |
1184 | client = i2c_new_device(adap, icl->board_info); | 1199 | if (!icd) |
1185 | if (!client) { | 1200 | return -ENOMEM; |
1186 | ret = -ENOMEM; | ||
1187 | goto ei2cnd; | ||
1188 | } | ||
1189 | 1201 | ||
1190 | platform_set_drvdata(pdev, client); | 1202 | icd->iface = icl->bus_id; |
1203 | platform_set_drvdata(pdev, icd); | ||
1204 | icd->dev.platform_data = icl; | ||
1191 | 1205 | ||
1192 | return 0; | 1206 | ret = soc_camera_device_register(icd); |
1193 | ei2cnd: | 1207 | if (ret < 0) |
1194 | i2c_put_adapter(adap); | 1208 | goto escdevreg; |
1195 | ei2cga: | ||
1196 | return ret; | ||
1197 | } | ||
1198 | 1209 | ||
1199 | static void soc_camera_free_i2c(struct platform_device *pdev) | 1210 | return 0; |
1200 | { | ||
1201 | struct i2c_client *client = platform_get_drvdata(pdev); | ||
1202 | 1211 | ||
1203 | if (!client) | 1212 | escdevreg: |
1204 | return; | 1213 | kfree(icd); |
1205 | 1214 | ||
1206 | i2c_unregister_device(client); | 1215 | return ret; |
1207 | i2c_put_adapter(client->adapter); | ||
1208 | } | 1216 | } |
1209 | #else | ||
1210 | #define soc_camera_init_i2c(d, icl) (-ENODEV) | ||
1211 | #define soc_camera_free_i2c(d) do {} while (0) | ||
1212 | #endif | ||
1213 | 1217 | ||
1214 | static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) | 1218 | /* Only called on rmmod for each platform device, since they are not |
1219 | * hot-pluggable. Now we know, that all our users - hosts and devices have | ||
1220 | * been unloaded already */ | ||
1221 | static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) | ||
1215 | { | 1222 | { |
1216 | struct soc_camera_link *icl = pdev->dev.platform_data; | 1223 | struct soc_camera_device *icd = platform_get_drvdata(pdev); |
1217 | 1224 | ||
1218 | if (!icl) | 1225 | if (!icd) |
1219 | return -EINVAL; | 1226 | return -EINVAL; |
1220 | 1227 | ||
1221 | if (icl->board_info) | 1228 | soc_camera_device_unregister(icd); |
1222 | return soc_camera_init_i2c(pdev, icl); | ||
1223 | else if (!icl->add_device || !icl->del_device) | ||
1224 | return -EINVAL; | ||
1225 | 1229 | ||
1226 | /* &pdev->dev will become &icd->dev */ | 1230 | kfree(icd); |
1227 | return icl->add_device(icl, &pdev->dev); | ||
1228 | } | ||
1229 | 1231 | ||
1230 | static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) | ||
1231 | { | ||
1232 | struct soc_camera_link *icl = pdev->dev.platform_data; | ||
1233 | |||
1234 | if (icl->board_info) | ||
1235 | soc_camera_free_i2c(pdev); | ||
1236 | else | ||
1237 | icl->del_device(icl); | ||
1238 | return 0; | 1232 | return 0; |
1239 | } | 1233 | } |
1240 | 1234 | ||
1241 | static struct platform_driver __refdata soc_camera_pdrv = { | 1235 | static struct platform_driver __refdata soc_camera_pdrv = { |
1242 | .probe = soc_camera_pdrv_probe, | 1236 | .remove = __devexit_p(soc_camera_pdrv_remove), |
1243 | .remove = __devexit_p(soc_camera_pdrv_remove), | 1237 | .driver = { |
1244 | .driver = { | 1238 | .name = "soc-camera-pdrv", |
1245 | .name = "soc-camera-pdrv", | 1239 | .owner = THIS_MODULE, |
1246 | .owner = THIS_MODULE, | ||
1247 | }, | 1240 | }, |
1248 | }; | 1241 | }; |
1249 | 1242 | ||
@@ -1256,7 +1249,7 @@ static int __init soc_camera_init(void) | |||
1256 | if (ret) | 1249 | if (ret) |
1257 | goto edrvr; | 1250 | goto edrvr; |
1258 | 1251 | ||
1259 | ret = platform_driver_register(&soc_camera_pdrv); | 1252 | ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe); |
1260 | if (ret) | 1253 | if (ret) |
1261 | goto epdr; | 1254 | goto epdr; |
1262 | 1255 | ||
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c index c48676356ab7..d84c134f8d59 100644 --- a/drivers/media/video/soc_camera_platform.c +++ b/drivers/media/video/soc_camera_platform.c | |||
@@ -21,35 +21,32 @@ | |||
21 | #include <media/soc_camera_platform.h> | 21 | #include <media/soc_camera_platform.h> |
22 | 22 | ||
23 | struct soc_camera_platform_priv { | 23 | struct soc_camera_platform_priv { |
24 | struct soc_camera_platform_info *info; | ||
25 | struct soc_camera_device icd; | ||
26 | struct soc_camera_data_format format; | 24 | struct soc_camera_data_format format; |
27 | }; | 25 | }; |
28 | 26 | ||
29 | static struct soc_camera_platform_info * | 27 | static struct soc_camera_platform_info * |
30 | soc_camera_platform_get_info(struct soc_camera_device *icd) | 28 | soc_camera_platform_get_info(struct soc_camera_device *icd) |
31 | { | 29 | { |
32 | struct soc_camera_platform_priv *priv; | 30 | struct platform_device *pdev = to_platform_device(dev_get_drvdata(&icd->dev)); |
33 | priv = container_of(icd, struct soc_camera_platform_priv, icd); | 31 | return pdev->dev.platform_data; |
34 | return priv->info; | ||
35 | } | 32 | } |
36 | 33 | ||
37 | static int soc_camera_platform_init(struct soc_camera_device *icd) | 34 | static int soc_camera_platform_init(struct soc_camera_device *icd) |
38 | { | 35 | { |
39 | struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); | 36 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
40 | 37 | ||
41 | if (p->power) | 38 | if (icl->power) |
42 | p->power(1); | 39 | icl->power(dev_get_drvdata(&icd->dev), 1); |
43 | 40 | ||
44 | return 0; | 41 | return 0; |
45 | } | 42 | } |
46 | 43 | ||
47 | static int soc_camera_platform_release(struct soc_camera_device *icd) | 44 | static int soc_camera_platform_release(struct soc_camera_device *icd) |
48 | { | 45 | { |
49 | struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); | 46 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
50 | 47 | ||
51 | if (p->power) | 48 | if (icl->power) |
52 | p->power(0); | 49 | icl->power(dev_get_drvdata(&icd->dev), 0); |
53 | 50 | ||
54 | return 0; | 51 | return 0; |
55 | } | 52 | } |
@@ -102,31 +99,29 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd, | |||
102 | return 0; | 99 | return 0; |
103 | } | 100 | } |
104 | 101 | ||
105 | static int soc_camera_platform_video_probe(struct soc_camera_device *icd) | 102 | static int soc_camera_platform_video_probe(struct soc_camera_device *icd, |
103 | struct platform_device *pdev) | ||
106 | { | 104 | { |
107 | struct soc_camera_platform_priv *priv; | 105 | struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); |
108 | priv = container_of(icd, struct soc_camera_platform_priv, icd); | 106 | struct soc_camera_platform_info *p = pdev->dev.platform_data; |
107 | int ret; | ||
109 | 108 | ||
110 | priv->format.name = priv->info->format_name; | 109 | priv->format.name = p->format_name; |
111 | priv->format.depth = priv->info->format_depth; | 110 | priv->format.depth = p->format_depth; |
112 | priv->format.fourcc = priv->info->format.pixelformat; | 111 | priv->format.fourcc = p->format.pixelformat; |
113 | priv->format.colorspace = priv->info->format.colorspace; | 112 | priv->format.colorspace = p->format.colorspace; |
114 | 113 | ||
115 | icd->formats = &priv->format; | 114 | icd->formats = &priv->format; |
116 | icd->num_formats = 1; | 115 | icd->num_formats = 1; |
117 | 116 | ||
118 | return soc_camera_video_start(icd); | 117 | /* ..._video_start() does dev_set_drvdata(&icd->dev, &pdev->dev) */ |
119 | } | 118 | ret = soc_camera_video_start(icd, &pdev->dev); |
120 | |||
121 | static void soc_camera_platform_video_remove(struct soc_camera_device *icd) | ||
122 | { | ||
123 | soc_camera_video_stop(icd); | 119 | soc_camera_video_stop(icd); |
120 | return ret; | ||
124 | } | 121 | } |
125 | 122 | ||
126 | static struct soc_camera_ops soc_camera_platform_ops = { | 123 | static struct soc_camera_ops soc_camera_platform_ops = { |
127 | .owner = THIS_MODULE, | 124 | .owner = THIS_MODULE, |
128 | .probe = soc_camera_platform_video_probe, | ||
129 | .remove = soc_camera_platform_video_remove, | ||
130 | .init = soc_camera_platform_init, | 125 | .init = soc_camera_platform_init, |
131 | .release = soc_camera_platform_release, | 126 | .release = soc_camera_platform_release, |
132 | .start_capture = soc_camera_platform_start_capture, | 127 | .start_capture = soc_camera_platform_start_capture, |
@@ -141,11 +136,10 @@ static struct soc_camera_ops soc_camera_platform_ops = { | |||
141 | static int soc_camera_platform_probe(struct platform_device *pdev) | 136 | static int soc_camera_platform_probe(struct platform_device *pdev) |
142 | { | 137 | { |
143 | struct soc_camera_platform_priv *priv; | 138 | struct soc_camera_platform_priv *priv; |
144 | struct soc_camera_platform_info *p; | 139 | struct soc_camera_platform_info *p = pdev->dev.platform_data; |
145 | struct soc_camera_device *icd; | 140 | struct soc_camera_device *icd; |
146 | int ret; | 141 | int ret; |
147 | 142 | ||
148 | p = pdev->dev.platform_data; | ||
149 | if (!p) | 143 | if (!p) |
150 | return -EINVAL; | 144 | return -EINVAL; |
151 | 145 | ||
@@ -153,31 +147,40 @@ static int soc_camera_platform_probe(struct platform_device *pdev) | |||
153 | if (!priv) | 147 | if (!priv) |
154 | return -ENOMEM; | 148 | return -ENOMEM; |
155 | 149 | ||
156 | priv->info = p; | ||
157 | platform_set_drvdata(pdev, priv); | 150 | platform_set_drvdata(pdev, priv); |
158 | 151 | ||
159 | icd = &priv->icd; | 152 | icd = to_soc_camera_dev(p->dev); |
153 | if (!icd) | ||
154 | goto enoicd; | ||
155 | |||
160 | icd->ops = &soc_camera_platform_ops; | 156 | icd->ops = &soc_camera_platform_ops; |
161 | icd->control = &pdev->dev; | 157 | dev_set_drvdata(&icd->dev, &pdev->dev); |
162 | icd->width_min = 0; | 158 | icd->width_min = 0; |
163 | icd->width_max = priv->info->format.width; | 159 | icd->width_max = p->format.width; |
164 | icd->height_min = 0; | 160 | icd->height_min = 0; |
165 | icd->height_max = priv->info->format.height; | 161 | icd->height_max = p->format.height; |
166 | icd->y_skip_top = 0; | 162 | icd->y_skip_top = 0; |
167 | icd->iface = priv->info->iface; | ||
168 | 163 | ||
169 | ret = soc_camera_device_register(icd); | 164 | ret = soc_camera_platform_video_probe(icd, pdev); |
170 | if (ret) | 165 | if (ret) { |
166 | icd->ops = NULL; | ||
171 | kfree(priv); | 167 | kfree(priv); |
168 | } | ||
172 | 169 | ||
173 | return ret; | 170 | return ret; |
171 | |||
172 | enoicd: | ||
173 | kfree(priv); | ||
174 | return -EINVAL; | ||
174 | } | 175 | } |
175 | 176 | ||
176 | static int soc_camera_platform_remove(struct platform_device *pdev) | 177 | static int soc_camera_platform_remove(struct platform_device *pdev) |
177 | { | 178 | { |
178 | struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); | 179 | struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); |
180 | struct soc_camera_platform_info *p = pdev->dev.platform_data; | ||
181 | struct soc_camera_device *icd = to_soc_camera_dev(p->dev); | ||
179 | 182 | ||
180 | soc_camera_device_unregister(&priv->icd); | 183 | icd->ops = NULL; |
181 | kfree(priv); | 184 | kfree(priv); |
182 | return 0; | 185 | return 0; |
183 | } | 186 | } |
@@ -206,3 +209,4 @@ module_exit(soc_camera_platform_module_exit); | |||
206 | MODULE_DESCRIPTION("SoC Camera Platform driver"); | 209 | MODULE_DESCRIPTION("SoC Camera Platform driver"); |
207 | MODULE_AUTHOR("Magnus Damm"); | 210 | MODULE_AUTHOR("Magnus Damm"); |
208 | MODULE_LICENSE("GPL v2"); | 211 | MODULE_LICENSE("GPL v2"); |
212 | MODULE_ALIAS("platform:soc_camera_platform"); | ||
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index aa5065ea09ed..d780a509faa9 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c | |||
@@ -224,8 +224,6 @@ struct tw9910_hsync_ctrl { | |||
224 | 224 | ||
225 | struct tw9910_priv { | 225 | struct tw9910_priv { |
226 | struct tw9910_video_info *info; | 226 | struct tw9910_video_info *info; |
227 | struct i2c_client *client; | ||
228 | struct soc_camera_device icd; | ||
229 | const struct tw9910_scale_ctrl *scale; | 227 | const struct tw9910_scale_ctrl *scale; |
230 | }; | 228 | }; |
231 | 229 | ||
@@ -511,35 +509,38 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height) | |||
511 | */ | 509 | */ |
512 | static int tw9910_init(struct soc_camera_device *icd) | 510 | static int tw9910_init(struct soc_camera_device *icd) |
513 | { | 511 | { |
514 | struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); | 512 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
513 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
515 | int ret = 0; | 514 | int ret = 0; |
516 | 515 | ||
517 | if (priv->info->link.power) { | 516 | if (icl->power) { |
518 | ret = priv->info->link.power(&priv->client->dev, 1); | 517 | ret = icl->power(&client->dev, 1); |
519 | if (ret < 0) | 518 | if (ret < 0) |
520 | return ret; | 519 | return ret; |
521 | } | 520 | } |
522 | 521 | ||
523 | if (priv->info->link.reset) | 522 | if (icl->reset) |
524 | ret = priv->info->link.reset(&priv->client->dev); | 523 | ret = icl->reset(&client->dev); |
525 | 524 | ||
526 | return ret; | 525 | return ret; |
527 | } | 526 | } |
528 | 527 | ||
529 | static int tw9910_release(struct soc_camera_device *icd) | 528 | static int tw9910_release(struct soc_camera_device *icd) |
530 | { | 529 | { |
531 | struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); | 530 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
531 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
532 | int ret = 0; | 532 | int ret = 0; |
533 | 533 | ||
534 | if (priv->info->link.power) | 534 | if (icl->power) |
535 | ret = priv->info->link.power(&priv->client->dev, 0); | 535 | ret = icl->power(&client->dev, 0); |
536 | 536 | ||
537 | return ret; | 537 | return ret; |
538 | } | 538 | } |
539 | 539 | ||
540 | static int tw9910_start_capture(struct soc_camera_device *icd) | 540 | static int tw9910_start_capture(struct soc_camera_device *icd) |
541 | { | 541 | { |
542 | struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); | 542 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
543 | struct tw9910_priv *priv = i2c_get_clientdata(client); | ||
543 | 544 | ||
544 | if (!priv->scale) { | 545 | if (!priv->scale) { |
545 | dev_err(&icd->dev, "norm select error\n"); | 546 | dev_err(&icd->dev, "norm select error\n"); |
@@ -567,8 +568,9 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd, | |||
567 | 568 | ||
568 | static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) | 569 | static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) |
569 | { | 570 | { |
570 | struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); | 571 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
571 | struct soc_camera_link *icl = priv->client->dev.platform_data; | 572 | struct tw9910_priv *priv = i2c_get_clientdata(client); |
573 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
572 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | | 574 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | |
573 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | | 575 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | |
574 | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; | 576 | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; |
@@ -610,13 +612,13 @@ static int tw9910_enum_input(struct soc_camera_device *icd, | |||
610 | static int tw9910_get_register(struct soc_camera_device *icd, | 612 | static int tw9910_get_register(struct soc_camera_device *icd, |
611 | struct v4l2_dbg_register *reg) | 613 | struct v4l2_dbg_register *reg) |
612 | { | 614 | { |
613 | struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); | 615 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
614 | int ret; | 616 | int ret; |
615 | 617 | ||
616 | if (reg->reg > 0xff) | 618 | if (reg->reg > 0xff) |
617 | return -EINVAL; | 619 | return -EINVAL; |
618 | 620 | ||
619 | ret = i2c_smbus_read_byte_data(priv->client, reg->reg); | 621 | ret = i2c_smbus_read_byte_data(client, reg->reg); |
620 | if (ret < 0) | 622 | if (ret < 0) |
621 | return ret; | 623 | return ret; |
622 | 624 | ||
@@ -631,20 +633,21 @@ static int tw9910_get_register(struct soc_camera_device *icd, | |||
631 | static int tw9910_set_register(struct soc_camera_device *icd, | 633 | static int tw9910_set_register(struct soc_camera_device *icd, |
632 | struct v4l2_dbg_register *reg) | 634 | struct v4l2_dbg_register *reg) |
633 | { | 635 | { |
634 | struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); | 636 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
635 | 637 | ||
636 | if (reg->reg > 0xff || | 638 | if (reg->reg > 0xff || |
637 | reg->val > 0xff) | 639 | reg->val > 0xff) |
638 | return -EINVAL; | 640 | return -EINVAL; |
639 | 641 | ||
640 | return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); | 642 | return i2c_smbus_write_byte_data(client, reg->reg, reg->val); |
641 | } | 643 | } |
642 | #endif | 644 | #endif |
643 | 645 | ||
644 | static int tw9910_set_crop(struct soc_camera_device *icd, | 646 | static int tw9910_set_crop(struct soc_camera_device *icd, |
645 | struct v4l2_rect *rect) | 647 | struct v4l2_rect *rect) |
646 | { | 648 | { |
647 | struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); | 649 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
650 | struct tw9910_priv *priv = i2c_get_clientdata(client); | ||
648 | int ret = -EINVAL; | 651 | int ret = -EINVAL; |
649 | u8 val; | 652 | u8 val; |
650 | 653 | ||
@@ -658,8 +661,8 @@ static int tw9910_set_crop(struct soc_camera_device *icd, | |||
658 | /* | 661 | /* |
659 | * reset hardware | 662 | * reset hardware |
660 | */ | 663 | */ |
661 | tw9910_reset(priv->client); | 664 | tw9910_reset(client); |
662 | ret = tw9910_write_array(priv->client, tw9910_default_regs); | 665 | ret = tw9910_write_array(client, tw9910_default_regs); |
663 | if (ret < 0) | 666 | if (ret < 0) |
664 | goto tw9910_set_fmt_error; | 667 | goto tw9910_set_fmt_error; |
665 | 668 | ||
@@ -670,7 +673,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, | |||
670 | if (SOCAM_DATAWIDTH_16 == priv->info->buswidth) | 673 | if (SOCAM_DATAWIDTH_16 == priv->info->buswidth) |
671 | val = LEN; | 674 | val = LEN; |
672 | 675 | ||
673 | ret = tw9910_mask_set(priv->client, OPFORM, LEN, val); | 676 | ret = tw9910_mask_set(client, OPFORM, LEN, val); |
674 | if (ret < 0) | 677 | if (ret < 0) |
675 | goto tw9910_set_fmt_error; | 678 | goto tw9910_set_fmt_error; |
676 | 679 | ||
@@ -698,28 +701,28 @@ static int tw9910_set_crop(struct soc_camera_device *icd, | |||
698 | val = 0; | 701 | val = 0; |
699 | } | 702 | } |
700 | 703 | ||
701 | ret = tw9910_mask_set(priv->client, VBICNTL, RTSEL_MASK, val); | 704 | ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val); |
702 | if (ret < 0) | 705 | if (ret < 0) |
703 | goto tw9910_set_fmt_error; | 706 | goto tw9910_set_fmt_error; |
704 | 707 | ||
705 | /* | 708 | /* |
706 | * set scale | 709 | * set scale |
707 | */ | 710 | */ |
708 | ret = tw9910_set_scale(priv->client, priv->scale); | 711 | ret = tw9910_set_scale(client, priv->scale); |
709 | if (ret < 0) | 712 | if (ret < 0) |
710 | goto tw9910_set_fmt_error; | 713 | goto tw9910_set_fmt_error; |
711 | 714 | ||
712 | /* | 715 | /* |
713 | * set cropping | 716 | * set cropping |
714 | */ | 717 | */ |
715 | ret = tw9910_set_cropping(priv->client, &tw9910_cropping_ctrl); | 718 | ret = tw9910_set_cropping(client, &tw9910_cropping_ctrl); |
716 | if (ret < 0) | 719 | if (ret < 0) |
717 | goto tw9910_set_fmt_error; | 720 | goto tw9910_set_fmt_error; |
718 | 721 | ||
719 | /* | 722 | /* |
720 | * set hsync | 723 | * set hsync |
721 | */ | 724 | */ |
722 | ret = tw9910_set_hsync(priv->client, &tw9910_hsync_ctrl); | 725 | ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl); |
723 | if (ret < 0) | 726 | if (ret < 0) |
724 | goto tw9910_set_fmt_error; | 727 | goto tw9910_set_fmt_error; |
725 | 728 | ||
@@ -727,7 +730,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, | |||
727 | 730 | ||
728 | tw9910_set_fmt_error: | 731 | tw9910_set_fmt_error: |
729 | 732 | ||
730 | tw9910_reset(priv->client); | 733 | tw9910_reset(client); |
731 | priv->scale = NULL; | 734 | priv->scale = NULL; |
732 | 735 | ||
733 | return ret; | 736 | return ret; |
@@ -784,9 +787,10 @@ static int tw9910_try_fmt(struct soc_camera_device *icd, | |||
784 | return 0; | 787 | return 0; |
785 | } | 788 | } |
786 | 789 | ||
787 | static int tw9910_video_probe(struct soc_camera_device *icd) | 790 | static int tw9910_video_probe(struct soc_camera_device *icd, |
791 | struct i2c_client *client) | ||
788 | { | 792 | { |
789 | struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); | 793 | struct tw9910_priv *priv = i2c_get_clientdata(client); |
790 | s32 val; | 794 | s32 val; |
791 | int ret; | 795 | int ret; |
792 | 796 | ||
@@ -810,10 +814,18 @@ static int tw9910_video_probe(struct soc_camera_device *icd) | |||
810 | icd->formats = tw9910_color_fmt; | 814 | icd->formats = tw9910_color_fmt; |
811 | icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); | 815 | icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); |
812 | 816 | ||
817 | /* Switch master clock on */ | ||
818 | ret = soc_camera_video_start(icd, &client->dev); | ||
819 | if (ret) | ||
820 | return ret; | ||
821 | |||
813 | /* | 822 | /* |
814 | * check and show Product ID | 823 | * check and show Product ID |
815 | */ | 824 | */ |
816 | val = i2c_smbus_read_byte_data(priv->client, ID); | 825 | val = i2c_smbus_read_byte_data(client, ID); |
826 | |||
827 | soc_camera_video_stop(icd); | ||
828 | |||
817 | if (0x0B != GET_ID(val) || | 829 | if (0x0B != GET_ID(val) || |
818 | 0x00 != GET_ReV(val)) { | 830 | 0x00 != GET_ReV(val)) { |
819 | dev_err(&icd->dev, | 831 | dev_err(&icd->dev, |
@@ -824,25 +836,14 @@ static int tw9910_video_probe(struct soc_camera_device *icd) | |||
824 | dev_info(&icd->dev, | 836 | dev_info(&icd->dev, |
825 | "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val)); | 837 | "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val)); |
826 | 838 | ||
827 | ret = soc_camera_video_start(icd); | ||
828 | if (ret < 0) | ||
829 | return ret; | ||
830 | |||
831 | icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; | 839 | icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; |
832 | icd->vdev->current_norm = V4L2_STD_NTSC; | 840 | icd->vdev->current_norm = V4L2_STD_NTSC; |
833 | 841 | ||
834 | return ret; | 842 | return ret; |
835 | } | 843 | } |
836 | 844 | ||
837 | static void tw9910_video_remove(struct soc_camera_device *icd) | ||
838 | { | ||
839 | soc_camera_video_stop(icd); | ||
840 | } | ||
841 | |||
842 | static struct soc_camera_ops tw9910_ops = { | 845 | static struct soc_camera_ops tw9910_ops = { |
843 | .owner = THIS_MODULE, | 846 | .owner = THIS_MODULE, |
844 | .probe = tw9910_video_probe, | ||
845 | .remove = tw9910_video_remove, | ||
846 | .init = tw9910_init, | 847 | .init = tw9910_init, |
847 | .release = tw9910_release, | 848 | .release = tw9910_release, |
848 | .start_capture = tw9910_start_capture, | 849 | .start_capture = tw9910_start_capture, |
@@ -871,18 +872,25 @@ static int tw9910_probe(struct i2c_client *client, | |||
871 | { | 872 | { |
872 | struct tw9910_priv *priv; | 873 | struct tw9910_priv *priv; |
873 | struct tw9910_video_info *info; | 874 | struct tw9910_video_info *info; |
874 | struct soc_camera_device *icd; | 875 | struct soc_camera_device *icd = client->dev.platform_data; |
876 | struct i2c_adapter *adapter = | ||
877 | to_i2c_adapter(client->dev.parent); | ||
878 | struct soc_camera_link *icl; | ||
875 | const struct tw9910_scale_ctrl *scale; | 879 | const struct tw9910_scale_ctrl *scale; |
876 | int i, ret; | 880 | int i, ret; |
877 | 881 | ||
878 | if (!client->dev.platform_data) | 882 | if (!icd) { |
883 | dev_err(&client->dev, "TW9910: missing soc-camera data!\n"); | ||
879 | return -EINVAL; | 884 | return -EINVAL; |
885 | } | ||
880 | 886 | ||
881 | info = container_of(client->dev.platform_data, | 887 | icl = to_soc_camera_link(icd); |
882 | struct tw9910_video_info, link); | 888 | if (!icl) |
889 | return -EINVAL; | ||
883 | 890 | ||
884 | if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent), | 891 | info = container_of(icl, struct tw9910_video_info, link); |
885 | I2C_FUNC_SMBUS_BYTE_DATA)) { | 892 | |
893 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
886 | dev_err(&client->dev, | 894 | dev_err(&client->dev, |
887 | "I2C-Adapter doesn't support " | 895 | "I2C-Adapter doesn't support " |
888 | "I2C_FUNC_SMBUS_BYTE_DATA\n"); | 896 | "I2C_FUNC_SMBUS_BYTE_DATA\n"); |
@@ -894,12 +902,9 @@ static int tw9910_probe(struct i2c_client *client, | |||
894 | return -ENOMEM; | 902 | return -ENOMEM; |
895 | 903 | ||
896 | priv->info = info; | 904 | priv->info = info; |
897 | priv->client = client; | ||
898 | i2c_set_clientdata(client, priv); | 905 | i2c_set_clientdata(client, priv); |
899 | 906 | ||
900 | icd = &priv->icd; | ||
901 | icd->ops = &tw9910_ops; | 907 | icd->ops = &tw9910_ops; |
902 | icd->control = &client->dev; | ||
903 | icd->iface = info->link.bus_id; | 908 | icd->iface = info->link.bus_id; |
904 | 909 | ||
905 | /* | 910 | /* |
@@ -925,9 +930,9 @@ static int tw9910_probe(struct i2c_client *client, | |||
925 | icd->height_min = min(scale[i].height, icd->height_min); | 930 | icd->height_min = min(scale[i].height, icd->height_min); |
926 | } | 931 | } |
927 | 932 | ||
928 | ret = soc_camera_device_register(icd); | 933 | ret = tw9910_video_probe(icd, client); |
929 | |||
930 | if (ret) { | 934 | if (ret) { |
935 | icd->ops = NULL; | ||
931 | i2c_set_clientdata(client, NULL); | 936 | i2c_set_clientdata(client, NULL); |
932 | kfree(priv); | 937 | kfree(priv); |
933 | } | 938 | } |
@@ -938,8 +943,9 @@ static int tw9910_probe(struct i2c_client *client, | |||
938 | static int tw9910_remove(struct i2c_client *client) | 943 | static int tw9910_remove(struct i2c_client *client) |
939 | { | 944 | { |
940 | struct tw9910_priv *priv = i2c_get_clientdata(client); | 945 | struct tw9910_priv *priv = i2c_get_clientdata(client); |
946 | struct soc_camera_device *icd = client->dev.platform_data; | ||
941 | 947 | ||
942 | soc_camera_device_unregister(&priv->icd); | 948 | icd->ops = NULL; |
943 | i2c_set_clientdata(client, NULL); | 949 | i2c_set_clientdata(client, NULL); |
944 | kfree(priv); | 950 | kfree(priv); |
945 | return 0; | 951 | return 0; |