aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Risolia <luca.risolia@studio.unibo.it>2007-06-13 13:52:01 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-07-18 13:24:08 -0400
commit3b2ae0be9e246974db65a5bf4ccd2de328f3dede (patch)
tree214b1f770ef032dd371d4fa1791c808c021d4104
parent3770be34199ace8c497ce454cebd7d63347dc4c3 (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>
-rw-r--r--drivers/media/video/et61x251/Kconfig2
-rw-r--r--drivers/media/video/et61x251/et61x251.h23
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c189
-rw-r--r--drivers/media/video/et61x251/et61x251_sensor.h8
-rw-r--r--drivers/media/video/et61x251/et61x251_tas5130d1b.c2
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 @@
1config USB_ET61X251 1config 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
136static DEFINE_MUTEX(et61x251_sysfs_lock); 137static DEFINE_MUTEX(et61x251_sysfs_lock);
137static DECLARE_RWSEM(et61x251_disconnect); 138static DECLARE_RWSEM(et61x251_dev_lock);
138 139
139struct et61x251_device { 140struct 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
178void 181void
179et61x251_attach_sensor(struct et61x251_device* cam, 182et61x251_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...) \
225dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ 228dev_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
247static int 247static int
248et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor) 248et61x251_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
271int 272int
272et61x251_i2c_try_read(struct et61x251_device* cam, 273et61x251_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
304int 305int
305et61x251_i2c_try_write(struct et61x251_device* cam, 306et61x251_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
617free_urbs: 619free_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
621free_buffers: 623free_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
978static int et61x251_create_sysfs(struct et61x251_device* cam) 980static 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
997err_i2c_reg: 999err_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);
1000err_val: 1002err_val:
1001 video_device_remove_file(v4ldev, &class_device_attr_val); 1003 class_device_remove_file(classdev, &class_device_attr_val);
1002err_reg: 1004err_reg:
1003 video_device_remove_file(v4ldev, &class_device_attr_reg); 1005 class_device_remove_file(classdev, &class_device_attr_reg);
1004err_out: 1006err_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
1181static void et61x251_release_resources(struct et61x251_device* cam) 1185static 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
1196static int et61x251_open(struct inode* inode, struct file* filp) 1204static 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
1261out: 1280out:
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
1268static int et61x251_release(struct inode* inode, struct file* filp) 1289static 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
2621static void et61x251_usb_disconnect(struct usb_interface* intf) 2643static 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
48extern void 48extern void
49et61x251_attach_sensor(struct et61x251_device* cam, 49et61x251_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);
56extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value); 56extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value);
57extern int et61x251_i2c_read(struct et61x251_device*, u8 address); 57extern int et61x251_i2c_read(struct et61x251_device*, u8 address);
58extern int et61x251_i2c_try_write(struct et61x251_device*, 58extern 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);
61extern int et61x251_i2c_try_read(struct et61x251_device*, 61extern int et61x251_i2c_try_read(struct et61x251_device*,
62 struct et61x251_sensor*, u8 address); 62 const struct et61x251_sensor*, u8 address);
63extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1, 63extern 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
72static struct et61x251_sensor tas5130d1b = { 72static 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,