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
This commit is contained in:
commit
9f71963702
18 changed files with 169 additions and 163 deletions
|
@ -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)
|
||||||
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[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ------------ 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[] = {
|
||||||
.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)
|
||||||
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)
|
||||||
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:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
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 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
# 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 @@
|
||||||
#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,
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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[] =
|
||||||
{ 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[] = {
|
||||||
.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 @@
|
||||||
|
|
||||||
#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,
|
||||||
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 {
|
||||||
#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
|
||||||
#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 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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)
|
||||||
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,8 +118,9 @@ 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
|
||||||
unsigned int buflength)
|
uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
|
||||||
|
unsigned int buflength)
|
||||||
{
|
{
|
||||||
unsigned int bufsize = PAGE_ALIGN(buflength);
|
unsigned int bufsize = PAGE_ALIGN(buflength);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
* 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)
|
||||||
* 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,8 +362,9 @@ 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
|
||||||
poll_table *wait)
|
uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
|
||||||
|
poll_table *wait)
|
||||||
{
|
{
|
||||||
struct uvc_buffer *buf;
|
struct uvc_buffer *buf;
|
||||||
unsigned int mask = 0;
|
unsigned int mask = 0;
|
||||||
|
@ -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)
|
||||||
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)
|
||||||
* 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)
|
||||||
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,
|
||||||
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 {
|
||||||
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)
|
||||||
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)
|
||||||
* 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)
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
/*
|
/*
|
||||||
* 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 @@
|
||||||
#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 @@
|
||||||
#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)
|
||||||
|
|
Loading…
Reference in a new issue