diff options
Diffstat (limited to 'drivers/media/pci')
56 files changed, 879 insertions, 937 deletions
diff --git a/drivers/media/pci/bt8xx/Makefile b/drivers/media/pci/bt8xx/Makefile index 5f06597c6a6..f9fe7c4e7d5 100644 --- a/drivers/media/pci/bt8xx/Makefile +++ b/drivers/media/pci/bt8xx/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/common ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 45e5d0661b6..ccd18e4ee78 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -3835,7 +3835,7 @@ bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup, { struct timeval ts; - do_gettimeofday(&ts); + v4l2_get_timestamp(&ts); if (wakeup->top == wakeup->bottom) { if (NULL != wakeup->top && curr->top != wakeup->top) { @@ -3878,7 +3878,7 @@ bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup, if (NULL == wakeup) return; - do_gettimeofday(&ts); + v4l2_get_timestamp(&ts); wakeup->vb.ts = ts; wakeup->vb.field_count = btv->field_count; wakeup->vb.state = state; @@ -3949,7 +3949,7 @@ bttv_irq_wakeup_top(struct bttv *btv) btv->curr.top = NULL; bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); - do_gettimeofday(&wakeup->vb.ts); + v4l2_get_timestamp(&wakeup->vb.ts); wakeup->vb.field_count = btv->field_count; wakeup->vb.state = VIDEOBUF_DONE; wake_up(&wakeup->vb.done); diff --git a/drivers/media/pci/bt8xx/bttv-i2c.c b/drivers/media/pci/bt8xx/bttv-i2c.c index 5039b8826e0..c63c643ed1f 100644 --- a/drivers/media/pci/bt8xx/bttv-i2c.c +++ b/drivers/media/pci/bt8xx/bttv-i2c.c @@ -173,7 +173,7 @@ bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last) if (i2c_debug) pr_cont(" %02x", msg->buf[cnt]); } - if (!(xmit & BT878_I2C_NOSTOP)) + if (i2c_debug && !(xmit & BT878_I2C_NOSTOP)) pr_cont(">\n"); return msg->len; @@ -366,8 +366,7 @@ int init_bttv_i2c(struct bttv *btv) strlcpy(btv->c.i2c_adap.name, "bttv", sizeof(btv->c.i2c_adap.name)); - memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template, - sizeof(bttv_i2c_algo_bit_template)); + btv->i2c_algo = bttv_i2c_algo_bit_template; btv->i2c_algo.udelay = i2c_udelay; btv->i2c_algo.data = btv; btv->c.i2c_adap.algo_data = &btv->i2c_algo; diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c index 7d96fab7d24..0e788fca992 100644 --- a/drivers/media/pci/bt8xx/dst_ca.c +++ b/drivers/media/pci/bt8xx/dst_ca.c @@ -180,11 +180,11 @@ static int ca_get_app_info(struct dst_state *state) put_command_and_length(&state->messages[0], CA_APP_INFO, length); // Copy application_type, application_manufacturer and manufacturer_code - memcpy(&state->messages[4], &state->messages[7], 5); + memmove(&state->messages[4], &state->messages[7], 5); // Set string length and copy string state->messages[9] = str_length; - memcpy(&state->messages[10], &state->messages[12], str_length); + memmove(&state->messages[10], &state->messages[12], str_length); return 0; } diff --git a/drivers/media/pci/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c index 8e971ff6058..b2c8c3439fe 100644 --- a/drivers/media/pci/cx18/cx18-alsa-main.c +++ b/drivers/media/pci/cx18/cx18-alsa-main.c @@ -197,7 +197,7 @@ err_exit: return ret; } -static int __init cx18_alsa_load(struct cx18 *cx) +static int cx18_alsa_load(struct cx18 *cx) { struct v4l2_device *v4l2_dev = &cx->v4l2_dev; struct cx18_stream *s; diff --git a/drivers/media/pci/cx18/cx18-alsa-pcm.h b/drivers/media/pci/cx18/cx18-alsa-pcm.h index d26e51f9457..e2b2c5b0121 100644 --- a/drivers/media/pci/cx18/cx18-alsa-pcm.h +++ b/drivers/media/pci/cx18/cx18-alsa-pcm.h @@ -20,7 +20,7 @@ * 02111-1307 USA */ -int __init snd_cx18_pcm_create(struct snd_cx18_card *cxsc); +int snd_cx18_pcm_create(struct snd_cx18_card *cxsc); /* Used by cx18-mailbox to announce the PCM data to the module */ void cx18_alsa_announce_pcm_data(struct snd_cx18_card *card, u8 *pcm_data, diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c index 4908eb7bcf6..4af8cd6df95 100644 --- a/drivers/media/pci/cx18/cx18-i2c.c +++ b/drivers/media/pci/cx18/cx18-i2c.c @@ -116,9 +116,6 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) const char *type = hw_devicenames[idx]; u32 hw = 1 << idx; - if (idx >= ARRAY_SIZE(hw_addrs)) - return -1; - if (hw == CX18_HW_TUNER) { /* special tuner group handling */ sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, @@ -240,15 +237,13 @@ int init_cx18_i2c(struct cx18 *cx) for (i = 0; i < 2; i++) { /* Setup algorithm for adapter */ - memcpy(&cx->i2c_algo[i], &cx18_i2c_algo_template, - sizeof(struct i2c_algo_bit_data)); + cx->i2c_algo[i] = cx18_i2c_algo_template; cx->i2c_algo_cb_data[i].cx = cx; cx->i2c_algo_cb_data[i].bus_index = i; cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i]; /* Setup adapter */ - memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template, - sizeof(struct i2c_adapter)); + cx->i2c_adap[i] = cx18_i2c_adap_template; cx->i2c_adap[i].algo_data = &cx->i2c_algo[i]; sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name), " #%d-%d", cx->instance, i); diff --git a/drivers/media/pci/cx18/cx18-vbi.c b/drivers/media/pci/cx18/cx18-vbi.c index 6d3121ff45a..add99642f1e 100644 --- a/drivers/media/pci/cx18/cx18-vbi.c +++ b/drivers/media/pci/cx18/cx18-vbi.c @@ -84,7 +84,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) (the max size of the VBI data is 36 * 43 + 4 bytes). So in this case we use the magic number 'ITV0'. */ memcpy(dst + sd, "ITV0", 4); - memcpy(dst + sd + 4, dst + sd + 12, line * 43); + memmove(dst + sd + 4, dst + sd + 12, line * 43); size = 4 + ((43 * line + 3) & ~3); } else { memcpy(dst + sd, "itv0", 4); diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig index eafa1144b17..b3688aa8acc 100644 --- a/drivers/media/pci/cx23885/Kconfig +++ b/drivers/media/pci/cx23885/Kconfig @@ -25,7 +25,10 @@ config VIDEO_CX23885 select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT + select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/pci/cx23885/Makefile b/drivers/media/pci/cx23885/Makefile index a2cbdcf15a8..2a2cafb8cf5 100644 --- a/drivers/media/pci/cx23885/Makefile +++ b/drivers/media/pci/cx23885/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_CX23885) += cx23885.o obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/common ccflags-y += -Idrivers/media/tuners ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 6277e145f0b..7e923f8dd2f 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -572,6 +572,39 @@ struct cx23885_board cx23885_boards[] = { [CX23885_BOARD_PROF_8000] = { .name = "Prof Revolution DVB-S2 8000", .portb = CX23885_MPEG_DVB, + }, + [CX23885_BOARD_HAUPPAUGE_HVR4400] = { + .name = "Hauppauge WinTV-HVR4400", + .portb = CX23885_MPEG_DVB, + }, + [CX23885_BOARD_AVERMEDIA_HC81R] = { + .name = "AVerTV Hybrid Express Slim HC81R", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, /* 0xc2 >> 1 */ + .tuner_bus = 1, + .porta = CX23885_ANALOG_VIDEO, + .input = {{ + .type = CX23885_VMUX_TELEVISION, + .vmux = CX25840_VIN2_CH1 | + CX25840_VIN5_CH2 | + CX25840_NONE0_CH3 | + CX25840_NONE1_CH3, + .amux = CX25840_AUDIO8, + }, { + .type = CX23885_VMUX_SVIDEO, + .vmux = CX25840_VIN8_CH1 | + CX25840_NONE_CH2 | + CX25840_VIN7_CH3 | + CX25840_SVIDEO_ON, + .amux = CX25840_AUDIO6, + }, { + .type = CX23885_VMUX_COMPONENT, + .vmux = CX25840_VIN1_CH1 | + CX25840_NONE_CH2 | + CX25840_NONE0_CH3 | + CX25840_NONE1_CH3, + .amux = CX25840_AUDIO6, + } }, } }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -788,6 +821,26 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x8000, .subdevice = 0x3034, .card = CX23885_BOARD_PROF_8000, + }, { + .subvendor = 0x0070, + .subdevice = 0xc108, + .card = CX23885_BOARD_HAUPPAUGE_HVR4400, + }, { + .subvendor = 0x0070, + .subdevice = 0xc138, + .card = CX23885_BOARD_HAUPPAUGE_HVR4400, + }, { + .subvendor = 0x0070, + .subdevice = 0xc12a, + .card = CX23885_BOARD_HAUPPAUGE_HVR4400, + }, { + .subvendor = 0x0070, + .subdevice = 0xc1f8, + .card = CX23885_BOARD_HAUPPAUGE_HVR4400, + }, { + .subvendor = 0x1461, + .subdevice = 0xd939, + .card = CX23885_BOARD_AVERMEDIA_HC81R, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -1012,6 +1065,10 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg) case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: altera_ci_tuner_reset(dev, port->nr); break; + case CX23885_BOARD_AVERMEDIA_HC81R: + /* XC3028L Reset Command */ + bitmask = 1 << 2; + break; } if (bitmask) { @@ -1301,6 +1358,42 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* enable irq */ cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ break; + case CX23885_BOARD_HAUPPAUGE_HVR4400: + /* GPIO-8 tda10071 demod reset */ + + /* Put the parts into reset and back */ + cx23885_gpio_enable(dev, GPIO_8, 1); + cx23885_gpio_clear(dev, GPIO_8); + mdelay(100); + cx23885_gpio_set(dev, GPIO_8); + mdelay(100); + break; + case CX23885_BOARD_AVERMEDIA_HC81R: + cx_clear(MC417_CTL, 1); + /* GPIO-0,1,2 setup direction as output */ + cx_set(GP0_IO, 0x00070000); + mdelay(10); + /* AF9013 demod reset */ + cx_set(GP0_IO, 0x00010001); + mdelay(10); + cx_clear(GP0_IO, 0x00010001); + mdelay(10); + cx_set(GP0_IO, 0x00010001); + mdelay(10); + /* demod tune? */ + cx_clear(GP0_IO, 0x00030003); + mdelay(10); + cx_set(GP0_IO, 0x00020002); + mdelay(10); + cx_set(GP0_IO, 0x00010001); + mdelay(10); + cx_clear(GP0_IO, 0x00020002); + /* XC3028L tuner reset */ + cx_set(GP0_IO, 0x00040004); + cx_clear(GP0_IO, 0x00040004); + cx_set(GP0_IO, 0x00040004); + mdelay(60); + break; } } @@ -1378,6 +1471,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) break; case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_MYGICA_X8507: if (!enable_885_ir) break; dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE); @@ -1420,6 +1514,7 @@ void cx23885_ir_fini(struct cx23885_dev *dev) case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_HAUPPAUGE_HVR1250: + case CX23885_BOARD_MYGICA_X8507: cx23885_irq_remove(dev, PCI_MSK_AV_CORE); /* sd_ir is a duplicate pointer to the AV Core, just clear it */ dev->sd_ir = NULL; @@ -1464,6 +1559,7 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev) case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_HAUPPAUGE_HVR1250: + case CX23885_BOARD_MYGICA_X8507: if (dev->sd_ir) cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE); break; @@ -1509,12 +1605,24 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1210: case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: + case CX23885_BOARD_HAUPPAUGE_HVR4400: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; } switch (dev->board) { + case CX23885_BOARD_AVERMEDIA_HC81R: + /* Defaults for VID B */ + ts1->gen_ctrl_val = 0x4; /* Parallel */ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + /* Defaults for VID C */ + /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */ + ts2->gen_ctrl_val = 0x10e; + ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ @@ -1581,6 +1689,11 @@ 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_HVR4400: + 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; + break; case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: @@ -1636,6 +1749,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_MPX885: case CX23885_BOARD_MYGICA_X8507: case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: + case CX23885_BOARD_AVERMEDIA_HC81R: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, "cx25840", 0x88 >> 1, NULL); diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index f0416a668b4..268654ac9a9 100644 --- a/drivers/media/pci/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c @@ -439,7 +439,7 @@ void cx23885_wakeup(struct cx23885_tsport *port, if ((s16) (count - buf->count) < 0) break; - do_gettimeofday(&buf->vb.ts); + v4l2_get_timestamp(&buf->vb.ts); dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i, count, buf->count); buf->vb.state = VIDEOBUF_DONE; diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 2f5b902e63a..9c5ed10b2c5 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -57,6 +57,7 @@ #include "netup-init.h" #include "lgdt3305.h" #include "atbm8830.h" +#include "ts2020.h" #include "ds3000.h" #include "cx23885-f300.h" #include "altera-ci.h" @@ -66,6 +67,8 @@ #include "stv090x.h" #include "stb6100.h" #include "stb6100_cfg.h" +#include "tda10071.h" +#include "a8293.h" static unsigned int debug; @@ -469,6 +472,11 @@ static struct ds3000_config tevii_ds3000_config = { .demod_address = 0x68, }; +static struct ts2020_config tevii_ts2020_config = { + .tuner_address = 0x60, + .clk_out_div = 1, +}; + static struct cx24116_config dvbworld_cx24116_config = { .demod_address = 0x05, }; @@ -493,20 +501,20 @@ static struct xc5000_config mygica_x8506_xc5000_config = { }; static struct stv090x_config prof_8000_stv090x_config = { - .device = STV0903, - .demod_mode = STV090x_SINGLE, - .clk_mode = STV090x_CLK_EXT, - .xtal = 27000000, - .address = 0x6A, - .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, - .repeater_level = STV090x_RPTLEVEL_64, - .adc1_range = STV090x_ADC_2Vpp, - .diseqc_envelope_mode = false, - - .tuner_get_frequency = stb6100_get_frequency, - .tuner_set_frequency = stb6100_set_frequency, - .tuner_set_bandwidth = stb6100_set_bandwidth, - .tuner_get_bandwidth = stb6100_get_bandwidth, + .device = STV0903, + .demod_mode = STV090x_SINGLE, + .clk_mode = STV090x_CLK_EXT, + .xtal = 27000000, + .address = 0x6A, + .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, + .repeater_level = STV090x_RPTLEVEL_64, + .adc1_range = STV090x_ADC_2Vpp, + .diseqc_envelope_mode = false, + + .tuner_get_frequency = stb6100_get_frequency, + .tuner_set_frequency = stb6100_set_frequency, + .tuner_set_bandwidth = stb6100_set_bandwidth, + .tuner_get_bandwidth = stb6100_get_bandwidth, }; static struct stb6100_config prof_8000_stb6100_config = { @@ -659,6 +667,20 @@ static struct mt2063_config terratec_mt2063_config[] = { }, }; +static const struct tda10071_config hauppauge_tda10071_config = { + .demod_i2c_addr = 0x05, + .tuner_i2c_addr = 0x54, + .i2c_wr_max = 64, + .ts_mode = TDA10071_TS_SERIAL, + .spec_inv = 0, + .xtal = 40444000, /* 40.444 MHz */ + .pll_multiplier = 20, +}; + +static const struct a8293_config hauppauge_a8293_config = { + .i2c_addr = 0x0b, +}; + static int netup_altera_fpga_rw(void *device, int flag, int data, int read) { struct cx23885_dev *dev = (struct cx23885_dev *)device; @@ -1011,8 +1033,11 @@ static int dvb_register(struct cx23885_tsport *port) fe0->dvb.frontend = dvb_attach(ds3000_attach, &tevii_ds3000_config, &i2c_bus->i2c_adap); - if (fe0->dvb.frontend != NULL) + if (fe0->dvb.frontend != NULL) { + dvb_attach(ts2020_attach, fe0->dvb.frontend, + &tevii_ts2020_config, &i2c_bus->i2c_adap); fe0->dvb.frontend->ops.set_voltage = f300_set_voltage; + } break; case CX23885_BOARD_DVBWORLD_2005: @@ -1242,6 +1267,17 @@ static int dvb_register(struct cx23885_tsport *port) fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage; } break; + case CX23885_BOARD_HAUPPAUGE_HVR4400: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(tda10071_attach, + &hauppauge_tda10071_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(a8293_attach, fe0->dvb.frontend, + &i2c_bus->i2c_adap, + &hauppauge_a8293_config); + } + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c index 4f1055a194b..7875dfbe09f 100644 --- a/drivers/media/pci/cx23885/cx23885-input.c +++ b/drivers/media/pci/cx23885/cx23885-input.c @@ -89,6 +89,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_HAUPPAUGE_HVR1250: + case CX23885_BOARD_MYGICA_X8507: /* * The only boards we handle right now. However other boards * using the CX2388x integrated IR controller should be similar @@ -140,6 +141,7 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: case CX23885_BOARD_HAUPPAUGE_HVR1250: + case CX23885_BOARD_MYGICA_X8507: /* * The IR controller on this board only returns pulse widths. * Any other mode setting will fail to set up the device. @@ -289,6 +291,13 @@ int cx23885_input_init(struct cx23885_dev *dev) /* A guess at the remote */ rc_map = RC_MAP_TEVII_NEC; break; + case CX23885_BOARD_MYGICA_X8507: + /* Integrated CX23885 IR controller */ + driver_type = RC_DRIVER_IR_RAW; + allowed_protos = RC_BIT_ALL; + /* A guess at the remote */ + rc_map = RC_MAP_TOTAL_MEDIA_IN_HAND_02; + break; default: return -ENODEV; } diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index 1a21926ca41..5991bc8dc15 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c @@ -300,7 +300,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev, if ((s16) (count - buf->count) < 0) break; - do_gettimeofday(&buf->vb.ts); + v4l2_get_timestamp(&buf->vb.ts); dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i, count, buf->count); buf->vb.state = VIDEOBUF_DONE; @@ -509,7 +509,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) || (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) || (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) || - (dev->board == CX23885_BOARD_MYGICA_X8507)) { + (dev->board == CX23885_BOARD_MYGICA_X8507) || + (dev->board == CX23885_BOARD_AVERMEDIA_HC81R)) { /* Configure audio routing */ v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, INPUT(input)->amux, 0, 0); @@ -1818,8 +1819,7 @@ int cx23885_video_register(struct cx23885_dev *dev) spin_lock_init(&dev->slock); /* Initialize VBI template */ - memcpy(&cx23885_vbi_template, &cx23885_video_template, - sizeof(cx23885_vbi_template)); + cx23885_vbi_template = cx23885_video_template; strcpy(cx23885_vbi_template.name, "cx23885-vbi"); dev->tvnorm = cx23885_video_template.current_norm; @@ -1878,6 +1878,18 @@ int cx23885_video_register(struct cx23885_dev *dev) }; v4l2_subdev_call(sd, tuner, s_config, &cfg); } + + if (dev->board == CX23885_BOARD_AVERMEDIA_HC81R) { + struct xc2028_ctrl ctrl = { + .fname = "xc3028L-v36.fw", + .max_len = 64 + }; + struct v4l2_priv_tun_config cfg = { + .tuner = dev->tuner_type, + .priv = &ctrl + }; + v4l2_subdev_call(sd, tuner, s_config, &cfg); + } } } diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h index 67f40d31450..59c322d870f 100644 --- a/drivers/media/pci/cx23885/cx23885.h +++ b/drivers/media/pci/cx23885/cx23885.h @@ -91,6 +91,8 @@ #define CX23885_BOARD_TEVII_S471 35 #define CX23885_BOARD_HAUPPAUGE_HVR1255_22111 36 #define CX23885_BOARD_PROF_8000 37 +#define CX23885_BOARD_HAUPPAUGE_HVR4400 38 +#define CX23885_BOARD_AVERMEDIA_HC81R 39 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c index c4bd1e95d33..d51eed051d5 100644 --- a/drivers/media/pci/cx23885/cx23888-ir.c +++ b/drivers/media/pci/cx23885/cx23888-ir.c @@ -1237,13 +1237,11 @@ int cx23888_ir_probe(struct cx23885_dev *dev) cx23888_ir_write4(dev, CX23888_IR_IRQEN_REG, 0); mutex_init(&state->rx_params_lock); - memcpy(&default_params, &default_rx_params, - sizeof(struct v4l2_subdev_ir_parameters)); + default_params = default_rx_params; v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params); mutex_init(&state->tx_params_lock); - memcpy(&default_params, &default_tx_params, - sizeof(struct v4l2_subdev_ir_parameters)); + default_params = default_tx_params; v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params); } else { kfifo_free(&state->rx_kfifo); diff --git a/drivers/media/pci/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig index 5f6b5421371..4017c942034 100644 --- a/drivers/media/pci/cx25821/Kconfig +++ b/drivers/media/pci/cx25821/Kconfig @@ -18,7 +18,7 @@ config VIDEO_CX25821 config VIDEO_CX25821_ALSA tristate "Conexant 25821 DMA audio support" - depends on VIDEO_CX25821 && SND && EXPERIMENTAL + depends on VIDEO_CX25821 && SND select SND_PCM ---help--- This is a video4linux driver for direct (DMA) audio on diff --git a/drivers/media/pci/cx25821/Makefile b/drivers/media/pci/cx25821/Makefile index 5bf3ea4c155..caa32b7b51f 100644 --- a/drivers/media/pci/cx25821/Makefile +++ b/drivers/media/pci/cx25821/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_CX25821) += cx25821.o obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/common ccflags-y += -Idrivers/media/tuners ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index 53b16dd7032..d4de021dc84 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -130,7 +130,7 @@ void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, if ((s16) (count - buf->count) < 0) break; - do_gettimeofday(&buf->vb.ts); + v4l2_get_timestamp(&buf->vb.ts); buf->vb.state = VIDEOBUF_DONE; list_del(&buf->vb.queue); wake_up(&buf->vb.done); diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig index d27fccbf03c..bb05eca2da2 100644 --- a/drivers/media/pci/cx88/Kconfig +++ b/drivers/media/pci/cx88/Kconfig @@ -62,6 +62,8 @@ config VIDEO_CX88_DVB select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT + select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT ---help--- This adds support for DVB/ATSC cards based on the diff --git a/drivers/media/pci/cx88/Makefile b/drivers/media/pci/cx88/Makefile index d3679c3ee24..8619c1becee 100644 --- a/drivers/media/pci/cx88/Makefile +++ b/drivers/media/pci/cx88/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/common ccflags-y += -Idrivers/media/tuners ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c index 0c255248cbc..e2e0b8faf7a 100644 --- a/drivers/media/pci/cx88/cx88-cards.c +++ b/drivers/media/pci/cx88/cx88-cards.c @@ -3743,7 +3743,7 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) cx88_card_list(core, pci); } - memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board)); + core->board = cx88_boards[core->boardnr]; if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB)) core->board.num_frontends = 1; diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c index 19a58754c6e..39f095c37ff 100644 --- a/drivers/media/pci/cx88/cx88-core.c +++ b/drivers/media/pci/cx88/cx88-core.c @@ -549,7 +549,7 @@ void cx88_wakeup(struct cx88_core *core, * up to 32767 buffers in flight... */ if ((s16) (count - buf->count) < 0) break; - do_gettimeofday(&buf->vb.ts); + v4l2_get_timestamp(&buf->vb.ts); dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i, count, buf->count); buf->vb.state = VIDEOBUF_DONE; diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index 666f83b2f3c..672b267a2d3 100644 --- a/drivers/media/pci/cx88/cx88-dvb.c +++ b/drivers/media/pci/cx88/cx88-dvb.c @@ -58,6 +58,7 @@ #include "stb6100.h" #include "stb6100_proc.h" #include "mb86a16.h" +#include "ts2020.h" #include "ds3000.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); @@ -264,7 +265,7 @@ static struct mb86a16_config twinhan_vp1027 = { .demod_address = 0x08, }; -#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054) static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) { static const u8 clock_config [] = { 0x89, 0x38, 0x38 }; @@ -700,6 +701,11 @@ static struct ds3000_config tevii_ds3000_config = { .set_ts_params = ds3000_set_ts_param, }; +static struct ts2020_config tevii_ts2020_config = { + .tuner_address = 0x60, + .clk_out_div = 1, +}; + static const struct stv0900_config prof_7301_stv0900_config = { .demod_address = 0x6a, /* demod_mode = 0,*/ @@ -1121,7 +1127,7 @@ static int dvb_register(struct cx8802_dev *dev) } break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: -#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054) /* MT352 is on a secondary I2C bus made from some GPIO lines */ fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &dev->vp3054->adap); @@ -1466,9 +1472,12 @@ static int dvb_register(struct cx8802_dev *dev) fe0->dvb.frontend = dvb_attach(ds3000_attach, &tevii_ds3000_config, &core->i2c_adap); - if (fe0->dvb.frontend != NULL) + if (fe0->dvb.frontend != NULL) { + dvb_attach(ts2020_attach, fe0->dvb.frontend, + &tevii_ts2020_config, &core->i2c_adap); fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + } break; case CX88_BOARD_OMICOM_SS4_PCI: case CX88_BOARD_TBS_8920: diff --git a/drivers/media/pci/cx88/cx88-i2c.c b/drivers/media/pci/cx88/cx88-i2c.c index de0f1af74e4..cf2d6961583 100644 --- a/drivers/media/pci/cx88/cx88-i2c.c +++ b/drivers/media/pci/cx88/cx88-i2c.c @@ -139,8 +139,7 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) if (i2c_udelay<5) i2c_udelay=5; - memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, - sizeof(core->i2c_algo)); + core->i2c_algo = cx8800_i2c_algo_template; core->i2c_adap.dev.parent = &pci->dev; diff --git a/drivers/media/pci/cx88/cx88-vp3054-i2c.c b/drivers/media/pci/cx88/cx88-vp3054-i2c.c index d77f8ecab9d..deede6e25d9 100644 --- a/drivers/media/pci/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/pci/cx88/cx88-vp3054-i2c.c @@ -118,8 +118,7 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) return -ENOMEM; dev->vp3054 = vp3054_i2c; - memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template, - sizeof(vp3054_i2c->algo)); + vp3054_i2c->algo = vp3054_i2c_algo_template; vp3054_i2c->adap.dev.parent = &dev->pci->dev; strlcpy(vp3054_i2c->adap.name, core->name, diff --git a/drivers/media/pci/cx88/cx88-vp3054-i2c.h b/drivers/media/pci/cx88/cx88-vp3054-i2c.h index be99c931dc3..95d0c60a35e 100644 --- a/drivers/media/pci/cx88/cx88-vp3054-i2c.h +++ b/drivers/media/pci/cx88/cx88-vp3054-i2c.h @@ -30,7 +30,7 @@ struct vp3054_i2c_state { }; /* ----------------------------------------------------------------------- */ -#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054) int vp3054_i2c_probe(struct cx8802_dev *dev); void vp3054_i2c_remove(struct cx8802_dev *dev); #else diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index ba0dba4a4d2..feff53c0a25 100644 --- a/drivers/media/pci/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h @@ -363,7 +363,7 @@ struct cx88_core { unsigned int tuner_formats; /* config info -- dvb */ -#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) +#if IS_ENABLED(CONFIG_VIDEO_CX88_DVB) int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); #endif void (*gate_ctrl)(struct cx88_core *core, int open); @@ -562,8 +562,7 @@ struct cx8802_dev { /* for blackbird only */ struct list_head devlist; -#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \ - defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE) +#if IS_ENABLED(CONFIG_VIDEO_CX88_BLACKBIRD) struct video_device *mpeg_dev; u32 mailbox; int width; @@ -574,13 +573,12 @@ struct cx8802_dev { struct cx2341x_handler cxhdl; #endif -#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) +#if IS_ENABLED(CONFIG_VIDEO_CX88_DVB) /* for dvb only */ struct videobuf_dvb_frontends frontends; #endif -#if defined(CONFIG_VIDEO_CX88_VP3054) || \ - defined(CONFIG_VIDEO_CX88_VP3054_MODULE) +#if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054) /* For VP3045 secondary I2C bus support */ struct vp3054_i2c_state *vp3054; #endif diff --git a/drivers/media/pci/dm1105/Kconfig b/drivers/media/pci/dm1105/Kconfig index 013df4e015c..173daf0c084 100644 --- a/drivers/media/pci/dm1105/Kconfig +++ b/drivers/media/pci/dm1105/Kconfig @@ -8,6 +8,7 @@ config DVB_DM1105 select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT select DVB_SI21XX if MEDIA_SUBDRV_AUTOSELECT select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT depends on RC_CORE help Support for cards based on the SDMC DM1105 PCI chip like diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c index 904c3ea350f..026767bed5c 100644 --- a/drivers/media/pci/dm1105/dm1105.c +++ b/drivers/media/pci/dm1105/dm1105.c @@ -45,6 +45,7 @@ #include "si21xx.h" #include "cx24116.h" #include "z0194a.h" +#include "ts2020.h" #include "ds3000.h" #define MODULE_NAME "dm1105" @@ -849,6 +850,11 @@ static struct ds3000_config dvbworld_ds3000_config = { .demod_address = 0x68, }; +static struct ts2020_config dvbworld_ts2020_config = { + .tuner_address = 0x60, + .clk_out_div = 1, +}; + static int frontend_init(struct dm1105_dev *dev) { int ret; @@ -898,8 +904,11 @@ static int frontend_init(struct dm1105_dev *dev) dev->fe = dvb_attach( ds3000_attach, &dvbworld_ds3000_config, &dev->i2c_adap); - if (dev->fe) + if (dev->fe) { + dvb_attach(ts2020_attach, dev->fe, + &dvbworld_ts2020_config, &dev->i2c_adap); dev->fe->ops.set_voltage = dm1105_set_voltage; + } break; case DM1105_BOARD_DVBWORLD_2002: diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c index 4a221c69399..e970cface70 100644 --- a/drivers/media/pci/ivtv/ivtv-alsa-main.c +++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c @@ -205,7 +205,7 @@ err_exit: return ret; } -static int __init ivtv_alsa_load(struct ivtv *itv) +static int ivtv_alsa_load(struct ivtv *itv) { struct v4l2_device *v4l2_dev = &itv->v4l2_dev; struct ivtv_stream *s; diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.h b/drivers/media/pci/ivtv/ivtv-alsa-pcm.h index 23dfe0d1240..186814e0b2d 100644 --- a/drivers/media/pci/ivtv/ivtv-alsa-pcm.h +++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.h @@ -20,4 +20,4 @@ * 02111-1307 USA */ -int __init snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc); +int snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc); diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index df88dc4ab55..2928e7287da 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -304,7 +304,7 @@ static void request_modules(struct ivtv *dev) static void flush_request_modules(struct ivtv *dev) { - flush_work_sync(&dev->request_module_wk); + flush_work(&dev->request_module_wk); } #else #define request_modules(dev) diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c index 46e262becb6..ceed2d87abf 100644 --- a/drivers/media/pci/ivtv/ivtv-i2c.c +++ b/drivers/media/pci/ivtv/ivtv-i2c.c @@ -267,8 +267,6 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) const char *type = hw_devicenames[idx]; u32 hw = 1 << idx; - if (idx >= ARRAY_SIZE(hw_addrs)) - return -1; if (hw == IVTV_HW_TUNER) { /* special tuner handling */ sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0, @@ -719,13 +717,10 @@ int init_ivtv_i2c(struct ivtv *itv) return -ENODEV; } if (itv->options.newi2c > 0) { - memcpy(&itv->i2c_adap, &ivtv_i2c_adap_hw_template, - sizeof(struct i2c_adapter)); + itv->i2c_adap = ivtv_i2c_adap_hw_template; } else { - memcpy(&itv->i2c_adap, &ivtv_i2c_adap_template, - sizeof(struct i2c_adapter)); - memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template, - sizeof(struct i2c_algo_bit_data)); + itv->i2c_adap = ivtv_i2c_adap_template; + itv->i2c_algo = ivtv_i2c_algo_template; } itv->i2c_algo.udelay = itv->options.i2c_clock_period / 2; itv->i2c_algo.data = itv; @@ -735,8 +730,7 @@ int init_ivtv_i2c(struct ivtv *itv) itv->instance); i2c_set_adapdata(&itv->i2c_adap, &itv->v4l2_dev); - memcpy(&itv->i2c_client, &ivtv_i2c_client_template, - sizeof(struct i2c_client)); + itv->i2c_client = ivtv_i2c_client_template; itv->i2c_client.adapter = &itv->i2c_adap; itv->i2c_adap.dev.parent = &itv->pdev->dev; diff --git a/drivers/media/pci/ivtv/ivtv-vbi.c b/drivers/media/pci/ivtv/ivtv-vbi.c index 293db806d93..3c156bc70fb 100644 --- a/drivers/media/pci/ivtv/ivtv-vbi.c +++ b/drivers/media/pci/ivtv/ivtv-vbi.c @@ -224,7 +224,7 @@ static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) (the max size of the VBI data is 36 * 43 + 4 bytes). So in this case we use the magic number 'ITV0'. */ memcpy(dst + sd, "ITV0", 4); - memcpy(dst + sd + 4, dst + sd + 12, line * 43); + memmove(dst + sd + 4, dst + sd + 12, line * 43); size = 4 + ((43 * line + 3) & ~3); } else { memcpy(dst + sd, "itv0", 4); @@ -532,7 +532,7 @@ void ivtv_vbi_work_handler(struct ivtv *itv) while (vi->cc_payload_idx) { cc = vi->cc_payload[0]; - memcpy(vi->cc_payload, vi->cc_payload + 1, + memmove(vi->cc_payload, vi->cc_payload + 1, sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0])); vi->cc_payload_idx--; if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80) diff --git a/drivers/media/pci/mantis/mantis_ca.c b/drivers/media/pci/mantis/mantis_ca.c index 3d704690900..60c6c2f2406 100644 --- a/drivers/media/pci/mantis/mantis_ca.c +++ b/drivers/media/pci/mantis/mantis_ca.c @@ -198,11 +198,12 @@ void mantis_ca_exit(struct mantis_pci *mantis) struct mantis_ca *ca = mantis->mantis_ca; dprintk(MANTIS_DEBUG, 1, "Mantis CA exit"); + if (!ca) + return; mantis_evmgr_exit(ca); dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device"); - if (ca) - dvb_ca_en50221_release(&ca->en50221); + dvb_ca_en50221_release(&ca->en50221); kfree(ca); } diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c index 049e18667cd..7859c43479d 100644 --- a/drivers/media/pci/meye/meye.c +++ b/drivers/media/pci/meye/meye.c @@ -35,6 +35,8 @@ #include <media/v4l2-common.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-fh.h> +#include <media/v4l2-event.h> #include <asm/uaccess.h> #include <asm/io.h> #include <linux/delay.h> @@ -811,7 +813,7 @@ again: mchip_hsize() * mchip_vsize() * 2); meye.grab_buffer[reqnr].size = mchip_hsize() * mchip_vsize() * 2; meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; - do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); + v4l2_get_timestamp(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr, sizeof(int), &meye.doneq_lock); @@ -832,7 +834,7 @@ again: size); meye.grab_buffer[reqnr].size = size; meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; - do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); + v4l2_get_timestamp(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr, sizeof(int), &meye.doneq_lock); @@ -865,7 +867,7 @@ static int meye_open(struct file *file) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; kfifo_reset(&meye.grabq); kfifo_reset(&meye.doneq); - return 0; + return v4l2_fh_open(file); } static int meye_release(struct file *file) @@ -873,7 +875,7 @@ static int meye_release(struct file *file) mchip_hic_stop(); mchip_dma_free(); clear_bit(0, &meye.in_use); - return 0; + return v4l2_fh_release(file); } static int meyeioc_g_params(struct meye_params *p) @@ -1032,8 +1034,9 @@ static int vidioc_querycap(struct file *file, void *fh, cap->version = (MEYE_DRIVER_MAJORVERSION << 8) + MEYE_DRIVER_MINORVERSION; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -1063,191 +1066,50 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int i) return 0; } -static int vidioc_queryctrl(struct file *file, void *fh, - struct v4l2_queryctrl *c) -{ - switch (c->id) { - - case V4L2_CID_BRIGHTNESS: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Brightness"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 32; - c->flags = 0; - break; - case V4L2_CID_HUE: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Hue"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 32; - c->flags = 0; - break; - case V4L2_CID_CONTRAST: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Contrast"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 32; - c->flags = 0; - break; - case V4L2_CID_SATURATION: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Saturation"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 32; - c->flags = 0; - break; - case V4L2_CID_AGC: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Agc"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 48; - c->flags = 0; - break; - case V4L2_CID_MEYE_SHARPNESS: - case V4L2_CID_SHARPNESS: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Sharpness"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 32; - - /* Continue to report legacy private SHARPNESS ctrl but - * say it is disabled in preference to ctrl in the spec - */ - c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 : - V4L2_CTRL_FLAG_DISABLED; - break; - case V4L2_CID_PICTURE: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Picture"); - c->minimum = 0; - c->maximum = 63; - c->step = 1; - c->default_value = 0; - c->flags = 0; - break; - case V4L2_CID_JPEGQUAL: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "JPEG quality"); - c->minimum = 0; - c->maximum = 10; - c->step = 1; - c->default_value = 8; - c->flags = 0; - break; - case V4L2_CID_FRAMERATE: - c->type = V4L2_CTRL_TYPE_INTEGER; - strcpy(c->name, "Framerate"); - c->minimum = 0; - c->maximum = 31; - c->step = 1; - c->default_value = 0; - c->flags = 0; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) +static int meye_s_ctrl(struct v4l2_ctrl *ctrl) { mutex_lock(&meye.lock); - switch (c->id) { + switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value); - meye.brightness = c->value << 10; + SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, ctrl->val); + meye.brightness = ctrl->val << 10; break; case V4L2_CID_HUE: sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERAHUE, c->value); - meye.hue = c->value << 10; + SONY_PIC_COMMAND_SETCAMERAHUE, ctrl->val); + meye.hue = ctrl->val << 10; break; case V4L2_CID_CONTRAST: sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value); - meye.contrast = c->value << 10; + SONY_PIC_COMMAND_SETCAMERACONTRAST, ctrl->val); + meye.contrast = ctrl->val << 10; break; case V4L2_CID_SATURATION: sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERACOLOR, c->value); - meye.colour = c->value << 10; + SONY_PIC_COMMAND_SETCAMERACOLOR, ctrl->val); + meye.colour = ctrl->val << 10; break; - case V4L2_CID_AGC: + case V4L2_CID_MEYE_AGC: sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERAAGC, c->value); - meye.params.agc = c->value; + SONY_PIC_COMMAND_SETCAMERAAGC, ctrl->val); + meye.params.agc = ctrl->val; break; case V4L2_CID_SHARPNESS: - case V4L2_CID_MEYE_SHARPNESS: sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value); - meye.params.sharpness = c->value; + SONY_PIC_COMMAND_SETCAMERASHARPNESS, ctrl->val); + meye.params.sharpness = ctrl->val; break; - case V4L2_CID_PICTURE: + case V4L2_CID_MEYE_PICTURE: sony_pic_camera_command( - SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value); - meye.params.picture = c->value; + SONY_PIC_COMMAND_SETCAMERAPICTURE, ctrl->val); + meye.params.picture = ctrl->val; break; - case V4L2_CID_JPEGQUAL: - meye.params.quality = c->value; + case V4L2_CID_JPEG_COMPRESSION_QUALITY: + meye.params.quality = ctrl->val; break; - case V4L2_CID_FRAMERATE: - meye.params.framerate = c->value; - break; - default: - mutex_unlock(&meye.lock); - return -EINVAL; - } - mutex_unlock(&meye.lock); - - return 0; -} - -static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c) -{ - mutex_lock(&meye.lock); - switch (c->id) { - case V4L2_CID_BRIGHTNESS: - c->value = meye.brightness >> 10; - break; - case V4L2_CID_HUE: - c->value = meye.hue >> 10; - break; - case V4L2_CID_CONTRAST: - c->value = meye.contrast >> 10; - break; - case V4L2_CID_SATURATION: - c->value = meye.colour >> 10; - break; - case V4L2_CID_AGC: - c->value = meye.params.agc; - break; - case V4L2_CID_SHARPNESS: - case V4L2_CID_MEYE_SHARPNESS: - c->value = meye.params.sharpness; - break; - case V4L2_CID_PICTURE: - c->value = meye.params.picture; - break; - case V4L2_CID_JPEGQUAL: - c->value = meye.params.quality; - break; - case V4L2_CID_FRAMERATE: - c->value = meye.params.framerate; + case V4L2_CID_MEYE_FRAMERATE: + meye.params.framerate = ctrl->val; break; default: mutex_unlock(&meye.lock); @@ -1426,7 +1288,7 @@ static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) return -EINVAL; buf->bytesused = meye.grab_buffer[index].size; - buf->flags = V4L2_BUF_FLAG_MAPPED; + buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; if (meye.grab_buffer[index].state == MEYE_BUF_USING) buf->flags |= V4L2_BUF_FLAG_QUEUED; @@ -1499,7 +1361,7 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->index = reqnr; buf->bytesused = meye.grab_buffer[reqnr].size; - buf->flags = V4L2_BUF_FLAG_MAPPED; + buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; buf->field = V4L2_FIELD_NONE; buf->timestamp = meye.grab_buffer[reqnr].timestamp; buf->sequence = meye.grab_buffer[reqnr].sequence; @@ -1577,12 +1439,12 @@ static long vidioc_default(struct file *file, void *fh, bool valid_prio, static unsigned int meye_poll(struct file *file, poll_table *wait) { - unsigned int res = 0; + unsigned int res = v4l2_ctrl_poll(file, wait); mutex_lock(&meye.lock); poll_wait(file, &meye.proc_list, wait); if (kfifo_len(&meye.doneq)) - res = POLLIN | POLLRDNORM; + res |= POLLIN | POLLRDNORM; mutex_unlock(&meye.lock); return res; } @@ -1669,9 +1531,6 @@ static const struct v4l2_ioctl_ops meye_ioctl_ops = { .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, @@ -1682,6 +1541,9 @@ static const struct v4l2_ioctl_ops meye_ioctl_ops = { .vidioc_dqbuf = vidioc_dqbuf, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, .vidioc_default = vidioc_default, }; @@ -1692,6 +1554,10 @@ static struct video_device meye_template = { .release = video_device_release, }; +static const struct v4l2_ctrl_ops meye_ctrl_ops = { + .s_ctrl = meye_s_ctrl, +}; + #ifdef CONFIG_PM static int meye_suspend(struct pci_dev *pdev, pm_message_t state) { @@ -1730,6 +1596,32 @@ static int meye_resume(struct pci_dev *pdev) static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) { + static const struct v4l2_ctrl_config ctrl_agc = { + .id = V4L2_CID_MEYE_AGC, + .type = V4L2_CTRL_TYPE_INTEGER, + .ops = &meye_ctrl_ops, + .name = "AGC", + .max = 63, + .step = 1, + .def = 48, + .flags = V4L2_CTRL_FLAG_SLIDER, + }; + static const struct v4l2_ctrl_config ctrl_picture = { + .id = V4L2_CID_MEYE_PICTURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .ops = &meye_ctrl_ops, + .name = "Picture", + .max = 63, + .step = 1, + }; + static const struct v4l2_ctrl_config ctrl_framerate = { + .id = V4L2_CID_MEYE_FRAMERATE, + .type = V4L2_CTRL_TYPE_INTEGER, + .ops = &meye_ctrl_ops, + .name = "Framerate", + .max = 31, + .step = 1, + }; struct v4l2_device *v4l2_dev = &meye.v4l2_dev; int ret = -EBUSY; unsigned long mchip_adr; @@ -1833,24 +1725,31 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) mutex_init(&meye.lock); init_waitqueue_head(&meye.proc_list); - meye.brightness = 32 << 10; - meye.hue = 32 << 10; - meye.colour = 32 << 10; - meye.contrast = 32 << 10; - meye.params.subsample = 0; - meye.params.quality = 8; - meye.params.sharpness = 32; - meye.params.agc = 48; - meye.params.picture = 0; - meye.params.framerate = 0; - - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, 32); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE, 32); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR, 32); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST, 32); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, 32); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0); - sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48); + + v4l2_ctrl_handler_init(&meye.hdl, 3); + v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 63, 1, 32); + v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops, + V4L2_CID_HUE, 0, 63, 1, 32); + v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops, + V4L2_CID_CONTRAST, 0, 63, 1, 32); + v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops, + V4L2_CID_SATURATION, 0, 63, 1, 32); + v4l2_ctrl_new_custom(&meye.hdl, &ctrl_agc, NULL); + v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops, + V4L2_CID_SHARPNESS, 0, 63, 1, 32); + v4l2_ctrl_new_custom(&meye.hdl, &ctrl_picture, NULL); + v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops, + V4L2_CID_JPEG_COMPRESSION_QUALITY, 0, 10, 1, 8); + v4l2_ctrl_new_custom(&meye.hdl, &ctrl_framerate, NULL); + if (meye.hdl.error) { + v4l2_err(v4l2_dev, "couldn't register controls\n"); + goto outvideoreg; + } + + v4l2_ctrl_handler_setup(&meye.hdl); + meye.vdev->ctrl_handler = &meye.hdl; + set_bit(V4L2_FL_USE_FH_PRIO, &meye.vdev->flags); if (video_register_device(meye.vdev, VFL_TYPE_GRABBER, video_nr) < 0) { @@ -1866,6 +1765,7 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) return 0; outvideoreg: + v4l2_ctrl_handler_free(&meye.hdl); free_irq(meye.mchip_irq, meye_irq); outreqirq: iounmap(meye.mchip_mmregs); diff --git a/drivers/media/pci/meye/meye.h b/drivers/media/pci/meye/meye.h index 4bdeb03f164..6fed9274cfa 100644 --- a/drivers/media/pci/meye/meye.h +++ b/drivers/media/pci/meye/meye.h @@ -39,6 +39,7 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kfifo.h> +#include <media/v4l2-ctrls.h> /****************************************************************************/ /* Motion JPEG chip registers */ @@ -290,6 +291,7 @@ struct meye_grab_buffer { /* Motion Eye device structure */ struct meye { struct v4l2_device v4l2_dev; /* Main v4l2_device struct */ + struct v4l2_ctrl_handler hdl; struct pci_dev *mchip_dev; /* pci device */ u8 mchip_irq; /* irq */ u8 mchip_mode; /* actual mchip mode: HIC_MODE... */ diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c index fad21411366..9e82d2105d5 100644 --- a/drivers/media/pci/ngene/ngene-cards.c +++ b/drivers/media/pci/ngene/ngene-cards.c @@ -327,6 +327,14 @@ static int demod_attach_drxd(struct ngene_channel *chan) pr_err("No DRXD found!\n"); return -ENODEV; } + return 0; +} + +static int tuner_attach_dtt7520x(struct ngene_channel *chan) +{ + struct drxd_config *feconf; + + feconf = chan->dev->card_info->fe_config[chan->number]; if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address, &chan->i2c_adapter, @@ -724,6 +732,7 @@ static struct ngene_info ngene_info_terratec = { .name = "Terratec Integra/Cinergy2400i Dual DVB-T", .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, .demod_attach = {demod_attach_drxd, demod_attach_drxd}, + .tuner_attach = {tuner_attach_dtt7520x, tuner_attach_dtt7520x}, .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, .i2c_access = 1, }; diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index bc08f1dbc29..dc68cf1070f 100644 --- a/drivers/media/pci/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c @@ -5773,6 +5773,23 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0000000, }, }, + [SAA7134_BOARD_HAWELL_HW_9004V1] = { + /* Hawell HW-9004V1 */ + /* Vadim Frolov <fralik@gmail.com> */ + .name = "Hawell HW-9004V1", + .audio_clock = 0x00200000, + .tuner_type = UNSET, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x618E700, + .inputs = {{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x6010000, + } }, + }, }; diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index e359d200d69..8fd24e7c940 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -308,7 +308,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev, /* finish current buffer */ q->curr->vb.state = state; - do_gettimeofday(&q->curr->vb.ts); + v4l2_get_timestamp(&q->curr->vb.ts); wake_up(&q->curr->vb.done); q->curr = NULL; } diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c index b209de40a4f..27915e501db 100644 --- a/drivers/media/pci/saa7134/saa7134-dvb.c +++ b/drivers/media/pci/saa7134/saa7134-dvb.c @@ -607,6 +607,9 @@ static int configure_tda827x_fe(struct saa7134_dev *dev, /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + if (!fe0) + return -EINVAL; + fe0->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap); if (fe0->dvb.frontend) { if (cdec_conf->i2c_gate) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 3abf52711e1..7c503fb6852 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -2248,6 +2248,17 @@ static int saa7134_streamon(struct file *file, void *priv, if (!res_get(dev, fh, res)) return -EBUSY; + /* The SAA7134 has a 1K FIFO; the datasheet suggests that when + * configured conservatively, there's 22 usec of buffering for video. + * We therefore request a DMA latency of 20 usec, giving us 2 usec of + * margin in case the FIFO is configured differently to the datasheet. + * Unfortunately, I lack register-level documentation to check the + * Linux FIFO setup and confirm the perfect value. + */ + pm_qos_add_request(&fh->qos_request, + PM_QOS_CPU_DMA_LATENCY, + 20); + return videobuf_streamon(saa7134_queue(fh)); } @@ -2259,6 +2270,8 @@ static int saa7134_streamoff(struct file *file, void *priv, struct saa7134_dev *dev = fh->dev; int res = saa7134_resource(fh); + pm_qos_remove_request(&fh->qos_request); + err = videobuf_streamoff(saa7134_queue(fh)); if (err < 0) return err; diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 075908fae4d..71eefef5e32 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -29,6 +29,7 @@ #include <linux/notifier.h> #include <linux/delay.h> #include <linux/mutex.h> +#include <linux/pm_qos.h> #include <asm/io.h> @@ -41,7 +42,7 @@ #include <media/videobuf-dma-sg.h> #include <sound/core.h> #include <sound/pcm.h> -#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) +#if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB) #include <media/videobuf-dvb.h> #endif @@ -332,6 +333,7 @@ struct saa7134_card_ir { #define SAA7134_BOARD_SENSORAY811_911 188 #define SAA7134_BOARD_KWORLD_PC150U 189 #define SAA7134_BOARD_ASUSTeK_PS3_100 190 +#define SAA7134_BOARD_HAWELL_HW_9004V1 191 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 @@ -469,6 +471,7 @@ struct saa7134_fh { enum v4l2_buf_type type; unsigned int resources; enum v4l2_priority prio; + struct pm_qos_request qos_request; /* video overlay */ struct v4l2_window win; @@ -642,7 +645,7 @@ struct saa7134_dev { struct work_struct empress_workqueue; int empress_started; -#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) +#if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB) /* SAA7134_MPEG_DVB only */ struct videobuf_dvb_frontends frontends; int (*original_demod_sleep)(struct dvb_frontend *fe); diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index 994018e2d0d..9bb0903ee5f 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -1298,6 +1298,7 @@ static int saa7164_g_chip_ident(struct file *file, void *fh, return 0; } +#ifdef CONFIG_VIDEO_ADV_DEBUG static int saa7164_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { @@ -1323,6 +1324,7 @@ static int saa7164_s_register(struct file *file, void *fh, return 0; } +#endif static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_s_std = vidioc_s_std, diff --git a/drivers/media/pci/sta2x11/Kconfig b/drivers/media/pci/sta2x11/Kconfig index 6749f67cab8..a94ccad0206 100644 --- a/drivers/media/pci/sta2x11/Kconfig +++ b/drivers/media/pci/sta2x11/Kconfig @@ -2,7 +2,7 @@ config STA2X11_VIP tristate "STA2X11 VIP Video For Linux" depends on STA2X11 select VIDEO_ADV7180 if MEDIA_SUBDRV_AUTOSELECT - select VIDEOBUF_DMA_CONTIG + select VIDEOBUF2_DMA_CONTIG depends on PCI && VIDEO_V4L2 && VIRT_TO_BUS help Say Y for support for STA2X11 VIP (Video Input Port) capture diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 27ae4884265..4b703fe8c95 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -1,7 +1,11 @@ /* * This is the driver for the STA2x11 Video Input Port. * + * Copyright (C) 2012 ST Microelectronics + * author: Federico Vaga <federico.vaga@gmail.com> * Copyright (C) 2010 WindRiver Systems, Inc. + * authors: Andreas Kies <andreas.kies@windriver.com> + * Vlad Lungu <vlad.lungu@windriver.com> * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -19,36 +23,30 @@ * The full GNU General Public License is included in this distribution in * the file called "COPYING". * - * Author: Andreas Kies <andreas.kies@windriver.com> - * Vlad Lungu <vlad.lungu@windriver.com> - * */ #include <linux/types.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> -#include <linux/vmalloc.h> - #include <linux/videodev2.h> - #include <linux/kmod.h> - #include <linux/pci.h> #include <linux/interrupt.h> -#include <linux/mutex.h> #include <linux/io.h> #include <linux/gpio.h> #include <linux/i2c.h> #include <linux/delay.h> #include <media/v4l2-common.h> #include <media/v4l2-device.h> +#include <media/v4l2-ctrls.h> #include <media/v4l2-ioctl.h> -#include <media/videobuf-dma-contig.h> +#include <media/v4l2-fh.h> +#include <media/v4l2-event.h> +#include <media/videobuf2-dma-contig.h> #include "sta2x11_vip.h" -#define DRV_NAME "sta2x11_vip" #define DRV_VERSION "1.3" #ifndef PCI_DEVICE_ID_STMICRO_VIP @@ -63,8 +61,8 @@ #define DVP_TFS 0x08 #define DVP_BFO 0x0C #define DVP_BFS 0x10 -#define DVP_VTP 0x14 -#define DVP_VBP 0x18 +#define DVP_VTP 0x14 +#define DVP_VBP 0x18 #define DVP_VMP 0x1C #define DVP_ITM 0x98 #define DVP_ITS 0x9C @@ -84,13 +82,21 @@ #define DVP_HLFLN_SD 0x00000001 -#define REG_WRITE(vip, reg, value) iowrite32((value), (vip->iomem)+(reg)) -#define REG_READ(vip, reg) ioread32((vip->iomem)+(reg)) - #define SAVE_COUNT 8 #define AUX_COUNT 3 #define IRQ_COUNT 1 + +struct vip_buffer { + struct vb2_buffer vb; + struct list_head list; + dma_addr_t dma; +}; +static inline struct vip_buffer *to_vip_buffer(struct vb2_buffer *vb2) +{ + return container_of(vb2, struct vip_buffer, vb); +} + /** * struct sta2x11_vip - All internal data for one instance of device * @v4l2_dev: device registered in v4l layer @@ -99,29 +105,26 @@ * @adapter: contains I2C adapter information * @register_save_area: All relevant register are saved here during suspend * @decoder: contains information about video DAC + * @ctrl_hdl: handler for control framework * @format: pixel format, fixed UYVY * @std: video standard (e.g. PAL/NTSC) * @input: input line for video signal ( 0 or 1 ) - * @users: Number of open of device ( max. 1 ) * @disabled: Device is in power down state - * @mutex: ensures exclusive opening of device * @slock: for excluse acces of registers - * @vb_vidq: queue maintained by videobuf layer - * @capture: linked list of capture buffer - * @active: struct videobuf_buffer currently beingg filled - * @started: device is ready to capture frame - * @closing: device will be shut down + * @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 + * @active: current active buffer + * @lock: used in videobuf2 callback * @tcount: Number of top frames * @bcount: Number of bottom frames * @overflow: Number of FIFO overflows - * @mem_spare: small buffer of unused frame - * @dma_spare: dma addres of mem_spare * @iomem: hardware base address * @config: I2C and gpio config from platform * * All non-local data is accessed via this structure. */ - struct sta2x11_vip { struct v4l2_device v4l2_dev; struct video_device *video_dev; @@ -129,21 +132,27 @@ struct sta2x11_vip { struct i2c_adapter *adapter; unsigned int register_save_area[IRQ_COUNT + SAVE_COUNT + AUX_COUNT]; struct v4l2_subdev *decoder; + struct v4l2_ctrl_handler ctrl_hdl; + + struct v4l2_pix_format format; v4l2_std_id std; unsigned int input; - int users; int disabled; - struct mutex mutex; /* exclusive access during open */ - spinlock_t slock; /* spin lock for hardware and queue access */ - struct videobuf_queue vb_vidq; - struct list_head capture; - struct videobuf_buffer *active; - int started, closing, tcount, bcount; + spinlock_t slock; + + struct vb2_alloc_ctx *alloc_ctx; + struct vb2_queue vb_vidq; + struct list_head buffer_list; + unsigned int sequence; + struct vip_buffer *active; /* current active buffer */ + spinlock_t lock; /* Used in videobuf2 callback */ + + /* Interrupt counters */ + int tcount, bcount; int overflow; - void *mem_spare; - dma_addr_t dma_spare; - void *iomem; + + void *iomem; /* I/O Memory */ struct vip_config *config; }; @@ -206,318 +215,195 @@ static struct v4l2_pix_format formats_60[] = { .colorspace = V4L2_COLORSPACE_SMPTE170M}, }; -/** - * buf_setup - Get size and number of video buffer - * @vq: queue in videobuf - * @count: Number of buffers (1..MAX_FRAMES). - * 0 use default value. - * @size: size of buffer in bytes - * - * returns size and number of buffers - * a preset value of 0 returns the default number. - * return value: 0, always succesfull. - */ -static int buf_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) +/* Write VIP register */ +static inline void reg_write(struct sta2x11_vip *vip, unsigned int reg, u32 val) { - struct sta2x11_vip *vip = vq->priv_data; - - *size = vip->format.width * vip->format.height * 2; - if (0 == *count || MAX_FRAMES < *count) - *count = MAX_FRAMES; - return 0; -}; - -/** - * buf_prepare - prepare buffer for usage - * @vq: queue in videobuf layer - * @vb: buffer to be prepared - * @field: type of video data (interlaced/non-interlaced) - * - * Allocate or realloc buffer - * return value: 0, successful. - * - * -EINVAL, supplied buffer is too small. - * - * other, buffer could not be locked. - */ -static int buf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) + iowrite32((val), (vip->iomem)+(reg)); +} +/* Read VIP register */ +static inline u32 reg_read(struct sta2x11_vip *vip, unsigned int reg) { - struct sta2x11_vip *vip = vq->priv_data; - int ret; - - vb->size = vip->format.width * vip->format.height * 2; - if ((0 != vb->baddr) && (vb->bsize < vb->size)) - return -EINVAL; - vb->width = vip->format.width; - vb->height = vip->format.height; - vb->field = field; - - if (VIDEOBUF_NEEDS_INIT == vb->state) { - ret = videobuf_iolock(vq, vb, NULL); - if (ret) - goto fail; - } - vb->state = VIDEOBUF_PREPARED; - return 0; -fail: - videobuf_dma_contig_free(vq, vb); - vb->state = VIDEOBUF_NEEDS_INIT; - return ret; + return ioread32((vip->iomem)+(reg)); } - -/** - * buf_queu - queue buffer for filling - * @vq: queue in videobuf layer - * @vb: buffer to be queued - * - * if capturing is already running, the buffer will be queued. Otherwise - * capture is started and the buffer is used directly. - */ -static void buf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +/* Start DMA acquisition */ +static void start_dma(struct sta2x11_vip *vip, struct vip_buffer *vip_buf) { - struct sta2x11_vip *vip = vq->priv_data; - u32 dma; + unsigned long offset = 0; + + if (vip->format.field == V4L2_FIELD_INTERLACED) + offset = vip->format.width * 2; - vb->state = VIDEOBUF_QUEUED; + spin_lock_irq(&vip->slock); + /* Enable acquisition */ + reg_write(vip, DVP_CTL, reg_read(vip, DVP_CTL) | DVP_CTL_ENA); + /* Set Top and Bottom Field memory address */ + reg_write(vip, DVP_VTP, (u32)vip_buf->dma); + reg_write(vip, DVP_VBP, (u32)vip_buf->dma + offset); + spin_unlock_irq(&vip->slock); +} - if (vip->active) { - list_add_tail(&vb->queue, &vip->capture); +/* Fetch the next buffer to activate */ +static void vip_active_buf_next(struct sta2x11_vip *vip) +{ + /* Get the next buffer */ + spin_lock(&vip->lock); + if (list_empty(&vip->buffer_list)) {/* No available buffer */ + spin_unlock(&vip->lock); return; } - - vip->started = 1; + vip->active = list_first_entry(&vip->buffer_list, + struct vip_buffer, + list); + /* Reset Top and Bottom counter */ vip->tcount = 0; vip->bcount = 0; - vip->active = vb; - vb->state = VIDEOBUF_ACTIVE; + spin_unlock(&vip->lock); + if (vb2_is_streaming(&vip->vb_vidq)) { /* streaming is on */ + start_dma(vip, vip->active); /* start dma capture */ + } +} - dma = videobuf_to_dma_contig(vb); - REG_WRITE(vip, DVP_TFO, (0 << 16) | (0)); - /* despite of interlace mode, upper and lower frames start at zero */ - REG_WRITE(vip, DVP_BFO, (0 << 16) | (0)); +/* Videobuf2 Operations */ +static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct sta2x11_vip *vip = vb2_get_drv_priv(vq); - switch (vip->format.field) { - case V4L2_FIELD_INTERLACED: - REG_WRITE(vip, DVP_TFS, - ((vip->format.height / 2 - 1) << 16) | - (2 * vip->format.width - 1)); - REG_WRITE(vip, DVP_BFS, ((vip->format.height / 2 - 1) << 16) | - (2 * vip->format.width - 1)); - REG_WRITE(vip, DVP_VTP, dma); - REG_WRITE(vip, DVP_VBP, dma + vip->format.width * 2); - REG_WRITE(vip, DVP_VMP, 4 * vip->format.width); - break; - case V4L2_FIELD_TOP: - REG_WRITE(vip, DVP_TFS, - ((vip->format.height - 1) << 16) | - (2 * vip->format.width - 1)); - REG_WRITE(vip, DVP_BFS, ((0) << 16) | - (2 * vip->format.width - 1)); - REG_WRITE(vip, DVP_VTP, dma); - REG_WRITE(vip, DVP_VBP, dma); - REG_WRITE(vip, DVP_VMP, 2 * vip->format.width); - break; - case V4L2_FIELD_BOTTOM: - REG_WRITE(vip, DVP_TFS, ((0) << 16) | - (2 * vip->format.width - 1)); - REG_WRITE(vip, DVP_BFS, - ((vip->format.height) << 16) | - (2 * vip->format.width - 1)); - REG_WRITE(vip, DVP_VTP, dma); - REG_WRITE(vip, DVP_VBP, dma); - REG_WRITE(vip, DVP_VMP, 2 * vip->format.width); - break; + if (!(*nbuffers) || *nbuffers < MAX_FRAMES) + *nbuffers = MAX_FRAMES; - default: - pr_warning("VIP: unknown field format\n"); - return; - } + *nplanes = 1; + sizes[0] = vip->format.sizeimage; + alloc_ctxs[0] = vip->alloc_ctx; - REG_WRITE(vip, DVP_CTL, DVP_CTL_ENA); -} + vip->sequence = 0; + vip->active = NULL; + vip->tcount = 0; + vip->bcount = 0; -/** - * buff_release - release buffer - * @vq: queue in videobuf layer - * @vb: buffer to be released - * - * release buffer in videobuf layer - */ -static void buf_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) + return 0; +}; +static int buffer_init(struct vb2_buffer *vb) { + struct vip_buffer *vip_buf = to_vip_buffer(vb); - videobuf_dma_contig_free(vq, vb); - vb->state = VIDEOBUF_NEEDS_INIT; + vip_buf->dma = vb2_dma_contig_plane_dma_addr(vb, 0); + INIT_LIST_HEAD(&vip_buf->list); + return 0; } -static struct videobuf_queue_ops vip_qops = { - .buf_setup = buf_setup, - .buf_prepare = buf_prepare, - .buf_queue = buf_queue, - .buf_release = buf_release, -}; - -/** - * vip_open - open video device - * @file: descriptor of device - * - * open device, make sure it is only opened once. - * return value: 0, no error. - * - * -EBUSY, device is already opened - * - * -ENOMEM, no memory for auxiliary DMA buffer - */ -static int vip_open(struct file *file) +static int buffer_prepare(struct vb2_buffer *vb) { - struct video_device *dev = video_devdata(file); - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue); + struct vip_buffer *vip_buf = to_vip_buffer(vb); + unsigned long size; + + size = vip->format.sizeimage; + if (vb2_plane_size(vb, 0) < size) { + v4l2_err(&vip->v4l2_dev, "buffer too small (%lu < %lu)\n", + vb2_plane_size(vb, 0), size); + return -EINVAL; + } - mutex_lock(&vip->mutex); - vip->users++; + vb2_set_plane_payload(&vip_buf->vb, 0, size); - if (vip->users > 1) { - vip->users--; - mutex_unlock(&vip->mutex); - return -EBUSY; + return 0; +} +static void buffer_queue(struct vb2_buffer *vb) +{ + struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue); + struct vip_buffer *vip_buf = to_vip_buffer(vb); + + spin_lock(&vip->lock); + list_add_tail(&vip_buf->list, &vip->buffer_list); + if (!vip->active) { /* No active buffer, active the first one */ + vip->active = list_first_entry(&vip->buffer_list, + struct vip_buffer, + list); + if (vb2_is_streaming(&vip->vb_vidq)) /* streaming is on */ + start_dma(vip, vip_buf); /* start dma capture */ } + spin_unlock(&vip->lock); +} +static int buffer_finish(struct vb2_buffer *vb) +{ + struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue); + struct vip_buffer *vip_buf = to_vip_buffer(vb); - file->private_data = dev; - vip->overflow = 0; - vip->started = 0; - vip->closing = 0; - vip->active = NULL; + /* Buffer handled, remove it from the list */ + spin_lock(&vip->lock); + list_del_init(&vip_buf->list); + spin_unlock(&vip->lock); - INIT_LIST_HEAD(&vip->capture); - vip->mem_spare = dma_alloc_coherent(&vip->pdev->dev, 64, - &vip->dma_spare, GFP_KERNEL); - if (!vip->mem_spare) { - vip->users--; - mutex_unlock(&vip->mutex); - return -ENOMEM; - } + vip_active_buf_next(vip); - mutex_unlock(&vip->mutex); - videobuf_queue_dma_contig_init_cached(&vip->vb_vidq, - &vip_qops, - &vip->pdev->dev, - &vip->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct videobuf_buffer), - vip, NULL); - REG_READ(vip, DVP_ITS); - REG_WRITE(vip, DVP_HLFLN, DVP_HLFLN_SD); - REG_WRITE(vip, DVP_ITM, DVP_IT_VSB | DVP_IT_VST); - REG_WRITE(vip, DVP_CTL, DVP_CTL_RST); - REG_WRITE(vip, DVP_CTL, 0); - REG_READ(vip, DVP_ITS); return 0; } -/** - * vip_close - close video device - * @file: descriptor of device - * - * close video device, wait until all pending operations are finished - * ( maximum FRAME_MAX buffers pending ) - * Turn off interrupts. - * - * return value: 0, always succesful. - */ -static int vip_close(struct file *file) +static int start_streaming(struct vb2_queue *vq, unsigned int count) { - struct video_device *dev = video_devdata(file); - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = vb2_get_drv_priv(vq); - vip->closing = 1; - if (vip->active) - videobuf_waiton(&vip->vb_vidq, vip->active, 0, 0); spin_lock_irq(&vip->slock); - - REG_WRITE(vip, DVP_ITM, 0); - REG_WRITE(vip, DVP_CTL, DVP_CTL_RST); - REG_WRITE(vip, DVP_CTL, 0); - REG_READ(vip, DVP_ITS); - - vip->started = 0; - vip->active = NULL; - + /* Enable interrupt VSYNC Top and Bottom*/ + reg_write(vip, DVP_ITM, DVP_IT_VSB | DVP_IT_VST); spin_unlock_irq(&vip->slock); - videobuf_stop(&vip->vb_vidq); - videobuf_mmap_free(&vip->vb_vidq); + if (count) + start_dma(vip, vip->active); - dma_free_coherent(&vip->pdev->dev, 64, vip->mem_spare, vip->dma_spare); - file->private_data = NULL; - mutex_lock(&vip->mutex); - vip->users--; - mutex_unlock(&vip->mutex); return 0; } -/** - * vip_read - read from video input - * @file: descriptor of device - * @data: user buffer - * @count: number of bytes to be read - * @ppos: position within stream - * - * read video data from video device. - * handling is done in generic videobuf layer - * return value: provided by videobuf layer - */ -static ssize_t vip_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) +/* abort streaming and wait for last buffer */ +static int stop_streaming(struct vb2_queue *vq) { - struct video_device *dev = file->private_data; - struct sta2x11_vip *vip = video_get_drvdata(dev); - - return videobuf_read_stream(&vip->vb_vidq, data, count, ppos, 0, - file->f_flags & O_NONBLOCK); + struct sta2x11_vip *vip = vb2_get_drv_priv(vq); + struct vip_buffer *vip_buf, *node; + + /* Disable acquisition */ + reg_write(vip, DVP_CTL, reg_read(vip, DVP_CTL) & ~DVP_CTL_ENA); + /* Disable all interrupts */ + reg_write(vip, DVP_ITM, 0); + + /* Release all active buffers */ + spin_lock(&vip->lock); + list_for_each_entry_safe(vip_buf, node, &vip->buffer_list, list) { + vb2_buffer_done(&vip_buf->vb, VB2_BUF_STATE_ERROR); + list_del(&vip_buf->list); + } + spin_unlock(&vip->lock); + return 0; } -/** - * vip_mmap - map user buffer - * @file: descriptor of device - * @vma: user buffer - * - * map user space buffer into kernel mode, including DMA address. - * handling is done in generic videobuf layer. - * return value: provided by videobuf layer - */ -static int vip_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_device *dev = file->private_data; - struct sta2x11_vip *vip = video_get_drvdata(dev); +static struct vb2_ops vip_video_qops = { + .queue_setup = queue_setup, + .buf_init = buffer_init, + .buf_prepare = buffer_prepare, + .buf_finish = buffer_finish, + .buf_queue = buffer_queue, + .start_streaming = start_streaming, + .stop_streaming = stop_streaming, +}; - return videobuf_mmap_mapper(&vip->vb_vidq, vma); -} -/** - * vip_poll - poll for event - * @file: descriptor of device - * @wait: contains events to be waited for - * - * wait for event related to video device. - * handling is done in generic videobuf layer. - * return value: provided by videobuf layer - */ -static unsigned int vip_poll(struct file *file, struct poll_table_struct *wait) -{ - struct video_device *dev = file->private_data; - struct sta2x11_vip *vip = video_get_drvdata(dev); +/* File Operations */ +static const struct v4l2_file_operations vip_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .unlocked_ioctl = video_ioctl2, + .read = vb2_fop_read, + .mmap = vb2_fop_mmap, + .poll = vb2_fop_poll +}; - return videobuf_poll_stream(file, &vip->vb_vidq, wait); -} /** * vidioc_querycap - return capabilities of device - * @file: descriptor of device (not used) - * @priv: points to current videodevice + * @file: descriptor of device * @cap: contains return values * * the capabilities of the device are returned @@ -527,25 +413,22 @@ static unsigned int vip_poll(struct file *file, struct poll_table_struct *wait) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = video_drvdata(file); - memset(cap, 0, sizeof(struct v4l2_capability)); - strcpy(cap->driver, DRV_NAME); - strcpy(cap->card, DRV_NAME); - cap->version = 0; + strcpy(cap->driver, KBUILD_MODNAME); + strcpy(cap->card, KBUILD_MODNAME); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(vip->pdev)); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } /** * vidioc_s_std - set video standard - * @file: descriptor of device (not used) - * @priv: points to current videodevice + * @file: descriptor of device * @std: contains standard to be set * * the video standard is set @@ -558,8 +441,7 @@ static int vidioc_querycap(struct file *file, void *priv, */ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) { - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = video_drvdata(file); v4l2_std_id oldstd = vip->std, newstd; int status; @@ -592,8 +474,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) /** * vidioc_g_std - get video standard - * @file: descriptor of device (not used) - * @priv: points to current videodevice + * @file: descriptor of device * @std: contains return values * * the current video standard is returned @@ -602,8 +483,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) */ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std) { - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = video_drvdata(file); *std = vip->std; return 0; @@ -611,8 +491,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std) /** * vidioc_querystd - get possible video standards - * @file: descriptor of device (not used) - * @priv: points to current videodevice + * @file: descriptor of device * @std: contains return values * * all possible video standards are returned @@ -621,79 +500,11 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std) */ static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std) { - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = video_drvdata(file); return v4l2_subdev_call(vip->decoder, video, querystd, std); - } -/** - * vidioc_queryctl - get possible control settings - * @file: descriptor of device (not used) - * @priv: points to current videodevice - * @ctrl: contains return values - * - * return possible values for a control - * return value: delivered by video DAC routine. - */ -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *ctrl) -{ - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); - - return v4l2_subdev_call(vip->decoder, core, queryctrl, ctrl); -} - -/** - * vidioc_g_ctl - get control value - * @file: descriptor of device (not used) - * @priv: points to current videodevice - * @ctrl: contains return values - * - * return setting for a control value - * return value: delivered by video DAC routine. - */ -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); - - return v4l2_subdev_call(vip->decoder, core, g_ctrl, ctrl); -} - -/** - * vidioc_s_ctl - set control value - * @file: descriptor of device (not used) - * @priv: points to current videodevice - * @ctrl: contains value to be set - * - * set value for a specific control - * return value: delivered by video DAC routine. - */ -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); - - return v4l2_subdev_call(vip->decoder, core, s_ctrl, ctrl); -} - -/** - * vidioc_enum_input - return name of input line - * @file: descriptor of device (not used) - * @priv: points to current videodevice - * @inp: contains return values - * - * the user friendly name of the input line is returned - * - * return value: 0, no error. - * - * -EINVAL, input line number out of range - */ static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp) { @@ -709,8 +520,7 @@ static int vidioc_enum_input(struct file *file, void *priv, /** * vidioc_s_input - set input line - * @file: descriptor of device ( not used) - * @priv: points to current videodevice + * @file: descriptor of device * @i: new input line number * * the current active input line is set @@ -721,8 +531,7 @@ static int vidioc_enum_input(struct file *file, void *priv, */ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = video_drvdata(file); int ret; if (i > 1) @@ -737,8 +546,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) /** * vidioc_g_input - return input line - * @file: descriptor of device ( not used) - * @priv: points to current videodevice + * @file: descriptor of device * @i: returned input line number * * the current active input line is returned @@ -747,8 +555,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) */ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = video_drvdata(file); *i = vip->input; return 0; @@ -756,8 +563,6 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) /** * vidioc_enum_fmt_vid_cap - return video capture format - * @file: descriptor of device ( not used) - * @priv: points to current videodevice * @f: returned format information * * returns name and format of video capture @@ -780,8 +585,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, /** * vidioc_try_fmt_vid_cap - set video capture format - * @file: descriptor of device ( not used) - * @priv: points to current videodevice + * @file: descriptor of device * @f: new format * * new video format is set which includes width and @@ -797,12 +601,13 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = video_drvdata(file); int interlace_lim; - if (V4L2_PIX_FMT_UYVY != f->fmt.pix.pixelformat) + if (V4L2_PIX_FMT_UYVY != f->fmt.pix.pixelformat) { + v4l2_warn(&vip->v4l2_dev, "Invalid format, only UYVY supported\n"); return -EINVAL; + } if (V4L2_STD_525_60 & vip->std) interlace_lim = 240; @@ -810,6 +615,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, interlace_lim = 288; switch (f->fmt.pix.field) { + default: case V4L2_FIELD_ANY: if (interlace_lim < f->fmt.pix.height) f->fmt.pix.field = V4L2_FIELD_INTERLACED; @@ -823,10 +629,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, break; case V4L2_FIELD_INTERLACED: break; - default: - return -EINVAL; } + /* It is the only supported format */ + f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; f->fmt.pix.height &= ~1; if (2 * interlace_lim < f->fmt.pix.height) f->fmt.pix.height = 2 * interlace_lim; @@ -842,8 +648,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, /** * vidioc_s_fmt_vid_cap - set current video format parameters - * @file: descriptor of device ( not used) - * @priv: points to current videodevice + * @file: descriptor of device * @f: returned format information * * set new capture format @@ -854,22 +659,63 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = video_drvdata(file); + unsigned int t_stop, b_stop, pitch; int ret; ret = vidioc_try_fmt_vid_cap(file, priv, f); if (ret) return ret; - memcpy(&vip->format, &f->fmt.pix, sizeof(struct v4l2_pix_format)); + if (vb2_is_busy(&vip->vb_vidq)) { + /* Can't change format during acquisition */ + v4l2_err(&vip->v4l2_dev, "device busy\n"); + return -EBUSY; + } + vip->format = f->fmt.pix; + switch (vip->format.field) { + case V4L2_FIELD_INTERLACED: + t_stop = ((vip->format.height / 2 - 1) << 16) | + (2 * vip->format.width - 1); + b_stop = t_stop; + pitch = 4 * vip->format.width; + break; + case V4L2_FIELD_TOP: + t_stop = ((vip->format.height - 1) << 16) | + (2 * vip->format.width - 1); + b_stop = (0 << 16) | (2 * vip->format.width - 1); + pitch = 2 * vip->format.width; + break; + case V4L2_FIELD_BOTTOM: + t_stop = (0 << 16) | (2 * vip->format.width - 1); + b_stop = (vip->format.height << 16) | + (2 * vip->format.width - 1); + pitch = 2 * vip->format.width; + break; + default: + v4l2_err(&vip->v4l2_dev, "unknown field format\n"); + return -EINVAL; + } + + spin_lock_irq(&vip->slock); + /* Y-X Top Field Offset */ + reg_write(vip, DVP_TFO, 0); + /* Y-X Bottom Field Offset */ + reg_write(vip, DVP_BFO, 0); + /* Y-X Top Field Stop*/ + reg_write(vip, DVP_TFS, t_stop); + /* Y-X Bottom Field Stop */ + reg_write(vip, DVP_BFS, b_stop); + /* Video Memory Pitch */ + reg_write(vip, DVP_VMP, pitch); + spin_unlock_irq(&vip->slock); + return 0; } /** * vidioc_g_fmt_vid_cap - get current video format parameters - * @file: descriptor of device ( not used) - * @priv: points to current videodevice + * @file: descriptor of device * @f: contains format information * * returns current video format parameters @@ -879,150 +725,47 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); - - memcpy(&f->fmt.pix, &vip->format, sizeof(struct v4l2_pix_format)); - return 0; -} - -/** - * vidioc_reqfs - request buffer - * @file: descriptor of device ( not used) - * @priv: points to current videodevice - * @p: video buffer - * - * Handling is done in generic videobuf layer. - */ -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *p) -{ - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); - - return videobuf_reqbufs(&vip->vb_vidq, p); -} - -/** - * vidioc_querybuf - query buffer - * @file: descriptor of device ( not used) - * @priv: points to current videodevice - * @p: video buffer - * - * query buffer state. - * Handling is done in generic videobuf layer. - */ -static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); + struct sta2x11_vip *vip = video_drvdata(file); - return videobuf_querybuf(&vip->vb_vidq, p); -} + f->fmt.pix = vip->format; -/** - * vidioc_qbuf - queue a buffer - * @file: descriptor of device ( not used) - * @priv: points to current videodevice - * @p: video buffer - * - * Handling is done in generic videobuf layer. - */ -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); - - return videobuf_qbuf(&vip->vb_vidq, p); -} - -/** - * vidioc_dqbuf - dequeue a buffer - * @file: descriptor of device ( not used) - * @priv: points to current videodevice - * @p: video buffer - * - * Handling is done in generic videobuf layer. - */ -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); - - return videobuf_dqbuf(&vip->vb_vidq, p, file->f_flags & O_NONBLOCK); -} - -/** - * vidioc_streamon - turn on streaming - * @file: descriptor of device ( not used) - * @priv: points to current videodevice - * @type: type of capture - * - * turn on streaming. - * Handling is done in generic videobuf layer. - */ -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); - - return videobuf_streamon(&vip->vb_vidq); -} - -/** - * vidioc_streamoff - turn off streaming - * @file: descriptor of device ( not used) - * @priv: points to current videodevice - * @type: type of capture - * - * turn off streaming. - * Handling is done in generic videobuf layer. - */ -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct video_device *dev = priv; - struct sta2x11_vip *vip = video_get_drvdata(dev); - - return videobuf_streamoff(&vip->vb_vidq); + return 0; } -static const struct v4l2_file_operations vip_fops = { - .owner = THIS_MODULE, - .open = vip_open, - .release = vip_close, - .ioctl = video_ioctl2, - .read = vip_read, - .mmap = vip_mmap, - .poll = vip_poll -}; - static const struct v4l2_ioctl_ops vip_ioctl_ops = { .vidioc_querycap = vidioc_querycap, - .vidioc_s_std = vidioc_s_std, + /* FMT handling */ + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + /* Buffer handlers */ + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + /* Stream on/off */ + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + /* Standard handling */ .vidioc_g_std = vidioc_g_std, + .vidioc_s_std = vidioc_s_std, .vidioc_querystd = vidioc_querystd, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, + /* Input handling */ .vidioc_enum_input = vidioc_enum_input, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_input = vidioc_s_input, .vidioc_g_input = vidioc_g_input, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, + .vidioc_s_input = vidioc_s_input, + /* Log status ioctl */ + .vidioc_log_status = v4l2_ctrl_log_status, + /* Event handling */ + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; static struct video_device video_dev_template = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .release = video_device_release, .fops = &vip_fops, .ioctl_ops = &vip_ioctl_ops, @@ -1036,9 +779,7 @@ static struct video_device video_dev_template = { * * check for both frame interrupts set ( top and bottom ). * check FIFO overflow, but limit number of log messages after open. - * signal a complete buffer if done. - * dequeue a new buffer if available. - * disable VIP if no buffer available. + * signal a complete buffer if done * * return value: IRQ_NONE, interrupt was not generated by VIP * @@ -1046,88 +787,122 @@ static struct video_device video_dev_template = { */ static irqreturn_t vip_irq(int irq, struct sta2x11_vip *vip) { - u32 status, dma; - unsigned long flags; - struct videobuf_buffer *vb; + unsigned int status; - status = REG_READ(vip, DVP_ITS); + status = reg_read(vip, DVP_ITS); - if (!status) { - pr_debug("VIP: irq ignored\n"); + if (!status) /* No interrupt to handle */ return IRQ_NONE; - } - - if (!vip->started) - return IRQ_HANDLED; - if (status & DVP_IT_VSB) - vip->bcount++; - - if (status & DVP_IT_VST) - vip->tcount++; + if (status & DVP_IT_FIFO) + if (vip->overflow++ > 5) + pr_info("VIP: fifo overflow\n"); - if ((DVP_IT_VSB | DVP_IT_VST) == (status & (DVP_IT_VST | DVP_IT_VSB))) { + if ((status & DVP_IT_VST) && (status & DVP_IT_VSB)) { /* this is bad, we are too slow, hope the condition is gone * on the next frame */ - pr_info("VIP: both irqs\n"); return IRQ_HANDLED; } - if (status & DVP_IT_FIFO) { - if (5 > vip->overflow++) - pr_info("VIP: fifo overflow\n"); + if (status & DVP_IT_VST) + if ((++vip->tcount) < 2) + return IRQ_HANDLED; + if (status & DVP_IT_VSB) { + vip->bcount++; + return IRQ_HANDLED; } - if (2 > vip->tcount) - return IRQ_HANDLED; + if (vip->active) { /* Acquisition is over on this buffer */ + /* Disable acquisition */ + reg_write(vip, DVP_CTL, reg_read(vip, DVP_CTL) & ~DVP_CTL_ENA); + /* Remove the active buffer from the list */ + do_gettimeofday(&vip->active->vb.v4l2_buf.timestamp); + vip->active->vb.v4l2_buf.sequence = vip->sequence++; + vb2_buffer_done(&vip->active->vb, VB2_BUF_STATE_DONE); + } - if (status & DVP_IT_VSB) - return IRQ_HANDLED; + return IRQ_HANDLED; +} - spin_lock_irqsave(&vip->slock, flags); +static void sta2x11_vip_init_register(struct sta2x11_vip *vip) +{ + /* Register initialization */ + spin_lock_irq(&vip->slock); + /* Clean interrupt */ + reg_read(vip, DVP_ITS); + /* Enable Half Line per vertical */ + reg_write(vip, DVP_HLFLN, DVP_HLFLN_SD); + /* Reset VIP control */ + reg_write(vip, DVP_CTL, DVP_CTL_RST); + /* Clear VIP control */ + reg_write(vip, DVP_CTL, 0); + spin_unlock_irq(&vip->slock); +} +static void sta2x11_vip_clear_register(struct sta2x11_vip *vip) +{ + spin_lock_irq(&vip->slock); + /* Disable interrupt */ + reg_write(vip, DVP_ITM, 0); + /* Reset VIP Control */ + reg_write(vip, DVP_CTL, DVP_CTL_RST); + /* Clear VIP Control */ + reg_write(vip, DVP_CTL, 0); + /* Clean VIP Interrupt */ + reg_read(vip, DVP_ITS); + spin_unlock_irq(&vip->slock); +} +static int sta2x11_vip_init_buffer(struct sta2x11_vip *vip) +{ + int err; - REG_WRITE(vip, DVP_CTL, REG_READ(vip, DVP_CTL) & ~DVP_CTL_ENA); - if (vip->active) { - do_gettimeofday(&vip->active->ts); - vip->active->field_count++; - vip->active->state = VIDEOBUF_DONE; - wake_up(&vip->active->done); - vip->active = NULL; + err = dma_set_coherent_mask(&vip->pdev->dev, DMA_BIT_MASK(29)); + if (err) { + v4l2_err(&vip->v4l2_dev, "Cannot configure coherent mask"); + return err; } - if (!vip->closing) { - if (list_empty(&vip->capture)) - goto done; - - vb = list_first_entry(&vip->capture, struct videobuf_buffer, - queue); - if (NULL == vb) { - pr_info("VIP: no buffer\n"); - goto done; - } - vb->state = VIDEOBUF_ACTIVE; - list_del(&vb->queue); - vip->active = vb; - dma = videobuf_to_dma_contig(vb); - switch (vip->format.field) { - case V4L2_FIELD_INTERLACED: - REG_WRITE(vip, DVP_VTP, dma); - REG_WRITE(vip, DVP_VBP, dma + vip->format.width * 2); - break; - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - REG_WRITE(vip, DVP_VTP, dma); - REG_WRITE(vip, DVP_VBP, dma); - break; - default: - pr_warning("VIP: unknown field format\n"); - goto done; - break; - } - REG_WRITE(vip, DVP_CTL, REG_READ(vip, DVP_CTL) | DVP_CTL_ENA); + memset(&vip->vb_vidq, 0, sizeof(struct vb2_queue)); + vip->vb_vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vip->vb_vidq.io_modes = VB2_MMAP | VB2_READ; + vip->vb_vidq.drv_priv = vip; + vip->vb_vidq.buf_struct_size = sizeof(struct vip_buffer); + vip->vb_vidq.ops = &vip_video_qops; + vip->vb_vidq.mem_ops = &vb2_dma_contig_memops; + 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); } -done: - spin_unlock_irqrestore(&vip->slock, flags); - return IRQ_HANDLED; + + 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) +{ + /* + * Inititialize an empty control so VIP can inerithing controls + * from ADV7180 + */ + v4l2_ctrl_handler_init(&vip->ctrl_hdl, 0); + + vip->v4l2_dev.ctrl_handler = &vip->ctrl_hdl; + if (vip->ctrl_hdl.error) { + int err = vip->ctrl_hdl.error; + + v4l2_ctrl_handler_free(&vip->ctrl_hdl); + return err; + } + + return 0; } /** @@ -1212,10 +987,17 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev, struct sta2x11_vip *vip; struct vip_config *config; + /* Check if hardware support 26-bit DMA */ + if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(26))) { + dev_err(&pdev->dev, "26-bit DMA addressing not available\n"); + return -EINVAL; + } + /* Enable PCI */ ret = pci_enable_device(pdev); if (ret) return ret; + /* Get VIP platform data */ config = dev_get_platdata(&pdev->dev); if (!config) { dev_info(&pdev->dev, "VIP slot disabled\n"); @@ -1223,6 +1005,7 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev, goto disable; } + /* Power configuration */ ret = vip_gpio_reserve(&pdev->dev, config->pwr_pin, 0, config->pwr_name); if (ret) @@ -1237,7 +1020,6 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev, goto disable; } } - if (config->pwr_pin != -1) { /* Datasheet says 5ms between PWR and RST */ usleep_range(5000, 25000); @@ -1251,17 +1033,20 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev, } usleep_range(5000, 25000); + /* Allocate a new VIP instance */ vip = kzalloc(sizeof(struct sta2x11_vip), GFP_KERNEL); if (!vip) { ret = -ENOMEM; goto release_gpios; } - vip->pdev = pdev; vip->std = V4L2_STD_PAL; vip->format = formats_50[0]; vip->config = config; + ret = sta2x11_vip_init_controls(vip); + if (ret) + goto free_mem; if (v4l2_device_register(&pdev->dev, &vip->v4l2_dev)) goto free_mem; @@ -1271,46 +1056,52 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev, pci_set_master(pdev); - ret = pci_request_regions(pdev, DRV_NAME); + ret = pci_request_regions(pdev, KBUILD_MODNAME); if (ret) goto unreg; vip->iomem = pci_iomap(pdev, 0, 0x100); if (!vip->iomem) { - ret = -ENOMEM; /* FIXME */ + ret = -ENOMEM; goto release; } pci_enable_msi(pdev); - INIT_LIST_HEAD(&vip->capture); + /* Initialize buffer */ + ret = sta2x11_vip_init_buffer(vip); + if (ret) + goto unmap; + spin_lock_init(&vip->slock); - mutex_init(&vip->mutex); - vip->started = 0; - vip->disabled = 0; ret = request_irq(pdev->irq, (irq_handler_t) vip_irq, - IRQF_SHARED, DRV_NAME, vip); + IRQF_SHARED, KBUILD_MODNAME, vip); if (ret) { dev_err(&pdev->dev, "request_irq failed\n"); ret = -ENODEV; - goto unmap; + goto release_buf; } + /* Alloc, initialize and register video device */ vip->video_dev = video_device_alloc(); if (!vip->video_dev) { ret = -ENOMEM; goto release_irq; } - *(vip->video_dev) = video_dev_template; + vip->video_dev = &video_dev_template; + vip->video_dev->v4l2_dev = &vip->v4l2_dev; + vip->video_dev->queue = &vip->vb_vidq; + set_bit(V4L2_FL_USE_FH_PRIO, &vip->video_dev->flags); video_set_drvdata(vip->video_dev, vip); ret = video_register_device(vip->video_dev, VFL_TYPE_GRABBER, -1); if (ret) goto vrelease; + /* Get ADV7180 subdevice */ vip->adapter = i2c_get_adapter(vip->config->i2c_id); if (!vip->adapter) { ret = -ENODEV; @@ -1328,10 +1119,11 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev, } i2c_put_adapter(vip->adapter); - v4l2_subdev_call(vip->decoder, core, init, 0); - pr_info("STA2X11 Video Input Port (VIP) loaded\n"); + sta2x11_vip_init_register(vip); + + dev_info(&pdev->dev, "STA2X11 Video Input Port (VIP) loaded\n"); return 0; vunreg: @@ -1343,10 +1135,12 @@ vrelease: video_device_release(vip->video_dev); release_irq: free_irq(pdev->irq, vip); +release_buf: + sta2x11_vip_release_buffer(vip); pci_disable_msi(pdev); unmap: + vb2_queue_release(&vip->vb_vidq); pci_iounmap(pdev, vip->iomem); - mutex_destroy(&vip->mutex); release: pci_release_regions(pdev); unreg: @@ -1382,16 +1176,18 @@ static void sta2x11_vip_remove_one(struct pci_dev *pdev) struct sta2x11_vip *vip = container_of(v4l2_dev, struct sta2x11_vip, v4l2_dev); + sta2x11_vip_clear_register(vip); + video_set_drvdata(vip->video_dev, NULL); video_unregister_device(vip->video_dev); /*do not call video_device_release() here, is already done */ free_irq(pdev->irq, vip); pci_disable_msi(pdev); + vb2_queue_release(&vip->vb_vidq); pci_iounmap(pdev, vip->iomem); pci_release_regions(pdev); v4l2_device_unregister(&vip->v4l2_dev); - mutex_destroy(&vip->mutex); vip_gpio_release(&pdev->dev, vip->config->pwr_pin, vip->config->pwr_name); @@ -1416,9 +1212,6 @@ static void sta2x11_vip_remove_one(struct pci_dev *pdev) * * return value: 0 always indicate success, * even if device could not be disabled. (workaround for hardware problem) - * - * reurn value : 0, always succesful, even if hardware does not not support - * power down mode. */ static int sta2x11_vip_suspend(struct pci_dev *pdev, pm_message_t state) { @@ -1429,15 +1222,15 @@ static int sta2x11_vip_suspend(struct pci_dev *pdev, pm_message_t state) int i; spin_lock_irqsave(&vip->slock, flags); - vip->register_save_area[0] = REG_READ(vip, DVP_CTL); - REG_WRITE(vip, DVP_CTL, vip->register_save_area[0] & DVP_CTL_DIS); - vip->register_save_area[SAVE_COUNT] = REG_READ(vip, DVP_ITM); - REG_WRITE(vip, DVP_ITM, 0); + vip->register_save_area[0] = reg_read(vip, DVP_CTL); + reg_write(vip, DVP_CTL, vip->register_save_area[0] & DVP_CTL_DIS); + vip->register_save_area[SAVE_COUNT] = reg_read(vip, DVP_ITM); + reg_write(vip, DVP_ITM, 0); for (i = 1; i < SAVE_COUNT; i++) - vip->register_save_area[i] = REG_READ(vip, 4 * i); + vip->register_save_area[i] = reg_read(vip, 4 * i); for (i = 0; i < AUX_COUNT; i++) vip->register_save_area[SAVE_COUNT + IRQ_COUNT + i] = - REG_READ(vip, registers_to_save[i]); + reg_read(vip, registers_to_save[i]); spin_unlock_irqrestore(&vip->slock, flags); /* save pci state */ pci_save_state(pdev); @@ -1477,7 +1270,7 @@ static int sta2x11_vip_resume(struct pci_dev *pdev) if (vip->disabled) { ret = pci_enable_device(pdev); if (ret) { - pr_warning("VIP: Can't enable device.\n"); + pr_warn("VIP: Can't enable device.\n"); return ret; } vip->disabled = 0; @@ -1488,7 +1281,7 @@ static int sta2x11_vip_resume(struct pci_dev *pdev) * do not call pci_disable_device on sta2x11 because it * break all other Bus masters on this EP */ - pr_warning("VIP: Can't enable device.\n"); + pr_warn("VIP: Can't enable device.\n"); vip->disabled = 1; return ret; } @@ -1497,12 +1290,12 @@ static int sta2x11_vip_resume(struct pci_dev *pdev) spin_lock_irqsave(&vip->slock, flags); for (i = 1; i < SAVE_COUNT; i++) - REG_WRITE(vip, 4 * i, vip->register_save_area[i]); + reg_write(vip, 4 * i, vip->register_save_area[i]); for (i = 0; i < AUX_COUNT; i++) - REG_WRITE(vip, registers_to_save[i], + reg_write(vip, registers_to_save[i], vip->register_save_area[SAVE_COUNT + IRQ_COUNT + i]); - REG_WRITE(vip, DVP_CTL, vip->register_save_area[0]); - REG_WRITE(vip, DVP_ITM, vip->register_save_area[SAVE_COUNT]); + reg_write(vip, DVP_CTL, vip->register_save_area[0]); + reg_write(vip, DVP_ITM, vip->register_save_area[SAVE_COUNT]); spin_unlock_irqrestore(&vip->slock, flags); return 0; } @@ -1515,7 +1308,7 @@ static DEFINE_PCI_DEVICE_TABLE(sta2x11_vip_pci_tbl) = { }; static struct pci_driver sta2x11_vip_driver = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .probe = sta2x11_vip_init_one, .remove = sta2x11_vip_remove_one, .id_table = sta2x11_vip_pci_tbl, diff --git a/drivers/media/pci/ttpci/Kconfig b/drivers/media/pci/ttpci/Kconfig index 314e417adda..0dcb8cd7767 100644 --- a/drivers/media/pci/ttpci/Kconfig +++ b/drivers/media/pci/ttpci/Kconfig @@ -1,8 +1,3 @@ -config TTPCI_EEPROM - tristate - depends on I2C - default n - config DVB_AV7110 tristate "AV7110 cards" depends on DVB_CORE && PCI && I2C diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index 4656d4a10af..3dc7aa9b6f4 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -235,7 +235,7 @@ static void recover_arm(struct av7110 *av7110) restart_feeds(av7110); -#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE) +#if IS_ENABLED(CONFIG_INPUT_EVDEV) av7110_check_ir_config(av7110, true); #endif } @@ -268,7 +268,7 @@ static int arm_thread(void *data) if (!av7110->arm_ready) continue; -#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE) +#if IS_ENABLED(CONFIG_INPUT_EVDEV) av7110_check_ir_config(av7110, false); #endif @@ -1730,7 +1730,7 @@ static int alps_tdlb7_tuner_set_params(struct dvb_frontend *fe) static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) { -#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE) +#if IS_ENABLED(CONFIG_DVB_SP8870) struct av7110* av7110 = fe->dvb->priv; return request_firmware(fw, name, &av7110->dev->pci->dev); @@ -2723,7 +2723,9 @@ static int av7110_attach(struct saa7146_dev* dev, if (ret < 0) goto err_av7110_exit_v4l_12; -#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE) + mutex_init(&av7110->ioctl_mutex); + +#if IS_ENABLED(CONFIG_INPUT_EVDEV) av7110_ir_init(av7110); #endif printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num); @@ -2766,7 +2768,7 @@ static int av7110_detach(struct saa7146_dev* saa) struct av7110 *av7110 = saa->ext_priv; dprintk(4, "%p\n", av7110); -#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE) +#if IS_ENABLED(CONFIG_INPUT_EVDEV) av7110_ir_exit(av7110); #endif if (budgetpatch || av7110->full_ts) { diff --git a/drivers/media/pci/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h index a378662b1dc..ef3d9606b26 100644 --- a/drivers/media/pci/ttpci/av7110.h +++ b/drivers/media/pci/ttpci/av7110.h @@ -271,6 +271,8 @@ struct av7110 { struct dvb_frontend* fe; fe_status_t fe_status; + struct mutex ioctl_mutex; + /* crash recovery */ void (*recover)(struct av7110* av7110); fe_sec_voltage_t saved_voltage; diff --git a/drivers/media/pci/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c index 952b33dbac4..301029ca453 100644 --- a/drivers/media/pci/ttpci/av7110_av.c +++ b/drivers/media/pci/ttpci/av7110_av.c @@ -1109,6 +1109,9 @@ static int dvb_video_ioctl(struct file *file, } } + if (mutex_lock_interruptible(&av7110->ioctl_mutex)) + return -ERESTARTSYS; + switch (cmd) { case VIDEO_STOP: av7110->videostate.play_state = VIDEO_STOPPED; @@ -1297,6 +1300,7 @@ static int dvb_video_ioctl(struct file *file, break; } + mutex_unlock(&av7110->ioctl_mutex); return ret; } @@ -1314,6 +1318,9 @@ static int dvb_audio_ioctl(struct file *file, (cmd != AUDIO_GET_STATUS)) return -EPERM; + if (mutex_lock_interruptible(&av7110->ioctl_mutex)) + return -ERESTARTSYS; + switch (cmd) { case AUDIO_STOP: if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY) @@ -1442,6 +1449,7 @@ static int dvb_audio_ioctl(struct file *file, ret = -ENOIOCTLCMD; } + mutex_unlock(&av7110->ioctl_mutex); return ret; } diff --git a/drivers/media/pci/ttpci/av7110_ca.c b/drivers/media/pci/ttpci/av7110_ca.c index 9fc1dd0ba4c..a6079b90252 100644 --- a/drivers/media/pci/ttpci/av7110_ca.c +++ b/drivers/media/pci/ttpci/av7110_ca.c @@ -253,12 +253,17 @@ static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg) struct dvb_device *dvbdev = file->private_data; struct av7110 *av7110 = dvbdev->priv; unsigned long arg = (unsigned long) parg; + int ret = 0; dprintk(8, "av7110:%p\n",av7110); + if (mutex_lock_interruptible(&av7110->ioctl_mutex)) + return -ERESTARTSYS; + switch (cmd) { case CA_RESET: - return ci_ll_reset(&av7110->ci_wbuffer, file, arg, &av7110->ci_slot[0]); + ret = ci_ll_reset(&av7110->ci_wbuffer, file, arg, + &av7110->ci_slot[0]); break; case CA_GET_CAP: { @@ -277,8 +282,10 @@ static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg) { ca_slot_info_t *info=(ca_slot_info_t *)parg; - if (info->num < 0 || info->num > 1) + if (info->num < 0 || info->num > 1) { + mutex_unlock(&av7110->ioctl_mutex); return -EINVAL; + } av7110->ci_slot[info->num].num = info->num; av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? CA_CI_LINK : CA_CI; @@ -306,10 +313,10 @@ static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg) { ca_descr_t *descr = (ca_descr_t*) parg; - if (descr->index >= 16) - return -EINVAL; - if (descr->parity > 1) + if (descr->index >= 16 || descr->parity > 1) { + mutex_unlock(&av7110->ioctl_mutex); return -EINVAL; + } av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetDescr, 5, (descr->index<<8)|descr->parity, (descr->cw[0]<<8)|descr->cw[1], @@ -320,9 +327,12 @@ static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg) } default: - return -EINVAL; + ret = -EINVAL; + break; } - return 0; + + mutex_unlock(&av7110->ioctl_mutex); + return ret; } static ssize_t dvb_ca_write(struct file *file, const char __user *buf, diff --git a/drivers/media/pci/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c index a90a3b9b09b..bb53d2488ad 100644 --- a/drivers/media/pci/zoran/zoran_card.c +++ b/drivers/media/pci/zoran/zoran_card.c @@ -708,8 +708,7 @@ static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = { static int zoran_register_i2c (struct zoran *zr) { - memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template, - sizeof(struct i2c_algo_bit_data)); + zr->i2c_algo = zoran_i2c_bit_data_template; zr->i2c_algo.data = zr; strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr), sizeof(zr->i2c_adapter.name)); diff --git a/drivers/media/pci/zoran/zoran_device.c b/drivers/media/pci/zoran/zoran_device.c index a4cd504b8ee..519164c572c 100644 --- a/drivers/media/pci/zoran/zoran_device.c +++ b/drivers/media/pci/zoran/zoran_device.c @@ -1169,7 +1169,7 @@ zoran_reap_stat_com (struct zoran *zr) } frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; buffer = &zr->jpg_buffers.buffer[frame]; - do_gettimeofday(&buffer->bs.timestamp); + v4l2_get_timestamp(&buffer->bs.timestamp); if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { buffer->bs.length = (stat_com & 0x7fffff) >> 1; @@ -1407,7 +1407,7 @@ zoran_irq (int irq, zr->v4l_buffers.buffer[zr->v4l_grab_frame].state = BUZ_STATE_DONE; zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.seq = zr->v4l_grab_seq; - do_gettimeofday(&zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.timestamp); + v4l2_get_timestamp(&zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.timestamp); zr->v4l_grab_frame = NO_GRAB_ACTIVE; zr->v4l_pend_tail++; } diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index e60ae41e231..2e8f518f298 100644 --- a/drivers/media/pci/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -1334,7 +1334,7 @@ static int zoran_v4l2_buffer_status(struct zoran_fh *fh, struct zoran *zr = fh->zr; unsigned long flags; - buf->flags = V4L2_BUF_FLAG_MAPPED; + buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: |