diff options
author | Dean Anderson <dean@sensoray.com> | 2010-03-03 17:39:19 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-17 23:46:33 -0400 |
commit | 4de39f5d6f8267a0b062cba70eaa84fb161007e4 (patch) | |
tree | fa6dd392a37c12bdfcfb336bc546b1845d2380ab /drivers/media/video/s2255drv.c | |
parent | 723fb9b79b5a2279ed8ea8adfa6f6c92d73deaa2 (diff) |
V4L/DVB: s2255drv: adding video input status capability
Video status capability for inputs on Sensoray 2255 driver.
Signed-off-by: Dean Anderson <dean@sensoray.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/s2255drv.c')
-rw-r--r-- | drivers/media/video/s2255drv.c | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 3de914deb8ee..a9c53335fd8f 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * s2255drv.c - a driver for the Sensoray 2255 USB video capture device | 2 | * s2255drv.c - a driver for the Sensoray 2255 USB video capture device |
3 | * | 3 | * |
4 | * Copyright (C) 2007-2008 by Sensoray Company Inc. | 4 | * Copyright (C) 2007-2010 by Sensoray Company Inc. |
5 | * Dean Anderson | 5 | * Dean Anderson |
6 | * | 6 | * |
7 | * Some video buffer code based on vivi driver: | 7 | * Some video buffer code based on vivi driver: |
@@ -76,11 +76,13 @@ | |||
76 | #define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME) | 76 | #define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME) |
77 | #define S2255_DEF_BUFS 16 | 77 | #define S2255_DEF_BUFS 16 |
78 | #define S2255_SETMODE_TIMEOUT 500 | 78 | #define S2255_SETMODE_TIMEOUT 500 |
79 | #define S2255_VIDSTATUS_TIMEOUT 350 | ||
79 | #define MAX_CHANNELS 4 | 80 | #define MAX_CHANNELS 4 |
80 | #define S2255_MARKER_FRAME 0x2255DA4AL | 81 | #define S2255_MARKER_FRAME 0x2255DA4AL |
81 | #define S2255_MARKER_RESPONSE 0x2255ACACL | 82 | #define S2255_MARKER_RESPONSE 0x2255ACACL |
82 | #define S2255_RESPONSE_SETMODE 0x01 | 83 | #define S2255_RESPONSE_SETMODE 0x01 |
83 | #define S2255_RESPONSE_FW 0x10 | 84 | #define S2255_RESPONSE_FW 0x10 |
85 | #define S2255_RESPONSE_STATUS 0x20 | ||
84 | #define S2255_USB_XFER_SIZE (16 * 1024) | 86 | #define S2255_USB_XFER_SIZE (16 * 1024) |
85 | #define MAX_CHANNELS 4 | 87 | #define MAX_CHANNELS 4 |
86 | #define MAX_PIPE_BUFFERS 1 | 88 | #define MAX_PIPE_BUFFERS 1 |
@@ -261,9 +263,16 @@ struct s2255_dev { | |||
261 | int chn_configured[MAX_CHANNELS]; | 263 | int chn_configured[MAX_CHANNELS]; |
262 | wait_queue_head_t wait_setmode[MAX_CHANNELS]; | 264 | wait_queue_head_t wait_setmode[MAX_CHANNELS]; |
263 | int setmode_ready[MAX_CHANNELS]; | 265 | int setmode_ready[MAX_CHANNELS]; |
266 | /* video status items */ | ||
267 | int vidstatus[MAX_CHANNELS]; | ||
268 | wait_queue_head_t wait_vidstatus[MAX_CHANNELS]; | ||
269 | int vidstatus_ready[MAX_CHANNELS]; | ||
270 | |||
264 | int chn_ready; | 271 | int chn_ready; |
265 | struct kref kref; | 272 | struct kref kref; |
266 | spinlock_t slock; | 273 | spinlock_t slock; |
274 | /* dsp firmware version (f2255usb.bin) */ | ||
275 | int dsp_fw_ver; | ||
267 | }; | 276 | }; |
268 | #define to_s2255_dev(d) container_of(d, struct s2255_dev, kref) | 277 | #define to_s2255_dev(d) container_of(d, struct s2255_dev, kref) |
269 | 278 | ||
@@ -296,8 +305,12 @@ struct s2255_fh { | |||
296 | 305 | ||
297 | /* current cypress EEPROM firmware version */ | 306 | /* current cypress EEPROM firmware version */ |
298 | #define S2255_CUR_USB_FWVER ((3 << 8) | 6) | 307 | #define S2255_CUR_USB_FWVER ((3 << 8) | 6) |
308 | /* current DSP FW version */ | ||
309 | #define S2255_CUR_DSP_FWVER 5 | ||
310 | /* Need DSP version 5+ for video status feature */ | ||
311 | #define S2255_MIN_DSP_STATUS 5 | ||
299 | #define S2255_MAJOR_VERSION 1 | 312 | #define S2255_MAJOR_VERSION 1 |
300 | #define S2255_MINOR_VERSION 14 | 313 | #define S2255_MINOR_VERSION 15 |
301 | #define S2255_RELEASE 0 | 314 | #define S2255_RELEASE 0 |
302 | #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ | 315 | #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ |
303 | S2255_MINOR_VERSION, \ | 316 | S2255_MINOR_VERSION, \ |
@@ -1261,6 +1274,42 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
1261 | return res; | 1274 | return res; |
1262 | } | 1275 | } |
1263 | 1276 | ||
1277 | static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn, | ||
1278 | u32 *pstatus) | ||
1279 | { | ||
1280 | int res; | ||
1281 | u32 *buffer; | ||
1282 | u32 chn_rev; | ||
1283 | mutex_lock(&dev->lock); | ||
1284 | chn_rev = G_chnmap[chn]; | ||
1285 | dprintk(4, "%s chan %d\n", __func__, chn_rev); | ||
1286 | buffer = kzalloc(512, GFP_KERNEL); | ||
1287 | if (buffer == NULL) { | ||
1288 | dev_err(&dev->udev->dev, "out of mem\n"); | ||
1289 | mutex_unlock(&dev->lock); | ||
1290 | return -ENOMEM; | ||
1291 | } | ||
1292 | /* form the get vid status command */ | ||
1293 | buffer[0] = IN_DATA_TOKEN; | ||
1294 | buffer[1] = chn_rev; | ||
1295 | buffer[2] = CMD_STATUS; | ||
1296 | *pstatus = 0; | ||
1297 | dev->vidstatus_ready[chn] = 0; | ||
1298 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); | ||
1299 | kfree(buffer); | ||
1300 | wait_event_timeout(dev->wait_vidstatus[chn], | ||
1301 | (dev->vidstatus_ready[chn] != 0), | ||
1302 | msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT)); | ||
1303 | if (dev->vidstatus_ready[chn] != 1) { | ||
1304 | printk(KERN_DEBUG "s2255: no vidstatus response\n"); | ||
1305 | res = -EFAULT; | ||
1306 | } | ||
1307 | *pstatus = dev->vidstatus[chn]; | ||
1308 | dprintk(4, "%s, vid status %d\n", __func__, *pstatus); | ||
1309 | mutex_unlock(&dev->lock); | ||
1310 | return res; | ||
1311 | } | ||
1312 | |||
1264 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | 1313 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
1265 | { | 1314 | { |
1266 | int res; | 1315 | int res; |
@@ -1386,11 +1435,24 @@ out_s_std: | |||
1386 | static int vidioc_enum_input(struct file *file, void *priv, | 1435 | static int vidioc_enum_input(struct file *file, void *priv, |
1387 | struct v4l2_input *inp) | 1436 | struct v4l2_input *inp) |
1388 | { | 1437 | { |
1438 | struct s2255_fh *fh = priv; | ||
1439 | struct s2255_dev *dev = fh->dev; | ||
1440 | u32 status = 0; | ||
1441 | |||
1389 | if (inp->index != 0) | 1442 | if (inp->index != 0) |
1390 | return -EINVAL; | 1443 | return -EINVAL; |
1391 | 1444 | ||
1392 | inp->type = V4L2_INPUT_TYPE_CAMERA; | 1445 | inp->type = V4L2_INPUT_TYPE_CAMERA; |
1393 | inp->std = S2255_NORMS; | 1446 | inp->std = S2255_NORMS; |
1447 | inp->status = 0; | ||
1448 | if (dev->dsp_fw_ver >= S2255_MIN_DSP_STATUS) { | ||
1449 | int rc; | ||
1450 | rc = s2255_cmd_status(dev, fh->channel, &status); | ||
1451 | dprintk(4, "s2255_cmd_status rc: %d status %x\n", rc, status); | ||
1452 | if (rc == 0) | ||
1453 | inp->status = (status & 0x01) ? 0 | ||
1454 | : V4L2_IN_ST_NO_SIGNAL; | ||
1455 | } | ||
1394 | strlcpy(inp->name, "Camera", sizeof(inp->name)); | 1456 | strlcpy(inp->name, "Camera", sizeof(inp->name)); |
1395 | return 0; | 1457 | return 0; |
1396 | } | 1458 | } |
@@ -1700,6 +1762,8 @@ static void s2255_destroy(struct kref *kref) | |||
1700 | for (i = 0; i < MAX_CHANNELS; i++) { | 1762 | for (i = 0; i < MAX_CHANNELS; i++) { |
1701 | dev->setmode_ready[i] = 1; | 1763 | dev->setmode_ready[i] = 1; |
1702 | wake_up(&dev->wait_setmode[i]); | 1764 | wake_up(&dev->wait_setmode[i]); |
1765 | dev->vidstatus_ready[i] = 1; | ||
1766 | wake_up(&dev->wait_vidstatus[i]); | ||
1703 | } | 1767 | } |
1704 | mutex_lock(&dev->open_lock); | 1768 | mutex_lock(&dev->open_lock); |
1705 | /* reset the DSP so firmware can be reload next time */ | 1769 | /* reset the DSP so firmware can be reload next time */ |
@@ -1965,6 +2029,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
1965 | S2255_FW_SUCCESS); | 2029 | S2255_FW_SUCCESS); |
1966 | wake_up(&dev->fw_data->wait_fw); | 2030 | wake_up(&dev->fw_data->wait_fw); |
1967 | break; | 2031 | break; |
2032 | case S2255_RESPONSE_STATUS: | ||
2033 | dev->vidstatus[cc] = pdword[3]; | ||
2034 | dev->vidstatus_ready[cc] = 1; | ||
2035 | wake_up(&dev->wait_vidstatus[cc]); | ||
2036 | dprintk(5, "got vidstatus %x chan %d\n", | ||
2037 | pdword[3], cc); | ||
2038 | break; | ||
1968 | default: | 2039 | default: |
1969 | printk(KERN_INFO "s2255 unknown resp\n"); | 2040 | printk(KERN_INFO "s2255 unknown resp\n"); |
1970 | } | 2041 | } |
@@ -2527,9 +2598,10 @@ static int s2255_probe(struct usb_interface *interface, | |||
2527 | dev->timer.data = (unsigned long)dev->fw_data; | 2598 | dev->timer.data = (unsigned long)dev->fw_data; |
2528 | 2599 | ||
2529 | init_waitqueue_head(&dev->fw_data->wait_fw); | 2600 | init_waitqueue_head(&dev->fw_data->wait_fw); |
2530 | for (i = 0; i < MAX_CHANNELS; i++) | 2601 | for (i = 0; i < MAX_CHANNELS; i++) { |
2531 | init_waitqueue_head(&dev->wait_setmode[i]); | 2602 | init_waitqueue_head(&dev->wait_setmode[i]); |
2532 | 2603 | init_waitqueue_head(&dev->wait_vidstatus[i]); | |
2604 | } | ||
2533 | 2605 | ||
2534 | dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); | 2606 | dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); |
2535 | 2607 | ||
@@ -2561,6 +2633,9 @@ static int s2255_probe(struct usb_interface *interface, | |||
2561 | __le32 *pRel; | 2633 | __le32 *pRel; |
2562 | pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; | 2634 | pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; |
2563 | printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); | 2635 | printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); |
2636 | dev->dsp_fw_ver = *pRel; | ||
2637 | if (*pRel < S2255_CUR_DSP_FWVER) | ||
2638 | printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); | ||
2564 | } | 2639 | } |
2565 | /* loads v4l specific */ | 2640 | /* loads v4l specific */ |
2566 | s2255_probe_v4l(dev); | 2641 | s2255_probe_v4l(dev); |
@@ -2597,6 +2672,8 @@ static void s2255_disconnect(struct usb_interface *interface) | |||
2597 | for (i = 0; i < MAX_CHANNELS; i++) { | 2672 | for (i = 0; i < MAX_CHANNELS; i++) { |
2598 | dev->setmode_ready[i] = 1; | 2673 | dev->setmode_ready[i] = 1; |
2599 | wake_up(&dev->wait_setmode[i]); | 2674 | wake_up(&dev->wait_setmode[i]); |
2675 | dev->vidstatus_ready[i] = 1; | ||
2676 | wake_up(&dev->wait_vidstatus[i]); | ||
2600 | } | 2677 | } |
2601 | 2678 | ||
2602 | mutex_lock(&dev->open_lock); | 2679 | mutex_lock(&dev->open_lock); |