aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/soc_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/soc_camera.c')
-rw-r--r--drivers/media/video/soc_camera.c106
1 files changed, 76 insertions, 30 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 0e890cc23377..16f595d4337a 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -16,19 +16,21 @@
16 * published by the Free Software Foundation. 16 * published by the Free Software Foundation.
17 */ 17 */
18 18
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/device.h> 19#include <linux/device.h>
22#include <linux/list.h>
23#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/i2c.h>
22#include <linux/init.h>
23#include <linux/list.h>
24#include <linux/module.h>
24#include <linux/mutex.h> 25#include <linux/mutex.h>
26#include <linux/platform_device.h>
25#include <linux/vmalloc.h> 27#include <linux/vmalloc.h>
26 28
29#include <media/soc_camera.h>
27#include <media/v4l2-common.h> 30#include <media/v4l2-common.h>
28#include <media/v4l2-ioctl.h>
29#include <media/v4l2-dev.h> 31#include <media/v4l2-dev.h>
32#include <media/v4l2-ioctl.h>
30#include <media/videobuf-core.h> 33#include <media/videobuf-core.h>
31#include <media/soc_camera.h>
32 34
33/* Default to VGA resolution */ 35/* Default to VGA resolution */
34#define DEFAULT_WIDTH 640 36#define DEFAULT_WIDTH 640
@@ -279,7 +281,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf,
279 return ret; 281 return ret;
280 } else if (!icd->current_fmt || 282 } else if (!icd->current_fmt ||
281 icd->current_fmt->fourcc != pix->pixelformat) { 283 icd->current_fmt->fourcc != pix->pixelformat) {
282 dev_err(&ici->dev, 284 dev_err(ici->dev,
283 "Host driver hasn't set up current format correctly!\n"); 285 "Host driver hasn't set up current format correctly!\n");
284 return -EINVAL; 286 return -EINVAL;
285 } 287 }
@@ -794,7 +796,7 @@ static void scan_add_host(struct soc_camera_host *ici)
794 796
795 list_for_each_entry(icd, &devices, list) { 797 list_for_each_entry(icd, &devices, list) {
796 if (icd->iface == ici->nr) { 798 if (icd->iface == ici->nr) {
797 icd->dev.parent = &ici->dev; 799 icd->dev.parent = ici->dev;
798 device_register_link(icd); 800 device_register_link(icd);
799 } 801 }
800 } 802 }
@@ -818,7 +820,7 @@ static int scan_add_device(struct soc_camera_device *icd)
818 list_for_each_entry(ici, &hosts, list) { 820 list_for_each_entry(ici, &hosts, list) {
819 if (icd->iface == ici->nr) { 821 if (icd->iface == ici->nr) {
820 ret = 1; 822 ret = 1;
821 icd->dev.parent = &ici->dev; 823 icd->dev.parent = ici->dev;
822 break; 824 break;
823 } 825 }
824 } 826 }
@@ -952,7 +954,6 @@ static void dummy_release(struct device *dev)
952 954
953int soc_camera_host_register(struct soc_camera_host *ici) 955int soc_camera_host_register(struct soc_camera_host *ici)
954{ 956{
955 int ret;
956 struct soc_camera_host *ix; 957 struct soc_camera_host *ix;
957 958
958 if (!ici || !ici->ops || 959 if (!ici || !ici->ops ||
@@ -965,12 +966,10 @@ int soc_camera_host_register(struct soc_camera_host *ici)
965 !ici->ops->reqbufs || 966 !ici->ops->reqbufs ||
966 !ici->ops->add || 967 !ici->ops->add ||
967 !ici->ops->remove || 968 !ici->ops->remove ||
968 !ici->ops->poll) 969 !ici->ops->poll ||
970 !ici->dev)
969 return -EINVAL; 971 return -EINVAL;
970 972
971 /* Number might be equal to the platform device ID */
972 dev_set_name(&ici->dev, "camera_host%d", ici->nr);
973
974 mutex_lock(&list_lock); 973 mutex_lock(&list_lock);
975 list_for_each_entry(ix, &hosts, list) { 974 list_for_each_entry(ix, &hosts, list) {
976 if (ix->nr == ici->nr) { 975 if (ix->nr == ici->nr) {
@@ -979,26 +978,14 @@ int soc_camera_host_register(struct soc_camera_host *ici)
979 } 978 }
980 } 979 }
981 980
981 dev_set_drvdata(ici->dev, ici);
982
982 list_add_tail(&ici->list, &hosts); 983 list_add_tail(&ici->list, &hosts);
983 mutex_unlock(&list_lock); 984 mutex_unlock(&list_lock);
984 985
985 ici->dev.release = dummy_release;
986
987 ret = device_register(&ici->dev);
988
989 if (ret)
990 goto edevr;
991
992 scan_add_host(ici); 986 scan_add_host(ici);
993 987
994 return 0; 988 return 0;
995
996edevr:
997 mutex_lock(&list_lock);
998 list_del(&ici->list);
999 mutex_unlock(&list_lock);
1000
1001 return ret;
1002} 989}
1003EXPORT_SYMBOL(soc_camera_host_register); 990EXPORT_SYMBOL(soc_camera_host_register);
1004 991
@@ -1012,7 +999,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
1012 list_del(&ici->list); 999 list_del(&ici->list);
1013 1000
1014 list_for_each_entry(icd, &devices, list) { 1001 list_for_each_entry(icd, &devices, list) {
1015 if (icd->dev.parent == &ici->dev) { 1002 if (icd->dev.parent == ici->dev) {
1016 device_unregister(&icd->dev); 1003 device_unregister(&icd->dev);
1017 /* Not before device_unregister(), .remove 1004 /* Not before device_unregister(), .remove
1018 * needs parent to call ici->ops->remove() */ 1005 * needs parent to call ici->ops->remove() */
@@ -1023,7 +1010,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
1023 1010
1024 mutex_unlock(&list_lock); 1011 mutex_unlock(&list_lock);
1025 1012
1026 device_unregister(&ici->dev); 1013 dev_set_drvdata(ici->dev, NULL);
1027} 1014}
1028EXPORT_SYMBOL(soc_camera_host_unregister); 1015EXPORT_SYMBOL(soc_camera_host_unregister);
1029 1016
@@ -1130,7 +1117,7 @@ int soc_camera_video_start(struct soc_camera_device *icd)
1130 vdev = video_device_alloc(); 1117 vdev = video_device_alloc();
1131 if (!vdev) 1118 if (!vdev)
1132 goto evidallocd; 1119 goto evidallocd;
1133 dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev); 1120 dev_dbg(ici->dev, "Allocated video_device %p\n", vdev);
1134 1121
1135 strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); 1122 strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
1136 1123
@@ -1174,6 +1161,57 @@ void soc_camera_video_stop(struct soc_camera_device *icd)
1174} 1161}
1175EXPORT_SYMBOL(soc_camera_video_stop); 1162EXPORT_SYMBOL(soc_camera_video_stop);
1176 1163
1164static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
1165{
1166 struct soc_camera_link *icl = pdev->dev.platform_data;
1167 struct i2c_adapter *adap;
1168 struct i2c_client *client;
1169
1170 if (!icl)
1171 return -EINVAL;
1172
1173 adap = i2c_get_adapter(icl->i2c_adapter_id);
1174 if (!adap) {
1175 dev_warn(&pdev->dev, "Cannot get adapter #%d. No driver?\n",
1176 icl->i2c_adapter_id);
1177 /* -ENODEV and -ENXIO do not produce an error on probe()... */
1178 return -ENOENT;
1179 }
1180
1181 icl->board_info->platform_data = icl;
1182 client = i2c_new_device(adap, icl->board_info);
1183 if (!client) {
1184 i2c_put_adapter(adap);
1185 return -ENOMEM;
1186 }
1187
1188 platform_set_drvdata(pdev, client);
1189
1190 return 0;
1191}
1192
1193static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
1194{
1195 struct i2c_client *client = platform_get_drvdata(pdev);
1196
1197 if (!client)
1198 return -ENODEV;
1199
1200 i2c_unregister_device(client);
1201 i2c_put_adapter(client->adapter);
1202
1203 return 0;
1204}
1205
1206static struct platform_driver __refdata soc_camera_pdrv = {
1207 .probe = soc_camera_pdrv_probe,
1208 .remove = __devexit_p(soc_camera_pdrv_remove),
1209 .driver = {
1210 .name = "soc-camera-pdrv",
1211 .owner = THIS_MODULE,
1212 },
1213};
1214
1177static int __init soc_camera_init(void) 1215static int __init soc_camera_init(void)
1178{ 1216{
1179 int ret = bus_register(&soc_camera_bus_type); 1217 int ret = bus_register(&soc_camera_bus_type);
@@ -1183,8 +1221,14 @@ static int __init soc_camera_init(void)
1183 if (ret) 1221 if (ret)
1184 goto edrvr; 1222 goto edrvr;
1185 1223
1224 ret = platform_driver_register(&soc_camera_pdrv);
1225 if (ret)
1226 goto epdr;
1227
1186 return 0; 1228 return 0;
1187 1229
1230epdr:
1231 driver_unregister(&ic_drv);
1188edrvr: 1232edrvr:
1189 bus_unregister(&soc_camera_bus_type); 1233 bus_unregister(&soc_camera_bus_type);
1190 return ret; 1234 return ret;
@@ -1192,6 +1236,7 @@ edrvr:
1192 1236
1193static void __exit soc_camera_exit(void) 1237static void __exit soc_camera_exit(void)
1194{ 1238{
1239 platform_driver_unregister(&soc_camera_pdrv);
1195 driver_unregister(&ic_drv); 1240 driver_unregister(&ic_drv);
1196 bus_unregister(&soc_camera_bus_type); 1241 bus_unregister(&soc_camera_bus_type);
1197} 1242}
@@ -1202,3 +1247,4 @@ module_exit(soc_camera_exit);
1202MODULE_DESCRIPTION("Image capture bus driver"); 1247MODULE_DESCRIPTION("Image capture bus driver");
1203MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); 1248MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
1204MODULE_LICENSE("GPL"); 1249MODULE_LICENSE("GPL");
1250MODULE_ALIAS("platform:soc-camera-pdrv");