aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s2255drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/s2255drv.c')
-rw-r--r--drivers/media/video/s2255drv.c130
1 files changed, 77 insertions, 53 deletions
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index 04eb2c3fabd8..b1d09d8e2b85 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -47,8 +47,10 @@
47#include <linux/mutex.h> 47#include <linux/mutex.h>
48#include <linux/videodev2.h> 48#include <linux/videodev2.h>
49#include <linux/version.h> 49#include <linux/version.h>
50#include <linux/mm.h>
50#include <media/videobuf-vmalloc.h> 51#include <media/videobuf-vmalloc.h>
51#include <media/v4l2-common.h> 52#include <media/v4l2-common.h>
53#include <media/v4l2-ioctl.h>
52#include <linux/vmalloc.h> 54#include <linux/vmalloc.h>
53#include <linux/usb.h> 55#include <linux/usb.h>
54 56
@@ -184,6 +186,7 @@ struct s2255_dmaqueue {
184#define S2255_FW_LOADED_DSPWAIT 1 186#define S2255_FW_LOADED_DSPWAIT 1
185#define S2255_FW_SUCCESS 2 187#define S2255_FW_SUCCESS 2
186#define S2255_FW_FAILED 3 188#define S2255_FW_FAILED 3
189#define S2255_FW_DISCONNECTING 4
187 190
188struct s2255_fw { 191struct s2255_fw {
189 int fw_loaded; 192 int fw_loaded;
@@ -263,7 +266,6 @@ struct s2255_buffer {
263 266
264struct s2255_fh { 267struct s2255_fh {
265 struct s2255_dev *dev; 268 struct s2255_dev *dev;
266 unsigned int resources;
267 const struct s2255_fmt *fmt; 269 const struct s2255_fmt *fmt;
268 unsigned int width; 270 unsigned int width;
269 unsigned int height; 271 unsigned int height;
@@ -273,14 +275,9 @@ struct s2255_fh {
273 /* mode below is the desired mode. 275 /* mode below is the desired mode.
274 mode in s2255_dev is the current mode that was last set */ 276 mode in s2255_dev is the current mode that was last set */
275 struct s2255_mode mode; 277 struct s2255_mode mode;
278 int resources[MAX_CHANNELS];
276}; 279};
277 280
278/*
279 * TODO: fixme S2255_MAX_USERS. Do not limit open driver handles.
280 * Limit V4L to one stream at a time.
281 */
282#define S2255_MAX_USERS 1
283
284#define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */ 281#define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */
285#define S2255_MAJOR_VERSION 1 282#define S2255_MAJOR_VERSION 1
286#define S2255_MINOR_VERSION 13 283#define S2255_MINOR_VERSION 13
@@ -476,10 +473,9 @@ static void s2255_timer(unsigned long user_data)
476 dprintk(100, "s2255 timer\n"); 473 dprintk(100, "s2255 timer\n");
477 if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) { 474 if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) {
478 printk(KERN_ERR "s2255: can't submit urb\n"); 475 printk(KERN_ERR "s2255: can't submit urb\n");
479 if (data->fw) { 476 atomic_set(&data->fw_state, S2255_FW_FAILED);
480 release_firmware(data->fw); 477 /* wake up anything waiting for the firmware */
481 data->fw = NULL; 478 wake_up(&data->wait_fw);
482 }
483 return; 479 return;
484 } 480 }
485} 481}
@@ -509,13 +505,18 @@ static void s2255_fwchunk_complete(struct urb *urb)
509 struct usb_device *udev = urb->dev; 505 struct usb_device *udev = urb->dev;
510 int len; 506 int len;
511 dprintk(100, "udev %p urb %p", udev, urb); 507 dprintk(100, "udev %p urb %p", udev, urb);
512 /* TODO: fixme. reflect change in status */
513 if (urb->status) { 508 if (urb->status) {
514 dev_err(&udev->dev, "URB failed with status %d", urb->status); 509 dev_err(&udev->dev, "URB failed with status %d", urb->status);
510 atomic_set(&data->fw_state, S2255_FW_FAILED);
511 /* wake up anything waiting for the firmware */
512 wake_up(&data->wait_fw);
515 return; 513 return;
516 } 514 }
517 if (data->fw_urb == NULL) { 515 if (data->fw_urb == NULL) {
518 dev_err(&udev->dev, "early disconncect\n"); 516 dev_err(&udev->dev, "s2255 disconnected\n");
517 atomic_set(&data->fw_state, S2255_FW_FAILED);
518 /* wake up anything waiting for the firmware */
519 wake_up(&data->wait_fw);
519 return; 520 return;
520 } 521 }
521#define CHUNK_SIZE 512 522#define CHUNK_SIZE 512
@@ -789,7 +790,8 @@ static int res_get(struct s2255_dev *dev, struct s2255_fh *fh)
789 } 790 }
790 /* it's free, grab it */ 791 /* it's free, grab it */
791 dev->resources[fh->channel] = 1; 792 dev->resources[fh->channel] = 1;
792 dprintk(1, "res: get\n"); 793 fh->resources[fh->channel] = 1;
794 dprintk(1, "s2255: res: get\n");
793 mutex_unlock(&dev->lock); 795 mutex_unlock(&dev->lock);
794 return 1; 796 return 1;
795} 797}
@@ -799,9 +801,18 @@ static int res_locked(struct s2255_dev *dev, struct s2255_fh *fh)
799 return dev->resources[fh->channel]; 801 return dev->resources[fh->channel];
800} 802}
801 803
804static int res_check(struct s2255_fh *fh)
805{
806 return fh->resources[fh->channel];
807}
808
809
802static void res_free(struct s2255_dev *dev, struct s2255_fh *fh) 810static void res_free(struct s2255_dev *dev, struct s2255_fh *fh)
803{ 811{
812 mutex_lock(&dev->lock);
804 dev->resources[fh->channel] = 0; 813 dev->resources[fh->channel] = 0;
814 fh->resources[fh->channel] = 0;
815 mutex_unlock(&dev->lock);
805 dprintk(1, "res: put\n"); 816 dprintk(1, "res: put\n");
806} 817}
807 818
@@ -1232,7 +1243,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
1232 } 1243 }
1233 1244
1234 if (!res_get(dev, fh)) { 1245 if (!res_get(dev, fh)) {
1235 dev_err(&dev->udev->dev, "res get busy\n"); 1246 dev_err(&dev->udev->dev, "s2255: stream busy\n");
1236 return -EBUSY; 1247 return -EBUSY;
1237 } 1248 }
1238 1249
@@ -1288,8 +1299,10 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
1288 } 1299 }
1289 s2255_stop_acquire(dev, fh->channel); 1300 s2255_stop_acquire(dev, fh->channel);
1290 res = videobuf_streamoff(&fh->vb_vidq); 1301 res = videobuf_streamoff(&fh->vb_vidq);
1302 if (res < 0)
1303 return res;
1291 res_free(dev, fh); 1304 res_free(dev, fh);
1292 return res; 1305 return 0;
1293} 1306}
1294 1307
1295static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) 1308static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
@@ -1462,12 +1475,7 @@ static int s2255_open(struct inode *inode, struct file *file)
1462 mutex_lock(&dev->open_lock); 1475 mutex_lock(&dev->open_lock);
1463 1476
1464 dev->users[cur_channel]++; 1477 dev->users[cur_channel]++;
1465 if (dev->users[cur_channel] > S2255_MAX_USERS) { 1478 dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]);
1466 dev->users[cur_channel]--;
1467 mutex_unlock(&dev->open_lock);
1468 printk(KERN_INFO "s2255drv: too many open handles!\n");
1469 return -EBUSY;
1470 }
1471 1479
1472 if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) { 1480 if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) {
1473 err("2255 firmware load failed. retrying.\n"); 1481 err("2255 firmware load failed. retrying.\n");
@@ -1478,7 +1486,8 @@ static int s2255_open(struct inode *inode, struct file *file)
1478 msecs_to_jiffies(S2255_LOAD_TIMEOUT)); 1486 msecs_to_jiffies(S2255_LOAD_TIMEOUT));
1479 if (atomic_read(&dev->fw_data->fw_state) 1487 if (atomic_read(&dev->fw_data->fw_state)
1480 != S2255_FW_SUCCESS) { 1488 != S2255_FW_SUCCESS) {
1481 printk(KERN_INFO "2255 FW load failed after 2 tries\n"); 1489 printk(KERN_INFO "2255 FW load failed.\n");
1490 dev->users[cur_channel]--;
1482 mutex_unlock(&dev->open_lock); 1491 mutex_unlock(&dev->open_lock);
1483 return -EFAULT; 1492 return -EFAULT;
1484 } 1493 }
@@ -1494,6 +1503,7 @@ static int s2255_open(struct inode *inode, struct file *file)
1494 != S2255_FW_SUCCESS) { 1503 != S2255_FW_SUCCESS) {
1495 printk(KERN_INFO "2255 firmware not loaded" 1504 printk(KERN_INFO "2255 firmware not loaded"
1496 "try again\n"); 1505 "try again\n");
1506 dev->users[cur_channel]--;
1497 mutex_unlock(&dev->open_lock); 1507 mutex_unlock(&dev->open_lock);
1498 return -EBUSY; 1508 return -EBUSY;
1499 } 1509 }
@@ -1502,6 +1512,7 @@ static int s2255_open(struct inode *inode, struct file *file)
1502 /* allocate + initialize per filehandle data */ 1512 /* allocate + initialize per filehandle data */
1503 fh = kzalloc(sizeof(*fh), GFP_KERNEL); 1513 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
1504 if (NULL == fh) { 1514 if (NULL == fh) {
1515 dev->users[cur_channel]--;
1505 mutex_unlock(&dev->open_lock); 1516 mutex_unlock(&dev->open_lock);
1506 return -ENOMEM; 1517 return -ENOMEM;
1507 } 1518 }
@@ -1561,44 +1572,48 @@ static void s2255_destroy(struct kref *kref)
1561 printk(KERN_ERR "s2255drv: kref problem\n"); 1572 printk(KERN_ERR "s2255drv: kref problem\n");
1562 return; 1573 return;
1563 } 1574 }
1575
1576 /*
1577 * Wake up any firmware load waiting (only done in .open,
1578 * which holds the open_lock mutex)
1579 */
1580 atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
1581 wake_up(&dev->fw_data->wait_fw);
1582
1564 /* prevent s2255_disconnect from racing s2255_open */ 1583 /* prevent s2255_disconnect from racing s2255_open */
1565 mutex_lock(&dev->open_lock); 1584 mutex_lock(&dev->open_lock);
1566 s2255_exit_v4l(dev); 1585 s2255_exit_v4l(dev);
1567 /* device unregistered so no longer possible to open. open_mutex 1586 /*
1568 can be unlocked */ 1587 * device unregistered so no longer possible to open. open_mutex
1588 * can be unlocked and timers deleted afterwards.
1589 */
1569 mutex_unlock(&dev->open_lock); 1590 mutex_unlock(&dev->open_lock);
1570 1591
1571 /* board shutdown stops the read pipe if it is running */ 1592 /* board shutdown stops the read pipe if it is running */
1572 s2255_board_shutdown(dev); 1593 s2255_board_shutdown(dev);
1573 1594
1574 /* make sure firmware still not trying to load */ 1595 /* make sure firmware still not trying to load */
1596 del_timer(&dev->timer); /* only started in .probe and .open */
1597
1575 if (dev->fw_data->fw_urb) { 1598 if (dev->fw_data->fw_urb) {
1576 dprintk(2, "kill fw_urb\n"); 1599 dprintk(2, "kill fw_urb\n");
1577 usb_kill_urb(dev->fw_data->fw_urb); 1600 usb_kill_urb(dev->fw_data->fw_urb);
1578 usb_free_urb(dev->fw_data->fw_urb); 1601 usb_free_urb(dev->fw_data->fw_urb);
1579 dev->fw_data->fw_urb = NULL; 1602 dev->fw_data->fw_urb = NULL;
1580 } 1603 }
1604
1581 /* 1605 /*
1582 * TODO: fixme(above, below): potentially leaving timers alive. 1606 * delete the dsp_wait timer, which sets the firmware
1583 * do not ignore timeout below if 1607 * state on completion. This is done before fw_data
1584 * it occurs. 1608 * is freed below.
1585 */ 1609 */
1586 1610
1587 /* make sure we aren't waiting for the DSP */ 1611 del_timer(&dev->fw_data->dsp_wait); /* only started in .open */
1588 if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_LOADED_DSPWAIT) {
1589 /* if we are, wait for the wakeup for fw_success or timeout */
1590 wait_event_timeout(dev->fw_data->wait_fw,
1591 (atomic_read(&dev->fw_data->fw_state)
1592 == S2255_FW_SUCCESS),
1593 msecs_to_jiffies(S2255_LOAD_TIMEOUT));
1594 }
1595 1612
1596 if (dev->fw_data) { 1613 if (dev->fw_data->fw)
1597 if (dev->fw_data->fw) 1614 release_firmware(dev->fw_data->fw);
1598 release_firmware(dev->fw_data->fw); 1615 kfree(dev->fw_data->pfw_data);
1599 kfree(dev->fw_data->pfw_data); 1616 kfree(dev->fw_data);
1600 kfree(dev->fw_data);
1601 }
1602 1617
1603 usb_put_dev(dev->udev); 1618 usb_put_dev(dev->udev);
1604 dprintk(1, "%s", __func__); 1619 dprintk(1, "%s", __func__);
@@ -1615,17 +1630,23 @@ static int s2255_close(struct inode *inode, struct file *file)
1615 1630
1616 mutex_lock(&dev->open_lock); 1631 mutex_lock(&dev->open_lock);
1617 1632
1618 if (dev->b_acquire[fh->channel]) 1633 /* turn off stream */
1619 s2255_stop_acquire(dev, fh->channel); 1634 if (res_check(fh)) {
1620 res_free(dev, fh); 1635 if (dev->b_acquire[fh->channel])
1636 s2255_stop_acquire(dev, fh->channel);
1637 videobuf_streamoff(&fh->vb_vidq);
1638 res_free(dev, fh);
1639 }
1640
1621 videobuf_mmap_free(&fh->vb_vidq); 1641 videobuf_mmap_free(&fh->vb_vidq);
1622 kfree(fh);
1623 dev->users[fh->channel]--; 1642 dev->users[fh->channel]--;
1643
1624 mutex_unlock(&dev->open_lock); 1644 mutex_unlock(&dev->open_lock);
1625 1645
1626 kref_put(&dev->kref, s2255_destroy); 1646 kref_put(&dev->kref, s2255_destroy);
1627 dprintk(1, "s2255: close called (minor=%d, users=%d)\n", 1647 dprintk(1, "s2255: close called (minor=%d, users=%d)\n",
1628 minor, dev->users[fh->channel]); 1648 minor, dev->users[fh->channel]);
1649 kfree(fh);
1629 return 0; 1650 return 0;
1630} 1651}
1631 1652
@@ -1658,12 +1679,7 @@ static const struct file_operations s2255_fops_v4l = {
1658 .llseek = no_llseek, 1679 .llseek = no_llseek,
1659}; 1680};
1660 1681
1661static struct video_device template = { 1682static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
1662 .name = "s2255v",
1663 .type = VID_TYPE_CAPTURE,
1664 .fops = &s2255_fops_v4l,
1665 .minor = -1,
1666 .release = video_device_release,
1667 .vidioc_querycap = vidioc_querycap, 1683 .vidioc_querycap = vidioc_querycap,
1668 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, 1684 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1669 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, 1685 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
@@ -1685,6 +1701,14 @@ static struct video_device template = {
1685#ifdef CONFIG_VIDEO_V4L1_COMPAT 1701#ifdef CONFIG_VIDEO_V4L1_COMPAT
1686 .vidiocgmbuf = vidioc_cgmbuf, 1702 .vidiocgmbuf = vidioc_cgmbuf,
1687#endif 1703#endif
1704};
1705
1706static struct video_device template = {
1707 .name = "s2255v",
1708 .fops = &s2255_fops_v4l,
1709 .ioctl_ops = &s2255_ioctl_ops,
1710 .minor = -1,
1711 .release = video_device_release,
1688 .tvnorms = S2255_NORMS, 1712 .tvnorms = S2255_NORMS,
1689 .current_norm = V4L2_STD_NTSC_M, 1713 .current_norm = V4L2_STD_NTSC_M,
1690}; 1714};
@@ -1706,7 +1730,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
1706 /* register 4 video devices */ 1730 /* register 4 video devices */
1707 dev->vdev[i] = video_device_alloc(); 1731 dev->vdev[i] = video_device_alloc();
1708 memcpy(dev->vdev[i], &template, sizeof(struct video_device)); 1732 memcpy(dev->vdev[i], &template, sizeof(struct video_device));
1709 dev->vdev[i]->dev = &dev->interface->dev; 1733 dev->vdev[i]->parent = &dev->interface->dev;
1710 if (video_nr == -1) 1734 if (video_nr == -1)
1711 ret = video_register_device(dev->vdev[i], 1735 ret = video_register_device(dev->vdev[i],
1712 VFL_TYPE_GRABBER, 1736 VFL_TYPE_GRABBER,