diff options
author | Luca Risolia <luca.risolia@studio.unibo.it> | 2007-06-13 13:52:01 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-07-18 13:24:08 -0400 |
commit | 3b2ae0be9e246974db65a5bf4ccd2de328f3dede (patch) | |
tree | 214b1f770ef032dd371d4fa1791c808c021d4104 /drivers/media/video | |
parent | 3770be34199ace8c497ce454cebd7d63347dc4c3 (diff) |
V4L/DVB (5766): ET61x251 driver updates
- Make the driver depend on V4L2 only (KConfig)
- Better and safe locking mechanism of the device structure on open(),
close() and disconnect()
- Use kref for handling device deallocation
- Generic cleanups
Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/et61x251/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/video/et61x251/et61x251.h | 23 | ||||
-rw-r--r-- | drivers/media/video/et61x251/et61x251_core.c | 189 | ||||
-rw-r--r-- | drivers/media/video/et61x251/et61x251_sensor.h | 8 | ||||
-rw-r--r-- | drivers/media/video/et61x251/et61x251_tas5130d1b.c | 2 |
5 files changed, 120 insertions, 104 deletions
diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig index 664676f44068..dcc1a0335440 100644 --- a/drivers/media/video/et61x251/Kconfig +++ b/drivers/media/video/et61x251/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config USB_ET61X251 | 1 | config USB_ET61X251 |
2 | tristate "USB ET61X[12]51 PC Camera Controller support" | 2 | tristate "USB ET61X[12]51 PC Camera Controller support" |
3 | depends on VIDEO_V4L1 | 3 | depends on VIDEO_V4L2 |
4 | ---help--- | 4 | ---help--- |
5 | Say Y here if you want support for cameras based on Etoms ET61X151 | 5 | Say Y here if you want support for cameras based on Etoms ET61X151 |
6 | or ET61X251 PC Camera Controllers. | 6 | or ET61X251 PC Camera Controllers. |
diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h index 262f98e12409..02c741d8f85a 100644 --- a/drivers/media/video/et61x251/et61x251.h +++ b/drivers/media/video/et61x251/et61x251.h | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/stddef.h> | 37 | #include <linux/stddef.h> |
38 | #include <linux/string.h> | 38 | #include <linux/string.h> |
39 | #include <linux/kref.h> | ||
39 | 40 | ||
40 | #include "et61x251_sensor.h" | 41 | #include "et61x251_sensor.h" |
41 | 42 | ||
@@ -134,7 +135,7 @@ struct et61x251_module_param { | |||
134 | }; | 135 | }; |
135 | 136 | ||
136 | static DEFINE_MUTEX(et61x251_sysfs_lock); | 137 | static DEFINE_MUTEX(et61x251_sysfs_lock); |
137 | static DECLARE_RWSEM(et61x251_disconnect); | 138 | static DECLARE_RWSEM(et61x251_dev_lock); |
138 | 139 | ||
139 | struct et61x251_device { | 140 | struct et61x251_device { |
140 | struct video_device* v4ldev; | 141 | struct video_device* v4ldev; |
@@ -158,12 +159,14 @@ struct et61x251_device { | |||
158 | struct et61x251_sysfs_attr sysfs; | 159 | struct et61x251_sysfs_attr sysfs; |
159 | struct et61x251_module_param module_param; | 160 | struct et61x251_module_param module_param; |
160 | 161 | ||
162 | struct kref kref; | ||
161 | enum et61x251_dev_state state; | 163 | enum et61x251_dev_state state; |
162 | u8 users; | 164 | u8 users; |
163 | 165 | ||
164 | struct mutex dev_mutex, fileop_mutex; | 166 | struct completion probe; |
167 | struct mutex open_mutex, fileop_mutex; | ||
165 | spinlock_t queue_lock; | 168 | spinlock_t queue_lock; |
166 | wait_queue_head_t open, wait_frame, wait_stream; | 169 | wait_queue_head_t wait_open, wait_frame, wait_stream; |
167 | }; | 170 | }; |
168 | 171 | ||
169 | /*****************************************************************************/ | 172 | /*****************************************************************************/ |
@@ -177,7 +180,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) | |||
177 | 180 | ||
178 | void | 181 | void |
179 | et61x251_attach_sensor(struct et61x251_device* cam, | 182 | et61x251_attach_sensor(struct et61x251_device* cam, |
180 | struct et61x251_sensor* sensor) | 183 | const struct et61x251_sensor* sensor) |
181 | { | 184 | { |
182 | memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor)); | 185 | memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor)); |
183 | } | 186 | } |
@@ -195,8 +198,8 @@ do { \ | |||
195 | else if ((level) == 2) \ | 198 | else if ((level) == 2) \ |
196 | dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ | 199 | dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ |
197 | else if ((level) >= 3) \ | 200 | else if ((level) >= 3) \ |
198 | dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ | 201 | dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \ |
199 | __FUNCTION__, __LINE__ , ## args); \ | 202 | __FILE__, __FUNCTION__, __LINE__ , ## args); \ |
200 | } \ | 203 | } \ |
201 | } while (0) | 204 | } while (0) |
202 | # define KDBG(level, fmt, args...) \ | 205 | # define KDBG(level, fmt, args...) \ |
@@ -205,8 +208,8 @@ do { \ | |||
205 | if ((level) == 1 || (level) == 2) \ | 208 | if ((level) == 1 || (level) == 2) \ |
206 | pr_info("et61x251: " fmt "\n", ## args); \ | 209 | pr_info("et61x251: " fmt "\n", ## args); \ |
207 | else if ((level) == 3) \ | 210 | else if ((level) == 3) \ |
208 | pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \ | 211 | pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \ |
209 | __LINE__ , ## args); \ | 212 | __FUNCTION__, __LINE__ , ## args); \ |
210 | } \ | 213 | } \ |
211 | } while (0) | 214 | } while (0) |
212 | # define V4LDBG(level, name, cmd) \ | 215 | # define V4LDBG(level, name, cmd) \ |
@@ -222,8 +225,8 @@ do { \ | |||
222 | 225 | ||
223 | #undef PDBG | 226 | #undef PDBG |
224 | #define PDBG(fmt, args...) \ | 227 | #define PDBG(fmt, args...) \ |
225 | dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ | 228 | dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \ |
226 | __FUNCTION__, __LINE__ , ## args) | 229 | __LINE__ , ## args) |
227 | 230 | ||
228 | #undef PDBGG | 231 | #undef PDBGG |
229 | #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ | 232 | #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ |
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index a6525513cd1e..585bd1fe0765 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c | |||
@@ -45,11 +45,11 @@ | |||
45 | 45 | ||
46 | #define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \ | 46 | #define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \ |
47 | "PC Camera Controllers" | 47 | "PC Camera Controllers" |
48 | #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" | 48 | #define ET61X251_MODULE_AUTHOR "(C) 2006-2007 Luca Risolia" |
49 | #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" | 49 | #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" |
50 | #define ET61X251_MODULE_LICENSE "GPL" | 50 | #define ET61X251_MODULE_LICENSE "GPL" |
51 | #define ET61X251_MODULE_VERSION "1:1.04" | 51 | #define ET61X251_MODULE_VERSION "1:1.09" |
52 | #define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 4) | 52 | #define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 9) |
53 | 53 | ||
54 | /*****************************************************************************/ | 54 | /*****************************************************************************/ |
55 | 55 | ||
@@ -245,7 +245,8 @@ int et61x251_read_reg(struct et61x251_device* cam, u16 index) | |||
245 | 245 | ||
246 | 246 | ||
247 | static int | 247 | static int |
248 | et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor) | 248 | et61x251_i2c_wait(struct et61x251_device* cam, |
249 | const struct et61x251_sensor* sensor) | ||
249 | { | 250 | { |
250 | int i, r; | 251 | int i, r; |
251 | 252 | ||
@@ -270,7 +271,7 @@ et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor) | |||
270 | 271 | ||
271 | int | 272 | int |
272 | et61x251_i2c_try_read(struct et61x251_device* cam, | 273 | et61x251_i2c_try_read(struct et61x251_device* cam, |
273 | struct et61x251_sensor* sensor, u8 address) | 274 | const struct et61x251_sensor* sensor, u8 address) |
274 | { | 275 | { |
275 | struct usb_device* udev = cam->usbdev; | 276 | struct usb_device* udev = cam->usbdev; |
276 | u8* data = cam->control_buffer; | 277 | u8* data = cam->control_buffer; |
@@ -303,7 +304,8 @@ et61x251_i2c_try_read(struct et61x251_device* cam, | |||
303 | 304 | ||
304 | int | 305 | int |
305 | et61x251_i2c_try_write(struct et61x251_device* cam, | 306 | et61x251_i2c_try_write(struct et61x251_device* cam, |
306 | struct et61x251_sensor* sensor, u8 address, u8 value) | 307 | const struct et61x251_sensor* sensor, u8 address, |
308 | u8 value) | ||
307 | { | 309 | { |
308 | struct usb_device* udev = cam->usbdev; | 310 | struct usb_device* udev = cam->usbdev; |
309 | u8* data = cam->control_buffer; | 311 | u8* data = cam->control_buffer; |
@@ -615,7 +617,7 @@ static int et61x251_start_transfer(struct et61x251_device* cam) | |||
615 | return 0; | 617 | return 0; |
616 | 618 | ||
617 | free_urbs: | 619 | free_urbs: |
618 | for (i = 0; (i < ET61X251_URBS) && cam->urb[i]; i++) | 620 | for (i = 0; (i < ET61X251_URBS) && cam->urb[i]; i++) |
619 | usb_free_urb(cam->urb[i]); | 621 | usb_free_urb(cam->urb[i]); |
620 | 622 | ||
621 | free_buffers: | 623 | free_buffers: |
@@ -682,7 +684,7 @@ static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count) | |||
682 | 684 | ||
683 | if (len < 4) { | 685 | if (len < 4) { |
684 | strncpy(str, buff, len); | 686 | strncpy(str, buff, len); |
685 | str[len+1] = '\0'; | 687 | str[len] = '\0'; |
686 | } else { | 688 | } else { |
687 | strncpy(str, buff, 4); | 689 | strncpy(str, buff, 4); |
688 | str[4] = '\0'; | 690 | str[4] = '\0'; |
@@ -977,30 +979,30 @@ static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, | |||
977 | 979 | ||
978 | static int et61x251_create_sysfs(struct et61x251_device* cam) | 980 | static int et61x251_create_sysfs(struct et61x251_device* cam) |
979 | { | 981 | { |
980 | struct video_device *v4ldev = cam->v4ldev; | 982 | struct class_device *classdev = &(cam->v4ldev->class_dev); |
981 | int err = 0; | 983 | int err = 0; |
982 | 984 | ||
983 | if ((err = video_device_create_file(v4ldev, &class_device_attr_reg))) | 985 | if ((err = class_device_create_file(classdev, &class_device_attr_reg))) |
984 | goto err_out; | 986 | goto err_out; |
985 | if ((err = video_device_create_file(v4ldev, &class_device_attr_val))) | 987 | if ((err = class_device_create_file(classdev, &class_device_attr_val))) |
986 | goto err_reg; | 988 | goto err_reg; |
987 | 989 | ||
988 | if (cam->sensor.sysfs_ops) { | 990 | if (cam->sensor.sysfs_ops) { |
989 | if ((err = video_device_create_file(v4ldev, | 991 | if ((err = class_device_create_file(classdev, |
990 | &class_device_attr_i2c_reg))) | 992 | &class_device_attr_i2c_reg))) |
991 | goto err_val; | 993 | goto err_val; |
992 | if ((err = video_device_create_file(v4ldev, | 994 | if ((err = class_device_create_file(classdev, |
993 | &class_device_attr_i2c_val))) | 995 | &class_device_attr_i2c_val))) |
994 | goto err_i2c_reg; | 996 | goto err_i2c_reg; |
995 | } | 997 | } |
996 | 998 | ||
997 | err_i2c_reg: | 999 | err_i2c_reg: |
998 | if (cam->sensor.sysfs_ops) | 1000 | if (cam->sensor.sysfs_ops) |
999 | video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); | 1001 | class_device_remove_file(classdev, &class_device_attr_i2c_reg); |
1000 | err_val: | 1002 | err_val: |
1001 | video_device_remove_file(v4ldev, &class_device_attr_val); | 1003 | class_device_remove_file(classdev, &class_device_attr_val); |
1002 | err_reg: | 1004 | err_reg: |
1003 | video_device_remove_file(v4ldev, &class_device_attr_reg); | 1005 | class_device_remove_file(classdev, &class_device_attr_reg); |
1004 | err_out: | 1006 | err_out: |
1005 | return err; | 1007 | return err; |
1006 | } | 1008 | } |
@@ -1103,7 +1105,8 @@ static int et61x251_init(struct et61x251_device* cam) | |||
1103 | int err = 0; | 1105 | int err = 0; |
1104 | 1106 | ||
1105 | if (!(cam->state & DEV_INITIALIZED)) { | 1107 | if (!(cam->state & DEV_INITIALIZED)) { |
1106 | init_waitqueue_head(&cam->open); | 1108 | mutex_init(&cam->open_mutex); |
1109 | init_waitqueue_head(&cam->wait_open); | ||
1107 | qctrl = s->qctrl; | 1110 | qctrl = s->qctrl; |
1108 | rect = &(s->cropcap.defrect); | 1111 | rect = &(s->cropcap.defrect); |
1109 | cam->compression.quality = ET61X251_COMPRESSION_QUALITY; | 1112 | cam->compression.quality = ET61X251_COMPRESSION_QUALITY; |
@@ -1177,64 +1180,80 @@ static int et61x251_init(struct et61x251_device* cam) | |||
1177 | return 0; | 1180 | return 0; |
1178 | } | 1181 | } |
1179 | 1182 | ||
1183 | /*****************************************************************************/ | ||
1180 | 1184 | ||
1181 | static void et61x251_release_resources(struct et61x251_device* cam) | 1185 | static void et61x251_release_resources(struct kref *kref) |
1182 | { | 1186 | { |
1187 | struct et61x251_device *cam; | ||
1188 | |||
1183 | mutex_lock(&et61x251_sysfs_lock); | 1189 | mutex_lock(&et61x251_sysfs_lock); |
1184 | 1190 | ||
1191 | cam = container_of(kref, struct et61x251_device, kref); | ||
1192 | |||
1185 | DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); | 1193 | DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); |
1186 | video_set_drvdata(cam->v4ldev, NULL); | 1194 | video_set_drvdata(cam->v4ldev, NULL); |
1187 | video_unregister_device(cam->v4ldev); | 1195 | video_unregister_device(cam->v4ldev); |
1196 | usb_put_dev(cam->usbdev); | ||
1197 | kfree(cam->control_buffer); | ||
1198 | kfree(cam); | ||
1188 | 1199 | ||
1189 | mutex_unlock(&et61x251_sysfs_lock); | 1200 | mutex_unlock(&et61x251_sysfs_lock); |
1190 | |||
1191 | kfree(cam->control_buffer); | ||
1192 | } | 1201 | } |
1193 | 1202 | ||
1194 | /*****************************************************************************/ | ||
1195 | 1203 | ||
1196 | static int et61x251_open(struct inode* inode, struct file* filp) | 1204 | static int et61x251_open(struct inode* inode, struct file* filp) |
1197 | { | 1205 | { |
1198 | struct et61x251_device* cam; | 1206 | struct et61x251_device* cam; |
1199 | int err = 0; | 1207 | int err = 0; |
1200 | 1208 | ||
1201 | /* | 1209 | if (!down_read_trylock(&et61x251_dev_lock)) |
1202 | This is the only safe way to prevent race conditions with | ||
1203 | disconnect | ||
1204 | */ | ||
1205 | if (!down_read_trylock(&et61x251_disconnect)) | ||
1206 | return -ERESTARTSYS; | 1210 | return -ERESTARTSYS; |
1207 | 1211 | ||
1208 | cam = video_get_drvdata(video_devdata(filp)); | 1212 | cam = video_get_drvdata(video_devdata(filp)); |
1209 | 1213 | ||
1210 | if (mutex_lock_interruptible(&cam->dev_mutex)) { | 1214 | if (wait_for_completion_interruptible(&cam->probe)) { |
1211 | up_read(&et61x251_disconnect); | 1215 | up_read(&et61x251_dev_lock); |
1212 | return -ERESTARTSYS; | 1216 | return -ERESTARTSYS; |
1213 | } | 1217 | } |
1214 | 1218 | ||
1219 | kref_get(&cam->kref); | ||
1220 | |||
1221 | if (mutex_lock_interruptible(&cam->open_mutex)) { | ||
1222 | kref_put(&cam->kref, et61x251_release_resources); | ||
1223 | up_read(&et61x251_dev_lock); | ||
1224 | return -ERESTARTSYS; | ||
1225 | } | ||
1226 | |||
1227 | if (cam->state & DEV_DISCONNECTED) { | ||
1228 | DBG(1, "Device not present"); | ||
1229 | err = -ENODEV; | ||
1230 | goto out; | ||
1231 | } | ||
1232 | |||
1215 | if (cam->users) { | 1233 | if (cam->users) { |
1216 | DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); | 1234 | DBG(2, "Device /dev/video%d is already in use", |
1235 | cam->v4ldev->minor); | ||
1236 | DBG(3, "Simultaneous opens are not supported"); | ||
1217 | if ((filp->f_flags & O_NONBLOCK) || | 1237 | if ((filp->f_flags & O_NONBLOCK) || |
1218 | (filp->f_flags & O_NDELAY)) { | 1238 | (filp->f_flags & O_NDELAY)) { |
1219 | err = -EWOULDBLOCK; | 1239 | err = -EWOULDBLOCK; |
1220 | goto out; | 1240 | goto out; |
1221 | } | 1241 | } |
1222 | mutex_unlock(&cam->dev_mutex); | 1242 | DBG(2, "A blocking open() has been requested. Wait for the " |
1223 | err = wait_event_interruptible_exclusive(cam->open, | 1243 | "device to be released..."); |
1224 | cam->state & DEV_DISCONNECTED | 1244 | up_read(&et61x251_dev_lock); |
1245 | err = wait_event_interruptible_exclusive(cam->wait_open, | ||
1246 | (cam->state & DEV_DISCONNECTED) | ||
1225 | || !cam->users); | 1247 | || !cam->users); |
1226 | if (err) { | 1248 | down_read(&et61x251_dev_lock); |
1227 | up_read(&et61x251_disconnect); | 1249 | if (err) |
1228 | return err; | 1250 | goto out; |
1229 | } | ||
1230 | if (cam->state & DEV_DISCONNECTED) { | 1251 | if (cam->state & DEV_DISCONNECTED) { |
1231 | up_read(&et61x251_disconnect); | 1252 | err = -ENODEV; |
1232 | return -ENODEV; | 1253 | goto out; |
1233 | } | 1254 | } |
1234 | mutex_lock(&cam->dev_mutex); | ||
1235 | } | 1255 | } |
1236 | 1256 | ||
1237 | |||
1238 | if (cam->state & DEV_MISCONFIGURED) { | 1257 | if (cam->state & DEV_MISCONFIGURED) { |
1239 | err = et61x251_init(cam); | 1258 | err = et61x251_init(cam); |
1240 | if (err) { | 1259 | if (err) { |
@@ -1259,36 +1278,32 @@ static int et61x251_open(struct inode* inode, struct file* filp) | |||
1259 | DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); | 1278 | DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); |
1260 | 1279 | ||
1261 | out: | 1280 | out: |
1262 | mutex_unlock(&cam->dev_mutex); | 1281 | mutex_unlock(&cam->open_mutex); |
1263 | up_read(&et61x251_disconnect); | 1282 | if (err) |
1283 | kref_put(&cam->kref, et61x251_release_resources); | ||
1284 | up_read(&et61x251_dev_lock); | ||
1264 | return err; | 1285 | return err; |
1265 | } | 1286 | } |
1266 | 1287 | ||
1267 | 1288 | ||
1268 | static int et61x251_release(struct inode* inode, struct file* filp) | 1289 | static int et61x251_release(struct inode* inode, struct file* filp) |
1269 | { | 1290 | { |
1270 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 1291 | struct et61x251_device* cam; |
1271 | 1292 | ||
1272 | mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ | 1293 | down_write(&et61x251_dev_lock); |
1273 | 1294 | ||
1274 | et61x251_stop_transfer(cam); | 1295 | cam = video_get_drvdata(video_devdata(filp)); |
1275 | 1296 | ||
1297 | et61x251_stop_transfer(cam); | ||
1276 | et61x251_release_buffers(cam); | 1298 | et61x251_release_buffers(cam); |
1277 | |||
1278 | if (cam->state & DEV_DISCONNECTED) { | ||
1279 | et61x251_release_resources(cam); | ||
1280 | usb_put_dev(cam->usbdev); | ||
1281 | mutex_unlock(&cam->dev_mutex); | ||
1282 | kfree(cam); | ||
1283 | return 0; | ||
1284 | } | ||
1285 | |||
1286 | cam->users--; | 1299 | cam->users--; |
1287 | wake_up_interruptible_nr(&cam->open, 1); | 1300 | wake_up_interruptible_nr(&cam->wait_open, 1); |
1288 | 1301 | ||
1289 | DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); | 1302 | DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); |
1290 | 1303 | ||
1291 | mutex_unlock(&cam->dev_mutex); | 1304 | kref_put(&cam->kref, et61x251_release_resources); |
1305 | |||
1306 | up_write(&et61x251_dev_lock); | ||
1292 | 1307 | ||
1293 | return 0; | 1308 | return 0; |
1294 | } | 1309 | } |
@@ -1324,7 +1339,7 @@ et61x251_read(struct file* filp, char __user * buf, | |||
1324 | DBG(3, "Close and open the device again to choose the read " | 1339 | DBG(3, "Close and open the device again to choose the read " |
1325 | "method"); | 1340 | "method"); |
1326 | mutex_unlock(&cam->fileop_mutex); | 1341 | mutex_unlock(&cam->fileop_mutex); |
1327 | return -EINVAL; | 1342 | return -EBUSY; |
1328 | } | 1343 | } |
1329 | 1344 | ||
1330 | if (cam->io == IO_NONE) { | 1345 | if (cam->io == IO_NONE) { |
@@ -1504,7 +1519,12 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) | |||
1504 | return -EIO; | 1519 | return -EIO; |
1505 | } | 1520 | } |
1506 | 1521 | ||
1507 | if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || | 1522 | if (!(vma->vm_flags & (VM_WRITE | VM_READ))) { |
1523 | mutex_unlock(&cam->fileop_mutex); | ||
1524 | return -EACCES; | ||
1525 | } | ||
1526 | |||
1527 | if (cam->io != IO_MMAP || | ||
1508 | size != PAGE_ALIGN(cam->frame[0].buf.length)) { | 1528 | size != PAGE_ALIGN(cam->frame[0].buf.length)) { |
1509 | mutex_unlock(&cam->fileop_mutex); | 1529 | mutex_unlock(&cam->fileop_mutex); |
1510 | return -EINVAL; | 1530 | return -EINVAL; |
@@ -1535,7 +1555,6 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) | |||
1535 | 1555 | ||
1536 | vma->vm_ops = &et61x251_vm_ops; | 1556 | vma->vm_ops = &et61x251_vm_ops; |
1537 | vma->vm_private_data = &cam->frame[i]; | 1557 | vma->vm_private_data = &cam->frame[i]; |
1538 | |||
1539 | et61x251_vm_open(vma); | 1558 | et61x251_vm_open(vma); |
1540 | 1559 | ||
1541 | mutex_unlock(&cam->fileop_mutex); | 1560 | mutex_unlock(&cam->fileop_mutex); |
@@ -1764,7 +1783,7 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) | |||
1764 | if (cam->frame[i].vma_use_count) { | 1783 | if (cam->frame[i].vma_use_count) { |
1765 | DBG(3, "VIDIOC_S_CROP failed. " | 1784 | DBG(3, "VIDIOC_S_CROP failed. " |
1766 | "Unmap the buffers first."); | 1785 | "Unmap the buffers first."); |
1767 | return -EINVAL; | 1786 | return -EBUSY; |
1768 | } | 1787 | } |
1769 | 1788 | ||
1770 | /* Preserve R,G or B origin */ | 1789 | /* Preserve R,G or B origin */ |
@@ -1921,6 +1940,8 @@ et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg) | |||
1921 | if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1940 | if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1922 | return -EINVAL; | 1941 | return -EINVAL; |
1923 | 1942 | ||
1943 | pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_ET61X251) ? | ||
1944 | 0 : V4L2_COLORSPACE_SRGB; | ||
1924 | pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251) | 1945 | pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251) |
1925 | ? 0 : (pfmt->width * pfmt->priv) / 8; | 1946 | ? 0 : (pfmt->width * pfmt->priv) / 8; |
1926 | pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); | 1947 | pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); |
@@ -1996,6 +2017,8 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, | |||
1996 | pix->pixelformat != V4L2_PIX_FMT_SBGGR8) | 2017 | pix->pixelformat != V4L2_PIX_FMT_SBGGR8) |
1997 | pix->pixelformat = pfmt->pixelformat; | 2018 | pix->pixelformat = pfmt->pixelformat; |
1998 | pix->priv = pfmt->priv; /* bpp */ | 2019 | pix->priv = pfmt->priv; /* bpp */ |
2020 | pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) ? | ||
2021 | 0 : V4L2_COLORSPACE_SRGB; | ||
1999 | pix->colorspace = pfmt->colorspace; | 2022 | pix->colorspace = pfmt->colorspace; |
2000 | pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) | 2023 | pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) |
2001 | ? 0 : (pix->width * pix->priv) / 8; | 2024 | ? 0 : (pix->width * pix->priv) / 8; |
@@ -2013,7 +2036,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, | |||
2013 | if (cam->frame[i].vma_use_count) { | 2036 | if (cam->frame[i].vma_use_count) { |
2014 | DBG(3, "VIDIOC_S_FMT failed. " | 2037 | DBG(3, "VIDIOC_S_FMT failed. " |
2015 | "Unmap the buffers first."); | 2038 | "Unmap the buffers first."); |
2016 | return -EINVAL; | 2039 | return -EBUSY; |
2017 | } | 2040 | } |
2018 | 2041 | ||
2019 | if (cam->stream == STREAM_ON) | 2042 | if (cam->stream == STREAM_ON) |
@@ -2129,14 +2152,14 @@ et61x251_vidioc_reqbufs(struct et61x251_device* cam, void __user * arg) | |||
2129 | if (cam->io == IO_READ) { | 2152 | if (cam->io == IO_READ) { |
2130 | DBG(3, "Close and open the device again to choose the mmap " | 2153 | DBG(3, "Close and open the device again to choose the mmap " |
2131 | "I/O method"); | 2154 | "I/O method"); |
2132 | return -EINVAL; | 2155 | return -EBUSY; |
2133 | } | 2156 | } |
2134 | 2157 | ||
2135 | for (i = 0; i < cam->nbuffers; i++) | 2158 | for (i = 0; i < cam->nbuffers; i++) |
2136 | if (cam->frame[i].vma_use_count) { | 2159 | if (cam->frame[i].vma_use_count) { |
2137 | DBG(3, "VIDIOC_REQBUFS failed. " | 2160 | DBG(3, "VIDIOC_REQBUFS failed. " |
2138 | "Previous buffers are still mapped."); | 2161 | "Previous buffers are still mapped."); |
2139 | return -EINVAL; | 2162 | return -EBUSY; |
2140 | } | 2163 | } |
2141 | 2164 | ||
2142 | if (cam->stream == STREAM_ON) | 2165 | if (cam->stream == STREAM_ON) |
@@ -2284,9 +2307,6 @@ et61x251_vidioc_streamon(struct et61x251_device* cam, void __user * arg) | |||
2284 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) | 2307 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) |
2285 | return -EINVAL; | 2308 | return -EINVAL; |
2286 | 2309 | ||
2287 | if (list_empty(&cam->inqueue)) | ||
2288 | return -EINVAL; | ||
2289 | |||
2290 | cam->stream = STREAM_ON; | 2310 | cam->stream = STREAM_ON; |
2291 | 2311 | ||
2292 | DBG(3, "Stream on"); | 2312 | DBG(3, "Stream on"); |
@@ -2535,8 +2555,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2535 | goto fail; | 2555 | goto fail; |
2536 | } | 2556 | } |
2537 | 2557 | ||
2538 | mutex_init(&cam->dev_mutex); | ||
2539 | |||
2540 | DBG(2, "ET61X[12]51 PC Camera Controller detected " | 2558 | DBG(2, "ET61X[12]51 PC Camera Controller detected " |
2541 | "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct); | 2559 | "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct); |
2542 | 2560 | ||
@@ -2568,7 +2586,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2568 | cam->v4ldev->release = video_device_release; | 2586 | cam->v4ldev->release = video_device_release; |
2569 | video_set_drvdata(cam->v4ldev, cam); | 2587 | video_set_drvdata(cam->v4ldev, cam); |
2570 | 2588 | ||
2571 | mutex_lock(&cam->dev_mutex); | 2589 | init_completion(&cam->probe); |
2572 | 2590 | ||
2573 | err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, | 2591 | err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, |
2574 | video_nr[dev_nr]); | 2592 | video_nr[dev_nr]); |
@@ -2578,7 +2596,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2578 | DBG(1, "Free /dev/videoX node not found"); | 2596 | DBG(1, "Free /dev/videoX node not found"); |
2579 | video_nr[dev_nr] = -1; | 2597 | video_nr[dev_nr] = -1; |
2580 | dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; | 2598 | dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; |
2581 | mutex_unlock(&cam->dev_mutex); | 2599 | complete_all(&cam->probe); |
2582 | goto fail; | 2600 | goto fail; |
2583 | } | 2601 | } |
2584 | 2602 | ||
@@ -2599,11 +2617,15 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2599 | "device controlling. Error #%d", err); | 2617 | "device controlling. Error #%d", err); |
2600 | #else | 2618 | #else |
2601 | DBG(2, "Optional device control through 'sysfs' interface disabled"); | 2619 | DBG(2, "Optional device control through 'sysfs' interface disabled"); |
2620 | DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' " | ||
2621 | "configuration option to enable it."); | ||
2602 | #endif | 2622 | #endif |
2603 | 2623 | ||
2604 | usb_set_intfdata(intf, cam); | 2624 | usb_set_intfdata(intf, cam); |
2625 | kref_init(&cam->kref); | ||
2626 | usb_get_dev(cam->usbdev); | ||
2605 | 2627 | ||
2606 | mutex_unlock(&cam->dev_mutex); | 2628 | complete_all(&cam->probe); |
2607 | 2629 | ||
2608 | return 0; | 2630 | return 0; |
2609 | 2631 | ||
@@ -2620,40 +2642,31 @@ fail: | |||
2620 | 2642 | ||
2621 | static void et61x251_usb_disconnect(struct usb_interface* intf) | 2643 | static void et61x251_usb_disconnect(struct usb_interface* intf) |
2622 | { | 2644 | { |
2623 | struct et61x251_device* cam = usb_get_intfdata(intf); | 2645 | struct et61x251_device* cam; |
2624 | |||
2625 | if (!cam) | ||
2626 | return; | ||
2627 | 2646 | ||
2628 | down_write(&et61x251_disconnect); | 2647 | down_write(&et61x251_dev_lock); |
2629 | 2648 | ||
2630 | mutex_lock(&cam->dev_mutex); | 2649 | cam = usb_get_intfdata(intf); |
2631 | 2650 | ||
2632 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); | 2651 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); |
2633 | 2652 | ||
2634 | wake_up_interruptible_all(&cam->open); | ||
2635 | |||
2636 | if (cam->users) { | 2653 | if (cam->users) { |
2637 | DBG(2, "Device /dev/video%d is open! Deregistration and " | 2654 | DBG(2, "Device /dev/video%d is open! Deregistration and " |
2638 | "memory deallocation are deferred on close.", | 2655 | "memory deallocation are deferred.", |
2639 | cam->v4ldev->minor); | 2656 | cam->v4ldev->minor); |
2640 | cam->state |= DEV_MISCONFIGURED; | 2657 | cam->state |= DEV_MISCONFIGURED; |
2641 | et61x251_stop_transfer(cam); | 2658 | et61x251_stop_transfer(cam); |
2642 | cam->state |= DEV_DISCONNECTED; | 2659 | cam->state |= DEV_DISCONNECTED; |
2643 | wake_up_interruptible(&cam->wait_frame); | 2660 | wake_up_interruptible(&cam->wait_frame); |
2644 | wake_up(&cam->wait_stream); | 2661 | wake_up(&cam->wait_stream); |
2645 | usb_get_dev(cam->usbdev); | 2662 | } else |
2646 | } else { | ||
2647 | cam->state |= DEV_DISCONNECTED; | 2663 | cam->state |= DEV_DISCONNECTED; |
2648 | et61x251_release_resources(cam); | ||
2649 | } | ||
2650 | 2664 | ||
2651 | mutex_unlock(&cam->dev_mutex); | 2665 | wake_up_interruptible_all(&cam->wait_open); |
2652 | 2666 | ||
2653 | if (!cam->users) | 2667 | kref_put(&cam->kref, et61x251_release_resources); |
2654 | kfree(cam); | ||
2655 | 2668 | ||
2656 | up_write(&et61x251_disconnect); | 2669 | up_write(&et61x251_dev_lock); |
2657 | } | 2670 | } |
2658 | 2671 | ||
2659 | 2672 | ||
diff --git a/drivers/media/video/et61x251/et61x251_sensor.h b/drivers/media/video/et61x251/et61x251_sensor.h index 5fadb5de68bf..e14586330623 100644 --- a/drivers/media/video/et61x251/et61x251_sensor.h +++ b/drivers/media/video/et61x251/et61x251_sensor.h | |||
@@ -22,7 +22,7 @@ | |||
22 | #define _ET61X251_SENSOR_H_ | 22 | #define _ET61X251_SENSOR_H_ |
23 | 23 | ||
24 | #include <linux/usb.h> | 24 | #include <linux/usb.h> |
25 | #include <linux/videodev.h> | 25 | #include <linux/videodev2.h> |
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/stddef.h> | 27 | #include <linux/stddef.h> |
28 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
@@ -47,7 +47,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id); | |||
47 | 47 | ||
48 | extern void | 48 | extern void |
49 | et61x251_attach_sensor(struct et61x251_device* cam, | 49 | et61x251_attach_sensor(struct et61x251_device* cam, |
50 | struct et61x251_sensor* sensor); | 50 | const struct et61x251_sensor* sensor); |
51 | 51 | ||
52 | /*****************************************************************************/ | 52 | /*****************************************************************************/ |
53 | 53 | ||
@@ -56,10 +56,10 @@ extern int et61x251_read_reg(struct et61x251_device*, u16 index); | |||
56 | extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value); | 56 | extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value); |
57 | extern int et61x251_i2c_read(struct et61x251_device*, u8 address); | 57 | extern int et61x251_i2c_read(struct et61x251_device*, u8 address); |
58 | extern int et61x251_i2c_try_write(struct et61x251_device*, | 58 | extern int et61x251_i2c_try_write(struct et61x251_device*, |
59 | struct et61x251_sensor*, u8 address, | 59 | const struct et61x251_sensor*, u8 address, |
60 | u8 value); | 60 | u8 value); |
61 | extern int et61x251_i2c_try_read(struct et61x251_device*, | 61 | extern int et61x251_i2c_try_read(struct et61x251_device*, |
62 | struct et61x251_sensor*, u8 address); | 62 | const struct et61x251_sensor*, u8 address); |
63 | extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1, | 63 | extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1, |
64 | u8 data2, u8 data3, u8 data4, u8 data5, | 64 | u8 data2, u8 data3, u8 data4, u8 data5, |
65 | u8 data6, u8 data7, u8 data8, u8 address); | 65 | u8 data6, u8 data7, u8 data8, u8 address); |
diff --git a/drivers/media/video/et61x251/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c index b06643409842..04b7fbb310a8 100644 --- a/drivers/media/video/et61x251/et61x251_tas5130d1b.c +++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c | |||
@@ -69,7 +69,7 @@ static int tas5130d1b_set_ctrl(struct et61x251_device* cam, | |||
69 | } | 69 | } |
70 | 70 | ||
71 | 71 | ||
72 | static struct et61x251_sensor tas5130d1b = { | 72 | static const struct et61x251_sensor tas5130d1b = { |
73 | .name = "TAS5130D1B", | 73 | .name = "TAS5130D1B", |
74 | .interface = ET61X251_I2C_3WIRES, | 74 | .interface = ET61X251_I2C_3WIRES, |
75 | .rsta = ET61X251_I2C_RSTA_STOP, | 75 | .rsta = ET61X251_I2C_RSTA_STOP, |