diff options
Diffstat (limited to 'drivers/media/pci')
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) { |