summaryrefslogtreecommitdiffstats
path: root/drivers/media/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/pci')
-rw-r--r--drivers/media/pci/bt8xx/dst_ca.c2
-rw-r--r--drivers/media/pci/cobalt/cobalt-driver.c11
-rw-r--r--drivers/media/pci/cobalt/cobalt-driver.h1
-rw-r--r--drivers/media/pci/cobalt/cobalt-v4l2.c4
-rw-r--r--drivers/media/pci/cx18/cx18-alsa-mixer.c6
-rw-r--r--drivers/media/pci/cx18/cx18-driver.c2
-rw-r--r--drivers/media/pci/cx18/cx18-driver.h6
-rw-r--r--drivers/media/pci/cx18/cx18-ioctl.c2
-rw-r--r--drivers/media/pci/cx18/cx18-streams.c12
-rw-r--r--drivers/media/pci/cx18/cx18-vbi.c6
-rw-r--r--drivers/media/pci/cx23885/cx23885-417.c3
-rw-r--r--drivers/media/pci/cx23885/cx23885-cards.c59
-rw-r--r--drivers/media/pci/cx23885/cx23885-core.c10
-rw-r--r--drivers/media/pci/cx23885/cx23885-dvb.c104
-rw-r--r--drivers/media/pci/cx23885/cx23885-vbi.c3
-rw-r--r--drivers/media/pci/cx23885/cx23885-video.c5
-rw-r--r--drivers/media/pci/cx23885/cx23885.h2
-rw-r--r--drivers/media/pci/cx25821/cx25821-alsa.c2
-rw-r--r--drivers/media/pci/cx25821/cx25821-core.c10
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.c5
-rw-r--r--drivers/media/pci/cx25821/cx25821.h1
-rw-r--r--drivers/media/pci/cx88/cx88-alsa.c8
-rw-r--r--drivers/media/pci/cx88/cx88-blackbird.c4
-rw-r--r--drivers/media/pci/cx88/cx88-dvb.c4
-rw-r--r--drivers/media/pci/cx88/cx88-mpeg.c10
-rw-r--r--drivers/media/pci/cx88/cx88-vbi.c3
-rw-r--r--drivers/media/pci/cx88/cx88-video.c13
-rw-r--r--drivers/media/pci/cx88/cx88.h2
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-core.c3
-rw-r--r--drivers/media/pci/dt3155/dt3155.c15
-rw-r--r--drivers/media/pci/dt3155/dt3155.h2
-rw-r--r--drivers/media/pci/ivtv/ivtv-alsa-mixer.c6
-rw-r--r--drivers/media/pci/netup_unidvb/Kconfig7
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb.h10
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb_ci.c4
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb_core.c174
-rw-r--r--drivers/media/pci/saa7134/saa7134-core.c22
-rw-r--r--drivers/media/pci/saa7134/saa7134-ts.c3
-rw-r--r--drivers/media/pci/saa7134/saa7134-vbi.c3
-rw-r--r--drivers/media/pci/saa7134/saa7134-video.c5
-rw-r--r--drivers/media/pci/saa7134/saa7134.h3
-rw-r--r--drivers/media/pci/saa7164/saa7164-encoder.c6
-rw-r--r--drivers/media/pci/saa7164/saa7164.h4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c15
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2.c44
-rw-r--r--drivers/media/pci/solo6x10/solo6x10.h2
-rw-r--r--drivers/media/pci/sta2x11/sta2x11_vip.c20
-rw-r--r--drivers/media/pci/tw68/tw68-core.c15
-rw-r--r--drivers/media/pci/tw68/tw68-video.c4
-rw-r--r--drivers/media/pci/tw68/tw68.h1
-rw-r--r--drivers/media/pci/tw686x/Kconfig2
-rw-r--r--drivers/media/pci/tw686x/tw686x-audio.c92
-rw-r--r--drivers/media/pci/tw686x/tw686x-core.c56
-rw-r--r--drivers/media/pci/tw686x/tw686x-regs.h9
-rw-r--r--drivers/media/pci/tw686x/tw686x-video.c595
-rw-r--r--drivers/media/pci/tw686x/tw686x.h42
-rw-r--r--drivers/media/pci/zoran/zr36016.c4
57 files changed, 977 insertions, 491 deletions
diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c
index da8b414..8681b91 100644
--- a/drivers/media/pci/bt8xx/dst_ca.c
+++ b/drivers/media/pci/bt8xx/dst_ca.c
@@ -655,7 +655,6 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
static int dst_ca_open(struct inode *inode, struct file *file)
{
dprintk(verbose, DST_CA_DEBUG, 1, " Device opened [%p] ", file);
- try_module_get(THIS_MODULE);
return 0;
}
@@ -663,7 +662,6 @@ static int dst_ca_open(struct inode *inode, struct file *file)
static int dst_ca_release(struct inode *inode, struct file *file)
{
dprintk(verbose, DST_CA_DEBUG, 1, " Device closed.");
- module_put(THIS_MODULE);
return 0;
}
diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c
index 8d6f04f..476f7f0 100644
--- a/drivers/media/pci/cobalt/cobalt-driver.c
+++ b/drivers/media/pci/cobalt/cobalt-driver.c
@@ -492,7 +492,6 @@ static int cobalt_subdevs_init(struct cobalt *cobalt)
.ain_sel = ADV7604_AIN7_8_9_NC_SYNC_3_1,
.bus_order = ADV7604_BUS_ORDER_BRG,
.blank_data = 1,
- .op_656_range = 1,
.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0,
.int1_config = ADV76XX_INT1_CONFIG_ACTIVE_HIGH,
.dr_str_data = ADV76XX_DR_STR_HIGH,
@@ -571,7 +570,6 @@ static int cobalt_subdevs_hsma_init(struct cobalt *cobalt)
.bus_order = ADV7842_BUS_ORDER_RBG,
.op_format_mode_sel = ADV7842_OP_FORMAT_MODE0,
.blank_data = 1,
- .op_656_range = 1,
.dr_str_data = 3,
.dr_str_clk = 3,
.dr_str_sync = 3,
@@ -691,17 +689,10 @@ static int cobalt_probe(struct pci_dev *pci_dev,
cobalt->pci_dev = pci_dev;
cobalt->instance = i;
- cobalt->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(cobalt->alloc_ctx)) {
- kfree(cobalt);
- return -ENOMEM;
- }
-
retval = v4l2_device_register(&pci_dev->dev, &cobalt->v4l2_dev);
if (retval) {
pr_err("cobalt: v4l2_device_register of card %d failed\n",
cobalt->instance);
- vb2_dma_sg_cleanup_ctx(cobalt->alloc_ctx);
kfree(cobalt);
return retval;
}
@@ -782,7 +773,6 @@ err:
cobalt_err("error %d on initialization\n", retval);
v4l2_device_unregister(&cobalt->v4l2_dev);
- vb2_dma_sg_cleanup_ctx(cobalt->alloc_ctx);
kfree(cobalt);
return retval;
}
@@ -818,7 +808,6 @@ static void cobalt_remove(struct pci_dev *pci_dev)
cobalt_info("removed cobalt card\n");
v4l2_device_unregister(v4l2_dev);
- vb2_dma_sg_cleanup_ctx(cobalt->alloc_ctx);
kfree(cobalt);
}
diff --git a/drivers/media/pci/cobalt/cobalt-driver.h b/drivers/media/pci/cobalt/cobalt-driver.h
index b2f08e4..ed00dc9 100644
--- a/drivers/media/pci/cobalt/cobalt-driver.h
+++ b/drivers/media/pci/cobalt/cobalt-driver.h
@@ -262,7 +262,6 @@ struct cobalt {
int instance;
struct pci_dev *pci_dev;
struct v4l2_device v4l2_dev;
- void *alloc_ctx;
void __iomem *bar0, *bar1;
diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c
index c0ba458..d05672f 100644
--- a/drivers/media/pci/cobalt/cobalt-v4l2.c
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -45,7 +45,7 @@ static const struct v4l2_dv_timings cea1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
static int cobalt_queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct cobalt_stream *s = q->drv_priv;
unsigned size = s->stride * s->height;
@@ -54,7 +54,6 @@ static int cobalt_queue_setup(struct vb2_queue *q,
*num_buffers = 3;
if (*num_buffers > NR_BUFS)
*num_buffers = NR_BUFS;
- alloc_ctxs[0] = s->cobalt->alloc_ctx;
if (*num_planes)
return sizes[0] < size ? -EINVAL : 0;
*num_planes = 1;
@@ -1224,6 +1223,7 @@ static int cobalt_node_register(struct cobalt *cobalt, int node)
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->min_buffers_needed = 2;
q->lock = &s->lock;
+ q->dev = &cobalt->pci_dev->dev;
vdev->queue = q;
video_set_drvdata(vdev, s);
diff --git a/drivers/media/pci/cx18/cx18-alsa-mixer.c b/drivers/media/pci/cx18/cx18-alsa-mixer.c
index 341bddc..2842752 100644
--- a/drivers/media/pci/cx18/cx18-alsa-mixer.c
+++ b/drivers/media/pci/cx18/cx18-alsa-mixer.c
@@ -93,7 +93,7 @@ static int snd_cx18_mixer_tv_vol_get(struct snd_kcontrol *kctl,
vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
snd_cx18_lock(cxsc);
- ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl);
+ ret = v4l2_g_ctrl(cx->sd_av->ctrl_handler, &vctrl);
snd_cx18_unlock(cxsc);
if (!ret)
@@ -115,14 +115,14 @@ static int snd_cx18_mixer_tv_vol_put(struct snd_kcontrol *kctl,
snd_cx18_lock(cxsc);
/* Fetch current state */
- ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl);
+ ret = v4l2_g_ctrl(cx->sd_av->ctrl_handler, &vctrl);
if (ret ||
(cx18_av_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) {
/* Set, if needed */
vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
- ret = v4l2_subdev_call(cx->sd_av, core, s_ctrl, &vctrl);
+ ret = v4l2_s_ctrl(cx->sd_av->ctrl_handler, &vctrl);
if (!ret)
ret = 1; /* Indicate control was changed w/o error */
}
diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c
index 260e462..2f23b26 100644
--- a/drivers/media/pci/cx18/cx18-driver.c
+++ b/drivers/media/pci/cx18/cx18-driver.c
@@ -560,7 +560,7 @@ static void cx18_process_options(struct cx18 *cx)
cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufsize;
cx->stream_buf_size[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufsize;
cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufsize;
- cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_active_samples * 36;
+ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = VBI_ACTIVE_SAMPLES * 36;
cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufsize;
cx->stream_buf_size[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control no data */
diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h
index 47ce80f..ef308a1 100644
--- a/drivers/media/pci/cx18/cx18-driver.h
+++ b/drivers/media/pci/cx18/cx18-driver.h
@@ -492,9 +492,9 @@ struct cx18_card;
* (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line =
* 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples
*/
-static const u32 vbi_active_samples = 1444; /* 4 byte SAV + 720 Y + 720 U/V */
-static const u32 vbi_hblank_samples_60Hz = 272; /* 4 byte EAV + 268 anc/fill */
-static const u32 vbi_hblank_samples_50Hz = 284; /* 4 byte EAV + 280 anc/fill */
+#define VBI_ACTIVE_SAMPLES 1444 /* 4 byte SAV + 720 Y + 720 U/V */
+#define VBI_HBLANK_SAMPLES_60HZ 272 /* 4 byte EAV + 268 anc/fill */
+#define VBI_HBLANK_SAMPLES_50HZ 284 /* 4 byte EAV + 280 anc/fill */
#define CX18_VBI_FRAMES 32
diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c
index eeb741c..fecca2a 100644
--- a/drivers/media/pci/cx18/cx18-ioctl.c
+++ b/drivers/media/pci/cx18/cx18-ioctl.c
@@ -177,7 +177,7 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
vbifmt->sampling_rate = 27000000;
vbifmt->offset = 248; /* FIXME - slightly wrong for both 50 & 60 Hz */
- vbifmt->samples_per_line = vbi_active_samples - 4;
+ vbifmt->samples_per_line = VBI_ACTIVE_SAMPLES - 4;
vbifmt->sample_format = V4L2_PIX_FMT_GREY;
vbifmt->start[0] = cx->vbi.start[0];
vbifmt->start[1] = cx->vbi.start[1];
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
index c986084..f3802ec 100644
--- a/drivers/media/pci/cx18/cx18-streams.c
+++ b/drivers/media/pci/cx18/cx18-streams.c
@@ -605,9 +605,9 @@ static void cx18_vbi_setup(struct cx18_stream *s)
/* Lines per field */
data[1] = (lines / 2) | ((lines / 2) << 16);
/* bytes per line */
- data[2] = (raw ? vbi_active_samples
- : (cx->is_60hz ? vbi_hblank_samples_60Hz
- : vbi_hblank_samples_50Hz));
+ data[2] = (raw ? VBI_ACTIVE_SAMPLES
+ : (cx->is_60hz ? VBI_HBLANK_SAMPLES_60HZ
+ : VBI_HBLANK_SAMPLES_50HZ));
/* Every X number of frames a VBI interrupt arrives
(frames as in 25 or 30 fps) */
data[3] = 1;
@@ -761,7 +761,7 @@ static void cx18_stream_configure_mdls(struct cx18_stream *s)
s->bufs_per_mdl = 1;
if (cx18_raw_vbi(s->cx)) {
s->mdl_size = (s->cx->is_60hz ? 12 : 18)
- * 2 * vbi_active_samples;
+ * 2 * VBI_ACTIVE_SAMPLES;
} else {
/*
* See comment in cx18_vbi_setup() below about the
@@ -769,8 +769,8 @@ static void cx18_stream_configure_mdls(struct cx18_stream *s)
* the lines on which EAV RP codes toggle.
*/
s->mdl_size = s->cx->is_60hz
- ? (21 - 4 + 1) * 2 * vbi_hblank_samples_60Hz
- : (23 - 2 + 1) * 2 * vbi_hblank_samples_50Hz;
+ ? (21 - 4 + 1) * 2 * VBI_HBLANK_SAMPLES_60HZ
+ : (23 - 2 + 1) * 2 * VBI_HBLANK_SAMPLES_50HZ;
}
break;
default:
diff --git a/drivers/media/pci/cx18/cx18-vbi.c b/drivers/media/pci/cx18/cx18-vbi.c
index add9964..43360cb 100644
--- a/drivers/media/pci/cx18/cx18-vbi.c
+++ b/drivers/media/pci/cx18/cx18-vbi.c
@@ -108,7 +108,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
/* FIXME - this function ignores the input size. */
static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size)
{
- u32 line_size = vbi_active_samples;
+ u32 line_size = VBI_ACTIVE_SAMPLES;
u32 lines = cx->vbi.count * 2;
u8 *q = buf;
u8 *p;
@@ -145,8 +145,8 @@ static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size,
struct v4l2_decode_vbi_line vbi;
int i;
u32 line = 0;
- u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz
- : vbi_hblank_samples_50Hz;
+ u32 line_size = cx->is_60hz ? VBI_HBLANK_SAMPLES_60HZ
+ : VBI_HBLANK_SAMPLES_50HZ;
/* find the first valid line */
for (i = hdr_size, buf += hdr_size; i < size; i++, buf++) {
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index bd33387..efec2d1 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1140,7 +1140,7 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
static int queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct cx23885_dev *dev = q->drv_priv;
@@ -1148,7 +1148,6 @@ static int queue_setup(struct vb2_queue *q,
dev->ts1.ts_packet_count = mpeglines;
*num_planes = 1;
sizes[0] = mpeglinesize * mpeglines;
- alloc_ctxs[0] = dev->alloc_ctx;
*num_buffers = mpegbufs;
return 0;
}
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
index 310ee76..4abf50f 100644
--- a/drivers/media/pci/cx23885/cx23885-cards.c
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
@@ -765,6 +765,11 @@ struct cx23885_board cx23885_boards[] = {
.amux = CX25840_AUDIO7,
} },
},
+ [CX23885_BOARD_HAUPPAUGE_QUADHD_DVB] = {
+ .name = "Hauppauge WinTV-QuadHD-DVB",
+ .portb = CX23885_MPEG_DVB,
+ .portc = CX23885_MPEG_DVB,
+ },
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -1060,6 +1065,14 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x1576,
.subdevice = 0x0460,
.card = CX23885_BOARD_VIEWCAST_460E,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x6a28,
+ .card = CX23885_BOARD_HAUPPAUGE_QUADHD_DVB, /* Tuner Pair 1 */
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x6b28,
+ .card = CX23885_BOARD_HAUPPAUGE_QUADHD_DVB, /* Tuner Pair 2 */
},
};
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -1257,6 +1270,14 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
case 150329:
/* WinTV-HVR5525 (PCIe, DVB-S/S2, DVB-T/T2/C) */
break;
+ case 166100:
+ /* WinTV-QuadHD (DVB) Tuner Pair 1 (PCIe, IR, half height,
+ DVB-T/T2/C, DVB-T/T2/C */
+ break;
+ case 166101:
+ /* WinTV-QuadHD (DVB) Tuner Pair 2 (PCIe, IR, half height,
+ DVB-T/T2/C, DVB-T/T2/C */
+ break;
default:
printk(KERN_WARNING "%s: warning: "
"unknown hauppauge model #%d\n",
@@ -1729,20 +1750,22 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
cx23885_gpio_set(dev, GPIO_2);
break;
case CX23885_BOARD_HAUPPAUGE_HVR5525:
+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB:
/*
- * GPIO-00 IR_WIDE
- * GPIO-02 wake#
- * GPIO-03 VAUX Pres.
- * GPIO-07 PROG#
- * GPIO-08 SAT_RESN
- * GPIO-09 TER_RESN
- * GPIO-10 B2_SENSE
- * GPIO-11 B1_SENSE
- * GPIO-15 IR_LED_STATUS
- * GPIO-19 IR_NARROW
- * GPIO-20 Blauster1
- * ALTGPIO VAUX_SWITCH
- * AUX_PLL_CLK : Blaster2
+ * HVR5525 GPIO Details:
+ * GPIO-00 IR_WIDE
+ * GPIO-02 wake#
+ * GPIO-03 VAUX Pres.
+ * GPIO-07 PROG#
+ * GPIO-08 SAT_RESN
+ * GPIO-09 TER_RESN
+ * GPIO-10 B2_SENSE
+ * GPIO-11 B1_SENSE
+ * GPIO-15 IR_LED_STATUS
+ * GPIO-19 IR_NARROW
+ * GPIO-20 Blauster1
+ * ALTGPIO VAUX_SWITCH
+ * AUX_PLL_CLK : Blaster2
*/
/* Put the parts into reset and back */
cx23885_gpio_enable(dev, GPIO_8 | GPIO_9, 1);
@@ -1802,6 +1825,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1255:
case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
case CX23885_BOARD_HAUPPAUGE_HVR1210:
+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB:
/* FIXME: Implement me */
break;
case CX23885_BOARD_HAUPPAUGE_HVR1270:
@@ -2000,6 +2024,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_STARBURST:
case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
case CX23885_BOARD_HAUPPAUGE_HVR5525:
+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB:
if (dev->i2c_bus[0].i2c_rc == 0)
hauppauge_eeprom(dev, eeprom+0xc0);
break;
@@ -2145,6 +2170,14 @@ void cx23885_card_setup(struct cx23885_dev *dev)
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
break;
+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB:
+ ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
+ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+ ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
+ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+ break;
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index 813c217..c86b109 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -2005,14 +2005,9 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
err = pci_set_dma_mask(pci_dev, 0xffffffff);
if (err) {
printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
- goto fail_context;
+ goto fail_ctrl;
}
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail_context;
- }
err = request_irq(pci_dev->irq, cx23885_irq,
IRQF_SHARED, dev->name, dev);
if (err < 0) {
@@ -2041,8 +2036,6 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
return 0;
fail_irq:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
-fail_context:
cx23885_dev_unregister(dev);
fail_ctrl:
v4l2_ctrl_handler_free(hdl);
@@ -2068,7 +2061,6 @@ static void cx23885_finidev(struct pci_dev *pci_dev)
pci_disable_device(pci_dev);
cx23885_dev_unregister(dev);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
v4l2_ctrl_handler_free(&dev->ctrl_handler);
v4l2_device_unregister(v4l2_dev);
kfree(dev);
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index f041b69..e5748a9 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -94,7 +94,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct cx23885_tsport *port = q->drv_priv;
@@ -102,7 +102,6 @@ static int queue_setup(struct vb2_queue *q,
port->ts_packet_count = 32;
*num_planes = 1;
sizes[0] = port->ts_packet_size * port->ts_packet_count;
- alloc_ctxs[0] = port->dev->alloc_ctx;
*num_buffers = 32;
return 0;
}
@@ -2269,9 +2268,107 @@ static int dvb_register(struct cx23885_tsport *port)
}
break;
}
+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB:
+ switch (port->nr) {
+ /* port b - Terrestrial/cable */
+ case 1:
+ /* attach frontend */
+ memset(&si2168_config, 0, sizeof(si2168_config));
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &fe0->dvb.frontend;
+ si2168_config.ts_mode = SI2168_TS_SERIAL;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ info.addr = 0x64;
+ info.platform_data = &si2168_config;
+ request_module("%s", info.type);
+ client_demod = i2c_new_device(&dev->i2c_bus[0].i2c_adap, &info);
+ if (!client_demod || !client_demod->dev.driver)
+ goto frontend_detach;
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ port->i2c_client_demod = client_demod;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = fe0->dvb.frontend;
+ si2157_config.if_port = 1;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ info.addr = 0x60;
+ info.platform_data = &si2157_config;
+ request_module("%s", info.type);
+ client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap, &info);
+ if (!client_tuner || !client_tuner->dev.driver) {
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ port->i2c_client_demod = NULL;
+ goto frontend_detach;
+ }
+ if (!try_module_get(client_tuner->dev.driver->owner)) {
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ port->i2c_client_demod = NULL;
+ goto frontend_detach;
+ }
+ port->i2c_client_tuner = client_tuner;
+ break;
+
+ /* port c - terrestrial/cable */
+ case 2:
+ /* attach frontend */
+ memset(&si2168_config, 0, sizeof(si2168_config));
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &fe0->dvb.frontend;
+ si2168_config.ts_mode = SI2168_TS_SERIAL;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ info.addr = 0x66;
+ info.platform_data = &si2168_config;
+ request_module("%s", info.type);
+ client_demod = i2c_new_device(&dev->i2c_bus[0].i2c_adap, &info);
+ if (!client_demod || !client_demod->dev.driver)
+ goto frontend_detach;
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ port->i2c_client_demod = client_demod;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = fe0->dvb.frontend;
+ si2157_config.if_port = 1;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ info.addr = 0x62;
+ info.platform_data = &si2157_config;
+ request_module("%s", info.type);
+ client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap, &info);
+ if (!client_tuner || !client_tuner->dev.driver) {
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ port->i2c_client_demod = NULL;
+ goto frontend_detach;
+ }
+ if (!try_module_get(client_tuner->dev.driver->owner)) {
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ port->i2c_client_demod = NULL;
+ goto frontend_detach;
+ }
+ port->i2c_client_tuner = client_tuner;
+ break;
+ }
+ break;
+
default:
printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
- " isn't supported yet\n",
+ " isn't supported yet\n",
dev->name);
break;
}
@@ -2397,6 +2494,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
q->mem_ops = &vb2_dma_sg_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &dev->lock;
+ q->dev = &dev->pci->dev;
err = vb2_queue_init(q);
if (err < 0)
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
index 39750eb..75e7fa7 100644
--- a/drivers/media/pci/cx23885/cx23885-vbi.c
+++ b/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -122,7 +122,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev,
static int queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct cx23885_dev *dev = q->drv_priv;
unsigned lines = VBI_PAL_LINE_COUNT;
@@ -131,7 +131,6 @@ static int queue_setup(struct vb2_queue *q,
lines = VBI_NTSC_LINE_COUNT;
*num_planes = 1;
sizes[0] = lines * VBI_LINE_LENGTH * 2;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index e1d7d08..6d73522 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -335,13 +335,12 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
static int queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct cx23885_dev *dev = q->drv_priv;
*num_planes = 1;
sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
@@ -1268,6 +1267,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
q->mem_ops = &vb2_dma_sg_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &dev->lock;
+ q->dev = &dev->pci->dev;
err = vb2_queue_init(q);
if (err < 0)
@@ -1284,6 +1284,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
q->mem_ops = &vb2_dma_sg_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &dev->lock;
+ q->dev = &dev->pci->dev;
err = vb2_queue_init(q);
if (err < 0)
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index b1a5409..24a0a6c 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -103,6 +103,7 @@
#define CX23885_BOARD_HAUPPAUGE_STARBURST 53
#define CX23885_BOARD_VIEWCAST_260E 54
#define CX23885_BOARD_VIEWCAST_460E 55
+#define CX23885_BOARD_HAUPPAUGE_QUADHD_DVB 56
#define GPIO_0 0x00000001
#define GPIO_1 0x00000002
@@ -430,7 +431,6 @@ struct cx23885_dev {
struct vb2_queue vb2_vidq;
struct cx23885_dmaqueue vbiq;
struct vb2_queue vb2_vbiq;
- void *alloc_ctx;
spinlock_t slock;
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c
index b602eba..df189b1 100644
--- a/drivers/media/pci/cx25821/cx25821-alsa.c
+++ b/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -693,7 +693,7 @@ static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device,
* Only boards with eeprom and byte 1 at eeprom=1 have it
*/
-static const struct pci_device_id cx25821_audio_pci_tbl[] = {
+static const struct pci_device_id __maybe_unused cx25821_audio_pci_tbl[] = {
{0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0,}
};
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c
index 0042803..9a5f912 100644
--- a/drivers/media/pci/cx25821/cx25821-core.c
+++ b/drivers/media/pci/cx25821/cx25821-core.c
@@ -1301,15 +1301,10 @@ static int cx25821_initdev(struct pci_dev *pci_dev,
goto fail_unregister_device;
}
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail_unregister_pci;
- }
err = cx25821_dev_setup(dev);
if (err)
- goto fail_free_ctx;
+ goto fail_unregister_pci;
/* print pci info */
pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
@@ -1340,8 +1335,6 @@ fail_irq:
pr_info("cx25821_initdev() can't get IRQ !\n");
cx25821_dev_unregister(dev);
-fail_free_ctx:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
fail_unregister_pci:
pci_disable_device(pci_dev);
fail_unregister_device:
@@ -1365,7 +1358,6 @@ static void cx25821_finidev(struct pci_dev *pci_dev)
free_irq(pci_dev->irq, dev);
cx25821_dev_unregister(dev);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
v4l2_device_unregister(v4l2_dev);
kfree(dev);
}
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index c48bba9..adcd09b 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -143,13 +143,11 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
static int cx25821_queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct cx25821_channel *chan = q->drv_priv;
unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3;
- alloc_ctxs[0] = chan->dev->alloc_ctx;
-
if (*num_planes)
return sizes[0] < size ? -EINVAL : 0;
@@ -759,6 +757,7 @@ int cx25821_video_register(struct cx25821_dev *dev)
q->mem_ops = &vb2_dma_sg_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &dev->lock;
+ q->dev = &dev->pci->dev;
if (!is_output) {
err = vb2_queue_init(q);
diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h
index a513b68..35c7375 100644
--- a/drivers/media/pci/cx25821/cx25821.h
+++ b/drivers/media/pci/cx25821/cx25821.h
@@ -249,7 +249,6 @@ struct cx25821_dev {
int hwrevision;
/* used by cx25821-alsa */
struct snd_card *card;
- void *alloc_ctx;
u32 clk_freq;
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index e158a1d..f3f13eb 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -799,13 +799,9 @@ static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
{
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
struct cx88_core *core = chip->core;
- struct v4l2_control client_ctl;
-
- memset(&client_ctl, 0, sizeof(client_ctl));
- client_ctl.value = 0 != value->value.integer.value[0];
- client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
- call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
+ wm8775_s_ctrl(core, V4L2_CID_AUDIO_LOUDNESS,
+ value->value.integer.value[0] != 0);
return 0;
}
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 3233d45..04fe9af 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -639,7 +639,7 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
static int queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct cx8802_dev *dev = q->drv_priv;
@@ -647,7 +647,6 @@ static int queue_setup(struct vb2_queue *q,
dev->ts_packet_size = 188 * 4;
dev->ts_packet_count = 32;
sizes[0] = dev->ts_packet_size * dev->ts_packet_count;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
@@ -1183,6 +1182,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
q->mem_ops = &vb2_dma_sg_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &core->lock;
+ q->dev = &dev->pci->dev;
err = vb2_queue_init(q);
if (err < 0)
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index 851d2a9..5bb63e7 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -84,7 +84,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct cx8802_dev *dev = q->drv_priv;
@@ -92,7 +92,6 @@ static int queue_setup(struct vb2_queue *q,
dev->ts_packet_size = 188 * 4;
dev->ts_packet_count = dvb_buf_tscnt;
sizes[0] = dev->ts_packet_size * dev->ts_packet_count;
- alloc_ctxs[0] = dev->alloc_ctx;
*num_buffers = dvb_buf_tscnt;
return 0;
}
@@ -1793,6 +1792,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
q->mem_ops = &vb2_dma_sg_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &core->lock;
+ q->dev = &dev->pci->dev;
err = vb2_queue_init(q);
if (err < 0)
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index f34c229..245357a 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -726,11 +726,6 @@ static int cx8802_probe(struct pci_dev *pci_dev,
if (NULL == dev)
goto fail_core;
dev->pci = pci_dev;
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail_dev;
- }
dev->core = core;
/* Maintain a reference so cx88-video can query the 8802 device. */
@@ -738,7 +733,7 @@ static int cx8802_probe(struct pci_dev *pci_dev,
err = cx8802_init_common(dev);
if (err != 0)
- goto fail_free;
+ goto fail_dev;
INIT_LIST_HEAD(&dev->drvlist);
mutex_lock(&cx8802_mutex);
@@ -749,8 +744,6 @@ static int cx8802_probe(struct pci_dev *pci_dev,
request_modules(dev);
return 0;
- fail_free:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
fail_dev:
kfree(dev);
fail_core:
@@ -798,7 +791,6 @@ static void cx8802_remove(struct pci_dev *pci_dev)
/* common */
cx8802_fini_common(dev);
cx88_core_put(dev->core,dev->pci);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
kfree(dev);
}
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index ccc646d..d3237cf 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -109,7 +109,7 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
static int queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct cx8800_dev *dev = q->drv_priv;
@@ -118,7 +118,6 @@ static int queue_setup(struct vb2_queue *q,
sizes[0] = VBI_LINE_NTSC_COUNT * VBI_LINE_LENGTH * 2;
else
sizes[0] = VBI_LINE_PAL_COUNT * VBI_LINE_LENGTH * 2;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 5f331df..5dc1e3f 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -431,14 +431,13 @@ static int restart_video_queue(struct cx8800_dev *dev,
static int queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct cx8800_dev *dev = q->drv_priv;
struct cx88_core *core = dev->core;
*num_planes = 1;
sizes[0] = (dev->fmt->depth * core->width * core->height) >> 3;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
@@ -1319,12 +1318,6 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
goto fail_core;
}
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail_core;
- }
-
/* initialize driver struct */
spin_lock_init(&dev->slock);
@@ -1445,6 +1438,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
q->mem_ops = &vb2_dma_sg_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &core->lock;
+ q->dev = &dev->pci->dev;
err = vb2_queue_init(q);
if (err < 0)
@@ -1461,6 +1455,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
q->mem_ops = &vb2_dma_sg_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &core->lock;
+ q->dev = &dev->pci->dev;
err = vb2_queue_init(q);
if (err < 0)
@@ -1530,7 +1525,6 @@ fail_unreg:
free_irq(pci_dev->irq, dev);
mutex_unlock(&core->lock);
fail_core:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
core->v4ldev = NULL;
cx88_core_put(core,dev->pci);
fail_free:
@@ -1564,7 +1558,6 @@ static void cx8800_finidev(struct pci_dev *pci_dev)
/* free memory */
cx88_core_put(core,dev->pci);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
kfree(dev);
}
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 78f817e..ecd4b7b 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -485,7 +485,6 @@ struct cx8800_dev {
/* pci i/o */
struct pci_dev *pci;
unsigned char pci_rev,pci_lat;
- void *alloc_ctx;
const struct cx8800_fmt *fmt;
@@ -549,7 +548,6 @@ struct cx8802_dev {
/* pci i/o */
struct pci_dev *pci;
unsigned char pci_rev,pci_lat;
- void *alloc_ctx;
/* dma queues */
struct cx88_dmaqueue mpegq;
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index 6e995ef..47def73 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -1569,10 +1569,9 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (pci_enable_device(pdev) < 0)
return -ENODEV;
- dev = vmalloc(sizeof(struct ddb));
+ dev = vzalloc(sizeof(struct ddb));
if (dev == NULL)
return -ENOMEM;
- memset(dev, 0, sizeof(struct ddb));
dev->pdev = pdev;
pci_set_drvdata(pdev, dev);
diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c
index 568c0c8..6a21969 100644
--- a/drivers/media/pci/dt3155/dt3155.c
+++ b/drivers/media/pci/dt3155/dt3155.c
@@ -133,7 +133,7 @@ static int wait_i2c_reg(void __iomem *addr)
static int
dt3155_queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct dt3155_priv *pd = vb2_get_drv_priv(vq);
@@ -141,7 +141,6 @@ dt3155_queue_setup(struct vb2_queue *vq,
if (vq->num_buffers + *nbuffers < 2)
*nbuffers = 2 - vq->num_buffers;
- alloc_ctxs[0] = pd->alloc_ctx;
if (*num_planes)
return sizes[0] < size ? -EINVAL : 0;
*num_planes = 1;
@@ -544,21 +543,16 @@ static int dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pd->vidq.min_buffers_needed = 2;
pd->vidq.gfp_flags = GFP_DMA32;
pd->vidq.lock = &pd->mux; /* for locking v4l2_file_operations */
+ pd->vidq.dev = &pdev->dev;
pd->vdev.queue = &pd->vidq;
err = vb2_queue_init(&pd->vidq);
if (err < 0)
goto err_v4l2_dev_unreg;
- pd->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
- if (IS_ERR(pd->alloc_ctx)) {
- dev_err(&pdev->dev, "Can't allocate buffer context");
- err = PTR_ERR(pd->alloc_ctx);
- goto err_v4l2_dev_unreg;
- }
spin_lock_init(&pd->lock);
pd->config = ACQ_MODE_EVEN;
err = pci_enable_device(pdev);
if (err)
- goto err_free_ctx;
+ goto err_v4l2_dev_unreg;
err = pci_request_region(pdev, 0, pci_name(pdev));
if (err)
goto err_pci_disable;
@@ -588,8 +582,6 @@ err_free_reg:
pci_release_region(pdev, 0);
err_pci_disable:
pci_disable_device(pdev);
-err_free_ctx:
- vb2_dma_contig_cleanup_ctx(pd->alloc_ctx);
err_v4l2_dev_unreg:
v4l2_device_unregister(&pd->v4l2_dev);
return err;
@@ -608,7 +600,6 @@ static void dt3155_remove(struct pci_dev *pdev)
pci_iounmap(pdev, pd->regs);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
- vb2_dma_contig_cleanup_ctx(pd->alloc_ctx);
}
static const struct pci_device_id pci_ids[] = {
diff --git a/drivers/media/pci/dt3155/dt3155.h b/drivers/media/pci/dt3155/dt3155.h
index b3531e0..39442e5 100644
--- a/drivers/media/pci/dt3155/dt3155.h
+++ b/drivers/media/pci/dt3155/dt3155.h
@@ -161,7 +161,6 @@
* @vdev: video_device structure
* @pdev: pointer to pci_dev structure
* @vidq: vb2_queue structure
- * @alloc_ctx: dma_contig allocation context
* @curr_buf: pointer to curren buffer
* @mux: mutex to protect the instance
* @dmaq: queue for dma buffers
@@ -181,7 +180,6 @@ struct dt3155_priv {
struct video_device vdev;
struct pci_dev *pdev;
struct vb2_queue vidq;
- struct vb2_alloc_ctx *alloc_ctx;
struct vb2_v4l2_buffer *curr_buf;
struct mutex mux;
struct list_head dmaq;
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-mixer.c b/drivers/media/pci/ivtv/ivtv-alsa-mixer.c
index 33ec05b..79b24bd 100644
--- a/drivers/media/pci/ivtv/ivtv-alsa-mixer.c
+++ b/drivers/media/pci/ivtv/ivtv-alsa-mixer.c
@@ -93,7 +93,7 @@ static int snd_ivtv_mixer_tv_vol_get(struct snd_kcontrol *kctl,
vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]);
snd_ivtv_lock(itvsc);
- ret = v4l2_subdev_call(itv->sd_audio, core, g_ctrl, &vctrl);
+ ret = v4l2_g_ctrl(itv->sd_audio->ctrl_handler, &vctrl);
snd_ivtv_unlock(itvsc);
if (!ret)
@@ -115,14 +115,14 @@ static int snd_ivtv_mixer_tv_vol_put(struct snd_kcontrol *kctl,
snd_ivtv_lock(itvsc);
/* Fetch current state */
- ret = v4l2_subdev_call(itv->sd_audio, core, g_ctrl, &vctrl);
+ ret = v4l2_g_ctrl(itv->sd_audio->ctrl_handler, &vctrl);
if (ret ||
(cx25840_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) {
/* Set, if needed */
vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]);
- ret = v4l2_subdev_call(itv->sd_audio, core, s_ctrl, &vctrl);
+ ret = v4l2_s_ctrl(itv->sd_audio->ctrl_handler, &vctrl);
if (!ret)
ret = 1; /* Indicate control was changed w/o error */
}
diff --git a/drivers/media/pci/netup_unidvb/Kconfig b/drivers/media/pci/netup_unidvb/Kconfig
index f277b0b..0ad3771 100644
--- a/drivers/media/pci/netup_unidvb/Kconfig
+++ b/drivers/media/pci/netup_unidvb/Kconfig
@@ -5,8 +5,13 @@ config DVB_NETUP_UNIDVB
select VIDEOBUF2_VMALLOC
select DVB_HORUS3A if MEDIA_SUBDRV_AUTOSELECT
select DVB_ASCOT2E if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_HELENE if MEDIA_SUBDRV_AUTOSELECT
select DVB_LNBH25 if MEDIA_SUBDRV_AUTOSELECT
select DVB_CXD2841ER if MEDIA_SUBDRV_AUTOSELECT
---help---
Support for NetUP PCI express Universal DVB card.
-
+ help
+ Say Y when you want to support NetUP Dual Universal DVB card
+ Card can receive two independent streams in following standards:
+ DVB-S/S2, T/T2, C/C2
+ Two CI slots available for CAM modules.
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb.h b/drivers/media/pci/netup_unidvb/netup_unidvb.h
index a67b281..39b08ec 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb.h
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb.h
@@ -50,6 +50,15 @@
#define NETUP_UNIDVB_IRQ_CAM0 (1 << 11)
#define NETUP_UNIDVB_IRQ_CAM1 (1 << 12)
+/* NetUP Universal DVB card hardware revisions and it's PCI device id's:
+ * 1.3 - CXD2841ER demod, ASCOT2E and HORUS3A tuners
+ * 1.4 - CXD2854ER demod, HELENE tuner
+*/
+enum netup_hw_rev {
+ NETUP_HW_REV_1_3 = 0x18F6,
+ NETUP_HW_REV_1_4 = 0x18F7
+};
+
struct netup_dma {
u8 num;
spinlock_t lock;
@@ -119,6 +128,7 @@ struct netup_unidvb_dev {
struct netup_dma dma[2];
struct netup_ci_state ci[2];
struct netup_spi *spi;
+ enum netup_hw_rev rev;
};
int netup_i2c_register(struct netup_unidvb_dev *ndev);
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c b/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
index f46ffac6..f535270 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
@@ -147,7 +147,7 @@ static int netup_unidvb_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
{
struct netup_ci_state *state = en50221->data;
struct netup_unidvb_dev *dev = state->dev;
- u8 val = *((u8 __force *)state->membase8_io + addr);
+ u8 val = *((u8 __force *)state->membase8_config + addr);
dev_dbg(&dev->pci_dev->dev,
"%s(): addr=0x%x val=0x%x\n", __func__, addr, val);
@@ -162,7 +162,7 @@ static int netup_unidvb_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
dev_dbg(&dev->pci_dev->dev,
"%s(): addr=0x%x data=0x%x\n", __func__, addr, data);
- *((u8 __force *)state->membase8_io + addr) = data;
+ *((u8 __force *)state->membase8_config + addr) = data;
return 0;
}
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
index 2b667b3..ac547cb 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
@@ -34,6 +34,7 @@
#include "cxd2841er.h"
#include "horus3a.h"
#include "ascot2e.h"
+#include "helene.h"
#include "lnbh25.h"
static int spi_enable;
@@ -120,7 +121,8 @@ static int netup_unidvb_tuner_ctrl(void *priv, int is_dvb_tc);
static void netup_unidvb_queue_cleanup(struct netup_dma *dma);
static struct cxd2841er_config demod_config = {
- .i2c_addr = 0xc8
+ .i2c_addr = 0xc8,
+ .xtal = SONY_XTAL_24000
};
static struct horus3a_config horus3a_conf = {
@@ -134,6 +136,12 @@ static struct ascot2e_config ascot2e_conf = {
.set_tuner_callback = netup_unidvb_tuner_ctrl
};
+static struct helene_config helene_conf = {
+ .i2c_address = 0xc0,
+ .xtal = SONY_HELENE_XTAL_24000,
+ .set_tuner_callback = netup_unidvb_tuner_ctrl
+};
+
static struct lnbh25_config lnbh25_conf = {
.i2c_address = 0x10,
.data2_config = LNBH25_TEN | LNBH25_EXTM
@@ -152,6 +160,11 @@ static int netup_unidvb_tuner_ctrl(void *priv, int is_dvb_tc)
__func__, dma->num, is_dvb_tc);
reg = readb(ndev->bmmio0 + GPIO_REG_IO);
mask = (dma->num == 0) ? GPIO_RFA_CTL : GPIO_RFB_CTL;
+
+ /* inverted tuner control in hw rev. 1.4 */
+ if (ndev->rev == NETUP_HW_REV_1_4)
+ is_dvb_tc = !is_dvb_tc;
+
if (!is_dvb_tc)
reg |= mask;
else
@@ -280,7 +293,7 @@ static int netup_unidvb_queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers,
unsigned int *nplanes,
unsigned int sizes[],
- void *alloc_ctxs[])
+ struct device *alloc_devs[])
{
struct netup_dma *dma = vb2_get_drv_priv(vq);
@@ -372,7 +385,15 @@ static int netup_unidvb_queue_init(struct netup_dma *dma,
static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev,
int num)
{
- struct vb2_dvb_frontend *fe0, *fe1, *fe2;
+ int fe_count = 2;
+ int i = 0;
+ struct vb2_dvb_frontend *fes[2];
+ u8 fe_name[32];
+
+ if (ndev->rev == NETUP_HW_REV_1_3)
+ demod_config.xtal = SONY_XTAL_20500;
+ else
+ demod_config.xtal = SONY_XTAL_24000;
if (num < 0 || num > 1) {
dev_dbg(&ndev->pci_dev->dev,
@@ -381,84 +402,96 @@ static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev,
}
mutex_init(&ndev->frontends[num].lock);
INIT_LIST_HEAD(&ndev->frontends[num].felist);
- if (vb2_dvb_alloc_frontend(&ndev->frontends[num], 1) == NULL ||
- vb2_dvb_alloc_frontend(
- &ndev->frontends[num], 2) == NULL ||
- vb2_dvb_alloc_frontend(
- &ndev->frontends[num], 3) == NULL) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to allocate vb2_dvb_frontend\n",
- __func__);
- return -ENOMEM;
+
+ for (i = 0; i < fe_count; i++) {
+ if (vb2_dvb_alloc_frontend(&ndev->frontends[num], i+1)
+ == NULL) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): unable to allocate vb2_dvb_frontend\n",
+ __func__);
+ return -ENOMEM;
+ }
}
- fe0 = vb2_dvb_get_frontend(&ndev->frontends[num], 1);
- fe1 = vb2_dvb_get_frontend(&ndev->frontends[num], 2);
- fe2 = vb2_dvb_get_frontend(&ndev->frontends[num], 3);
- if (fe0 == NULL || fe1 == NULL || fe2 == NULL) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): frontends has not been allocated\n", __func__);
- return -EINVAL;
+
+ for (i = 0; i < fe_count; i++) {
+ fes[i] = vb2_dvb_get_frontend(&ndev->frontends[num], i+1);
+ if (fes[i] == NULL) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): frontends has not been allocated\n",
+ __func__);
+ return -EINVAL;
+ }
+ }
+
+ for (i = 0; i < fe_count; i++) {
+ netup_unidvb_queue_init(&ndev->dma[num], &fes[i]->dvb.dvbq);
+ snprintf(fe_name, sizeof(fe_name), "netup_fe%d", i);
+ fes[i]->dvb.name = fe_name;
}
- netup_unidvb_queue_init(&ndev->dma[num], &fe0->dvb.dvbq);
- netup_unidvb_queue_init(&ndev->dma[num], &fe1->dvb.dvbq);
- netup_unidvb_queue_init(&ndev->dma[num], &fe2->dvb.dvbq);
- fe0->dvb.name = "netup_fe0";
- fe1->dvb.name = "netup_fe1";
- fe2->dvb.name = "netup_fe2";
- fe0->dvb.frontend = dvb_attach(cxd2841er_attach_s,
+
+ fes[0]->dvb.frontend = dvb_attach(cxd2841er_attach_s,
&demod_config, &ndev->i2c[num].adap);
- if (fe0->dvb.frontend == NULL) {
+ if (fes[0]->dvb.frontend == NULL) {
dev_dbg(&ndev->pci_dev->dev,
"%s(): unable to attach DVB-S/S2 frontend\n",
__func__);
goto frontend_detach;
}
- horus3a_conf.set_tuner_priv = &ndev->dma[num];
- if (!dvb_attach(horus3a_attach, fe0->dvb.frontend,
- &horus3a_conf, &ndev->i2c[num].adap)) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to attach DVB-S/S2 tuner frontend\n",
- __func__);
- goto frontend_detach;
+
+ if (ndev->rev == NETUP_HW_REV_1_3) {
+ horus3a_conf.set_tuner_priv = &ndev->dma[num];
+ if (!dvb_attach(horus3a_attach, fes[0]->dvb.frontend,
+ &horus3a_conf, &ndev->i2c[num].adap)) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach HORUS3A DVB-S/S2 tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
+ } else {
+ helene_conf.set_tuner_priv = &ndev->dma[num];
+ if (!dvb_attach(helene_attach_s, fes[0]->dvb.frontend,
+ &helene_conf, &ndev->i2c[num].adap)) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): unable to attach HELENE DVB-S/S2 tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
}
- if (!dvb_attach(lnbh25_attach, fe0->dvb.frontend,
+
+ if (!dvb_attach(lnbh25_attach, fes[0]->dvb.frontend,
&lnbh25_conf, &ndev->i2c[num].adap)) {
dev_dbg(&ndev->pci_dev->dev,
"%s(): unable to attach SEC frontend\n", __func__);
goto frontend_detach;
}
+
/* DVB-T/T2 frontend */
- fe1->dvb.frontend = dvb_attach(cxd2841er_attach_t,
+ fes[1]->dvb.frontend = dvb_attach(cxd2841er_attach_t_c,
&demod_config, &ndev->i2c[num].adap);
- if (fe1->dvb.frontend == NULL) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to attach DVB-T frontend\n", __func__);
- goto frontend_detach;
- }
- fe1->dvb.frontend->id = 1;
- ascot2e_conf.set_tuner_priv = &ndev->dma[num];
- if (!dvb_attach(ascot2e_attach, fe1->dvb.frontend,
- &ascot2e_conf, &ndev->i2c[num].adap)) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to attach DVB-T tuner frontend\n",
- __func__);
- goto frontend_detach;
- }
- /* DVB-C/C2 frontend */
- fe2->dvb.frontend = dvb_attach(cxd2841er_attach_c,
- &demod_config, &ndev->i2c[num].adap);
- if (fe2->dvb.frontend == NULL) {
+ if (fes[1]->dvb.frontend == NULL) {
dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to attach DVB-C frontend\n", __func__);
+ "%s(): unable to attach Ter frontend\n", __func__);
goto frontend_detach;
}
- fe2->dvb.frontend->id = 2;
- if (!dvb_attach(ascot2e_attach, fe2->dvb.frontend,
- &ascot2e_conf, &ndev->i2c[num].adap)) {
- dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to attach DVB-T/C tuner frontend\n",
- __func__);
- goto frontend_detach;
+ fes[1]->dvb.frontend->id = 1;
+ if (ndev->rev == NETUP_HW_REV_1_3) {
+ ascot2e_conf.set_tuner_priv = &ndev->dma[num];
+ if (!dvb_attach(ascot2e_attach, fes[1]->dvb.frontend,
+ &ascot2e_conf, &ndev->i2c[num].adap)) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach Ter tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
+ } else {
+ helene_conf.set_tuner_priv = &ndev->dma[num];
+ if (!dvb_attach(helene_attach, fes[1]->dvb.frontend,
+ &helene_conf, &ndev->i2c[num].adap)) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): unable to attach HELENE Ter tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
}
if (vb2_dvb_register_bus(&ndev->frontends[num],
@@ -730,7 +763,7 @@ static int netup_unidvb_request_mmio(struct pci_dev *pci_dev)
static int netup_unidvb_request_modules(struct device *dev)
{
static const char * const modules[] = {
- "lnbh25", "ascot2e", "horus3a", "cxd2841er", NULL
+ "lnbh25", "ascot2e", "horus3a", "cxd2841er", "helene", NULL
};
const char * const *curr_mod = modules;
int err;
@@ -774,6 +807,16 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev,
if (!ndev)
goto dev_alloc_err;
+ /* detect hardware revision */
+ if (pci_dev->device == NETUP_HW_REV_1_3)
+ ndev->rev = NETUP_HW_REV_1_3;
+ else
+ ndev->rev = NETUP_HW_REV_1_4;
+
+ dev_info(&pci_dev->dev,
+ "%s(): board (0x%x) hardware revision 0x%x\n",
+ __func__, pci_dev->device, ndev->rev);
+
ndev->old_fw = old_firmware;
ndev->wq = create_singlethread_workqueue(NETUP_UNIDVB_NAME);
if (!ndev->wq) {
@@ -932,7 +975,7 @@ wq_create_err:
kfree(ndev);
dev_alloc_err:
dev_err(&pci_dev->dev,
- "%s(): failed to initizalize device\n", __func__);
+ "%s(): failed to initialize device\n", __func__);
return -EIO;
}
@@ -972,7 +1015,8 @@ static void netup_unidvb_finidev(struct pci_dev *pci_dev)
static struct pci_device_id netup_unidvb_pci_tbl[] = {
- { PCI_DEVICE(0x1b55, 0x18f6) },
+ { PCI_DEVICE(0x1b55, 0x18f6) }, /* hw rev. 1.3 */
+ { PCI_DEVICE(0x1b55, 0x18f7) }, /* hw rev. 1.4 */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, netup_unidvb_pci_tbl);
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index c0e1780..ffb66a9 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -1164,18 +1164,13 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
saa7134_board_init1(dev);
saa7134_hwinit1(dev);
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail3;
- }
/* get irq */
err = request_irq(pci_dev->irq, saa7134_irq,
IRQF_SHARED, dev->name, dev);
if (err < 0) {
pr_err("%s: can't get IRQ %d\n",
dev->name,pci_dev->irq);
- goto fail4;
+ goto fail3;
}
/* wait a bit, register i2c bus */
@@ -1233,7 +1228,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
if (err < 0) {
pr_info("%s: can't register video device\n",
dev->name);
- goto fail5;
+ goto fail4;
}
pr_info("%s: registered device %s [v4l2]\n",
dev->name, video_device_node_name(dev->video_dev));
@@ -1246,7 +1241,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
vbi_nr[dev->nr]);
if (err < 0)
- goto fail5;
+ goto fail4;
pr_info("%s: registered device %s\n",
dev->name, video_device_node_name(dev->vbi_dev));
@@ -1257,7 +1252,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
radio_nr[dev->nr]);
if (err < 0)
- goto fail5;
+ goto fail4;
pr_info("%s: registered device %s\n",
dev->name, video_device_node_name(dev->radio_dev));
}
@@ -1268,7 +1263,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
err = v4l2_mc_create_media_graph(dev->media_dev);
if (err) {
pr_err("failed to create media graph\n");
- goto fail5;
+ goto fail4;
}
#endif
/* everything worked */
@@ -1287,17 +1282,15 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
#ifdef CONFIG_MEDIA_CONTROLLER
err = media_device_register(dev->media_dev);
if (err)
- goto fail5;
+ goto fail4;
#endif
return 0;
- fail5:
+ fail4:
saa7134_unregister_video(dev);
saa7134_i2c_unregister(dev);
free_irq(pci_dev->irq, dev);
- fail4:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
fail3:
saa7134_hwfini(dev);
iounmap(dev->lmmio);
@@ -1367,7 +1360,6 @@ static void saa7134_finidev(struct pci_dev *pci_dev)
/* release resources */
free_irq(pci_dev->irq, dev);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
iounmap(dev->lmmio);
release_mem_region(pci_resource_start(pci_dev,0),
pci_resource_len(pci_dev,0));
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index 0584a2a..7eaf36a 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
int saa7134_ts_queue_setup(struct vb2_queue *q,
unsigned int *nbuffers, unsigned int *nplanes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct saa7134_dmaqueue *dmaq = q->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
@@ -131,7 +131,6 @@ int saa7134_ts_queue_setup(struct vb2_queue *q,
*nbuffers = 3;
*nplanes = 1;
sizes[0] = size;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
EXPORT_SYMBOL_GPL(saa7134_ts_queue_setup);
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index e76da37..cf9a31e 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -140,7 +140,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
static int queue_setup(struct vb2_queue *q,
unsigned int *nbuffers, unsigned int *nplanes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct saa7134_dmaqueue *dmaq = q->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
@@ -155,7 +155,6 @@ static int queue_setup(struct vb2_queue *q,
*nbuffers = saa7134_buffer_count(size, *nbuffers);
*nplanes = 1;
sizes[0] = size;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index ffa3954..8a6ebd0 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -963,7 +963,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
static int queue_setup(struct vb2_queue *q,
unsigned int *nbuffers, unsigned int *nplanes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct saa7134_dmaqueue *dmaq = q->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
@@ -980,7 +980,6 @@ static int queue_setup(struct vb2_queue *q,
*nbuffers = saa7134_buffer_count(size, *nbuffers);
*nplanes = 1;
sizes[0] = size;
- alloc_ctxs[0] = dev->alloc_ctx;
saa7134_enable_analog_tuner(dev);
@@ -2173,6 +2172,7 @@ int saa7134_video_init1(struct saa7134_dev *dev)
q->buf_struct_size = sizeof(struct saa7134_buf);
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &dev->lock;
+ q->dev = &dev->pci->dev;
ret = vb2_queue_init(q);
if (ret)
return ret;
@@ -2191,6 +2191,7 @@ int saa7134_video_init1(struct saa7134_dev *dev)
q->buf_struct_size = sizeof(struct saa7134_buf);
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &dev->lock;
+ q->dev = &dev->pci->dev;
ret = vb2_queue_init(q);
if (ret)
return ret;
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 69a9bbf..3849083 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -610,7 +610,6 @@ struct saa7134_dev {
/* video+ts+vbi capture */
- void *alloc_ctx;
struct saa7134_dmaqueue video_q;
struct vb2_queue video_vbq;
struct saa7134_dmaqueue vbi_q;
@@ -854,7 +853,7 @@ int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
int saa7134_ts_queue_setup(struct vb2_queue *q,
unsigned int *nbuffers, unsigned int *nplanes,
- unsigned int sizes[], void *alloc_ctxs[]);
+ unsigned int sizes[], struct device *alloc_devs[]);
int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count);
void saa7134_ts_stop_streaming(struct vb2_queue *vq);
diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c
index 1b184c3..32a353d 100644
--- a/drivers/media/pci/saa7164/saa7164-encoder.c
+++ b/drivers/media/pci/saa7164/saa7164-encoder.c
@@ -1022,8 +1022,7 @@ int saa7164_encoder_register(struct saa7164_port *port)
dprintk(DBGLVL_ENC, "%s()\n", __func__);
- if (port->type != SAA7164_MPEG_ENCODER)
- BUG();
+ BUG_ON(port->type != SAA7164_MPEG_ENCODER);
/* Sanity check that the PCI configuration space is active */
if (port->hwcfg.BARLocation == 0) {
@@ -1151,8 +1150,7 @@ void saa7164_encoder_unregister(struct saa7164_port *port)
dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
- if (port->type != SAA7164_MPEG_ENCODER)
- BUG();
+ BUG_ON(port->type != SAA7164_MPEG_ENCODER);
if (port->v4l_device) {
if (port->v4l_device->minor != -1)
diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h
index 8337524..97411b0 100644
--- a/drivers/media/pci/saa7164/saa7164.h
+++ b/drivers/media/pci/saa7164/saa7164.h
@@ -263,10 +263,6 @@ struct saa7164_i2c {
u32 i2c_rc;
};
-struct saa7164_ctrl {
- struct v4l2_queryctrl v;
-};
-
struct saa7164_tvnorm {
char *name;
v4l2_std_id id;
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 67a14c4..3991643 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -33,7 +33,7 @@
#include "solo6x10-jpeg.h"
#define MIN_VID_BUFFERS 2
-#define FRAME_BUF_SIZE (196 * 1024)
+#define FRAME_BUF_SIZE (400 * 1024)
#define MP4_QS 16
#define DMA_ALIGN 4096
@@ -664,12 +664,9 @@ static int solo_ring_thread(void *data)
static int solo_enc_queue_setup(struct vb2_queue *q,
unsigned int *num_buffers,
unsigned int *num_planes, unsigned int sizes[],
- void *alloc_ctxs[])
+ struct device *alloc_devs[])
{
- struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
-
sizes[0] = FRAME_BUF_SIZE;
- alloc_ctxs[0] = solo_enc->alloc_ctx;
*num_planes = 1;
if (*num_buffers < MIN_VID_BUFFERS)
@@ -1239,11 +1236,6 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
return ERR_PTR(-ENOMEM);
hdl = &solo_enc->hdl;
- solo_enc->alloc_ctx = vb2_dma_sg_init_ctx(&solo_dev->pdev->dev);
- if (IS_ERR(solo_enc->alloc_ctx)) {
- ret = PTR_ERR(solo_enc->alloc_ctx);
- goto hdl_free;
- }
v4l2_ctrl_handler_init(hdl, 10);
v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
@@ -1299,6 +1291,7 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
solo_enc->vidq.lock = &solo_enc->lock;
+ solo_enc->vidq.dev = &solo_dev->pdev->dev;
ret = vb2_queue_init(&solo_enc->vidq);
if (ret)
goto hdl_free;
@@ -1347,7 +1340,6 @@ pci_free:
solo_enc->desc_items, solo_enc->desc_dma);
hdl_free:
v4l2_ctrl_handler_free(hdl);
- vb2_dma_sg_cleanup_ctx(solo_enc->alloc_ctx);
kfree(solo_enc);
return ERR_PTR(ret);
}
@@ -1362,7 +1354,6 @@ static void solo_enc_free(struct solo_enc_dev *solo_enc)
solo_enc->desc_items, solo_enc->desc_dma);
video_unregister_device(solo_enc->vfd);
v4l2_ctrl_handler_free(&solo_enc->hdl);
- vb2_dma_sg_cleanup_ctx(solo_enc->alloc_ctx);
kfree(solo_enc);
}
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
index 721ff53..b4be479 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
@@ -315,12 +315,11 @@ static void solo_stop_thread(struct solo_dev *solo_dev)
static int solo_queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct solo_dev *solo_dev = vb2_get_drv_priv(q);
sizes[0] = solo_image_size(solo_dev);
- alloc_ctxs[0] = solo_dev->alloc_ctx;
*num_planes = 1;
if (*num_buffers < MIN_VID_BUFFERS)
@@ -386,26 +385,24 @@ static int solo_querycap(struct file *file, void *priv,
static int solo_enum_ext_input(struct solo_dev *solo_dev,
struct v4l2_input *input)
{
- static const char * const dispnames_1[] = { "4UP" };
- static const char * const dispnames_2[] = { "4UP-1", "4UP-2" };
- static const char * const dispnames_5[] = {
- "4UP-1", "4UP-2", "4UP-3", "4UP-4", "16UP"
- };
- const char * const *dispnames;
+ int ext = input->index - solo_dev->nr_chans;
+ unsigned int nup, first;
- if (input->index >= (solo_dev->nr_chans + solo_dev->nr_ext))
+ if (ext >= solo_dev->nr_ext)
return -EINVAL;
- if (solo_dev->nr_ext == 5)
- dispnames = dispnames_5;
- else if (solo_dev->nr_ext == 2)
- dispnames = dispnames_2;
- else
- dispnames = dispnames_1;
-
- snprintf(input->name, sizeof(input->name), "Multi %s",
- dispnames[input->index - solo_dev->nr_chans]);
-
+ nup = (ext == 4) ? 16 : 4;
+ first = (ext & 3) << 2; /* first channel in the n-up */
+ snprintf(input->name, sizeof(input->name),
+ "Multi %d-up (cameras %d-%d)",
+ nup, first + 1, first + nup);
+ /* Possible outputs:
+ * Multi 4-up (cameras 1-4)
+ * Multi 4-up (cameras 5-8)
+ * Multi 4-up (cameras 9-12)
+ * Multi 4-up (cameras 13-16)
+ * Multi 16-up (cameras 1-16)
+ */
return 0;
}
@@ -681,16 +678,11 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
solo_dev->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
solo_dev->vidq.lock = &solo_dev->lock;
+ solo_dev->vidq.dev = &solo_dev->pdev->dev;
ret = vb2_queue_init(&solo_dev->vidq);
if (ret < 0)
goto fail;
- solo_dev->alloc_ctx = vb2_dma_contig_init_ctx(&solo_dev->pdev->dev);
- if (IS_ERR(solo_dev->alloc_ctx)) {
- dev_err(&solo_dev->pdev->dev, "Can't allocate buffer context");
- return PTR_ERR(solo_dev->alloc_ctx);
- }
-
/* Cycle all the channels and clear */
for (i = 0; i < solo_dev->nr_chans; i++) {
solo_v4l2_set_ch(solo_dev, i);
@@ -718,7 +710,6 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
fail:
video_device_release(solo_dev->vfd);
- vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
solo_dev->vfd = NULL;
return ret;
@@ -730,7 +721,6 @@ void solo_v4l2_exit(struct solo_dev *solo_dev)
return;
video_unregister_device(solo_dev->vfd);
- vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
solo_dev->vfd = NULL;
}
diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
index 4ab6586..5bd4987 100644
--- a/drivers/media/pci/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -178,7 +178,6 @@ struct solo_enc_dev {
u32 sequence;
struct vb2_queue vidq;
struct list_head vidq_active;
- void *alloc_ctx;
int desc_count;
int desc_nelts;
struct solo_p2m_desc *desc_items;
@@ -269,7 +268,6 @@ struct solo_dev {
/* Buffer handling */
struct vb2_queue vidq;
- struct vb2_alloc_ctx *alloc_ctx;
u32 sequence;
struct task_struct *kthread;
struct mutex lock;
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index 1fc195f..aeb2b4e 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -111,7 +111,6 @@ static inline struct vip_buffer *to_vip_buffer(struct vb2_v4l2_buffer *vb2)
* @input: input line for video signal ( 0 or 1 )
* @disabled: Device is in power down state
* @slock: for excluse acces of registers
- * @alloc_ctx: context for videobuf2
* @vb_vidq: queue maintained by videobuf2 layer
* @buffer_list: list of buffer in use
* @sequence: sequence number of acquired buffer
@@ -141,7 +140,6 @@ struct sta2x11_vip {
int disabled;
spinlock_t slock;
- struct vb2_alloc_ctx *alloc_ctx;
struct vb2_queue vb_vidq;
struct list_head buffer_list;
unsigned int sequence;
@@ -267,7 +265,7 @@ static void vip_active_buf_next(struct sta2x11_vip *vip)
/* Videobuf2 Operations */
static int queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers, unsigned int *nplanes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct sta2x11_vip *vip = vb2_get_drv_priv(vq);
@@ -276,7 +274,6 @@ static int queue_setup(struct vb2_queue *vq,
*nplanes = 1;
sizes[0] = vip->format.sizeimage;
- alloc_ctxs[0] = vip->alloc_ctx;
vip->sequence = 0;
vip->active = NULL;
@@ -861,25 +858,15 @@ static int sta2x11_vip_init_buffer(struct sta2x11_vip *vip)
vip->vb_vidq.ops = &vip_video_qops;
vip->vb_vidq.mem_ops = &vb2_dma_contig_memops;
vip->vb_vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ vip->vb_vidq.dev = &vip->pdev->dev;
err = vb2_queue_init(&vip->vb_vidq);
if (err)
return err;
INIT_LIST_HEAD(&vip->buffer_list);
spin_lock_init(&vip->lock);
-
-
- vip->alloc_ctx = vb2_dma_contig_init_ctx(&vip->pdev->dev);
- if (IS_ERR(vip->alloc_ctx)) {
- v4l2_err(&vip->v4l2_dev, "Can't allocate buffer context");
- return PTR_ERR(vip->alloc_ctx);
- }
-
return 0;
}
-static void sta2x11_vip_release_buffer(struct sta2x11_vip *vip)
-{
- vb2_dma_contig_cleanup_ctx(vip->alloc_ctx);
-}
+
static int sta2x11_vip_init_controls(struct sta2x11_vip *vip)
{
/*
@@ -1120,7 +1107,6 @@ vrelease:
video_unregister_device(&vip->video_dev);
free_irq(pdev->irq, vip);
release_buf:
- sta2x11_vip_release_buffer(vip);
pci_disable_msi(pdev);
unmap:
vb2_queue_release(&vip->vb_vidq);
diff --git a/drivers/media/pci/tw68/tw68-core.c b/drivers/media/pci/tw68/tw68-core.c
index 4e77618..8474528 100644
--- a/drivers/media/pci/tw68/tw68-core.c
+++ b/drivers/media/pci/tw68/tw68-core.c
@@ -305,19 +305,13 @@ static int tw68_initdev(struct pci_dev *pci_dev,
/* Then do any initialisation wanted before interrupts are on */
tw68_hw_init1(dev);
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail3;
- }
-
/* get irq */
err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw68_irq,
IRQF_SHARED, dev->name, dev);
if (err < 0) {
pr_err("%s: can't get IRQ %d\n",
dev->name, pci_dev->irq);
- goto fail4;
+ goto fail3;
}
/*
@@ -331,7 +325,7 @@ static int tw68_initdev(struct pci_dev *pci_dev,
if (err < 0) {
pr_err("%s: can't register video device\n",
dev->name);
- goto fail5;
+ goto fail4;
}
tw_setl(TW68_INTMASK, dev->pci_irqmask);
@@ -340,10 +334,8 @@ static int tw68_initdev(struct pci_dev *pci_dev,
return 0;
-fail5:
- video_unregister_device(&dev->vdev);
fail4:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
+ video_unregister_device(&dev->vdev);
fail3:
iounmap(dev->lmmio);
fail2:
@@ -367,7 +359,6 @@ static void tw68_finidev(struct pci_dev *pci_dev)
/* unregister */
video_unregister_device(&dev->vdev);
v4l2_ctrl_handler_free(&dev->hdl);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
/* release resources */
iounmap(dev->lmmio);
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index 07116a8..5e82128 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -378,7 +378,7 @@ static int tw68_buffer_count(unsigned int size, unsigned int count)
static int tw68_queue_setup(struct vb2_queue *q,
unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct tw68_dev *dev = vb2_get_drv_priv(q);
unsigned tot_bufs = q->num_buffers + *num_buffers;
@@ -388,7 +388,6 @@ static int tw68_queue_setup(struct vb2_queue *q,
tot_bufs = 2;
tot_bufs = tw68_buffer_count(size, tot_bufs);
*num_buffers = tot_bufs - q->num_buffers;
- alloc_ctxs[0] = dev->alloc_ctx;
/*
* We allow create_bufs, but only if the sizeimage is >= as the
* current sizeimage. The tw68_buffer_count calculation becomes quite
@@ -983,6 +982,7 @@ int tw68_video_init2(struct tw68_dev *dev, int video_nr)
dev->vidq.buf_struct_size = sizeof(struct tw68_buf);
dev->vidq.lock = &dev->lock;
dev->vidq.min_buffers_needed = 2;
+ dev->vidq.dev = &dev->pci->dev;
ret = vb2_queue_init(&dev->vidq);
if (ret)
return ret;
diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h
index 6c7dcb3..5585c7e 100644
--- a/drivers/media/pci/tw68/tw68.h
+++ b/drivers/media/pci/tw68/tw68.h
@@ -165,7 +165,6 @@ struct tw68_dev {
unsigned field;
struct vb2_queue vidq;
struct list_head active;
- void *alloc_ctx;
/* various v4l controls */
const struct tw68_tvnorm *tvnorm; /* video */
diff --git a/drivers/media/pci/tw686x/Kconfig b/drivers/media/pci/tw686x/Kconfig
index fb85369..34ff377 100644
--- a/drivers/media/pci/tw686x/Kconfig
+++ b/drivers/media/pci/tw686x/Kconfig
@@ -3,6 +3,8 @@ config VIDEO_TW686X
depends on PCI && VIDEO_DEV && VIDEO_V4L2 && SND
depends on HAS_DMA
select VIDEOBUF2_VMALLOC
+ select VIDEOBUF2_DMA_CONTIG
+ select VIDEOBUF2_DMA_SG
select SND_PCM
help
Support for Intersil/Techwell TW686x-based frame grabber cards.
diff --git a/drivers/media/pci/tw686x/tw686x-audio.c b/drivers/media/pci/tw686x/tw686x-audio.c
index 91459ab..96e444c 100644
--- a/drivers/media/pci/tw686x/tw686x-audio.c
+++ b/drivers/media/pci/tw686x/tw686x-audio.c
@@ -62,12 +62,22 @@ void tw686x_audio_irq(struct tw686x_dev *dev, unsigned long requests,
}
spin_unlock_irqrestore(&ac->lock, flags);
+ if (!done || !next)
+ continue;
+ /*
+ * Checking for a non-nil dma_desc[pb]->virt buffer is
+ * the same as checking for memcpy DMA mode.
+ */
desc = &ac->dma_descs[pb];
- if (done && next && desc->virt) {
- memcpy(done->virt, desc->virt, desc->size);
- ac->ptr = done->dma - ac->buf[0].dma;
- snd_pcm_period_elapsed(ac->ss);
+ if (desc->virt) {
+ memcpy(done->virt, desc->virt,
+ dev->period_size);
+ } else {
+ u32 reg = pb ? ADMA_B_ADDR[ch] : ADMA_P_ADDR[ch];
+ reg_write(dev, reg, next->dma);
}
+ ac->ptr = done->dma - ac->buf[0].dma;
+ snd_pcm_period_elapsed(ac->ss);
}
}
@@ -83,10 +93,9 @@ static int tw686x_pcm_hw_free(struct snd_pcm_substream *ss)
}
/*
- * The audio device rate is global and shared among all
- * capture channels. The driver makes no effort to prevent
- * rate modifications. User is free change the rate, but it
- * means changing the rate for all capture sub-devices.
+ * Audio parameters are global and shared among all
+ * capture channels. The driver prevents changes to
+ * the parameters if any audio channel is capturing.
*/
static const struct snd_pcm_hardware tw686x_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
@@ -99,9 +108,9 @@ static const struct snd_pcm_hardware tw686x_capture_hw = {
.rate_max = 48000,
.channels_min = 1,
.channels_max = 1,
- .buffer_bytes_max = TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ,
- .period_bytes_min = TW686X_AUDIO_PAGE_SZ,
- .period_bytes_max = TW686X_AUDIO_PAGE_SZ,
+ .buffer_bytes_max = TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX,
+ .period_bytes_min = AUDIO_DMA_SIZE_MIN,
+ .period_bytes_max = AUDIO_DMA_SIZE_MAX,
.periods_min = TW686X_AUDIO_PERIODS_MIN,
.periods_max = TW686X_AUDIO_PERIODS_MAX,
};
@@ -143,6 +152,14 @@ static int tw686x_pcm_prepare(struct snd_pcm_substream *ss)
int i;
spin_lock_irqsave(&dev->lock, flags);
+ /*
+ * Given the audio parameters are global (i.e. shared across
+ * DMA channels), we need to check new params are allowed.
+ */
+ if (((dev->audio_rate != rt->rate) ||
+ (dev->period_size != period_size)) && dev->audio_enabled)
+ goto err_audio_busy;
+
tw686x_disable_channel(dev, AUDIO_CHANNEL_OFFSET + ac->ch);
spin_unlock_irqrestore(&dev->lock, flags);
@@ -156,12 +173,21 @@ static int tw686x_pcm_prepare(struct snd_pcm_substream *ss)
reg_write(dev, AUDIO_CONTROL2, reg);
}
- if (period_size != TW686X_AUDIO_PAGE_SZ ||
- rt->periods < TW686X_AUDIO_PERIODS_MIN ||
- rt->periods > TW686X_AUDIO_PERIODS_MAX) {
- return -EINVAL;
+ if (dev->period_size != period_size) {
+ u32 reg;
+
+ dev->period_size = period_size;
+ reg = reg_read(dev, AUDIO_CONTROL1);
+ reg &= ~(AUDIO_DMA_SIZE_MASK << AUDIO_DMA_SIZE_SHIFT);
+ reg |= period_size << AUDIO_DMA_SIZE_SHIFT;
+
+ reg_write(dev, AUDIO_CONTROL1, reg);
}
+ if (rt->periods < TW686X_AUDIO_PERIODS_MIN ||
+ rt->periods > TW686X_AUDIO_PERIODS_MAX)
+ return -EINVAL;
+
spin_lock_irqsave(&ac->lock, flags);
INIT_LIST_HEAD(&ac->buf_list);
@@ -181,9 +207,19 @@ static int tw686x_pcm_prepare(struct snd_pcm_substream *ss)
ac->curr_bufs[0] = p_buf;
ac->curr_bufs[1] = b_buf;
ac->ptr = 0;
+
+ if (dev->dma_mode != TW686X_DMA_MODE_MEMCPY) {
+ reg_write(dev, ADMA_P_ADDR[ac->ch], p_buf->dma);
+ reg_write(dev, ADMA_B_ADDR[ac->ch], b_buf->dma);
+ }
+
spin_unlock_irqrestore(&ac->lock, flags);
return 0;
+
+err_audio_busy:
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return -EBUSY;
}
static int tw686x_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
@@ -197,6 +233,7 @@ static int tw686x_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
case SNDRV_PCM_TRIGGER_START:
if (ac->curr_bufs[0] && ac->curr_bufs[1]) {
spin_lock_irqsave(&dev->lock, flags);
+ dev->audio_enabled = 1;
tw686x_enable_channel(dev,
AUDIO_CHANNEL_OFFSET + ac->ch);
spin_unlock_irqrestore(&dev->lock, flags);
@@ -209,6 +246,7 @@ static int tw686x_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
break;
case SNDRV_PCM_TRIGGER_STOP:
spin_lock_irqsave(&dev->lock, flags);
+ dev->audio_enabled = 0;
tw686x_disable_channel(dev, AUDIO_CHANNEL_OFFSET + ac->ch);
spin_unlock_irqrestore(&dev->lock, flags);
@@ -266,8 +304,8 @@ static int tw686x_snd_pcm_init(struct tw686x_dev *dev)
return snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(dev->pci_dev),
- TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ,
- TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ);
+ TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX,
+ TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX);
}
static void tw686x_audio_dma_free(struct tw686x_dev *dev,
@@ -290,11 +328,19 @@ static int tw686x_audio_dma_alloc(struct tw686x_dev *dev,
{
int pb;
+ /*
+ * In the memcpy DMA mode we allocate a consistent buffer
+ * and use it for the DMA capture. Otherwise, DMA
+ * acts on the ALSA buffers as received in pcm_prepare.
+ */
+ if (dev->dma_mode != TW686X_DMA_MODE_MEMCPY)
+ return 0;
+
for (pb = 0; pb < 2; pb++) {
u32 reg = pb ? ADMA_B_ADDR[ac->ch] : ADMA_P_ADDR[ac->ch];
void *virt;
- virt = pci_alloc_consistent(dev->pci_dev, TW686X_AUDIO_PAGE_SZ,
+ virt = pci_alloc_consistent(dev->pci_dev, AUDIO_DMA_SIZE_MAX,
&ac->dma_descs[pb].phys);
if (!virt) {
dev_err(&dev->pci_dev->dev,
@@ -303,7 +349,7 @@ static int tw686x_audio_dma_alloc(struct tw686x_dev *dev,
return -ENOMEM;
}
ac->dma_descs[pb].virt = virt;
- ac->dma_descs[pb].size = TW686X_AUDIO_PAGE_SZ;
+ ac->dma_descs[pb].size = AUDIO_DMA_SIZE_MAX;
reg_write(dev, reg, ac->dma_descs[pb].phys);
}
return 0;
@@ -334,12 +380,8 @@ int tw686x_audio_init(struct tw686x_dev *dev)
struct snd_card *card;
int err, ch;
- /*
- * AUDIO_CONTROL1
- * DMA byte length [31:19] = 4096 (i.e. ALSA period)
- * External audio enable [0] = enabled
- */
- reg_write(dev, AUDIO_CONTROL1, 0x80000001);
+ /* Enable external audio */
+ reg_write(dev, AUDIO_CONTROL1, BIT(0));
err = snd_card_new(&pci_dev->dev, SNDRV_DEFAULT_IDX1,
SNDRV_DEFAULT_STR1,
diff --git a/drivers/media/pci/tw686x/tw686x-core.c b/drivers/media/pci/tw686x/tw686x-core.c
index cf53b0e..71a0453 100644
--- a/drivers/media/pci/tw686x/tw686x-core.c
+++ b/drivers/media/pci/tw686x/tw686x-core.c
@@ -21,12 +21,14 @@
* under stress testings it has been found that the machine can
* freeze completely if DMA registers are programmed while streaming
* is active.
- * This driver tries to access hardware registers as infrequently
- * as possible by:
- * i. allocating fixed DMA buffers and memcpy'ing into
- * vmalloc'ed buffers
- * ii. using a timer to mitigate the rate of DMA reset operations,
- * on DMA channels error.
+ *
+ * Therefore, driver implements a dma_mode called 'memcpy' which
+ * avoids cycling the DMA buffers, and insteads allocates extra DMA buffers
+ * and then copies into vmalloc'ed user buffers.
+ *
+ * In addition to this, when streaming is on, the driver tries to access
+ * hardware registers as infrequently as possible. This is done by using
+ * a timer to limit the rate at which DMA is reset on DMA channels error.
*/
#include <linux/init.h>
@@ -55,6 +57,42 @@ static u32 dma_interval = 0x00098968;
module_param(dma_interval, int, 0444);
MODULE_PARM_DESC(dma_interval, "Minimum time span for DMA interrupting host");
+static unsigned int dma_mode = TW686X_DMA_MODE_MEMCPY;
+static const char *dma_mode_name(unsigned int mode)
+{
+ switch (mode) {
+ case TW686X_DMA_MODE_MEMCPY:
+ return "memcpy";
+ case TW686X_DMA_MODE_CONTIG:
+ return "contig";
+ case TW686X_DMA_MODE_SG:
+ return "sg";
+ default:
+ return "unknown";
+ }
+}
+
+static int tw686x_dma_mode_get(char *buffer, struct kernel_param *kp)
+{
+ return sprintf(buffer, dma_mode_name(dma_mode));
+}
+
+static int tw686x_dma_mode_set(const char *val, struct kernel_param *kp)
+{
+ if (!strcasecmp(val, dma_mode_name(TW686X_DMA_MODE_MEMCPY)))
+ dma_mode = TW686X_DMA_MODE_MEMCPY;
+ else if (!strcasecmp(val, dma_mode_name(TW686X_DMA_MODE_CONTIG)))
+ dma_mode = TW686X_DMA_MODE_CONTIG;
+ else if (!strcasecmp(val, dma_mode_name(TW686X_DMA_MODE_SG)))
+ dma_mode = TW686X_DMA_MODE_SG;
+ else
+ return -EINVAL;
+ return 0;
+}
+module_param_call(dma_mode, tw686x_dma_mode_set, tw686x_dma_mode_get,
+ &dma_mode, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(dma_mode, "DMA operation mode (memcpy/contig/sg, default=memcpy)");
+
void tw686x_disable_channel(struct tw686x_dev *dev, unsigned int channel)
{
u32 dma_en = reg_read(dev, DMA_CHANNEL_ENABLE);
@@ -212,6 +250,7 @@ static int tw686x_probe(struct pci_dev *pci_dev,
if (!dev)
return -ENOMEM;
dev->type = pci_id->driver_data;
+ dev->dma_mode = dma_mode;
sprintf(dev->name, "tw%04X", pci_dev->device);
dev->video_channels = kcalloc(max_channels(dev),
@@ -228,9 +267,10 @@ static int tw686x_probe(struct pci_dev *pci_dev,
goto free_video;
}
- pr_info("%s: PCI %s, IRQ %d, MMIO 0x%lx\n", dev->name,
+ pr_info("%s: PCI %s, IRQ %d, MMIO 0x%lx (%s mode)\n", dev->name,
pci_name(pci_dev), pci_dev->irq,
- (unsigned long)pci_resource_start(pci_dev, 0));
+ (unsigned long)pci_resource_start(pci_dev, 0),
+ dma_mode_name(dma_mode));
dev->pci_dev = pci_dev;
if (pci_enable_device(pci_dev)) {
diff --git a/drivers/media/pci/tw686x/tw686x-regs.h b/drivers/media/pci/tw686x/tw686x-regs.h
index fcef586..15a9566 100644
--- a/drivers/media/pci/tw686x/tw686x-regs.h
+++ b/drivers/media/pci/tw686x/tw686x-regs.h
@@ -105,6 +105,10 @@
0x2d0, 0x2d1, 0x2d2, 0x2d3 })
#define SYS_MODE_DMA_SHIFT 13
+#define AUDIO_DMA_SIZE_SHIFT 19
+#define AUDIO_DMA_SIZE_MIN SZ_512
+#define AUDIO_DMA_SIZE_MAX SZ_4K
+#define AUDIO_DMA_SIZE_MASK (SZ_8K - 1)
#define DMA_CMD_ENABLE BIT(31)
#define INT_STATUS_DMA_TOUT BIT(17)
@@ -119,4 +123,9 @@
#define TW686X_STD_PAL_CN 5
#define TW686X_STD_PAL_60 6
+#define TW686X_FIELD_MODE 0x3
+#define TW686X_FRAME_MODE 0x2
+/* 0x1 is reserved */
+#define TW686X_SG_MODE 0x0
+
#define TW686X_FIFO_ERROR(x) (x & ~(0xff))
diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c
index 253e108..cdb16de 100644
--- a/drivers/media/pci/tw686x/tw686x-video.c
+++ b/drivers/media/pci/tw686x/tw686x-video.c
@@ -19,6 +19,8 @@
#include <linux/slab.h>
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-dma-sg.h>
#include <media/videobuf2-vmalloc.h>
#include "tw686x.h"
#include "tw686x-regs.h"
@@ -26,6 +28,11 @@
#define TW686X_INPUTS_PER_CH 4
#define TW686X_VIDEO_WIDTH 720
#define TW686X_VIDEO_HEIGHT(id) ((id & V4L2_STD_525_60) ? 480 : 576)
+#define TW686X_MAX_FPS(id) ((id & V4L2_STD_525_60) ? 30 : 25)
+
+#define TW686X_MAX_SG_ENTRY_SIZE 4096
+#define TW686X_MAX_SG_DESC_COUNT 256 /* PAL 720x576 needs 203 4-KB pages */
+#define TW686X_SG_TABLE_SIZE (TW686X_MAX_SG_DESC_COUNT * sizeof(struct tw686x_sg_desc))
static const struct tw686x_format formats[] = {
{
@@ -43,53 +50,367 @@ static const struct tw686x_format formats[] = {
}
};
-static unsigned int tw686x_fields_map(v4l2_std_id std, unsigned int fps)
+static void tw686x_buf_done(struct tw686x_video_channel *vc,
+ unsigned int pb)
{
- static const unsigned int map[15] = {
- 0x00000000, 0x00000001, 0x00004001, 0x00104001, 0x00404041,
- 0x01041041, 0x01104411, 0x01111111, 0x04444445, 0x04511445,
- 0x05145145, 0x05151515, 0x05515455, 0x05551555, 0x05555555
- };
+ struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
+ struct tw686x_dev *dev = vc->dev;
+ struct vb2_v4l2_buffer *vb;
+ struct vb2_buffer *vb2_buf;
- static const unsigned int std_625_50[26] = {
- 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7,
- 8, 8, 9, 10, 10, 11, 11, 12, 13, 13, 14, 14, 0
- };
+ if (vc->curr_bufs[pb]) {
+ vb = &vc->curr_bufs[pb]->vb;
- static const unsigned int std_525_60[31] = {
- 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
- 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 0, 0
- };
+ vb->field = dev->dma_ops->field;
+ vb->sequence = vc->sequence++;
+ vb2_buf = &vb->vb2_buf;
- unsigned int i;
+ if (dev->dma_mode == TW686X_DMA_MODE_MEMCPY)
+ memcpy(vb2_plane_vaddr(vb2_buf, 0), desc->virt,
+ desc->size);
+ vb2_buf->timestamp = ktime_get_ns();
+ vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE);
+ }
+
+ vc->pb = !pb;
+}
+
+/*
+ * We can call this even when alloc_dma failed for the given channel
+ */
+static void tw686x_memcpy_dma_free(struct tw686x_video_channel *vc,
+ unsigned int pb)
+{
+ struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
+ struct tw686x_dev *dev = vc->dev;
+ struct pci_dev *pci_dev;
+ unsigned long flags;
+
+ /* Check device presence. Shouldn't really happen! */
+ spin_lock_irqsave(&dev->lock, flags);
+ pci_dev = dev->pci_dev;
+ spin_unlock_irqrestore(&dev->lock, flags);
+ if (!pci_dev) {
+ WARN(1, "trying to deallocate on missing device\n");
+ return;
+ }
+
+ if (desc->virt) {
+ pci_free_consistent(dev->pci_dev, desc->size,
+ desc->virt, desc->phys);
+ desc->virt = NULL;
+ }
+}
+
+static int tw686x_memcpy_dma_alloc(struct tw686x_video_channel *vc,
+ unsigned int pb)
+{
+ struct tw686x_dev *dev = vc->dev;
+ u32 reg = pb ? VDMA_B_ADDR[vc->ch] : VDMA_P_ADDR[vc->ch];
+ unsigned int len;
+ void *virt;
+
+ WARN(vc->dma_descs[pb].virt,
+ "Allocating buffer but previous still here\n");
+
+ len = (vc->width * vc->height * vc->format->depth) >> 3;
+ virt = pci_alloc_consistent(dev->pci_dev, len,
+ &vc->dma_descs[pb].phys);
+ if (!virt) {
+ v4l2_err(&dev->v4l2_dev,
+ "dma%d: unable to allocate %s-buffer\n",
+ vc->ch, pb ? "B" : "P");
+ return -ENOMEM;
+ }
+ vc->dma_descs[pb].size = len;
+ vc->dma_descs[pb].virt = virt;
+ reg_write(dev, reg, vc->dma_descs[pb].phys);
+
+ return 0;
+}
+
+static void tw686x_memcpy_buf_refill(struct tw686x_video_channel *vc,
+ unsigned int pb)
+{
+ struct tw686x_v4l2_buf *buf;
+
+ while (!list_empty(&vc->vidq_queued)) {
+
+ buf = list_first_entry(&vc->vidq_queued,
+ struct tw686x_v4l2_buf, list);
+ list_del(&buf->list);
+
+ vc->curr_bufs[pb] = buf;
+ return;
+ }
+ vc->curr_bufs[pb] = NULL;
+}
- if (std & V4L2_STD_525_60) {
- if (fps >= ARRAY_SIZE(std_525_60))
- fps = 30;
- i = std_525_60[fps];
+static const struct tw686x_dma_ops memcpy_dma_ops = {
+ .alloc = tw686x_memcpy_dma_alloc,
+ .free = tw686x_memcpy_dma_free,
+ .buf_refill = tw686x_memcpy_buf_refill,
+ .mem_ops = &vb2_vmalloc_memops,
+ .hw_dma_mode = TW686X_FRAME_MODE,
+ .field = V4L2_FIELD_INTERLACED,
+};
+
+static void tw686x_contig_buf_refill(struct tw686x_video_channel *vc,
+ unsigned int pb)
+{
+ struct tw686x_v4l2_buf *buf;
+
+ while (!list_empty(&vc->vidq_queued)) {
+ u32 reg = pb ? VDMA_B_ADDR[vc->ch] : VDMA_P_ADDR[vc->ch];
+ dma_addr_t phys;
+
+ buf = list_first_entry(&vc->vidq_queued,
+ struct tw686x_v4l2_buf, list);
+ list_del(&buf->list);
+
+ phys = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
+ reg_write(vc->dev, reg, phys);
+
+ buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
+ vc->curr_bufs[pb] = buf;
+ return;
+ }
+ vc->curr_bufs[pb] = NULL;
+}
+
+static const struct tw686x_dma_ops contig_dma_ops = {
+ .buf_refill = tw686x_contig_buf_refill,
+ .mem_ops = &vb2_dma_contig_memops,
+ .hw_dma_mode = TW686X_FRAME_MODE,
+ .field = V4L2_FIELD_INTERLACED,
+};
+
+static int tw686x_sg_desc_fill(struct tw686x_sg_desc *descs,
+ struct tw686x_v4l2_buf *buf,
+ unsigned int buf_len)
+{
+ struct sg_table *vbuf = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
+ unsigned int len, entry_len;
+ struct scatterlist *sg;
+ int i, count;
+
+ /* Clear the scatter-gather table */
+ memset(descs, 0, TW686X_SG_TABLE_SIZE);
+
+ count = 0;
+ for_each_sg(vbuf->sgl, sg, vbuf->nents, i) {
+ dma_addr_t phys = sg_dma_address(sg);
+ len = sg_dma_len(sg);
+
+ while (len && buf_len) {
+
+ if (count == TW686X_MAX_SG_DESC_COUNT)
+ return -ENOMEM;
+
+ entry_len = min_t(unsigned int, len,
+ TW686X_MAX_SG_ENTRY_SIZE);
+ entry_len = min_t(unsigned int, entry_len, buf_len);
+ descs[count].phys = cpu_to_le32(phys);
+ descs[count++].flags_length =
+ cpu_to_le32(BIT(30) | entry_len);
+ phys += entry_len;
+ len -= entry_len;
+ buf_len -= entry_len;
+ }
+
+ if (!buf_len)
+ return 0;
+ }
+
+ return -ENOMEM;
+}
+
+static void tw686x_sg_buf_refill(struct tw686x_video_channel *vc,
+ unsigned int pb)
+{
+ struct tw686x_dev *dev = vc->dev;
+ struct tw686x_v4l2_buf *buf;
+
+ while (!list_empty(&vc->vidq_queued)) {
+ unsigned int buf_len;
+
+ buf = list_first_entry(&vc->vidq_queued,
+ struct tw686x_v4l2_buf, list);
+ list_del(&buf->list);
+
+ buf_len = (vc->width * vc->height * vc->format->depth) >> 3;
+ if (tw686x_sg_desc_fill(vc->sg_descs[pb], buf, buf_len)) {
+ v4l2_err(&dev->v4l2_dev,
+ "dma%d: unable to fill %s-buffer\n",
+ vc->ch, pb ? "B" : "P");
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ continue;
+ }
+
+ buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
+ vc->curr_bufs[pb] = buf;
+ return;
+ }
+
+ vc->curr_bufs[pb] = NULL;
+}
+
+static void tw686x_sg_dma_free(struct tw686x_video_channel *vc,
+ unsigned int pb)
+{
+ struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
+ struct tw686x_dev *dev = vc->dev;
+
+ if (desc->size) {
+ pci_free_consistent(dev->pci_dev, desc->size,
+ desc->virt, desc->phys);
+ desc->virt = NULL;
+ }
+
+ vc->sg_descs[pb] = NULL;
+}
+
+static int tw686x_sg_dma_alloc(struct tw686x_video_channel *vc,
+ unsigned int pb)
+{
+ struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
+ struct tw686x_dev *dev = vc->dev;
+ u32 reg = pb ? DMA_PAGE_TABLE1_ADDR[vc->ch] :
+ DMA_PAGE_TABLE0_ADDR[vc->ch];
+ void *virt;
+
+ if (desc->size) {
+
+ virt = pci_alloc_consistent(dev->pci_dev, desc->size,
+ &desc->phys);
+ if (!virt) {
+ v4l2_err(&dev->v4l2_dev,
+ "dma%d: unable to allocate %s-buffer\n",
+ vc->ch, pb ? "B" : "P");
+ return -ENOMEM;
+ }
+ desc->virt = virt;
+ reg_write(dev, reg, desc->phys);
} else {
- if (fps >= ARRAY_SIZE(std_625_50))
- fps = 25;
- i = std_625_50[fps];
+ virt = dev->video_channels[0].dma_descs[pb].virt +
+ vc->ch * TW686X_SG_TABLE_SIZE;
}
- return map[i];
+ vc->sg_descs[pb] = virt;
+ return 0;
+}
+
+static int tw686x_sg_setup(struct tw686x_dev *dev)
+{
+ unsigned int sg_table_size, pb, ch, channels;
+
+ if (is_second_gen(dev)) {
+ /*
+ * TW6865/TW6869: each channel needs a pair of
+ * P-B descriptor tables.
+ */
+ channels = max_channels(dev);
+ sg_table_size = TW686X_SG_TABLE_SIZE;
+ } else {
+ /*
+ * TW6864/TW6868: we need to allocate a pair of
+ * P-B descriptor tables, common for all channels.
+ * Each table will be bigger than 4 KB.
+ */
+ channels = 1;
+ sg_table_size = max_channels(dev) * TW686X_SG_TABLE_SIZE;
+ }
+
+ for (ch = 0; ch < channels; ch++) {
+ struct tw686x_video_channel *vc = &dev->video_channels[ch];
+
+ for (pb = 0; pb < 2; pb++)
+ vc->dma_descs[pb].size = sg_table_size;
+ }
+
+ return 0;
+}
+
+static const struct tw686x_dma_ops sg_dma_ops = {
+ .setup = tw686x_sg_setup,
+ .alloc = tw686x_sg_dma_alloc,
+ .free = tw686x_sg_dma_free,
+ .buf_refill = tw686x_sg_buf_refill,
+ .mem_ops = &vb2_dma_sg_memops,
+ .hw_dma_mode = TW686X_SG_MODE,
+ .field = V4L2_FIELD_SEQ_TB,
+};
+
+static const unsigned int fps_map[15] = {
+ /*
+ * bit 31 enables selecting the field control register
+ * bits 0-29 are a bitmask with fields that will be output.
+ * For NTSC (and PAL-M, PAL-60), all 30 bits are used.
+ * For other PAL standards, only the first 25 bits are used.
+ */
+ 0x00000000, /* output all fields */
+ 0x80000006, /* 2 fps (60Hz), 2 fps (50Hz) */
+ 0x80018006, /* 4 fps (60Hz), 4 fps (50Hz) */
+ 0x80618006, /* 6 fps (60Hz), 6 fps (50Hz) */
+ 0x81818186, /* 8 fps (60Hz), 8 fps (50Hz) */
+ 0x86186186, /* 10 fps (60Hz), 8 fps (50Hz) */
+ 0x86619866, /* 12 fps (60Hz), 10 fps (50Hz) */
+ 0x86666666, /* 14 fps (60Hz), 12 fps (50Hz) */
+ 0x9999999e, /* 16 fps (60Hz), 14 fps (50Hz) */
+ 0x99e6799e, /* 18 fps (60Hz), 16 fps (50Hz) */
+ 0x9e79e79e, /* 20 fps (60Hz), 16 fps (50Hz) */
+ 0x9e7e7e7e, /* 22 fps (60Hz), 18 fps (50Hz) */
+ 0x9fe7f9fe, /* 24 fps (60Hz), 20 fps (50Hz) */
+ 0x9ffe7ffe, /* 26 fps (60Hz), 22 fps (50Hz) */
+ 0x9ffffffe, /* 28 fps (60Hz), 24 fps (50Hz) */
+};
+
+static unsigned int tw686x_real_fps(unsigned int index, unsigned int max_fps)
+{
+ unsigned long mask;
+
+ if (!index || index >= ARRAY_SIZE(fps_map))
+ return max_fps;
+
+ mask = GENMASK(max_fps - 1, 0);
+ return hweight_long(fps_map[index] & mask);
+}
+
+static unsigned int tw686x_fps_idx(unsigned int fps, unsigned int max_fps)
+{
+ unsigned int idx, real_fps;
+ int delta;
+
+ /* First guess */
+ idx = (12 + 15 * fps) / max_fps;
+
+ /* Minimal possible framerate is 2 frames per second */
+ if (!idx)
+ return 1;
+
+ /* Check if the difference is bigger than abs(1) and adjust */
+ real_fps = tw686x_real_fps(idx, max_fps);
+ delta = real_fps - fps;
+ if (delta < -1)
+ idx++;
+ else if (delta > 1)
+ idx--;
+
+ /* Max framerate */
+ if (idx >= 15)
+ return 0;
+
+ return idx;
}
static void tw686x_set_framerate(struct tw686x_video_channel *vc,
unsigned int fps)
{
- unsigned int map;
-
- if (vc->fps == fps)
- return;
+ unsigned int i;
- map = tw686x_fields_map(vc->video_standard, fps) << 1;
- map |= map << 1;
- if (map > 0)
- map |= BIT(31);
- reg_write(vc->dev, VIDEO_FIELD_CTRL[vc->ch], map);
- vc->fps = fps;
+ i = tw686x_fps_idx(fps, TW686X_MAX_FPS(vc->video_standard));
+ reg_write(vc->dev, VIDEO_FIELD_CTRL[vc->ch], fps_map[i]);
+ vc->fps = tw686x_real_fps(i, TW686X_MAX_FPS(vc->video_standard));
}
static const struct tw686x_format *format_by_fourcc(unsigned int fourcc)
@@ -104,7 +425,7 @@ static const struct tw686x_format *format_by_fourcc(unsigned int fourcc)
static int tw686x_queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers, unsigned int *nplanes,
- unsigned int sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], struct device *alloc_devs[])
{
struct tw686x_video_channel *vc = vb2_get_drv_priv(vq);
unsigned int szimage =
@@ -152,75 +473,6 @@ static void tw686x_buf_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&vc->qlock, flags);
}
-/*
- * We can call this even when alloc_dma failed for the given channel
- */
-static void tw686x_free_dma(struct tw686x_video_channel *vc, unsigned int pb)
-{
- struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
- struct tw686x_dev *dev = vc->dev;
- struct pci_dev *pci_dev;
- unsigned long flags;
-
- /* Check device presence. Shouldn't really happen! */
- spin_lock_irqsave(&dev->lock, flags);
- pci_dev = dev->pci_dev;
- spin_unlock_irqrestore(&dev->lock, flags);
- if (!pci_dev) {
- WARN(1, "trying to deallocate on missing device\n");
- return;
- }
-
- if (desc->virt) {
- pci_free_consistent(dev->pci_dev, desc->size,
- desc->virt, desc->phys);
- desc->virt = NULL;
- }
-}
-
-static int tw686x_alloc_dma(struct tw686x_video_channel *vc, unsigned int pb)
-{
- struct tw686x_dev *dev = vc->dev;
- u32 reg = pb ? VDMA_B_ADDR[vc->ch] : VDMA_P_ADDR[vc->ch];
- unsigned int len;
- void *virt;
-
- WARN(vc->dma_descs[pb].virt,
- "Allocating buffer but previous still here\n");
-
- len = (vc->width * vc->height * vc->format->depth) >> 3;
- virt = pci_alloc_consistent(dev->pci_dev, len,
- &vc->dma_descs[pb].phys);
- if (!virt) {
- v4l2_err(&dev->v4l2_dev,
- "dma%d: unable to allocate %s-buffer\n",
- vc->ch, pb ? "B" : "P");
- return -ENOMEM;
- }
- vc->dma_descs[pb].size = len;
- vc->dma_descs[pb].virt = virt;
- reg_write(dev, reg, vc->dma_descs[pb].phys);
-
- return 0;
-}
-
-static void tw686x_buffer_refill(struct tw686x_video_channel *vc,
- unsigned int pb)
-{
- struct tw686x_v4l2_buf *buf;
-
- while (!list_empty(&vc->vidq_queued)) {
-
- buf = list_first_entry(&vc->vidq_queued,
- struct tw686x_v4l2_buf, list);
- list_del(&buf->list);
-
- vc->curr_bufs[pb] = buf;
- return;
- }
- vc->curr_bufs[pb] = NULL;
-}
-
static void tw686x_clear_queue(struct tw686x_video_channel *vc,
enum vb2_buffer_state state)
{
@@ -262,7 +514,8 @@ static int tw686x_start_streaming(struct vb2_queue *vq, unsigned int count)
spin_lock_irqsave(&vc->qlock, flags);
/* Sanity check */
- if (!vc->dma_descs[0].virt || !vc->dma_descs[1].virt) {
+ if (dev->dma_mode == TW686X_DMA_MODE_MEMCPY &&
+ (!vc->dma_descs[0].virt || !vc->dma_descs[1].virt)) {
spin_unlock_irqrestore(&vc->qlock, flags);
v4l2_err(&dev->v4l2_dev,
"video%d: refusing to start without DMA buffers\n",
@@ -272,7 +525,7 @@ static int tw686x_start_streaming(struct vb2_queue *vq, unsigned int count)
}
for (pb = 0; pb < 2; pb++)
- tw686x_buffer_refill(vc, pb);
+ dev->dma_ops->buf_refill(vc, pb);
spin_unlock_irqrestore(&vc->qlock, flags);
vc->sequence = 0;
@@ -375,10 +628,11 @@ static int tw686x_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct tw686x_video_channel *vc = video_drvdata(file);
+ struct tw686x_dev *dev = vc->dev;
f->fmt.pix.width = vc->width;
f->fmt.pix.height = vc->height;
- f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+ f->fmt.pix.field = dev->dma_ops->field;
f->fmt.pix.pixelformat = vc->format->fourcc;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.bytesperline = (f->fmt.pix.width * vc->format->depth) / 8;
@@ -390,6 +644,7 @@ static int tw686x_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct tw686x_video_channel *vc = video_drvdata(file);
+ struct tw686x_dev *dev = vc->dev;
unsigned int video_height = TW686X_VIDEO_HEIGHT(vc->video_standard);
const struct tw686x_format *format;
@@ -412,7 +667,7 @@ static int tw686x_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = (f->fmt.pix.width * format->depth) / 8;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+ f->fmt.pix.field = dev->dma_ops->field;
return 0;
}
@@ -421,6 +676,7 @@ static int tw686x_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct tw686x_video_channel *vc = video_drvdata(file);
+ struct tw686x_dev *dev = vc->dev;
u32 val, width, line_width, height;
unsigned long bitsperframe;
int err, pb;
@@ -438,15 +694,16 @@ static int tw686x_s_fmt_vid_cap(struct file *file, void *priv,
vc->height = f->fmt.pix.height;
/* We need new DMA buffers if the framesize has changed */
- if (bitsperframe != vc->width * vc->height * vc->format->depth) {
+ if (dev->dma_ops->alloc &&
+ bitsperframe != vc->width * vc->height * vc->format->depth) {
for (pb = 0; pb < 2; pb++)
- tw686x_free_dma(vc, pb);
+ dev->dma_ops->free(vc, pb);
for (pb = 0; pb < 2; pb++) {
- err = tw686x_alloc_dma(vc, pb);
+ err = dev->dma_ops->alloc(vc, pb);
if (err) {
if (pb > 0)
- tw686x_free_dma(vc, 0);
+ dev->dma_ops->free(vc, 0);
return err;
}
}
@@ -464,6 +721,19 @@ static int tw686x_s_fmt_vid_cap(struct file *file, void *priv,
else
val &= ~BIT(24);
+ val &= ~0x7ffff;
+
+ /* Program the DMA scatter-gather */
+ if (dev->dma_mode == TW686X_DMA_MODE_SG) {
+ u32 start_idx, end_idx;
+
+ start_idx = is_second_gen(dev) ?
+ 0 : vc->ch * TW686X_MAX_SG_DESC_COUNT;
+ end_idx = start_idx + TW686X_MAX_SG_DESC_COUNT - 1;
+
+ val |= (end_idx << 10) | start_idx;
+ }
+
val &= ~(0x7 << 20);
val |= vc->format->mode << 20;
reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], val);
@@ -540,6 +810,12 @@ static int tw686x_s_std(struct file *file, void *priv, v4l2_std_id id)
ret = tw686x_g_fmt_vid_cap(file, priv, &f);
if (!ret)
tw686x_s_fmt_vid_cap(file, priv, &f);
+
+ /*
+ * Frame decimation depends on the chosen standard,
+ * so reset it to the current value.
+ */
+ tw686x_set_framerate(vc, vc->fps);
return 0;
}
@@ -609,6 +885,40 @@ static int tw686x_g_std(struct file *file, void *priv, v4l2_std_id *id)
return 0;
}
+static int tw686x_g_parm(struct file *file, void *priv,
+ struct v4l2_streamparm *sp)
+{
+ struct tw686x_video_channel *vc = video_drvdata(file);
+ struct v4l2_captureparm *cp = &sp->parm.capture;
+
+ if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ sp->parm.capture.readbuffers = 3;
+
+ cp->capability = V4L2_CAP_TIMEPERFRAME;
+ cp->timeperframe.numerator = 1;
+ cp->timeperframe.denominator = vc->fps;
+ return 0;
+}
+
+static int tw686x_s_parm(struct file *file, void *priv,
+ struct v4l2_streamparm *sp)
+{
+ struct tw686x_video_channel *vc = video_drvdata(file);
+ struct v4l2_captureparm *cp = &sp->parm.capture;
+ unsigned int denominator = cp->timeperframe.denominator;
+ unsigned int numerator = cp->timeperframe.numerator;
+ unsigned int fps;
+
+ if (vb2_is_busy(&vc->vidq))
+ return -EBUSY;
+
+ fps = (!numerator || !denominator) ? 0 : denominator / numerator;
+ if (vc->fps != fps)
+ tw686x_set_framerate(vc, fps);
+ return tw686x_g_parm(file, priv, sp);
+}
+
static int tw686x_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
@@ -695,6 +1005,9 @@ static const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = {
.vidioc_g_std = tw686x_g_std,
.vidioc_s_std = tw686x_s_std,
+ .vidioc_g_parm = tw686x_g_parm,
+ .vidioc_s_parm = tw686x_s_parm,
+
.vidioc_enum_input = tw686x_enum_input,
.vidioc_g_input = tw686x_g_input,
.vidioc_s_input = tw686x_s_input,
@@ -713,26 +1026,11 @@ static const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = {
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
-static void tw686x_buffer_copy(struct tw686x_video_channel *vc,
- unsigned int pb, struct vb2_v4l2_buffer *vb)
-{
- struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
- struct vb2_buffer *vb2_buf = &vb->vb2_buf;
-
- vb->field = V4L2_FIELD_INTERLACED;
- vb->sequence = vc->sequence++;
-
- memcpy(vb2_plane_vaddr(vb2_buf, 0), desc->virt, desc->size);
- vb2_buf->timestamp = ktime_get_ns();
- vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE);
-}
-
void tw686x_video_irq(struct tw686x_dev *dev, unsigned long requests,
unsigned int pb_status, unsigned int fifo_status,
unsigned int *reset_ch)
{
struct tw686x_video_channel *vc;
- struct vb2_v4l2_buffer *vb;
unsigned long flags;
unsigned int ch, pb;
@@ -781,14 +1079,9 @@ void tw686x_video_irq(struct tw686x_dev *dev, unsigned long requests,
continue;
}
- /* handle video stream */
spin_lock_irqsave(&vc->qlock, flags);
- if (vc->curr_bufs[pb]) {
- vb = &vc->curr_bufs[pb]->vb;
- tw686x_buffer_copy(vc, pb, vb);
- }
- vc->pb = !pb;
- tw686x_buffer_refill(vc, pb);
+ tw686x_buf_done(vc, pb);
+ dev->dma_ops->buf_refill(vc, pb);
spin_unlock_irqrestore(&vc->qlock, flags);
}
}
@@ -803,8 +1096,9 @@ void tw686x_video_free(struct tw686x_dev *dev)
if (vc->device)
video_unregister_device(vc->device);
- for (pb = 0; pb < 2; pb++)
- tw686x_free_dma(vc, pb);
+ if (dev->dma_ops->free)
+ for (pb = 0; pb < 2; pb++)
+ dev->dma_ops->free(vc, pb);
}
}
@@ -813,10 +1107,25 @@ int tw686x_video_init(struct tw686x_dev *dev)
unsigned int ch, val, pb;
int err;
+ if (dev->dma_mode == TW686X_DMA_MODE_MEMCPY)
+ dev->dma_ops = &memcpy_dma_ops;
+ else if (dev->dma_mode == TW686X_DMA_MODE_CONTIG)
+ dev->dma_ops = &contig_dma_ops;
+ else if (dev->dma_mode == TW686X_DMA_MODE_SG)
+ dev->dma_ops = &sg_dma_ops;
+ else
+ return -EINVAL;
+
err = v4l2_device_register(&dev->pci_dev->dev, &dev->v4l2_dev);
if (err)
return err;
+ if (dev->dma_ops->setup) {
+ err = dev->dma_ops->setup(dev);
+ if (err)
+ return err;
+ }
+
for (ch = 0; ch < max_channels(dev); ch++) {
struct tw686x_video_channel *vc = &dev->video_channels[ch];
struct video_device *vdev;
@@ -842,10 +1151,12 @@ int tw686x_video_init(struct tw686x_dev *dev)
reg_write(dev, HACTIVE_LO[ch], 0xd0);
reg_write(dev, VIDEO_SIZE[ch], 0);
- for (pb = 0; pb < 2; pb++) {
- err = tw686x_alloc_dma(vc, pb);
- if (err)
- goto error;
+ if (dev->dma_ops->alloc) {
+ for (pb = 0; pb < 2; pb++) {
+ err = dev->dma_ops->alloc(vc, pb);
+ if (err)
+ goto error;
+ }
}
vc->vidq.io_modes = VB2_READ | VB2_MMAP | VB2_DMABUF;
@@ -853,11 +1164,12 @@ int tw686x_video_init(struct tw686x_dev *dev)
vc->vidq.drv_priv = vc;
vc->vidq.buf_struct_size = sizeof(struct tw686x_v4l2_buf);
vc->vidq.ops = &tw686x_video_qops;
- vc->vidq.mem_ops = &vb2_vmalloc_memops;
+ vc->vidq.mem_ops = dev->dma_ops->mem_ops;
vc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
vc->vidq.min_buffers_needed = 2;
vc->vidq.lock = &vc->vb_mutex;
vc->vidq.gfp_flags = GFP_DMA32;
+ vc->vidq.dev = &dev->pci_dev->dev;
err = vb2_queue_init(&vc->vidq);
if (err) {
@@ -915,10 +1227,9 @@ int tw686x_video_init(struct tw686x_dev *dev)
vc->num = vdev->num;
}
- /* Set DMA frame mode on all channels. Only supported mode for now. */
val = TW686X_DEF_PHASE_REF;
for (ch = 0; ch < max_channels(dev); ch++)
- val |= TW686X_FRAME_MODE << (16 + ch * 2);
+ val |= dev->dma_ops->hw_dma_mode << (16 + ch * 2);
reg_write(dev, PHASE_REF, val);
reg_write(dev, MISC2[0], 0xe7);
diff --git a/drivers/media/pci/tw686x/tw686x.h b/drivers/media/pci/tw686x/tw686x.h
index 44b5755..f24a2a9 100644
--- a/drivers/media/pci/tw686x/tw686x.h
+++ b/drivers/media/pci/tw686x/tw686x.h
@@ -27,16 +27,14 @@
#define TYPE_SECOND_GEN 0x10
#define TW686X_DEF_PHASE_REF 0x1518
-#define TW686X_FIELD_MODE 0x3
-#define TW686X_FRAME_MODE 0x2
-/* 0x1 is reserved */
-#define TW686X_SG_MODE 0x0
-
-#define TW686X_AUDIO_PAGE_SZ 4096
#define TW686X_AUDIO_PAGE_MAX 16
#define TW686X_AUDIO_PERIODS_MIN 2
#define TW686X_AUDIO_PERIODS_MAX TW686X_AUDIO_PAGE_MAX
+#define TW686X_DMA_MODE_MEMCPY 0
+#define TW686X_DMA_MODE_CONTIG 1
+#define TW686X_DMA_MODE_SG 2
+
struct tw686x_format {
char *name;
unsigned int fourcc;
@@ -50,6 +48,12 @@ struct tw686x_dma_desc {
unsigned int size;
};
+struct tw686x_sg_desc {
+ /* 3 MSBits for flags, 13 LSBits for length */
+ __le32 flags_length;
+ __le32 phys;
+};
+
struct tw686x_audio_buf {
dma_addr_t dma;
void *virt;
@@ -82,6 +86,7 @@ struct tw686x_video_channel {
struct video_device *device;
struct tw686x_v4l2_buf *curr_bufs[2];
struct tw686x_dma_desc dma_descs[2];
+ struct tw686x_sg_desc *sg_descs[2];
struct v4l2_ctrl_handler ctrl_handler;
const struct tw686x_format *format;
@@ -99,6 +104,16 @@ struct tw686x_video_channel {
bool no_signal;
};
+struct tw686x_dma_ops {
+ int (*setup)(struct tw686x_dev *dev);
+ int (*alloc)(struct tw686x_video_channel *vc, unsigned int pb);
+ void (*free)(struct tw686x_video_channel *vc, unsigned int pb);
+ void (*buf_refill)(struct tw686x_video_channel *vc, unsigned int pb);
+ const struct vb2_mem_ops *mem_ops;
+ enum v4l2_field field;
+ u32 hw_dma_mode;
+};
+
/**
* struct tw686x_dev - global device status
* @lock: spinlock controlling access to the
@@ -112,15 +127,18 @@ struct tw686x_dev {
char name[32];
unsigned int type;
+ unsigned int dma_mode;
struct pci_dev *pci_dev;
__u32 __iomem *mmio;
- void *alloc_ctx;
-
+ const struct tw686x_dma_ops *dma_ops;
struct tw686x_video_channel *video_channels;
struct tw686x_audio_channel *audio_channels;
- int audio_rate; /* per-device value */
+ /* Per-device audio parameters */
+ int audio_rate;
+ int period_size;
+ int audio_enabled;
struct timer_list dma_delay_timer;
u32 pending_dma_en; /* must be protected by lock */
@@ -143,6 +161,12 @@ static inline unsigned int max_channels(struct tw686x_dev *dev)
return dev->type & TYPE_MAX_CHANNELS; /* 4 or 8 channels */
}
+static inline unsigned is_second_gen(struct tw686x_dev *dev)
+{
+ /* each channel has its own DMA SG table */
+ return dev->type & TYPE_SECOND_GEN;
+}
+
void tw686x_enable_channel(struct tw686x_dev *dev, unsigned int channel);
void tw686x_disable_channel(struct tw686x_dev *dev, unsigned int channel);
diff --git a/drivers/media/pci/zoran/zr36016.c b/drivers/media/pci/zoran/zr36016.c
index b87ddba..c12ca9f 100644
--- a/drivers/media/pci/zoran/zr36016.c
+++ b/drivers/media/pci/zoran/zr36016.c
@@ -246,10 +246,6 @@ static int zr36016_pushit (struct zr36016 *ptr,
//TODO//
========================================================================= */
-// needed offset values PAL NTSC SECAM
-static const int zr016_xoff[] = { 20, 20, 20 };
-static const int zr016_yoff[] = { 8, 9, 7 };
-
static void
zr36016_init (struct zr36016 *ptr)
{
OpenPOWER on IntegriCloud