提交 9f719637 编写于 作者: L Linus Torvalds

Merge branch 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6:
  V4L/DVB: uvc: Fix multiple symbols definitions with UVC gadget and host drivers
  V4L/DVB: v4l: mem2mem_testdev: fix g_fmt NULL pointer dereference
  V4L/DVB: uvcvideo: Power line frequency control doesn't support GET_MIN/MAX/RES
  V4L/DVB: ivtv: Add delay to ensure the decoder always restarts with a blank screen
  V4L/DVB: Documentation: Add the Philips FQ1236 MK5 to video4linux/CARDLIST.tuner
  V4L/DVB: tveeprom: Add an entry for tuner code 168: a TCL M30WTP-4N-E tuner
  V4L/DVB: tuner: Add a definition for the Philips FQ1236 MK5 NTSC tuner
  V4L/DVB: OMAP_VOUT: fix: Module params were not working through bootargs
  V4L/DVB: OMAP_VOUT: fix: Replaced dma-sg with dma-contig
  V4L/DVB: OMAP_VOUT:Build FIX: Rebased against latest DSS2 changes
...@@ -82,3 +82,4 @@ tuner=81 - Partsnic (Daewoo) PTI-5NF05 ...@@ -82,3 +82,4 @@ tuner=81 - Partsnic (Daewoo) PTI-5NF05
tuner=82 - Philips CU1216L tuner=82 - Philips CU1216L
tuner=83 - NXP TDA18271 tuner=83 - NXP TDA18271
tuner=84 - Sony BTF-Pxn01Z tuner=84 - Sony BTF-Pxn01Z
tuner=85 - Philips FQ1236 MK5
...@@ -524,6 +524,7 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) ...@@ -524,6 +524,7 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
buffer[3] = 0x39; buffer[3] = 0x39;
break; break;
case TUNER_PHILIPS_FQ1216LME_MK3: case TUNER_PHILIPS_FQ1216LME_MK3:
case TUNER_PHILIPS_FQ1236_MK5:
tuner_err("This tuner doesn't have FM\n"); tuner_err("This tuner doesn't have FM\n");
/* Set the low band for sanity, since it covers 88-108 MHz */ /* Set the low band for sanity, since it covers 88-108 MHz */
buffer[3] = 0x01; buffer[3] = 0x01;
......
...@@ -1353,6 +1353,17 @@ static struct tuner_params tuner_sony_btf_pxn01z_params[] = { ...@@ -1353,6 +1353,17 @@ static struct tuner_params tuner_sony_btf_pxn01z_params[] = {
}, },
}; };
/* ------------ TUNER_PHILIPS_FQ1236_MK5 - Philips NTSC ------------ */
static struct tuner_params tuner_philips_fq1236_mk5_params[] = {
{
.type = TUNER_PARAM_TYPE_NTSC,
.ranges = tuner_fm1236_mk3_ntsc_ranges,
.count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
.has_tda9887 = 1, /* TDA9885, no FM radio */
},
};
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
struct tunertype tuners[] = { struct tunertype tuners[] = {
...@@ -1826,6 +1837,11 @@ struct tunertype tuners[] = { ...@@ -1826,6 +1837,11 @@ struct tunertype tuners[] = {
.params = tuner_sony_btf_pxn01z_params, .params = tuner_sony_btf_pxn01z_params,
.count = ARRAY_SIZE(tuner_sony_btf_pxn01z_params), .count = ARRAY_SIZE(tuner_sony_btf_pxn01z_params),
}, },
[TUNER_PHILIPS_FQ1236_MK5] = { /* NTSC, TDA9885, no FM radio */
.name = "Philips FQ1236 MK5",
.params = tuner_philips_fq1236_mk5_params,
.count = ARRAY_SIZE(tuner_philips_fq1236_mk5_params),
},
}; };
EXPORT_SYMBOL(tuners); EXPORT_SYMBOL(tuners);
......
...@@ -912,6 +912,9 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) ...@@ -912,6 +912,9 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
clear_bit(IVTV_F_S_STREAMING, &s->s_flags); clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
ivtv_flush_queues(s); ivtv_flush_queues(s);
/* decoder needs time to settle */
ivtv_msleep_timeout(40, 0);
/* decrement decoding */ /* decrement decoding */
atomic_dec(&itv->decoding); atomic_dec(&itv->decoding);
......
...@@ -988,6 +988,9 @@ static int m2mtest_probe(struct platform_device *pdev) ...@@ -988,6 +988,9 @@ static int m2mtest_probe(struct platform_device *pdev)
goto err_m2m; goto err_m2m;
} }
q_data[V4L2_M2M_SRC].fmt = &formats[0];
q_data[V4L2_M2M_DST].fmt = &formats[0];
return 0; return 0;
err_m2m: err_m2m:
......
config VIDEO_OMAP2_VOUT config VIDEO_OMAP2_VOUT
tristate "OMAP2/OMAP3 V4L2-Display driver" tristate "OMAP2/OMAP3 V4L2-Display driver"
depends on ARCH_OMAP24XX || ARCH_OMAP34XX depends on ARCH_OMAP2 || ARCH_OMAP3
select VIDEOBUF_GEN select VIDEOBUF_GEN
select VIDEOBUF_DMA_SG select VIDEOBUF_DMA_CONTIG
select OMAP2_DSS select OMAP2_DSS
select OMAP2_VRAM select OMAP2_VRAM
select OMAP2_VRFB select OMAP2_VRFB
......
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
# #
# OMAP2/3 Display driver # OMAP2/3 Display driver
omap-vout-mod-objs := omap_vout.o omap_voutlib.o omap-vout-y := omap_vout.o omap_voutlib.o
obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout-mod.o obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o
...@@ -38,8 +38,9 @@ ...@@ -38,8 +38,9 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/slab.h>
#include <media/videobuf-dma-sg.h> #include <media/videobuf-dma-contig.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
...@@ -1053,9 +1054,9 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q, ...@@ -1053,9 +1054,9 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
struct videobuf_buffer *vb, struct videobuf_buffer *vb,
enum v4l2_field field) enum v4l2_field field)
{ {
dma_addr_t dmabuf;
struct vid_vrfb_dma *tx; struct vid_vrfb_dma *tx;
enum dss_rotation rotation; enum dss_rotation rotation;
struct videobuf_dmabuf *dmabuf = NULL;
struct omap_vout_device *vout = q->priv_data; struct omap_vout_device *vout = q->priv_data;
u32 dest_frame_index = 0, src_element_index = 0; u32 dest_frame_index = 0, src_element_index = 0;
u32 dest_element_index = 0, src_frame_index = 0; u32 dest_element_index = 0, src_frame_index = 0;
...@@ -1074,24 +1075,17 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q, ...@@ -1074,24 +1075,17 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
if (V4L2_MEMORY_USERPTR == vb->memory) { if (V4L2_MEMORY_USERPTR == vb->memory) {
if (0 == vb->baddr) if (0 == vb->baddr)
return -EINVAL; return -EINVAL;
/* Virtual address */
/* priv points to struct videobuf_pci_sg_memory. But we went
* pointer to videobuf_dmabuf, which is member of
* videobuf_pci_sg_memory */
dmabuf = videobuf_to_dma(q->bufs[vb->i]);
dmabuf->vmalloc = (void *) vb->baddr;
/* Physical address */ /* Physical address */
dmabuf->bus_addr = vout->queued_buf_addr[vb->i] = (u8 *)
(dma_addr_t) omap_vout_uservirt_to_phys(vb->baddr); omap_vout_uservirt_to_phys(vb->baddr);
} else {
vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];
} }
if (!rotation_enabled(vout)) { if (!rotation_enabled(vout))
dmabuf = videobuf_to_dma(q->bufs[vb->i]);
vout->queued_buf_addr[vb->i] = (u8 *) dmabuf->bus_addr;
return 0; return 0;
}
dmabuf = videobuf_to_dma(q->bufs[vb->i]); dmabuf = vout->buf_phy_addr[vb->i];
/* If rotation is enabled, copy input buffer into VRFB /* If rotation is enabled, copy input buffer into VRFB
* memory space using DMA. We are copying input buffer * memory space using DMA. We are copying input buffer
* into VRFB memory space of desired angle and DSS will * into VRFB memory space of desired angle and DSS will
...@@ -1120,7 +1114,7 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q, ...@@ -1120,7 +1114,7 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
tx->dev_id, 0x0); tx->dev_id, 0x0);
/* src_port required only for OMAP1 */ /* src_port required only for OMAP1 */
omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
dmabuf->bus_addr, src_element_index, src_frame_index); dmabuf, src_element_index, src_frame_index);
/*set dma source burst mode for VRFB */ /*set dma source burst mode for VRFB */
omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
rotation = calc_rotation(vout); rotation = calc_rotation(vout);
...@@ -1211,7 +1205,6 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1211,7 +1205,6 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
void *pos; void *pos;
unsigned long start = vma->vm_start; unsigned long start = vma->vm_start;
unsigned long size = (vma->vm_end - vma->vm_start); unsigned long size = (vma->vm_end - vma->vm_start);
struct videobuf_dmabuf *dmabuf = NULL;
struct omap_vout_device *vout = file->private_data; struct omap_vout_device *vout = file->private_data;
struct videobuf_queue *q = &vout->vbq; struct videobuf_queue *q = &vout->vbq;
...@@ -1241,8 +1234,7 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1241,8 +1234,7 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
vma->vm_ops = &omap_vout_vm_ops; vma->vm_ops = &omap_vout_vm_ops;
vma->vm_private_data = (void *) vout; vma->vm_private_data = (void *) vout;
dmabuf = videobuf_to_dma(q->bufs[i]); pos = (void *)vout->buf_virt_addr[i];
pos = dmabuf->vmalloc;
vma->vm_pgoff = virt_to_phys((void *)pos) >> PAGE_SHIFT; vma->vm_pgoff = virt_to_phys((void *)pos) >> PAGE_SHIFT;
while (size > 0) { while (size > 0) {
unsigned long pfn; unsigned long pfn;
...@@ -1347,8 +1339,8 @@ static int omap_vout_open(struct file *file) ...@@ -1347,8 +1339,8 @@ static int omap_vout_open(struct file *file)
video_vbq_ops.buf_queue = omap_vout_buffer_queue; video_vbq_ops.buf_queue = omap_vout_buffer_queue;
spin_lock_init(&vout->vbq_lock); spin_lock_init(&vout->vbq_lock);
videobuf_queue_sg_init(q, &video_vbq_ops, NULL, &vout->vbq_lock, videobuf_queue_dma_contig_init(q, &video_vbq_ops, q->dev,
vout->type, V4L2_FIELD_NONE, &vout->vbq_lock, vout->type, V4L2_FIELD_NONE,
sizeof(struct videobuf_buffer), vout); sizeof(struct videobuf_buffer), vout);
v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
...@@ -1799,7 +1791,6 @@ static int vidioc_reqbufs(struct file *file, void *fh, ...@@ -1799,7 +1791,6 @@ static int vidioc_reqbufs(struct file *file, void *fh,
unsigned int i, num_buffers = 0; unsigned int i, num_buffers = 0;
struct omap_vout_device *vout = fh; struct omap_vout_device *vout = fh;
struct videobuf_queue *q = &vout->vbq; struct videobuf_queue *q = &vout->vbq;
struct videobuf_dmabuf *dmabuf = NULL;
if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) || (req->count < 0)) if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) || (req->count < 0))
return -EINVAL; return -EINVAL;
...@@ -1825,8 +1816,7 @@ static int vidioc_reqbufs(struct file *file, void *fh, ...@@ -1825,8 +1816,7 @@ static int vidioc_reqbufs(struct file *file, void *fh,
num_buffers = (vout->vid == OMAP_VIDEO1) ? num_buffers = (vout->vid == OMAP_VIDEO1) ?
video1_numbuffers : video2_numbuffers; video1_numbuffers : video2_numbuffers;
for (i = num_buffers; i < vout->buffer_allocated; i++) { for (i = num_buffers; i < vout->buffer_allocated; i++) {
dmabuf = videobuf_to_dma(q->bufs[i]); omap_vout_free_buffer(vout->buf_virt_addr[i],
omap_vout_free_buffer((u32)dmabuf->vmalloc,
vout->buffer_size); vout->buffer_size);
vout->buf_virt_addr[i] = 0; vout->buf_virt_addr[i] = 0;
vout->buf_phy_addr[i] = 0; vout->buf_phy_addr[i] = 0;
...@@ -1855,12 +1845,7 @@ static int vidioc_reqbufs(struct file *file, void *fh, ...@@ -1855,12 +1845,7 @@ static int vidioc_reqbufs(struct file *file, void *fh,
goto reqbuf_err; goto reqbuf_err;
vout->buffer_allocated = req->count; vout->buffer_allocated = req->count;
for (i = 0; i < req->count; i++) {
dmabuf = videobuf_to_dma(q->bufs[i]);
dmabuf->vmalloc = (void *) vout->buf_virt_addr[i];
dmabuf->bus_addr = (dma_addr_t) vout->buf_phy_addr[i];
dmabuf->sglen = 1;
}
reqbuf_err: reqbuf_err:
mutex_unlock(&vout->lock); mutex_unlock(&vout->lock);
return ret; return ret;
...@@ -2488,7 +2473,7 @@ static int omap_vout_remove(struct platform_device *pdev) ...@@ -2488,7 +2473,7 @@ static int omap_vout_remove(struct platform_device *pdev)
for (k = 0; k < vid_dev->num_displays; k++) { for (k = 0; k < vid_dev->num_displays; k++) {
if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED) if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED)
vid_dev->displays[k]->disable(vid_dev->displays[k]); vid_dev->displays[k]->driver->disable(vid_dev->displays[k]);
omap_dss_put_device(vid_dev->displays[k]); omap_dss_put_device(vid_dev->displays[k]);
} }
...@@ -2545,7 +2530,9 @@ static int __init omap_vout_probe(struct platform_device *pdev) ...@@ -2545,7 +2530,9 @@ static int __init omap_vout_probe(struct platform_device *pdev)
def_display = NULL; def_display = NULL;
} }
if (def_display) { if (def_display) {
ret = def_display->enable(def_display); struct omap_dss_driver *dssdrv = def_display->driver;
ret = dssdrv->enable(def_display);
if (ret) { if (ret) {
/* Here we are not considering a error /* Here we are not considering a error
* as display may be enabled by frame * as display may be enabled by frame
...@@ -2559,21 +2546,21 @@ static int __init omap_vout_probe(struct platform_device *pdev) ...@@ -2559,21 +2546,21 @@ static int __init omap_vout_probe(struct platform_device *pdev)
if (def_display->caps & if (def_display->caps &
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE #ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
if (def_display->enable_te) if (dssdrv->enable_te)
def_display->enable_te(def_display, 1); dssdrv->enable_te(def_display, 1);
if (def_display->set_update_mode) if (dssdrv->set_update_mode)
def_display->set_update_mode(def_display, dssdrv->set_update_mode(def_display,
OMAP_DSS_UPDATE_AUTO); OMAP_DSS_UPDATE_AUTO);
#else /* MANUAL_UPDATE */ #else /* MANUAL_UPDATE */
if (def_display->enable_te) if (dssdrv->enable_te)
def_display->enable_te(def_display, 0); dssdrv->enable_te(def_display, 0);
if (def_display->set_update_mode) if (dssdrv->set_update_mode)
def_display->set_update_mode(def_display, dssdrv->set_update_mode(def_display,
OMAP_DSS_UPDATE_MANUAL); OMAP_DSS_UPDATE_MANUAL);
#endif #endif
} else { } else {
if (def_display->set_update_mode) if (dssdrv->set_update_mode)
def_display->set_update_mode(def_display, dssdrv->set_update_mode(def_display,
OMAP_DSS_UPDATE_AUTO); OMAP_DSS_UPDATE_AUTO);
} }
} }
...@@ -2592,8 +2579,8 @@ static int __init omap_vout_probe(struct platform_device *pdev) ...@@ -2592,8 +2579,8 @@ static int __init omap_vout_probe(struct platform_device *pdev)
for (i = 0; i < vid_dev->num_displays; i++) { for (i = 0; i < vid_dev->num_displays; i++) {
struct omap_dss_device *display = vid_dev->displays[i]; struct omap_dss_device *display = vid_dev->displays[i];
if (display->update) if (display->driver->update)
display->update(display, 0, 0, display->driver->update(display, 0, 0,
display->panel.timings.x_res, display->panel.timings.x_res,
display->panel.timings.y_res); display->panel.timings.y_res);
} }
...@@ -2608,8 +2595,8 @@ static int __init omap_vout_probe(struct platform_device *pdev) ...@@ -2608,8 +2595,8 @@ static int __init omap_vout_probe(struct platform_device *pdev)
if (ovl->manager && ovl->manager->device) if (ovl->manager && ovl->manager->device)
def_display = ovl->manager->device; def_display = ovl->manager->device;
if (def_display) if (def_display && def_display->driver)
def_display->disable(def_display); def_display->driver->disable(def_display);
} }
probe_err0: probe_err0:
kfree(vid_dev); kfree(vid_dev);
......
...@@ -267,6 +267,21 @@ hauppauge_tuner[] = ...@@ -267,6 +267,21 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Xceive XC4000"}, { TUNER_ABSENT, "Xceive XC4000"},
{ TUNER_ABSENT, "Dibcom 7070"}, { TUNER_ABSENT, "Dibcom 7070"},
{ TUNER_PHILIPS_TDA8290, "NXP 18271C2"}, { TUNER_PHILIPS_TDA8290, "NXP 18271C2"},
{ TUNER_ABSENT, "unknown"},
{ TUNER_ABSENT, "unknown"},
{ TUNER_ABSENT, "unknown"},
{ TUNER_ABSENT, "unknown"},
/* 160-169 */
{ TUNER_ABSENT, "unknown"},
{ TUNER_ABSENT, "unknown"},
{ TUNER_ABSENT, "unknown"},
{ TUNER_ABSENT, "unknown"},
{ TUNER_ABSENT, "unknown"},
{ TUNER_ABSENT, "unknown"},
{ TUNER_ABSENT, "unknown"},
{ TUNER_ABSENT, "unknown"},
{ TUNER_PHILIPS_FQ1236_MK5, "TCL M30WTP-4N-E"},
{ TUNER_ABSENT, "unknown"},
}; };
/* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are
......
...@@ -122,8 +122,8 @@ static struct uvc_control_info uvc_ctrls[] = { ...@@ -122,8 +122,8 @@ static struct uvc_control_info uvc_ctrls[] = {
.selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
.index = 10, .index = 10,
.size = 1, .size = 1,
.flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
| UVC_CONTROL_RESTORE, | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
}, },
{ {
.entity = UVC_GUID_UVC_PROCESSING, .entity = UVC_GUID_UVC_PROCESSING,
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "uvc.h" #include "uvc.h"
unsigned int uvc_trace_param; unsigned int uvc_gadget_trace_param;
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
* Function descriptors * Function descriptors
...@@ -656,6 +656,6 @@ uvc_bind_config(struct usb_configuration *c, ...@@ -656,6 +656,6 @@ uvc_bind_config(struct usb_configuration *c,
return ret; return ret;
} }
module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); module_param_named(trace, uvc_gadget_trace_param, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(trace, "Trace level bitmask"); MODULE_PARM_DESC(trace, "Trace level bitmask");
...@@ -107,11 +107,11 @@ struct uvc_streaming_control { ...@@ -107,11 +107,11 @@ struct uvc_streaming_control {
#define UVC_WARN_MINMAX 0 #define UVC_WARN_MINMAX 0
#define UVC_WARN_PROBE_DEF 1 #define UVC_WARN_PROBE_DEF 1
extern unsigned int uvc_trace_param; extern unsigned int uvc_gadget_trace_param;
#define uvc_trace(flag, msg...) \ #define uvc_trace(flag, msg...) \
do { \ do { \
if (uvc_trace_param & flag) \ if (uvc_gadget_trace_param & flag) \
printk(KERN_DEBUG "uvcvideo: " msg); \ printk(KERN_DEBUG "uvcvideo: " msg); \
} while (0) } while (0)
...@@ -220,16 +220,10 @@ struct uvc_file_handle ...@@ -220,16 +220,10 @@ struct uvc_file_handle
#define to_uvc_file_handle(handle) \ #define to_uvc_file_handle(handle) \
container_of(handle, struct uvc_file_handle, vfh) container_of(handle, struct uvc_file_handle, vfh)
extern struct v4l2_file_operations uvc_v4l2_fops;
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
* Functions * Functions
*/ */
extern int uvc_video_enable(struct uvc_video *video, int enable);
extern int uvc_video_init(struct uvc_video *video);
extern int uvc_video_pump(struct uvc_video *video);
extern void uvc_endpoint_stream(struct uvc_device *dev); extern void uvc_endpoint_stream(struct uvc_device *dev);
extern void uvc_function_connect(struct uvc_device *uvc); extern void uvc_function_connect(struct uvc_device *uvc);
......
...@@ -78,7 +78,8 @@ ...@@ -78,7 +78,8 @@
* *
*/ */
void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) static void
uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
{ {
mutex_init(&queue->mutex); mutex_init(&queue->mutex);
spin_lock_init(&queue->irqlock); spin_lock_init(&queue->irqlock);
...@@ -87,6 +88,28 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) ...@@ -87,6 +88,28 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
queue->type = type; queue->type = type;
} }
/*
* Free the video buffers.
*
* This function must be called with the queue lock held.
*/
static int uvc_free_buffers(struct uvc_video_queue *queue)
{
unsigned int i;
for (i = 0; i < queue->count; ++i) {
if (queue->buffer[i].vma_use_count != 0)
return -EBUSY;
}
if (queue->count) {
vfree(queue->mem);
queue->count = 0;
}
return 0;
}
/* /*
* Allocate the video buffers. * Allocate the video buffers.
* *
...@@ -95,7 +118,8 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) ...@@ -95,7 +118,8 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
* *
* Buffers will be individually mapped, so they must all be page aligned. * Buffers will be individually mapped, so they must all be page aligned.
*/ */
int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, static int
uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
unsigned int buflength) unsigned int buflength)
{ {
unsigned int bufsize = PAGE_ALIGN(buflength); unsigned int bufsize = PAGE_ALIGN(buflength);
...@@ -150,28 +174,6 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, ...@@ -150,28 +174,6 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
return ret; return ret;
} }
/*
* Free the video buffers.
*
* This function must be called with the queue lock held.
*/
int uvc_free_buffers(struct uvc_video_queue *queue)
{
unsigned int i;
for (i = 0; i < queue->count; ++i) {
if (queue->buffer[i].vma_use_count != 0)
return -EBUSY;
}
if (queue->count) {
vfree(queue->mem);
queue->count = 0;
}
return 0;
}
static void __uvc_query_buffer(struct uvc_buffer *buf, static void __uvc_query_buffer(struct uvc_buffer *buf,
struct v4l2_buffer *v4l2_buf) struct v4l2_buffer *v4l2_buf)
{ {
...@@ -195,8 +197,8 @@ static void __uvc_query_buffer(struct uvc_buffer *buf, ...@@ -195,8 +197,8 @@ static void __uvc_query_buffer(struct uvc_buffer *buf,
} }
} }
int uvc_query_buffer(struct uvc_video_queue *queue, static int
struct v4l2_buffer *v4l2_buf) uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
{ {
int ret = 0; int ret = 0;
...@@ -217,8 +219,8 @@ int uvc_query_buffer(struct uvc_video_queue *queue, ...@@ -217,8 +219,8 @@ int uvc_query_buffer(struct uvc_video_queue *queue,
* Queue a video buffer. Attempting to queue a buffer that has already been * Queue a video buffer. Attempting to queue a buffer that has already been
* queued will return -EINVAL. * queued will return -EINVAL.
*/ */
int uvc_queue_buffer(struct uvc_video_queue *queue, static int
struct v4l2_buffer *v4l2_buf) uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
{ {
struct uvc_buffer *buf; struct uvc_buffer *buf;
unsigned long flags; unsigned long flags;
...@@ -298,8 +300,9 @@ static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) ...@@ -298,8 +300,9 @@ static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
* Dequeue a video buffer. If nonblocking is false, block until a buffer is * Dequeue a video buffer. If nonblocking is false, block until a buffer is
* available. * available.
*/ */
int uvc_dequeue_buffer(struct uvc_video_queue *queue, static int
struct v4l2_buffer *v4l2_buf, int nonblocking) uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
int nonblocking)
{ {
struct uvc_buffer *buf; struct uvc_buffer *buf;
int ret = 0; int ret = 0;
...@@ -359,7 +362,8 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue, ...@@ -359,7 +362,8 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue,
* This function implements video queue polling and is intended to be used by * This function implements video queue polling and is intended to be used by
* the device poll handler. * the device poll handler.
*/ */
unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, static unsigned int
uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
poll_table *wait) poll_table *wait)
{ {
struct uvc_buffer *buf; struct uvc_buffer *buf;
...@@ -407,7 +411,8 @@ static struct vm_operations_struct uvc_vm_ops = { ...@@ -407,7 +411,8 @@ static struct vm_operations_struct uvc_vm_ops = {
* This function implements video buffer memory mapping and is intended to be * This function implements video buffer memory mapping and is intended to be
* used by the device mmap handler. * used by the device mmap handler.
*/ */
int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) static int
uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
{ {
struct uvc_buffer *uninitialized_var(buffer); struct uvc_buffer *uninitialized_var(buffer);
struct page *page; struct page *page;
...@@ -457,6 +462,42 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) ...@@ -457,6 +462,42 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
return ret; return ret;
} }
/*
* Cancel the video buffers queue.
*
* Cancelling the queue marks all buffers on the irq queue as erroneous,
* wakes them up and removes them from the queue.
*
* If the disconnect parameter is set, further calls to uvc_queue_buffer will
* fail with -ENODEV.
*
* This function acquires the irq spinlock and can be called from interrupt
* context.
*/
static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
{
struct uvc_buffer *buf;
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
while (!list_empty(&queue->irqqueue)) {
buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
wake_up(&buf->wait);
}
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
* blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
* state outside the queue code.
*/
if (disconnect)
queue->flags |= UVC_QUEUE_DISCONNECTED;
spin_unlock_irqrestore(&queue->irqlock, flags);
}
/* /*
* Enable or disable the video buffers queue. * Enable or disable the video buffers queue.
* *
...@@ -474,7 +515,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) ...@@ -474,7 +515,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
* This function can't be called from interrupt context. Use * This function can't be called from interrupt context. Use
* uvc_queue_cancel() instead. * uvc_queue_cancel() instead.
*/ */
int uvc_queue_enable(struct uvc_video_queue *queue, int enable) static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
{ {
unsigned int i; unsigned int i;
int ret = 0; int ret = 0;
...@@ -503,44 +544,8 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable) ...@@ -503,44 +544,8 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
return ret; return ret;
} }
/* static struct uvc_buffer *
* Cancel the video buffers queue. uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
*
* Cancelling the queue marks all buffers on the irq queue as erroneous,
* wakes them up and removes them from the queue.
*
* If the disconnect parameter is set, further calls to uvc_queue_buffer will
* fail with -ENODEV.
*
* This function acquires the irq spinlock and can be called from interrupt
* context.
*/
void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
{
struct uvc_buffer *buf;
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
while (!list_empty(&queue->irqqueue)) {
buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
wake_up(&buf->wait);
}
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
* blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
* state outside the queue code.
*/
if (disconnect)
queue->flags |= UVC_QUEUE_DISCONNECTED;
spin_unlock_irqrestore(&queue->irqlock, flags);
}
struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf)
{ {
struct uvc_buffer *nextbuf; struct uvc_buffer *nextbuf;
unsigned long flags; unsigned long flags;
...@@ -568,7 +573,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, ...@@ -568,7 +573,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
return nextbuf; return nextbuf;
} }
struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue) static struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue)
{ {
struct uvc_buffer *buf = NULL; struct uvc_buffer *buf = NULL;
......
...@@ -58,30 +58,10 @@ struct uvc_video_queue { ...@@ -58,30 +58,10 @@ struct uvc_video_queue {
struct list_head irqqueue; struct list_head irqqueue;
}; };
extern void uvc_queue_init(struct uvc_video_queue *queue,
enum v4l2_buf_type type);
extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
unsigned int nbuffers, unsigned int buflength);
extern int uvc_free_buffers(struct uvc_video_queue *queue);
extern int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_queue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf, int nonblocking);
extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf);
extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
struct file *file, poll_table *wait);
extern int uvc_queue_mmap(struct uvc_video_queue *queue,
struct vm_area_struct *vma);
static inline int uvc_queue_streaming(struct uvc_video_queue *queue) static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
{ {
return queue->flags & UVC_QUEUE_STREAMING; return queue->flags & UVC_QUEUE_STREAMING;
} }
extern struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -363,7 +363,7 @@ uvc_v4l2_poll(struct file *file, poll_table *wait) ...@@ -363,7 +363,7 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
return mask; return mask;
} }
struct v4l2_file_operations uvc_v4l2_fops = { static struct v4l2_file_operations uvc_v4l2_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = uvc_v4l2_open, .open = uvc_v4l2_open,
.release = uvc_v4l2_release, .release = uvc_v4l2_release,
......
...@@ -271,7 +271,7 @@ uvc_video_alloc_requests(struct uvc_video *video) ...@@ -271,7 +271,7 @@ uvc_video_alloc_requests(struct uvc_video *video)
* This function fills the available USB requests (listed in req_free) with * This function fills the available USB requests (listed in req_free) with
* video data from the queued buffers. * video data from the queued buffers.
*/ */
int static int
uvc_video_pump(struct uvc_video *video) uvc_video_pump(struct uvc_video *video)
{ {
struct usb_request *req; struct usb_request *req;
...@@ -328,7 +328,7 @@ uvc_video_pump(struct uvc_video *video) ...@@ -328,7 +328,7 @@ uvc_video_pump(struct uvc_video *video)
/* /*
* Enable or disable the video stream. * Enable or disable the video stream.
*/ */
int static int
uvc_video_enable(struct uvc_video *video, int enable) uvc_video_enable(struct uvc_video *video, int enable)
{ {
unsigned int i; unsigned int i;
...@@ -367,7 +367,7 @@ uvc_video_enable(struct uvc_video *video, int enable) ...@@ -367,7 +367,7 @@ uvc_video_enable(struct uvc_video *video, int enable)
/* /*
* Initialize the UVC video stream. * Initialize the UVC video stream.
*/ */
int static int
uvc_video_init(struct uvc_video *video) uvc_video_init(struct uvc_video *video)
{ {
INIT_LIST_HEAD(&video->req_free); INIT_LIST_HEAD(&video->req_free);
......
...@@ -28,10 +28,10 @@ ...@@ -28,10 +28,10 @@
#include "config.c" #include "config.c"
#include "epautoconf.c" #include "epautoconf.c"
#include "f_uvc.c"
#include "uvc_queue.c" #include "uvc_queue.c"
#include "uvc_v4l2.c"
#include "uvc_video.c" #include "uvc_video.c"
#include "uvc_v4l2.c"
#include "f_uvc.c"
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
* Device descriptor * Device descriptor
......
...@@ -130,6 +130,7 @@ ...@@ -130,6 +130,7 @@
#define TUNER_PHILIPS_CU1216L 82 #define TUNER_PHILIPS_CU1216L 82
#define TUNER_NXP_TDA18271 83 #define TUNER_NXP_TDA18271 83
#define TUNER_SONY_BTF_PXN01Z 84 #define TUNER_SONY_BTF_PXN01Z 84
#define TUNER_PHILIPS_FQ1236_MK5 85 /* NTSC, TDA9885, no FM radio */
/* tv card specific */ /* tv card specific */
#define TDA9887_PRESENT (1<<0) #define TDA9887_PRESENT (1<<0)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册