mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 09:14:19 +08:00
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>
This commit is contained in:
parent
723fb9b79b
commit
4de39f5d6f
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* s2255drv.c - a driver for the Sensoray 2255 USB video capture device
|
* s2255drv.c - a driver for the Sensoray 2255 USB video capture device
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2008 by Sensoray Company Inc.
|
* Copyright (C) 2007-2010 by Sensoray Company Inc.
|
||||||
* Dean Anderson
|
* Dean Anderson
|
||||||
*
|
*
|
||||||
* Some video buffer code based on vivi driver:
|
* Some video buffer code based on vivi driver:
|
||||||
@ -76,11 +76,13 @@
|
|||||||
#define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME)
|
#define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME)
|
||||||
#define S2255_DEF_BUFS 16
|
#define S2255_DEF_BUFS 16
|
||||||
#define S2255_SETMODE_TIMEOUT 500
|
#define S2255_SETMODE_TIMEOUT 500
|
||||||
|
#define S2255_VIDSTATUS_TIMEOUT 350
|
||||||
#define MAX_CHANNELS 4
|
#define MAX_CHANNELS 4
|
||||||
#define S2255_MARKER_FRAME 0x2255DA4AL
|
#define S2255_MARKER_FRAME 0x2255DA4AL
|
||||||
#define S2255_MARKER_RESPONSE 0x2255ACACL
|
#define S2255_MARKER_RESPONSE 0x2255ACACL
|
||||||
#define S2255_RESPONSE_SETMODE 0x01
|
#define S2255_RESPONSE_SETMODE 0x01
|
||||||
#define S2255_RESPONSE_FW 0x10
|
#define S2255_RESPONSE_FW 0x10
|
||||||
|
#define S2255_RESPONSE_STATUS 0x20
|
||||||
#define S2255_USB_XFER_SIZE (16 * 1024)
|
#define S2255_USB_XFER_SIZE (16 * 1024)
|
||||||
#define MAX_CHANNELS 4
|
#define MAX_CHANNELS 4
|
||||||
#define MAX_PIPE_BUFFERS 1
|
#define MAX_PIPE_BUFFERS 1
|
||||||
@ -261,9 +263,16 @@ struct s2255_dev {
|
|||||||
int chn_configured[MAX_CHANNELS];
|
int chn_configured[MAX_CHANNELS];
|
||||||
wait_queue_head_t wait_setmode[MAX_CHANNELS];
|
wait_queue_head_t wait_setmode[MAX_CHANNELS];
|
||||||
int setmode_ready[MAX_CHANNELS];
|
int setmode_ready[MAX_CHANNELS];
|
||||||
|
/* video status items */
|
||||||
|
int vidstatus[MAX_CHANNELS];
|
||||||
|
wait_queue_head_t wait_vidstatus[MAX_CHANNELS];
|
||||||
|
int vidstatus_ready[MAX_CHANNELS];
|
||||||
|
|
||||||
int chn_ready;
|
int chn_ready;
|
||||||
struct kref kref;
|
struct kref kref;
|
||||||
spinlock_t slock;
|
spinlock_t slock;
|
||||||
|
/* dsp firmware version (f2255usb.bin) */
|
||||||
|
int dsp_fw_ver;
|
||||||
};
|
};
|
||||||
#define to_s2255_dev(d) container_of(d, struct s2255_dev, kref)
|
#define to_s2255_dev(d) container_of(d, struct s2255_dev, kref)
|
||||||
|
|
||||||
@ -296,8 +305,12 @@ struct s2255_fh {
|
|||||||
|
|
||||||
/* current cypress EEPROM firmware version */
|
/* current cypress EEPROM firmware version */
|
||||||
#define S2255_CUR_USB_FWVER ((3 << 8) | 6)
|
#define S2255_CUR_USB_FWVER ((3 << 8) | 6)
|
||||||
|
/* current DSP FW version */
|
||||||
|
#define S2255_CUR_DSP_FWVER 5
|
||||||
|
/* Need DSP version 5+ for video status feature */
|
||||||
|
#define S2255_MIN_DSP_STATUS 5
|
||||||
#define S2255_MAJOR_VERSION 1
|
#define S2255_MAJOR_VERSION 1
|
||||||
#define S2255_MINOR_VERSION 14
|
#define S2255_MINOR_VERSION 15
|
||||||
#define S2255_RELEASE 0
|
#define S2255_RELEASE 0
|
||||||
#define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \
|
#define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \
|
||||||
S2255_MINOR_VERSION, \
|
S2255_MINOR_VERSION, \
|
||||||
@ -1261,6 +1274,42 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn,
|
||||||
|
u32 *pstatus)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
u32 *buffer;
|
||||||
|
u32 chn_rev;
|
||||||
|
mutex_lock(&dev->lock);
|
||||||
|
chn_rev = G_chnmap[chn];
|
||||||
|
dprintk(4, "%s chan %d\n", __func__, chn_rev);
|
||||||
|
buffer = kzalloc(512, GFP_KERNEL);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
dev_err(&dev->udev->dev, "out of mem\n");
|
||||||
|
mutex_unlock(&dev->lock);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
/* form the get vid status command */
|
||||||
|
buffer[0] = IN_DATA_TOKEN;
|
||||||
|
buffer[1] = chn_rev;
|
||||||
|
buffer[2] = CMD_STATUS;
|
||||||
|
*pstatus = 0;
|
||||||
|
dev->vidstatus_ready[chn] = 0;
|
||||||
|
res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
|
||||||
|
kfree(buffer);
|
||||||
|
wait_event_timeout(dev->wait_vidstatus[chn],
|
||||||
|
(dev->vidstatus_ready[chn] != 0),
|
||||||
|
msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT));
|
||||||
|
if (dev->vidstatus_ready[chn] != 1) {
|
||||||
|
printk(KERN_DEBUG "s2255: no vidstatus response\n");
|
||||||
|
res = -EFAULT;
|
||||||
|
}
|
||||||
|
*pstatus = dev->vidstatus[chn];
|
||||||
|
dprintk(4, "%s, vid status %d\n", __func__, *pstatus);
|
||||||
|
mutex_unlock(&dev->lock);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
|
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
@ -1386,11 +1435,24 @@ out_s_std:
|
|||||||
static int vidioc_enum_input(struct file *file, void *priv,
|
static int vidioc_enum_input(struct file *file, void *priv,
|
||||||
struct v4l2_input *inp)
|
struct v4l2_input *inp)
|
||||||
{
|
{
|
||||||
|
struct s2255_fh *fh = priv;
|
||||||
|
struct s2255_dev *dev = fh->dev;
|
||||||
|
u32 status = 0;
|
||||||
|
|
||||||
if (inp->index != 0)
|
if (inp->index != 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
inp->type = V4L2_INPUT_TYPE_CAMERA;
|
inp->type = V4L2_INPUT_TYPE_CAMERA;
|
||||||
inp->std = S2255_NORMS;
|
inp->std = S2255_NORMS;
|
||||||
|
inp->status = 0;
|
||||||
|
if (dev->dsp_fw_ver >= S2255_MIN_DSP_STATUS) {
|
||||||
|
int rc;
|
||||||
|
rc = s2255_cmd_status(dev, fh->channel, &status);
|
||||||
|
dprintk(4, "s2255_cmd_status rc: %d status %x\n", rc, status);
|
||||||
|
if (rc == 0)
|
||||||
|
inp->status = (status & 0x01) ? 0
|
||||||
|
: V4L2_IN_ST_NO_SIGNAL;
|
||||||
|
}
|
||||||
strlcpy(inp->name, "Camera", sizeof(inp->name));
|
strlcpy(inp->name, "Camera", sizeof(inp->name));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1700,6 +1762,8 @@ static void s2255_destroy(struct kref *kref)
|
|||||||
for (i = 0; i < MAX_CHANNELS; i++) {
|
for (i = 0; i < MAX_CHANNELS; i++) {
|
||||||
dev->setmode_ready[i] = 1;
|
dev->setmode_ready[i] = 1;
|
||||||
wake_up(&dev->wait_setmode[i]);
|
wake_up(&dev->wait_setmode[i]);
|
||||||
|
dev->vidstatus_ready[i] = 1;
|
||||||
|
wake_up(&dev->wait_vidstatus[i]);
|
||||||
}
|
}
|
||||||
mutex_lock(&dev->open_lock);
|
mutex_lock(&dev->open_lock);
|
||||||
/* reset the DSP so firmware can be reload next time */
|
/* 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)
|
|||||||
S2255_FW_SUCCESS);
|
S2255_FW_SUCCESS);
|
||||||
wake_up(&dev->fw_data->wait_fw);
|
wake_up(&dev->fw_data->wait_fw);
|
||||||
break;
|
break;
|
||||||
|
case S2255_RESPONSE_STATUS:
|
||||||
|
dev->vidstatus[cc] = pdword[3];
|
||||||
|
dev->vidstatus_ready[cc] = 1;
|
||||||
|
wake_up(&dev->wait_vidstatus[cc]);
|
||||||
|
dprintk(5, "got vidstatus %x chan %d\n",
|
||||||
|
pdword[3], cc);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_INFO "s2255 unknown resp\n");
|
printk(KERN_INFO "s2255 unknown resp\n");
|
||||||
}
|
}
|
||||||
@ -2527,9 +2598,10 @@ static int s2255_probe(struct usb_interface *interface,
|
|||||||
dev->timer.data = (unsigned long)dev->fw_data;
|
dev->timer.data = (unsigned long)dev->fw_data;
|
||||||
|
|
||||||
init_waitqueue_head(&dev->fw_data->wait_fw);
|
init_waitqueue_head(&dev->fw_data->wait_fw);
|
||||||
for (i = 0; i < MAX_CHANNELS; i++)
|
for (i = 0; i < MAX_CHANNELS; i++) {
|
||||||
init_waitqueue_head(&dev->wait_setmode[i]);
|
init_waitqueue_head(&dev->wait_setmode[i]);
|
||||||
|
init_waitqueue_head(&dev->wait_vidstatus[i]);
|
||||||
|
}
|
||||||
|
|
||||||
dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
|
dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
|
|
||||||
@ -2561,6 +2633,9 @@ static int s2255_probe(struct usb_interface *interface,
|
|||||||
__le32 *pRel;
|
__le32 *pRel;
|
||||||
pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4];
|
pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4];
|
||||||
printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel);
|
printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel);
|
||||||
|
dev->dsp_fw_ver = *pRel;
|
||||||
|
if (*pRel < S2255_CUR_DSP_FWVER)
|
||||||
|
printk(KERN_INFO "s2255: f2255usb.bin out of date.\n");
|
||||||
}
|
}
|
||||||
/* loads v4l specific */
|
/* loads v4l specific */
|
||||||
s2255_probe_v4l(dev);
|
s2255_probe_v4l(dev);
|
||||||
@ -2597,6 +2672,8 @@ static void s2255_disconnect(struct usb_interface *interface)
|
|||||||
for (i = 0; i < MAX_CHANNELS; i++) {
|
for (i = 0; i < MAX_CHANNELS; i++) {
|
||||||
dev->setmode_ready[i] = 1;
|
dev->setmode_ready[i] = 1;
|
||||||
wake_up(&dev->wait_setmode[i]);
|
wake_up(&dev->wait_setmode[i]);
|
||||||
|
dev->vidstatus_ready[i] = 1;
|
||||||
|
wake_up(&dev->wait_vidstatus[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&dev->open_lock);
|
mutex_lock(&dev->open_lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user