diff options
| -rw-r--r-- | arch/sh/boards/board-ap325rxa.c | 43 | ||||
| -rw-r--r-- | drivers/media/video/soc_camera.c | 61 | ||||
| -rw-r--r-- | include/media/soc_camera.h | 6 | ||||
| -rw-r--r-- | include/media/soc_camera_platform.h | 2 |
4 files changed, 86 insertions, 26 deletions
diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c index 327d47c25a57..7e2d2de0384d 100644 --- a/arch/sh/boards/board-ap325rxa.c +++ b/arch/sh/boards/board-ap325rxa.c | |||
| @@ -310,6 +310,9 @@ static int camera_set_capture(struct soc_camera_platform_info *info, | |||
| 310 | return ret; | 310 | return ret; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | static int ap325rxa_camera_add(struct soc_camera_link *icl, struct device *dev); | ||
| 314 | static void ap325rxa_camera_del(struct soc_camera_link *icl); | ||
| 315 | |||
| 313 | static struct soc_camera_platform_info camera_info = { | 316 | static struct soc_camera_platform_info camera_info = { |
| 314 | .iface = 0, | 317 | .iface = 0, |
| 315 | .format_name = "UYVY", | 318 | .format_name = "UYVY", |
| @@ -323,6 +326,10 @@ static struct soc_camera_platform_info camera_info = { | |||
| 323 | .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | | 326 | .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | |
| 324 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8, | 327 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8, |
| 325 | .set_capture = camera_set_capture, | 328 | .set_capture = camera_set_capture, |
| 329 | .link = { | ||
| 330 | .add_device = ap325rxa_camera_add, | ||
| 331 | .del_device = ap325rxa_camera_del, | ||
| 332 | }, | ||
| 326 | }; | 333 | }; |
| 327 | 334 | ||
| 328 | static struct platform_device camera_device = { | 335 | static struct platform_device camera_device = { |
| @@ -332,15 +339,20 @@ static struct platform_device camera_device = { | |||
| 332 | }, | 339 | }, |
| 333 | }; | 340 | }; |
| 334 | 341 | ||
| 335 | static int __init camera_setup(void) | 342 | static int ap325rxa_camera_add(struct soc_camera_link *icl, |
| 343 | struct device *dev) | ||
| 336 | { | 344 | { |
| 337 | if (camera_probe() > 0) | 345 | if (icl != &camera_info.link || camera_probe() <= 0) |
| 338 | platform_device_register(&camera_device); | 346 | return -ENODEV; |
| 339 | 347 | ||
| 340 | return 0; | 348 | return platform_device_register(&camera_device); |
| 341 | } | 349 | } |
| 342 | late_initcall(camera_setup); | ||
| 343 | 350 | ||
| 351 | static void ap325rxa_camera_del(struct soc_camera_link *icl) | ||
| 352 | { | ||
| 353 | if (icl == &camera_info.link) | ||
| 354 | platform_device_unregister(&camera_device); | ||
| 355 | } | ||
| 344 | #endif /* CONFIG_I2C */ | 356 | #endif /* CONFIG_I2C */ |
| 345 | 357 | ||
| 346 | static int ov7725_power(struct device *dev, int mode) | 358 | static int ov7725_power(struct device *dev, int mode) |
| @@ -423,11 +435,19 @@ static struct ov772x_camera_info ov7725_info = { | |||
| 423 | }, | 435 | }, |
| 424 | }; | 436 | }; |
| 425 | 437 | ||
| 426 | static struct platform_device ap325rxa_camera = { | 438 | static struct platform_device ap325rxa_camera[] = { |
| 427 | .name = "soc-camera-pdrv", | 439 | { |
| 428 | .id = 0, | 440 | .name = "soc-camera-pdrv", |
| 429 | .dev = { | 441 | .id = 0, |
| 430 | .platform_data = &ov7725_info.link, | 442 | .dev = { |
| 443 | .platform_data = &ov7725_info.link, | ||
| 444 | }, | ||
| 445 | }, { | ||
| 446 | .name = "soc-camera-pdrv", | ||
| 447 | .id = 1, | ||
| 448 | .dev = { | ||
| 449 | .platform_data = &camera_info.link, | ||
| 450 | }, | ||
| 431 | }, | 451 | }, |
| 432 | }; | 452 | }; |
| 433 | 453 | ||
| @@ -438,7 +458,8 @@ static struct platform_device *ap325rxa_devices[] __initdata = { | |||
| 438 | &ceu_device, | 458 | &ceu_device, |
| 439 | &nand_flash_device, | 459 | &nand_flash_device, |
| 440 | &sdcard_cn3_device, | 460 | &sdcard_cn3_device, |
| 441 | &ap325rxa_camera, | 461 | &ap325rxa_camera[0], |
| 462 | &ap325rxa_camera[1], | ||
| 442 | }; | 463 | }; |
| 443 | 464 | ||
| 444 | static struct spi_board_info ap325rxa_spi_devices[] = { | 465 | static struct spi_board_info ap325rxa_spi_devices[] = { |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 9f5ae8167855..0340754e5406 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
| @@ -1165,45 +1165,76 @@ void soc_camera_video_stop(struct soc_camera_device *icd) | |||
| 1165 | } | 1165 | } |
| 1166 | EXPORT_SYMBOL(soc_camera_video_stop); | 1166 | EXPORT_SYMBOL(soc_camera_video_stop); |
| 1167 | 1167 | ||
| 1168 | static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) | 1168 | #ifdef CONFIG_I2C_BOARDINFO |
| 1169 | static int soc_camera_init_i2c(struct platform_device *pdev, | ||
| 1170 | struct soc_camera_link *icl) | ||
| 1169 | { | 1171 | { |
| 1170 | struct soc_camera_link *icl = pdev->dev.platform_data; | ||
| 1171 | struct i2c_adapter *adap; | ||
| 1172 | struct i2c_client *client; | 1172 | struct i2c_client *client; |
| 1173 | struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); | ||
| 1174 | int ret; | ||
| 1173 | 1175 | ||
| 1174 | if (!icl) | ||
| 1175 | return -EINVAL; | ||
| 1176 | |||
| 1177 | adap = i2c_get_adapter(icl->i2c_adapter_id); | ||
| 1178 | if (!adap) { | 1176 | if (!adap) { |
| 1179 | dev_warn(&pdev->dev, "Cannot get adapter #%d. No driver?\n", | 1177 | ret = -ENODEV; |
| 1180 | icl->i2c_adapter_id); | 1178 | dev_err(&pdev->dev, "Cannot get adapter #%d. No driver?\n", |
| 1181 | /* -ENODEV and -ENXIO do not produce an error on probe()... */ | 1179 | icl->i2c_adapter_id); |
| 1182 | return -ENOENT; | 1180 | goto ei2cga; |
| 1183 | } | 1181 | } |
| 1184 | 1182 | ||
| 1185 | icl->board_info->platform_data = icl; | 1183 | icl->board_info->platform_data = icl; |
| 1186 | client = i2c_new_device(adap, icl->board_info); | 1184 | client = i2c_new_device(adap, icl->board_info); |
| 1187 | if (!client) { | 1185 | if (!client) { |
| 1188 | i2c_put_adapter(adap); | 1186 | ret = -ENOMEM; |
| 1189 | return -ENOMEM; | 1187 | goto ei2cnd; |
| 1190 | } | 1188 | } |
| 1191 | 1189 | ||
| 1192 | platform_set_drvdata(pdev, client); | 1190 | platform_set_drvdata(pdev, client); |
| 1193 | 1191 | ||
| 1194 | return 0; | 1192 | return 0; |
| 1193 | ei2cnd: | ||
| 1194 | i2c_put_adapter(adap); | ||
| 1195 | ei2cga: | ||
| 1196 | return ret; | ||
| 1195 | } | 1197 | } |
| 1196 | 1198 | ||
| 1197 | static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) | 1199 | static void soc_camera_free_i2c(struct platform_device *pdev) |
| 1198 | { | 1200 | { |
| 1199 | struct i2c_client *client = platform_get_drvdata(pdev); | 1201 | struct i2c_client *client = platform_get_drvdata(pdev); |
| 1200 | 1202 | ||
| 1201 | if (!client) | 1203 | if (!client) |
| 1202 | return -ENODEV; | 1204 | return; |
| 1203 | 1205 | ||
| 1204 | i2c_unregister_device(client); | 1206 | i2c_unregister_device(client); |
| 1205 | i2c_put_adapter(client->adapter); | 1207 | i2c_put_adapter(client->adapter); |
| 1208 | } | ||
| 1209 | #else | ||
| 1210 | #define soc_camera_init_i2c(d, icl) (-ENODEV) | ||
| 1211 | #define soc_camera_free_i2c(d) do {} while (0) | ||
| 1212 | #endif | ||
| 1206 | 1213 | ||
| 1214 | static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) | ||
| 1215 | { | ||
| 1216 | struct soc_camera_link *icl = pdev->dev.platform_data; | ||
| 1217 | |||
| 1218 | if (!icl) | ||
| 1219 | return -EINVAL; | ||
| 1220 | |||
| 1221 | if (icl->board_info) | ||
| 1222 | return soc_camera_init_i2c(pdev, icl); | ||
| 1223 | else if (!icl->add_device || !icl->del_device) | ||
| 1224 | return -EINVAL; | ||
| 1225 | |||
| 1226 | /* &pdev->dev will become &icd->dev */ | ||
| 1227 | return icl->add_device(icl, &pdev->dev); | ||
| 1228 | } | ||
| 1229 | |||
| 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); | ||
| 1207 | return 0; | 1238 | return 0; |
| 1208 | } | 1239 | } |
| 1209 | 1240 | ||
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 23ecead35e7a..813e12061daa 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h | |||
| @@ -102,6 +102,12 @@ struct soc_camera_link { | |||
| 102 | int i2c_adapter_id; | 102 | int i2c_adapter_id; |
| 103 | struct i2c_board_info *board_info; | 103 | struct i2c_board_info *board_info; |
| 104 | const char *module_name; | 104 | const char *module_name; |
| 105 | /* | ||
| 106 | * For non-I2C devices platform platform has to provide methods to | ||
| 107 | * add a device to the system and to remove | ||
| 108 | */ | ||
| 109 | int (*add_device)(struct soc_camera_link *, struct device *); | ||
| 110 | void (*del_device)(struct soc_camera_link *); | ||
| 105 | /* Optional callbacks to power on or off and reset the sensor */ | 111 | /* Optional callbacks to power on or off and reset the sensor */ |
| 106 | int (*power)(struct device *, int); | 112 | int (*power)(struct device *, int); |
| 107 | int (*reset)(struct device *); | 113 | int (*reset)(struct device *); |
diff --git a/include/media/soc_camera_platform.h b/include/media/soc_camera_platform.h index 1d092b4678aa..af224deadb43 100644 --- a/include/media/soc_camera_platform.h +++ b/include/media/soc_camera_platform.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #define __SOC_CAMERA_H__ | 12 | #define __SOC_CAMERA_H__ |
| 13 | 13 | ||
| 14 | #include <linux/videodev2.h> | 14 | #include <linux/videodev2.h> |
| 15 | #include <media/soc_camera.h> | ||
| 15 | 16 | ||
| 16 | struct soc_camera_platform_info { | 17 | struct soc_camera_platform_info { |
| 17 | int iface; | 18 | int iface; |
| @@ -21,6 +22,7 @@ struct soc_camera_platform_info { | |||
| 21 | unsigned long bus_param; | 22 | unsigned long bus_param; |
| 22 | void (*power)(int); | 23 | void (*power)(int); |
| 23 | int (*set_capture)(struct soc_camera_platform_info *info, int enable); | 24 | int (*set_capture)(struct soc_camera_platform_info *info, int enable); |
| 25 | struct soc_camera_link link; | ||
| 24 | }; | 26 | }; |
| 25 | 27 | ||
| 26 | #endif /* __SOC_CAMERA_H__ */ | 28 | #endif /* __SOC_CAMERA_H__ */ |
